512 lines
16 KiB
C#
512 lines
16 KiB
C#
/*
|
||
* @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-x,N为总人数
|
||
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-x,N为总人数";
|
||
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-x,N为总人数
|
||
/// </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>
|
||
/// 得分排名 <={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;
|
||
}
|
||
}
|
||
}
|
||
}
|