/* * @Author: 白哉 * @Description: * @Date: 2025年04月03日 星期四 11:04:31 * @Modify: */ using System.Collections.Generic; using ET; using Logic.Action; using Logic.AI; using Logic.Skill; using MemoryPack; using UnityEngine; namespace RuntimeData { // 奇观类型枚举 public enum WonderTypeEnum { None, PEACE, KNOWLEDGE, TRADE, WEALTH, POWER, PARK, EYE } // 奇观状态枚举 public enum WonderState { NO_HINT, HAVE_HINT, FINISH_NOT_BUILD, FINISH_BUILD, Max } // 外交关系枚举 public enum DiplomacyState { NoDiplomacy, Neutral, League, War, LeagueRupture, } // 好感状态枚举 public enum FeelingState { Trust, Appreciate, Indifferent, Suspicion, Terrible, } // 好感策略枚举 public enum FeelingStrategy { Wise, Charming, Peaceful, Diplomatic, Powerful, Brave, Violent, Threatening, Weak, Annoying, Foolish, Intrusive, Dominative, } [MemoryPackable] public partial class PlayerMapData { public uint SelfPlayerId; public List PlayerDataList; private Dictionary _playerDataDict; public PlayerData SelfPlayerData => GetPlayerData(SelfPlayerId); // 无数据初始化 [MemoryPackConstructor] public PlayerMapData() { PlayerDataList = new List(); _playerDataDict = new Dictionary(); } // 配置初始化 public PlayerMapData(MapConfig mapConfig, MapIdGenerator idGenerator) { PlayerDataList = new List(); _playerDataDict = new Dictionary(); for (int i = 0; i < mapConfig.PlayerCount; i++) { PlayerData player; //处理player到底是谁的问题。目前临时使用的方案,今后要改。目前civ一定=force,所以可以这么做 if (i == 0) player = new PlayerData(mapConfig.selfCivId,mapConfig.selfForceId,idGenerator); else if (mapConfig.selfCivId == i) player = new PlayerData((uint)0,(uint)0,idGenerator); else player = new PlayerData((uint)i,(uint)i,idGenerator); PlayerDataList.Add(player); _playerDataDict[player.Id] = player; //从player的初始科技树获取信息,为player设置初始skill if (Table.Instance.PlayerDataAssets.GetPlayerInfo(player, out var info)) { foreach (var t in info.TechStart) { if(!Table.Instance.TechDataAssets.GetTechInfo(t, out var techInfo))continue; foreach(var a in techInfo.techActions) if (a.ActionType == CommonActionType.UnitSkill) { if(a.SkillType is SkillType.KaguyaFrenchNapoleonicCode or SkillType.CommonPlayerSkillIndustry or SkillType.RemiliaForcesSkill1) player.AddSkill(a.SkillType); } } } } SelfPlayerId = PlayerDataList[0].Id; } public PlayerMapData(PlayerMapData copyData) { PlayerDataList = new List(); _playerDataDict = new Dictionary(); SelfPlayerId = copyData.SelfPlayerId; foreach (var copyPlayer in copyData.PlayerDataList) { var player = new PlayerData(copyPlayer); PlayerDataList.Add(player); _playerDataDict[player.Id] = player; } } public void DeepCopy(PlayerMapData copyData) { _playerDataDict.Clear(); SelfPlayerId = copyData.SelfPlayerId; for (int i = 0; i < copyData.PlayerDataList.Count; i++) { var copyPlayer = copyData.PlayerDataList[i]; if (i >= PlayerDataList.Count) { var player = new PlayerData(copyPlayer); PlayerDataList.Add(player); _playerDataDict[player.Id] = player; } else { PlayerDataList[i].DeepCopy(copyPlayer); _playerDataDict[PlayerDataList[i].Id] = PlayerDataList[i]; } } for (int i = PlayerDataList.Count - 1; i >= copyData.PlayerDataList.Count; i--) { _playerDataDict.Remove(PlayerDataList[i].Id); PlayerDataList.RemoveAt(i); } } // MemoryPack 反序列化之后的后处理 [MemoryPackOnDeserialized] public void OnAfterMemoryPackDeserialize() { _playerDataDict ??= new Dictionary(); _playerDataDict.Clear(); foreach (var player in PlayerDataList) _playerDataDict[player.Id] = player; } // 根据 pid 获取玩家数据 public bool GetPlayerDataByPlayerID(uint pid, out PlayerData playerData) { return _playerDataDict.TryGetValue(pid, out playerData); } // 判断自己是否胜利 public bool CheckSelfWin() { foreach (var playerData in PlayerDataList) { if (playerData.Id == SelfPlayerId) continue; if (playerData.Alive) return false; } return true; } //用于经典模式,判断是否已经抵达31回合,从而结束游戏 public bool CheckTimeEnd() { return false; if(SelfPlayerData.Turn == 61) return true; return false; } // 判断自己是否失败 public bool CheckSelfLose() { return !SelfPlayerData.Alive; } public PlayerData GetPlayerData(uint id) { if (_playerDataDict.TryGetValue(id, out var playerData)) { return playerData; } return null; } public void OnTurnStart(MapData map, PlayerData player) { player.OnTurnStart(map); } public void OnTurnEnd(MapData map, PlayerData player) { player.OnTurnEnd(map); } } [MemoryPackable] public partial class PlayerData : IdentifierBase { // 文明 id, 阵营 id, 摇篮城市 id public uint Turn; public uint PlayerCivId; public uint PlayerForceId; public uint CradleCityId; //首发英雄是否已经获得 public bool HasFirstHero; // 是否存活 public bool Alive; // 财富总额 public int PlayerWealth; public int PlayerTechPoint; //分数 public int PlayerScore; // 视野 public MapSightData Sight; // 科技 public TechTreeData TechTree; // 奇观 public WonderData Wonder; // 外交 public DiplomacyData DiplomacyData; //英雄 public PlayerHeroData PlayerHeroData; // 用于记录已经连续几个 turn 没有进行攻击 public int TurnNoAttack; // 用于记录累计击杀多少 unit public int TotalKill; public GiantType FirstHero; //记录伟人的累计经验,下标直接从ChessType的Enum对应的uint转过来 public int[] giantExp = new int[6]; //记录伟人的复活冷却cd惩罚 public int[] giantPenalty = new int[6]; public List MeetPlayers; public List CurAttackPlayers; public List LastAttackPlayers; //用于记录是否死亡,是否要centMessage来宣告死亡信息 public bool DieMark = false; //用于记录当前是否正在playing,主要是视觉那边使用 public bool IsPlaying; // 用以绑定开始游戏时的 Steam ID public ulong SteamID; // 无参数初始化 [MemoryPackConstructor] public PlayerData() { Sight = new MapSightData(); TechTree = new TechTreeData(); Wonder = new WonderData(); DiplomacyData = new DiplomacyData(); MeetPlayers = new List(); CurAttackPlayers = new List(); LastAttackPlayers = new List(); SteamID = 0; //InitData(); } // 带 ID 初始化 public PlayerData(uint civId, uint forceId, MapIdGenerator idGenerator) { Turn = 0; Id = idGenerator.GeneratorId(); if(Table.Instance.PlayerDataAssets.GetPlayerInfoByCivId(civId,forceId,out var info)) TechTree = new TechTreeData(info.TechStart); else TechTree = new TechTreeData(); Sight = new MapSightData(); Wonder = new WonderData(); DiplomacyData = new DiplomacyData(); PlayerHeroData = new PlayerHeroData(); CurAttackPlayers = new List(); LastAttackPlayers = new List(); MeetPlayers = new List(); MeetPlayers.Add(Id); InitData(civId,forceId); SteamID = 0; } public PlayerData(PlayerData copyData) { Turn = copyData.Turn; Id = copyData.Id; PlayerCivId = copyData.PlayerCivId; PlayerForceId = copyData.PlayerForceId; CradleCityId = copyData.CradleCityId; Alive = copyData.Alive; PlayerWealth = copyData.PlayerWealth; PlayerTechPoint = copyData.PlayerTechPoint; FirstHero = copyData.FirstHero; Sight = new MapSightData(copyData.Sight); TechTree = new TechTreeData(copyData.TechTree); Wonder = new WonderData(copyData.Wonder); DiplomacyData = new DiplomacyData(copyData.DiplomacyData); PlayerHeroData = new PlayerHeroData(copyData.PlayerHeroData); CurAttackPlayers = new List(); foreach (var id in copyData.CurAttackPlayers) CurAttackPlayers.Add(id); LastAttackPlayers = new List(); foreach (var id in copyData.LastAttackPlayers) LastAttackPlayers.Add(id); MeetPlayers = new List(); foreach (var id in copyData.MeetPlayers) MeetPlayers.Add(id); TurnNoAttack = copyData.TurnNoAttack; TotalKill = copyData.TotalKill; foreach (var skill in copyData.Skills) Skills.Add(skill.GetCopySkill()); //拷贝giantExp和giantPenalty for (int i = 0; i < 6; i++) { giantExp[i] = copyData.giantExp[i]; giantPenalty[i] = copyData.giantPenalty[i]; } SteamID = copyData.SteamID; } public void DeepCopy(PlayerData copyData) { Turn = copyData.Turn; Id = copyData.Id; PlayerCivId = copyData.PlayerCivId; PlayerForceId = copyData.PlayerForceId; CradleCityId = copyData.CradleCityId; Alive = copyData.Alive; PlayerWealth = copyData.PlayerWealth; PlayerTechPoint = copyData.PlayerTechPoint; FirstHero = copyData.FirstHero; Sight.DeepCopy(copyData.Sight); TechTree.DeepCopy(copyData.TechTree); Wonder.DeepCopy(copyData.Wonder); DiplomacyData.DeepCopy(copyData.DiplomacyData); PlayerHeroData.DeepCopy(copyData.PlayerHeroData); CurAttackPlayers.Clear(); foreach (var id in copyData.CurAttackPlayers) CurAttackPlayers.Add(id); LastAttackPlayers.Clear(); foreach (var id in copyData.LastAttackPlayers) LastAttackPlayers.Add(id); MeetPlayers.Clear(); foreach (var id in copyData.MeetPlayers) MeetPlayers.Add(id); TurnNoAttack = copyData.TurnNoAttack; TotalKill = copyData.TotalKill; foreach (var skill in copyData.Skills) { AddSkill(skill.GetSkillType()); if (!GetSkill(skill.GetSkillType(), out var selfSkill)) continue; selfSkill.DeepCopy(skill); } for (int i = Skills.Count - 1; i >= 0; i--) { if (copyData.GetSkill(Skills[i].GetSkillType(), out _)) continue; Skills.RemoveAt(i); } for (int i = 0; i < 6; i++) { giantExp[i] = copyData.giantExp[i]; giantPenalty[i] = copyData.giantPenalty[i]; } SteamID = copyData.SteamID; } private void InitData(uint civId,uint forceId) { Alive = true; PlayerWealth = 5; PlayerCivId = civId; PlayerForceId = forceId; PlayerTechPoint = 0; TurnNoAttack = 0; TotalKill = 0; PlayerHeroData.Init(Table.Instance.TransCivIdToCivEnum(civId) ,Table.Instance.TransForceIdToForceEnum(forceId)); } // 全局通知调用 public void OnTurnStart(MapData map) { Turn++; //减少1点伟人复活冷却的时间点 for (int i = 0; i < 6; i++) if (giantPenalty[i] > 0) giantPenalty[i]--; LastAttackPlayers.Clear(); foreach (var id in CurAttackPlayers) LastAttackPlayers.Add(id); CurAttackPlayers.Clear(); for (int i = Skills.Count - 1; i >= 0; i--) { var skill = Skills[i]; if (skill.IsFinished()) { Skills.RemoveAt(i); continue; } skill.OnTurnStart(this, map); } // 刷新好感 RefreshFeelingValue(map); // 刷新外交 RefreshDiplomacyState(map); IsPlaying = true; } public void OnTurnEnd(MapData map) { foreach (var skill in Skills)skill.OnTurnEnd(this, map); foreach (var player in map.PlayerMap.PlayerDataList) { if (player.Id == Id) continue; DiplomacyData.GetCountryDiplomacyInfo(player.Id, out var selfToPlayer); // 回合结束处理联盟破裂标记 if (selfToPlayer.DiplomacyState == DiplomacyState.LeagueRupture) selfToPlayer.IsLeagueRupture = true; // 回合结束处理AI 冷静期计数 if (selfToPlayer.IsCalm > 0) selfToPlayer.IsCalm--; } IsPlaying = false; } // 添加当前回合攻击者 public void AddAttacker(uint playerId) { DiplomacyData.AddTurnAttacker(playerId, Turn); } // 检查前几回合内是否有攻击者 public bool CheckTurnsAttacker(uint turns, uint playerId) { if (turns >= Turn) turns = Turn; return DiplomacyData.CheckTurnAttacker(Turn - turns, playerId); } // 刷新对他国好感值 public void RefreshFeelingValue(MapData map) { int maxScore = -1; uint maxScorePlayer = 0; foreach (var player in map.PlayerMap.PlayerDataList) { if (!player.Alive) continue; if (player.PlayerScore <= maxScore) continue; maxScore = player.PlayerScore; maxScorePlayer = player.Id; } var originCity = new HashSet(); foreach (var player in map.PlayerMap.PlayerDataList) { originCity.Add(player.CradleCityId); } foreach (var player in map.PlayerMap.PlayerDataList) { if (!player.Alive) continue; if (player.Id == Id) continue; DiplomacyData.GetCountryDiplomacyInfo(player.Id, out var selfToPlayer); player.DiplomacyData.GetCountryDiplomacyInfo(Id, out var playerToSelf); selfToPlayer.FeelingStrategyList.Clear(); if (playerToSelf == null || selfToPlayer == null) continue; var score = 50f; // 明智的 愚蠢的 var score1 = 0f; foreach (var otherPlayer in map.PlayerMap.PlayerDataList) { if (!player.Alive) continue; if (otherPlayer.Id == Id || otherPlayer.Id == player.Id) continue; DiplomacyData.GetCountryDiplomacyInfo(otherPlayer.Id, out var selfToOtherPlayer); if (selfToOtherPlayer.DiplomacyState == DiplomacyState.NoDiplomacy) continue; player.DiplomacyData.GetCountryDiplomacyInfo(otherPlayer.Id, out var playerToOtherPlayer); if (playerToOtherPlayer.DiplomacyState == DiplomacyState.NoDiplomacy) continue; if (selfToOtherPlayer.DiplomacyState == playerToOtherPlayer.DiplomacyState) score1 += 5; else score1 -= 5; } if (score1> 0) { score1 += 5; score += Mathf.Min(20, score1); selfToPlayer.FeelingStrategyList.Add(FeelingStrategy.Wise); } if (score1 < 0) { score1 -= 5; score += Mathf.Max(-20, score1); selfToPlayer.FeelingStrategyList.Add(FeelingStrategy.Foolish); } // 迷人的 恼人的 if (map.MapConfig.AIDiff == AIDifficult.EASY && player.Id == map.PlayerMap.SelfPlayerId && Id != map.PlayerMap.SelfPlayerId) { score += 15; selfToPlayer.FeelingStrategyList.Add(FeelingStrategy.Charming); } if (map.MapConfig.AIDiff == AIDifficult.LUNATIC && player.Id == map.PlayerMap.SelfPlayerId && Id != map.PlayerMap.SelfPlayerId) { score -= 15; selfToPlayer.FeelingStrategyList.Add(FeelingStrategy.Annoying); } // 和平的 暴力的 if (!CheckTurnsAttacker(3, player.Id)) { score += 15; selfToPlayer.FeelingStrategyList.Add(FeelingStrategy.Peaceful); } else { score -= 15; selfToPlayer.FeelingStrategyList.Add(FeelingStrategy.Violent); } // 外交的 if (selfToPlayer.IsEmbassy || playerToSelf.IsEmbassy) { score += 15; selfToPlayer.FeelingStrategyList.Add(FeelingStrategy.Diplomatic); } // 强大的 弱小的 var selfScore = 0f; var playerScore = 0f; var selfUnit = new HashSet(); map.GetUnitDataListByPlayerId(Id, selfUnit); var targetUnit = new HashSet(); map.GetUnitDataListByPlayerId(player.Id, targetUnit); foreach (var unit in selfUnit) selfScore += unit.GetMilitary(); foreach (var unit in targetUnit) playerScore += unit.GetMilitary(); if (selfScore < playerScore) { score += 15; selfToPlayer.FeelingStrategyList.Add(FeelingStrategy.Powerful); } if (selfScore > playerScore) { score -= 15; selfToPlayer.FeelingStrategyList.Add(FeelingStrategy.Weak); } // 勇敢的 if (maxScorePlayer != Id) { player.DiplomacyData.GetCountryDiplomacyInfo(maxScorePlayer, out var playerToMaxScorePlayer); if (playerToMaxScorePlayer.DiplomacyState == DiplomacyState.War) { score += 15; selfToPlayer.FeelingStrategyList.Add(FeelingStrategy.Brave); } } // 威胁的 var playerUnit = new HashSet(); map.GetUnitDataListByPlayerId(player.Id, playerUnit); var selfTerritory = map.GetPlayerTerritoryGridIdSet(Id); foreach (var gridId in selfTerritory) { if (!map.GridMap.GetGridDataByGid(gridId, out var gridData)) continue; foreach (var unit in playerUnit) { if (!map.GetGridDataByUnitId(unit.Id, out var unitGrid)) continue; var dis = map.GridMap.CalcDistance(unitGrid, gridData); if (dis > 1) continue; score -= 15; selfToPlayer.FeelingStrategyList.Add(FeelingStrategy.Threatening); break; } if (selfToPlayer.FeelingStrategyList.Contains(FeelingStrategy.Threatening)) break; } // 侵略的 var playerTerritory = map.GetPlayerTerritoryGridIdSet(player.Id); foreach (var playerGridId in playerTerritory) { if (!map.GridMap.GetGridDataByGid(playerGridId, out var playerGrid)) continue; foreach (var selfGridId in selfTerritory) { if (!map.GridMap.GetGridDataByGid(selfGridId, out var selfGrid)) continue; var dis = map.GridMap.CalcDistance(playerGrid, selfGrid); if (dis > 1) continue; score -= 15; selfToPlayer.FeelingStrategyList.Add(FeelingStrategy.Intrusive); break; } if (selfToPlayer.FeelingStrategyList.Contains(FeelingStrategy.Intrusive)) break; } // 主宰的 var count = 0f; if (maxScorePlayer == player.Id) { var otherCity = new List(); map.GetCityDataListByPlayerId(player.Id, otherCity); foreach (var city in otherCity) { if (originCity.Contains(city.Id)) count++; } if (count >= originCity.Count * 0.5f) { score -= 15; selfToPlayer.FeelingStrategyList.Add(FeelingStrategy.Dominative); } } score = Mathf.Max(0, score); selfToPlayer.FeelingValue = score; if (score <= 10) selfToPlayer.FeelingState = FeelingState.Terrible; else if (score <= 30) selfToPlayer.FeelingState = FeelingState.Suspicion; else if (score <= 60) selfToPlayer.FeelingState = FeelingState.Indifferent; else if (score <= 85) selfToPlayer.FeelingState = FeelingState.Appreciate; else if (score <= 100) selfToPlayer.FeelingState = FeelingState.Trust; } } // 刷新对他国的外交关系,回合开始时调用 public void RefreshDiplomacyState(MapData map) { foreach (var player in map.PlayerMap.PlayerDataList) { if (!player.Alive) continue; if (player.Id == Id) continue; DiplomacyData.GetCountryDiplomacyInfo(player.Id, out var selfToPlayer); player.DiplomacyData.GetCountryDiplomacyInfo(Id, out var playerToSelf); // 如果没有外交关系,且没有见过面,则设置为无外交关系 if (!MeetPlayers.Contains(player.Id)) selfToPlayer.DiplomacyState = DiplomacyState.NoDiplomacy; // 如果没有外交关系,且见过面,则设置为中立 else if (selfToPlayer.DiplomacyState == DiplomacyState.NoDiplomacy) selfToPlayer.DiplomacyState = DiplomacyState.Neutral; // 如果上一回合回合内双方未发生战斗,则该回合开始时变为中立关系 //判断有没有对方单位站在我方city上 bool OtherPlayerOnSelfCity = false; var cityList = new HashSet(); map.GetCityDataListByPlayerId(Id,cityList); foreach (var city in cityList) { if(!map.GetGridDataByCityId(city.Id,out var grid))continue; if(!map.GetUnitDataByGid(grid.Id,out var unit))continue; if(!map.GetPlayerDataByUnitId(unit.Id,out var tPlayer))continue; if (tPlayer.Id == player.Id) { OtherPlayerOnSelfCity = true; break; } } if (selfToPlayer.DiplomacyState == DiplomacyState.War && !LastAttackPlayers.Contains(player.Id) && !OtherPlayerOnSelfCity) selfToPlayer.DiplomacyState = DiplomacyState.Neutral; // 联盟破裂转中立 if (selfToPlayer.DiplomacyState == DiplomacyState.LeagueRupture && playerToSelf.DiplomacyState == DiplomacyState.LeagueRupture && selfToPlayer.IsLeagueRupture && playerToSelf.IsLeagueRupture) { selfToPlayer.DiplomacyState = DiplomacyState.Neutral; playerToSelf.DiplomacyState = DiplomacyState.Neutral; selfToPlayer.IsLeagueRupture = false; playerToSelf.IsLeagueRupture = false; } } } } // 奇观信息 [MemoryPackable] public partial class WonderData { // 所有奇观信息 public Dictionary WonderInfoDict; public HashSet WonderRenderMark; [MemoryPackConstructor] public WonderData() { WonderInfoDict = new Dictionary(); WonderRenderMark = new HashSet(); foreach (WonderTypeEnum wonderType in System.Enum.GetValues(typeof(WonderTypeEnum))) WonderInfoDict[wonderType] = WonderState.NO_HINT; } public WonderData(WonderData copyData) { WonderInfoDict = new Dictionary(copyData.WonderInfoDict); WonderRenderMark = new HashSet(copyData.WonderRenderMark); foreach (var kv in copyData.WonderInfoDict) { WonderInfoDict[kv.Key] = kv.Value; } foreach (var typeEnum in copyData.WonderRenderMark) WonderRenderMark.Add(typeEnum); } public void DeepCopy(WonderData copyData) { WonderInfoDict.Clear(); WonderRenderMark.Clear(); foreach (var kv in copyData.WonderInfoDict) WonderInfoDict[kv.Key] = kv.Value; foreach (var typeEnum in copyData.WonderRenderMark) WonderRenderMark.Add(typeEnum); } // 获取某个奇观的状态 public WonderState GetWonderState(WonderTypeEnum wonderType) { if (WonderInfoDict.TryGetValue(wonderType, out var state)) { return state; } return WonderState.NO_HINT; } public void SetWonderState(WonderTypeEnum wonderType, WonderState state) { WonderInfoDict[wonderType] = state; WonderRenderMark.Add(wonderType); } // 判断某个奇观是否变动 public bool IsWonderRenderMark(WonderTypeEnum wonderType) { return WonderRenderMark.Contains(wonderType); } } // 视野信息 [MemoryPackable] public partial class MapSightData { public HashSet SightGidSet; [MemoryPackConstructor] public MapSightData() { SightGidSet = new HashSet(); } public MapSightData(MapSightData copyData) { SightGidSet = new HashSet(copyData.SightGidSet); } public void DeepCopy(MapSightData copyData) { SightGidSet.Clear(); foreach (var gid in copyData.SightGidSet) SightGidSet.Add(gid); } // 判断是否在视野内 public bool CheckIsInSight(uint gid) { return SightGidSet.Contains(gid); } } // 科技信息 [MemoryPackable] public partial class TechTreeData { public HashSet TechSet; [MemoryPackIgnore] public HashSet TechActionCacheSet; [MemoryPackIgnore] public HashSet TechAtomCacheSet; [MemoryPackConstructor] public TechTreeData() { TechSet = new HashSet(); TechActionCacheSet = new HashSet(); TechAtomCacheSet = new HashSet(); } public TechTreeData(List startTechList = null) { TechSet = new HashSet(); TechActionCacheSet = new HashSet(); TechAtomCacheSet = new HashSet(); if (startTechList != null) { foreach(var t in startTechList) LearnTech(t); } } public TechTreeData(TechTreeData copyData) { TechSet = new HashSet(copyData.TechSet); TechActionCacheSet = new HashSet(copyData.TechActionCacheSet); TechAtomCacheSet = new HashSet(copyData.TechAtomCacheSet); } // MemoryPack 反序列化之后的后处理 [MemoryPackOnDeserialized] public void OnAfterMemoryPackDeserialize() { TechActionCacheSet ??= new HashSet(); foreach (var tech in TechSet) { var techInfo = Table.Instance.TechDataAssets.GetTechInfo(tech); foreach (var techItem in techInfo.techActions) TechActionCacheSet.Add(techItem.Id); foreach (var techAtom in techInfo.TechAtomList) TechAtomCacheSet.Add(techAtom); } } public void DeepCopy(TechTreeData copyData) { TechSet.Clear(); TechActionCacheSet.Clear(); foreach (var tech in copyData.TechSet) TechSet.Add(tech); foreach (var act in copyData.TechActionCacheSet) TechActionCacheSet.Add(act); foreach (var atom in copyData.TechAtomCacheSet) TechAtomCacheSet.Add(atom); } public void LearnTech(TechType techType) { TechSet.Add(techType); var techInfo = Table.Instance.TechDataAssets.GetTechInfo(techType); foreach (var act in techInfo.techActions) TechActionCacheSet.Add(act.Id); foreach(var techAtom in techInfo.TechAtomList) TechAtomCacheSet.Add(techAtom); } // 删除科技 public void RemoveTech(TechType techType) { TechSet.Remove(techType); } // 是否拥有某个科技 public bool CheckIfHasTech(TechType techType) { return TechSet.Contains(techType); } //是否拥有某个原子科技 public bool CheckIfHasTechAtom(TechAtom atom) { return TechAtomCacheSet.Contains(atom); } public bool HasAllTech() { bool ret = true; foreach (TechType tech in System.Enum.GetValues(typeof(TechType))) { var techInfo = Table.Instance.TechDataAssets.GetTechInfo(tech); if (techInfo.GiantTech) continue; if (CheckIfHasTech(tech)) continue; ret = false; break; } return ret; } public int GetScore() { int ret = 0; foreach (var tech in TechSet) { var techInfo = Table.Instance.TechDataAssets.GetTechInfo(tech); ret += techInfo.CostLevel * 100; } return ret; } public bool CheckActionCan(CommonActionId actionId) { if (!Table.Instance.ActionDataAssets.GetActionInfo(actionId, out var info)) return false; if (info.NoNeedTech) return true; return TechActionCacheSet.Contains(actionId.Id); } public bool CheckIfTechUnsee(TechType techType) { var techInfo = Table.Instance.TechDataAssets.GetTechInfo(techType); if (techInfo.GiantTech) { int has = 0; foreach(var tt in techInfo.GiantTechSet) if (TechSet.Contains(tt)) has++; //Debug.Log(has); return has < 3; } return !TechSet.Contains(Table.Instance.TechDataAssets.GetTechInfo(techType).FatherTechType); } public bool CheckIfTechCanLearn(TechType techType) { //Debug.Log(techType); return !TechSet.Contains(techType) && !CheckIfTechUnsee(techType); } } // 主动攻击我的敌人信息 [MemoryPackable] public partial class DiplomacyData { public List Info; private Dictionary _infoDict; [MemoryPackConstructor] public DiplomacyData() { Info = new List(); } public DiplomacyData(DiplomacyData copyData) { Info = new List(); } // MemoryPack 反序列化之后的后处理 [MemoryPackOnDeserialized] public void OnAfterMemoryPackDeserialize() { Refresh(); } public void DeepCopy(DiplomacyData copyData) { for (int i = 0; i < copyData.Info.Count; i++) { if (Info.Count <= i) Info.Add(new CountryDiplomacyInfo()); Info[i].DeepCopy(copyData.Info[i]); } } public bool CheckTurnAttacker(uint turn, uint playerId) { GetCountryDiplomacyInfo(playerId, out var info); if (info == null) return false; return info.AttackTurn != 0 && info.AttackTurn >= turn; } public void AddTurnAttacker(uint playerId, uint turn) { GetCountryDiplomacyInfo(playerId, out var info); if (info == null) return; info.AttackTurn = turn; } public void GetCountryDiplomacyInfo(uint playerId, out CountryDiplomacyInfo info) { Refresh(); if (!_infoDict.TryGetValue(playerId, out info)) { info = new CountryDiplomacyInfo { PlayerId = playerId }; Info.Add(info); _infoDict[playerId] = info; } } private void Refresh() { if (_infoDict == null) _infoDict = new Dictionary(); if (_infoDict.Count == Info.Count) return; _infoDict.Clear(); foreach (var countryDiplomacy in Info) _infoDict[countryDiplomacy.PlayerId] = countryDiplomacy; } } // 对他国的数据 [MemoryPackable] public partial class CountryDiplomacyInfo { public uint PlayerId; // 我对国家 PlayerId 的外交关系 public DiplomacyState DiplomacyState; // 我对国家 PlayerId 的好感值 public float FeelingValue; // 我对国家 PlayerId 的好感态度 public FeelingState FeelingState; // 我对国家 PlayerId 的好感策略 public List FeelingStrategyList; // 国家 PlayerId 攻击我的回合记录 public uint AttackTurn; // 国家 PlayerId 是否在我国建立了大使馆 public bool IsEmbassy; // 联盟破裂回合结束标记 public bool IsLeagueRupture; // 国家对我发起的结盟请求 public bool IsLeagueRequest; // 冷静期标记 public int IsCalm; [MemoryPackConstructor] public CountryDiplomacyInfo() { AttackTurn = 0; IsCalm = 0; IsEmbassy = false; IsLeagueRupture = false; IsLeagueRequest = false; FeelingStrategyList = new List(); } public CountryDiplomacyInfo(CountryDiplomacyInfo copyData) { PlayerId = copyData.PlayerId; AttackTurn = copyData.AttackTurn; DiplomacyState = copyData.DiplomacyState; FeelingValue = copyData.FeelingValue; FeelingState = copyData.FeelingState; FeelingStrategyList= new List(); foreach (var strategy in copyData.FeelingStrategyList)FeelingStrategyList.Add(strategy); IsEmbassy = copyData.IsEmbassy; IsLeagueRupture = copyData.IsLeagueRupture; IsLeagueRequest = copyData.IsLeagueRequest; IsCalm = copyData.IsCalm; } public void DeepCopy(CountryDiplomacyInfo copyData) { PlayerId = copyData.PlayerId; AttackTurn = copyData.AttackTurn; DiplomacyState = copyData.DiplomacyState; FeelingValue = copyData.FeelingValue; FeelingState = copyData.FeelingState; FeelingStrategyList.Clear(); foreach (var strategy in copyData.FeelingStrategyList)FeelingStrategyList.Add(strategy); IsEmbassy = copyData.IsEmbassy; IsLeagueRupture = copyData.IsLeagueRupture; IsLeagueRequest = copyData.IsLeagueRequest; IsCalm = copyData.IsCalm; } } // 英雄的数据 [MemoryPackable] public partial class PlayerHeroData { //当前最多获取英雄数量 public int MaxHeroCount; //当前已经拥有的英雄数量 public int HeroCount => HeroList.Count; //当前已经有的英雄 public List HeroList; private GiantType _leaderGiantType; [MemoryPackConstructor] public PlayerHeroData() { MaxHeroCount = 1; HeroList = new List(); _leaderGiantType = GiantType.None; } public PlayerHeroData(PlayerHeroData copyData) { MaxHeroCount = copyData.MaxHeroCount; HeroList = new List(copyData.HeroList); _leaderGiantType = copyData._leaderGiantType; } public void DeepCopy(PlayerHeroData copyData) { MaxHeroCount = copyData.MaxHeroCount; HeroList = new List(copyData.HeroList); _leaderGiantType = copyData._leaderGiantType; } public void Init(CivEnum civEnum, ForceEnum forceEnum) { _leaderGiantType = civEnum switch { CivEnum.Egyptian => GiantType.EgyptianRemilia, CivEnum.French => GiantType.FrenchKaguya, _ => GiantType.None }; } public GiantType GetLeaderGiantType() { return _leaderGiantType; } public bool HasHero(GiantType giantType) { foreach(var hero in HeroList) if (hero.GiantType == giantType) return true; return false; } public void AddHero(GiantType giantType) { UnitFullType t = new UnitFullType(){UnitType = UnitType.Giant,GiantType = giantType,UnitLevel = 0}; //如果不是首个英雄,起步是Lv1 if (HeroList.Count > 0) t.UnitLevel = 1; HeroList.Add(t); } } }