2026-05-22 17:15:30 +08:00

512 lines
16 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.Collections.Generic;
using Logic.CrashSight;
using Logic.Multilingual;
using MemoryPack;
using RuntimeData;
namespace TH1_Logic.MatchConfig
{
public enum PlayerTaskType
{
None = 0,
// 持续存活时间>={param1}回合
SurviveOrLoseMatch = 1,
// 场上已经死亡玩家数量+同队存活玩家数量>={param1}但是我存活, -x表示 N-xN为总人数
OtherDie = 2,
// 得分排名 <={param1}
ScoreWin = 3,
// 得分>={param1}
ScoreValue = 4,
// 拥有城市数量>={param1}
HasCityCount = 5,
// 拥有UnitType={param4}的单位{param1}个
HasUnitCount = 6,
// 拥有等级>={param1}的城市数量>={param2}个
HasLevelCityCount = 7,
// 拥有金币>={param1}
HasCoinCount = 8,
// 本阵营累计探索迷雾>={param1}
HasExploreCount = 9,
}
[MemoryPackable]
public partial class PlayerTaskInfo
{
public PlayerTaskType TaskType;
public bool IsSettlement;
public bool IsSuccess;
public int Param1;
public int Param2;
public int Param3;
public UnitType Param4;
public int Param1Cur;
public int Param2Cur;
public int Param3Cur;
// 串行教程的任务顺序。同一 PlayerSettlementInfo 下,相同 Order 的任务并行判定,
// 必须当前 Order 全部完成后才会激活 Order+1。默认 0 = 全部并行(保持老行为)。
// ⚠️ MemoryPack 字段必须追加在末尾,不可插入中间。
public int Order;
// 自定义任务描述。空字符串 = 使用 PlayerTaskData.PlayerTaskDesc 默认描述。
// 支持 {param1_cur}/{param1_tar}/{param2_cur}/{param2_tar}/{param3_cur}/{param3_tar}/{param4_tar} 占位符。
// ⚠️ MemoryPack 字段必须追加在末尾。
[MultilingualField] public string CustomDesc;
// 任务完成后要解除的关卡限制。仅 Tutor 模式生效,其他结算类型忽略。
// 完成时会从 MapData.MapConfig.MatchLimits 移除对应限制,然后清空本列表(消耗式,幂等)。
// ⚠️ MemoryPack 字段必须追加在末尾。
public List<MatchLimitType> UnlockLimits;
// 自定义任务 Hint 描述(鼠标悬停显示的详细说明)。空字符串 = 使用 PlayerTaskData.HintDesc 默认。
// ⚠️ MemoryPack 字段必须追加在末尾。
[MultilingualField] public string CustomHint;
[MemoryPackConstructor]
public PlayerTaskInfo()
{
}
public void Init(PlayerTaskInfo taskInfo)
{
TaskType = taskInfo.TaskType;
Param1 = taskInfo.Param1;
Param2 = taskInfo.Param2;
Param3 = taskInfo.Param3;
Param4 = taskInfo.Param4;
Order = taskInfo.Order;
CustomDesc = taskInfo.CustomDesc;
CustomHint = taskInfo.CustomHint;
UnlockLimits = taskInfo.UnlockLimits == null
? null
: new List<MatchLimitType>(taskInfo.UnlockLimits);
IsSettlement = false;
IsSuccess = false;
}
public PlayerTaskInfo(PlayerTaskInfo copyData)
{
TaskType = copyData.TaskType;
IsSettlement = copyData.IsSettlement;
Param1 = copyData.Param1;
Param2 = copyData.Param2;
Param3 = copyData.Param3;
Param4 = copyData.Param4;
Order = copyData.Order;
CustomDesc = copyData.CustomDesc;
CustomHint = copyData.CustomHint;
UnlockLimits = copyData.UnlockLimits == null
? null
: new List<MatchLimitType>(copyData.UnlockLimits);
}
public void DeepCopy(PlayerTaskInfo copyData)
{
TaskType = copyData.TaskType;
IsSettlement = copyData.IsSettlement;
Param1 = copyData.Param1;
Param2 = copyData.Param2;
Param3 = copyData.Param3;
Param4 = copyData.Param4;
Order = copyData.Order;
CustomDesc = copyData.CustomDesc;
CustomHint = copyData.CustomHint;
if (copyData.UnlockLimits == null)
{
UnlockLimits = null;
}
else
{
UnlockLimits ??= new List<MatchLimitType>();
UnlockLimits.Clear();
UnlockLimits.AddRange(copyData.UnlockLimits);
}
}
}
public class PlayerTaskLogicFactory
{
private static Dictionary<PlayerTaskType, PlayerTaskLogicBase> _logicDict = new Dictionary<PlayerTaskType, PlayerTaskLogicBase>()
{
{ PlayerTaskType.SurviveOrLoseMatch, new SurviveOrLosePlayerTaskLogic() },
{ PlayerTaskType.OtherDie, new OtherDiePlayerTaskLogic() },
{ PlayerTaskType.ScoreWin, new ScoreWinTaskLogic() },
{ PlayerTaskType.ScoreValue, new ScoreValueTaskLogic() },
{ PlayerTaskType.HasCityCount, new HasCityCountTaskLogic() },
{ PlayerTaskType.HasUnitCount, new HasUnitCountTaskLogic() },
{ PlayerTaskType.HasLevelCityCount, new HasLevelCityCountTaskLogic() },
{ PlayerTaskType.HasCoinCount, new HasCoinCountTaskLogic() },
{ PlayerTaskType.HasExploreCount, new HasExploreCountTaskLogic() },
};
public static string GetPlayerTaskTypeDesc(PlayerTaskType taskType)
{
switch (taskType)
{
case PlayerTaskType.None:
return "无";
case PlayerTaskType.SurviveOrLoseMatch:
return "持续存活时间>={param1}回合";
case PlayerTaskType.OtherDie:
return "场上已经死亡玩家数量+同队存活玩家数量>={param1}但是我存活, -x表示 N-xN为总人数";
case PlayerTaskType.ScoreWin:
return "得分排名 <={param1}";
case PlayerTaskType.ScoreValue:
return "得分>={param1}";
case PlayerTaskType.HasCityCount:
return "拥有城市数量>={param1}";
case PlayerTaskType.HasUnitCount:
return "拥有UnitType={param4}的单位{param1}个";
case PlayerTaskType.HasLevelCityCount:
return "拥有等级>={param1}的城市数量>={param2}个";
case PlayerTaskType.HasCoinCount:
return "拥有金币>={param1}";
case PlayerTaskType.HasExploreCount:
return "本阵营累计探索迷雾>={param1}";
default:
return "未知任务类型";
}
}
public static void RefreshPlayerTaskInfo(MapData map, PlayerData player, PlayerTaskInfo info)
{
if (!_logicDict.TryGetValue(info.TaskType, out var logic))
{
LogSystem.LogError($"RefreshPlayerTaskInfo Error TaskType:{info.TaskType} No Logic");
return;
}
logic.Refresh(map, player, info);
}
}
public abstract class PlayerTaskLogicBase
{
public abstract PlayerTaskType GetPlayerTaskType();
public abstract void Refresh(MapData map, PlayerData player, PlayerTaskInfo info);
}
/// <summary>
/// 持续存活时间>={param1}回合
/// </summary>
public class SurviveOrLosePlayerTaskLogic : PlayerTaskLogicBase
{
public override PlayerTaskType GetPlayerTaskType()
{
return PlayerTaskType.SurviveOrLoseMatch;
}
public override void Refresh(MapData map, PlayerData player, PlayerTaskInfo info)
{
if (info.IsSettlement) return;
if (!player.IsSurvival && player.Turn <= info.Param1)
{
info.IsSettlement = true;
info.IsSuccess = false;
return;
}
info.Param1Cur = (int)player.Turn;
if (player.IsSurvival && player.Turn >= info.Param1)
{
info.IsSettlement = true;
info.IsSuccess = true;
}
}
}
/// <summary>
/// 场上已经死亡玩家数量+同队存活玩家数量>={param1}但是我存活, -x表示 N-xN为总人数
/// </summary>
public class OtherDiePlayerTaskLogic : PlayerTaskLogicBase
{
public override PlayerTaskType GetPlayerTaskType()
{
return PlayerTaskType.OtherDie;
}
public override void Refresh(MapData map, PlayerData player, PlayerTaskInfo info)
{
if (info.IsSettlement) return;
if (!player.IsSurvival)
{
info.IsSettlement = true;
info.IsSuccess = false;
return;
}
var playerList = map.PlayerMap.PlayerDataList;
var dieCount = 0;
var aliveTeammateCount = 0;
foreach (var p in playerList)
{
if (!p.IsSurvival) dieCount++;
else if (p.Id != player.Id
&& map.MapConfig != null
&& map.MapConfig.ArePlayersInSameTeam(player.Id, p.Id))
{
aliveTeammateCount++;
}
}
var settlementCount = dieCount + aliveTeammateCount;
info.Param1Cur = settlementCount;
var targetCount = info.Param1 >= 0 ? info.Param1 : playerList.Count + info.Param1;
if (settlementCount >= targetCount)
{
info.IsSettlement = true;
info.IsSuccess = true;
}
}
}
/// <summary>
/// 得分排名 &lt;={param1}
/// </summary>
public class ScoreWinTaskLogic : PlayerTaskLogicBase
{
public override PlayerTaskType GetPlayerTaskType()
{
return PlayerTaskType.ScoreWin;
}
public override void Refresh(MapData map, PlayerData player, PlayerTaskInfo info)
{
if (info.IsSettlement) return;
if (!player.IsSurvival)
{
info.IsSettlement = true;
info.IsSuccess = false;
return;
}
if (player.Turn < 5) return;
int rank = 1;
int playerScore = player.PlayerScore;
foreach (var p in map.PlayerMap.PlayerDataList)
{
if (p.Id != player.Id && p.PlayerScore > playerScore) rank++;
}
info.Param1Cur = rank;
if (rank <= info.Param1)
{
info.IsSettlement = true;
info.IsSuccess = true;
}
}
}
/// <summary>
/// 得分>={param1}
/// </summary>
public class ScoreValueTaskLogic : PlayerTaskLogicBase
{
public override PlayerTaskType GetPlayerTaskType()
{
return PlayerTaskType.ScoreValue;
}
public override void Refresh(MapData map, PlayerData player, PlayerTaskInfo info)
{
if (info.IsSettlement) return;
if (!player.IsSurvival)
{
info.IsSettlement = true;
info.IsSuccess = false;
return;
}
info.Param1Cur = player.PlayerScore;
if (player.PlayerScore >= info.Param1)
{
info.IsSettlement = true;
info.IsSuccess = true;
}
}
}
/// <summary>
/// 拥有城市数量>={param1}
/// </summary>
public class HasCityCountTaskLogic : PlayerTaskLogicBase
{
public override PlayerTaskType GetPlayerTaskType()
{
return PlayerTaskType.HasCityCount;
}
public override void Refresh(MapData map, PlayerData player, PlayerTaskInfo info)
{
if (info.IsSettlement) return;
if (!player.IsSurvival)
{
info.IsSettlement = true;
info.IsSuccess = false;
return;
}
int cityCount = map.GetCityCount(player.Id);
info.Param1Cur = cityCount;
if (cityCount >= info.Param1)
{
info.IsSettlement = true;
info.IsSuccess = true;
}
}
}
/// <summary>
/// 拥有UnitType={param1}的单位{param2}个
/// </summary>
public class HasUnitCountTaskLogic : PlayerTaskLogicBase
{
public override PlayerTaskType GetPlayerTaskType()
{
return PlayerTaskType.HasUnitCount;
}
public override void Refresh(MapData map, PlayerData player, PlayerTaskInfo info)
{
if (info.IsSettlement) return;
if (!player.IsSurvival)
{
info.IsSettlement = true;
info.IsSuccess = false;
return;
}
var unitList = new List<UnitData>();
map.GetUnitDataListByPlayerId(player.Id, unitList);
int count = 0;
foreach (var unit in unitList)
{
if (unit.UnitType == info.Param4) count++;
}
info.Param1Cur = count;
if (count >= info.Param1)
{
info.IsSettlement = true;
info.IsSuccess = true;
}
}
}
/// <summary>
/// 拥有等级>={param1}的城市数量>={param2}个
/// </summary>
public class HasLevelCityCountTaskLogic : PlayerTaskLogicBase
{
public override PlayerTaskType GetPlayerTaskType()
{
return PlayerTaskType.HasLevelCityCount;
}
public override void Refresh(MapData map, PlayerData player, PlayerTaskInfo info)
{
if (info.IsSettlement) return;
if (!player.IsSurvival)
{
info.IsSettlement = true;
info.IsSuccess = false;
return;
}
var cityList = new List<CityData>();
map.GetCityDataListByPlayerId(player.Id, cityList);
int count = 0;
foreach (var city in cityList)
{
if (city.Level >= info.Param1) count++;
}
info.Param2Cur = count;
if (count >= info.Param2)
{
info.IsSettlement = true;
info.IsSuccess = true;
}
}
}
/// <summary>
/// 拥有金币>={param1}
/// </summary>
public class HasCoinCountTaskLogic : PlayerTaskLogicBase
{
public override PlayerTaskType GetPlayerTaskType()
{
return PlayerTaskType.HasCoinCount;
}
public override void Refresh(MapData map, PlayerData player, PlayerTaskInfo info)
{
if (info.IsSettlement) return;
if (!player.IsSurvival)
{
info.IsSettlement = true;
info.IsSuccess = false;
return;
}
info.Param1Cur = player.PlayerCoin;
if (player.PlayerCoin >= info.Param1)
{
info.IsSettlement = true;
info.IsSuccess = true;
}
}
}
/// <summary>
/// 本阵营累计探索迷雾>={param1}
/// </summary>
public class HasExploreCountTaskLogic : PlayerTaskLogicBase
{
public override PlayerTaskType GetPlayerTaskType()
{
return PlayerTaskType.HasExploreCount;
}
public override void Refresh(MapData map, PlayerData player, PlayerTaskInfo info)
{
if (info.IsSettlement) return;
if (!player.IsSurvival)
{
info.IsSettlement = true;
info.IsSuccess = false;
return;
}
int exploreCount = player.Sight.SightGidSet.Count;
info.Param1Cur = exploreCount;
if (exploreCount >= info.Param1)
{
info.IsSettlement = true;
info.IsSuccess = true;
}
}
}
}