271 lines
8.9 KiB
C#
271 lines
8.9 KiB
C#
/*
|
||
* @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;
|
||
}
|
||
}
|
||
} |