package common import pb "gac-hkrpg-go/protocol/proto" // BattleAvatarServantInfo is a separate native statistic, keyed by its owner's // avatar_id. Never infer ownership from lineup position or the servant's ID. func applyBattleServantStatistics(report *BattleReport, servants []*pb.BattleAvatarServantInfo) { owners := make(map[uint32]*BattleAvatarReport, len(report.Avatars)) for _, avatar := range report.Avatars { owners[avatar.AvatarID] = avatar } matched := false seen := make(map[uint32]bool) for _, servant := range servants { if servant == nil || servant.AvatarId == 0 { continue } owner := owners[servant.AvatarId] if owner == nil || (servant.EntityId != 0 && seen[servant.EntityId]) { continue } if servant.EntityId != 0 { seen[servant.EntityId] = true } matched = true damage := servant.TotalDamage if damage == 0 { damage = sumAttackDamageProperties(servant.AttackTypeDamage) } owner.TotalDamage += damage owner.MemospriteDamage += damage owner.TotalBreakDamage += servant.TotalBreakDamage owner.TotalHeal += servant.TotalHeal owner.TotalShield += servant.TotalShield for _, pair := range []struct { values []*pb.AttackDamageProperty target map[string]float64 maximum bool }{{servant.AttackTypeDamage, owner.AttackTypeDamage, false}, {servant.AttackTypeBreakDamage, owner.AttackTypeBreakDamage, false}, {servant.AttackTypeMaxDamage, owner.AttackTypeMaxDamage, true}} { for _, value := range pair.values { if value == nil || value.AttackType == "" { continue } if pair.maximum { pair.target[value.AttackType] = max(pair.target[value.AttackType], value.Damage) } else { pair.target[value.AttackType] += value.Damage } } } } if !matched { return } // Rebuild from attributed records; the earlier monster fallback can already // include servant damage, so adding to that fallback would count it twice. report.TeamTotalDamage, report.TeamTotalHeal, report.TeamTotalShield = 0, 0, 0 for _, avatar := range report.Avatars { report.TeamTotalDamage += avatar.TotalDamage report.TeamTotalHeal += avatar.TotalHeal report.TeamTotalShield += avatar.TotalShield } for _, avatar := range report.Avatars { avatar.DamagePercent = 0 if report.TeamTotalDamage > 0 { avatar.DamagePercent = avatar.TotalDamage / report.TeamTotalDamage * 100 } } }