970 lines
33 KiB
C#
970 lines
33 KiB
C#
/*
|
||
* @Author: 白哉
|
||
* @Description:
|
||
* @Date: 2025年04月03日 星期四 11:04:31
|
||
* @Modify:
|
||
*/
|
||
|
||
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using Logic.Action;
|
||
using Logic.AI;
|
||
using NUnit.Framework;
|
||
using Unity.VisualScripting;
|
||
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,
|
||
}
|
||
|
||
|
||
[Serializable]
|
||
public class PlayerMapData : ISerializationCallbackReceiver
|
||
{
|
||
public uint SelfPlayerId;
|
||
public List<PlayerData> PlayerDataList;
|
||
|
||
private Dictionary<uint, PlayerData> _playerDataDict;
|
||
public PlayerData SelfPlayerData => GetPlayerData(SelfPlayerId);
|
||
|
||
|
||
// 无数据初始化
|
||
public PlayerMapData()
|
||
{
|
||
PlayerDataList = new List<PlayerData>();
|
||
_playerDataDict = new Dictionary<uint, PlayerData>();
|
||
}
|
||
|
||
// 配置初始化
|
||
public PlayerMapData(MapConfig mapConfig, MapIdGenerator idGenerator)
|
||
{
|
||
PlayerDataList = new List<PlayerData>();
|
||
_playerDataDict = new Dictionary<uint, PlayerData>();
|
||
|
||
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;
|
||
}
|
||
|
||
SelfPlayerId = PlayerDataList[0].Id;
|
||
}
|
||
|
||
public PlayerMapData(PlayerMapData copyData)
|
||
{
|
||
PlayerDataList = new List<PlayerData>();
|
||
_playerDataDict = new Dictionary<uint, PlayerData>();
|
||
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);
|
||
}
|
||
}
|
||
|
||
public void OnBeforeSerialize()
|
||
{
|
||
|
||
}
|
||
|
||
public void OnAfterDeserialize()
|
||
{
|
||
_playerDataDict ??= new Dictionary<uint, PlayerData>();
|
||
_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()
|
||
{
|
||
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);
|
||
}
|
||
}
|
||
|
||
|
||
[Serializable]
|
||
public class PlayerData : IdentifierBase
|
||
{
|
||
// 文明 id, 阵营 id, 摇篮城市 id
|
||
public uint Turn;
|
||
public uint PlayerCivId;
|
||
public uint PlayerForceId;
|
||
public uint CradleCityId;
|
||
|
||
// 是否存活
|
||
public bool Alive;
|
||
// 财富总额
|
||
public int PlayerWealth2;
|
||
|
||
public int PlayerWealth
|
||
{
|
||
get => PlayerWealth2;
|
||
set
|
||
{
|
||
PlayerWealth2 = value;
|
||
if (PlayerWealth2 < 0)
|
||
{
|
||
Debug.Log(111);
|
||
}
|
||
}
|
||
}
|
||
|
||
//分数
|
||
public int PlayerScore;
|
||
// 视野
|
||
public MapSightData Sight;
|
||
// 科技
|
||
public TechTreeData TechTree;
|
||
// 奇观
|
||
public WonderData Wonder;
|
||
|
||
// 用于记录已经连续几个 turn 没有进行攻击
|
||
public int TurnNoAttack;
|
||
// 用于记录累计击杀多少 unit
|
||
public int TotalKill;
|
||
|
||
public List<uint> MeetPlayers;
|
||
public List<uint> CurAttackPlayers;
|
||
public List<uint> LastAttackPlayers;
|
||
public DiplomacyData DiplomacyData;
|
||
|
||
//用于记录是否死亡,是否要centMessage来宣告死亡信息
|
||
public bool DieMark = false;
|
||
|
||
// 无参数初始化
|
||
public PlayerData()
|
||
{
|
||
Sight = new MapSightData();
|
||
TechTree = new TechTreeData();
|
||
Wonder = new WonderData();
|
||
DiplomacyData = new DiplomacyData();
|
||
MeetPlayers = new List<uint>();
|
||
CurAttackPlayers = new List<uint>();
|
||
LastAttackPlayers = new List<uint>();
|
||
//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();
|
||
CurAttackPlayers = new List<uint>();
|
||
LastAttackPlayers = new List<uint>();
|
||
MeetPlayers = new List<uint>();
|
||
MeetPlayers.Add(Id);
|
||
InitData(civId,forceId);
|
||
}
|
||
|
||
public PlayerData(PlayerData copyData)
|
||
{
|
||
Turn = copyData.Turn;
|
||
Id = copyData.Id;
|
||
PlayerCivId = copyData.PlayerCivId;
|
||
PlayerForceId = copyData.PlayerForceId;
|
||
CradleCityId = copyData.CradleCityId;
|
||
Alive = copyData.Alive;
|
||
PlayerWealth2 = copyData.PlayerWealth2;
|
||
|
||
Sight = new MapSightData(copyData.Sight);
|
||
TechTree = new TechTreeData(copyData.TechTree);
|
||
Wonder = new WonderData(copyData.Wonder);
|
||
DiplomacyData = new DiplomacyData(copyData.DiplomacyData);
|
||
|
||
CurAttackPlayers = new List<uint>();
|
||
foreach (var id in copyData.CurAttackPlayers) CurAttackPlayers.Add(id);
|
||
LastAttackPlayers = new List<uint>();
|
||
foreach (var id in copyData.LastAttackPlayers) LastAttackPlayers.Add(id);
|
||
|
||
MeetPlayers = new List<uint>();
|
||
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());
|
||
}
|
||
|
||
public void DeepCopy(PlayerData copyData)
|
||
{
|
||
Turn = copyData.Turn;
|
||
Id = copyData.Id;
|
||
PlayerCivId = copyData.PlayerCivId;
|
||
PlayerForceId = copyData.PlayerForceId;
|
||
CradleCityId = copyData.CradleCityId;
|
||
Alive = copyData.Alive;
|
||
PlayerWealth2 = copyData.PlayerWealth2;
|
||
|
||
Sight.DeepCopy(copyData.Sight);
|
||
TechTree.DeepCopy(copyData.TechTree);
|
||
Wonder.DeepCopy(copyData.Wonder);
|
||
DiplomacyData.DeepCopy(copyData.DiplomacyData);
|
||
|
||
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);
|
||
}
|
||
}
|
||
|
||
private void InitData(uint civId,uint forceId)
|
||
{
|
||
Alive = true;
|
||
PlayerWealth2 = 5;
|
||
PlayerCivId = civId;
|
||
PlayerForceId = forceId;
|
||
|
||
TurnNoAttack = 0;
|
||
TotalKill = 0;
|
||
}
|
||
|
||
// 全局通知调用
|
||
public void OnTurnStart(MapData map)
|
||
{
|
||
Turn++;
|
||
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);
|
||
}
|
||
|
||
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;
|
||
}
|
||
}
|
||
|
||
// 添加当前回合攻击者
|
||
public void AddAttacker(uint playerId)
|
||
{
|
||
DiplomacyData.AddTurnAttacker(Turn, playerId);
|
||
}
|
||
|
||
// 检查前几回合内是否有攻击者
|
||
public bool CheckTurnsAttacker(uint turns, uint playerId)
|
||
{
|
||
for (int i = 0; i < turns; i++)
|
||
{
|
||
if (Turn < i) return false;
|
||
if (!DiplomacyData.CheckTurnAttacker(Turn - (uint)i, playerId)) continue;
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
// 刷新对他国好感值
|
||
public void RefreshFeelingValue(MapData map)
|
||
{
|
||
int maxScore = 0;
|
||
uint maxScorePlayer = 0;
|
||
foreach (var player in map.PlayerMap.PlayerDataList)
|
||
{
|
||
if (player.PlayerScore <= maxScore) continue;
|
||
maxScore = player.PlayerScore;
|
||
maxScorePlayer = player.Id;
|
||
}
|
||
|
||
foreach (var player in map.PlayerMap.PlayerDataList)
|
||
{
|
||
if (player.Id == Id) continue;
|
||
DiplomacyData.GetCountryDiplomacyInfo(player.Id, out var selfToPlayer);
|
||
player.DiplomacyData.GetCountryDiplomacyInfo(Id, out var playerToSelf);
|
||
if (playerToSelf == null || selfToPlayer == null) continue;
|
||
var score = 0f;
|
||
|
||
// 明智的 愚蠢的
|
||
var score1 = 0f;
|
||
foreach (var otherPlayer in map.PlayerMap.PlayerDataList)
|
||
{
|
||
if (otherPlayer.Id == Id || otherPlayer.Id == player.Id) continue;
|
||
DiplomacyData.GetCountryDiplomacyInfo(player.Id, out var selfToOtherPlayer);
|
||
if (selfToOtherPlayer.DiplomacyState == DiplomacyState.NoDiplomacy) continue;
|
||
player.DiplomacyData.GetCountryDiplomacyInfo(player.Id, out var playerToOtherPlayer);
|
||
if (playerToOtherPlayer.DiplomacyState == DiplomacyState.NoDiplomacy) continue;
|
||
|
||
if (selfToOtherPlayer.DiplomacyState == playerToOtherPlayer.DiplomacyState) score1 += 5;
|
||
else score1 -= 5;
|
||
}
|
||
if (score1 + 5 > 0) score += Mathf.Min(20, score1);
|
||
if (score1 - 5 < 0) score += Mathf.Max(-20, score1);
|
||
|
||
// 迷人的 恼人的
|
||
if (map.MapConfig.AIDiff == AIDifficult.EASY && player.Id == map.PlayerMap.SelfPlayerId &&
|
||
Id != map.PlayerMap.SelfPlayerId) score += 15;
|
||
if (map.MapConfig.AIDiff == AIDifficult.LUNATIC && player.Id == map.PlayerMap.SelfPlayerId &&
|
||
Id != map.PlayerMap.SelfPlayerId) score -= 15;
|
||
|
||
// 和平的 暴力的
|
||
if (!CheckTurnsAttacker(3, player.Id)) score += 15;
|
||
else score -= 15;
|
||
|
||
// 外交的
|
||
if (selfToPlayer.IsEmbassy || playerToSelf.IsEmbassy) score += 15;
|
||
|
||
// 强大的 弱小的
|
||
var selfScore = 0f;
|
||
var playerScore = 0f;
|
||
foreach (var gridId in Sight.SightGidSet)
|
||
{
|
||
if (!map.GetUnitDataByGid(gridId, out var unit)) continue;
|
||
if (!map.GetPlayerIdByUnitId(unit.Id, out var ownerId)) continue;
|
||
if (ownerId == Id) selfScore += unit.GetCost();
|
||
if (ownerId == player.Id) playerScore += unit.GetCost();
|
||
}
|
||
if (selfScore < playerScore) score += 15;
|
||
if (selfScore > playerScore) score -= 15;
|
||
|
||
// 勇敢的
|
||
if (maxScorePlayer != Id)
|
||
{
|
||
player.DiplomacyData.GetCountryDiplomacyInfo(maxScorePlayer, out var playerToMaxScorePlayer);
|
||
if (playerToMaxScorePlayer.DiplomacyState == DiplomacyState.War) score += 15;
|
||
}
|
||
|
||
// 威胁的
|
||
var playerUnit = new HashSet<UnitData>();
|
||
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;
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 侵略的
|
||
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;
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 主宰的
|
||
if (maxScorePlayer == player.Id)
|
||
{
|
||
var count = 0;
|
||
var playerCity = new HashSet<CityData>();
|
||
map.GetCityDataListByPlayerId(player.Id, playerCity);
|
||
foreach (var city in playerCity) if (city.IsCradle) count++;
|
||
if (count > 0) count--;
|
||
score -= 15 + count * 5;
|
||
}
|
||
|
||
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.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;
|
||
// 如果上一回合回合内双方未发生战斗,则该回合开始时变为中立关系
|
||
if (selfToPlayer.DiplomacyState == DiplomacyState.War && !LastAttackPlayers.Contains(player.Id))
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
// 奇观信息
|
||
[Serializable]
|
||
public class WonderData : ISerializationCallbackReceiver
|
||
{
|
||
// 所有奇观信息
|
||
public Dictionary<WonderTypeEnum, WonderState> WonderInfoDict;
|
||
public HashSet<WonderTypeEnum> WonderRenderMark;
|
||
|
||
public List<WonderTypeEnum> WonderInfoKeyList;
|
||
public List<WonderState> WonderInfoValueList;
|
||
public List<WonderTypeEnum> WonderRenderList;
|
||
|
||
|
||
public WonderData()
|
||
{
|
||
WonderInfoDict = new Dictionary<WonderTypeEnum, WonderState>();
|
||
WonderRenderMark = new HashSet<WonderTypeEnum>();
|
||
foreach (WonderTypeEnum wonderType in System.Enum.GetValues(typeof(WonderTypeEnum)))
|
||
WonderInfoDict[wonderType] = WonderState.NO_HINT;
|
||
}
|
||
|
||
public WonderData(WonderData copyData)
|
||
{
|
||
WonderInfoDict = new Dictionary<WonderTypeEnum, WonderState>(copyData.WonderInfoDict);
|
||
WonderRenderMark = new HashSet<WonderTypeEnum>(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 void OnBeforeSerialize()
|
||
{
|
||
WonderInfoKeyList ??= new List<WonderTypeEnum>();
|
||
WonderInfoValueList ??= new List<WonderState>();
|
||
WonderRenderList ??= new List<WonderTypeEnum>();
|
||
WonderInfoKeyList.Clear();
|
||
WonderInfoValueList.Clear();
|
||
WonderRenderList.Clear();
|
||
foreach (var kv in WonderInfoDict)
|
||
{
|
||
WonderInfoKeyList.Add(kv.Key);
|
||
WonderInfoValueList.Add(kv.Value);
|
||
}
|
||
|
||
foreach (var render in WonderRenderMark) WonderRenderList.Add(render);
|
||
}
|
||
|
||
public void OnAfterDeserialize()
|
||
{
|
||
WonderInfoDict ??= new Dictionary<WonderTypeEnum, WonderState>();
|
||
WonderRenderMark ??= new HashSet<WonderTypeEnum>();
|
||
WonderInfoDict.Clear();
|
||
WonderRenderMark.Clear();
|
||
for (int i = 0; i < WonderInfoKeyList.Count; i++)
|
||
{
|
||
WonderInfoDict[WonderInfoKeyList[i]] = WonderInfoValueList[i];
|
||
}
|
||
foreach (var render in WonderRenderList) WonderRenderMark.Add(render);
|
||
}
|
||
|
||
// 获取某个奇观的状态
|
||
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);
|
||
}
|
||
}
|
||
|
||
|
||
// 视野信息
|
||
[Serializable]
|
||
public class MapSightData : ISerializationCallbackReceiver
|
||
{
|
||
public HashSet<uint> SightGidSet;
|
||
public List<uint> SightGidListForSerialize;
|
||
|
||
|
||
public MapSightData()
|
||
{
|
||
SightGidSet = new HashSet<uint>();
|
||
}
|
||
|
||
public MapSightData(MapSightData copyData)
|
||
{
|
||
SightGidSet = new HashSet<uint>(copyData.SightGidSet);
|
||
}
|
||
|
||
public void DeepCopy(MapSightData copyData)
|
||
{
|
||
SightGidSet.Clear();
|
||
foreach (var gid in copyData.SightGidSet) SightGidSet.Add(gid);
|
||
}
|
||
|
||
public void OnBeforeSerialize()
|
||
{
|
||
SightGidListForSerialize ??= new List<uint>();
|
||
SightGidListForSerialize.Clear();
|
||
foreach (var gid in SightGidSet) SightGidListForSerialize.Add(gid);
|
||
}
|
||
|
||
public void OnAfterDeserialize()
|
||
{
|
||
SightGidSet ??= new HashSet<uint>();
|
||
SightGidSet.Clear();
|
||
foreach (var gid in SightGidListForSerialize) SightGidSet.Add(gid);
|
||
}
|
||
|
||
// 判断是否在视野内
|
||
public bool CheckIsInSight(uint gid)
|
||
{
|
||
return SightGidSet.Contains(gid);
|
||
}
|
||
}
|
||
|
||
|
||
// 科技信息
|
||
[Serializable]
|
||
public class TechTreeData : ISerializationCallbackReceiver
|
||
{
|
||
public HashSet<TechType> TechSet;
|
||
public HashSet<uint> TechActionCacheSet;
|
||
|
||
//仅用于序列化
|
||
public List<TechType> TechListForSerial;
|
||
public List<uint> TechActionCacheList;
|
||
|
||
|
||
public TechTreeData(List<TechType> StartTechList = null)
|
||
{
|
||
TechSet = new HashSet<TechType>();
|
||
TechActionCacheSet = new HashSet<uint>();
|
||
if(StartTechList != null)
|
||
foreach(var t in StartTechList)
|
||
LearnTech(t);
|
||
}
|
||
|
||
public TechTreeData(TechTreeData copyData)
|
||
{
|
||
TechSet = new HashSet<TechType>(copyData.TechSet);
|
||
TechActionCacheSet = new HashSet<uint>(copyData.TechActionCacheSet);
|
||
}
|
||
|
||
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);
|
||
}
|
||
|
||
public void OnBeforeSerialize()
|
||
{
|
||
TechListForSerial ??= new List<TechType>();
|
||
TechActionCacheList ??= new List<uint>();
|
||
TechListForSerial.Clear();
|
||
TechActionCacheList.Clear();
|
||
foreach (var techType in TechSet) TechListForSerial.Add(techType);
|
||
foreach (var cache in TechActionCacheSet) TechActionCacheList.Add(cache);
|
||
}
|
||
|
||
public void OnAfterDeserialize()
|
||
{
|
||
TechSet ??= new HashSet<TechType>();
|
||
TechActionCacheSet ??= new HashSet<uint>();
|
||
TechSet.Clear();
|
||
TechActionCacheSet.Clear();
|
||
foreach (var techType in TechListForSerial) TechSet.Add(techType);
|
||
foreach (var cache in TechActionCacheList) TechActionCacheSet.Add(cache);
|
||
}
|
||
|
||
public void LearnTech(TechType techType)
|
||
{
|
||
TechSet.Add(techType);
|
||
var techInfo = Table.Instance.TechDataAssets.GetTechInfo(techType);
|
||
foreach (var techItem in techInfo.techActions)
|
||
TechActionCacheSet.Add(techItem.Id);
|
||
}
|
||
|
||
// 删除科技
|
||
public void RemoveTech(TechType techType)
|
||
{
|
||
TechSet.Remove(techType);
|
||
}
|
||
|
||
// 是否拥有某个科技
|
||
public bool CheckIfHasTech(TechType techType)
|
||
{
|
||
return TechSet.Contains(techType);
|
||
}
|
||
|
||
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);
|
||
|
||
}
|
||
}
|
||
|
||
|
||
// 主动攻击我的敌人信息
|
||
[Serializable]
|
||
public class DiplomacyData : ISerializationCallbackReceiver
|
||
{
|
||
public List<CountryDiplomacyInfo> Info;
|
||
private Dictionary<uint, CountryDiplomacyInfo> _infoDict;
|
||
|
||
public DiplomacyData()
|
||
{
|
||
Info = new List<CountryDiplomacyInfo>();
|
||
}
|
||
|
||
public DiplomacyData(DiplomacyData copyData)
|
||
{
|
||
Info = new List<CountryDiplomacyInfo>();
|
||
}
|
||
|
||
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<uint, CountryDiplomacyInfo>();
|
||
if (_infoDict.Count == Info.Count) return;
|
||
|
||
_infoDict.Clear();
|
||
foreach (var countryDiplomacy in Info) _infoDict[countryDiplomacy.PlayerId] = countryDiplomacy;
|
||
}
|
||
|
||
public void OnBeforeSerialize()
|
||
{
|
||
|
||
}
|
||
|
||
public void OnAfterDeserialize()
|
||
{
|
||
|
||
}
|
||
}
|
||
|
||
|
||
// 对他国的数据
|
||
[Serializable]
|
||
public class CountryDiplomacyInfo
|
||
{
|
||
public uint PlayerId;
|
||
// 我对国家 PlayerId 的外交关系
|
||
public DiplomacyState DiplomacyState;
|
||
// 我对国家 PlayerId 的好感值
|
||
public float FeelingValue;
|
||
// 我对国家 PlayerId 的好感态度
|
||
public FeelingState FeelingState;
|
||
// 国家 PlayerId 攻击我的回合记录
|
||
public uint AttackTurn;
|
||
// 国家 PlayerId 是否在我国建立了大使馆
|
||
public bool IsEmbassy;
|
||
// 联盟破裂回合结束标记
|
||
public bool IsLeagueRupture;
|
||
|
||
public CountryDiplomacyInfo()
|
||
{
|
||
AttackTurn = 0;
|
||
IsEmbassy = false;
|
||
IsLeagueRupture = false;
|
||
}
|
||
|
||
public CountryDiplomacyInfo(CountryDiplomacyInfo copyData)
|
||
{
|
||
PlayerId = copyData.PlayerId;
|
||
AttackTurn = copyData.AttackTurn;
|
||
DiplomacyState = copyData.DiplomacyState;
|
||
FeelingValue = copyData.FeelingValue;
|
||
FeelingState = copyData.FeelingState;
|
||
IsEmbassy = copyData.IsEmbassy;
|
||
IsLeagueRupture = copyData.IsLeagueRupture;
|
||
}
|
||
|
||
public void DeepCopy(CountryDiplomacyInfo copyData)
|
||
{
|
||
PlayerId = copyData.PlayerId;
|
||
AttackTurn = copyData.AttackTurn;
|
||
DiplomacyState = copyData.DiplomacyState;
|
||
FeelingValue = copyData.FeelingValue;
|
||
FeelingState = copyData.FeelingState;
|
||
IsEmbassy = copyData.IsEmbassy;
|
||
IsLeagueRupture = copyData.IsLeagueRupture;
|
||
}
|
||
}
|
||
} |