TH1/Unity/Assets/Scripts/TH1_Logic/Achievement/AchievementCondition.cs
2026-06-12 23:35:09 +08:00

883 lines
27 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年05月13日 星期二 17:05:32
* @Modify:
*/
using System;
using System.Collections.Generic;
using Logic.Pool;
using OPS.Obfuscator.Attribute;
using RuntimeData;
using UnityEngine;
namespace Logic.Achievement
{
public enum AchievementConditionType
{
// 召唤 n 次伟人
TrainGiant,
// 建造 n 次奇观
BuildWonder,
// 奇观属于城市
WonderInCity,
// 奇观上有单位持续 n 回合
UnitOnWonder,
// 周围有 n 个建筑
AroundBuildings,
// 周围有 n 个奇观
AroundWonders,
// 周围有 n 个敌方单位
AroundEnemyUnits,
// 周围有 n 个友方单位
AroundSelfUnits,
// 周围有 n 个特定城市格子
AroundCityGrids,
// n 回合有击杀无伤亡
KillNoAttacked,
// 在地图中央竖线上
InMiddleLine,
// 从上至下第 n 行
InRow,
// 地图规格 n * m
MapSize,
// 夺回奇观城市 n 次
ReclaimWonderCity,
// 属于特定城市
InCity,
// 在 n 个不同城市建造过这个奇观
BuildInDifferentCity,
// 某 职阶 的伟人占领过奇观的拥有城市
OccupyWonderCity,
// 与特定城市通过 n 个 资源连接
ConnectCity,
// n 个不同伟人到过此处
DifferentGiantArrive,
// 间隔回合消灭从海上登陆该奇观的小兵
KillLandTroop,
// 建造 n 回合内信仰翻 n 倍
FaithTimes,
// 周围有 n 个文明的土地(曾经来自)
AroundCivilizationLand,
// 所在城市有 n 个 资源
InCityResources,
// 转换该奇观上的地方单位
ConvertUnit,
// 使用非 某阵营 持续 n 回合达成其余条件
NotCiv,
// 己方特定类型 unit type 在奇观上死亡
UnitTypeDie,
}
[DoNotObfuscateClass]
[Serializable]
public abstract class AchievementConditionBase : ISerializationCallbackReceiver
{
protected static List<GridData> _aroundBuf;
public virtual void OnBeforeSerialize() { }
public virtual void OnAfterDeserialize() { }
public abstract AchievementConditionType GetConditionType();
public abstract void ClearCache();
public abstract bool CheckCondition(AchievementItem item, MapData map);
public abstract void GetProgress(out int current, out int target);
public abstract bool CheckChanged(AchievementConditionBase condition);
public abstract void CopyChange(AchievementConditionBase condition);
// 用于记录回退,所以期望一定是返回 false 从而回退成就所以默认返回true
public virtual bool ReCheckCondition()
{
return true;
}
public virtual void ClearUserData() { }
public virtual void OnTurnStart(MapData map, PlayerData player)
{
}
public virtual void OnTrainUnit(MapData map, PlayerData player, CityData city, UnitData newUnit)
{
}
public virtual void OnBuildWonder(MapData map, PlayerData player, CityData city, GridData grid)
{
}
public virtual void OnKillUnit(MapData map, UnitData origin, UnitData target)
{
}
public virtual void OnUnitMove(MapData map, UnitData unit, GridData gridData)
{
}
public virtual void OnGameEnd(MapData map, bool isWin)
{
}
public virtual string GetConditionDescription()
{
return string.Empty;
}
}
[DoNotObfuscateClass]
[Serializable]
public class TrainGiantCondition : AchievementConditionBase
{
public int TargetCount;
public GiantType TargetGiant;
public int TrainCount;
public TrainGiantCondition()
{
TargetCount = 1;
TrainCount = 0;
TargetGiant = GiantType.None;
}
public override AchievementConditionType GetConditionType()
{
return AchievementConditionType.TrainGiant;
}
public override void OnGameEnd(MapData map, bool isWin)
{
if (!isWin) return;
if (map == null) return;
var player = map.PlayerMap.SelfPlayerData;
if (player == null) return;
if (!player.PlayerHeroData.HasHero(TargetGiant)) return;
TrainCount++;
}
public override void ClearCache()
{
}
public override void ClearUserData()
{
TrainCount = 0;
}
public override bool CheckCondition(AchievementItem item, MapData map)
{
return TrainCount >= TargetCount;
}
public override void GetProgress(out int current, out int target)
{
current = Mathf.Min(TrainCount, TargetCount);
target = TargetCount;
}
public override void CopyChange(AchievementConditionBase condition)
{
var cond = condition as TrainGiantCondition;
if (cond == null) return;
if (TargetGiant != cond.TargetGiant) return;
TrainCount += cond.TrainCount;
}
public override bool ReCheckCondition()
{
return TrainCount >= TargetCount;
}
public override bool CheckChanged(AchievementConditionBase condition)
{
var cond = condition as TrainGiantCondition;
if (cond == null) return true;
TargetGiant = cond.TargetGiant;
TargetCount = cond.TargetCount;
return false;
}
}
[DoNotObfuscateClass]
[Serializable]
public class BuildWonderConditionCondition : AchievementConditionBase
{
public int TargetCount;
public WonderLibrary Wonder;
public int BuildCount;
public BuildWonderConditionCondition()
{
TargetCount = 1;
BuildCount = 0;
Wonder = WonderLibrary.EgyptianRemiliaPEACE;
}
public override AchievementConditionType GetConditionType()
{
return AchievementConditionType.BuildWonder;
}
public override void OnBuildWonder(MapData map, PlayerData player, CityData city, GridData grid)
{
//if (player.Id != map.PlayerMap.SelfPlayerId) return;
//if (grid.Wonder != Wonder) return;
//BuildCount++;
}
public override void OnGameEnd(MapData map, bool isWin)
{
if (!isWin) return;
if (map == null) return;
var player = map.PlayerMap.SelfPlayerData;
if (player == null) return;
if (!player.Wonder.IsWonderLibraryBuilt(Wonder,player)) return;
BuildCount++;
}
public override void ClearCache()
{
}
public override bool CheckCondition(AchievementItem item, MapData map)
{
return BuildCount >= TargetCount;
}
public override void GetProgress(out int current, out int target)
{
current = Mathf.Min(BuildCount, TargetCount);
target = TargetCount;
}
public override void CopyChange(AchievementConditionBase condition)
{
var cond = condition as BuildWonderConditionCondition;
if (cond == null) return;
if (Wonder != cond.Wonder) return;
BuildCount += cond.BuildCount;
}
public override bool CheckChanged(AchievementConditionBase condition)
{
var cond = condition as BuildWonderConditionCondition;
if (cond == null) return true;
Wonder = cond.Wonder;
TargetCount = cond.TargetCount;
return false;
}
}
[DoNotObfuscateClass]
[Serializable]
public class WonderInCityConditionCondition : AchievementConditionBase
{
public WonderLibrary Wonder;
public CityLibrary TargetCity;
public WonderInCityConditionCondition()
{
TargetCity = CityLibrary.Cairo;
}
public override AchievementConditionType GetConditionType()
{
return AchievementConditionType.WonderInCity;
}
public override void ClearCache()
{
}
public override bool CheckCondition(AchievementItem item, MapData map)
{
var cityList = new List<CityData>();
map.GetCityDataListByPlayerId(map.PlayerMap.SelfPlayerId, cityList);
foreach (var city in cityList)
{
if (city.CityInfo != TargetCity) continue;
foreach (var gridId in city.Territory.TerritoryArea)
{
if (!map.GridMap.GetGridDataByGid(gridId, out var gridData)) continue;
if (gridData.Wonder != Wonder) continue;
return true;
}
}
return false;
}
public override void GetProgress(out int current, out int target)
{
current = 0;
target = 1;
}
public override void CopyChange(AchievementConditionBase condition)
{
var cond = condition as WonderInCityConditionCondition;
if (cond == null) return;
if (Wonder != cond.Wonder) return;
}
public override bool CheckChanged(AchievementConditionBase condition)
{
var cond = condition as WonderInCityConditionCondition;
if (cond == null) return true;
Wonder = cond.Wonder;
TargetCity = cond.TargetCity;
return false;
}
}
[DoNotObfuscateClass]
[Serializable]
public class UnitOnWonderConditionCondition : AchievementConditionBase
{
public WonderLibrary Wonder;
public GiantType Giant;
public int TargetTurns;
public uint RecordTurn;
public uint _gridId;
public UnitOnWonderConditionCondition()
{
Wonder = WonderLibrary.EgyptianRemiliaEYE;
Giant = GiantType.None;
TargetTurns = 1;
RecordTurn = 0;
_gridId = 0;
}
public override AchievementConditionType GetConditionType()
{
return AchievementConditionType.UnitOnWonder;
}
public override void OnTurnStart(MapData map, PlayerData player)
{
}
public override void ClearCache()
{
RecordTurn = 0;
}
public override bool CheckCondition(AchievementItem item, MapData map)
{
if (map == null) return false;
if (!map.GridMap.GetGridDataByGid(_gridId, out var gridData))
{
foreach (var grid in map.GridMap.GridList)
{
if (grid.Wonder != Wonder) continue;
gridData = grid;
break;
}
}
if (gridData == null)
{
RecordTurn = map.PlayerMap.SelfPlayerData.Turn;
return false;
}
_gridId = gridData.Id;
if (!gridData.RealUnit(map,out var unitData))
{
RecordTurn = map.PlayerMap.SelfPlayerData.Turn;
return false;
}
if (unitData.UnitFullType.GiantType != Giant)
{
RecordTurn = map.PlayerMap.SelfPlayerData.Turn;
return false;
}
return RecordTurn + TargetTurns <= map.PlayerMap.SelfPlayerData.Turn;
}
public override void GetProgress(out int current, out int target)
{
current = Mathf.Min((int)RecordTurn, TargetTurns);
target = TargetTurns;
}
public override void CopyChange(AchievementConditionBase condition)
{
var cond = condition as UnitOnWonderConditionCondition;
if (cond == null) return;
if (Wonder != cond.Wonder) return;
}
public override bool CheckChanged(AchievementConditionBase condition)
{
var cond = condition as UnitOnWonderConditionCondition;
if (cond == null) return true;
Wonder = cond.Wonder;
Giant = cond.Giant;
TargetTurns = cond.TargetTurns;
return false;
}
}
[DoNotObfuscateClass]
[Serializable]
public class AroundBuildingsConditionCondition : AchievementConditionBase
{
public WonderLibrary Wonder;
public int OffsetX;
public int OffsetY;
public int TargetCount;
public TerrainType Terrain;
public TerrainFeature Feature;
public Vegetation Vegetation;
public ResourceType Resource;
private uint _gridId;
private int _recordCount;
public AroundBuildingsConditionCondition()
{
OffsetX = 1;
OffsetY = 1;
TargetCount = 1;
Terrain = TerrainType.None;
Feature = TerrainFeature.None;
Vegetation = Vegetation.None;
Resource = ResourceType.None;
}
public override AchievementConditionType GetConditionType()
{
return AchievementConditionType.AroundBuildings;
}
public override void ClearCache()
{
}
public override bool CheckCondition(AchievementItem item, MapData map)
{
if (map == null) return false;
_recordCount = 0;
if (!map.GridMap.GetGridDataByGid(_gridId, out var gridData))
{
foreach (var grid in map.GridMap.GridList)
{
if (grid.Wonder != Wonder) continue;
gridData = grid;
break;
}
}
if (gridData == null) return false;
_gridId = gridData.Id;
_aroundBuf ??= new List<GridData>();
_aroundBuf.Clear();
map.GridMap.GetAroundGridData(OffsetX, OffsetY, gridData, _aroundBuf);
foreach (var aroundGrid in _aroundBuf)
{
if (Terrain != TerrainType.None && aroundGrid.Terrain == Terrain) _recordCount++;
if (Feature != TerrainFeature.None && aroundGrid.Feature == Feature) _recordCount++;
if (Vegetation != Vegetation.None && aroundGrid.Vegetation == Vegetation) _recordCount++;
if (Resource != ResourceType.None && aroundGrid.Resource == Resource) _recordCount++;
}
return _recordCount >= TargetCount;
}
public override void GetProgress(out int current, out int target)
{
current = Mathf.Min(_recordCount, TargetCount);
target = TargetCount;
}
public override void CopyChange(AchievementConditionBase condition)
{
var cond = condition as AroundBuildingsConditionCondition;
if (cond == null) return;
}
public override bool CheckChanged(AchievementConditionBase condition)
{
var cond = condition as AroundBuildingsConditionCondition;
if (cond == null) return true;
Wonder = cond.Wonder;
OffsetX = cond.OffsetX;
OffsetY = cond.OffsetY;
TargetCount = cond.TargetCount;
Terrain = cond.Terrain;
Feature = cond.Feature;
Vegetation = cond.Vegetation;
Resource = cond.Resource;
return false;
}
}
[DoNotObfuscateClass]
[Serializable]
public class AroundWondersConditionCondition : AchievementConditionBase
{
public WonderLibrary Wonder;
public WonderLibrary AroundWonder;
public int OffsetX;
public int OffsetY;
public int TargetCount;
private uint _gridId;
private uint _recordCount;
public AroundWondersConditionCondition()
{
OffsetX = 1;
OffsetY = 1;
TargetCount = 1;
}
public override AchievementConditionType GetConditionType()
{
return AchievementConditionType.AroundWonders;
}
public override void ClearCache()
{
}
public override bool CheckCondition(AchievementItem item, MapData map)
{
if (map == null) return false;
_recordCount = 0;
if (!map.GridMap.GetGridDataByGid(_gridId, out var gridData))
{
foreach (var grid in map.GridMap.GridList)
{
if (grid.Wonder != Wonder) continue;
gridData = grid;
break;
}
}
if (gridData == null) return false;
_gridId = gridData.Id;
_aroundBuf ??= new List<GridData>();
_aroundBuf.Clear();
map.GridMap.GetAroundGridData(OffsetX, OffsetY, gridData, _aroundBuf);
foreach (var aroundGrid in _aroundBuf)
{
if (aroundGrid.Wonder == AroundWonder) _recordCount++;
}
return _recordCount >= TargetCount;
}
public override void GetProgress(out int current, out int target)
{
current = Mathf.Min((int)_recordCount, TargetCount);
target = TargetCount;
}
public override void CopyChange(AchievementConditionBase condition)
{
var cond = condition as AroundWondersConditionCondition;
if (cond == null) return;
}
public override bool CheckChanged(AchievementConditionBase condition)
{
var cond = condition as AroundWondersConditionCondition;
if (cond == null) return true;
Wonder = cond.Wonder;
AroundWonder = cond.AroundWonder;
OffsetX = cond.OffsetX;
OffsetY = cond.OffsetY;
TargetCount = cond.TargetCount;
return false;
}
}
[DoNotObfuscateClass]
[Serializable]
public class AroundEnemyUnitsConditionCondition : AchievementConditionBase
{
public WonderLibrary Wonder;
public int TargetCount;
public int OffsetX;
public int OffsetY;
private uint _gridId;
private uint _recordCount;
public AroundEnemyUnitsConditionCondition()
{
OffsetX = 1;
OffsetY = 1;
TargetCount = 1;
}
public override AchievementConditionType GetConditionType()
{
return AchievementConditionType.AroundEnemyUnits;
}
public override void ClearCache()
{
}
public override bool CheckCondition(AchievementItem item, MapData map)
{
if (map == null) return false;
if (!map.GridMap.GetGridDataByGid(_gridId, out var gridData))
{
foreach (var grid in map.GridMap.GridList)
{
if (grid.Wonder != Wonder) continue;
gridData = grid;
break;
}
}
if (gridData == null) return false;
_gridId = gridData.Id;
_aroundBuf ??= new List<GridData>();
_aroundBuf.Clear();
map.GridMap.GetAroundGridData(OffsetX, OffsetY, gridData, _aroundBuf);
_recordCount = 0;
using var pooledSelfUnits = THCollectionPool.GetHashSetHandle<UnitData>(out var selfUnits);
map.GetUnitDataListByPlayerId(map.PlayerMap.SelfPlayerId, selfUnits);
foreach (var aroundGrid in _aroundBuf)
{
if (!aroundGrid.RealUnit(map, out var unit)) continue;
if (selfUnits.Contains(unit)) continue;
_recordCount++;
}
return _recordCount >= TargetCount;
}
public override void GetProgress(out int current, out int target)
{
current = Mathf.Min((int)_recordCount, TargetCount);
target = TargetCount;
}
public override void CopyChange(AchievementConditionBase condition)
{
var cond = condition as AroundEnemyUnitsConditionCondition;
if (cond == null) return;
}
public override bool CheckChanged(AchievementConditionBase condition)
{
var cond = condition as AroundEnemyUnitsConditionCondition;
if (cond == null) return true;
Wonder = cond.Wonder;
TargetCount = cond.TargetCount;
OffsetX = cond.OffsetX;
OffsetY = cond.OffsetY;
return false;
}
}
[DoNotObfuscateClass]
[Serializable]
public class AroundSelfUnitsConditionCondition : AchievementConditionBase
{
public WonderLibrary Wonder;
public int TargetCount;
public int OffsetX;
public int OffsetY;
private uint _gridId;
private uint _recordCount;
public AroundSelfUnitsConditionCondition()
{
OffsetX = 1;
OffsetY = 1;
TargetCount = 1;
}
public override AchievementConditionType GetConditionType()
{
return AchievementConditionType.AroundSelfUnits;
}
public override void ClearCache()
{
}
public override bool CheckCondition(AchievementItem item, MapData map)
{
if (map == null) return false;
if (!map.GridMap.GetGridDataByGid(_gridId, out var gridData))
{
foreach (var grid in map.GridMap.GridList)
{
if (grid.Wonder != Wonder) continue;
gridData = grid;
break;
}
}
if (gridData == null) return false;
_gridId = gridData.Id;
_aroundBuf ??= new List<GridData>();
_aroundBuf.Clear();
map.GridMap.GetAroundGridData(OffsetX, OffsetY, gridData, _aroundBuf);
_recordCount = 0;
using var pooledSelfUnits = THCollectionPool.GetHashSetHandle<UnitData>(out var selfUnits);
map.GetUnitDataListByPlayerId(map.PlayerMap.SelfPlayerId, selfUnits);
foreach (var aroundGrid in _aroundBuf)
{
if (!aroundGrid.RealUnit(map, out var unit)) continue;
if (!selfUnits.Contains(unit)) continue;
_recordCount++;
}
return _recordCount >= TargetCount;
}
public override void GetProgress(out int current, out int target)
{
current = Mathf.Min((int)_recordCount, TargetCount);
target = TargetCount;
}
public override void CopyChange(AchievementConditionBase condition)
{
var cond = condition as AroundSelfUnitsConditionCondition;
if (cond == null) return;
}
public override bool CheckChanged(AchievementConditionBase condition)
{
var cond = condition as AroundSelfUnitsConditionCondition;
if (cond == null) return true;
Wonder = cond.Wonder;
TargetCount = cond.TargetCount;
OffsetX = cond.OffsetX;
OffsetY = cond.OffsetY;
return false;
}
}
[DoNotObfuscateClass]
[Serializable]
public class AroundCityGridsConditionCondition : AchievementConditionBase
{
public WonderLibrary Wonder;
public CityLibrary TargetCity;
public int TargetCount;
public int OffsetX;
public int OffsetY;
private uint _gridId;
private uint _recordCount;
public AroundCityGridsConditionCondition()
{
OffsetX = 1;
OffsetY = 1;
}
public override AchievementConditionType GetConditionType()
{
return AchievementConditionType.AroundCityGrids;
}
public override void ClearCache()
{
}
public override bool CheckCondition(AchievementItem item, MapData map)
{
if (map == null) return false;
if (!map.GridMap.GetGridDataByGid(_gridId, out var gridData))
{
foreach (var grid in map.GridMap.GridList)
{
if (grid.Wonder != Wonder) continue;
gridData = grid;
break;
}
}
if (gridData == null) return false;
_gridId = gridData.Id;
_aroundBuf ??= new List<GridData>();
_aroundBuf.Clear();
map.GridMap.GetAroundGridData(OffsetX, OffsetY, gridData, _aroundBuf);
_recordCount = 0;
foreach (var aroundGrid in _aroundBuf)
{
if (!map.GetCityDataByTerritoryGid(aroundGrid.Id, out var city)) continue;
if (city.CityInfo != TargetCity) continue;
_recordCount++;
}
return _recordCount >= TargetCount;
}
public override void GetProgress(out int current, out int target)
{
current = Mathf.Min((int)_recordCount, TargetCount);
target = TargetCount;
}
public override void CopyChange(AchievementConditionBase condition)
{
var cond = condition as AroundSelfUnitsConditionCondition;
if (cond == null) return;
}
public override bool CheckChanged(AchievementConditionBase condition)
{
var cond = condition as AroundCityGridsConditionCondition;
if (cond == null) return true;
Wonder = cond.Wonder;
TargetCity = cond.TargetCity;
TargetCount = cond.TargetCount;
OffsetX = cond.OffsetX;
OffsetY = cond.OffsetY;
return false;
}
}
}