private static void Main(string[] args) { var stringReader = new StringReader(XElement.Load("./Bootstrapper.exe.nlog") .ToString()); using (var xmlReader = XmlReader.Create(stringReader)) { LogManager.Configuration = new XmlLoggingConfiguration(xmlReader, null); } ActionHelper.ActionInfo(2); StatusEffectHelper.StatusInfo(2); ZoneHelper.MapInfo(138); var process = Process.GetProcessesByName("ffxiv_dx11") .FirstOrDefault(); MemoryHandler.Instance.SetProcess(new ProcessModel { IsWin64 = true, Process = process }); while (Scanner.Instance.IsScanning) { Thread.Sleep(1000); Console.WriteLine("Scanning..."); } Scanner.Instance.SignaturesFoundEvent += delegate(object sender, SignaturesFoundEvent e) { foreach (var kvp in e.Signatures) { Console.WriteLine($"{kvp.Key} => {kvp.Value.GetAddress():X}"); } Console.WriteLine("To exit this application press \"Enter\"."); Console.ReadLine(); }; }
public static ActorEntity ResolveActorFromBytes(byte[] source, bool isCurrentUser = false) { var entry = new ActorEntity(); try { entry.MapIndex = 0; entry.TargetID = 0; entry.Name = MemoryHandler.Instance.GetStringFromBytes(source, 48); entry.ID = BitConverter.ToUInt32(source, 0x74); entry.NPCID1 = BitConverter.ToUInt32(source, 0x78); entry.NPCID2 = BitConverter.ToUInt32(source, 0x80); entry.OwnerID = BitConverter.ToUInt32(source, 0x84); entry.Type = (Actor.Type)source[0x8A]; entry.TargetType = (Actor.TargetType)source[0x8C]; entry.Distance = source[0x8E]; entry.GatheringStatus = source[0x8F]; entry.X = BitConverter.ToSingle(source, 0xA0); entry.Z = BitConverter.ToSingle(source, 0xA4); entry.Y = BitConverter.ToSingle(source, 0xA8); entry.Heading = BitConverter.ToSingle(source, 0xB0); entry.Fate = BitConverter.ToUInt32(source, 0xE4); // ?? entry.GatheringInvisible = source[0x11C]; // ?? entry.ModelID = BitConverter.ToUInt32(source, 0x174); entry.ActionStatus = (Actor.ActionStatus)source[0x17C]; entry.IsGM = BitConverter.ToBoolean(source, 0x183); // ? entry.Icon = (Actor.Icon)source[0x18C]; entry.Status = (Actor.Status)source[0x17E]; //0x18E]; entry.ClaimedByID = BitConverter.ToUInt32(source, 0x180); // 0x1A0); var targetID = BitConverter.ToUInt32(source, 0x188); // 0x1A8); var pcTargetID = BitConverter.ToUInt32(source, 0x938); // 0xAA8); entry.Job = (Actor.Job)source[0x1540]; // 0x17C0]; entry.Level = source[0x1541]; // 0x17C1]; entry.GrandCompany = source[0x1543]; // 0x17C3]; entry.GrandCompanyRank = source[0x1544]; //0x17C4]; entry.Title = source[0x1546]; //0x17C6]; entry.HPCurrent = BitConverter.ToInt32(source, 0x1548); // 0x17C8); entry.HPMax = BitConverter.ToInt32(source, 0x154C); // 0x17CC); entry.MPCurrent = BitConverter.ToInt32(source, 0x1550); // 0x17D0); entry.MPMax = BitConverter.ToInt32(source, 0x1554); // 0x17D4); entry.TPCurrent = BitConverter.ToInt16(source, 0x1558); // 0x17D8); entry.TPMax = 1000; entry.GPCurrent = BitConverter.ToInt16(source, 0x155A); // 0x17DA); entry.GPMax = BitConverter.ToInt16(source, 0x155C); // 0x17DC); entry.CPCurrent = BitConverter.ToInt16(source, 0x155E); // 0x17DE); entry.CPMax = BitConverter.ToInt16(source, 0x1560); // 0x17E0); entry.Race = source[0x2808]; // ?? entry.Sex = (Actor.Sex)source[0x2809]; //? entry.IsCasting = BitConverter.ToBoolean(source, 0x2A30); // 0x2C90); entry.CastingID = BitConverter.ToInt16(source, 0x2A34); // 0x2C94); entry.CastingTargetID = BitConverter.ToUInt32(source, 0x2A40); // 0x2CA0); entry.CastingProgress = BitConverter.ToSingle(source, 0x2A64); // 0x2CC4); entry.CastingTime = BitConverter.ToSingle(source, 0x2A68); // 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; } entry.StatusEntries = new List <StatusEntry>(); const int statusSize = 12; var statusesSource = new byte[limit * statusSize]; Buffer.BlockCopy(source, 0x28B8, statusesSource, 0, limit * 12); for (var i = 0; i < limit; i++) { var statusSource = new byte[statusSize]; Buffer.BlockCopy(statusesSource, i * statusSize, statusSource, 0, statusSize); var statusEntry = new StatusEntry { TargetName = entry.Name, StatusID = BitConverter.ToInt16(statusSource, 0x0), Duration = BitConverter.ToSingle(statusSource, 0x4), CasterID = BitConverter.ToUInt32(statusSource, 0x8) }; try { var statusInfo = StatusEffectHelper.StatusInfo(statusEntry.StatusID); statusEntry.IsCompanyAction = statusInfo.CompanyAction; var statusKey = ""; switch (Settings.Default.GameLanguage) { case "English": statusKey = statusInfo.Name.English; break; case "French": statusKey = statusInfo.Name.French; break; case "German": statusKey = statusInfo.Name.German; break; case "Japanese": statusKey = statusInfo.Name.Japanese; break; } statusEntry.StatusName = statusKey; } catch (Exception ex) { statusEntry.StatusName = "UNKNOWN"; } if (statusEntry.IsValid()) { entry.StatusEntries.Add(statusEntry); } } } catch (Exception ex) { } CleanXPValue(ref entry); if (isCurrentUser) { PCWorkerDelegate.CurrentUser = entry; } entry.CurrentUser = PCWorkerDelegate.CurrentUser; return(entry); }
/// <summary> /// </summary> /// <param name="statusEntriesMonsters"></param> private void ProcessDamageOverTime(IEnumerable <StatusEntry> statusEntriesMonsters) { foreach (var statusEntry in statusEntriesMonsters) { try { var statusInfo = StatusEffectHelper.StatusInfo(statusEntry.StatusID); var statusKey = statusInfo.Name.English; switch (Constants.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; } if (String.IsNullOrWhiteSpace(statusKey)) { continue; } var amount = NPCEntry.Level / ((60 - NPCEntry.Level) * .025m); var key = statusKey; XOverTimeAction actionData = null; foreach (var damageOverTimeAction in DamageOverTimeHelper.PlayerActions.ToList() .Where(d => String.Equals(d.Key, key, Constants.InvariantComparer))) { actionData = damageOverTimeAction.Value; } if (actionData == null) { continue; } var zeroFoundInList = false; var bio = Regex.IsMatch(key, @"(バイオ|bactérie|bio|毒菌)", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); var thunder = Regex.IsMatch(key, @"(サンダ|foudre|blitz|thunder|闪雷)", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); var lastDamageAmountByActions = ParseHelper.LastAmountByAction.GetPlayer(Name) .ToList(); var resolvedPotency = 80; var thunderDuration = 24; var originalThunderDamage = 0m; foreach (var lastDamageAmountByAction in lastDamageAmountByActions) { if (thunder) { var found = false; var thunderActions = DamageOverTimeHelper.ThunderActions; var action = lastDamageAmountByAction; if (thunderActions["III"].Any(thunderAction => String.Equals(action.Key, thunderAction, Constants.InvariantComparer))) { found = true; thunderDuration = DamageOverTimeHelper.PlayerActions["thunder iii"].Duration; originalThunderDamage = action.Value; amount = (action.Value / DamageOverTimeHelper.PlayerActions["thunder iii"].ActionPotency) * 30; } if (thunderActions["II"].Any(thunderAction => String.Equals(action.Key, thunderAction, Constants.InvariantComparer))) { found = true; thunderDuration = DamageOverTimeHelper.PlayerActions["thunder ii"].Duration; originalThunderDamage = action.Value; amount = (action.Value / DamageOverTimeHelper.PlayerActions["thunder ii"].ActionPotency) * 30; } if (thunderActions["I"].Any(thunderAction => String.Equals(action.Key, thunderAction, Constants.InvariantComparer))) { found = true; thunderDuration = DamageOverTimeHelper.PlayerActions["thunder"].Duration; originalThunderDamage = action.Value; amount = action.Value; } if (found) { break; } } if (bio) { var found = false; var ruinActions = DamageOverTimeHelper.RuinActions; var action = lastDamageAmountByAction; if (ruinActions["II"].Any(ruinAction => String.Equals(action.Key, ruinAction, Constants.InvariantComparer))) { found = zeroFoundInList = true; amount = action.Value; } if (ruinActions["I"].Any(ruinAction => String.Equals(action.Key, ruinAction, Constants.InvariantComparer))) { found = zeroFoundInList = true; amount = action.Value; } if (found) { break; } } if (String.Equals(lastDamageAmountByAction.Key, key, Constants.InvariantComparer)) { amount = lastDamageAmountByAction.Value; break; } } statusKey = String.Format("{0} [•]", statusKey); if (amount == 0) { amount = 75; } resolvedPotency = zeroFoundInList ? resolvedPotency : bio ? resolvedPotency : actionData.ActionPotency; var tickDamage = Math.Ceiling(((amount / resolvedPotency) * actionData.ActionOverTimePotency) / 3); if (actionData.HasNoInitialResult && !zeroFoundInList) { var nonZeroActions = lastDamageAmountByActions.Where(d => !d.Key.Contains("•")); var keyValuePairs = nonZeroActions as IList <KeyValuePair <string, decimal> > ?? nonZeroActions.ToList(); var damage = 0m; switch (bio) { case true: damage = Math.Ceiling(((amount / resolvedPotency) * actionData.ActionOverTimePotency) / 3); break; case false: if (keyValuePairs.Any()) { amount = keyValuePairs.Sum(action => action.Value); amount = amount / keyValuePairs.Count(); } damage = Math.Ceiling(((amount / resolvedPotency) * actionData.ActionOverTimePotency) / 3); break; } tickDamage = damage > 0 ? damage : tickDamage; } if (originalThunderDamage > 300 && thunder) { tickDamage = Math.Ceiling(originalThunderDamage / (thunderDuration + 3)); } var line = new Line { Action = statusKey, Amount = tickDamage, EventDirection = EventDirection.Unknown, EventType = EventType.Damage, EventSubject = EventSubject.Unknown, Source = Name, Target = statusEntry.TargetName }; Controller.Timeline.FightingRightNow = true; Controller.Timeline.FightingTimer.Stop(); Controller.Timeline.StoreHistoryTimer.Stop(); DispatcherHelper.Invoke(delegate { line.Hit = true; var currentCritPercent = (double)Stats.GetStatValue("DamageCritPercent"); if (new Random().NextDouble() * 3 < currentCritPercent) { line.Crit = true; line.Amount = line.Amount * 1.5m; } Controller.Timeline.GetSetPlayer(line.Source) .SetDamageOverTime(line); Controller.Timeline.GetSetMonster(line.Target) .SetDamageTakenOverTime(line); }); } catch (Exception ex) { } } Controller.Timeline.FightingTimer.Start(); Controller.Timeline.StoreHistoryTimer.Start(); }
private void ProcessBuffs(IEnumerable <StatusEntry> statusEntriesPlayers) { foreach (var statusEntry in statusEntriesPlayers) { try { var statusInfo = StatusEffectHelper.StatusInfo(statusEntry.StatusID); var statusKey = statusInfo.Name.English; switch (Constants.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; } if (String.IsNullOrWhiteSpace(statusKey)) { continue; } var line = new Line { Action = statusKey, Amount = 0, EventDirection = EventDirection.Unknown, EventType = EventType.Unknown, EventSubject = EventSubject.Unknown, Source = Name, }; try { var players = Controller.Timeline.Party.ToList(); var entry = statusEntry; foreach (var player in players.Where(player => player.Name.Contains(entry.TargetName))) { line.Target = player.Name; break; } } catch (Exception ex) { } if (String.IsNullOrWhiteSpace(line.Target)) { line.Target = String.Format("[???] {0}", statusEntry.TargetName); } DispatcherHelper.Invoke(() => Controller.Timeline.GetSetPlayer(line.Source) .SetBuff(line)); } catch (Exception ex) { } } }
/// <summary> /// </summary> /// <param name="statusEntriesPlayers"></param> private void ProcessHealingOverTime(IEnumerable <StatusEntry> statusEntriesPlayers) { foreach (var statusEntry in statusEntriesPlayers) { try { var statusInfo = StatusEffectHelper.StatusInfo(statusEntry.StatusID); var statusKey = statusInfo.Name.English; switch (Constants.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; } if (String.IsNullOrWhiteSpace(statusKey)) { continue; } var amount = NPCEntry.Level / ((60 - NPCEntry.Level) * .025m); var key = statusKey; XOverTimeAction actionData = null; foreach (var healingOverTimeAction in HealingOverTimeHelper.PlayerActions.ToList() .Where(d => String.Equals(d.Key, key, Constants.InvariantComparer))) { actionData = healingOverTimeAction.Value; } if (actionData == null) { continue; } var zeroFoundInList = false; var regen = Regex.IsMatch(key, @"(リジェネ|récup|regen|再生|whispering|murmure|erhebendes|光の囁き|日光的低语)", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); var healingHistoryList = ParseHelper.LastAmountByAction.GetPlayer(Name) .ToList(); var resolvedPotency = 350; foreach (var healingAction in healingHistoryList) { if (regen) { var found = false; var cureActions = HealingOverTimeHelper.CureActions; var medicaActions = HealingOverTimeHelper.MedicaActions; var action = healingAction; if (cureActions["III"].Any(cureAction => String.Equals(action.Key, cureAction, Constants.InvariantComparer))) { found = zeroFoundInList = true; resolvedPotency = 550; } if (cureActions["II"].Any(cureAction => String.Equals(action.Key, cureAction, Constants.InvariantComparer))) { found = zeroFoundInList = true; resolvedPotency = 650; } if (cureActions["I"].Any(cureAction => String.Equals(action.Key, cureAction, Constants.InvariantComparer))) { found = zeroFoundInList = true; resolvedPotency = 400; } if (medicaActions["II"].Any(medicaAction => String.Equals(action.Key, medicaAction, Constants.InvariantComparer))) { found = zeroFoundInList = true; resolvedPotency = 200; } if (medicaActions["I"].Any(medicaAction => String.Equals(action.Key, medicaAction, Constants.InvariantComparer))) { found = zeroFoundInList = true; resolvedPotency = 300; } if (found) { if (action.Value > 0) { amount = action.Value; } break; } } if (String.Equals(healingAction.Key, key, Constants.InvariantComparer)) { amount = healingAction.Value; break; } } statusKey = String.Format("{0} [•]", statusKey); if (amount == 0) { amount = 75; } resolvedPotency = zeroFoundInList ? resolvedPotency : regen ? resolvedPotency : actionData.ActionPotency; var tickHealing = Math.Ceiling(((amount / resolvedPotency) * actionData.ActionOverTimePotency) / 3); if (actionData.HasNoInitialResult && !zeroFoundInList) { var nonZeroActions = healingHistoryList.Where(d => !d.Key.Contains("•")); var keyValuePairs = nonZeroActions as IList <KeyValuePair <string, decimal> > ?? nonZeroActions.ToList(); var healing = 0m; switch (regen) { case true: healing = Math.Ceiling(((amount / resolvedPotency) * actionData.ActionOverTimePotency) / 3); break; case false: if (keyValuePairs.Any()) { amount = keyValuePairs.Sum(action => action.Value); amount = amount / keyValuePairs.Count(); } healing = Math.Ceiling(((amount / resolvedPotency) * actionData.ActionOverTimePotency) / 3); break; } tickHealing = healing > 0 ? healing : tickHealing; } var line = new Line { Action = statusKey, Amount = tickHealing, EventDirection = EventDirection.Unknown, EventType = EventType.Cure, EventSubject = EventSubject.Unknown, Source = Name }; try { var players = Controller.Timeline.Party.ToList(); var entry = statusEntry; foreach (var player in players.Where(player => player.Name.Contains(entry.TargetName))) { line.Target = player.Name; break; } } catch (Exception ex) { } if (String.IsNullOrWhiteSpace(line.Target)) { line.Target = String.Format("[???] {0}", statusEntry.TargetName); } Controller.Timeline.FightingRightNow = true; Controller.Timeline.FightingTimer.Stop(); switch (Settings.Default.StoreHistoryEvent) { case "Any": Controller.Timeline.StoreHistoryTimer.Stop(); break; } DispatcherHelper.Invoke(delegate { line.Hit = true; // resolve player hp each tick to ensure they are not at max try { var players = PCWorkerDelegate.GetNPCEntities(); if (!players.Any()) { return; } foreach (var actorEntity in players) { var playerName = actorEntity.Name; Controller.Timeline.TrySetPlayerCurable(playerName, actorEntity.HPMax - actorEntity.HPCurrent); } } catch (Exception ex) { } var currentCritPercent = (double)Stats.GetStatValue("HealingCritPercent"); if (new Random().NextDouble() * 3 < currentCritPercent) { line.Crit = true; line.Amount = line.Amount * 1.5m; } Controller.Timeline.GetSetPlayer(line.Source) .SetHealingOverTime(line); }); } catch (Exception ex) { } } Controller.Timeline.FightingTimer.Start(); switch (Settings.Default.StoreHistoryEvent) { case "Any": Controller.Timeline.StoreHistoryTimer.Start(); break; } }
/// <summary> /// </summary> /// <param name="sender"> </param> /// <param name="e"> </param> private void ScanTimerElapsed(object sender, ElapsedEventArgs e) { if (_isScanning) { return; } _isScanning = true; double refresh = 1000; if (Double.TryParse(Settings.Default.PartyInfoWorkerRefresh.ToString(CultureInfo.InvariantCulture), out refresh)) { _scanTimer.Interval = refresh; } Func <bool> scannerWorker = delegate { if (MemoryHandler.Instance.SigScanner.Locations.ContainsKey("CHARMAP")) { if (MemoryHandler.Instance.SigScanner.Locations.ContainsKey("PARTYMAP")) { if (MemoryHandler.Instance.SigScanner.Locations.ContainsKey("PARTYCOUNT")) { PartyInfoMap = MemoryHandler.Instance.SigScanner.Locations["PARTYMAP"]; PartyCountMap = MemoryHandler.Instance.SigScanner.Locations["PARTYCOUNT"]; try { var partyEntities = new List <PartyEntity>(); var partyCount = MemoryHandler.Instance.GetByte(PartyCountMap); if (partyCount > 0 && partyCount < 9) { for (uint i = 0; i < partyCount; i++) { uint size; switch (Settings.Default.GameLanguage) { case "Chinese": size = 594; break; default: size = 544; break; } var address = PartyInfoMap + (i * size); var actor = MemoryHandler.Instance.GetStructure <Structures.PartyMember>(address); var entry = new PartyEntity { Name = MemoryHandler.Instance.GetString(address, 32), ID = actor.ID, Coordinate = new Coordinate(actor.X, actor.Z, actor.Y), X = actor.X, Z = actor.Z, Y = actor.Y, Level = actor.Level, HPCurrent = actor.HPCurrent, HPMax = actor.HPMax, MPCurrent = actor.MPCurrent, MPMax = actor.MPMax, Job = actor.Job }; if (entry.HPMax == 0) { entry.HPMax = 1; } foreach (var status in actor.Statuses) { var statusEntry = new StatusEntry { TargetName = entry.Name, StatusID = status.StatusID, Duration = status.Duration, CasterID = status.CasterID }; try { var statusInfo = StatusEffectHelper.StatusInfo(statusEntry.StatusID); statusEntry.IsCompanyAction = statusInfo.CompanyAction; var statusKey = statusInfo.Name.English; switch (Settings.Default.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; } statusEntry.StatusName = statusKey; } catch (Exception ex) { statusEntry.StatusName = "UNKNOWN"; } if (statusEntry.IsValid()) { entry.StatusEntries.Add(statusEntry); } } if (entry.IsValid) { partyEntities.Add(entry); } } } AppContextHelper.Instance.RaiseNewPartyEntries(partyEntities); } catch (Exception ex) { } } } } _isScanning = false; return(true); }; scannerWorker.BeginInvoke(delegate { }, scannerWorker); }
public static ActorEntity ResolveActorFromBytes(byte[] source, bool isCurrentUser = false, ActorEntity entry = null) { entry = entry ?? new ActorEntity(); try { uint targetID; uint pcTargetID; entry.MapIndex = 0; entry.TargetID = 0; switch (Settings.Default.GameLanguage) { case "Chinese": entry.Name = MemoryHandler.Instance.GetStringFromBytes(source, 48); entry.ID = BitConverter.ToUInt32(source, 0x74); entry.NPCID1 = BitConverter.ToUInt32(source, 0x78); entry.NPCID2 = BitConverter.ToUInt32(source, 0x80); entry.OwnerID = BitConverter.ToUInt32(source, 0x84); entry.Type = (Actor.Type)source[0x8A]; entry.TargetType = (Actor.TargetType)source[0x8C]; entry.GatheringStatus = source[0x8E]; entry.Distance = source[0x8F]; entry.X = BitConverter.ToSingle(source, 0xA0); entry.Z = BitConverter.ToSingle(source, 0xA4); entry.Y = BitConverter.ToSingle(source, 0xA8); entry.Heading = BitConverter.ToSingle(source, 0xB0); entry.Fate = BitConverter.ToUInt32(source, 0xE4); // ?? entry.GatheringInvisible = source[0x11C]; // ?? entry.ModelID = BitConverter.ToUInt32(source, 0x174); entry.ActionStatus = (Actor.ActionStatus)source[0x17C]; entry.IsGM = BitConverter.ToBoolean(source, 0x183); // ? entry.Icon = (Actor.Icon)source[0x18C]; entry.Status = (Actor.Status)source[0x18E]; entry.ClaimedByID = BitConverter.ToUInt32(source, 0x1A0); targetID = BitConverter.ToUInt32(source, 0x1A8); pcTargetID = BitConverter.ToUInt32(source, 0xAA8); entry.Job = (Actor.Job)source[0x17C0]; entry.Level = source[0x17C1]; entry.GrandCompany = source[0x17C3]; entry.GrandCompanyRank = source[0x17C4]; entry.Title = source[0x17C6]; entry.HPCurrent = BitConverter.ToInt32(source, 0x17C8); entry.HPMax = BitConverter.ToInt32(source, 0x17CC); entry.MPCurrent = BitConverter.ToInt32(source, 0x17D0); entry.MPMax = BitConverter.ToInt32(source, 0x17D4); entry.TPCurrent = BitConverter.ToInt16(source, 0x17D8); entry.TPMax = 1000; entry.GPCurrent = BitConverter.ToInt16(source, 0x17DA); entry.GPMax = BitConverter.ToInt16(source, 0x17DC); entry.CPCurrent = BitConverter.ToInt16(source, 0x17DE); entry.CPMax = BitConverter.ToInt16(source, 0x17E0); entry.Race = source[0x2E58]; // ?? entry.Sex = (Actor.Sex)source[0x2E59]; //? entry.IsCasting = BitConverter.ToBoolean(source, 0x32E0); entry.CastingID = BitConverter.ToInt16(source, 0x32E4); entry.CastingTargetID = BitConverter.ToUInt32(source, 0x32F0); entry.CastingProgress = BitConverter.ToSingle(source, 0x3314); entry.CastingTime = BitConverter.ToSingle(source, 0x33F8); entry.Coordinate = new Coordinate(entry.X, entry.Z, entry.Y); break; default: entry.Name = MemoryHandler.Instance.GetStringFromBytes(source, 48); entry.ID = BitConverter.ToUInt32(source, 0x74); entry.NPCID1 = BitConverter.ToUInt32(source, 0x7C); entry.NPCID2 = BitConverter.ToUInt32(source, 0x80); entry.OwnerID = BitConverter.ToUInt32(source, 0x84); entry.Type = (Actor.Type)source[0x8A]; entry.TargetType = (Actor.TargetType)source[0x8C]; entry.GatheringStatus = source[0x8F]; entry.Distance = source[0x91]; var defaultBaseOffset = MemoryHandler.Instance.ProcessModel.IsWin64 ? 0x10 : 0; entry.X = BitConverter.ToSingle(source, 0xA0 + defaultBaseOffset); entry.Z = BitConverter.ToSingle(source, 0xA4 + defaultBaseOffset); entry.Y = BitConverter.ToSingle(source, 0xA8 + defaultBaseOffset); entry.Heading = BitConverter.ToSingle(source, 0xB0 + defaultBaseOffset); entry.HitBoxRadius = BitConverter.ToSingle(source, 0xC0 + defaultBaseOffset); entry.Fate = BitConverter.ToUInt32(source, 0xE4 + defaultBaseOffset); // ?? entry.GatheringInvisible = source[0x11C]; // ?? entry.ModelID = BitConverter.ToUInt32(source, 0x174); entry.ActionStatus = (Actor.ActionStatus)source[0x17C]; // 0x17D - 0 = Green name, 4 = non-agro (yellow name) entry.IsGM = BitConverter.ToBoolean(source, 0x183); // ? entry.Icon = (Actor.Icon)source[0x18C]; entry.Status = (Actor.Status)source[0x17E]; //0x18E]; entry.ClaimedByID = BitConverter.ToUInt32(source, 0x180); // 0x1A0); targetID = BitConverter.ToUInt32(source, 0x188); // 0x1A8); pcTargetID = BitConverter.ToUInt32(source, 0x938); // 0xAA8); var defaultStatOffset = MemoryHandler.Instance.ProcessModel.IsWin64 ? 0x230 : 0; entry.Job = (Actor.Job)source[0x14C0 + defaultStatOffset]; // 0x17C0]; entry.Level = source[0x14C1 + defaultStatOffset]; // 0x17C1]; entry.GrandCompany = source[0x14C3 + defaultStatOffset]; // 0x17C3]; entry.GrandCompanyRank = source[0x14C4 + defaultStatOffset]; //0x17C4]; entry.Title = source[0x1546 + defaultStatOffset]; //0x17C6]; entry.HPCurrent = BitConverter.ToInt32(source, 0x14C8 + defaultStatOffset); // 0x17C8); entry.HPMax = BitConverter.ToInt32(source, 0x14CC + defaultStatOffset); // 0x17CC); entry.MPCurrent = BitConverter.ToInt32(source, 0x14D0 + defaultStatOffset); // 0x17D0); entry.MPMax = BitConverter.ToInt32(source, 0x14D4 + defaultStatOffset); // 0x17D4); entry.TPCurrent = BitConverter.ToInt16(source, 0x14D8 + defaultStatOffset); // 0x17D8); entry.TPMax = 1000; entry.GPCurrent = BitConverter.ToInt16(source, 0x14DA + defaultStatOffset); // 0x17DA); entry.GPMax = BitConverter.ToInt16(source, 0x14DC + defaultStatOffset); // 0x17DC); entry.CPCurrent = BitConverter.ToInt16(source, 0x14DE + defaultStatOffset); // 0x17DE); entry.CPMax = BitConverter.ToInt16(source, 0x14E0 + defaultStatOffset); // 0x17E0); entry.Race = source[0x2808]; // ?? entry.Sex = (Actor.Sex)source[0x2809]; //? entry.IsCasting = BitConverter.ToBoolean(source, 0x2A30); // 0x2C90); entry.CastingID = BitConverter.ToInt16(source, 0x2A34); // 0x2C94); entry.CastingTargetID = BitConverter.ToUInt32(source, 0x2A40); // 0x2CA0); entry.CastingProgress = BitConverter.ToSingle(source, 0x2A64); // 0x2CC4); entry.CastingTime = BitConverter.ToSingle(source, 0x2A68); // 0x2DA8); entry.Coordinate = new Coordinate(entry.X, entry.Z, entry.Y); break; } 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; } entry.StatusEntries = new List <StatusEntry>(); const int statusSize = 12; var statusesSource = new byte[limit * statusSize]; switch (Settings.Default.GameLanguage) { case "Chinese": Buffer.BlockCopy(source, 0x3168, statusesSource, 0, limit * 12); break; default: var defaultStatusEffectOffset = MemoryHandler.Instance.ProcessModel.IsWin64 ? 0x3740 : 0x2878; Buffer.BlockCopy(source, defaultStatusEffectOffset, statusesSource, 0, limit * 12); break; } for (var i = 0; i < limit; i++) { var statusSource = new byte[statusSize]; Buffer.BlockCopy(statusesSource, i * statusSize, statusSource, 0, statusSize); var statusEntry = new StatusEntry { TargetEntity = entry, TargetName = entry.Name, StatusID = BitConverter.ToInt16(statusSource, 0x0), Stacks = statusSource[0x2], Duration = BitConverter.ToSingle(statusSource, 0x4), CasterID = BitConverter.ToUInt32(statusSource, 0x8) }; try { var pc = PCWorkerDelegate.GetNPCEntity(statusEntry.CasterID); var npc = NPCWorkerDelegate.GetNPCEntity(statusEntry.CasterID); var monster = MonsterWorkerDelegate.GetNPCEntity(statusEntry.CasterID); statusEntry.SourceEntity = (pc ?? npc) ?? monster; } catch (Exception ex) { } try { var statusInfo = StatusEffectHelper.StatusInfo(statusEntry.StatusID); statusEntry.IsCompanyAction = statusInfo.CompanyAction; var statusKey = statusInfo.Name.English; switch (Settings.Default.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; } statusEntry.StatusName = statusKey; } catch (Exception ex) { statusEntry.StatusName = "UNKNOWN"; } if (statusEntry.IsValid()) { entry.StatusEntries.Add(statusEntry); } } } catch (Exception ex) { } CleanXPValue(ref entry); if (isCurrentUser) { PCWorkerDelegate.CurrentUser = entry; } entry.CurrentUser = PCWorkerDelegate.CurrentUser; return(entry); }
public static PartyEntity ResolvePartyMemberFromBytes(byte[] source, ActorEntity actorEntity = null) { if (actorEntity != null) { var entry = new PartyEntity { X = actorEntity.X, Y = actorEntity.Y, Z = actorEntity.Z, Coordinate = actorEntity.Coordinate, ID = actorEntity.ID, Name = actorEntity.Name, Job = actorEntity.Job, Level = actorEntity.Level, HPCurrent = actorEntity.HPCurrent, HPMax = actorEntity.HPMax, MPCurrent = actorEntity.MPCurrent, MPMax = actorEntity.MPMax, StatusEntries = actorEntity.StatusEntries, }; CleanXPValue(ref entry); return(entry); } else { var entry = new PartyEntity(); try { switch (Settings.Default.GameLanguage) { case "Chinese": default: entry.X = BitConverter.ToSingle(source, 0x0); entry.Z = BitConverter.ToSingle(source, 0x4); entry.Y = BitConverter.ToSingle(source, 0x8); entry.Coordinate = new Coordinate(entry.X, entry.Z, entry.Z); entry.ID = BitConverter.ToUInt32(source, 0x10); entry.Name = MemoryHandler.Instance.GetStringFromBytes(source, 0x20); entry.Job = (Actor.Job)source[0x61]; entry.Level = source[0x63]; entry.HPCurrent = BitConverter.ToInt32(source, 0x68); entry.HPMax = BitConverter.ToInt32(source, 0x6C); entry.MPCurrent = BitConverter.ToInt16(source, 0x70); entry.MPMax = BitConverter.ToInt16(source, 0x72); break; } const int limit = 15; entry.StatusEntries = new List <StatusEntry>(); const int statusSize = 12; var statusesSource = new byte[limit * statusSize]; switch (Settings.Default.GameLanguage) { case "Chinese": default: var defaultStatusEffectOffset = MemoryHandler.Instance.ProcessModel.IsWin64 ? 0x88 : 0x80; Buffer.BlockCopy(source, defaultStatusEffectOffset, statusesSource, 0, limit * 12); break; } for (var i = 0; i < limit; i++) { var statusSource = new byte[statusSize]; Buffer.BlockCopy(statusesSource, i * statusSize, statusSource, 0, statusSize); var statusEntry = new StatusEntry { TargetName = entry.Name, StatusID = BitConverter.ToInt16(statusSource, 0x0), Stacks = statusSource[0x2], Duration = BitConverter.ToSingle(statusSource, 0x4), CasterID = BitConverter.ToUInt32(statusSource, 0x8) }; try { var pc = PCWorkerDelegate.GetNPCEntity(statusEntry.CasterID); var npc = NPCWorkerDelegate.GetNPCEntity(statusEntry.CasterID); var monster = MonsterWorkerDelegate.GetNPCEntity(statusEntry.CasterID); statusEntry.SourceEntity = (pc ?? npc) ?? monster; } catch (Exception ex) { } try { if (statusEntry.StatusID > 0) { var statusInfo = StatusEffectHelper.StatusInfo(statusEntry.StatusID); statusEntry.IsCompanyAction = statusInfo.CompanyAction; var statusKey = statusInfo.Name.English; switch (Settings.Default.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; } statusEntry.StatusName = statusKey; } } catch (Exception ex) { statusEntry.StatusName = "UNKNOWN"; } if (statusEntry.IsValid()) { entry.StatusEntries.Add(statusEntry); } } } catch (Exception ex) { } CleanXPValue(ref entry); return(entry); } }