/* * @Author: 白哉 * @Description: 行为逻辑类 * @Date: 2025年04月10日 星期四 11:04:44 * @Modify: */ using System; using System.Collections.Generic; using System.Linq; using System.Net; using Logic.AI; using Logic.Audio; using Logic.CrashSight; using Logic.Skill; using RuntimeData; using TH1_Core.Events; using TH1_Core.Managers; using TH1_Logic.Core; using UnityEngine; using TH1Renderer; using TH1Resource; using Unity.VisualScripting; //这里是所有BuildAction派生子类的实现模块 namespace Logic.Action { public enum UnitActionType { None,Upgrade,Recover,HEAL,Examine,Gather,Capture,Disband,ROYALFLAMES,ROYALFLAMESPRO,HeroUpgrade, TEWIFRENCHBUFF, MOKOUFRENCHBOOM, KAGUYAFRENCHAROUND, ForceDisband, RemoveRedMist, REMILIABUFF, AbsorbRedMist, REMILIAABSORB, KANAKOSIT, KANAKOUNSIT, AYAMOVEAGAIN, KomeijiRinFire, KomeijiRinCityExp, KomeijiBonePileBoom, ReisenFrenchBoom, ToggleShenlan, CultureUnitUpgrade, } public static class UnitActionUpgradeHelper { public static bool TryGetCultureUnitUpgradeCost(UnitData unit, out int cost) { cost = 0; if (unit == null) return false; if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitFullType, out var info)) return false; cost = info.Cost; return true; } public static bool ApplyOfficerUpgrade(MapData map, UnitData unit) { if (map == null || unit == null) return false; unit.SetOfficer(); unit.Health = unit.GetMaxHealth(); unit.Renderer(map)?.InstantUpdateUnit(true); if (unit.Grid(map)?.InMainSight() ?? false) AudioManager.Instance.PlayAudio("SFX/UNIT_levelup"); if (map == Main.MapData && unit.Player(map) == Main.MapData.PlayerMap.SelfPlayerData) { EventManager.Publish(new ShowUINotifyMoment() { MomentSubType = MomentSubType.BattleLevelup, Empire = Main.MapData.PlayerMap.SelfPlayerData.Empire }); } return true; } } //UnitAction单位行动逻辑类 public class UnitActionAction : ActionLogicBase { public UnitActionAction(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { //鲁棒性判断 if (actionParams.UnitData == null) return false; var unitData = actionParams.UnitData; var playerData = actionParams.PlayerData; if (playerData == null) if (!actionParams.MapData.GetPlayerDataByUnitId(actionParams.UnitData.Id, out playerData)) return false; if (!actionParams.MapData.GetGridDataByUnitId(actionParams.UnitData.Id, out var gridData)) return false; //处理 ToggleShenlan:纯调试/视觉效果,不消耗行动点也不扣费 if (_actionId.UnitActionType == UnitActionType.ToggleShenlan) { if (unitData.GetSkill(SkillType.Shenlan, out _)) { unitData.RemoveSkill(SkillType.Shenlan, actionParams.MapData); } else { unitData.AddOrOverrideSkill(SkillType.Shenlan, actionParams.MapData, unitData.Id); // 仅在获得 Shenlan 时播放 VFX,取消时不播 gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Dancing)); gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); } unitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); BoatUnitOnLandDiagnostic.ReportIfNeeded(actionParams.MapData, unitData, gridData, $"UnitAction:{_actionId.UnitActionType}"); return true; } if (_actionId.UnitActionType == UnitActionType.Capture) { //处理捕获city的情况 if (actionParams.MapData.GetCityDataByGid(gridData.Id, out var cityData)) { //Step #1 先更新unit 状态 actionParams.UnitData.ClearActionPoint(); actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); //Step #2 再处理占领城市的所有logic & view Main.PlayerLogic.OccupyCity_LogicView(actionParams.MapData, actionParams.UnitData, cityData); //Step #3 再更新heroTask unitData.HeroTask(actionParams.MapData)?.OnCaptureCity(actionParams.MapData); foreach (var item in actionParams.PlayerData.MomentData.Items) { item.OnCaptureCity(actionParams.MapData, actionParams.PlayerData, cityData); } var player = unitData?.Player(actionParams.MapData); if (player != null) { foreach (var kv in player.PlayerHeroData.HeroTaskDict) kv.Value.OnPlayerCaptureCity(actionParams.MapData); } BoatUnitOnLandDiagnostic.ReportIfNeeded(actionParams.MapData, unitData, gridData, $"UnitAction:{_actionId.UnitActionType}"); return true; } //处理占领村庄的情况 else { gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); cityData = Main.PlayerLogic.OccupyVillage_LogicOnly(actionParams.MapData,actionParams.UnitData,gridData); //Step #3 再更新heroTask unitData.HeroTask(actionParams.MapData)?.OnCaptureVillage(actionParams.MapData); var player = unitData?.Player(actionParams.MapData); if (player != null) { foreach (var kv in player.PlayerHeroData.HeroTaskDict) kv.Value.OnPlayerCaptureVillage(actionParams.MapData); } //Step #3.5 如果玩家有视野,播放音效 if(gridData.InMainSight()) AudioManager.Instance.PlayAudio("SFX/UNIT_capture"); //处理占领城市的特效(所有领土会升起一面旗帜 HashSet gridList = new HashSet(); cityData.Territory.GetAllTerritoryArea(gridList); foreach (var gd in gridList) { if (actionParams.MapData.GridMap.GetGridDataByGid(gd, out var gdd)) { //设置gdd格子的VFXrendermark var t = new GridVFXParams(GridVFXType.Flag); t.CivId = playerData.PlayerCivId; gdd.Renderer(actionParams.MapData)?.PlayVFXInSight(t); } } actionParams.UnitData.ClearActionPoint(); unitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); //Step #5 处理NotifyMoment if (actionParams.UnitData.Player(actionParams.MapData) == Main.MapData.PlayerMap.SelfPlayerData) { EventManager.Publish(new ShowUINotifyMoment() { MomentSubType = MomentSubType.BattleCaptureVillage, Empire = Main.MapData.PlayerMap.SelfPlayerData.Empire }); } BoatUnitOnLandDiagnostic.ReportIfNeeded(actionParams.MapData, unitData, gridData, $"UnitAction:{_actionId.UnitActionType}"); return true; } } if (_actionId.UnitActionType == UnitActionType.Upgrade) { return UnitActionUpgradeHelper.ApplyOfficerUpgrade(actionParams.MapData, actionParams.UnitData); } //处理ship if (_actionId.UnitType is UnitType.Ship or UnitType.RammerShip or UnitType.BomberShip or UnitType.KomeijiIndianShip or UnitType.KomeijiIndianBomberShip) { if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_actionId.UnitType,GiantType.None,0, out var info )) return false; if (actionParams.PlayerData.PlayerCoin < info.Cost) return false; actionParams.PlayerData.SpendCoin(info.Cost); Main.UnitLogic.UnitTypeTransform(actionParams.MapData,actionParams.UnitData,_actionId.UnitType); Main.PlayerLogic.UpdateSight_LogicView(actionParams.MapData,actionParams.PlayerData,actionParams.MapData.GridMap.GetAroundGridIdList(unitData.GetSightRange(actionParams.MapData),gridData)); actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); actionParams.UnitData.Grid(actionParams.MapData)?.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); //Step #3.5 如果玩家有视野,播放音效 if(actionParams.UnitData.Grid(actionParams.MapData)?.InMainSight() ?? false) AudioManager.Instance.PlayAudio("SFX/UNIT_levelup"); BoatUnitOnLandDiagnostic.ReportIfNeeded(actionParams.MapData, unitData, gridData, $"UnitAction:{_actionId.UnitType}"); return true; } //剩下的都需要CP,消耗CP //用ret做记录 bool ret = false; //处理disband if (_actionId.UnitActionType == UnitActionType.Disband) { int earn = 0; if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(actionParams.UnitData.UnitFullType, out var info )) return false; earn += info.Cost / 2; if (actionParams.UnitData.CarryUnitFullType.UnitType != UnitType.None && Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(actionParams.UnitData.CarryUnitFullType,out var carryInfo)) earn += carryInfo.Cost / 2; var startPos = Table.Instance.GridToWorld(gridData); actionParams.PlayerData.AddCoin(earn,startPos); if (actionParams.MapData.IsCurrentShowMap()) { //播放雾效 gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); actionParams.UnitData.Renderer(Main.MapData)?.Die(); //更新原来所属的城市的cityinfo } var city = actionParams.UnitData.City(actionParams.MapData); Main.UnitLogic.UnitUnnaturalDie(actionParams.MapData,actionParams.UnitData); if (city != null) { ret = true; } } //处理recover if (_actionId.UnitActionType == UnitActionType.Recover) { //如果有KomeijiFear,清除所有恐惧层数,但不恢复血量 if (actionParams.UnitData.GetSkill(SkillType.KomeijiFear, out _)) { actionParams.UnitData.RemoveSkill(SkillType.KomeijiFear, actionParams.MapData); ret = true; actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); } else { int recoverV = 4; if (!actionParams.MapData.GetPlayerDataByTerritoryGridId(gridData.Id, out var terrPlayerData)) recoverV = 2; else if (!actionParams.MapData.SameUnion(terrPlayerData.Id , actionParams.PlayerData.Id)) recoverV = 2; Main.UnitLogic.RecoverHealth_Legacy(actionParams.MapData, null, actionParams.UnitData, recoverV); ret = true; if(actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true) ?? false) gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Heal)); } } //处理gather if (_actionId.UnitActionType == UnitActionType.Gather) { gridData.Resource = ResourceType.None; actionParams.PlayerData.AddCoin(10,Table.Instance.GridToWorld(gridData)); gridData.Renderer(actionParams.MapData)?.InstantUpdateGrid(true); ret = true; if (actionParams.MapData == Main.MapData && actionParams.MapData.PlayerMap.SelfPlayerId == playerData.Id) { gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); } } //处理examine if (_actionId.UnitActionType == UnitActionType.Examine) { unitData.HeroTask(actionParams.MapData)?.OnTreasure(actionParams.MapData); var player = unitData?.Player(actionParams.MapData); if (player != null) { foreach (var kv in player.PlayerHeroData.HeroTaskDict) kv.Value.OnPlayerTreasure(actionParams.MapData); } gridData.Resource = ResourceType.None; gridData.Renderer(actionParams.MapData)?.InstantUpdateGrid(true); var value = actionParams.MapData.Net.GetRandom(actionParams.MapData).Next(0, 5); //播放雾效 if (actionParams.MapData == Main.MapData && actionParams.MapData.PlayerMap.SelfPlayerId == playerData.Id) { gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); AudioManager.Instance.PlayAudio("SFX/UNIT_treasure"); } if (value == 0) { actionParams.PlayerData.AddCoin(10,Table.Instance.GridToWorld(gridData)); } //给一个单位 else if (value == 1) { Main.UnitLogic.PassiveMoveAway(actionParams.MapData, actionParams.UnitData); if(!actionParams.MapData.GetCapitalCityDataByPlayerId(actionParams.PlayerData.Id, out var capital)) return false; if (gridData.Terrain == TerrainType.Land) { if (actionParams.MapData.AddUnitData(gridData.Id, capital.Id,new UnitFullType(UnitType.Swordsman,GiantType.None,0) , out var unit)) { unit.SetOfficer(); unit.Health = unit.GetMaxHealth(); unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); }; } else { if (actionParams.MapData.AddUnitData(gridData.Id, capital.Id, new UnitFullType(UnitType.RammerShip, GiantType.None, 0), out var unit)) { unit.AddSkill_Legacy(SkillType.OFFICER,actionParams.MapData,true,-1,false,-1,false,SpecialAddSkillType.Normal,0); unit.SetOfficer(); unit.Health = unit.GetMaxHealth(); unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); } } capital.SetCityRenderer(actionParams.MapData); } //随机赠送一个当前可学习科技 else if (value == 2) { if (Table.Instance.PlayerDataAssets.GetPlayerInfo(actionParams.PlayerData, out var playerInfo)) { var canLearnTechList = new List(); foreach (var techType in playerInfo.TechPool) { if (actionParams.PlayerData.TechTree.CheckIfTechCanLearn(techType)) canLearnTechList.Add(techType); } if (canLearnTechList.Count > 0) { var index = actionParams.MapData.Net.GetRandom(actionParams.MapData).Next(0, canLearnTechList.Count); var techType = canLearnTechList[index]; Main.PlayerLogic.ResearchTech(actionParams.MapData, actionParams.PlayerData, techType, 0); if (actionParams.PlayerData.IsSelfPlayer()) EventManager.Publish(new ShowUINotifyCommon(){UINotifyCommonType = UINotifyCommonType.ExamineTech}); } else { actionParams.PlayerData.AddCoin(10,Table.Instance.GridToWorld(gridData)); } } else { actionParams.PlayerData.AddCoin(10,Table.Instance.GridToWorld(gridData)); } } //获得4点文化点 else if (value == 3) { actionParams.PlayerData.AddCulturePoint(4); if (actionParams.PlayerData.IsSelfPlayer()) EventManager.Publish(new ShowUINotifyCommon(){UINotifyCommonType = UINotifyCommonType.ExamineCulture}); } //给首都3点城市经验 else { if (!actionParams.MapData.GetCapitalCityDataByPlayerId(actionParams.PlayerData.Id, out var capital)) return false; Main.CityLogic.GridGiveCityExp_LogicView(actionParams.MapData, actionParams.PlayerData, capital.Grid(actionParams.MapData), capital, 3); if (actionParams.PlayerData.IsSelfPlayer()) EventManager.Publish(new ShowUINotifyCommon(){UINotifyCommonType = UINotifyCommonType.ExamineCityExp}); } ret = true; //Step #4 Moment if (actionParams.MapData == Main.MapData && actionParams.UnitData.Player(actionParams.MapData) == Main.MapData.PlayerMap.SelfPlayerData) { EventManager.Publish(new ShowUINotifyMoment() { MomentSubType = MomentSubType.ExploitTreasure, Empire = Main.MapData.PlayerMap.SelfPlayerData.Empire }); } } if (ret) { actionParams.UnitData.ClearActionPoint(); actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); BoatUnitOnLandDiagnostic.ReportIfNeeded(actionParams.MapData, actionParams.UnitData, gridData, $"UnitAction:{_actionId.UnitActionType}"); } return ret; } public override bool CheckCan(CommonActionParams actionParams) { //鲁棒性判断 if (actionParams.UnitData == null) return false; if (actionParams.PlayerData == null) return false; if (!actionParams.MapData.GetGridDataByUnitId(actionParams.UnitData.Id, out var gridData)) return false; //如果unit不是player的,退出 if(!actionParams.MapData.GetPlayerDataByUnitId(actionParams.UnitData.Id, out var playerData) || playerData != actionParams.PlayerData) return false; //ToggleShenlan 是调试/视觉切换,不需要钱/科技/CP,只要属于自己即可 if (_actionId.UnitActionType == UnitActionType.ToggleShenlan) return true; //判断钱够不够 if (GetCost(actionParams) > actionParams.PlayerData.PlayerCoin) return false; //如果不具备科技 if (!actionParams.PlayerData.TechTree.CheckActionCan(_actionId)) return false; if (_actionId.UnitActionType == UnitActionType.Upgrade) { //鲁棒性处理 if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(actionParams.UnitData.UnitFullType, out var info)) return false; return actionParams.UnitData.IsCanBeOfficer(); } //先处理不需要CP的 Upgrade UnitShip UnitRammerShip UnitBattleShip 这4个 if (_actionId.UnitType is UnitType.Ship or UnitType.RammerShip or UnitType.BomberShip or UnitType.KomeijiIndianShip or UnitType.KomeijiIndianBomberShip) { if(actionParams.UnitData.UnitFullType.UnitType != UnitType.Boat) return false; if (!actionParams.MapData.GetPlayerDataByTerritoryGridId(gridData.Id, out var player1)) return false; if(!actionParams.MapData.SameUnion(player1.Id,actionParams.PlayerData.Id)) return false; return true; } //剩下的都需要CP,如果Unit有没有CP了,return false if (actionParams.UnitData.GetActionPoint(ActionPointType.Capture) <= 0) return false; //处理capture if (_actionId.UnitActionType == UnitActionType.Capture) { //如果是占领别的城市 if (actionParams.MapData.GetCityDataByGid(gridData.Id, out var cityData)) { actionParams.MapData.GetPlayerDataByCityId(cityData.Id,out var playerId1); actionParams.MapData.GetPlayerDataByUnitId(actionParams.UnitData.Id,out var playerId2); return playerId1 != playerId2; } //如果是占领村庄 else { return gridData.Resource == ResourceType.CityCenter; } } //处理disband if (_actionId.UnitActionType == UnitActionType.Disband) { if ((actionParams.UnitData.UnitType is UnitType.Giant or UnitType.GiantJuggernaut or UnitType.KaguyaFrenchReisenIllusion or UnitType.KaguyaFrenchMokouEgg) || actionParams.UnitData.CarryUnitType == UnitType.Giant) return false; return true; } //处理recover if (_actionId.UnitActionType == UnitActionType.Recover) { if (actionParams.UnitData.GetSkill(SkillType.KomeijiFear, out _)) return true; if (actionParams.UnitData.GetSkill(SkillType.SAKUYATIRED, out _)) return true; if (actionParams.UnitData.Health < actionParams.UnitData.GetMaxHealth()) return true; return false; } //处理gather if (_actionId.UnitActionType == UnitActionType.Gather) return gridData.Resource == ResourceType.Starfish; //处理examine if (_actionId.UnitActionType == UnitActionType.Examine) return gridData.Resource == ResourceType.Treasure; //处理战技ROYALFLAMES if (_actionId.UnitActionType == UnitActionType.ROYALFLAMES) { if (!actionParams.UnitData.GetSkill(SkillType.ROYALFLAMES, out var skillInfo)) return false; return true; } return false; } public override bool CheckShow(CommonActionParams actionParams,out ShowType showType) { showType = ShowType.None; //鲁棒性判断 if (actionParams.UnitData == null) return false; if (actionParams.PlayerData == null) return false; if (!actionParams.MapData.GetGridDataByUnitId(actionParams.UnitData.Id, out var gridData)) return false; //如果unit不是player的,退出 if(!actionParams.MapData.GetPlayerDataByUnitId(actionParams.UnitData.Id, out var playerData) || playerData.Id != actionParams.PlayerData.Id) return false; //判断钱够不够 checkshow中 即使钱不够,也可以显示的 //if (GetCost() > actionParams.PlayerData.PlayerWealth) // return false; //ToggleShenlan:调试技能,永远不在ActionArea中显示(仅靠InputLogic连点触发) if (_actionId.UnitActionType == UnitActionType.ToggleShenlan) return false; //如果不具备科技 if (!actionParams.PlayerData.TechTree.CheckActionCan(_actionId)) return false; //先处理不需要CP的 Upgrade UnitShip UnitRammerShip UnitBattleShip 这4个 if (_actionId.UnitActionType == UnitActionType.Upgrade) { //鲁棒性处理 if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(actionParams.UnitData.UnitType, actionParams.UnitData.GiantType, actionParams.UnitData.UnitLevel,out var info)) return false; if (actionParams.UnitData.IsCanBeOfficer()) return true; return false; } if (_actionId.UnitType is UnitType.Ship or UnitType.RammerShip or UnitType.BomberShip or UnitType.KomeijiIndianShip or UnitType.KomeijiIndianBomberShip) { if(actionParams.UnitData.UnitType != UnitType.Boat) return false; if (!actionParams.MapData.GetPlayerDataByTerritoryGridId(gridData.Id, out var player1)) return false; if(!actionParams.MapData.SameUnion(player1.Id,actionParams.PlayerData.Id)) return false; return true; } //剩下的都需要CP,如果Unit有没有CP了,return false if (actionParams.UnitData.GetActionPoint(ActionPointType.Capture) <= 0) return false; //处理capture if (_actionId.UnitActionType == UnitActionType.Capture) { //如果是占领别的城市 if (actionParams.MapData.GetCityDataByGid(gridData.Id, out var cityData)) { actionParams.MapData.GetPlayerDataByCityId(cityData.Id,out var playerId1); actionParams.MapData.GetPlayerDataByUnitId(actionParams.UnitData.Id,out var playerId2); return playerId1 != playerId2; } //如果是占领村庄 else { return gridData.Resource == ResourceType.CityCenter; } } //处理disband if (_actionId.UnitActionType == UnitActionType.Disband) { if ((actionParams.UnitData.UnitType is UnitType.Giant or UnitType.GiantJuggernaut or UnitType.KaguyaFrenchReisenIllusion or UnitType.KaguyaFrenchMokouEgg) || actionParams.UnitData.CarryUnitType == UnitType.Giant) return false; return true; } //处理recover if (_actionId.UnitActionType == UnitActionType.Recover) { if (actionParams.UnitData.GetSkill(SkillType.KomeijiFear, out _)) return true; if (actionParams.UnitData.GetSkill(SkillType.SAKUYATIRED, out _)) return true; if (actionParams.UnitData.Health < actionParams.UnitData.GetMaxHealth()) return true; return false; } //处理gather if (_actionId.UnitActionType == UnitActionType.Gather) return gridData.Resource == ResourceType.Starfish; //处理examine if (_actionId.UnitActionType == UnitActionType.Examine) return gridData.Resource == ResourceType.Treasure; //处理战技ROYALFLAMES if (_actionId.UnitActionType == UnitActionType.ROYALFLAMES) { if (!actionParams.UnitData.GetSkill(SkillType.ROYALFLAMES, out var skillInfo)) return false; return true; } return false; } //付钱 protected bool UnitActionPayMoney(CommonActionParams actionParam) { if (actionParam.PlayerData.PlayerCoin - GetCost(actionParam) < 0) return false; actionParam.PlayerData.SpendCoin(GetCost(actionParam)); return true; } //确认是否满足基本信息,并且补全actionParam(主要是补充unit所处的grid) protected bool UnitActionCheckBaseInfo(CommonActionParams actionParam) { //鲁棒性判断,必须包含unitData和playerData,表明是哪个玩家正在操作哪个单位 if (actionParam.UnitData == null) return false; if (actionParam.PlayerData == null) return false; if (!actionParam.MapData.GetGridDataByUnitId(actionParam.UnitData.Id, out var grid)) return false; actionParam.GridData = grid; return true; } protected bool UnitActionCheckUnitBelongPlayer(CommonActionParams actionParam) { //如果unit不是player的,退出 if(!actionParam.MapData.GetPlayerDataByUnitId(actionParam.UnitData.Id, out var playerData) || playerData != actionParam.PlayerData) return false; return true; } //确认是否有科技 protected bool UnitActionCheckHasTech(CommonActionParams actionParam) { //如果没有对应科技,return false if (!actionParam.PlayerData.TechTree.CheckActionCan(_actionId)) return false; return true; } //确认是否有钱 protected bool UnitActionCheckHasMoney(CommonActionParams actionParams) { //判断钱够不够 if (GetCost(actionParams) > actionParams.PlayerData.PlayerCoin) return false; return true; } //确认unit是否有CP protected bool UnitActionCheckUnitHasCP(CommonActionParams actionParam) { if (actionParam.UnitData == null || actionParam.UnitData.GetActionPoint(ActionPointType.Capture) <= 0) return false; return true; } //确认unit的UnitTypeData的EnableActions是否包含当前actionId protected bool CheckUnitEnableAction(CommonActionParams actionParam) { if (actionParam.UnitData == null) return false; if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(actionParam.UnitData.UnitFullType, out var info)) return false; if (!info.EnableAction || info.EnableActions == null) return false; foreach (var enabledId in info.EnableActions) { if (enabledId == _actionId) return true; } return false; } //确认unit是否拥有这个skill protected bool UnitActionCheckUnitHasSkill(CommonActionParams actionParam) { //将unitActionType转化为skillType if (!Enum.TryParse(_actionId.UnitActionType.ToString(), out SkillType skillType)) return false; if (actionParam.UnitData == null || !actionParam.UnitData.HasEffectiveSkill(skillType, out var _)) return false; return true; } } //目前废弃 public class UnitActionROYALFLAMESPRO : UnitActionAction { public UnitActionROYALFLAMESPRO(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { return false; } public override bool CheckCan(CommonActionParams actionParam) { return false; } public override bool CheckShow(CommonActionParams actionParam,out ShowType showType) { showType = ShowType.None; return false; } } public class UnitActionCultureUnitUpgrade : UnitActionAction { public UnitActionCultureUnitUpgrade(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { if (!CheckCan(actionParams)) return false; if (!UnitActionUpgradeHelper.TryGetCultureUnitUpgradeCost(actionParams.UnitData, out var cost)) return false; actionParams.PlayerData.AddCulturePoint(-cost); return UnitActionUpgradeHelper.ApplyOfficerUpgrade(actionParams.MapData, actionParams.UnitData); } public override int GetCost(CommonActionParams actionParams) { return UnitActionUpgradeHelper.TryGetCultureUnitUpgradeCost(actionParams?.UnitData, out var cost) ? cost : 0; } public override bool CheckCan(CommonActionParams actionParam) { if (!UnitActionCheckBaseInfo(actionParam)) return false; if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false; if (!actionParam.PlayerData.CanCultureUpgradeUnit(actionParam.MapData)) return false; if (!CheckUnitCanCultureUpgrade(actionParam.UnitData)) return false; if (!UnitActionUpgradeHelper.TryGetCultureUnitUpgradeCost(actionParam.UnitData, out var cost)) return false; return actionParam.PlayerData.PlayerCultureInfo.PlayerCulture >= cost; } public override bool CheckShow(CommonActionParams actionParam, out ShowType showType) { showType = ShowType.None; if (!UnitActionCheckBaseInfo(actionParam)) return false; if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false; if (!actionParam.PlayerData.CanCultureUpgradeUnit(actionParam.MapData)) return false; if (!CheckUnitCanCultureUpgrade(actionParam.UnitData)) return false; if (!UnitActionUpgradeHelper.TryGetCultureUnitUpgradeCost(actionParam.UnitData, out _)) return false; return true; } public override ActionShowState CheckShowState(CommonActionParams actionParams) { if (!CheckShow(actionParams, out _)) return ActionShowState.None; if (!UnitActionUpgradeHelper.TryGetCultureUnitUpgradeCost(actionParams.UnitData, out var cost)) return ActionShowState.None; return actionParams.PlayerData.PlayerCultureInfo.PlayerCulture >= cost ? ActionShowState.Available : ActionShowState.Expensive; } private bool CheckUnitCanCultureUpgrade(UnitData unit) { return unit != null && unit.IsPrepareOfficer() && !unit.IsOfficer(); } } //英雄升级 public class UnitActionHeroUpgrade : UnitActionAction { private int _healthBeforeAnim; private bool CheckUnitCanGiantUpgrade(CommonActionParams actionParams) { var unit = actionParams.UnitData; var player = actionParams.PlayerData; if (player == null) return false; if(unit == null || unit.UnitType != UnitType.Giant || unit.GiantType == GiantType.None || unit.UnitLevel >= 4) return false; if(!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType,unit.GiantType,unit.UnitLevel,out var info)) return false; return unit.HeroTask(actionParams.MapData)?.CheckFinished(actionParams.MapData, player) ?? false; } public UnitActionHeroUpgrade(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { if (actionParams.UnitData == null) return false; _healthBeforeAnim = actionParams.UnitData.Health; //if (!CheckCan(actionParams)) return false; var unit = actionParams.UnitData; if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType, unit.UnitLevel, out var info)) return false; //step #1 已经升到满级就return if (unit.UnitLevel + 1 > 4) return false; //step #2 英雄升级 var giantType = unit.GiantType; var targetLevel = unit.UnitLevel + 1; if (!Main.UnitLogic.HeroUpgrade(actionParams.MapData, unit)) return false; //step #3 回复10点血 unit.AddHealth(10 + unit.GetHeroUpgradeRecoverAddition(actionParams.MapData)); //更新视觉,自动排除非真map情况和不在视野情况 if(actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true)??false){ actionParams.UnitData.Grid(actionParams.MapData)?.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Heal)); } if(actionParams.UnitData.Grid(actionParams.MapData)?.InMainSight()??false) AudioManager.Instance.PlayAudio("SFX/UNIT_levelup"); //step #3.5 场上所有相同GiantType的英雄单位一起升级 //若本次升级的是FrenchReisen,则同玩家场上所有KaguyaFrenchReisenIllusion也同步升级到相同等级 var sameGiantUnits = new System.Collections.Generic.List(); actionParams.MapData.GetUnitDataListByPlayerId(actionParams.PlayerId, sameGiantUnits); bool isFrenchReisenUpgrade = giantType == GiantType.FrenchReisen; foreach (var other in sameGiantUnits) { if (other.Id == unit.Id) continue; if (!other.IsAlive()) continue; bool isSameGiantHero = other.UnitType == UnitType.Giant && other.GiantType == giantType; bool isReisenIllusion = isFrenchReisenUpgrade && other.UnitType == UnitType.KaguyaFrenchReisenIllusion; if (!isSameGiantHero && !isReisenIllusion) continue; if (other.UnitLevel >= targetLevel) continue; var otherTargetType = new UnitFullType() { UnitType = other.UnitType, GiantType = other.GiantType, UnitLevel = (uint)targetLevel }; Main.UnitLogic.UnitTypeTransform(actionParams.MapData, other, otherTargetType); other.AddHealth(10 + other.GetHeroUpgradeRecoverAddition(actionParams.MapData)); other.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); //同类英雄升级后也更新视野 if (other.Grid(actionParams.MapData) != null) Main.PlayerLogic.UpdateSightByRadius_LogicView(actionParams.MapData, actionParams.PlayerData, other.Grid(actionParams.MapData), other.GetSightRange(actionParams.MapData)); } //step #3.6 升级后更新主英雄视野(升级可能增加视野范围) if (unit.Grid(actionParams.MapData) != null) Main.PlayerLogic.UpdateSightByRadius_LogicView(actionParams.MapData, actionParams.PlayerData, unit.Grid(actionParams.MapData), unit.GetSightRange(actionParams.MapData)); //Step #4 Moment if (actionParams.UnitData.Player(actionParams.MapData) == Main.MapData.PlayerMap.SelfPlayerData) { EventManager.Publish(new ShowUINotifyMoment() { MomentSubType = MomentSubType.BattleHeroLevelup, Empire = Main.MapData.PlayerMap.SelfPlayerData.Empire }); } return true; } public override bool CheckCan(CommonActionParams actionParam) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParam)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false; //step #3 check unit是否是hero并满足升级条件 if (!CheckUnitCanGiantUpgrade(actionParam)) return false; return true; } public override bool CheckShow(CommonActionParams actionParam,out ShowType showType) { showType = ShowType.None; return CheckCan(actionParam); } public bool ExecuteViewBefore(CommonActionParams actionParams) { return true; } public bool ExecuteViewAfter(CommonActionParams actionParams) { return true; } } public class UnitActionHEAL : UnitActionAction { public UnitActionHEAL(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { var map = actionParams.MapData; var unit = actionParams.UnitData; if (map == null || unit == null) return false; if (!map.GetGridDataByUnitId(actionParams.UnitData.Id, out var targetGrid)) return false; _sharedAroundBuf ??= new List(); _sharedAroundBuf.Clear(); map.GridMap.GetAroundGridData(1, 1, targetGrid, _sharedAroundBuf); foreach (var grid in _sharedAroundBuf) { if (!grid.RealUnit(map, out var tunit)) continue; if(tunit.Id == unit.Id)continue; if (!map.SameUnionByUnitId(unit.Id,tunit.Id)) continue; Main.UnitLogic.RecoverHealth_Legacy(map, unit, tunit, 4); } unit.ClearActionPoint(); unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); return true; } public override bool CheckCan(CommonActionParams actionParam) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParam)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false; //step #3 check是否有CP释放技能 if (!UnitActionCheckUnitHasCP(actionParam)) return false; //step #4 check unit是否拥有skill技能 if (!UnitActionCheckUnitHasSkill(actionParam)) return false; return true; } public override bool CheckShow(CommonActionParams actionParam,out ShowType showType) { showType = ShowType.None; return CheckCan(actionParam); } } public class UnitActionTEWIFRENCHBUFF : UnitActionAction { public UnitActionTEWIFRENCHBUFF(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { var selfUnit = actionParams.UnitData; var selfGrid = actionParams.GridData; if(selfGrid == null) if(!actionParams.MapData.GetGridDataByUnitId(selfUnit.Id, out selfGrid)) return false; if (!actionParams.MapData.GetPlayerDataByUnitId(selfUnit.Id, out var selfPlayer)) return false; _sharedAroundBuf ??= new List(); _sharedAroundBuf.Clear(); actionParams.MapData.GridMap.GetAroundGridData(1,1,selfGrid, _sharedAroundBuf); foreach (var grid in _sharedAroundBuf) { if (grid == selfGrid) continue; if(!grid.RealUnit(actionParams.MapData,out var targetUnit))continue; if(!actionParams.MapData.GetPlayerDataByUnitId(targetUnit.Id, out var targetPlayer)) continue; if(!actionParams.MapData.SameUnion(targetPlayer.Id,selfPlayer.Id)) continue; targetUnit.AddSkill_Legacy(SkillType.MOVERANGEUP,actionParams.MapData,false,1,false,-1,false,SpecialAddSkillType.AddTurnLimit,0); targetUnit.AddSkill_Legacy(SkillType.HouraisanFrenchFakeMoon,actionParams.MapData,false,1,false, -1,false,SpecialAddSkillType.AddTurnLimit,0); targetUnit.AddSkill_Legacy(SkillType.KAGUYAFRENCHSYNERGY,actionParams.MapData,false,1,false, -1,false,SpecialAddSkillType.AddTurnLimit,0); if(targetUnit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true)??false) grid.Renderer(actionParams.MapData)?.PlayVFXInSight( new GridVFXParams(GridVFXType.SkillIcon, SkillType.HouraisanFrenchFakeMoon, targetUnit.UnitFullType)); } actionParams.UnitData.ClearActionPoint(); actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); return true; } public override bool CheckCan(CommonActionParams actionParam) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParam)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false; //step #3 check是否有CP释放技能 if (!UnitActionCheckUnitHasCP(actionParam)) return false; //step #4 check unit是否拥有skill技能 if (!UnitActionCheckUnitHasSkill(actionParam)) return false; return true; } public override bool CheckShow(CommonActionParams actionParam,out ShowType showType) { showType = ShowType.None; return CheckCan(actionParam); } } public class UnitActionMOKOUFRENCHBOOM : UnitActionAction { public UnitActionMOKOUFRENCHBOOM(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { if (actionParams.MapData == null) return false; var selfUnit = actionParams.UnitData; if (selfUnit == null) return false; var selfGrid = actionParams.GridData; if (selfGrid == null) { if (!actionParams.MapData.GetGridDataByUnitId(selfUnit.Id, out selfGrid)) return false; } if (!actionParams.MapData.GetPlayerDataByUnitId(selfUnit.Id, out var selfPlayer)) return false; _sharedAroundBuf ??= new List(); _sharedAroundBuf.Clear(); actionParams.MapData.GridMap.GetAroundGridData(1,1,selfGrid, _sharedAroundBuf); foreach (var grid in _sharedAroundBuf) { if (grid == selfGrid) continue; if(!grid.RealUnit(actionParams.MapData,out var targetUnit))continue; var dmg = Table.Instance.CalcDamage(actionParams.MapData,selfUnit,targetUnit,10); var dmgType = actionParams.MapData.SameUnionByUnitId(selfUnit.Id, targetUnit.Id) ? DamageType.KillSelf : DamageType.True; var settle = Main.UnitLogic.DamageSettlement(actionParams.MapData, selfUnit, targetUnit, dmg, dmgType); if (settle == null) continue; if (settle.DamageTargetGrid != null && settle.DamageTargetGrid.InMainSight()) { if (!settle.IsKill) { settle.DamageTargetGrid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Hurt)); targetUnit?.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); } else { if (targetUnit == null || targetUnit.CanBeKilled(actionParams.MapData)) settle.DamageTargetGrid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Die)); settle.DamageTargetGrid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Hurt)); settle.DamageTargetGrid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); targetUnit?.Renderer(actionParams.MapData)?.Die(); } } } Main.UnitLogic.DamageSettlement(actionParams.MapData, selfUnit, selfUnit, selfUnit.Health, DamageType.KillSelf); selfUnit.Renderer(actionParams.MapData)?.Die(); return true; } public override bool CheckCan(CommonActionParams actionParam) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParam)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false; //step #3 check是否有CP释放技能 if (!UnitActionCheckUnitHasCP(actionParam)) return false; //step #4 check unit是否拥有skill技能 if (!UnitActionCheckUnitHasSkill(actionParam)) return false; return true; } public override bool CheckShow(CommonActionParams actionParam,out ShowType showType) { showType = ShowType.None; return CheckCan(actionParam); } } public class UnitActionKAGUYAFRENCHAROUND : UnitActionAction { public UnitActionKAGUYAFRENCHAROUND(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { var selfUnit = actionParams.UnitData; var selfGrid = actionParams.GridData; if(selfGrid == null) if(!actionParams.MapData.GetGridDataByUnitId(selfUnit.Id, out selfGrid)) return false; if (!actionParams.MapData.GetPlayerDataByUnitId(selfUnit.Id, out var selfPlayer)) return false; _sharedAroundBuf ??= new List(); _sharedAroundBuf.Clear(); actionParams.MapData.GridMap.GetAroundGridData(1,1,selfGrid, _sharedAroundBuf); foreach (var grid in _sharedAroundBuf) { if (grid == selfGrid) continue; if(!grid.RealUnit(actionParams.MapData,out var targetUnit))continue; if(!actionParams.MapData.GetPlayerDataByUnitId(targetUnit.Id, out var targetPlayer)) continue; if(!actionParams.MapData.SameUnion(targetPlayer.Id,selfPlayer.Id)) continue; targetUnit.AddSkill_Legacy(SkillType.KAGUYAFRENCHFOREVERBUFF, actionParams.MapData,false,1,true,1,true,SpecialAddSkillType.AddLevel, selfUnit.Id); //if (targetUnit.GetSkill(SkillType.KAGUYAFRENCHFOREVERBUFF, out var skill)) //skill.AddLevel(actionParams.MapData, selfUnit, targetUnit, 1); targetUnit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); grid.Renderer(actionParams.MapData)?.PlayVFXInSight( new GridVFXParams(GridVFXType.SkillIcon, SkillType.KAGUYAFRENCHFOREVERBUFF, targetUnit.UnitFullType)); } actionParams.UnitData.ClearActionPoint(); actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); return true; } public override bool CheckCan(CommonActionParams actionParam) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParam)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false; //step #3 check是否有CP释放技能 if (!UnitActionCheckUnitHasCP(actionParam)) return false; //step #4 check unit是否拥有skill技能 if (!UnitActionCheckUnitHasSkill(actionParam)) return false; return true; } public override bool CheckShow(CommonActionParams actionParam,out ShowType showType) { showType = ShowType.None; return CheckCan(actionParam); } } public class UnitActionForceDisband : UnitActionAction { public UnitActionForceDisband(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { //Step #1 鲁棒性判断 if (actionParams.UnitData == null) return false; var unitData = actionParams.UnitData; var playerData = actionParams.PlayerData; if (playerData == null) if (!actionParams.MapData.GetPlayerDataByUnitId(actionParams.UnitData.Id, out playerData)) return false; if (!actionParams.MapData.GetGridDataByUnitId(actionParams.UnitData.Id, out var gridData)) return false; //Step #2 计算花费的金币数,增加金币 int earn = 0; //返还造价一半的金币 if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(actionParams.UnitData.UnitFullType, out var info )) return false; earn += info.Cost / 2; //如果是有carry技能,那么船和船上单位分开计费 if (actionParams.UnitData.CarryUnitType != UnitType.None && Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(actionParams.UnitData.CarryUnitType, GiantType.None,0, out var carryInfo)) earn += carryInfo.Cost / 2; //AddCoin自带动画考量 actionParams.PlayerData.AddCoin(earn,gridData); //Step #3 如果是真map,需要播放单位死亡动画 if (actionParams.MapData == Main.MapData) { //播放雾效 gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); //通知渲染器播放死亡 if(MapRenderer.Instance.ROUnitMap.TryGetValue(actionParams.UnitData.Id,out var renderer)) renderer.Die(); } //Step #4 单位彻底死亡 Main.UnitLogic.UnitUnnaturalDie(actionParams.MapData,actionParams.UnitData); return true; } public override bool CheckCan(CommonActionParams actionParam) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParam)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false; return true; } } public class UnitActionRemoveRedMist : UnitActionAction { public UnitActionRemoveRedMist(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { //Step #1 鲁棒性判断 var unit = actionParams.UnitData; if (unit == null || !unit.Grid(actionParams.MapData,out var grid)) return false; //Step #2 清除红雾 grid.RemoveSpType(GridSpType.RemiliaGrid,actionParams.MapData); unit.ClearActionPoint(); if (grid.InMainSight()) { grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); grid.Renderer(actionParams.MapData)?.InstantUpdateGrid(); unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(false); } return true; } public override bool CheckCan(CommonActionParams actionParams) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParams)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false; //#step #3 check 是否有CP if (actionParams.UnitData.GetActionPoint(ActionPointType.Capture) <= 0) return false; //#step #4 check 当前grid是否是remiliaGrid if (!actionParams.UnitData.Grid(actionParams.MapData, out var grid) || !grid.HasSpType(GridSpType.RemiliaGrid)) return false; //#step #5 部分格子无法清除红雾 if (grid.Resource == ResourceType.RemiliaMilitary) return false; //#step #6 如果是remilia阵营的单位,无法清除 var playerCivId = actionParams.UnitData.Player(actionParams.MapData)?.PlayerCivId; if (playerCivId is 0) return false; return true; } public override bool CheckShow(CommonActionParams actionParams,out ShowType showType) { showType = ShowType.None; return CheckCan(actionParams); } } public class UnitActionREMILIABUFF : UnitActionAction { public UnitActionREMILIABUFF(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { var selfUnit = actionParams.UnitData; var selfGrid = actionParams.GridData; if(selfGrid == null) if(!actionParams.MapData.GetGridDataByUnitId(selfUnit.Id, out selfGrid)) return false; if (!actionParams.MapData.GetPlayerDataByUnitId(selfUnit.Id, out var selfPlayer)) return false; _sharedAroundBuf ??= new List(); _sharedAroundBuf.Clear(); actionParams.MapData.GridMap.GetAroundGridData(1,1,selfGrid, _sharedAroundBuf); foreach (var grid in _sharedAroundBuf) { if (grid.Resource == ResourceType.CityCenter) continue; if (grid.Terrain != TerrainType.Land) continue; if (grid.HasSpType(GridSpType.RemiliaGrid)) continue; grid.AddSpType(GridSpType.RemiliaGrid,actionParams.MapData,selfUnit); if (grid.InMainSight()) { grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.RedMistCreate)); grid.Renderer(actionParams.MapData)?.InstantUpdateGrid(); if(grid.MainSelfPlayerVisibleUnit(out var gridUnit)) gridUnit.Renderer(actionParams.MapData)?.InstantUpdateUnit(false); } } actionParams.UnitData.ClearActionPoint(); actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); return true; } public override bool CheckCan(CommonActionParams actionParam) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParam)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false; //step #3 check是否有CP释放技能 if (!UnitActionCheckUnitHasCP(actionParam)) return false; //step #4 check unit是否拥有skill技能 if (!UnitActionCheckUnitHasSkill(actionParam)) return false; return true; } public override bool CheckShow(CommonActionParams actionParam,out ShowType showType) { showType = ShowType.None; return CheckCan(actionParam); } } public class UnitActionAbsorbRedMist : UnitActionAction { public UnitActionAbsorbRedMist(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { //Step #1 鲁棒性判断 var unit = actionParams.UnitData; if (unit == null || !unit.Grid(actionParams.MapData,out var grid)) return false; //Step #2 清除红雾 grid.RemoveSpType(GridSpType.RemiliaGrid,actionParams.MapData); if (grid.InMainSight()) { grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Heal)); grid.Renderer(actionParams.MapData)?.InstantUpdateGrid(); unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(false); } //Step #3 恢复血量 Main.UnitLogic.RecoverHealth_Legacy(actionParams.MapData,actionParams.UnitData,actionParams.UnitData,4); return true; } public override bool CheckCan(CommonActionParams actionParams) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParams)) return false; //#step #2 check unit属于player 且player是斯卡雷特阵营 if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false; if(actionParams.PlayerData.PlayerCivId != 0) return false; //#step #3 check GetActionPoint(ActionPointType.Capture) 不需要任何CP! //if (actionParams.UnitData.GetActionPoint(ActionPointType.Capture) <= 0) return false; //#step #4 check 当前grid是否是remiliaGrid if (!actionParams.UnitData.Grid(actionParams.MapData, out var grid) || !grid.HasSpType(GridSpType.RemiliaGrid)) return false; return true; } public override bool CheckShow(CommonActionParams actionParams,out ShowType showType) { showType = ShowType.None; return CheckCan(actionParams); } } public class UnitActionRemiliaAbsorb : UnitActionAction { public UnitActionRemiliaAbsorb(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { //Step #1 鲁棒性判断 var unit = actionParams.UnitData; if (unit == null || !unit.Grid(actionParams.MapData,out var grid)) return false; //Step #2 清除红雾 int count = 0; _sharedAroundBuf ??= new List(); _sharedAroundBuf.Clear(); actionParams.MapData.GridMap.GetAroundGridData(1, 1, grid, _sharedAroundBuf); foreach (var tgrid in _sharedAroundBuf) { if (!tgrid.HasSpType(GridSpType.RemiliaGrid)) continue; count++; tgrid.RemoveSpType(GridSpType.RemiliaGrid,actionParams.MapData); if (tgrid.InMainSight()) { tgrid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); tgrid.Renderer(actionParams.MapData)?.InstantUpdateGrid(); if(tgrid.RealUnit(actionParams.MapData,out var gridUnit)) gridUnit.Renderer(actionParams.MapData)?.InstantUpdateUnit(false); } } //Step #3 赋予buff unit.AddSkill_Legacy(SkillType.REMILIABUFF3, actionParams.MapData,false,0,true,count,true,SpecialAddSkillType.AddLevel,unit.Id); //if (unit.GetSkill(SkillType.REMILIABUFF3, out var skill)) //skill.AddLevel(actionParams.MapData, unit, unit, count); return true; } public override bool CheckCan(CommonActionParams actionParams) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParams)) return false; //#step #2 check unit属于player 且player是斯卡雷特阵营 if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false; if(actionParams.PlayerData.PlayerCivId != 0) return false; //#step #3 check GetActionPoint(ActionPointType.Capture) 当前单位拥有该技能 if (!actionParams.UnitData.GetSkill(SkillType.REMILIAABSORB, out var _)) return false; //#step #4 check 当前grid是否是remiliaGrid if (!actionParams.UnitData.Grid(actionParams.MapData, out var grid))return false; _sharedAroundBuf ??= new List(); _sharedAroundBuf.Clear(); actionParams.MapData.GridMap.GetAroundGridData(1, 1, grid, _sharedAroundBuf); bool hasRemiliaGrid = false; foreach (var tgrid in _sharedAroundBuf) if (tgrid.HasSpType(GridSpType.RemiliaGrid)) { hasRemiliaGrid = true; break; } if (!hasRemiliaGrid) return false; return true; } public override bool CheckShow(CommonActionParams actionParams,out ShowType showType) { showType = ShowType.None; return CheckCan(actionParams); } } public class UnitActionKanakoSit : UnitActionAction { public UnitActionKanakoSit(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { //Step #1 鲁棒性判断 var unit = actionParams.UnitData; if (unit == null || !unit.Grid(actionParams.MapData,out var grid)) return false; //Step #2 赋予buff unit.AddSkill_Legacy(SkillType.KANAKOSITTING, actionParams.MapData,true,-1,false,-1,false,SpecialAddSkillType.Force,0); //Step #3 消耗CP(不需要消耗) //unit.ClearAPMPCP(); //Step #4 刷新视觉 if (unit.InMainSight()) { unit.Renderer(actionParams.MapData).InstantUpdateUnit(showoff: true); grid.Renderer(actionParams.MapData).PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); } return true; } public override bool CheckCan(CommonActionParams actionParams) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParams)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false; //#step #3 check unitTypeData的EnableActions里包含此action,且不处在sit状态 if (!CheckUnitEnableAction(actionParams)) return false; if (actionParams.UnitData.GetSkill(SkillType.KANAKOSITTING, out var _)) return false; return true; } public override bool CheckShow(CommonActionParams actionParams,out ShowType showType) { showType = ShowType.None; return CheckCan(actionParams); } } public class UnitActionKanakoUnSit : UnitActionAction { public UnitActionKanakoUnSit(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { //Step #1 鲁棒性判断 var unit = actionParams.UnitData; if (unit == null || !unit.Grid(actionParams.MapData,out var grid)) return false; //Step #2 去除buff unit.RemoveSkill(SkillType.KANAKOSITTING, actionParams.MapData); //Step #3 消耗CP //unit.ClearAPMPCP(); //Step #4 刷新视觉 if (unit.InMainSight()) { unit.Renderer(actionParams.MapData).InstantUpdateUnit(showoff: true); grid.Renderer(actionParams.MapData).PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); } return true; } public override bool CheckCan(CommonActionParams actionParams) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParams)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false; //#step #3 check 当前单位正在Sit if (!actionParams.UnitData.GetSkill(SkillType.KANAKOSITTING, out var _)) return false; return true; } public override bool CheckShow(CommonActionParams actionParams,out ShowType showType) { showType = ShowType.None; return CheckCan(actionParams); } } public class UnitActionAyaMoveAgain : UnitActionAction { public UnitActionAyaMoveAgain(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { //Step #1 鲁棒性判断 if (actionParams?.MapData == null) return false; var unit = actionParams.UnitData; if (unit == null || !unit.Grid(actionParams.MapData,out var grid) || grid == null) return false; //Step #2 去除buff if (!unit.GetSkill(SkillType.AYAMOVEAGAIN, out var skill) || skill == null) return false; if (skill.Level <= 0) return false; skill.ReduceLevel(actionParams.MapData, actionParams.UnitData, 1); unit.AddActionPoint(ActionPointType.Move); //Step #4 刷新视觉 if (unit.InMainSight()) { unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(showoff: true); } return true; } public override bool CheckCan(CommonActionParams actionParams) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParams)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false; //#step #3 check 当前单位正在Sit if (!actionParams.UnitData.GetSkill(SkillType.AYAMOVEAGAIN, out var skill) || skill.Level <= 0) return false; return true; } public override bool CheckShow(CommonActionParams actionParams,out ShowType showType) { showType = ShowType.None; return CheckCan(actionParams); } } public class UnitActionKomeijiRinFire : UnitActionAction { public UnitActionKomeijiRinFire(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { var unit = actionParams.UnitData; if (unit == null || !unit.Grid(actionParams.MapData, out var grid)) return false; //Step #1 获取CorpseBuff层数 if (!unit.GetSkill(SkillType.CorpseBuff, out var corpseSkill)) return false; int level = corpseSkill.Level; if (level <= 0) return false; //Step #2 将CorpseBuff层数增加到RinFire上 unit.AddSkill_Legacy(SkillType.RinFire, actionParams.MapData, false, 0, true, level, false, SpecialAddSkillType.AddLevel, unit.Id); //Step #3 清除CorpseBuff unit.RemoveSkill(SkillType.CorpseBuff, actionParams.MapData); //Step #4 刷新视觉 if (unit.InMainSight()) { unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); } return true; } public override bool CheckCan(CommonActionParams actionParams) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParams)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false; //#step #3 check unitTypeData的EnableActions里包含此action if (!CheckUnitEnableAction(actionParams)) return false; //#step #4 check 当前unit拥有CorpseBuff且层数>0 if (!actionParams.UnitData.GetSkill(SkillType.CorpseBuff, out var corpseSkill) || corpseSkill.Level <= 0) return false; return true; } public override bool CheckShow(CommonActionParams actionParams, out ShowType showType) { showType = ShowType.None; //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParams)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false; //#step #3 check unitTypeData的EnableActions里包含此action if (!CheckUnitEnableAction(actionParams)) return false; //#step #4 check 当前unit拥有CorpseBuff if (!actionParams.UnitData.GetSkill(SkillType.CorpseBuff, out var _)) return false; return true; } } public class UnitActionKomeijiRinCityExp : UnitActionAction { public UnitActionKomeijiRinCityExp(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { var unit = actionParams.UnitData; if (unit == null || !unit.Grid(actionParams.MapData, out var grid)) return false; //Step #1 获取MahaCorpseBuff层数 if (!unit.GetSkill(SkillType.MahaCorpseBuff, out var mahaCorpseSkill)) return false; int level = mahaCorpseSkill.Level; if (level <= 0) return false; //Step #2 获取当前所处的我方城市 if (!actionParams.MapData.GetCityDataByTerritoryGid(grid.Id, out var city)) return false; if (!city.Player(actionParams.MapData, out var cityPlayer) || cityPlayer != actionParams.PlayerData) return false; //Step #3 将MahaCorpseBuff层数转化为CityExp Main.CityLogic.UpdateGrid_ViewOnly(actionParams.MapData, grid); Main.CityLogic.GridGiveCityExp_LogicView(actionParams.MapData, actionParams.PlayerData, city.Grid(actionParams.MapData), city, level); //Step #4 清除MahaCorpseBuff unit.RemoveSkill(SkillType.MahaCorpseBuff, actionParams.MapData); //Step #5 刷新视觉 if (unit.InMainSight()) { unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true); grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); } return true; } public override bool CheckCan(CommonActionParams actionParams) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParams)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false; //#step #3 check 是IndianRin英雄 if (actionParams.UnitData.GiantType != GiantType.IndianRin) return false; //#step #4 check unitTypeData的EnableActions里包含此action if (!CheckUnitEnableAction(actionParams)) return false; //#step #5 check 当前unit拥有MahaCorpseBuff且层数>0 if (!actionParams.UnitData.GetSkill(SkillType.MahaCorpseBuff, out var mahaCorpseSkill) || mahaCorpseSkill.Level <= 0) return false; //#step #6 check 当前所处我方城市领土 if (!actionParams.MapData.GetGridDataByUnitId(actionParams.UnitData.Id, out var grid)) return false; if (!actionParams.MapData.GetCityDataByTerritoryGid(grid.Id, out var city)) return false; if (!city.Player(actionParams.MapData, out var cityPlayer) || cityPlayer != actionParams.PlayerData) return false; return true; } public override bool CheckShow(CommonActionParams actionParams, out ShowType showType) { showType = ShowType.None; //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParams)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false; //#step #3 check 是IndianRin英雄 if (actionParams.UnitData.GiantType != GiantType.IndianRin) return false; //#step #4 check unitTypeData的EnableActions里包含此action if (!CheckUnitEnableAction(actionParams)) return false; //#step #5 check 当前unit拥有MahaCorpseBuff且层数>0 if (!actionParams.UnitData.GetSkill(SkillType.MahaCorpseBuff, out var mahaCorpseSkill) || mahaCorpseSkill.Level <= 0) return false; //#step #6 check 当前所处我方城市领土 if (!actionParams.MapData.GetGridDataByUnitId(actionParams.UnitData.Id, out var grid)) return false; if (!actionParams.MapData.GetCityDataByTerritoryGid(grid.Id, out var city)) return false; if (!city.Player(actionParams.MapData, out var cityPlayer) || cityPlayer != actionParams.PlayerData) return false; return true; } } //铃仙法式自爆:单纯消除自身,不产生任何其它效果 //语义等同于 UndeadSkill 的"消散"路径(UnitUnnaturalDie),因此无论是否持有 Undead 表现一致 public class UnitActionReisenFrenchBoom : UnitActionAction { public UnitActionReisenFrenchBoom(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { var unit = actionParams.UnitData; var map = actionParams.MapData; if (unit == null || !unit.Grid(map, out var grid)) return false; //缓存renderer,UnitUnnaturalDie会把unit从grid解绑 var unitRenderer = unit.Renderer(map); Main.UnitLogic.UnitUnnaturalDie(map, unit); if (map == Main.MapData) { unitRenderer?.Die(); grid.Renderer(map)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); grid.Renderer(map)?.InstantUpdateGrid(); } return true; } public override bool CheckCan(CommonActionParams actionParams) { if (!UnitActionCheckBaseInfo(actionParams)) return false; if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false; if (!CheckUnitEnableAction(actionParams)) return false; return true; } public override bool CheckShow(CommonActionParams actionParams, out ShowType showType) { showType = ShowType.None; if (!UnitActionCheckBaseInfo(actionParams)) return false; if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false; if (!CheckUnitEnableAction(actionParams)) return false; return true; } } public class UnitActionKomeijiBonePileBoom : UnitActionAction { public UnitActionKomeijiBonePileBoom(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { var unit = actionParams.UnitData; var map = actionParams.MapData; if (unit == null || !unit.Grid(map, out var grid)) return false; //Step #1 对周围1格范围的单位(不包括自己)造成2点溅射伤害并添加1层KomeijiFear _sharedAroundBuf ??= new List(); _sharedAroundBuf.Clear(); map.GridMap.GetAroundGridData(1, 1, grid, _sharedAroundBuf); foreach (var around in _sharedAroundBuf) { if (!around.RealUnit(map, out var target)) continue; if (target.Id == unit.Id) continue; // 缓存renderer,DamageSettlement可能导致单位死亡后无法获取 var targetRenderer = target.Renderer(map); if (map.IsLeagueOrJustBreakByUnit(unit.Id, target.Id)) continue; var settlement = Main.UnitLogic.DamageSettlement(map, unit, target, 2, DamageType.Splash); if (target.IsAlive()) { // 存活:添加恐惧并刷新UI if (!target.GetSkill(SkillType.KomeijiFearImmune, out _)) { target.AddOrOverrideSkill(SkillType.KomeijiFear, map, unit.Id); // 播放恐惧VFX around.Renderer(map)?.PlayVFXInSight(new GridVFXParams(GridVFXType.KomeijiFear)); } if (map == Main.MapData) { targetRenderer?.InstantUpdateUnit(false); targetRenderer?.RenderUpdateUnitImage(); } } else if (map == Main.MapData) { // 死亡:清除渲染 targetRenderer?.Die(); around.Renderer(map)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Die)); around.Renderer(map)?.InstantUpdateGrid(); } // 播放伤害VFX if (map == Main.MapData && settlement != null) { around.Renderer(map)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Hurt)); around.Renderer(map)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Damage, 2)); } } //Step #2 引爆后骨堆自身死亡 var unitRenderer = unit.Renderer(map); Main.UnitLogic.UnitUnnaturalDie(map, unit); if (map == Main.MapData) { unitRenderer?.Die(); grid.Renderer(map)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Die)); grid.Renderer(map)?.InstantUpdateGrid(); } return true; } public override bool CheckCan(CommonActionParams actionParams) { //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParams)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false; //#step #3 check unitTypeData的EnableActions里包含此action if (!CheckUnitEnableAction(actionParams)) return false; return true; } public override bool CheckShow(CommonActionParams actionParams, out ShowType showType) { showType = ShowType.None; //step #1 check基本信息 if (!UnitActionCheckBaseInfo(actionParams)) return false; //#step #2 check unit属于player if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false; //#step #3 check unitTypeData的EnableActions里包含此action if (!CheckUnitEnableAction(actionParams)) return false; return true; } } }