/* * @Author: 白哉 * @Description: * @Date: 2025年04月03日 星期四 11:04:31 * @Modify: */ using System; using System.Collections.Generic; using Logic; using Logic.CrashSight; using Logic.Skill; using MemoryPack; using TH1_Logic.Core; using TH1_Logic.HeroTask; using TH1_Renderer; using TH1Renderer; using UnityEngine; namespace RuntimeData { // 地图上所有的小兵数据 [MemoryPackable] public partial class UnitMapData { public List UnitList; [MemoryPackIgnore] //public bool UnitMapRenderMark; private Dictionary _unitDict; [MemoryPackConstructor] public UnitMapData() { UnitList = new List(); _unitDict = new Dictionary(); //UnitMapRenderMark = true; } public UnitMapData(UnitMapData copyData) { UnitList = new List(); _unitDict = new Dictionary(); foreach (var unitData in copyData.UnitList) { var newUnitData = new UnitData(unitData); UnitList.Add(newUnitData); _unitDict[newUnitData.Id] = newUnitData; } } // MemoryPack 反序列化之后的后处理 [MemoryPackOnDeserialized] public void OnAfterMemoryPackDeserialize() { _unitDict ??= new Dictionary(); _unitDict.Clear(); foreach (var unit in UnitList) _unitDict[unit.Id] = unit; } public void DeepCopy(UnitMapData copyData) { _unitDict.Clear(); for (int i = 0; i < copyData.UnitList.Count; i++) { var copyUnit = copyData.UnitList[i]; if (i >= UnitList.Count) { var unit = new UnitData(copyUnit); UnitList.Add(unit); _unitDict[unit.Id] = unit; } else { UnitList[i].DeepCopy(copyUnit); _unitDict[UnitList[i].Id] = UnitList[i]; } } for (int i = UnitList.Count - 1; i >= copyData.UnitList.Count; i--) { _unitDict.Remove(UnitList[i].Id); UnitList.RemoveAt(i); } } public void OnTurnStart(MapData map, PlayerData player) { var units = new HashSet(); map.GetUnitDataListByPlayerId(player.Id, units); foreach (var unit in units) { Main.UnitLogic.StartNextTurn(map, unit); unit.OnTurnStart(map); } } public void OnAfterTurnStart(MapData map, PlayerData player) { var units = new HashSet(); map.GetUnitDataListByPlayerId(player.Id, units); foreach (var unit in units) { unit.OnAfterTurnStart(map); } } public void OnTurnEnd(MapData map, PlayerData player) { var units = new HashSet(); map.GetUnitDataListByPlayerId(player.Id, units); foreach (var unit in units) { Main.UnitLogic.UnitEndTurn(map, unit); unit.OnTurnEnd(map); } } // 新建小兵 public UnitData AddUnitData(UnitFullType unitFullType, MapIdGenerator idGenerator) { var unit = new UnitData(unitFullType ,idGenerator); UnitList.Add(unit); _unitDict[unit.Id] = unit; return unit; } // 删除小兵 public void RemoveUnitData(uint unitId) { if (_unitDict.TryGetValue(unitId, out var unitData)) { UnitList.Remove(unitData); _unitDict.Remove(unitId); } } // 通过 uid 找小兵数据 unitData public bool GetUnitDataByUnitId(uint unitId, out UnitData unitData) { return _unitDict.TryGetValue(unitId, out unitData); } } [Serializable] public struct UnitFullType : IEquatable { public UnitType UnitType; public GiantType GiantType; public uint UnitLevel; public UnitFullType(UnitType unitType, GiantType giantType, uint level) { UnitType = unitType; GiantType = giantType; UnitLevel = level; } public bool Equals(UnitFullType other) { return UnitType == other.UnitType && GiantType == other.GiantType && UnitLevel == other.UnitLevel; } public override bool Equals(object obj) { return obj is UnitFullType other && Equals(other); } public override int GetHashCode() { return HashCode.Combine((int)UnitType, (int)GiantType, UnitLevel); } public static bool operator ==(UnitFullType left, UnitFullType right) { return left.Equals(right); } public static bool operator !=(UnitFullType left, UnitFullType right) { return !(left == right); } } //小兵数据 [MemoryPackable] public partial class UnitData : IdentifierBase { // 判断是否已经setDie并从mapDataRelation中除名,如果是判断unit是否存活,应该用IsAlive函数 [MemoryPackInclude] private bool _notSetDie; //单位类型 public UnitFullType UnitFullType; // 单位类型(legacy) public UnitType UnitType => UnitFullType.UnitType; public GiantType GiantType => UnitFullType.GiantType; public uint UnitLevel => UnitFullType.UnitLevel; //棋子种类 public ChessType ChessType; // 血量 public int Health; // move points,行动值 public int MP; // attack points,攻击值 public int AP; // capture city points, 城市行动值,用来占领或者建设城市 public int CP; // 攻击范围 //英雄经验值 public int GiantExp; public UnitFullType OriginUnitFullType; //是否老兵 //public bool Veteran; //存储carry的UnitType public UnitFullType CarryUnitFullType; public UnitType CarryUnitType => CarryUnitFullType.UnitType; public GiantType CarryGiantType => CarryUnitFullType.GiantType; public uint CarryUnitLevel => CarryUnitFullType.UnitLevel; //存储carry的exp状态 //public int CarryExp; //存储carry的Veteran状态 //public bool CarryVeteran; // 防御削减系数 public float DefenseReduction; // 军团编号 [MemoryPackIgnore] public uint LegionId; public UnitFullType FullTypeCache; public List SkillCache; public void SetAlive() { _notSetDie = true; } public void SetDie() { _notSetDie = false; } public bool IsAlive() { return _notSetDie && Health > 0; } public PlayerData Player(MapData map) { map.GetPlayerDataByUnitId(this.Id, out var player); return player; } public bool Player(MapData map,out PlayerData player) { return map.GetPlayerDataByUnitId(this.Id, out player); } public CityData City(MapData map) { map.GetCityDataByUnitId(this.Id, out var city); return city; } public GridData Grid(MapData map) { map.GetGridDataByUnitId(Id, out var grid); return grid; } public bool Grid(MapData map,out GridData grid) { return map.GetGridDataByUnitId(Id, out grid); } public UnitRenderer Renderer(MapData map) { if (!map.IsCurrentShowMap()) return null; return MapRenderer.Instance.ROUnitMap.GetValueOrDefault(this.Id); } public HeroTaskContentBase HeroTask(MapData map) { HeroTaskContentBase heroTask = null; Player(map)?.PlayerHeroData.HeroTaskDict.TryGetValue(UnitFullType,out heroTask); return heroTask; } //获取最大血量 public int GetMaxHealth() { if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitFullType, out var unitTypeInfo)) return 0; if (unitTypeInfo.NoMaxHealth) { if (CarryUnitFullType.UnitType != UnitType.None) { if(Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(CarryUnitFullType,out var carryUnitTypeInfo)) return carryUnitTypeInfo.MaxHealth + GetOfficerHealth(); return 0; } return 0; } else return unitTypeInfo.MaxHealth + GetOfficerHealth(); } public bool IsMainMap() { if (!Main.MapData.UnitMap.GetUnitDataByUnitId(Id, out var unitData) || unitData != this) return false; return true; } public bool InMainSight() { if (!IsMainMap()) return false; var grid = Grid(Main.MapData); if (grid == null) return false; return grid.InMainSight(); } //获取画面的位置 public Vector3 GetPosition(MapData map) { if (map != Main.MapData) return Vector3.zero; var t = MapRenderer.Instance.ROUnitMap[Id]; if(t == null)return Vector3.zero; return t.GetPosition(); } // 获取血量百分比 public float GetHealthRatio() { return (float)Health / GetMaxHealth(); } // 获取ProjectileType public ProjectileType GetProjectileType(MapData map,GridData targetGrid)//, MoveAttackType moveAttackType) { if (!Grid(map, out var originGrid)) return ProjectileType.None; int distance = map.GridMap.CalcDistance(originGrid, targetGrid); //TODO 将来复杂了就走skill生命周期,现在就全先写在这儿了 //如果拥有kanakositting,全部变为远程 if (GetSkill(SkillType.KANAKOSITTING, out var _)) { return ProjectileType.KanakoAttack; } if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitFullType, out var info)) return ProjectileType.None; if (distance == 1 && info.ForceMelee) return ProjectileType.Melee; return info.ProjectileType; } // 获取军事分 public float GetMilitary() { if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitFullType, out var info)) return 0; //如果是英雄,要单独结算,按照英雄的不同等级定价结算 if (UnitFullType.UnitType == UnitType.Giant) return UnitFullType.UnitLevel switch { 0 => 10, 1 => 10, 2 => 15, 3 => 25, _ => 0 }; //如果生命值低于50%,得分打8折 if (GetHealthRatio() <= 0.5f) return info.Cost * 0.8f; return info.Cost; } // 获取造价 public float GetCost() { if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitFullType, out var info)) return 0; return info.Cost; } [MemoryPackConstructor] public UnitData() { } //注意,这里没有处理unit Copy之后,skill要触发skillAdd生命周期的情况 public UnitData(UnitData copyData) { Id = copyData.Id; _notSetDie = copyData._notSetDie; UnitFullType = copyData.UnitFullType; Health = copyData.Health; MP = copyData.MP; AP = copyData.AP; CP = copyData.CP; GiantExp = copyData.GiantExp; CarryUnitFullType = copyData.CarryUnitFullType; OriginUnitFullType = copyData.OriginUnitFullType; LegionId = copyData.LegionId; DefenseReduction = copyData.DefenseReduction; foreach (var skill in copyData.Skills) Skills.Add(skill.GetCopySkill()); SkillCache = new List(); foreach (var skill in copyData.SkillCache) SkillCache.Add(skill.GetCopySkill()); } //注意,这里没有处理unit Copy之后,skill要触发skillAdd生命周期的情况 public void DeepCopy(UnitData copyData) { Id = copyData.Id; _notSetDie = copyData._notSetDie; UnitFullType = copyData.UnitFullType; ChessType = copyData.ChessType; Health = copyData.Health; MP = copyData.MP; AP = copyData.AP; CP = copyData.CP; GiantExp = copyData.GiantExp; CarryUnitFullType = copyData.CarryUnitFullType; OriginUnitFullType = copyData.OriginUnitFullType; LegionId = copyData.LegionId; DefenseReduction = copyData.DefenseReduction; Skills.Clear(); foreach (var skill in copyData.Skills) Skills.Add(skill.GetCopySkill()); SkillCache ??= new List(); SkillCache.Clear(); foreach (var skill in copyData.SkillCache) SkillCache.Add(skill.GetCopySkill()); } // 无参数初始化 public UnitData(UnitFullType unitFullType, MapIdGenerator idGenerator) { Id = idGenerator.GeneratorId(); UnitFullType = unitFullType; SkillCache = new List(); InitData(); } public void InitData() { if (Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitFullType, out var unitTypeInfo) && unitTypeInfo.NoMaxHealth) { //TODO 目前 nomaxhealth和carry不是一个概念 CarryUnitFullType.UnitType = UnitType.Warrior; } _notSetDie = true; Health = GetMaxHealth(); ChessType = unitTypeInfo.ChessType; MP = 0; AP = 0; CP = 0; //AttackRange = Table.Instance.QueryUnitAttackRange(UnitType); //MoveRange = Table.Instance.QueryUnitMoveRange(UnitType); //Exp = 0; GiantExp = 0; //Veteran = false; LegionId = 0; } //----------------------------------------- 判断属性 ---------------------------------------------- public bool IsBigGuy(bool useToCheckDie = false) { if(UnitType == UnitType.BigGuy) return true; if(UnitType == UnitType.KaguyaFrenchWolf) return true; if(UnitType == UnitType.WolfJuggernaut) return true; if(UnitType == UnitType.Juggernaut) return true; if(UnitType == UnitType.RemiliaEgyptianKoakuma && !useToCheckDie) return true; if(UnitType == UnitType.RemiliaEgyptianKoakumaLion) return true; if(UnitType == UnitType.MoriyaHebi && UnitLevel >= 3) return true; return false; } public bool IsHero(bool useToCheckDie = false) { if(GiantType == GiantType.None && CarryGiantType == GiantType.None) return false; if(UnitType == UnitType.KaguyaFrenchMokouEgg) return true; if(GiantType == GiantType.FrenchMokou && useToCheckDie) return false; return true; } // 全局通知调用 public void OnTurnStart(MapData map) { OnSkillsTurnStart(map); } public void OnAfterTurnStart(MapData map) { OnSkillsAfterTurnStart(map); } public void OnTurnEnd(MapData map) { OnSkillsTurnEnd(map); AP = 0; CP = 0; MP = 0; } protected override void OnSkillsTurnStart(MapData map) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.BeforeTurnStart(); if (skill.IsFinished()) { skill.OnFinished(this, map); Skills.Remove(skill); continue; } skill.OnTurnStart(this, map); } } protected override void OnSkillsAfterTurnStart(MapData map) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.OnAfterTurnStart(this, map); } } protected override void OnSkillsTurnEnd(MapData map) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.OnTurnEnd(this, map); } } //返回该unit的视野半径(考虑unit站在map的实机位置下的视野半径) public int GetSightRange(MapData map) { int v = 1; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; v += skill.GetExtraSight(this,map); } if (map.GetGridDataByUnitId(this.Id, out var grid) && grid.Feature == TerrainFeature.Mountain) v = Mathf.Max(v, 2); return v; } //返回该unit如果站在具体的pos下的视野半径 public int GetSightRange(MapData map,GridData grid) { int v = 1; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; v += skill.GetExtraSight(this,map); } if (grid.Feature == TerrainFeature.Mountain) v = Mathf.Max(v, 2); return v; } public int GetAttackRange(MapData mapData) { var attackRange = 0; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; attackRange += skill.GetExtraAttackRange(mapData,this); } attackRange += Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitFullType, out var info) ? info.AttackRange : 0; return attackRange; } //最终移动能力。 目前仅用于Kanako Sitting的情况(拥有移动力,但是无法移动) public int FinalMoveRange(MapData mapData) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (!skill.GetFinalMoveRange(this, out var finalMoveRange)) continue; return finalMoveRange; } return GetMoveRange(mapData); } public int GetMoveRange(MapData mapData) { if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitFullType, out var info)) return 0; var moveRange = info.MoveRange; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; moveRange += skill.GetExtraMoveRange(mapData,this); } return moveRange; } //返回该unit是否是静止经验(无法升级) public bool CheckIsStaticExp(MapData map) { var isStaticExp = false; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsLimitSelfExp(this, map)) isStaticExp = true; } return isStaticExp; } //返回该unit处于城市的时候是否获得防御加成 public bool CheckIsCityDefenseBuff() { return GetSkill(SkillType.FORTIFY,out var _); } //LandAndPort, WaterAndAshore, LandAndWater, WaterOnly, LandOnly, Fly public LandType GetLandType() { return Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitFullType,out var Info)?Info.LandType:LandType.None; } //----------------------------------------- 数值计算相关函数 --------------------------------------------- // 获取技能加成倍数 (本人拥有的其他技能对特定技能的加成倍数) public float GetSpecialSkillBonus(MapData mapData, SkillType skillType) { var value = 1f; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; value *= skill.GetSpecialSkillBonus(mapData, this, skillType); } return value; } // 获得总攻击力的string显示 public string GetAttackShowString(MapData map) { var raw = GetRawAttackValue(map, null); var add = GetAttackAdditionParam(map, null); var mul = GetAttackMultiplicationParam(map); string ret = raw.ToString(); if (add != 0) ret += (add > 0 ?" + ":" - ") + Mathf.Abs(add); if (mul != 1f) ret += " (× " + mul.ToString() + ")"; return ret; } public float GetRawAttackValue(MapData map, UnitData target = null) { if(!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitFullType, out var info)) return 0; return info.Attack; } // 基础攻击力 public float GetBaseAttackValue(MapData map, UnitData target = null) { if(!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitFullType, out var info)) return 0; return info.Attack + GetAttackAdditionParam(map, target); } // 总攻击力 public float GetAllAttackValue(MapData map, UnitData target = null) { return GetBaseAttackValue(map, target) * GetAttackMultiplicationParam(map, target); } // 攻击力加算系数 public float GetAttackAdditionParam(MapData map, UnitData target = null) { var value = 0f; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; value += skill.GetAttackAdditionParam(map, this, target); } return value; } // 攻击力乘算系数 public float GetAttackMultiplicationParam(MapData map, UnitData target = null) { var value = 1f; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; value *= skill.GetAttackMultiplicationParam(map, this, target); } return value; } // 获得总防御力的string显示 public string GetDefenseShowString(MapData map) { var raw = GetRawDefenseValue(map, null); var add = GetDefenseAdditionParam(map, null); var mul = GetDefenseMultiplicationParam(map); string ret = raw.ToString(); if (add != 0) ret += (add > 0 ?" + ":" - ") + Mathf.Abs(add); if (mul != 1f) ret += " (× " + mul.ToString() + ")"; return ret; } // 获得总射程的string显示 public string GetMoveRangeShowString(MapData mapData) { var raw = Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitFullType, out var info) ? info.MoveRange : 0; var add = 0; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; add += skill.GetExtraMoveRange(mapData,this); } //var mul = GetDefenseMultiplicationParam(map); string ret = raw.ToString(); if (add != 0) { //特判椛椛的铁十字追击 if(GetSkill(SkillType.MOMIJIHUNTER,out var _)) ret += (add > 0 ?" + ":" - ") + Mathf.Abs(add) + "?"; else ret += (add > 0 ?" + ":" - ") + Mathf.Abs(add); } //if (mul != 1f) ret += " (× " + mul.ToString() + ")"; return ret; } // 获得总射程的string显示 public string GetAttackRangeShowString(MapData mapData) { var raw = Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitFullType, out var info) ? info.AttackRange : 0; var add = 0; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; add += skill.GetExtraAttackRange(mapData,this); } //var mul = GetDefenseMultiplicationParam(map); string ret = raw.ToString(); if (add != 0) ret += (add > 0 ?" + ":" - ") + Mathf.Abs(add); //if (mul != 1f) ret += " (× " + mul.ToString() + ")"; return ret; } public float GetRawDefenseValue(MapData map, UnitData target = null) { if(!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitFullType, out var info)) return 0; return info.Defense; } // 基础防御力 public float GetBaseDefenseValue(MapData map, UnitData target = null) { if(!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitFullType, out var info)) return 0; return info.Defense + GetDefenseAdditionParam(map, target); } // 总防御力 public float GetAllDefenseValue(MapData map, UnitData target = null) { return GetBaseDefenseValue(map, target) * GetDefenseMultiplicationParam(map, target); } // 防御力加算系数 public float GetDefenseAdditionParam(MapData map, UnitData target = null) { var value = 0f; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; value += skill.GetDefenseAdditionParam(map, this, target); } return value; } //只用于显示防御外壳判断用的系数计算(会去除<1的乘算因子) public float GetDefenseMultiplicationParamOnlyForDefenseShow(MapData map, UnitData target = null) { var buffValue = 1f; // 增益效果(>1)取最大值 var debuffMult = 1f; // 减益效果(<1)累乘 var isZero = 1f; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; var t = skill.GetDefenseMultiplicationParam(map, this, target); isZero *= t; // 分离增益和减益 if (t > 1f) buffValue = Mathf.Max(t, buffValue); // 增益取最大 else if (t < 1f) debuffMult *= t; // 减益累乘 } var p = GetTerrainDefenseMultiplicationParam(map); if (p > 1f) buffValue = Mathf.Max(p, buffValue); else if (p < 1f) debuffMult *= p; isZero *= p; if (isZero == 0f) return 0f; // 最终防御系数 = 最大增益 * 减益累乘 return buffValue; } // 防御力乘算系数 public float GetDefenseMultiplicationParam(MapData map, UnitData target = null) { var buffValue = 1f; // 增益效果(>1)取最大值 var debuffMult = 1f; // 减益效果(<1)累乘 var isZero = 1f; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; var t = skill.GetDefenseMultiplicationParam(map, this, target); isZero *= t; // 分离增益和减益 if (t > 1f) buffValue = Mathf.Max(t, buffValue); // 增益取最大 else if (t < 1f) debuffMult *= t; // 减益累乘 } var p = GetTerrainDefenseMultiplicationParam(map); if (p > 1f) buffValue = Mathf.Max(p, buffValue); else if (p < 1f) debuffMult *= p; isZero *= p; if (isZero == 0f) return 0f; // 最终防御系数 = 最大增益 * 减益累乘 return buffValue * debuffMult; } // 地形防御乘算系数 public float GetTerrainDefenseMultiplicationParam(MapData map) { var extraDefense = 1f; if (!map.GetGridDataByUnitId(Id, out var grid) || !map.GetPlayerDataByUnitId(Id, out var unitPlayer)) { LogSystem.LogError("UnitData GetExtraDefense Cant find grid or player by uid"); return extraDefense; } //如果是中立土地 if (!map.GetPlayerDataByTerritoryGridId(grid.Id, out var gridPlayer)) return extraDefense; //如果不是盟友土地 if(!map.SameUnion(unitPlayer.Id,gridPlayer.Id)) return extraDefense; if (grid.Resource == ResourceType.NavalBase || grid.Resource == ResourceType.Military || grid.Resource == ResourceType.RemiliaMilitary) extraDefense *= 1.5f; return extraDefense; } // 获取暴击率 public float GetCriticalHitRate(MapData map) { var criticalHitRate = 0f; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; criticalHitRate += skill.GetCriticalHitRate(this, map); } return criticalHitRate; } #region [------------------------------ Skill 相关 -----------------------------------] //清楚隐身状态 /*public void RemoveHideState(MapData map) { foreach(skill) //RemoveSkill(SkillType.HideState, map); }*/ //获取officer的额外血量 public int GetOfficerHealth() { int ret = 0; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; ret += skill.GetOfficerHealth(); } return ret; } //判断当前是不是officer public bool IsOfficer() { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsOfficer()) return true; } return false; } public bool IsPrepareOfficer() { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsPrepareOfficer()) return true; } return false; } public bool IsCanBeOfficer() { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsCanBeOfficer()) return true; } return false; } // 是否能移动到伟人身周 public bool IsCanMoveGiantNearbyGrid(MapData map) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsCanMoveGiantNearbyGrid(this, map)) return true; } return false; } // 是否movekill public bool IsCanMoveKill(MapData mapData) { if (GetAttackRange(mapData) == 1) return true; return false; } // 是否拥有特别伤害技能,例如ROYALFLAME public bool IsHasAttackSkill(MapData map) { return false; } // 是否能移动无人城市 public bool IsCanMoveNoUnitSelfCity(MapData map) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsCanMoveToNoUnitSelfCity(this, map)) return true; } return false; } // 是否可以死亡 public bool CanBeKilled(MapData map) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (!skill.IsCanBeKill(this, map)) return false; } return true; } // 是否可以被伤害结算 public bool IsLimitDamaged(MapData map, int dmg) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsLimitDamaged(this, map, dmg)) return true; } return false; } // 是否经验锁定 public bool IsExpLock(MapData map) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsLimitSelfExp(this, map)) return true; } return false; } //返回该unit是否能在terrain上移动 public bool IsCanMoveOnTerrain(MapData map, TerrainType terrainType) { var landType = GetLandType(); if (terrainType == TerrainType.Land && (landType == LandType.LandAndPort || landType == LandType.LandOnly || landType == LandType.LandAndWater || landType == LandType.Fly)) return true; if (terrainType == TerrainType.ShallowSea && (landType == LandType.WaterAndAshore || landType == LandType.WaterOnly || landType == LandType.LandAndWater || landType == LandType.Fly)) return true; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsCanMoveOnTerrain(this, map, terrainType)) return true; } return false; } //返回该unit是否能在feature上移动 public bool IsCanMoveOnFeature(MapData map, TerrainFeature featureType) { if (featureType != TerrainFeature.Mountain) return true; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsCanMoveOnFeature(this, map,featureType)) return true; } return false; } //返回该unit是否能攻击所有人 public bool CanAttackAll(MapData map) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.CanAttackAll(this, map)) return true; } return false; } //返回该unit是否隐身 public bool IsHideState(MapData map) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsHideState()) return true; } return false; } //返回该unit是否不可见(不考虑视野),与上方IsHideState的区别在于, 我方/盟友的隐身单位是可见的,敌方的隐身单位才不可见 public bool IsHideAndCantSee(MapData map,PlayerData player) { if (!IsHideState(map)) return false; if (player == null) return false; if (Player(map, out var unitPlayer) && map.SameUnion(unitPlayer.Id, player.Id)) return false; return true; } //返回该unit是否能攻击 public bool IsLimitSelfAttack(MapData map) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsLimitSelfAttack(this, map)) return true; } return false; } //返回该unit是否能移动 public bool IsLimitSelfMove(MapData map) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsLimitSelfMove(this, map)) return true; } return false; } //返回该unit是否能攻击ground public bool IsCanAttackTargetGrid(MapData map, GridData target) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsCanAttackTargetGrid(map,this,target)) return true; } return false; } //返回该unit是否能攻击Ally public bool IsCanAttackAlly() { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsCanAttackAlly()) return true; } return false; } //返回该unit是否能攻击ground public bool IsCanAttackTargetAlly(MapData map, UnitData target) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (!skill.IsCanAttackTargetAlly(map,this,target)) return false; } return true; } //返回该unit是否能反击 public bool IsLimitSelfCounterAttack(MapData map) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsLimitSelfCounterAttack(this, map)) return true; } return false; } //返回目标 unit 是否能反击 public bool IsLimitTargetCounterAttack(MapData map) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsLimitTargetCounterAttack(this, map)) return true; } return false; } public bool IsCanTransport() { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsCanTransport()) return true; } return false; } // 移动是否会失败(并不限制移动) public bool IsActiveMoveFailed(MapData map, GridData target, MoveType moveType, List path = null) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.ActiveMoveFailed(this, target, map, moveType, path)) return true; } return false; } // 移动后的变化 public void BeforeMove(MapData map, GridData target, MoveType moveType, List path = null) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.BeforeMove(this, target, map, moveType, path); } } // 移动后 public void OnMove(MapData map, GridData target, MoveType moveType, List path = null) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.OnMove(this, target, map,moveType, path); } //赋予格子特殊效果,scarletEmpire的单位走到格子上时会得到被赋予一个技能realTimeVampire if(target.HasSpType(GridSpType.RemiliaGrid) && target.RealUnit(map,out var unit) && unit.Player(map,out var player) && player.PlayerCivId == 0) AddSkill_Legacy(SkillType.ScarletMistRealTimeVampire, map,true,-1,false,-1,false,SpecialAddSkillType.Force,0); else if(GetSkill(SkillType.ScarletMistRealTimeVampire,out var _)) RemoveSkill(SkillType.ScarletMistRealTimeVampire,map); } // 成为移动目标时 public void OnBeInteractTarget(MapData map, UnitData origin, GridData target) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.OnBeInteractTarget(origin, this, target, map); } } // 伤害结算前 public void BeforeDamagedSupportStage(MapData map, SettlementInfo info) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.BeforeDamagedSupportStage(map, info); } } // 伤害结算前 public void BeforeDamagedTransformStage(MapData map, SettlementInfo info) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.BeforeDamagedTransformStage(map, info); } } // 对他人攻击前 public void BeforeActiveAttackOther(MapData mapData, UnitData origin, UnitData target,out int addDmg) { addDmg = 0; var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.BeforeActiveAttackOther(mapData, origin, target, out var tmpAddDmg); addDmg += tmpAddDmg; } } // 对他人攻击后 public void AfterActiveAttackOther(MapData mapData, UnitData origin, UnitData target) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.AfterActiveAttackOther(mapData, origin, target); } } // 受他人攻击后 public void AfterActiveAttacked(MapData mapData, UnitData origin, UnitData target) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.AfterActiveAttacked(mapData, origin, target); } } // 对他人伤害结算前 public void BeforeDamageOther(MapData map, SettlementInfo info) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.BeforeDamageOther(map, info); } } // 伤害结算时 public void OnDamaged(MapData mapData, SettlementInfo info) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.OnDamaged(mapData, info); } } // 对他人伤害结算时 public void OnDamageOther(MapData mapData, SettlementInfo info) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.OnDamageOther(mapData, info); } } // 对他人伤害结算后 public void AfterDamageOther(MapData mapData, SettlementInfo info) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.AfterDamageOther(mapData, info); } } // 对他人治疗结算时 public void OnHealOther(MapData mapData, UnitData target,HealType healType) { var isFrozen = IsFrozen(); var copy = new List(Skills); foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.OnHealOther(mapData,this,target, healType); } //HeroTask(mapData)?.OnDamageOther(mapData, info); //for (int i = Skills.Count - 1; i >= 0; i--) Skills[i].OnHealOther(mapData, info); //HeroTask(mapData)?.OnDamageOther(mapData, info); } //获取抵达某格所需要的movecostinfo下限,目前仅用于momijiHUnter,也就是说moveinfo>该值才 public float GetGridMoveFloor(MapData mapData, UnitData originUnit,GridData targetGrid) { var isFrozen = IsFrozen(); var copy = new List(Skills); float ret = 0f; foreach (var skill in copy) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; ret = Mathf.Max(ret,skill.GetGridMoveFloor(mapData,originUnit,targetGrid)); } return ret; } //获取自身占据的population数额 public int GetPopulation() { if (GetSkill(SkillType.NOPOPULATION, out var _)) return 0; return 1; } public int GetKillCount() { int ret = 0; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; ret += skill.GetKillCount(); } return ret; } //判断是否被某人视作英雄 public bool TreatedAsHero(MapData map,UnitData unit) { /*if (UnitFullType.UnitType == UnitType.RemiliaEgyptianKoakuma || UnitFullType.UnitType == UnitType.RemiliaEgyptianKoakumaLion) { if (unit.Player(map) != Player(map)) return false; return true; }*/ if (UnitFullType.UnitType == UnitType.Giant) return true; if (CarryUnitFullType.UnitType == UnitType.Giant) return true; var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsTreatAsHero(map, this,unit)) return true; } return false; } // 判断是否只能在我方领土内移动 public bool IsLimitMoveToSelfTerrain(MapData map) { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsLimitMoveToSelfTerrain(this, map)) return true; } return false; } // 是否无视ZOC public bool IsIgnoreZOC() { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; if (skill.IsIgnoreZOC()) return true; } return false; } #endregion //------------------------------------------------- 对unitData的基础操作 ---------------------------------------------- //清空 AP Cp MP public void ClearAPMPCP() { AP = 0; MP = 0; CP = 0; } public void SetFullAPCPMP() { AP = 1; MP = 1; CP = 1; } public void SetFullAPCPMP_AllSkillRefresh() { SetFullAPCPMP(); var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.OnRefresh(); } } public int AddHealth(int hp) { var offset = Math.Min(GetMaxHealth() - Health, hp); Health += offset; return offset; } public void SetOfficer() { var isFrozen = IsFrozen(); foreach (var skill in Skills) { if (isFrozen && skill.SkillPriority == SkillPriority.Normal) continue; skill.SetOfficer(); } } public bool IsFrozen() { foreach (var skill in Skills) { if (skill.IsAllSkillBan()) return true; } return false; } } }