2026-02-27 14:22:21 +08:00

1171 lines
39 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @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<UnitData> UnitList;
[MemoryPackIgnore]
//public bool UnitMapRenderMark;
private Dictionary<uint, UnitData> _unitDict;
[MemoryPackConstructor]
public UnitMapData()
{
UnitList = new List<UnitData>();
_unitDict = new Dictionary<uint, UnitData>();
//UnitMapRenderMark = true;
}
public UnitMapData(UnitMapData copyData)
{
UnitList = new List<UnitData>();
_unitDict = new Dictionary<uint, UnitData>();
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<uint, UnitData>();
_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<UnitData>();
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<UnitData>();
map.GetUnitDataListByPlayerId(player.Id, units);
foreach (var unit in units)
{
unit.OnAfterTurnStart(map);
}
}
public void OnTurnEnd(MapData map, PlayerData player)
{
var units = new HashSet<UnitData>();
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<UnitFullType>
{
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 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());
}
//注意这里没有处理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());
}
// 无参数初始化
public UnitData(UnitFullType unitFullType, MapIdGenerator idGenerator)
{
Id = idGenerator.GeneratorId();
UnitFullType = unitFullType;
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;
}
//返回该unit的视野半径(考虑unit站在map的实机位置下的视野半径)
public int GetSightRange(MapData map)
{
int v = 1;
foreach (var skill in Skills)
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;
foreach (var skill in Skills)
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;
foreach (var skill in Skills)
{
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)
{
foreach (var skill in Skills)
{
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;
foreach (var skill in Skills)
{
moveRange += skill.GetExtraMoveRange(mapData,this);
}
return moveRange;
}
//返回该unit是否是静止经验(无法升级)
public bool CheckIsStaticExp(MapData map)
{
var isStaticExp = false;
foreach (var skill in Skills)
{
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;
foreach (var skill in Skills) 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;
foreach (var skill in Skills) value += skill.GetAttackAdditionParam(map, this, target);
return value;
}
// 攻击力乘算系数
public float GetAttackMultiplicationParam(MapData map, UnitData target = null)
{
var value = 1f;
foreach (var skill in Skills) 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;
foreach (var skill in Skills)
{
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;
foreach (var skill in Skills)
{
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;
foreach (var skill in Skills) value += skill.GetDefenseAdditionParam(map, this, target);
return value;
}
// 防御力乘算系数
public float GetDefenseMultiplicationParam(MapData map, UnitData target = null)
{
var value = 1f;
var isZero = 1f;
foreach (var skill in Skills)
{
var t = skill.GetDefenseMultiplicationParam(map, this, target);
value = Mathf.Max(t,value);
isZero *= t;
}
var p = GetTerrainDefenseMultiplicationParam(map);
value = Mathf.Max(p,value);
isZero *= p;
if (isZero == 0f) return 0f;
return value;
}
// 地形防御乘算系数
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;
foreach (var skill in Skills) criticalHitRate += skill.GetCriticalHitRate(this, map);
return criticalHitRate;
}
#region [------------------------------ Skill -----------------------------------]
//获取officer的额外血量
public int GetOfficerHealth()
{
int ret = 0;
foreach (var skill in Skills)
ret += skill.GetOfficerHealth();
return ret;
}
//判断当前是不是officer
public bool IsOfficer()
{
foreach (var skill in Skills)
if (skill.IsOfficer()) return true;
return false;
}
public bool IsPrepareOfficer()
{
foreach (var skill in Skills)
if (skill.IsPrepareOfficer()) return true;
return false;
}
public bool IsCanBeOfficer()
{
foreach (var skill in Skills)
if (skill.IsCanBeOfficer()) return true;
return false;
}
// 是否能移动到伟人身周
public bool IsCanMoveGiantNearbyGrid(MapData map)
{
foreach (var skill in Skills)
{
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)
{
foreach (var skill in Skills)
{
if (skill.IsCanMoveToNoUnitSelfCity(this, map)) return true;
}
return false;
}
// 是否可以死亡
public bool CanBeKilled(MapData map)
{
foreach (var skill in Skills)
{
if (!skill.IsCanBeKill(this, map)) return false;
}
return true;
}
// 是否可以被伤害结算
public bool CanBeDamaged(MapData map, int dmg)
{
foreach (var skill in Skills)
{
if (skill.IsCanBeDamaged(this, map, dmg)) return true;
}
return false;
}
// 是否经验锁定
public bool IsExpLock(MapData map)
{
foreach (var skill in Skills)
{
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;
foreach (var skill in Skills)
{
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;
foreach (var skill in Skills)
{
if (skill.IsCanMoveOnFeature(this, map,featureType)) return true;
}
return false;
}
//返回该unit是否能攻击所有人
public bool CanAttackAll(MapData map)
{
foreach (var skill in Skills)
{
if (skill.CanAttackAll(this, map)) return true;
}
return false;
}
//返回该unit是否能攻击
public bool IsLimitSelfAttack(MapData map)
{
foreach (var skill in Skills)
{
if (skill.IsLimitSelfAttack(this, map)) return true;
}
return false;
}
//返回该unit是否能攻击ground
public bool IsCanAttackTargetGrid(MapData map, GridData target)
{
foreach (var skill in Skills)
{
if (skill.IsCanAttackTargetGrid(map,this,target)) return true;
}
return false;
}
//返回该unit是否能攻击Ally
public bool IsCanAttackAlly()
{
foreach (var skill in Skills)
{
if (skill.IsCanAttackAlly()) return true;
}
return false;
}
//返回该unit是否能攻击ground
public bool IsCanAttackTargetAlly(MapData map, UnitData target)
{
foreach (var skill in Skills)
{
if (!skill.IsCanAttackTargetAlly(map,this,target)) return false;
}
return true;
}
//返回该unit是否能反击
public bool IsLimitSelfCounterAttack(MapData map)
{
foreach (var skill in Skills)
{
if (skill.IsLimitSelfCounterAttack(this, map)) return true;
}
return false;
}
//返回目标 unit 是否能反击
public bool IsLimitTargetCounterAttack(MapData map)
{
foreach (var skill in Skills)
{
if (skill.IsLimitTargetCounterAttack(this, map)) return true;
}
return false;
}
public bool IsCanTransport()
{
foreach (var skill in Skills)
{
if (skill.IsCanTransport()) return true;
}
return false;
}
// 移动后的变化
public void OnMove(MapData map, GridData target, MoveType moveType, List<Vector2Int> path = null)
{
var copy = new List<SkillBase>(Skills);
foreach (var skill in copy) skill.OnMove(this, target, map,moveType, path);
//赋予格子特殊效果
if(target.HasSpType(GridSpType.RemiliaGrid) && target.Unit(map,out var unit) && unit.Player(map,out var player) && player.PlayerCivId == 0)
AddSkill(SkillType.ScarletMistRealTimeVampire, map,true,-1,false,-1,false,AddSkillType.Force,0);
else
if(GetSkill(SkillType.ScarletMistRealTimeVampire,out var _))
RemoveSkill(SkillType.ScarletMistRealTimeVampire,map);
}
// 伤害结算前
public void BeforeDamagedSupportStage(MapData map, SettlementInfo info)
{
var copy = new List<SkillBase>(Skills);
foreach (var skill in copy) skill.BeforeDamagedSupportStage(map, info);
}
// 伤害结算前
public void BeforeDamagedTransformStage(MapData map, SettlementInfo info)
{
var copy = new List<SkillBase>(Skills);
foreach (var skill in copy) skill.BeforeDamagedTransformStage(map, info);
}
// 对他人攻击前
public void BeforeActiveAttackOther(MapData mapData, UnitData origin, UnitData target,out int addDmg)
{
addDmg = 0;
var copy = new List<SkillBase>(Skills);
foreach (var skill in copy)
{
skill.BeforeActiveAttackOther(mapData, origin, target, out var tmpAddDmg);
addDmg += tmpAddDmg;
}
}
// 对他人攻击后
public void AfterActiveAttackOther(MapData mapData, UnitData origin, UnitData target)
{
var copy = new List<SkillBase>(Skills);
foreach (var skill in copy) skill.AfterActiveAttackOther(mapData, origin, target);
}
// 受他人攻击后
public void AfterActiveAttacked(MapData mapData, UnitData origin, UnitData target)
{
var copy = new List<SkillBase>(Skills);
foreach (var skill in copy) skill.AfterActiveAttacked(mapData, origin, target);
}
// 对他人伤害结算前
public void BeforeDamageOther(MapData map, SettlementInfo info)
{
var copy = new List<SkillBase>(Skills);
foreach (var skill in copy) skill.BeforeDamageOther(map, info);
}
// 伤害结算时
public void OnDamaged(MapData mapData, SettlementInfo info)
{
var copy = new List<SkillBase>(Skills);
foreach (var skill in copy) skill.OnDamaged(mapData, info);
}
// 对他人伤害结算时
public void OnDamageOther(MapData mapData, SettlementInfo info)
{
var copy = new List<SkillBase>(Skills);
foreach (var skill in copy) skill.OnDamageOther(mapData, info);
}
// 对他人伤害结算后
public void AfterDamageOther(MapData mapData, SettlementInfo info)
{
var copy = new List<SkillBase>(Skills);
foreach (var skill in copy) skill.AfterDamageOther(mapData, info);
}
// 对他人治疗结算时
public void OnHealOther(MapData mapData, UnitData target,HealType healType)
{
var copy = new List<SkillBase>(Skills);
foreach (var skill in copy) 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 copy = new List<SkillBase>(Skills);
float ret = 0f;
foreach (var skill in copy)
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;
foreach(var skill in Skills)
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;
foreach (var skill in Skills)
{
if (skill.IsTreatAsHero(map, this,unit)) return true;
}
return false;
}
// 判断是否只能在我方领土内移动
public bool IsLimitMoveToSelfTerrain(MapData map)
{
foreach (var skill in Skills)
{
if (skill.IsLimitMoveToSelfTerrain(this, map)) 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();
foreach (var skill in Skills)
skill.OnRefresh();
}
public int AddHealth(int hp)
{
var offset = Math.Min(GetMaxHealth() - Health, hp);
Health += offset;
return offset;
}
public void SetOfficer()
{
foreach (var skill in Skills)
skill.SetOfficer();
}
}
}