// 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, EffectiveDistance = 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); } }
private int GetPartyType(Combatant combatant) { // The PartyTypeEnum was renamed in 2.6.0.0 to work around that, we use reflection and cast the result to int. return((int)combatant.GetType().GetMethod("get_PartyType").Invoke(combatant, new object[] {})); }
// Converts an EnmityList into a List<AggroEntry>. public 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>(); EnmityList list = ReadEnmityList(aggroAddress); for (int i = 0; i < list.numEntries; i++) { EnmityListEntry 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); } 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 == 1) { 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 == 1) { enmityAddress = list[0] + enmitySignatureOffset; aggroAddress = IntPtr.Add(enmityAddress, 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 == 1) { targetAddress = list[0] + targetSignatureOffset; } else { targetAddress = IntPtr.Zero; fail.Add(nameof(targetAddress)); 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, "targetAddress: 0x{0:X}", targetAddress.ToInt64()); Combatant c = GetSelfCombatant(); if (c != null) { logger.Log(LogLevel.Debug, "MyCharacter: '{0}' (0x{1:X})", c.Name, c.ID); } if (!success) { logger.Log(LogLevel.Error, "Failed to memory scan: {0}.", String.Join(",", fail)); } return(success); }
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; } 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()); Combatant c = GetSelfCombatant(); if (c != null) { logger.Log(LogLevel.Debug, "MyCharacter: '{0}' (0x{1:X})", c.Name, c.ID); } if (!success) { logger.Log(LogLevel.Error, "Failed to memory scan 5.2: {0}.", String.Join(",", fail)); } else { logger.Log(LogLevel.Info, "Found enmity memory for 5.2."); } return(success); }