TH1/Unity/Assets/Scripts/TH1_Logic/MatchConfig/PlayerSettlementInfo.cs
2026-05-12 13:05:44 +08:00

271 lines
8.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @Author: 白哉
* @Description:
* @Date: 2025年09月05日 星期五 15:09:09
* @Modify:
*/
using System;
using System.Collections.Generic;
using Logic.CrashSight;
using MemoryPack;
using RuntimeData;
namespace TH1_Logic.MatchConfig
{
public enum PlayerSettlementType
{
None = 0,
AllSuccessOrFailure = 1,
OneSuccessOrFailure = 2,
}
[MemoryPackable]
public partial class PlayerSettlementGroup
{
public bool IsWin;
public bool IsSettlement;
public List<PlayerSettlementInfo> Settlements;
[MemoryPackConstructor]
public PlayerSettlementGroup()
{
Settlements = new List<PlayerSettlementInfo>();
}
public void Init(List<PlayerSettlementInfo> settlements)
{
Settlements ??= new List<PlayerSettlementInfo>();
Settlements.Clear();
foreach (var settlement in settlements)
{
var newSettlement = new PlayerSettlementInfo(settlement);
newSettlement.Init(settlement);
Settlements.Add(newSettlement);
}
}
public PlayerSettlementGroup(PlayerSettlementGroup copyData)
{
IsSettlement = copyData.IsSettlement;
IsWin = copyData.IsWin;
Settlements = new List<PlayerSettlementInfo>();
for (int i = 0; i < copyData.Settlements.Count; i++)
{
Settlements.Add(new PlayerSettlementInfo(copyData.Settlements[i]));
}
}
public void DeepCopy(PlayerSettlementGroup copyData)
{
IsSettlement = copyData.IsSettlement;
IsWin = copyData.IsWin;
Settlements ??= new List<PlayerSettlementInfo>();
Settlements.Clear();
for (int i = 0; i < copyData.Settlements.Count; i++)
{
Settlements.Add(new PlayerSettlementInfo(copyData.Settlements[i]));
}
}
public static void RefreshPlayerSettlementGroup(MapData map, PlayerData player, PlayerSettlementGroup info)
{
if (info.IsSettlement) return;
foreach (var settlement in info.Settlements)
{
PlayerSettlementLogicFactory.RefreshPlayerSettlementInfo(map, player, settlement);
if (!settlement.IsSettlement) continue;
info.IsSettlement = true;
info.IsWin = settlement.IsWin;
return;
}
}
}
[MemoryPackable]
public partial class PlayerSettlementInfo
{
public PlayerSettlementType SettlementType;
public bool IsSettlement;
public bool IsWin;
public List<PlayerTaskInfo> Tasks;
[MemoryPackConstructor]
public PlayerSettlementInfo()
{
Tasks = new List<PlayerTaskInfo>();
IsSettlement = false;
IsWin = false;
}
public void Init(PlayerSettlementInfo settlement)
{
SettlementType = settlement.SettlementType;
IsSettlement = false;
IsWin = false;
Tasks ??= new List<PlayerTaskInfo>();
Tasks.Clear();
foreach (var task in settlement.Tasks)
{
var newTask = new PlayerTaskInfo();
newTask.Init(task);
Tasks.Add(newTask);
}
}
public PlayerSettlementInfo(PlayerSettlementInfo copyData)
{
SettlementType = copyData.SettlementType;
IsSettlement = copyData.IsSettlement;
IsWin = copyData.IsWin;
Tasks = new List<PlayerTaskInfo>(copyData.Tasks);
for (int i = 0; i < copyData.Tasks.Count; i++)
{
Tasks.Add(new PlayerTaskInfo(copyData.Tasks[i]));
}
}
public void DeepCopy(PlayerSettlementInfo copyData)
{
SettlementType = copyData.SettlementType;
IsSettlement = copyData.IsSettlement;
IsWin = copyData.IsWin;
for (int i = 0; i < copyData.Tasks.Count; i++)
{
var copyTask = copyData.Tasks[i];
if (i >= Tasks.Count)
{
var task = new PlayerTaskInfo(copyTask);
Tasks.Add(task);
}
else Tasks[i].DeepCopy(copyTask);
}
for (int i = Tasks.Count - 1; i >= copyData.Tasks.Count; i--)
{
Tasks.RemoveAt(i);
}
}
}
public class PlayerSettlementLogicFactory
{
private static Dictionary<PlayerSettlementType, IPlayerSettlement> _logicDict = new Dictionary<PlayerSettlementType, IPlayerSettlement>()
{
{ PlayerSettlementType.AllSuccessOrFailure, new AllSuccessOrFailureSettlement() },
{ PlayerSettlementType.OneSuccessOrFailure, new OneSuccessOrFailureSettlement() },
};
public static void RefreshPlayerSettlementInfo(MapData map, PlayerData player, PlayerSettlementInfo info)
{
if (!_logicDict.TryGetValue(info.SettlementType, out var logic))
{
LogSystem.LogError($"RefreshPlayerSettlementInfo Error TaskType:{info.SettlementType} No Logic");
return;
}
// 串行任务支持:只刷新"当前激活波次"的任务(未完成任务中最小 Order
// Order 全部为 0 时退化为并行,保持老行为。
int activeOrder = GetActiveOrder(info);
foreach (var task in info.Tasks)
{
if (task.Order != activeOrder) continue;
PlayerTaskLogicFactory.RefreshPlayerTaskInfo(map, player, task);
}
logic.Refresh(map, player, info);
}
/// <summary>
/// 当前激活波次 = 所有未完成任务中最小的 Order。
/// 全部完成时返回 int.MaxValue不再激活任何任务
/// </summary>
public static int GetActiveOrder(PlayerSettlementInfo info)
{
int active = int.MaxValue;
foreach (var task in info.Tasks)
{
if (task.IsSettlement) continue;
if (task.Order < active) active = task.Order;
}
return active;
}
}
public abstract class IPlayerSettlement
{
public abstract PlayerSettlementType GetSettlementType();
public abstract void Refresh(MapData map, PlayerData player, PlayerSettlementInfo info);
}
public class AllSuccessOrFailureSettlement : IPlayerSettlement
{
public override PlayerSettlementType GetSettlementType()
{
return PlayerSettlementType.AllSuccessOrFailure;
}
public override void Refresh(MapData map, PlayerData player, PlayerSettlementInfo info)
{
if (info.IsSettlement) return;
// 串行任务只刷新当前激活波次。Order 全 0 时等价于并行刷新所有任务。
int activeOrder = PlayerSettlementLogicFactory.GetActiveOrder(info);
foreach (var task in info.Tasks)
{
if (task.Order != activeOrder) continue;
PlayerTaskLogicFactory.RefreshPlayerTaskInfo(map, player, task);
}
// 失败立即结算;成功必须所有任务(所有波次)都 IsSettlement+IsSuccess。
bool allDone = true;
bool oneFailure = false;
foreach (var task in info.Tasks)
{
if (!task.IsSettlement) allDone = false;
if (task.IsSettlement && !task.IsSuccess) oneFailure = true;
}
info.IsSettlement = oneFailure || allDone;
info.IsWin = !oneFailure;
}
}
public class OneSuccessOrFailureSettlement : IPlayerSettlement
{
public override PlayerSettlementType GetSettlementType()
{
return PlayerSettlementType.OneSuccessOrFailure;
}
public override void Refresh(MapData map, PlayerData player, PlayerSettlementInfo info)
{
if (info.IsSettlement) return;
int activeOrder = PlayerSettlementLogicFactory.GetActiveOrder(info);
foreach (var task in info.Tasks)
{
if (task.Order != activeOrder) continue;
PlayerTaskLogicFactory.RefreshPlayerTaskInfo(map, player, task);
}
bool allDone = true;
bool oneSuccess = false;
foreach (var task in info.Tasks)
{
if (!task.IsSettlement) allDone = false;
if (task.IsSettlement && task.IsSuccess) oneSuccess = true;
}
info.IsSettlement = oneSuccess || allDone;
info.IsWin = oneSuccess;
}
}
}