示例#1
0
        public static TargetResult GetTargetInfo()
        {
            var result = new TargetResult();

            if (!CanGetTargetInfo() || !MemoryHandler.Instance.IsAttached)
            {
                return(result);
            }

            try {
                var targetAddress = (IntPtr)Scanner.Instance.Locations[Signatures.TargetKey];

                if (targetAddress.ToInt64() > 0)
                {
                    byte[] targetInfoSource = MemoryHandler.Instance.GetByteArray(targetAddress, MemoryHandler.Instance.Structures.TargetInfo.SourceSize);

                    var currentTarget   = MemoryHandler.Instance.GetPlatformIntFromBytes(targetInfoSource, MemoryHandler.Instance.Structures.TargetInfo.Current);
                    var mouseOverTarget = MemoryHandler.Instance.GetPlatformIntFromBytes(targetInfoSource, MemoryHandler.Instance.Structures.TargetInfo.MouseOver);
                    var focusTarget     = MemoryHandler.Instance.GetPlatformIntFromBytes(targetInfoSource, MemoryHandler.Instance.Structures.TargetInfo.Focus);
                    var previousTarget  = MemoryHandler.Instance.GetPlatformIntFromBytes(targetInfoSource, MemoryHandler.Instance.Structures.TargetInfo.Previous);

                    var currentTargetID = BitConverter.TryToUInt32(targetInfoSource, MemoryHandler.Instance.Structures.TargetInfo.CurrentID);

                    if (currentTarget > 0)
                    {
                        try {
                            ActorItem entry = GetTargetActorItemFromSource(currentTarget);
                            currentTargetID = entry.ID;
                            if (entry.IsValid)
                            {
                                result.TargetsFound             = true;
                                result.TargetInfo.CurrentTarget = entry;
                            }
                        }
                        catch (Exception ex) {
                            MemoryHandler.Instance.RaiseException(Logger, ex, true);
                        }
                    }

                    if (mouseOverTarget > 0)
                    {
                        try {
                            ActorItem entry = GetTargetActorItemFromSource(mouseOverTarget);
                            if (entry.IsValid)
                            {
                                result.TargetsFound = true;
                                result.TargetInfo.MouseOverTarget = entry;
                            }
                        }
                        catch (Exception ex) {
                            MemoryHandler.Instance.RaiseException(Logger, ex, true);
                        }
                    }

                    if (focusTarget > 0)
                    {
                        try {
                            ActorItem entry = GetTargetActorItemFromSource(focusTarget);
                            if (entry.IsValid)
                            {
                                result.TargetsFound           = true;
                                result.TargetInfo.FocusTarget = entry;
                            }
                        }
                        catch (Exception ex) {
                            MemoryHandler.Instance.RaiseException(Logger, ex, true);
                        }
                    }

                    if (previousTarget > 0)
                    {
                        try {
                            ActorItem entry = GetTargetActorItemFromSource(previousTarget);
                            if (entry.IsValid)
                            {
                                result.TargetsFound = true;
                                result.TargetInfo.PreviousTarget = entry;
                            }
                        }
                        catch (Exception ex) {
                            MemoryHandler.Instance.RaiseException(Logger, ex, true);
                        }
                    }

                    if (currentTargetID > 0)
                    {
                        result.TargetsFound = true;
                        result.TargetInfo.CurrentTargetID = currentTargetID;
                    }
                }

                if (result.TargetInfo.CurrentTargetID > 0)
                {
                    try {
                        if (CanGetEnmityEntities())
                        {
                            var enmityCount     = MemoryHandler.Instance.GetInt16(Scanner.Instance.Locations[Signatures.EnmityCountKey]);
                            var enmityStructure = (IntPtr)Scanner.Instance.Locations[Signatures.EnmityMapKey];

                            if (enmityCount > 0 && enmityCount < 16 && enmityStructure.ToInt64() > 0)
                            {
                                var enmitySourceSize = MemoryHandler.Instance.Structures.EnmityItem.SourceSize;
                                for (uint i = 0; i < enmityCount; i++)
                                {
                                    try {
                                        var address     = new IntPtr(enmityStructure.ToInt64() + i * enmitySourceSize);
                                        var enmityEntry = new EnmityItem {
                                            ID     = (uint)MemoryHandler.Instance.GetPlatformInt(address, MemoryHandler.Instance.Structures.EnmityItem.ID),
                                            Name   = MemoryHandler.Instance.GetString(address + MemoryHandler.Instance.Structures.EnmityItem.Name),
                                            Enmity = MemoryHandler.Instance.GetUInt32(address + MemoryHandler.Instance.Structures.EnmityItem.Enmity)
                                        };
                                        if (enmityEntry.ID <= 0)
                                        {
                                            continue;
                                        }

                                        if (string.IsNullOrWhiteSpace(enmityEntry.Name))
                                        {
                                            ActorItem pc      = PCWorkerDelegate.GetActorItem(enmityEntry.ID);
                                            ActorItem npc     = NPCWorkerDelegate.GetActorItem(enmityEntry.ID);
                                            ActorItem monster = MonsterWorkerDelegate.GetActorItem(enmityEntry.ID);
                                            try {
                                                enmityEntry.Name = (pc ?? npc).Name ?? monster.Name;
                                            }
                                            catch (Exception ex) {
                                                MemoryHandler.Instance.RaiseException(Logger, ex, true);
                                            }
                                        }

                                        result.TargetInfo.EnmityItems.Add(enmityEntry);
                                    }
                                    catch (Exception ex) {
                                        MemoryHandler.Instance.RaiseException(Logger, ex, true);
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex) {
                        MemoryHandler.Instance.RaiseException(Logger, ex, true);
                    }
                }
            }
            catch (Exception ex) {
                MemoryHandler.Instance.RaiseException(Logger, ex, true);
            }

            return(result);
        }
示例#2
0
        public static async Task <ActorResult> GetActors()
        {
            var result = new ActorResult();

            if (!CanGetActors() || !MemoryHandler.Instance.IsAttached)
            {
                return(result);
            }

            try {
                IntPtr targetAddress = IntPtr.Zero;

                var endianSize = MemoryHandler.Instance.ProcessModel.IsWin64
                                     ? 8
                                     : 4;

                var    sourceSize          = MemoryHandler.Instance.Structures.ActorItem.SourceSize;
                var    limit               = MemoryHandler.Instance.Structures.ActorItem.EntityCount;
                byte[] characterAddressMap = MemoryHandler.Instance.GetByteArray(Scanner.Instance.Locations[Signatures.CharacterMapKey], endianSize * limit);
                Dictionary <IntPtr, IntPtr> uniqueAddresses = new Dictionary <IntPtr, IntPtr>();
                IntPtr firstAddress = IntPtr.Zero;

                DateTime now = DateTime.Now;

                TimeSpan staleActorRemovalTime = TimeSpan.FromSeconds(0.25);

                var firstTime = true;

                for (var i = 0; i < limit; i++)
                {
                    IntPtr characterAddress;

                    if (MemoryHandler.Instance.ProcessModel.IsWin64)
                    {
                        characterAddress = new IntPtr(BitConverter.TryToInt64(characterAddressMap, i * endianSize));
                    }
                    else
                    {
                        characterAddress = new IntPtr(BitConverter.TryToInt32(characterAddressMap, i * endianSize));
                    }

                    if (characterAddress == IntPtr.Zero)
                    {
                        continue;
                    }

                    if (firstTime)
                    {
                        firstAddress = characterAddress;
                        firstTime    = false;
                    }

                    uniqueAddresses[characterAddress] = characterAddress;
                }

                foreach (KeyValuePair <uint, ActorItem> kvp in MonsterWorkerDelegate.ActorItems)
                {
                    result.RemovedMonsters.TryAdd(kvp.Key, kvp.Value.Clone());
                }

                foreach (KeyValuePair <uint, ActorItem> kvp in NPCWorkerDelegate.ActorItems)
                {
                    result.RemovedNPCs.TryAdd(kvp.Key, kvp.Value.Clone());
                }

                foreach (KeyValuePair <uint, ActorItem> kvp in PCWorkerDelegate.ActorItems)
                {
                    result.RemovedPCs.TryAdd(kvp.Key, kvp.Value.Clone());
                }

                foreach (KeyValuePair <IntPtr, IntPtr> kvp in uniqueAddresses)
                {
                    try {
                        var    characterAddress = new IntPtr(kvp.Value.ToInt64());
                        byte[] source           = MemoryHandler.Instance.GetByteArray(characterAddress, sourceSize);

                        // var source = MemoryHandler.Instance.GetByteArray(characterAddress, 0x3F40);
                        var ID     = BitConverter.TryToUInt32(source, MemoryHandler.Instance.Structures.ActorItem.ID);
                        var NPCID2 = BitConverter.TryToUInt32(source, MemoryHandler.Instance.Structures.ActorItem.NPCID2);
                        var Type   = (Actor.Type)source[MemoryHandler.Instance.Structures.ActorItem.Type];

                        ActorItem existing = null;
                        var       newEntry = false;

                        switch (Type)
                        {
                        case Actor.Type.Monster:
                            if (result.RemovedMonsters.ContainsKey(ID))
                            {
                                result.RemovedMonsters.TryRemove(ID, out ActorItem removedMonster);
                                existing = MonsterWorkerDelegate.GetActorItem(ID);
                            }
                            else
                            {
                                newEntry = true;
                            }

                            break;

                        case Actor.Type.PC:
                            if (result.RemovedPCs.ContainsKey(ID))
                            {
                                result.RemovedPCs.TryRemove(ID, out ActorItem removedPC);
                                existing = PCWorkerDelegate.GetActorItem(ID);
                            }
                            else
                            {
                                newEntry = true;
                            }

                            break;

                        case Actor.Type.NPC:
                        case Actor.Type.Aetheryte:
                        case Actor.Type.EventObject:
                            if (result.RemovedNPCs.ContainsKey(NPCID2))
                            {
                                result.RemovedNPCs.TryRemove(NPCID2, out ActorItem removedNPC);
                                existing = NPCWorkerDelegate.GetActorItem(NPCID2);
                            }
                            else
                            {
                                newEntry = true;
                            }

                            break;

                        default:
                            if (result.RemovedNPCs.ContainsKey(ID))
                            {
                                result.RemovedNPCs.TryRemove(ID, out ActorItem removedNPC);
                                existing = NPCWorkerDelegate.GetActorItem(ID);
                            }
                            else
                            {
                                newEntry = true;
                            }

                            break;
                        }

                        var isFirstEntry = kvp.Value.ToInt64() == firstAddress.ToInt64();

                        ActorItem entry = await ActorItemResolver.ResolveActorFromBytes(source, isFirstEntry, existing);

                        if (entry != null && entry.IsValid)
                        {
                            if (expiringActors.ContainsKey(ID))
                            {
                                expiringActors.Remove(ID);
                            }
                        }

                        if (entry.Type == Actor.Type.EventObject)
                        {
                            var(EventObjectTypeID, EventObjectType) = GetEventObjectType(targetAddress);
                            entry.EventObjectTypeID = EventObjectTypeID;
                            entry.EventObjectType   = EventObjectType;
                        }

                        EnsureMapAndZone(entry);

                        if (isFirstEntry)
                        {
                            if (targetAddress.ToInt64() > 0)
                            {
                                byte[] targetInfoSource = MemoryHandler.Instance.GetByteArray(targetAddress, 128);
                                entry.TargetID = (int)BitConverter.TryToUInt32(targetInfoSource, MemoryHandler.Instance.Structures.ActorItem.ID);
                            }
                        }

                        // it doesn't matter what this is set to; it won't be used in code below
                        ActorItem removed;

                        if (!entry.IsValid)
                        {
                            result.NewMonsters.TryRemove(entry.ID, out removed);
                            result.NewMonsters.TryRemove(entry.NPCID2, out removed);
                            result.NewNPCs.TryRemove(entry.ID, out removed);
                            result.NewNPCs.TryRemove(entry.NPCID2, out removed);
                            result.NewPCs.TryRemove(entry.ID, out removed);
                            result.NewPCs.TryRemove(entry.NPCID2, out removed);
                            continue;
                        }

                        if (existing != null)
                        {
                            continue;
                        }

                        if (newEntry)
                        {
                            switch (entry.Type)
                            {
                            case Actor.Type.Monster:
                                MonsterWorkerDelegate.EnsureActorItem(entry.ID, entry);
                                result.NewMonsters.TryAdd(entry.ID, entry.Clone());
                                break;

                            case Actor.Type.PC:
                                PCWorkerDelegate.EnsureActorItem(entry.ID, entry);
                                result.NewPCs.TryAdd(entry.ID, entry.Clone());
                                break;

                            case Actor.Type.Aetheryte:
                            case Actor.Type.EventObject:
                            case Actor.Type.NPC:
                                NPCWorkerDelegate.EnsureActorItem(entry.NPCID2, entry);
                                result.NewNPCs.TryAdd(entry.NPCID2, entry.Clone());
                                break;

                            default:
                                NPCWorkerDelegate.EnsureActorItem(entry.ID, entry);
                                result.NewNPCs.TryAdd(entry.ID, entry.Clone());
                                break;
                            }
                        }
                    }
                    catch (Exception ex) {
                        MemoryHandler.Instance.RaiseException(Logger, ex, true);
                    }
                }

                try {
                    // add the "removed" actors to the expiring list
                    foreach (KeyValuePair <uint, ActorItem> kvp in result.RemovedMonsters)
                    {
                        if (!expiringActors.ContainsKey(kvp.Key))
                        {
                            expiringActors[kvp.Key] = now + staleActorRemovalTime;
                        }
                    }

                    foreach (KeyValuePair <uint, ActorItem> kvp in result.RemovedNPCs)
                    {
                        if (!expiringActors.ContainsKey(kvp.Key))
                        {
                            expiringActors[kvp.Key] = now + staleActorRemovalTime;
                        }
                    }

                    foreach (KeyValuePair <uint, ActorItem> kvp in result.RemovedPCs)
                    {
                        if (!expiringActors.ContainsKey(kvp.Key))
                        {
                            expiringActors[kvp.Key] = now + staleActorRemovalTime;
                        }
                    }


                    // check expiring list for stale actors
                    foreach (var kvp in expiringActors.ToList())
                    {
                        if (now > kvp.Value)
                        {
                            // Stale actor. Remove it.
                            MonsterWorkerDelegate.RemoveActorItem(kvp.Key);
                            NPCWorkerDelegate.RemoveActorItem(kvp.Key);
                            PCWorkerDelegate.RemoveActorItem(kvp.Key);

                            expiringActors.Remove(kvp.Key);
                        }
                        else
                        {
                            // Not stale enough yet. We're not actually removing it.
                            result.RemovedMonsters.TryRemove(kvp.Key, out ActorItem _);
                            result.RemovedNPCs.TryRemove(kvp.Key, out ActorItem _);
                            result.RemovedPCs.TryRemove(kvp.Key, out ActorItem _);
                        }
                    }
                }
                catch (Exception ex) {
                    MemoryHandler.Instance.RaiseException(Logger, ex, true);
                }

                MemoryHandler.Instance.ScanCount++;
            }
            catch (Exception ex) {
                MemoryHandler.Instance.RaiseException(Logger, ex, true);
            }

            return(result);
        }
示例#3
0
        public static PartyMember ResolvePartyMemberFromBytes(byte[] source, ActorItem actorItem = null)
        {
            if (actorItem != null)
            {
                var entry = new PartyMember {
                    X            = actorItem.X,
                    Y            = actorItem.Y,
                    Z            = actorItem.Z,
                    Coordinate   = actorItem.Coordinate,
                    ID           = actorItem.ID,
                    UUID         = actorItem.UUID,
                    Name         = actorItem.Name,
                    Job          = actorItem.Job,
                    Level        = actorItem.Level,
                    HPCurrent    = actorItem.HPCurrent,
                    HPMax        = actorItem.HPMax,
                    MPCurrent    = actorItem.MPCurrent,
                    MPMax        = actorItem.MPMax,
                    HitBoxRadius = actorItem.HitBoxRadius,
                };
                entry.StatusItems.AddRange(actorItem.StatusItems);
                CleanXPValue(ref entry);
                return(entry);
            }
            else
            {
                var defaultStatusEffectOffset = MemoryHandler.Instance.Structures.PartyMember.DefaultStatusEffectOffset;
                var entry = new PartyMember();
                try {
                    entry.X            = BitConverter.TryToSingle(source, MemoryHandler.Instance.Structures.PartyMember.X);
                    entry.Z            = BitConverter.TryToSingle(source, MemoryHandler.Instance.Structures.PartyMember.Z);
                    entry.Y            = BitConverter.TryToSingle(source, MemoryHandler.Instance.Structures.PartyMember.Y);
                    entry.Coordinate   = new Coordinate(entry.X, entry.Z, entry.Z);
                    entry.ID           = BitConverter.TryToUInt32(source, MemoryHandler.Instance.Structures.PartyMember.ID);
                    entry.UUID         = Guid.NewGuid().ToString();
                    entry.Name         = MemoryHandler.Instance.GetStringFromBytes(source, MemoryHandler.Instance.Structures.PartyMember.Name);
                    entry.JobID        = source[MemoryHandler.Instance.Structures.PartyMember.Job];
                    entry.Job          = (Actor.Job)entry.JobID;
                    entry.HitBoxRadius = 0.5f;

                    entry.Level     = source[MemoryHandler.Instance.Structures.PartyMember.Level];
                    entry.HPCurrent = BitConverter.TryToInt32(source, MemoryHandler.Instance.Structures.PartyMember.HPCurrent);
                    entry.HPMax     = BitConverter.TryToInt32(source, MemoryHandler.Instance.Structures.PartyMember.HPMax);
                    entry.MPCurrent = BitConverter.TryToInt16(source, MemoryHandler.Instance.Structures.PartyMember.MPCurrent);
                    entry.MPMax     = BitConverter.TryToInt16(source, MemoryHandler.Instance.Structures.PartyMember.MPMax);
                    const int limit = 15;

                    int    statusSize     = MemoryHandler.Instance.Structures.StatusItem.SourceSize;
                    byte[] statusesSource = new byte[limit * statusSize];

                    List <StatusItem> foundStatuses = new List <StatusItem>();

                    Buffer.BlockCopy(source, defaultStatusEffectOffset, statusesSource, 0, limit * statusSize);
                    for (var i = 0; i < limit; i++)
                    {
                        bool isNewStatus = false;

                        byte[] statusSource = new byte[statusSize];
                        Buffer.BlockCopy(statusesSource, i * statusSize, statusSource, 0, statusSize);

                        short StatusID = BitConverter.TryToInt16(statusSource, MemoryHandler.Instance.Structures.StatusItem.StatusID);
                        uint  CasterID = BitConverter.TryToUInt32(statusSource, MemoryHandler.Instance.Structures.StatusItem.CasterID);

                        var statusEntry = entry.StatusItems.FirstOrDefault(x => x.CasterID == CasterID && x.StatusID == StatusID);

                        if (statusEntry == null)
                        {
                            statusEntry = new StatusItem();
                            isNewStatus = true;
                        }

                        statusEntry.TargetEntity = null;
                        statusEntry.TargetName   = entry.Name;
                        statusEntry.StatusID     = StatusID;
                        statusEntry.Stacks       = statusSource[MemoryHandler.Instance.Structures.StatusItem.Stacks];
                        statusEntry.Duration     = BitConverter.TryToSingle(statusSource, MemoryHandler.Instance.Structures.StatusItem.Duration);
                        statusEntry.CasterID     = CasterID;

                        foundStatuses.Add(statusEntry);

                        try {
                            ActorItem pc      = PCWorkerDelegate.GetActorItem(statusEntry.CasterID);
                            ActorItem npc     = NPCWorkerDelegate.GetActorItem(statusEntry.CasterID);
                            ActorItem monster = MonsterWorkerDelegate.GetActorItem(statusEntry.CasterID);
                            statusEntry.SourceEntity = (pc ?? npc) ?? monster;
                        }
                        catch (Exception ex) {
                            MemoryHandler.Instance.RaiseException(Logger, ex, true);
                        }

                        try {
                            if (statusEntry.StatusID > 0)
                            {
                                Models.XIVDatabase.StatusItem statusInfo = StatusEffectLookup.GetStatusInfo((uint)statusEntry.StatusID);
                                statusEntry.IsCompanyAction = statusInfo.CompanyAction;
                                var statusKey = statusInfo.Name.English;
                                switch (MemoryHandler.Instance.GameLanguage)
                                {
                                case "French":
                                    statusKey = statusInfo.Name.French;
                                    break;

                                case "Japanese":
                                    statusKey = statusInfo.Name.Japanese;
                                    break;

                                case "German":
                                    statusKey = statusInfo.Name.German;
                                    break;

                                case "Chinese":
                                    statusKey = statusInfo.Name.Chinese;
                                    break;

                                case "Korean":
                                    statusKey = statusInfo.Name.Korean;
                                    break;
                                }

                                statusEntry.StatusName = statusKey;
                            }
                        }
                        catch (Exception) {
                            statusEntry.StatusName = "UNKNOWN";
                        }

                        if (statusEntry.IsValid())
                        {
                            if (isNewStatus)
                            {
                                entry.StatusItems.Add(statusEntry);
                            }

                            foundStatuses.Add(statusEntry);
                        }
                    }

                    entry.StatusItems.RemoveAll(x => !foundStatuses.Contains(x));
                }
                catch (Exception ex) {
                    MemoryHandler.Instance.RaiseException(Logger, ex, true);
                }

                CleanXPValue(ref entry);
                return(entry);
            }
        }
示例#4
0
        public static ActorItem ResolveActorFromBytes(byte[] source, bool isCurrentUser = false, ActorItem entry = null)
        {
            entry = entry ?? new ActorItem();
            var defaultBaseOffset         = MemoryHandler.Instance.Structures.ActorItem.DefaultBaseOffset;
            var defaultStatOffset         = MemoryHandler.Instance.Structures.ActorItem.DefaultStatOffset;
            var defaultStatusEffectOffset = MemoryHandler.Instance.Structures.ActorItem.DefaultStatusEffectOffset;

            try {
                entry.MapTerritory = 0;
                entry.MapIndex     = 0;
                entry.MapID        = 0;
                entry.TargetID     = 0;
                entry.Name         = MemoryHandler.Instance.GetStringFromBytes(source, MemoryHandler.Instance.Structures.ActorItem.Name);
                entry.ID           = BitConverter.TryToUInt32(source, MemoryHandler.Instance.Structures.ActorItem.ID);
                entry.UUID         = string.IsNullOrEmpty(entry.UUID)
                                 ? Guid.NewGuid().ToString()
                                 : entry.UUID;
                entry.NPCID1  = BitConverter.TryToUInt32(source, MemoryHandler.Instance.Structures.ActorItem.NPCID1);
                entry.NPCID2  = BitConverter.TryToUInt32(source, MemoryHandler.Instance.Structures.ActorItem.NPCID2);
                entry.OwnerID = BitConverter.TryToUInt32(source, MemoryHandler.Instance.Structures.ActorItem.OwnerID);
                entry.TypeID  = source[MemoryHandler.Instance.Structures.ActorItem.Type];
                entry.Type    = (Actor.Type)entry.TypeID;

                entry.TargetTypeID = source[MemoryHandler.Instance.Structures.ActorItem.TargetType];
                entry.TargetType   = (Actor.TargetType)entry.TargetTypeID;

                entry.GatheringStatus = source[MemoryHandler.Instance.Structures.ActorItem.GatheringStatus];
                entry.Distance        = source[MemoryHandler.Instance.Structures.ActorItem.Distance];

                entry.X                  = BitConverter.TryToSingle(source, MemoryHandler.Instance.Structures.ActorItem.X + defaultBaseOffset);
                entry.Z                  = BitConverter.TryToSingle(source, MemoryHandler.Instance.Structures.ActorItem.Z + defaultBaseOffset);
                entry.Y                  = BitConverter.TryToSingle(source, MemoryHandler.Instance.Structures.ActorItem.Y + defaultBaseOffset);
                entry.Heading            = BitConverter.TryToSingle(source, MemoryHandler.Instance.Structures.ActorItem.Heading + defaultBaseOffset);
                entry.HitBoxRadius       = BitConverter.TryToSingle(source, MemoryHandler.Instance.Structures.ActorItem.HitBoxRadius + defaultBaseOffset);
                entry.Fate               = BitConverter.TryToUInt32(source, MemoryHandler.Instance.Structures.ActorItem.Fate + defaultBaseOffset); // ??
                entry.TargetFlags        = source[MemoryHandler.Instance.Structures.ActorItem.TargetFlags];                                        // ??
                entry.GatheringInvisible = source[MemoryHandler.Instance.Structures.ActorItem.GatheringInvisible];                                 // ??
                entry.ModelID            = BitConverter.TryToUInt32(source, MemoryHandler.Instance.Structures.ActorItem.ModelID);
                entry.ActionStatusID     = source[MemoryHandler.Instance.Structures.ActorItem.ActionStatus];
                entry.ActionStatus       = (Actor.ActionStatus)entry.ActionStatusID;

                // 0x17D - 0 = Green name, 4 = non-agro (yellow name)
                entry.IsGM   = BitConverter.TryToBoolean(source, MemoryHandler.Instance.Structures.ActorItem.IsGM); // ?
                entry.IconID = source[MemoryHandler.Instance.Structures.ActorItem.Icon];
                entry.Icon   = (Actor.Icon)entry.IconID;

                entry.StatusID = source[MemoryHandler.Instance.Structures.ActorItem.Status];
                entry.Status   = (Actor.Status)entry.StatusID;

                entry.ClaimedByID = BitConverter.TryToUInt32(source, MemoryHandler.Instance.Structures.ActorItem.ClaimedByID);
                var targetID   = BitConverter.TryToUInt32(source, MemoryHandler.Instance.Structures.ActorItem.TargetID);
                var pcTargetID = targetID;

                entry.JobID = source[MemoryHandler.Instance.Structures.ActorItem.Job + defaultStatOffset];
                entry.Job   = (Actor.Job)entry.JobID;

                entry.Level            = source[MemoryHandler.Instance.Structures.ActorItem.Level + defaultStatOffset];
                entry.GrandCompany     = source[MemoryHandler.Instance.Structures.ActorItem.GrandCompany + defaultStatOffset];
                entry.GrandCompanyRank = source[MemoryHandler.Instance.Structures.ActorItem.GrandCompanyRank + defaultStatOffset];
                entry.Title            = source[MemoryHandler.Instance.Structures.ActorItem.Title + defaultStatOffset];
                entry.HPCurrent        = BitConverter.TryToInt32(source, MemoryHandler.Instance.Structures.ActorItem.HPCurrent + defaultStatOffset);
                entry.HPMax            = BitConverter.TryToInt32(source, MemoryHandler.Instance.Structures.ActorItem.HPMax + defaultStatOffset);
                entry.MPCurrent        = BitConverter.TryToInt32(source, MemoryHandler.Instance.Structures.ActorItem.MPCurrent + defaultStatOffset);
                entry.MPMax            = 10000;
                entry.TPCurrent        = BitConverter.TryToInt16(source, MemoryHandler.Instance.Structures.ActorItem.TPCurrent + defaultStatOffset);
                entry.TPMax            = 1000;
                entry.GPCurrent        = BitConverter.TryToInt16(source, MemoryHandler.Instance.Structures.ActorItem.GPCurrent + defaultStatOffset);
                entry.GPMax            = BitConverter.TryToInt16(source, MemoryHandler.Instance.Structures.ActorItem.GPMax + defaultStatOffset);
                entry.CPCurrent        = BitConverter.TryToInt16(source, MemoryHandler.Instance.Structures.ActorItem.CPCurrent + defaultStatOffset);
                entry.CPMax            = BitConverter.TryToInt16(source, MemoryHandler.Instance.Structures.ActorItem.CPMax + defaultStatOffset);

                // entry.Race = source[0x2578]; // ??
                // entry.Sex = (Actor.Sex) source[0x2579]; //?
                entry.AgroFlags       = source[MemoryHandler.Instance.Structures.ActorItem.AgroFlags];
                entry.CombatFlags     = source[MemoryHandler.Instance.Structures.ActorItem.CombatFlags];
                entry.DifficultyRank  = source[MemoryHandler.Instance.Structures.ActorItem.DifficultyRank];
                entry.CastingID       = BitConverter.TryToInt16(source, MemoryHandler.Instance.Structures.ActorItem.CastingID);        // 0x2C94);
                entry.CastingTargetID = BitConverter.TryToUInt32(source, MemoryHandler.Instance.Structures.ActorItem.CastingTargetID); // 0x2CA0);
                entry.CastingProgress = BitConverter.TryToSingle(source, MemoryHandler.Instance.Structures.ActorItem.CastingProgress); // 0x2CC4);
                entry.CastingTime     = BitConverter.TryToSingle(source, MemoryHandler.Instance.Structures.ActorItem.CastingTime);     // 0x2DA8);
                entry.Coordinate      = new Coordinate(entry.X, entry.Z, entry.Y);
                if (targetID > 0)
                {
                    entry.TargetID = (int)targetID;
                }
                else
                {
                    if (pcTargetID > 0)
                    {
                        entry.TargetID = (int)pcTargetID;
                    }
                }

                if (entry.CastingTargetID == 3758096384)
                {
                    entry.CastingTargetID = 0;
                }

                entry.MapIndex = 0;
                var limit = 60;
                switch (entry.Type)
                {
                case Actor.Type.PC:
                    limit = 30;
                    break;
                }

                int    statusSize     = MemoryHandler.Instance.Structures.StatusItem.SourceSize;
                byte[] statusesSource = new byte[limit * statusSize];

                List <StatusItem> foundStatuses = new List <StatusItem>();

                Buffer.BlockCopy(source, defaultStatusEffectOffset, statusesSource, 0, limit * statusSize);
                for (var i = 0; i < limit; i++)
                {
                    bool isNewStatus = false;

                    byte[] statusSource = new byte[statusSize];
                    Buffer.BlockCopy(statusesSource, i * statusSize, statusSource, 0, statusSize);

                    short StatusID = BitConverter.TryToInt16(statusSource, MemoryHandler.Instance.Structures.StatusItem.StatusID);
                    uint  CasterID = BitConverter.TryToUInt32(statusSource, MemoryHandler.Instance.Structures.StatusItem.CasterID);

                    var statusEntry = entry.StatusItems.FirstOrDefault(x => x.CasterID == CasterID && x.StatusID == StatusID);

                    if (statusEntry == null)
                    {
                        statusEntry = new StatusItem();
                        isNewStatus = true;
                    }

                    statusEntry.TargetEntity = entry;
                    statusEntry.TargetName   = entry.Name;
                    statusEntry.StatusID     = StatusID;
                    statusEntry.Stacks       = statusSource[MemoryHandler.Instance.Structures.StatusItem.Stacks];
                    statusEntry.Duration     = BitConverter.TryToSingle(statusSource, MemoryHandler.Instance.Structures.StatusItem.Duration);
                    statusEntry.CasterID     = CasterID;

                    try {
                        ActorItem pc      = PCWorkerDelegate.GetActorItem(statusEntry.CasterID);
                        ActorItem npc     = NPCWorkerDelegate.GetActorItem(statusEntry.CasterID);
                        ActorItem monster = MonsterWorkerDelegate.GetActorItem(statusEntry.CasterID);
                        statusEntry.SourceEntity = (pc ?? npc) ?? monster;
                    }
                    catch (Exception ex) {
                        MemoryHandler.Instance.RaiseException(Logger, ex, true);
                    }

                    try {
                        Models.XIVDatabase.StatusItem statusInfo = StatusEffectLookup.GetStatusInfo((uint)statusEntry.StatusID);
                        if (statusInfo != null)
                        {
                            statusEntry.IsCompanyAction = statusInfo.CompanyAction;
                            var statusKey = statusInfo.Name.English;
                            switch (MemoryHandler.Instance.GameLanguage)
                            {
                            case "French":
                                statusKey = statusInfo.Name.French;
                                break;

                            case "Japanese":
                                statusKey = statusInfo.Name.Japanese;
                                break;

                            case "German":
                                statusKey = statusInfo.Name.German;
                                break;

                            case "Chinese":
                                statusKey = statusInfo.Name.Chinese;
                                break;

                            case "Korean":
                                statusKey = statusInfo.Name.Korean;
                                break;
                            }

                            statusEntry.StatusName = statusKey;
                        }
                    }
                    catch (Exception) {
                        statusEntry.StatusName = "UNKNOWN";
                    }

                    if (statusEntry.IsValid())
                    {
                        if (isNewStatus)
                        {
                            entry.StatusItems.Add(statusEntry);
                        }

                        foundStatuses.Add(statusEntry);
                    }
                }

                entry.StatusItems.RemoveAll(x => !foundStatuses.Contains(x));

                // handle empty names
                if (string.IsNullOrEmpty(entry.Name))
                {
                    if (entry.Type == Actor.Type.EventObject)
                    {
                        entry.Name = $"{nameof(entry.EventObjectTypeID)}: {entry.EventObjectTypeID}";
                    }
                    else
                    {
                        entry.Name = $"{nameof(entry.TypeID)}: {entry.TypeID}";
                    }
                }
            }
            catch (Exception ex) {
                MemoryHandler.Instance.RaiseException(Logger, ex, true);
            }

            CleanXPValue(ref entry);

            if (isCurrentUser)
            {
                PCWorkerDelegate.CurrentUser = entry;
            }

            return(entry);
        }