Compare commits
5 Commits
main
...
wuwenbo/2v
| Author | SHA1 | Date | |
|---|---|---|---|
| 319307fa84 | |||
| ecd8255b72 | |||
| e77831bdc3 | |||
| d51777bdbe | |||
| ec04df6514 |
@ -61,7 +61,7 @@ namespace RuntimeData
|
||||
public MatchSettlementType MatchSettlement;
|
||||
public List<PlayerSettlementInfo> PlayerSettlements;
|
||||
|
||||
// 单机用
|
||||
// 兼容旧数据(已弃用)
|
||||
public uint selfCivId;
|
||||
public uint selfForceId;
|
||||
|
||||
@ -83,6 +83,12 @@ namespace RuntimeData
|
||||
// 水域类型,默认为 Pangea
|
||||
public Logic.MapWaterType WaterType = Logic.MapWaterType.Pangea;
|
||||
|
||||
// 单机用:真人玩家选择的 PlayerInfos 索引
|
||||
public uint SelfPlayerInfoIndex;
|
||||
// 存储着基于 Index 的玩家战前数据,包括真人和 AI
|
||||
public List<PlayerInfo> PlayerInfos;
|
||||
|
||||
|
||||
[MemoryPackConstructor]
|
||||
public MapConfig()
|
||||
{
|
||||
@ -90,6 +96,7 @@ namespace RuntimeData
|
||||
PlayerSettlements = new List<PlayerSettlementInfo>();
|
||||
_memberCivs = new Dictionary<ulong, MemberCiv>();
|
||||
MatchLimits = new List<MatchLimitType>();
|
||||
PlayerInfos = new List<PlayerInfo>();
|
||||
}
|
||||
|
||||
public MapConfig(uint width, uint height, uint playerCount,uint civId, uint forceId, AIDifficult aiDiff = AIDifficult.LUNATIC)
|
||||
@ -98,10 +105,18 @@ namespace RuntimeData
|
||||
Height = height;
|
||||
PlayerCount = playerCount;
|
||||
AIDiff = aiDiff;
|
||||
SelfPlayerInfoIndex = 0;
|
||||
selfCivId = civId;
|
||||
selfForceId = forceId;
|
||||
MultiCivs = new List<MemberCiv>();
|
||||
_memberCivs = new Dictionary<ulong, MemberCiv>();
|
||||
PlayerInfos = new List<PlayerInfo>();
|
||||
EnsurePlayerInfosCount();
|
||||
if (GetPlayerInfoByIndex(SelfPlayerInfoIndex, out var selfInfo))
|
||||
{
|
||||
selfInfo.CivId = civId;
|
||||
selfInfo.ForceId = forceId;
|
||||
}
|
||||
}
|
||||
|
||||
// MemoryPack 反序列化之后的后处理
|
||||
@ -112,26 +127,136 @@ namespace RuntimeData
|
||||
// 旧存档兼容:WaterType 字段不存在时默认为 Pangea
|
||||
if (!System.Enum.IsDefined(typeof(Logic.MapWaterType), WaterType))
|
||||
WaterType = Logic.MapWaterType.Pangea;
|
||||
MultiCivs ??= new List<MemberCiv>();
|
||||
PlayerInfos ??= new List<PlayerInfo>();
|
||||
_memberCivs ??= new Dictionary<ulong, MemberCiv>();
|
||||
RefreshMultiCivsDict();
|
||||
EnsurePlayerInfosCount();
|
||||
NormalizeMemberPlayerInfoIndexes();
|
||||
}
|
||||
|
||||
public void EnsurePlayerInfosCount()
|
||||
{
|
||||
PlayerInfos ??= new List<PlayerInfo>();
|
||||
if (PlayerCount == 0)
|
||||
{
|
||||
PlayerInfos.Clear();
|
||||
SelfPlayerInfoIndex = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < PlayerCount; i++)
|
||||
{
|
||||
if (i >= PlayerInfos.Count)
|
||||
{
|
||||
PlayerInfos.Add(new PlayerInfo { Index = (uint)i, CivId = (uint)i, ForceId = (uint)i });
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerInfos[i] ??= new PlayerInfo();
|
||||
PlayerInfos[i].Index = (uint)i;
|
||||
}
|
||||
}
|
||||
|
||||
if (PlayerInfos.Count > PlayerCount)
|
||||
{
|
||||
PlayerInfos.RemoveRange((int)PlayerCount, PlayerInfos.Count - (int)PlayerCount);
|
||||
}
|
||||
|
||||
if (SelfPlayerInfoIndex >= PlayerCount) SelfPlayerInfoIndex = 0;
|
||||
|
||||
// 旧数据迁移:若旧字段有效,补到 SelfPlayerInfoIndex 对应的 PlayerInfo
|
||||
if (GetPlayerInfoByIndex(SelfPlayerInfoIndex, out var selfInfo))
|
||||
{
|
||||
if (selfCivId != 0 || selfForceId != 0)
|
||||
{
|
||||
selfInfo.CivId = selfCivId;
|
||||
selfInfo.ForceId = selfForceId;
|
||||
}
|
||||
}
|
||||
|
||||
// 旧联机数据迁移:MemberCiv 可能还带着 Civ/Force,迁移到其索引对应 PlayerInfo
|
||||
if (MultiCivs == null) return;
|
||||
foreach (var member in MultiCivs)
|
||||
{
|
||||
if (member == null) continue;
|
||||
if (member.PlayerInfoIndex >= PlayerCount) continue;
|
||||
if (member.CivId == 0 && member.ForceId == 0) continue;
|
||||
if (!GetPlayerInfoByIndex(member.PlayerInfoIndex, out var info)) continue;
|
||||
info.CivId = member.CivId;
|
||||
info.ForceId = member.ForceId;
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetPlayerInfoByIndex(uint index, out PlayerInfo info)
|
||||
{
|
||||
info = null;
|
||||
EnsurePlayerInfosCount();
|
||||
if (index >= PlayerInfos.Count) return false;
|
||||
info = PlayerInfos[(int)index];
|
||||
info ??= new PlayerInfo { Index = index, CivId = index, ForceId = index };
|
||||
PlayerInfos[(int)index] = info;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void NormalizeMemberPlayerInfoIndexes()
|
||||
{
|
||||
if (MultiCivs == null || MultiCivs.Count == 0) return;
|
||||
EnsurePlayerInfosCount();
|
||||
if (PlayerCount == 0) return;
|
||||
|
||||
var used = new HashSet<uint>();
|
||||
for (int i = 0; i < MultiCivs.Count; i++)
|
||||
{
|
||||
var member = MultiCivs[i];
|
||||
if (member == null) continue;
|
||||
if (member.PlayerInfoIndex < PlayerCount && !used.Contains(member.PlayerInfoIndex))
|
||||
{
|
||||
used.Add(member.PlayerInfoIndex);
|
||||
continue;
|
||||
}
|
||||
member.PlayerInfoIndex = uint.MaxValue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MultiCivs.Count; i++)
|
||||
{
|
||||
var member = MultiCivs[i];
|
||||
if (member == null || member.PlayerInfoIndex != uint.MaxValue) continue;
|
||||
uint fallback = 0;
|
||||
while (fallback < PlayerCount && used.Contains(fallback)) fallback++;
|
||||
if (fallback >= PlayerCount)
|
||||
{
|
||||
member.PlayerInfoIndex = 0;
|
||||
continue;
|
||||
}
|
||||
member.PlayerInfoIndex = fallback;
|
||||
used.Add(fallback);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 根据房间成员信息更新 mapconfig 信息
|
||||
public void UpdateLobbyMember(Dictionary<ulong, MemberInfo> memberInfos)
|
||||
{
|
||||
// 先剔除已离开 lobby 的成员,避免 MultiCivs 留下幽灵占位:
|
||||
// 旧版只 Add 不 Remove,会导致大厅 nP 跳号(1P/4P/5P/6P),
|
||||
// 以及开战时给离线幽灵创 PlayerData、占用 PlayerCount 名额、AI 补位变少。
|
||||
MultiCivs.RemoveAll(mc => !memberInfos.ContainsKey(mc.MemberId));
|
||||
EnsurePlayerInfosCount();
|
||||
RefreshMultiCivsDict();
|
||||
for (int i = MultiCivs.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (memberInfos.ContainsKey(MultiCivs[i].MemberId)) continue;
|
||||
_memberCivs.Remove(MultiCivs[i].MemberId);
|
||||
MultiCivs.RemoveAt(i);
|
||||
}
|
||||
RefreshMultiCivsDict();
|
||||
foreach (var kv in memberInfos)
|
||||
{
|
||||
if (_memberCivs.ContainsKey(kv.Key)) continue;
|
||||
var civ = new MemberCiv();
|
||||
civ.MemberId = kv.Key;
|
||||
civ.CivId = 0;
|
||||
civ.ForceId = 0;
|
||||
civ.PlayerInfoIndex = uint.MaxValue;
|
||||
MultiCivs.Add(civ);
|
||||
}
|
||||
RefreshMultiCivsDict();
|
||||
NormalizeMemberPlayerInfoIndexes();
|
||||
}
|
||||
|
||||
// 内部刷新
|
||||
@ -161,14 +286,31 @@ namespace RuntimeData
|
||||
return;
|
||||
}
|
||||
|
||||
EnsurePlayerInfosCount();
|
||||
uint newIndex = civ.PlayerInfoIndex;
|
||||
if (newIndex >= PlayerCount)
|
||||
{
|
||||
// 兼容旧消息:按 Civ/Force 找索引
|
||||
for (uint i = 0; i < PlayerCount; i++)
|
||||
{
|
||||
if (!GetPlayerInfoByIndex(i, out var info)) continue;
|
||||
if (info.CivId != civ.CivId || info.ForceId != civ.ForceId) continue;
|
||||
newIndex = i;
|
||||
break;
|
||||
}
|
||||
if (newIndex >= PlayerCount) newIndex = 0;
|
||||
}
|
||||
|
||||
foreach (var memberCiv in MultiCivs)
|
||||
{
|
||||
if (memberCiv.MemberId != civ.MemberId) continue;
|
||||
memberCiv.CivId = civ.CivId;
|
||||
memberCiv.ForceId = civ.ForceId;
|
||||
memberCiv.PlayerInfoIndex = newIndex;
|
||||
NormalizeMemberPlayerInfoIndexes();
|
||||
return;
|
||||
}
|
||||
civ.PlayerInfoIndex = newIndex;
|
||||
MultiCivs.Add(civ);
|
||||
NormalizeMemberPlayerInfoIndexes();
|
||||
}
|
||||
|
||||
// 主从端一致的本地数据检测
|
||||
@ -190,18 +332,17 @@ namespace RuntimeData
|
||||
// 从 MapData 中重绑定 MemberCiv 的 Player 信息
|
||||
public bool ReBindPlayerInfoFromMapData(MapData mapData)
|
||||
{
|
||||
EnsurePlayerInfosCount();
|
||||
RefreshMultiCivsDict();
|
||||
NormalizeMemberPlayerInfoIndexes();
|
||||
if (mapData.Net.Mode == NetMode.Single)
|
||||
{
|
||||
foreach (var player in mapData.PlayerMap.PlayerDataList)
|
||||
{
|
||||
if (player.PlayerCivId != selfCivId || player.PlayerForceId != selfForceId) continue;
|
||||
mapData.PlayerMap.SelfPlayerId = player.Id;
|
||||
}
|
||||
if (mapData.PlayerMap.SelfPlayerId == 0)
|
||||
if (SelfPlayerInfoIndex < mapData.PlayerMap.PlayerDataList.Count)
|
||||
mapData.PlayerMap.SelfPlayerId = mapData.PlayerMap.PlayerDataList[(int)SelfPlayerInfoIndex].Id;
|
||||
else
|
||||
{
|
||||
LogSystem.LogError($"单机模式指定地图中找不到指定的阵营信息, 启动游戏失败, " +
|
||||
$"地图 ID : {Id} 文明 ID : {selfCivId} 势力 ID : {selfForceId}");
|
||||
$"地图 ID : {Id} 玩家索引 : {SelfPlayerInfoIndex}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -210,16 +351,13 @@ namespace RuntimeData
|
||||
{
|
||||
foreach (var member in MultiCivs)
|
||||
{
|
||||
foreach (var player in mapData.PlayerMap.PlayerDataList)
|
||||
{
|
||||
if (player.PlayerCivId != member.CivId || player.PlayerForceId != member.ForceId) continue;
|
||||
member.PlayerId = player.PlayerCivId;
|
||||
}
|
||||
if (member.PlayerInfoIndex >= mapData.PlayerMap.PlayerDataList.Count) member.PlayerId = 0;
|
||||
else member.PlayerId = mapData.PlayerMap.PlayerDataList[(int)member.PlayerInfoIndex].Id;
|
||||
|
||||
if (member.PlayerId == 0)
|
||||
{
|
||||
LogSystem.LogError($"联机模式指定地图中找不到指定的阵营信息, 启动游戏失败, " +
|
||||
$"地图 ID : {Id} 文明 ID : {member.CivId} 势力 ID : {member.ForceId}");
|
||||
$"地图 ID : {Id} 玩家索引 : {member.PlayerInfoIndex}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -273,6 +411,17 @@ namespace RuntimeData
|
||||
{
|
||||
public ulong MemberId;
|
||||
public uint PlayerId;
|
||||
// 兼容旧数据(已弃用,真实值来自 PlayerInfos[PlayerInfoIndex])
|
||||
public uint CivId;
|
||||
public uint ForceId;
|
||||
public uint PlayerInfoIndex;
|
||||
}
|
||||
|
||||
|
||||
[MemoryPackable]
|
||||
public partial class PlayerInfo
|
||||
{
|
||||
public uint Index;
|
||||
public uint CivId;
|
||||
public uint ForceId;
|
||||
}
|
||||
@ -1778,7 +1927,7 @@ namespace RuntimeData
|
||||
{
|
||||
foreach (var player in PlayerMap.PlayerDataList)
|
||||
{
|
||||
if (MatchSettlement.IsWin(player.Id)) return player;
|
||||
if (MatchSettlement.IsWin(this, player.Id)) return player;
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -1787,7 +1936,7 @@ namespace RuntimeData
|
||||
// 游戏是否结束
|
||||
public bool CheckIfGameEnd(out bool isWin)
|
||||
{
|
||||
isWin = MatchSettlement.IsWin(PlayerMap.SelfPlayerId);
|
||||
isWin = MatchSettlement.IsWin(this, PlayerMap.SelfPlayerId);
|
||||
return MatchSettlement.IsFinished;
|
||||
}
|
||||
|
||||
|
||||
@ -152,6 +152,7 @@ namespace RuntimeData
|
||||
public int RandomSeed;
|
||||
private System.Random _random;
|
||||
private static readonly ArrayBufferWriter<byte> _bufferWriter = new ArrayBufferWriter<byte>(64 * 1024);
|
||||
private List<ulong> _tmpMemberIdListBuffer;
|
||||
|
||||
// 玩家开始时间记录
|
||||
[MemoryPackIgnore]
|
||||
@ -206,16 +207,35 @@ namespace RuntimeData
|
||||
if (Mode != NetMode.Multi) return;
|
||||
if (LobbyManager.Instance.Lobby.IsLobbyOwner())
|
||||
{
|
||||
// 创建 Player 的时候会分配一次 PlayerId,这里直接使用
|
||||
mapData.MapConfig.EnsurePlayerInfosCount();
|
||||
var memberIds = LobbyManager.Instance.Lobby.GetAllMemberIds();
|
||||
|
||||
// 移除不在当前房间的映射
|
||||
_tmpMemberIdListBuffer ??= new List<ulong>();
|
||||
_tmpMemberIdListBuffer.Clear();
|
||||
foreach (var kv in Players)
|
||||
{
|
||||
if (memberIds.Contains(kv.Key)) continue;
|
||||
_tmpMemberIdListBuffer.Add(kv.Key);
|
||||
}
|
||||
foreach (var memberId in _tmpMemberIdListBuffer) Players.Remove(memberId);
|
||||
|
||||
// 创建 Player 的时候会分配一次 PlayerId,这里直接使用 index -> PlayerId
|
||||
foreach (var memberCiv in mapData.MapConfig.MultiCivs)
|
||||
{
|
||||
if (memberCiv.PlayerInfoIndex >= mapData.PlayerMap.PlayerDataList.Count)
|
||||
{
|
||||
memberCiv.PlayerId = 0;
|
||||
continue;
|
||||
}
|
||||
memberCiv.PlayerId = mapData.PlayerMap.PlayerDataList[(int)memberCiv.PlayerInfoIndex].Id;
|
||||
if (memberCiv.PlayerId == 0) continue;
|
||||
if (Players.ContainsKey(memberCiv.MemberId)) continue;
|
||||
if (!memberIds.Contains(memberCiv.MemberId)) continue;
|
||||
Players[memberCiv.MemberId] = memberCiv.PlayerId;
|
||||
}
|
||||
|
||||
// 添加其他人
|
||||
foreach (var memberId in LobbyManager.Instance.Lobby.GetAllMemberIds())
|
||||
foreach (var memberId in memberIds)
|
||||
{
|
||||
if (Players.ContainsKey(memberId)) continue;
|
||||
foreach (var player in mapData.PlayerMap.PlayerDataList)
|
||||
|
||||
@ -118,47 +118,53 @@ namespace RuntimeData
|
||||
|
||||
if (netMode == NetMode.Single)
|
||||
{
|
||||
map.MapConfig.EnsurePlayerInfosCount();
|
||||
for (int i = 0; i < map.MapConfig.PlayerCount; i++)
|
||||
{
|
||||
PlayerData player;
|
||||
//处理player到底是谁的问题。目前临时使用的方案,今后要改。目前civ一定=force,所以可以这么做
|
||||
if (i == 0)
|
||||
player = new PlayerData(map.MapConfig.selfCivId,map.MapConfig.selfForceId,idGenerator);
|
||||
else if (map.MapConfig.selfCivId == i)
|
||||
player = new PlayerData((uint)0,(uint)0,idGenerator);
|
||||
else
|
||||
player = new PlayerData((uint)i,(uint)i,idGenerator);
|
||||
uint civId = (uint)i;
|
||||
uint forceId = (uint)i;
|
||||
if (map.MapConfig.GetPlayerInfoByIndex((uint)i, out var playerInfo))
|
||||
{
|
||||
civId = playerInfo.CivId;
|
||||
forceId = playerInfo.ForceId;
|
||||
}
|
||||
PlayerData player = new PlayerData(civId, forceId, idGenerator);
|
||||
PlayerDataList.Add(player);
|
||||
_playerDataDict[player.Id] = player;
|
||||
}
|
||||
}
|
||||
if (netMode == NetMode.Multi)
|
||||
{
|
||||
// 这里 civList 要包含所有 civId (civId = civEnum - 1,目前 17 个 civ → 0..16)
|
||||
var civList = new List<uint>();
|
||||
for (int i = 0; i < 17; i++) civList.Add((uint)i);
|
||||
map.MapConfig.EnsurePlayerInfosCount();
|
||||
for (int i = 0; i < map.MapConfig.PlayerCount; i++)
|
||||
{
|
||||
uint civId = (uint)i;
|
||||
uint forceId = (uint)i;
|
||||
if (map.MapConfig.GetPlayerInfoByIndex((uint)i, out var playerInfo))
|
||||
{
|
||||
civId = playerInfo.CivId;
|
||||
forceId = playerInfo.ForceId;
|
||||
}
|
||||
var player = new PlayerData(civId, forceId, idGenerator);
|
||||
PlayerDataList.Add(player);
|
||||
_playerDataDict[player.Id] = player;
|
||||
}
|
||||
|
||||
foreach (var multiCiv in map.MapConfig.MultiCivs)
|
||||
{
|
||||
var player = new PlayerData(multiCiv.CivId, multiCiv.CivId, idGenerator);
|
||||
PlayerDataList.Add(player);
|
||||
_playerDataDict[player.Id] = player;
|
||||
civList.Remove(multiCiv.CivId);
|
||||
multiCiv.PlayerId = player.Id;
|
||||
}
|
||||
|
||||
for (int i = map.MapConfig.MultiCivs.Count; i < map.MapConfig.PlayerCount; i++)
|
||||
{
|
||||
int idx = UnityEngine.Random.Range(0, civList.Count);//map.Net.GetRandom().Next
|
||||
var civId = civList[idx];
|
||||
var player = new PlayerData(civId, civId, idGenerator);
|
||||
PlayerDataList.Add(player);
|
||||
_playerDataDict[player.Id] = player;
|
||||
civList.RemoveAt(idx);
|
||||
if (multiCiv.PlayerInfoIndex >= PlayerDataList.Count)
|
||||
{
|
||||
multiCiv.PlayerId = 0;
|
||||
continue;
|
||||
}
|
||||
multiCiv.PlayerId = PlayerDataList[(int)multiCiv.PlayerInfoIndex].Id;
|
||||
}
|
||||
}
|
||||
|
||||
SelfPlayerId = PlayerDataList[0].Id;
|
||||
if (netMode == NetMode.Single && map.MapConfig.SelfPlayerInfoIndex < PlayerDataList.Count)
|
||||
SelfPlayerId = PlayerDataList[(int)map.MapConfig.SelfPlayerInfoIndex].Id;
|
||||
else
|
||||
SelfPlayerId = PlayerDataList[0].Id;
|
||||
foreach (var self in PlayerDataList)
|
||||
{
|
||||
foreach (var target in PlayerDataList)
|
||||
|
||||
@ -224,6 +224,7 @@ namespace TH1_Logic.Action
|
||||
//Step #6 处理break结盟
|
||||
if (_actionId.PlayerActionType == PlayerActionType.BreakAlly)
|
||||
{
|
||||
if (dipInfo.IsTeammate || dipInfo2.IsTeammate) return false;
|
||||
//Step #1 设置双方的外交状态为背盟
|
||||
dipInfo.DiplomacyState = DiplomacyState.LeagueRupture;
|
||||
dipInfo2.DiplomacyState = DiplomacyState.LeagueRupture;
|
||||
@ -352,10 +353,11 @@ namespace TH1_Logic.Action
|
||||
if (_actionId.PlayerActionType == PlayerActionType.BreakAlly)
|
||||
{
|
||||
actionParams.PlayerData.GetCountryDiplomacyInfo(actionParams.TargetPlayerData.Id, out var dipInfo);
|
||||
actionParams.TargetPlayerData.GetCountryDiplomacyInfo(actionParams.PlayerData.Id,out var dipInfo2);
|
||||
if (dipInfo.IsTeammate || dipInfo2.IsTeammate) return false;
|
||||
//如果没有结盟 return
|
||||
if (dipInfo.DiplomacyState != DiplomacyState.League) return false;
|
||||
//如果对方率先break,return
|
||||
actionParams.TargetPlayerData.GetCountryDiplomacyInfo(actionParams.PlayerData.Id,out var dipInfo2);
|
||||
if (dipInfo2.DiplomacyState == DiplomacyState.LeagueRupture) return false;
|
||||
return true;
|
||||
}
|
||||
@ -446,10 +448,11 @@ namespace TH1_Logic.Action
|
||||
//Step #8 判断能否break结盟
|
||||
{
|
||||
actionParams.PlayerData.GetCountryDiplomacyInfo(actionParams.TargetPlayerData.Id, out var dipInfo);
|
||||
actionParams.TargetPlayerData.GetCountryDiplomacyInfo(actionParams.PlayerData.Id,out var dipInfo2);
|
||||
if (dipInfo.IsTeammate || dipInfo2.IsTeammate) return false;
|
||||
//如果没有结盟 return
|
||||
if (dipInfo.DiplomacyState != DiplomacyState.League) return false;
|
||||
//如果对方率先break,return
|
||||
actionParams.TargetPlayerData.GetCountryDiplomacyInfo(actionParams.PlayerData.Id,out var dipInfo2);
|
||||
if (dipInfo2.DiplomacyState == DiplomacyState.LeagueRupture) return false;
|
||||
return true;
|
||||
}
|
||||
@ -488,6 +491,7 @@ namespace TH1_Logic.Action
|
||||
//Step #3 计算breakAlly按钮的情况
|
||||
if (_actionId.PlayerActionType == PlayerActionType.BreakAlly)
|
||||
{
|
||||
if (dipInfo.IsTeammate || dipInfo2.IsTeammate) return ActionShowState.Unavailable;
|
||||
return ActionShowState.Available;
|
||||
}
|
||||
|
||||
|
||||
@ -107,6 +107,7 @@ namespace Logic.Editor
|
||||
private void OnGUIMapConfig(MapConfig mapConfig)
|
||||
{
|
||||
EditorGUILayout.BeginVertical();
|
||||
mapConfig.EnsurePlayerInfosCount();
|
||||
|
||||
// 基础配置
|
||||
if (InspectorUtils.InspectorButtonWithTextWidth("删除关卡"))
|
||||
@ -135,7 +136,9 @@ namespace Logic.Editor
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
InspectorUtils.InspectorTextWidthRich("玩家数量:");
|
||||
var oldPlayerCount = mapConfig.PlayerCount;
|
||||
mapConfig.PlayerCount = (uint)EditorGUILayout.IntField((int)mapConfig.PlayerCount, GUILayout.Width(200));
|
||||
if (oldPlayerCount != mapConfig.PlayerCount) mapConfig.EnsurePlayerInfosCount();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
@ -159,13 +162,19 @@ namespace Logic.Editor
|
||||
// 单机配置
|
||||
InspectorUtils.InspectorTextWidthRich("<b>单机配置</b>");
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
InspectorUtils.InspectorTextWidthRich("文明ID:");
|
||||
mapConfig.selfCivId = (uint)EditorGUILayout.IntField((int)mapConfig.selfCivId, GUILayout.Width(200));
|
||||
InspectorUtils.InspectorTextWidthRich("单机玩家索引:");
|
||||
mapConfig.SelfPlayerInfoIndex = (uint)EditorGUILayout.IntField((int)mapConfig.SelfPlayerInfoIndex, GUILayout.Width(200));
|
||||
if (mapConfig.PlayerCount > 0 && mapConfig.SelfPlayerInfoIndex >= mapConfig.PlayerCount)
|
||||
mapConfig.SelfPlayerInfoIndex = mapConfig.PlayerCount - 1;
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
InspectorUtils.InspectorTextWidthRich("势力ID:");
|
||||
mapConfig.selfForceId = (uint)EditorGUILayout.IntField((int)mapConfig.selfForceId, GUILayout.Width(200));
|
||||
InspectorUtils.InspectorTextWidthRich("单机玩家阵营(Civ/Force):");
|
||||
if (mapConfig.GetPlayerInfoByIndex(mapConfig.SelfPlayerInfoIndex, out var selfInfo))
|
||||
{
|
||||
selfInfo.CivId = (uint)EditorGUILayout.IntField((int)selfInfo.CivId, GUILayout.Width(95));
|
||||
selfInfo.ForceId = (uint)EditorGUILayout.IntField((int)selfInfo.ForceId, GUILayout.Width(95));
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
@ -146,11 +146,13 @@ namespace Logic.Editor
|
||||
var civ = Main.Instance.MapConfig.GetMemberCiv(selfMemberId);
|
||||
if (civ != null)
|
||||
{
|
||||
Main.Instance.MapConfig.GetPlayerInfoByIndex(civ.PlayerInfoIndex, out var info);
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (InspectorUtils.InspectorButtonWithTextWidth("改1")) civ.CivId = 1;
|
||||
if (InspectorUtils.InspectorButtonWithTextWidth("改2")) civ.CivId = 2;
|
||||
if (InspectorUtils.InspectorButtonWithTextWidth("改3")) civ.CivId = 3;
|
||||
if (InspectorUtils.InspectorButtonWithTextWidth("改4")) civ.CivId = 4;
|
||||
InspectorUtils.InspectorTextWidthRich($"Idx:{civ.PlayerInfoIndex} Civ:{info?.CivId ?? 0} Force:{info?.ForceId ?? 0}");
|
||||
if (InspectorUtils.InspectorButtonWithTextWidth("改Idx0")) { civ.PlayerInfoIndex = 0; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
|
||||
if (InspectorUtils.InspectorButtonWithTextWidth("改Idx1")) { civ.PlayerInfoIndex = 1; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
|
||||
if (InspectorUtils.InspectorButtonWithTextWidth("改Idx2")) { civ.PlayerInfoIndex = 2; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
|
||||
if (InspectorUtils.InspectorButtonWithTextWidth("改Idx3")) { civ.PlayerInfoIndex = 3; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
@ -11,6 +11,7 @@ using Logic.CrashSight;
|
||||
using MemoryPack;
|
||||
using RuntimeData;
|
||||
using TH1_Logic.Collect;
|
||||
using TH1_Logic.Core;
|
||||
|
||||
|
||||
namespace TH1_Logic.MatchConfig
|
||||
@ -56,11 +57,31 @@ namespace TH1_Logic.MatchConfig
|
||||
}
|
||||
|
||||
public bool IsWin(uint id)
|
||||
{
|
||||
return IsWin(Main.MapData, id);
|
||||
}
|
||||
|
||||
public bool IsWin(MapData map, uint id)
|
||||
{
|
||||
if (!IsFinished) return false;
|
||||
var settlementGroup = PlayerSettlements.GetValueOrDefault(id);
|
||||
if (settlementGroup == null) return false;
|
||||
return settlementGroup.IsWin;
|
||||
if (settlementGroup != null && settlementGroup.IsWin) return true;
|
||||
|
||||
if (map == null) return false;
|
||||
if (!map.PlayerMap.GetPlayerDataByPlayerID(id, out var selfPlayer)) return false;
|
||||
|
||||
foreach (var kv in PlayerSettlements)
|
||||
{
|
||||
if (kv.Key == id) continue;
|
||||
if (kv.Value == null || !kv.Value.IsWin) continue;
|
||||
if (!map.PlayerMap.GetPlayerDataByPlayerID(kv.Key, out var teammatePlayer)) continue;
|
||||
if (!selfPlayer.GetCountryDiplomacyInfo(teammatePlayer.Id, out var selfToTeammateDip)) continue;
|
||||
if (!teammatePlayer.GetCountryDiplomacyInfo(selfPlayer.Id, out var teammateToSelfDip)) continue;
|
||||
if (!selfToTeammateDip.IsTeammate && !teammateToSelfDip.IsTeammate) continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public MatchSettlementInfo(MatchSettlementInfo copyData)
|
||||
@ -416,7 +437,6 @@ namespace TH1_Logic.MatchConfig
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 偶现 bug 兜底:玩家明明已经满足"应当结束"的客观条件,但 task 链路因为某种运行时累积态没把
|
||||
/// PlayerSettlementGroup 翻成 IsSettlement,导致游戏一直能下一回合。已知"退出再读档"可恢复。
|
||||
|
||||
@ -29,6 +29,8 @@ namespace Logic
|
||||
//player[pid]解雇unit[uid]
|
||||
public int UpdateSight_LogicView(MapData mapData, PlayerData playerData, List<uint> gidList,bool viewNextFrame,float duration);
|
||||
//unit[uid]在grid[tpos]的位置,为player[pid]更新了视野情况
|
||||
bool SetTeammateAndLeague(MapData mapData, PlayerData playerA, PlayerData playerB, bool isTeammate);
|
||||
//设置双方队友关系;当 isTeammate=true 时同步设为结盟,并通过首都周围视野触发双向 meet
|
||||
|
||||
//-------tech相关操作-------
|
||||
//返回player[pid]的tid科技是否被锁了
|
||||
|
||||
@ -1696,12 +1696,48 @@ namespace Logic
|
||||
}
|
||||
}
|
||||
|
||||
// 设置双方队友关系;当 isTeammate=true 时同步设为结盟,并通过首都周围视野触发双向 meet
|
||||
public bool SetTeammateAndLeague(MapData map, PlayerData playerA, PlayerData playerB, bool isTeammate)
|
||||
{
|
||||
if (map == null || playerA == null || playerB == null) return false;
|
||||
if (playerA.Id == playerB.Id) return false;
|
||||
if (!playerA.GetCountryDiplomacyInfo(playerB.Id, out var playerAToB)) return false;
|
||||
if (!playerB.GetCountryDiplomacyInfo(playerA.Id, out var playerBToA)) return false;
|
||||
|
||||
playerAToB.IsTeammate = isTeammate;
|
||||
playerBToA.IsTeammate = isTeammate;
|
||||
|
||||
if (!isTeammate) return true;
|
||||
|
||||
playerAToB.DiplomacyState = DiplomacyState.League;
|
||||
playerBToA.DiplomacyState = DiplomacyState.League;
|
||||
playerAToB.IsLeagueRequest = false;
|
||||
playerBToA.IsLeagueRequest = false;
|
||||
playerAToB.IsLeagueRupture = false;
|
||||
playerBToA.IsLeagueRupture = false;
|
||||
|
||||
if (map.GetCapitalCityDataByPlayerId(playerB.Id, out var playerBCapital)
|
||||
&& map.GetGridDataByCityId(playerBCapital.Id, out var playerBCapitalGrid))
|
||||
{
|
||||
UpdateSight_LogicView(map, playerA, map.GridMap.GetAroundGridIdList(1, playerBCapitalGrid, true));
|
||||
}
|
||||
|
||||
if (map.GetCapitalCityDataByPlayerId(playerA.Id, out var playerACapital)
|
||||
&& map.GetGridDataByCityId(playerACapital.Id, out var playerACapitalGrid))
|
||||
{
|
||||
UpdateSight_LogicView(map, playerB, map.GridMap.GetAroundGridIdList(1, playerACapitalGrid, true));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 设置外交关系
|
||||
public void SetDiplomacyLeague(MapData map, PlayerData originPlayer, PlayerData targetPlayer, DiplomacyState state)
|
||||
{
|
||||
if (!originPlayer.GetCountryDiplomacyInfo(targetPlayer.Id, out var player1ToPlayer2)) return;
|
||||
|
||||
if (!targetPlayer.GetCountryDiplomacyInfo(originPlayer.Id, out var player2ToPlayer1)) return;
|
||||
if (state == DiplomacyState.War && (player1ToPlayer2.IsTeammate || player2ToPlayer1.IsTeammate)) return;
|
||||
player1ToPlayer2.DiplomacyState = state;
|
||||
player2ToPlayer1.DiplomacyState = state;
|
||||
if (state == DiplomacyState.War)
|
||||
|
||||
@ -161,7 +161,12 @@ namespace TH1_Logic.Steam
|
||||
}
|
||||
|
||||
var data = new ChangeCivMessage();
|
||||
data.Civ = memberCiv;
|
||||
data.Civ = new MemberCiv
|
||||
{
|
||||
MemberId = memberCiv.MemberId,
|
||||
PlayerInfoIndex = memberCiv.PlayerInfoIndex,
|
||||
PlayerId = memberCiv.PlayerId
|
||||
};
|
||||
SendMessage(data);
|
||||
}
|
||||
|
||||
|
||||
@ -121,11 +121,13 @@ namespace TH1_Logic.Steam
|
||||
var civ = Main.Instance.MapConfig.GetMemberCiv(selfMemberId);
|
||||
if (civ != null)
|
||||
{
|
||||
Main.Instance.MapConfig.GetPlayerInfoByIndex(civ.PlayerInfoIndex, out var info);
|
||||
GUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("改1")) civ.CivId = 1;
|
||||
if (GUILayout.Button("改2")) civ.CivId = 2;
|
||||
if (GUILayout.Button("改3")) civ.CivId = 3;
|
||||
if (GUILayout.Button("改4")) civ.CivId = 4;
|
||||
GUILayout.Label($"Idx:{civ.PlayerInfoIndex} Civ:{info?.CivId ?? 0} Force:{info?.ForceId ?? 0}");
|
||||
if (GUILayout.Button("改Idx0")) { civ.PlayerInfoIndex = 0; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
|
||||
if (GUILayout.Button("改Idx1")) { civ.PlayerInfoIndex = 1; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
|
||||
if (GUILayout.Button("改Idx2")) { civ.PlayerInfoIndex = 2; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
|
||||
if (GUILayout.Button("改Idx3")) { civ.PlayerInfoIndex = 3; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,6 +268,10 @@ namespace Logic
|
||||
&& mapData.GetPlayerDataByUnitId(unitData.Id, out var player1)
|
||||
&& player1.Id != player2.Id)
|
||||
{
|
||||
if (player1.GetCountryDiplomacyInfo(player2.Id, out var player1ToPlayer2)
|
||||
&& player2.GetCountryDiplomacyInfo(player1.Id, out var player2ToPlayer1)
|
||||
&& (player1ToPlayer2.IsTeammate || player2ToPlayer1.IsTeammate))
|
||||
return true;
|
||||
player2.AddAttacker(player1.Id);
|
||||
Main.PlayerLogic.SetDiplomacyLeague(mapData, player1, player2, DiplomacyState.War);
|
||||
}
|
||||
@ -515,11 +519,17 @@ namespace Logic
|
||||
|
||||
if (type is DamageType.ActiveAttack or DamageType.FollowAttack or DamageType.Splash or DamageType.True)
|
||||
{
|
||||
Main.PlayerLogic.SetDiplomacyLeague(mapData,player1, player2, DiplomacyState.War);
|
||||
player1.CurAttackPlayers.Add(player2.Id);
|
||||
player2.CurAttackPlayers.Add(player1.Id);
|
||||
player2.AddAttacker(player1.Id);
|
||||
player1.TurnNoAttack = 0;
|
||||
bool isTeammate = player1.GetCountryDiplomacyInfo(player2.Id, out var player1ToPlayer2)
|
||||
&& player2.GetCountryDiplomacyInfo(player1.Id, out var player2ToPlayer1)
|
||||
&& (player1ToPlayer2.IsTeammate || player2ToPlayer1.IsTeammate);
|
||||
if (!isTeammate)
|
||||
{
|
||||
Main.PlayerLogic.SetDiplomacyLeague(mapData,player1, player2, DiplomacyState.War);
|
||||
player1.CurAttackPlayers.Add(player2.Id);
|
||||
player2.CurAttackPlayers.Add(player1.Id);
|
||||
player2.AddAttacker(player1.Id);
|
||||
player1.TurnNoAttack = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Step #4 Moment Process
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user