/* * @Author: 白哉 * @Description: * @Date: 2025年09月05日 星期五 15:09:36 * @Modify: */ using System.Collections.Generic; using Logic; using Logic.CrashSight; using Logic.Skill; using MemoryPack; using NLog.Targets; using NUnit.Framework; using RuntimeData; using TH1_Logic.Core; using UnityEngine; namespace TH1_Logic.HeroTask { public enum HeroTaskContentType { // 累计承受伤害 AccumulateDamageTaken, // 累计造成伤害 AccumulateDamageDealt, // 累计杀人 AccumulateKills, // 累计产生(自身或他人)治疗 AccumulateHealing, // 累计开启遗迹 AccumulateRelicsOpened, // 累计探索新地块 AccumulateAreasExplored, // 累计占领新城市 AccumulateCitiesCaptured, // 单位X 给任何单位增加N次技能A的层数,X的该计数+N AddSkillStacks, // 单位X 的技能A 生效时(接口,技能自定义),则该计数变化(技能自定义) SkillActivation, // 累计获得金钱(目前是tewi专用) TewiAddCoin, // 满足条件的Skill总共掉层X次,Skill 属于 一个特定的List SkillDropLevels, // 遇到X 个其他玩家 (这里X = 50% * N 下取整,N=本局玩家总数) MeetOtherPlayers, // 施加X次 将一个grid AddSpType(RemiliaGrid) AddSpType, // 累计获得金币 AddCoin, // 拥有{param1}项科技(除了none) GetTech, // 生产{param1}个UnitFullType={param2}的单位 TrainUnit, // UnitFullType.UnitType={param1}的单位完成{param2}次击杀 UnitKills, // SanaeDevine技能投出{param1}次大吉 SanaeDivineGreat, // 造成{param1}点溅射伤害 SplashDamage, // 场上拥有{param1}技能的单位死亡{param2}个 UnitDeathWithSkill, // 指定小兵累计探索新地块 TargetTypeAreasExplored, // 累计开启遗迹{param1}个 (和之前的差别是,之前是当前英雄累计开启遗迹) AccumulateRelicsOpenedIncludeOthers, // 累计占领他人城市{param1}个或者占领村庄{param2}个 AccumulateCaptureOtherCitiesOrVillages, // 累计承受伤害和造成伤害 AccumulateDamageTakenAndDealt, } [MemoryPackable] [MemoryPackUnion(1, typeof(HeroTaskContentAccumulateDamageTaken))] [MemoryPackUnion(2, typeof(HeroTaskContentAccumulateDamageDealt))] [MemoryPackUnion(3, typeof(HeroTaskContentAccumulateKills))] [MemoryPackUnion(4, typeof(HeroTaskContentAccumulateHealing))] [MemoryPackUnion(5, typeof(HeroTaskContentAccumulateRelicsOpened))] [MemoryPackUnion(6, typeof(HeroTaskContentAccumulateAreasExplored))] [MemoryPackUnion(7, typeof(HeroTaskContentAccumulateCitiesCaptured))] [MemoryPackUnion(8, typeof(HeroTaskContentAddSkillStacks))] [MemoryPackUnion(9, typeof(HeroTaskContentSkillActivation))] [MemoryPackUnion(10, typeof(HeroTaskContentTewiAddCoin))] [MemoryPackUnion(11, typeof(HeroTaskContentSkillDropLevels))] [MemoryPackUnion(12, typeof(HeroTaskContentMeetOtherPlayers))] [MemoryPackUnion(13, typeof(HeroTaskContentAddSpType))] [MemoryPackUnion(14, typeof(HeroTaskContentAddCoin))] [MemoryPackUnion(15, typeof(HeroTaskContentGetTech))] [MemoryPackUnion(16, typeof(HeroTaskContentTrainUnit))] [MemoryPackUnion(17, typeof(HeroTaskContentUnitKills))] [MemoryPackUnion(18, typeof(HeroTaskContentSanaeDivineGreat))] [MemoryPackUnion(19, typeof(HeroTaskContentSplashDamage))] [MemoryPackUnion(20, typeof(HeroTaskContentUnitDeathWithSkill))] [MemoryPackUnion(21, typeof(HeroTaskContentTargetTypeAreasExplored))] [MemoryPackUnion(22, typeof(HeroTaskContentTargetAccumulateRelicsOpenedIncludeOthers))] [MemoryPackUnion(23, typeof(HeroTaskContentAccumulateCaptureOtherCitiesOrVillages))] [MemoryPackUnion(24, typeof(HeroTaskContentAccumulateDamageTakenAndDealt))] public abstract partial class HeroTaskContentBase { public bool IsSelf; public uint Level; public uint TargetLevel; public SkillType SkillType; public GridSpType SpType; public List UnitFullTypes; public List TargetTypes; public List SkillTypeList; public bool IsForceFinished; public abstract HeroTaskContentType GetContentType(); [MemoryPackConstructor] public HeroTaskContentBase() { IsSelf = true; Level = 0; TargetLevel = 1; IsForceFinished = false; UnitFullTypes = new List(); SkillTypeList = new List(); TargetTypes = new List(); } public virtual string LevelShowString() { return Level.ToString(); } public virtual string TargetLevelShowString() { return TargetLevel.ToString(); } public abstract HeroTaskContentBase GetCopyHeroTaskContent(); public virtual void ForceFinish() { IsForceFinished = true; } public virtual bool CheckFinished(MapData map, PlayerData self) { return IsForceFinished || Level >= TargetLevel; } public virtual void OnTaskInit(MapData mapData,PlayerData self) { } public virtual void OnTewiCoinAdd(MapData mapData, uint value) { } public virtual void OnAddCoin(uint value) { } // 一层生命周期 public virtual void OnDamageOther(MapData mapData, SettlementInfo info) { } public virtual void OnDamaged(MapData mapData, SettlementInfo info) { } // 二层生命周期 public virtual void OnPlayerDamageOther(MapData mapData, SettlementInfo info) { } public virtual void OnPlayerDamaged(MapData mapData, SettlementInfo info) { } // 三层生命周期 public virtual void OnAnyDamageOther(MapData mapData, SettlementInfo info) { } public virtual void OnAnyDamaged(MapData mapData, SettlementInfo info) { } public virtual void OnHealthReturn(MapData mapData, int realValue,int value) { } public virtual void OnTreasure(MapData mapData) { } public virtual void OnPlayerTreasure(MapData mapData) { } public virtual void OnCaptureCity(MapData mapData) { } public virtual void OnPlayerCaptureCity(MapData mapData) { } public virtual void OnCaptureVillage(MapData mapData) { } public virtual void OnPlayerCaptureVillage(MapData mapData) { } public virtual void OnExploredGrids(MapData mapData, UnitData unit, int count) { } public virtual void OnAnyExploredGrids(MapData mapData, UnitData unit, int count) { } public virtual void OnAddSkillLevels(MapData mapData, SkillType skillType, uint addLevels) { } public virtual void OnReduceSkillLevels(MapData mapData, SkillType skillType, uint reduceLevels) { } public virtual void OnSkillActivation(MapData mapData, SkillType skillType, uint addLevels) { } public virtual int GetFinishCost() { if (Level >= TargetLevel) return 0; if (Level == TargetLevel) return 20; return ((int)(1f * (TargetLevel - Level) / TargetLevel / 0.2f) + 1) * 3 + 5; } public virtual void OnAddSpType(MapData mapData, GridSpType spType) { } public virtual void OnMeetOtherPlayers(MapData mapData, PlayerData self) { } public virtual void OnTechGet(PlayerData self) { } public virtual void OnTrainUnit(MapData mapData, PlayerData self, UnitData unit) { } public virtual void OnTransformUnit(MapData mapData, PlayerData self, UnitData unit) { } public virtual void OnSanaeDevine(MapData mapdata, PlayerData self, SanaeDivineType type) { } } [MemoryPackable] public partial class HeroTaskContentAccumulateDamageTaken : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.AccumulateDamageTaken; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentAccumulateDamageTaken(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; return newContent; } public override void OnDamaged(MapData mapData, SettlementInfo info) { Level += (uint)info.HealthReduceValue; } } [MemoryPackable] public partial class HeroTaskContentAccumulateDamageDealt : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.AccumulateDamageDealt; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentAccumulateDamageDealt(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; return newContent; } public override void OnDamageOther(MapData mapData, SettlementInfo info) { Level += (uint)info.HealthReduceValue; } } [MemoryPackable] public partial class HeroTaskContentAccumulateDamageTakenAndDealt : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.AccumulateDamageTakenAndDealt; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentAccumulateDamageTakenAndDealt(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; return newContent; } public override void OnDamaged(MapData mapData, SettlementInfo info) { Level += (uint)info.HealthReduceValue; } public override void OnDamageOther(MapData mapData, SettlementInfo info) { Level += (uint)info.HealthReduceValue; } } [MemoryPackable] public partial class HeroTaskContentAccumulateKills : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.AccumulateKills; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentAccumulateKills(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; return newContent; } public override void OnDamageOther(MapData mapData, SettlementInfo info) { if (info.IsKill && info.DamageType != DamageType.KillSelf) Level++; } } [MemoryPackable] public partial class HeroTaskContentAccumulateHealing : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.AccumulateHealing; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentAccumulateHealing(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; return newContent; } public override void OnHealthReturn(MapData mapData, int realValue,int value) { Level += (uint)realValue; } } [MemoryPackable] public partial class HeroTaskContentAccumulateRelicsOpened : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.AccumulateRelicsOpened; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentAccumulateRelicsOpened(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; return newContent; } public override void OnTreasure(MapData mapData) { Level++; } } [MemoryPackable] public partial class HeroTaskContentAccumulateAreasExplored : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.AccumulateAreasExplored; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentAccumulateAreasExplored(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; return newContent; } public override void OnExploredGrids(MapData mapData, UnitData unit, int count) { Level += (uint)count; } } [MemoryPackable] public partial class HeroTaskContentAccumulateCitiesCaptured : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.AccumulateCitiesCaptured; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentAccumulateCitiesCaptured(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; return newContent; } public override void OnCaptureCity(MapData mapData) { Level++; } } [MemoryPackable] public partial class HeroTaskContentAddSkillStacks : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.AddSkillStacks; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentAddSkillStacks(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; newContent.SkillType = SkillType; return newContent; } public override void OnAddSkillLevels(MapData mapData, SkillType skillType, uint addLevels) { if (skillType != SkillType) return; Level += addLevels; } } [MemoryPackable] public partial class HeroTaskContentSkillActivation : HeroTaskContentBase { public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentSkillActivation(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; newContent.SkillType = SkillType; return newContent; } public override HeroTaskContentType GetContentType() { return HeroTaskContentType.SkillActivation; } public override void OnSkillActivation(MapData mapData, SkillType skillType, uint addLevels) { if (skillType != SkillType) return; Level += addLevels; } } [MemoryPackable] public partial class HeroTaskContentTewiAddCoin : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.TewiAddCoin; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentTewiAddCoin(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; newContent.SkillType = SkillType; return newContent; } public override void OnTewiCoinAdd(MapData mapData, uint value) { Level += value; } } [MemoryPackable] public partial class HeroTaskContentSkillDropLevels : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.SkillDropLevels; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentSkillDropLevels(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; newContent.SkillType = SkillType; newContent.SkillTypeList ??= new List(); newContent.SkillTypeList.Clear(); foreach (var skillType in SkillTypeList) newContent.SkillTypeList.Add(skillType); return newContent; } public override void OnReduceSkillLevels(MapData mapData, SkillType skillType, uint reduceLevels) { if (!SkillTypeList.Contains(skillType)) return; Level += reduceLevels; } } [MemoryPackable] public partial class HeroTaskContentMeetOtherPlayers : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.MeetOtherPlayers; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentMeetOtherPlayers(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; newContent.SkillType = SkillType; return newContent; } public override void OnTaskInit(MapData mapData, PlayerData self) { var max = Mathf.CeilToInt(mapData.PlayerMap.PlayerDataList.Count / 3f); if (TargetLevel > max) TargetLevel = (uint)max; Level = (uint)Mathf.Max(0, self.MeetPlayers.Count - 1); } public override void OnMeetOtherPlayers(MapData mapData, PlayerData self) { var max = Mathf.CeilToInt(mapData.PlayerMap.PlayerDataList.Count / 3f); if (TargetLevel > max) TargetLevel = (uint)max; Level = (uint)Mathf.Max(0, self.MeetPlayers.Count - 1); } } [MemoryPackable] public partial class HeroTaskContentAddSpType : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.AddSpType; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentAddSpType(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; newContent.SpType = SpType; return newContent; } public override void OnAddSpType(MapData mapData, GridSpType spType) { if (SpType == spType) Level++; } } [MemoryPackable] public partial class HeroTaskContentAddCoin : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.AddCoin; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentAddCoin(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; newContent.SpType = SpType; return newContent; } public override void OnAddCoin(uint value) { Level += value; } } [MemoryPackable] public partial class HeroTaskContentGetTech : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.GetTech; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentGetTech(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; return newContent; } public override void OnTaskInit(MapData mapData, PlayerData self) { OnTechGet(self); } public override void OnTechGet(PlayerData self) { Level = 0; foreach (var tech in self.TechTree.TechSet) { if (tech == TechType.None) continue; Level ++; } } } [MemoryPackable] public partial class HeroTaskContentTrainUnit : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.TrainUnit; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentTrainUnit(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; newContent.UnitFullTypes??=new List(); newContent.UnitFullTypes.Clear(); foreach (var fullType in UnitFullTypes) newContent.UnitFullTypes.Add(fullType); return newContent; } public override void OnTrainUnit(MapData mapData, PlayerData self, UnitData unit) { foreach (var fullType in UnitFullTypes) { if (!unit.UnitFullType.Equals(fullType)) continue; Level ++; break; } } public override void OnTransformUnit(MapData mapData, PlayerData self, UnitData unit) { foreach (var fullType in UnitFullTypes) { if (!unit.UnitFullType.Equals(fullType)) continue; Level ++; break; } } } [MemoryPackable] public partial class HeroTaskContentUnitKills : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.UnitKills; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentUnitKills(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; newContent.UnitFullTypes??=new List(); newContent.UnitFullTypes.Clear(); foreach (var fullType in UnitFullTypes) newContent.UnitFullTypes.Add(fullType); return newContent; } public override void OnPlayerDamageOther(MapData mapData, SettlementInfo info) { if (!info.IsKill || info.DamageType == DamageType.KillSelf) return; foreach (var fullType in UnitFullTypes) { if (info.DamageOrigin.UnitFullType.UnitType != fullType.UnitType) continue; Level ++; break; } } } [MemoryPackable] public partial class HeroTaskContentSanaeDivineGreat : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.SanaeDivineGreat; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentSanaeDivineGreat(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; newContent.TargetTypes ??= new List(); newContent.TargetTypes.Clear(); foreach (var targetType in TargetTypes) newContent.TargetTypes.Add(targetType); return newContent; } public override void OnSanaeDevine(MapData mapdata, PlayerData self, SanaeDivineType type) { if (TargetTypes.Contains(type)) Level++; } } [MemoryPackable] public partial class HeroTaskContentSplashDamage : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.SplashDamage; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentSplashDamage(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; return newContent; } public override void OnDamageOther(MapData mapData, SettlementInfo info) { if (info.DamageType != DamageType.Splash) return; Level += (uint)info.HealthReduceValue; } } [MemoryPackable] public partial class HeroTaskContentUnitDeathWithSkill : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.UnitDeathWithSkill; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentUnitDeathWithSkill(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; newContent.SkillType = SkillType; return newContent; } public override void OnAnyDamaged(MapData mapData, SettlementInfo info) { if (!info.IsKill) return; if (!info.DamageTarget.GetSkill(SkillType, out _)) return; Level++; } } [MemoryPackable] public partial class HeroTaskContentTargetTypeAreasExplored : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.TargetTypeAreasExplored; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentTargetTypeAreasExplored(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; newContent.UnitFullTypes??=new List(); newContent.UnitFullTypes.Clear(); foreach (var fullType in UnitFullTypes) newContent.UnitFullTypes.Add(fullType); return newContent; } public override void OnAnyExploredGrids(MapData mapData, UnitData unit, int count) { foreach (var fullType in UnitFullTypes) { if (!unit.UnitFullType.Equals(fullType)) continue; Level += (uint)count; break; } } } [MemoryPackable] public partial class HeroTaskContentTargetAccumulateRelicsOpenedIncludeOthers : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.AccumulateRelicsOpenedIncludeOthers; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentTargetAccumulateRelicsOpenedIncludeOthers(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; return newContent; } public override void OnPlayerTreasure(MapData mapData) { Level++; } } [MemoryPackable] public partial class HeroTaskContentAccumulateCaptureOtherCitiesOrVillages : HeroTaskContentBase { public override HeroTaskContentType GetContentType() { return HeroTaskContentType.AccumulateCaptureOtherCitiesOrVillages; } public override HeroTaskContentBase GetCopyHeroTaskContent() { var newContent = new HeroTaskContentAccumulateCaptureOtherCitiesOrVillages(); newContent.Level = Level; newContent.TargetLevel = TargetLevel; return newContent; } public override void OnPlayerCaptureCity(MapData mapData) { Level += 2; } public override void OnPlayerCaptureVillage(MapData mapData) { Level++; } } }