1066 lines
37 KiB
C#
1066 lines
37 KiB
C#
/*
|
||
* @Author: 白哉
|
||
* @Description:
|
||
* @Date: 2025年04月03日 星期四 11:04:31
|
||
* @Modify:
|
||
*/
|
||
|
||
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using Logic.Action;
|
||
using Logic.AI;
|
||
using MemoryPack;
|
||
using Steamworks;
|
||
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<PlayerData> PlayerDataList;
|
||
|
||
private Dictionary<uint, PlayerData> _playerDataDict;
|
||
public PlayerData SelfPlayerData => GetPlayerData(SelfPlayerId);
|
||
|
||
|
||
// 无数据初始化
|
||
[MemoryPackConstructor]
|
||
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;
|
||
|
||
//从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<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);
|
||
}
|
||
}
|
||
|
||
// MemoryPack 反序列化之后的后处理
|
||
[MemoryPackOnDeserialized]
|
||
public void OnAfterMemoryPackDeserialize()
|
||
{
|
||
_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()
|
||
{
|
||
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;
|
||
|
||
// 用于记录已经连续几个 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<uint> MeetPlayers;
|
||
public List<uint> CurAttackPlayers;
|
||
public List<uint> 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<uint>();
|
||
CurAttackPlayers = new List<uint>();
|
||
LastAttackPlayers = new List<uint>();
|
||
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();
|
||
CurAttackPlayers = new List<uint>();
|
||
LastAttackPlayers = new List<uint>();
|
||
MeetPlayers = new List<uint>();
|
||
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);
|
||
|
||
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());
|
||
//拷贝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);
|
||
|
||
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;
|
||
}
|
||
|
||
// 全局通知调用
|
||
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<uint>();
|
||
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<UnitData>();
|
||
map.GetUnitDataListByPlayerId(Id, selfUnit);
|
||
var targetUnit = new HashSet<UnitData>();
|
||
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<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;
|
||
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<CityData>();
|
||
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<CityData>();
|
||
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<WonderTypeEnum, WonderState> WonderInfoDict;
|
||
public HashSet<WonderTypeEnum> WonderRenderMark;
|
||
|
||
|
||
[MemoryPackConstructor]
|
||
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 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<uint> SightGidSet;
|
||
|
||
|
||
[MemoryPackConstructor]
|
||
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 bool CheckIsInSight(uint gid)
|
||
{
|
||
return SightGidSet.Contains(gid);
|
||
}
|
||
}
|
||
|
||
|
||
// 科技信息
|
||
[MemoryPackable]
|
||
public partial class TechTreeData
|
||
{
|
||
public HashSet<TechType> TechSet;
|
||
public HashSet<uint> TechActionCacheSet;
|
||
|
||
|
||
[MemoryPackConstructor]
|
||
public TechTreeData()
|
||
{
|
||
|
||
}
|
||
|
||
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 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);
|
||
|
||
}
|
||
}
|
||
|
||
|
||
// 主动攻击我的敌人信息
|
||
[MemoryPackable]
|
||
public partial class DiplomacyData
|
||
{
|
||
public List<CountryDiplomacyInfo> Info;
|
||
private Dictionary<uint, CountryDiplomacyInfo> _infoDict;
|
||
|
||
|
||
[MemoryPackConstructor]
|
||
public DiplomacyData()
|
||
{
|
||
Info = new List<CountryDiplomacyInfo>();
|
||
}
|
||
|
||
public DiplomacyData(DiplomacyData copyData)
|
||
{
|
||
Info = new List<CountryDiplomacyInfo>();
|
||
}
|
||
|
||
// 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<uint, CountryDiplomacyInfo>();
|
||
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<FeelingStrategy> 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<FeelingStrategy>();
|
||
}
|
||
|
||
public CountryDiplomacyInfo(CountryDiplomacyInfo copyData)
|
||
{
|
||
PlayerId = copyData.PlayerId;
|
||
AttackTurn = copyData.AttackTurn;
|
||
DiplomacyState = copyData.DiplomacyState;
|
||
FeelingValue = copyData.FeelingValue;
|
||
FeelingState = copyData.FeelingState;
|
||
FeelingStrategyList= new List<FeelingStrategy>();
|
||
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;
|
||
}
|
||
}
|
||
} |