using System;
|
using System.Collections;
|
using System.Collections.Generic;
|
using System.Linq;
|
using UnityEngine;
|
using LitJson;
|
using Spine;
|
|
//!单英雄查看战力 只算自己的上阵属性 不算羁绊 总上阵属性 光环
|
// 战力的计算方式
|
// 先算上阵的单武将战力按公式一一算出各个属性(基础/战斗),再把算出来的各个属性代入到战力公式
|
// 所有武将战力加起来 + 技能战力汇总(公式)就是整个号的战力
|
public class FightPowerManager : Singleton<FightPowerManager>
|
{
|
public string propertyFormula;
|
public string fightPropertyFormula;
|
public string fightPowerFormula;
|
public string skillFightPowerFormula;
|
|
Dictionary<string, double> propertyVariables = new Dictionary<string, double>();
|
Dictionary<string, double> fightPowerVariables = new Dictionary<string, double>(); //总战力中的单武将战力
|
|
|
public FightPowerManager()
|
{
|
// 数值1:基础三维属性计算公式
|
// 数值2:战斗属性/战斗抗性/特殊属性计算公式
|
// 数值3:属性战力计算公式,计算参数详见 S.属性条目配置
|
var config = FuncConfigConfig.Get("HeroAttrFormula");
|
propertyFormula = config.Numerical1;
|
fightPropertyFormula = config.Numerical2;
|
fightPowerFormula = config.Numerical3;
|
skillFightPowerFormula = config.Numerical4;
|
}
|
|
#region 初始化战力计算的信息
|
TeamType teamTypeCalc = TeamType.Story; //不同阵容战力不同
|
bool isPreviewTeamPower; //预览阵容(队伍)战力
|
int dropIndexCalc = -1; //掉落装备在阵容的索引,用于预览战力对比
|
|
//计算阵容战力,装备对比等情况需要代入
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="teamType">阵容类型</param>
|
/// <param name="dropindex">掉落装备的索引,-1代表不替换计算</param>
|
/// <param name="ispreview">预览阵容战力</param>
|
public void InitFightPowerParam(TeamType teamType = TeamType.Story, int dropindex = -1, bool ispreview = false)
|
{
|
teamTypeCalc = teamType;
|
isPreviewTeamPower = ispreview;
|
|
dropIndexCalc = dropindex;
|
#if UNITY_EDITOR
|
Debug.Log("战力:初始化参数 dropIndex:" + dropIndexCalc + " 阵型:" + teamTypeCalc + " ispreview:" + ispreview);
|
#endif
|
}
|
#endregion
|
|
|
|
#region 先计算所有功能的汇总属性
|
|
//功能属性 类型:值
|
public Dictionary<int, int> lvAttrs = new Dictionary<int, int>(); //等级属性
|
|
//分开存储预览和 真实属性
|
public Dictionary<int, int> equipAttrs = new Dictionary<int, int>(); //装备属性
|
public Dictionary<string, int> lineUpPerDict = new Dictionary<string, int>(); //阵容属性加成
|
public Dictionary<int, int> countryAttrs = new Dictionary<int, int>(); //阵容国家(光环)属性
|
|
//等级属性
|
void RefreshLVAttrs()
|
{
|
lvAttrs.Clear();
|
var playerLVConfig = PlayerLVConfig.Get(PlayerDatas.Instance.baseData.LV);
|
foreach (var attrType in PlayerPropertyConfig.baseAttrs)
|
{
|
lvAttrs[attrType] = GetPlayerLVValue(playerLVConfig, attrType);
|
}
|
#if UNITY_EDITOR
|
Debug.Log("战力:等级属性 " + JsonMapper.ToJson(lvAttrs));
|
#endif
|
|
}
|
|
public int GetPlayerLVValue(PlayerLVConfig config, int type)
|
{
|
if (type == 6)
|
{
|
return config.Atk;
|
}
|
else if (type == 7)
|
{
|
return config.Def;
|
}
|
else if (type == 8)
|
{
|
return config.MaxHP;
|
}
|
return 0;
|
}
|
|
//装备属性:身上装备汇总
|
void RefrehEquipAttrs()
|
{
|
equipAttrs.Clear(); //身上装备属性重置
|
for (int i = 0; i < EquipModel.TotleEquip; i++)
|
{
|
var equip = EquipModel.Instance.GetEquip(i);
|
if (dropIndexCalc != -1)
|
{
|
var dropEquip = PackManager.Instance.GetItemByIndex(PackType.DropItem, dropIndexCalc);
|
if (dropEquip.config.EquipPlace - 1 == i)
|
{
|
equip = dropEquip; //替换计算总战力
|
}
|
}
|
if (equip == null)
|
{
|
continue;
|
}
|
var baseIDAttrs = EquipModel.Instance.GetEquipBaseAttrs(equip);
|
var baseVauleAttrs = EquipModel.Instance.GetEquipBaseValues(equip);
|
if (baseIDAttrs != null)
|
{
|
for (int j = 0; j < baseIDAttrs.Count; j++)
|
{
|
if (!equipAttrs.ContainsKey(baseIDAttrs[j]))
|
{
|
equipAttrs[baseIDAttrs[j]] = baseVauleAttrs[j];
|
}
|
else
|
{
|
equipAttrs[baseIDAttrs[j]] += baseVauleAttrs[j];
|
}
|
}
|
}
|
|
var fightIDAttrs = EquipModel.Instance.GetEquipFightAttrs(equip);
|
var fightValueAttrs = EquipModel.Instance.GetEquipFightValues(equip);
|
if (fightIDAttrs != null)
|
{
|
for (int j = 0; j < fightIDAttrs.Count; j++)
|
{
|
if (!equipAttrs.ContainsKey(fightIDAttrs[j]))
|
{
|
equipAttrs[fightIDAttrs[j]] = fightValueAttrs[j];
|
}
|
else
|
{
|
equipAttrs[fightIDAttrs[j]] += fightValueAttrs[j];
|
}
|
}
|
}
|
}
|
|
#if UNITY_EDITOR
|
Debug.Log("战力:装备属性 " + JsonMapper.ToJson(equipAttrs));
|
#endif
|
}
|
|
// 计算队伍中上阵的所有武将的上阵属性 和 光环
|
void RefreshTeamAttrs()
|
{
|
//阵容属性
|
// 阵容:所有武将上阵属性
|
lineUpPerDict = HeroUIManager.Instance.GetLineupPer(teamTypeCalc, isPreviewTeamPower);
|
|
#if UNITY_EDITOR
|
Debug.Log("战力:上阵属性 " + JsonMapper.ToJson(lineUpPerDict));
|
#endif
|
// 阵容:国家(光环)属性
|
countryAttrs = HeroUIManager.Instance.GetCountryAttrs(teamTypeCalc, isPreviewTeamPower);
|
#if UNITY_EDITOR
|
Debug.Log("战力:国家(光环)属性 " + JsonMapper.ToJson(countryAttrs));
|
#endif
|
}
|
|
#endregion
|
|
//单属性公式分基础三维和战斗属性
|
// 【主公属性】
|
// 等级属性 lvValue
|
// 装备属性 equipValue
|
// 图鉴属性 bookValue 、 bookPer
|
|
// 【阵容属性】 - 该阵容所有武将有效
|
// 初始加成 lineupInitAddPer
|
// 升级加成 lineupLVAddPer
|
// 突破加成 lineupBreakLVAddPer
|
// 吞噬加成 lineupStarAddPer
|
// 阵容光环 lineupHaloValue 、 lineupHaloPer
|
|
// 【武将属性】
|
// 继承比例 inheritPer
|
// 自身属性 heroSelfValue 、 heroSelfPer
|
// 吞噬属性 starTalentValue 、 starTalentPer
|
// 突破属性 breakLVValue 、 breakLVPer
|
// 觉醒属性 awakeTalentValue 、 awakeTalentPer
|
// 羁绊属性 fetterValue 、 fetterPer
|
|
#region 属性公式
|
// 单基础属性计算
|
public double GetPropertyVaule(int attrType, HeroInfo hero, string formula)
|
{
|
propertyVariables.Clear();
|
propertyVariables["lvValue"] = lvAttrs.ContainsKey(attrType) ? lvAttrs[attrType] : 0;
|
propertyVariables["equipValue"] = equipAttrs.ContainsKey(attrType) ? equipAttrs[attrType] : 0;
|
propertyVariables["bookValue"] = 0;
|
propertyVariables["bookPer"] = GetBookPer(attrType) / 10000.0f;
|
|
//!!!单武将战力预览的话需要排除队伍影响战力,只算武将自身的上阵属性
|
propertyVariables["lineupInitAddPer"] = GetLineUpPer(attrType, "lineupInitAddPer") / 10000.0f;
|
propertyVariables["lineupLVAddPer"] = GetLineUpPer(attrType, "lineupLVAddPer") / 10000.0f;
|
propertyVariables["lineupBreakLVAddPer"] = GetLineUpPer(attrType, "lineupBreakLVAddPer") / 10000.0f;
|
propertyVariables["lineupStarAddPer"] = GetLineUpPer(attrType, "lineupStarAddPer") / 10000.0f;
|
|
//阵容光环 三围百分比加成
|
propertyVariables["lineupHaloValue"] = countryAttrs.ContainsKey(attrType) ? countryAttrs[attrType] : 0;
|
propertyVariables["lineupHaloPer"] = GetCountryPer(attrType) / 10000.0f;
|
|
|
//武将属性
|
propertyVariables["inheritPer"] = hero.GetInheritAttrPer(attrType) / 10000.0f;
|
propertyVariables["heroSelfValue"] = hero.GetSelfAddValue(attrType);
|
propertyVariables["heroSelfPer"] = hero.GetSelfAddPer(attrType) / 10000.0f;
|
propertyVariables["starTalentValue"] = hero.GetTalentAttrValue(attrType);
|
propertyVariables["starTalentPer"] = hero.GetTalentAttrPer(attrType) / 10000.0f;
|
propertyVariables["breakLVValue"] = hero.GetBreakAttrValue(attrType);
|
propertyVariables["breakLVPer"] = hero.GetBreakAttrPer(attrType) / 10000.0f;
|
propertyVariables["awakeTalentValue"] = hero.GetAwakeAttrValue(attrType);
|
propertyVariables["awakeTalentPer"] = hero.GetAwakeAttrPer(attrType) / 10000.0f;
|
propertyVariables["fetterValue"] = hero.GetFetterAttrValue(attrType);
|
propertyVariables["fetterPer"] = hero.GetFetterAttrPer(attrType) / 10000.0f;
|
|
#if UNITY_EDITOR
|
//排除值为0的属性输出
|
var tmpPropertyVariables = propertyVariables.Where(x => x.Value > 0).ToDictionary(x => x.Key, x => x.Value);
|
if (!tmpPropertyVariables.IsNullOrEmpty())
|
propertyStrForDebug += $"属性ID {attrType} - {JsonMapper.ToJson(tmpPropertyVariables)}";
|
#endif
|
return JaceCalculator.Calculate(formula, propertyVariables);
|
}
|
|
|
int GetLineUpPer(int attrType, string key)
|
{
|
if (!PlayerPropertyConfig.baseAttrs.Contains(attrType))
|
{
|
return 0;
|
}
|
|
return lineUpPerDict[key];
|
}
|
|
int GetBookPer(int attrType)
|
{
|
if (!PlayerPropertyConfig.baseAttrs.Contains(attrType))
|
{
|
return 0;
|
}
|
return HeroUIManager.Instance.bookPer;
|
}
|
|
int GetCountryPer(int attrType)
|
{
|
if (PlayerPropertyConfig.baseAttr2perDict.ContainsKey(attrType))
|
{
|
var pertype = PlayerPropertyConfig.baseAttr2perDict[attrType];
|
return countryAttrs.ContainsKey(pertype) ? countryAttrs[pertype] : 0;
|
}
|
|
return 0;
|
}
|
|
|
|
#endregion
|
|
|
#region 计算战力
|
//如果服务端战力计算有压力,可改成关键点结算(如同步排行榜跨服等),表现由客户端自己计算
|
//装备战力为最终总战力的结果比(提升整个角色总战力)
|
|
//计算总战力中的武将战力,几个武将加起来就是总战力,其他功能属性计算应该涵盖在英雄里
|
public long CalculatePower()
|
{
|
#if UNITY_EDITOR
|
Debug.Log("战力:开始计算");
|
#endif
|
// --- 先计算所有功能的汇总属性 ---
|
RefreshLVAttrs();
|
RefrehEquipAttrs();
|
RefreshTeamAttrs();
|
|
|
// --- 算单武将功能属性战力 后相加---
|
long fightPower = 0;
|
var team = TeamManager.Instance.GetTeam(teamTypeCalc);
|
if (team == null)
|
{
|
return fightPower;
|
}
|
TeamHero[] teamHeroes = isPreviewTeamPower ? team.tempHeroes : team.serverHeroes;
|
foreach (var hero in teamHeroes)
|
{
|
if (hero == null)
|
{
|
continue;
|
}
|
HeroInfo heroInfo = HeroManager.Instance.GetHero(hero.guid);
|
if (heroInfo == null)
|
{
|
continue;
|
}
|
|
fightPower += CalculateTeamHeroPower(heroInfo);
|
|
}
|
|
#if UNITY_EDITOR
|
Debug.Log("战力:计算完毕 " + fightPower);
|
#endif
|
return fightPower;
|
}
|
|
#if UNITY_EDITOR
|
string propertyStrForDebug = "";
|
#endif
|
|
//计算阵容中武将战力
|
public long CalculateTeamHeroPower(HeroInfo hero)
|
{
|
|
fightPowerVariables.Clear();
|
hero.RefreshFetterAttrsWhenCalcPower(teamTypeCalc); //羁绊属性要实时算
|
|
#if UNITY_EDITOR
|
propertyStrForDebug = "";
|
#endif
|
foreach (var config in PlayerPropertyConfig.GetValues())
|
{
|
if (config.showType < 1 || config.showType > 4)
|
{
|
continue;
|
}
|
if (config.showType == 1)
|
{
|
fightPowerVariables[config.Parameter] = (ulong)GetPropertyVaule(config.ID, hero, propertyFormula);
|
}
|
else
|
{
|
fightPowerVariables[config.Parameter] = (ulong)GetPropertyVaule(config.ID, hero, fightPropertyFormula);
|
}
|
}
|
|
#if UNITY_EDITOR
|
Debug.Log($"战力:武将ID {hero.heroId} 属性信息 {propertyStrForDebug}");
|
#endif
|
|
//属性系数根据官职等级的加成
|
var fightPowerRatioConfig = FightPowerRatioConfig.Get(PlayerDatas.Instance.baseData.realmLevel);
|
|
fightPowerVariables["AtkRatio"] = fightPowerRatioConfig.AtkRatio;
|
fightPowerVariables["MaxHPRatio"] = fightPowerRatioConfig.MaxHPRatio;
|
fightPowerVariables["DefRatio"] = fightPowerRatioConfig.DefRatio;
|
fightPowerVariables["StunRateRatio"] = fightPowerRatioConfig.StunRateRatio;
|
fightPowerVariables["SuperHitRateRatio"] = fightPowerRatioConfig.SuperHitRateRatio;
|
fightPowerVariables["ComboRateRatio"] = fightPowerRatioConfig.ComboRateRatio;
|
fightPowerVariables["MissRateRatio"] = fightPowerRatioConfig.MissRateRatio;
|
fightPowerVariables["ParryRateRatio"] = fightPowerRatioConfig.ParryRateRatio;
|
fightPowerVariables["SuckHPPerRatio"] = fightPowerRatioConfig.SuckHPPerRatio;
|
fightPowerVariables["StunRateDefRatio"] = fightPowerRatioConfig.StunRateDefRatio;
|
fightPowerVariables["SuperHitRateDefRatio"] = fightPowerRatioConfig.SuperHitRateDefRatio;
|
fightPowerVariables["ComboRateDefRatio"] = fightPowerRatioConfig.ComboRateDefRatio;
|
fightPowerVariables["MissRateDefRatio"] = fightPowerRatioConfig.MissRateDefRatio;
|
fightPowerVariables["ParryRateDefRatio"] = fightPowerRatioConfig.ParryRateDefRatio;
|
fightPowerVariables["SuckHPPerDefRatio"] = fightPowerRatioConfig.SuckHPPerDefRatio;
|
fightPowerVariables["NormalSkillPerRatio"] = fightPowerRatioConfig.NormalSkillPerRatio;
|
fightPowerVariables["NormalSkillPerDefRatio"] = fightPowerRatioConfig.NormalSkillPerDefRatio;
|
fightPowerVariables["AngerSkillPerRatio"] = fightPowerRatioConfig.AngerSkillPerRatio;
|
fightPowerVariables["AngerSkillPerDefRatio"] = fightPowerRatioConfig.AngerSkillPerDefRatio;
|
fightPowerVariables["SuperDamPerRatio"] = fightPowerRatioConfig.SuperDamPerRatio;
|
fightPowerVariables["SuperDamPerDefRatio"] = fightPowerRatioConfig.SuperDamPerDefRatio;
|
fightPowerVariables["ShieldPerRatio"] = fightPowerRatioConfig.ShieldPerRatio;
|
fightPowerVariables["ShieldPerDefRatio"] = fightPowerRatioConfig.ShieldPerDefRatio;
|
fightPowerVariables["DOTPerRatio"] = fightPowerRatioConfig.DOTPerRatio;
|
fightPowerVariables["DOTPerDefRatio"] = fightPowerRatioConfig.DOTPerDefRatio;
|
fightPowerVariables["WeiFinalDamPerRatio"] = fightPowerRatioConfig.WeiFinalDamPerRatio;
|
fightPowerVariables["WeiFinalDamPerDefRatio"] = fightPowerRatioConfig.WeiFinalDamPerDefRatio;
|
fightPowerVariables["ShuFinalDamPerRatio"] = fightPowerRatioConfig.ShuFinalDamPerRatio;
|
fightPowerVariables["ShuFinalDamPerDefRatio"] = fightPowerRatioConfig.ShuFinalDamPerDefRatio;
|
fightPowerVariables["WuFinalDamPerRatio"] = fightPowerRatioConfig.WuFinalDamPerRatio;
|
fightPowerVariables["WuFinalDamPerDefRatio"] = fightPowerRatioConfig.WuFinalDamPerDefRatio;
|
fightPowerVariables["QunFinalDamPerRatio"] = fightPowerRatioConfig.QunFinalDamPerRatio;
|
fightPowerVariables["QunFinalDamPerDefRatio"] = fightPowerRatioConfig.QunFinalDamPerDefRatio;
|
fightPowerVariables["FinalDamPerRatio"] = fightPowerRatioConfig.FinalDamPerRatio;
|
fightPowerVariables["FinalDamPerDefRatio"] = fightPowerRatioConfig.FinalDamPerDefRatio;
|
fightPowerVariables["PhyDamPerRatio"] = fightPowerRatioConfig.PhyDamPerRatio;
|
fightPowerVariables["PhyDamPerDefRatio"] = fightPowerRatioConfig.PhyDamPerDefRatio;
|
fightPowerVariables["MagDamPerRatio"] = fightPowerRatioConfig.MagDamPerRatio;
|
fightPowerVariables["MagDamPerDefRatio"] = fightPowerRatioConfig.MagDamPerDefRatio;
|
fightPowerVariables["CurePerRatio"] = fightPowerRatioConfig.CurePerRatio;
|
fightPowerVariables["CurePerDefRatio"] = fightPowerRatioConfig.CurePerDefRatio;
|
|
|
long fightPower = (long)JaceCalculator.Calculate(fightPowerFormula, fightPowerVariables);
|
#if UNITY_EDITOR
|
//排除值为0的属性输出
|
var tmpFightPowerVariables = fightPowerVariables.Where(x => x.Value > 0).ToDictionary(x => x.Key, x => x.Value);
|
if (!tmpFightPowerVariables.IsNullOrEmpty())
|
Debug.Log($"战力:武将ID {hero.heroId} 属性战力 {fightPower} 属性战力参数 {JsonMapper.ToJson(tmpFightPowerVariables)}");
|
#endif
|
|
//加上技能战力
|
fightPowerVariables.Clear();
|
fightPowerVariables["PlayerLV"] = PlayerDatas.Instance.baseData.LV;
|
fightPowerVariables["OfficialLV"] = PlayerDatas.Instance.baseData.realmLevel;
|
fightPowerVariables["SkillPower"] = hero.GetSkillsFightPower();
|
|
long skillPower = (long)JaceCalculator.Calculate(skillFightPowerFormula, fightPowerVariables);
|
|
#if UNITY_EDITOR
|
Debug.Log($"战力:武将ID {hero.heroId} 技能战力 {skillPower} 技能参数 {JsonMapper.ToJson(fightPowerVariables)}");
|
|
Debug.Log($"战力:武将ID {hero.heroId} 总战力 {fightPower + skillPower}");
|
#endif
|
|
return fightPower + skillPower;
|
}
|
|
|
/// <summary>
|
/// 和身上装备对比差
|
/// </summary>
|
/// <param name="item">地板装备</param>
|
/// <returns></returns>
|
public long GetFightPowerChange(ItemModel item)
|
{
|
InitFightPowerParam();
|
var fightPower = CalculatePower();
|
|
InitFightPowerParam(dropindex: item.gridIndex);
|
var tmpFightPower = CalculatePower();
|
return tmpFightPower - fightPower;
|
}
|
|
|
// 单英雄查看战力
|
// 1. 上阵英雄显示,在主线阵容下的战力
|
// 2. 非上阵或其他上阵阵容:上阵不足6个人的,按增加的方式的计算;人数满的情况下按替换6号位计算
|
public long GetHeroFightPower(HeroInfo heroInfo)
|
{
|
bool ispreview = false;
|
var team = TeamManager.Instance.GetTeam(TeamType.Story);
|
if (!team.HasHero(heroInfo.itemHero.guid))
|
{
|
//替换上阵位置
|
ispreview = true;
|
var index = team.GetEmptyPosition();
|
if (index < 0)
|
{
|
team.AddHero(heroInfo, 5);
|
}
|
else
|
{
|
team.AddHero(heroInfo, index);
|
}
|
}
|
|
InitFightPowerParam(ispreview: ispreview);
|
RefreshLVAttrs();
|
RefrehEquipAttrs();
|
RefreshTeamAttrs();
|
|
var fightPower = CalculateTeamHeroPower(heroInfo);
|
|
//计算完恢复队伍
|
if (ispreview)
|
team.RestoreTeam();
|
return fightPower;
|
}
|
|
|
//查看阵容战力
|
public long GetTeamFightPower(TeamType team, bool isPreview)
|
{
|
InitFightPowerParam(team, -1, isPreview);
|
return CalculatePower();
|
}
|
#endregion
|
|
|
public Dictionary<int, long> GetHeroTotalAttr(HeroInfo hero)
|
{
|
|
Dictionary<int, long> tmpAttrs = new Dictionary<int, long>();
|
hero.RefreshFetterAttrsWhenCalcPower(TeamType.Story); //羁绊属性要实时算
|
|
#if UNITY_EDITOR
|
propertyStrForDebug = "";
|
#endif
|
|
foreach (var config in PlayerPropertyConfig.GetValues())
|
{
|
if (config.showType < 1 || config.showType > 4)
|
{
|
continue;
|
}
|
if (config.showType == 1)
|
{
|
tmpAttrs[config.ID] = (long)GetPropertyVaule(config.ID, hero, propertyFormula);
|
}
|
else
|
{
|
tmpAttrs[config.ID] = (long)GetPropertyVaule(config.ID, hero, fightPropertyFormula);
|
}
|
}
|
#if UNITY_EDITOR
|
Debug.Log($"战力:武将ID {hero.heroId} 属性信息 {propertyStrForDebug}");
|
#endif
|
return tmpAttrs;
|
}
|
}
|