public PlayerInfo(Player user, DamageTracker tracker) { Tracker = tracker; Player = user; SkillLog = CollectionHelper.Instance.CreateSyncedCollection<SkillResult>(); Received = new SkillStats(tracker, SkillLog); Dealt = new SkillStats(tracker, SkillLog); }
public PlayerInfo(Player user, DamageTracker tracker) { Tracker = tracker; Player = user; SkillLog = new SynchronizedObservableCollection <SkillResult>(); Received = new SkillStats(tracker, SkillLog); Dealt = new SkillStats(tracker, SkillLog); }
private void ResetDamageTracker(ResetPlayerStatsMessage message = null) { if (Server == null) return; var saveEncounter = message != null && message.ShouldSaveCurrent; if (saveEncounter && !DamageTracker.IsArchived && DamageTracker.StatsByUser.Count > 0 && DamageTracker.FirstAttack != null && DamageTracker.LastAttack != null) { DamageTracker.IsArchived = true; DamageTracker.Abnormals = _abnormalityStorage.Clone(); ArchivedDamageTrackers.Add(DamageTracker); return; } if (message != null && !message.ShouldSaveCurrent && DamageTracker.IsArchived) { ArchivedDamageTrackers.Remove(DamageTracker); } _abnormalityStorage.ClearEnded(); DamageTracker = new DamageTracker { OnlyBosses = OnlyBosses, IgnoreOneshots = IgnoreOneshots, Abnormals = _abnormalityStorage }; }
private void LoadEncounter(DamageTracker obj) { DamageTracker = obj; }
/// <summary> /// Creates a new instance of SkillStats /// </summary> /// <param name="tracker">DamageTracker used for calculations</param> /// <param name="skillLog">SkillLog used for calculations</param> public SkillStats(DamageTracker tracker, SyncedCollection<SkillResult> skillLog) { _tracker = tracker; _skillLog = skillLog; }
public static bool IsValid(this EachSkillResultServerMessage message, DamageTracker tracker = null) { return(message != null && !message.IsUseless && //stuff like warrior DFA (tracker?.FirstAttack != null || (!message.IsHeal && message.Amount > 0)) && //only record first hit is it's a damage hit (heals occurring outside of fights) !(message.Target.Equals(message.Source) && !message.IsHeal && message.Amount > 0)); //disregard damage dealt to self (gunner self destruct) }
public static bool IsValid(this EachSkillResultServerMessage message, DamageTracker tracker = null) { return message != null && !message.IsUseless && //stuff like warrior DFA (tracker?.FirstAttack != null || (!message.IsHeal && message.Amount > 0)) &&//only record first hit is it's a damage hit (heals occurring outside of fights) !(message.Target.Equals(message.Source) && !message.IsHeal && message.Amount > 0);//disregard damage dealt to self (gunner self destruct) }
/// <summary> /// Creates a new instance of SkillStats /// </summary> /// <param name="tracker">DamageTracker used for calculations</param> /// <param name="skillLog">SkillLog used for calculations</param> public SkillStats(DamageTracker tracker, SynchronizedObservableCollection <SkillResult> skillLog) { _tracker = tracker; _skillLog = skillLog; }
public static void ToTeraDpsApi(ExportType exportType, DamageTracker damageTracker, TeraData teraData) { if (exportType == ExportType.None) return; //if we want to upload, primary target must be dead if (exportType.HasFlag(ExportType.Upload) && !damageTracker.IsPrimaryTargetDead) return; var exportToExcel = (exportType & (ExportType.Excel | ExportType.ExcelTemp)) != 0; //if we're not exporting to excel and credentials aren't fully entered, return //if (!exportToExcel // && (string.IsNullOrEmpty(SettingsHelper.Instance.Settings.TeraDpsToken) // || string.IsNullOrEmpty(SettingsHelper.Instance.Settings.TeraDpsUser))) // return; //ignore if not a boss var entity = damageTracker.PrimaryTarget; if (!(entity?.Info.Boss ?? false)) return; var abnormals = damageTracker.Abnormals; bool timedEncounter = false; //Nightmare desolarus if (entity.Info.HuntingZoneId == 759 && entity.Info.TemplateId == 1003) { timedEncounter = true; } var firstHit = damageTracker.StatsByUser.SelectMany(x => x.SkillLog).Where(x => x.Target == entity).Min(x => x.Time as DateTime?) ?? new DateTime(0); var lastHit = damageTracker.StatsByUser.SelectMany(x => x.SkillLog).Where(x => x.Target == entity).Max(x => x.Time as DateTime?) ?? new DateTime(0); var firstTick = firstHit.Ticks; var lastTick = lastHit.Ticks; var interval = lastTick - firstTick; var seconds = interval/TimeSpan.TicksPerSecond; if (seconds == 0) return; long totaldamage; if (timedEncounter) totaldamage = damageTracker.StatsByUser.SelectMany(x => x.SkillLog) .Where(x => x.Time >= firstHit && x.Time <= lastHit) .Sum(x => x.Damage); else totaldamage = damageTracker.StatsByUser.SelectMany(x => x.SkillLog) .Where(x => x.Target == entity) .Sum(x => x.Damage); var partyDps = TimeSpan.TicksPerSecond * totaldamage / interval; var teradpsData = new EncounterBase { encounterUnixEpoch = DateTimeTools.DateTimeToUnixTimestamp(damageTracker.LastAttack?.ToUniversalTime() ?? DateTime.UtcNow), areaId = entity.Info.HuntingZoneId + "", bossId = entity.Info.TemplateId + "", fightDuration = seconds + "", partyDps = partyDps + "" }; foreach (var debuff in abnormals.Get(entity).OrderByDescending(x=>x.Value.Duration(firstTick, lastTick))) { long percentage = debuff.Value.Duration(firstTick, lastTick) * 100 / interval; if(percentage == 0) { continue; } teradpsData.debuffUptime.Add(new KeyValuePair<string, string>( debuff.Key.Id+"", percentage+"" )); } foreach (var user in damageTracker.StatsByUser.OrderByDescending(x=>x.Dealt.Damage)) { var filteredSkillog = timedEncounter ? user.SkillLog.Where(x => x.Time >= firstHit && x.Time <= lastHit).ToList() : user.SkillLog.Where(x => x.Target == entity).ToList(); long damage=filteredSkillog.Sum(x => x.Damage); if (damage <= 0) continue; var teradpsUser = new Members(); teradpsUser.playerTotalDamage = damage + ""; var buffs = abnormals.Get(user.Player); teradpsUser.playerClass = user.Class.ToString(); teradpsUser.playerName = user.Name; teradpsUser.playerServer = SettingsHelper.Instance.BasicTeraData.Servers.GetServerName(user.Player.ServerId); teradpsUser.playerAverageCritRate = Math.Round(100 * (double)filteredSkillog.Count(x => x.IsCritical && x.Damage > 0) / filteredSkillog.Count(x => x.Damage > 0)) + ""; teradpsUser.healCrit = user.Player.IsHealer ? Math.Round(100 * (double)filteredSkillog.Count(x => x.IsCritical && x.Heal > 0) / filteredSkillog.Count(x => x.Heal > 0)) + "" : null; teradpsUser.playerDps = TimeSpan.TicksPerSecond * damage / interval + ""; teradpsUser.playerTotalDamagePercentage = damage * 100 / totaldamage + ""; var death = buffs.Death; teradpsUser.playerDeaths = death.Count(firstTick, lastTick) + ""; teradpsUser.playerDeathDuration = death.Duration(firstTick, lastTick)/TimeSpan.TicksPerSecond + ""; var aggro = buffs.Aggro(entity); teradpsUser.aggro = 100 * aggro.Duration(firstTick, lastTick) / interval + ""; foreach (var buff in buffs.Times.OrderByDescending(x => x.Value.Duration(firstTick, lastTick))) { long percentage = (buff.Value.Duration(firstTick, lastTick) * 100 / interval); if (percentage == 0) { continue; } teradpsUser.buffUptime.Add(new KeyValuePair<string, string>( buff.Key.Id + "", percentage + "" )); } var aggregated = new List<AggregatedSkillResult>(); var collection = new List<SkillResult>(); foreach (var skill in filteredSkillog) { collection.Add(skill); if (aggregated.All(asr => !skill.IsSameSkillAs(asr))) aggregated.Add(new AggregatedSkillResult(skill.SkillShortName, skill.IsHeal, AggregationType.Name, CollectionHelper.Instance.CreateSyncedCollection(collection))); } foreach (var skill in aggregated.OrderByDescending(x=>x.Damage)) { var skillLog = new SkillLog(); var skilldamage = skill.Damage; if (skilldamage == 0) continue; skillLog.skillAverageCrit = skill.AverageCrit + ""; skillLog.skillAverageWhite = skill.AverageWhite + ""; skillLog.skillCritRate = Math.Round(skill.CritRate * 100) + ""; skillLog.skillDamagePercent = Math.Round(skill.DamagePercent * 100) + ""; skillLog.skillHighestCrit = skill.HighestCrit + ""; skillLog.skillHits = skill.Hits + ""; skillLog.skillId = teraData.SkillDatabase.GetSkillByPetName(skill.NpcInfo?.Name,user.Player.RaceGenderClass)?.Id.ToString() ?? skill.SkillId.ToString(); skillLog.skillLowestCrit = skill.LowestCrit + ""; skillLog.skillTotalDamage = skilldamage + ""; teradpsUser.skillLog.Add(skillLog); } teradpsData.members.Add(teradpsUser); } //export to excel if specified if (exportToExcel) Task.Run(() => ExcelExport.ExcelSave(exportType, teradpsData, teraData)); //return if we don't need to upload if (!exportType.HasFlag(ExportType.Upload)) return; /* Validation, without that, the server cpu will be burning \o */ var areaId = int.Parse(teradpsData.areaId); if ( //areaId != 886 && //areaId != 467 && //areaId != 767 && //areaId != 768 && //areaId != 468 && areaId != 770 && areaId != 769 && areaId != 916 && areaId != 969 && areaId != 970 && areaId != 950 ) { return; } //if (int.Parse(teradpsData.partyDps) < 2000000 && areaId != 468) //{ // return; //} try { using (var client = new HttpClient()) { client.Timeout = TimeSpan.FromSeconds(40); var response = client.GetAsync("http://moongourd.com/shared/servertime"); var timediff = (response.Result.Headers.Date.Value.UtcDateTime.Ticks - DateTime.UtcNow.Ticks) / TimeSpan.TicksPerSecond; teradpsData.encounterUnixEpoch += timediff; } } catch (Exception e) { Debug.WriteLine("Get server time error"); return; } var json = JsonConvert.SerializeObject(teradpsData, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); Task.Run(() => Send(entity, json, 3)); }