diff --git a/My project/Assets/Scripts/Data/PlayerData.cs b/My project/Assets/Scripts/Data/PlayerData.cs index 2ef78bcdf..1e6a93fb7 100644 --- a/My project/Assets/Scripts/Data/PlayerData.cs +++ b/My project/Assets/Scripts/Data/PlayerData.cs @@ -8,7 +8,10 @@ using System; using System.Collections.Generic; +using System.Linq; using Logic.Action; +using Logic.AI; +using NUnit.Framework; using Unity.VisualScripting; using UnityEngine; @@ -28,6 +31,7 @@ namespace RuntimeData EYE } + // 奇观状态枚举 public enum WonderState { @@ -39,6 +43,28 @@ namespace RuntimeData } + // 外交关系枚举 + public enum DiplomacyState + { + NoDiplomacy, + Neutral, + League, + War, + LeagueRupture, + } + + + // 好感状态枚举 + public enum FeelingState + { + Trust, + Appreciate, + Indifferent, + Suspicion, + Terrible, + } + + [Serializable] public class PlayerMapData : ISerializationCallbackReceiver { @@ -229,6 +255,7 @@ namespace RuntimeData public List MeetPlayers; public List CurAttackPlayers; public List LastAttackPlayers; + public DiplomacyData DiplomacyData; //用于记录是否死亡,是否要centMessage来宣告死亡信息 public bool DieMark = false; @@ -239,6 +266,7 @@ namespace RuntimeData Sight = new MapSightData(); TechTree = new TechTreeData(); Wonder = new WonderData(); + DiplomacyData = new DiplomacyData(); MeetPlayers = new List(); CurAttackPlayers = new List(); LastAttackPlayers = new List(); @@ -257,6 +285,7 @@ namespace RuntimeData Sight = new MapSightData(); Wonder = new WonderData(); + DiplomacyData = new DiplomacyData(); CurAttackPlayers = new List(); LastAttackPlayers = new List(); MeetPlayers = new List(); @@ -277,6 +306,7 @@ namespace RuntimeData Sight = new MapSightData(copyData.Sight); TechTree = new TechTreeData(copyData.TechTree); Wonder = new WonderData(copyData.Wonder); + DiplomacyData = new DiplomacyData(copyData.DiplomacyData); CurAttackPlayers = new List(); foreach (var id in copyData.CurAttackPlayers) CurAttackPlayers.Add(id); @@ -305,6 +335,7 @@ namespace RuntimeData 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); @@ -358,11 +389,186 @@ namespace RuntimeData 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(); + 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(); + 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; + } + } } } @@ -640,4 +846,125 @@ namespace RuntimeData } } + + + // 主动攻击我的敌人信息 + [Serializable] + public class DiplomacyData : ISerializationCallbackReceiver + { + public List Info; + private Dictionary _infoDict; + + public DiplomacyData() + { + Info = new List(); + } + + public DiplomacyData(DiplomacyData copyData) + { + Info = new List(); + } + + 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; + } + + 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; + } + } } \ No newline at end of file diff --git a/My project/Assets/Scripts/Logic/Action/ActionLogic.cs b/My project/Assets/Scripts/Logic/Action/ActionLogic.cs index f40bb85e1..3ed303e01 100644 --- a/My project/Assets/Scripts/Logic/Action/ActionLogic.cs +++ b/My project/Assets/Scripts/Logic/Action/ActionLogic.cs @@ -2490,7 +2490,7 @@ namespace Logic.Action } } - + // 小兵攻击,目前只用于 AI 的行为 public class UnitAttackAction : ActionLogicBase { diff --git a/My project/Assets/Scripts/Logic/Player/PlayerLogic.cs b/My project/Assets/Scripts/Logic/Player/PlayerLogic.cs index 44011a5f5..ebac2312d 100644 --- a/My project/Assets/Scripts/Logic/Player/PlayerLogic.cs +++ b/My project/Assets/Scripts/Logic/Player/PlayerLogic.cs @@ -870,7 +870,14 @@ namespace Logic } } - + // 主动建立同盟 + public void SetDiplomacyLeague( PlayerData originPlayer, PlayerData targetPlayer, DiplomacyState state) + { + originPlayer.DiplomacyData.GetCountryDiplomacyInfo(targetPlayer.Id, out var player1ToPlayer2); + targetPlayer.DiplomacyData.GetCountryDiplomacyInfo(originPlayer.Id, out var player2ToPlayer1); + player1ToPlayer2.DiplomacyState = state; + player2ToPlayer1.DiplomacyState = state; + } } } diff --git a/My project/Assets/Scripts/Logic/Unit/UnitLogic.cs b/My project/Assets/Scripts/Logic/Unit/UnitLogic.cs index 48448b0e2..aa71148ad 100644 --- a/My project/Assets/Scripts/Logic/Unit/UnitLogic.cs +++ b/My project/Assets/Scripts/Logic/Unit/UnitLogic.cs @@ -209,8 +209,10 @@ namespace Logic if (!mapData.GetCityDataByUnitId(unit2.Id, out var city2)) return false; if (!mapData.GetGridDataByUnitId(unit1.Id, out var grid1)) return false; if (!mapData.GetGridDataByUnitId(unit2.Id, out var grid2)) return false; + Main.PlayerLogic.SetDiplomacyLeague(player1, player2, DiplomacyState.War); player1.CurAttackPlayers.Add(player2.Id); player2.CurAttackPlayers.Add(player1.Id); + player2.AddAttacker(player1.Id); player1.TurnNoAttack = 0; // 计算攻击伤害