/* * @Author: 白哉 * @Description: 行为逻辑类 * @Date: 2025年04月10日 星期四 11:04:44 * @Modify: */ using System; using System.Collections.Generic; using System.Linq; using Logic.AI; using Logic.CrashSight; using RuntimeData; using TH1_Logic.Core; using UnityEngine; using TH1Renderer; using TH1Resource; using UnityEditor; using UnityEngineInternal; //这里是所有BuildAction派生子类的实现模块 namespace Logic.Action { // TrainUnit 训练单位类 public class TrainUnitAction : ActionLogicBase { public TrainUnitAction(CommonActionId id) : base(id) { } protected bool TrainUnitActionCheckBaseData(CommonActionParams actionParam) { if (actionParam.PlayerData == null) return false; return true; } protected bool TrainUnitActionCheckHasTech(CommonActionParams actionParam) { //如果没科技,return if(!actionParam.PlayerData.TechTree.CheckActionCan(_actionId)) return false; return true; } protected bool TrainUnitActionCheckWaterUnit() { if (Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_actionId.UnitType,_actionId.GiantType,_actionId.UnitLevel,out var info) && info.LandType == LandType.WaterAndAshore) return true; return false; } protected bool TrainUnitActionCheckCityFullPop(CommonActionParams actionParam) { if (actionParam.MainObjectType == MainObjectType.City) { if (actionParam.MapData.CheckIfCityFullPopulation(actionParam.CityData)) return true; } if (actionParam.MainObjectType == MainObjectType.Grid) { if (!actionParam.MapData.GetCityDataByTerritoryGid(actionParam.GridData.Id, out var city)) return true; if (actionParam.MapData.CheckIfCityFullPopulation(city)) return true; } return false; } protected bool TrainUnitActionCheckCityBelongPlayer(CommonActionParams actionParam) { if (actionParam.PlayerData == null) return false; if (!actionParam.MapData.GetPlayerDataByCityId(actionParam.CityData.Id, out var playerData) || playerData.Id != actionParam.PlayerData.Id) return false; return true; } protected bool TrainUnitActionCheckGridBelongPlayer(CommonActionParams actionParam) { if (actionParam.GridData == null || !actionParam.MapData.GetPlayerDataByTerritoryGridId(actionParam.GridData.Id, out var player)) return false; if (player.Id != actionParam.PlayerData.Id) return false; return true; } protected bool TrainUnitActionCheckUnitOnCity(CommonActionParams actionParam) { if (!actionParam.MapData.GetGridDataByCityId(actionParam.CityId, out var grid)) return true; if (actionParam.MapData.GetUnitDataByGid(grid.Id, out var unitData)) return true; return false; } protected bool TrainUnitActionCheckUnitOnGrid(CommonActionParams actionParam) { if (actionParam.MapData.GetUnitDataByGid(actionParam.GridData.Id, out var unitData)) return true; return false; } protected bool TrainUnitActionCheckMoneyEnough(CommonActionParams actionParam) { if (GetCost() > actionParam.PlayerData.PlayerWealth) return false; return true; } public override bool Execute(CommonActionParams actionParams, bool isMoment) { if (_actionId.UnitType == UnitType.None) return false; if (actionParams.MainObjectType == MainObjectType.City && actionParams.CityData == null) return false; if (actionParams.MainObjectType == MainObjectType.Grid && actionParams.GridData == null) return false; GridData gridData = null; CityData cityData = null; //如果是city产兵 if (actionParams.MainObjectType == MainObjectType.City) { cityData = actionParams.CityData; //从city处获得准确的gridData if (!actionParams.MapData.GetGridDataByCityId(actionParams.CityData.Id, out gridData)) return false; } //否则如果是grid产兵 if (actionParams.MainObjectType == MainObjectType.Grid) { //从actionParams获得准确的gridData gridData = actionParams.GridData; if (actionParams.CityData != null) cityData = actionParams.CityData; else actionParams.MapData.GetCityDataByTerritoryGid(gridData.Id, out cityData); } if (gridData == null) return false; //减去花费 actionParams.PlayerData.PlayerWealth -= GetCost(); //生产新单位 var newUnit = actionParams.MapData.AddUnitData(gridData.Id,cityData.Id,_actionId.UnitType,_actionId.GiantType); cityData.CityInfoRenderMark = true; //更新视野 Main.PlayerLogic.UpdateSight(actionParams.MapData,actionParams.PlayerData,actionParams.MapData.GridMap.GetAroundGridIdList(newUnit.GetSightRange(),gridData)); //如果是真mapdata,增加得分,然后处理得分动画 if (Main.MapData == actionParams.MapData)// && actionParams.PlayerData.Id == actionParams.MapData.PlayerMap.SelfPlayerData.Id) { var v1 = Table.Instance.GridToWorld(gridData); int score = GetCost() * 5; if (actionParams.PlayerData.Id == actionParams.MapData.PlayerMap.SelfPlayerData.Id) { var faithPanel = GameObject.Find("UICanvas/TopBarPanel/FaithPanel/Icon").transform; var endPos = faithPanel.position; MapRenderer.Instance.ProjectileManager.CreateProjectile(v1,endPos,ProjectileType.Faith,ProjectileMoveType.CoinParabola,score); } AchievementDataManager.Instance.OnTrainUnit(actionParams.MapData, actionParams.PlayerData, actionParams.CityData, newUnit); } return true; } public override bool CheckCan(CommonActionParams actionParam) { GridData gridData; PlayerData playerData; CityData cityData; //step #0 基础鲁棒性 (playerData不能为空) if (!TrainUnitActionCheckBaseData(actionParam)) return false; //Part1 如果是城市产兵 if (actionParam.MainObjectType == MainObjectType.City) { //step #1 city产兵的特殊鲁棒性 if (actionParam.CityData == null) return false; //step #2 check player操作的city 是不是自己的city,存储gridData if (!TrainUnitActionCheckCityBelongPlayer(actionParam)) return false; //step #3 赋值gridData(city的位置) if (!actionParam.MapData.GetGridDataByCityId(actionParam.CityData.Id, out gridData)) return false; //step #4如果没科技,return if(!TrainUnitActionCheckHasTech(actionParam)) return false; //step #5确认是否是水生unit if (TrainUnitActionCheckWaterUnit()) return false; //step #6 确认城市是否满员 if (TrainUnitActionCheckCityFullPop(actionParam)) return false; //step #7 如果城市上面有单位,不能生产,不显示 if (TrainUnitActionCheckUnitOnCity(actionParam)) return false; //step #8 判断钱够不够 if (!TrainUnitActionCheckMoneyEnough(actionParam)) return false; //step #9 只处理非英雄 if (_actionId.UnitType == UnitType.Giant) return false; return true; } //Part2 如果是grid产兵 if (actionParam.MainObjectType == MainObjectType.Grid) { //step #1 确认基础鲁棒性 if (actionParam.GridData == null) return false; gridData = actionParam.GridData; //step #2 进行基础赋值 if (!actionParam.MapData.GetCityDataByTerritoryGid(gridData.Id, out cityData)) return false; if (!actionParam.MapData.GetPlayerDataByCityId(cityData.Id, out playerData)) return false; //step #3 check city是不是player的 if (!TrainUnitActionCheckGridBelongPlayer(actionParam)) return false; //step #4 如果没科技,return if (!TrainUnitActionCheckHasTech(actionParam)) return false; //step #5 如果城市满员 if (TrainUnitActionCheckCityFullPop(actionParam)) return false; //step #6如果格子上面有单位,不能生产,不显示 if (TrainUnitActionCheckUnitOnGrid(actionParam)) return false; //step #7判断钱够不够 if (!TrainUnitActionCheckMoneyEnough(actionParam)) return false; //step #8 只处理非英雄 if (_actionId.UnitType == UnitType.Giant) return false; //----------终于进入正式的特判环节,前面都是通用判断,下面开始进入白名单 //Part 2.1 //红魔馆妖精女仆在树林生产 if (playerData.PlayerForceId == 0 && gridData.Vegetation == Vegetation.Trees && (gridData.Resource == ResourceType.Animal || gridData.Resource == ResourceType.None) && _actionId.UnitType == UnitType.Warrior) return true; //Part 2.2 //军营产兵 if (gridData.Resource == ResourceType.Military) { //step #1 如果水生unit,不行 if(TrainUnitActionCheckWaterUnit()) return false; //step #2 如果是伟人,return if (_actionId.UnitType == UnitType.Giant) return false; return true; } } return false; } public override bool CheckShow(CommonActionParams actionParam) { GridData gridData; PlayerData playerData; CityData cityData; //step #0 基础鲁棒性 (playerData不能为空) if (!TrainUnitActionCheckBaseData(actionParam)) return false; //Part1 如果是城市产兵 if (actionParam.MainObjectType == MainObjectType.City) { //step #1 city产兵的特殊鲁棒性 if (actionParam.CityData == null) return false; //step #2 check player操作的city 是不是自己的city,存储gridData if (!TrainUnitActionCheckCityBelongPlayer(actionParam)) return false; //step #3 赋值gridData(city的位置) if (!actionParam.MapData.GetGridDataByCityId(actionParam.CityData.Id, out gridData)) return false; //step #4如果没科技,return if(!TrainUnitActionCheckHasTech(actionParam)) return false; //step #5确认是否是水生unit if (TrainUnitActionCheckWaterUnit()) return false; //step #6 确认城市是否满员 //if (TrainUnitActionCheckCityFullPop(actionParam)) return false; //step #7 如果城市上面有单位,不能生产,不显示 if (TrainUnitActionCheckUnitOnCity(actionParam)) return false; //step #8 判断钱够不够 //if (!TrainUnitActionCheckMoneyEnough(actionParam)) return false; //step #9 只处理非英雄 if (_actionId.UnitType == UnitType.Giant) return false; return true; } //Part2 如果是grid产兵 if (actionParam.MainObjectType == MainObjectType.Grid) { //step #1 确认基础鲁棒性 if (actionParam.GridData == null) return false; gridData = actionParam.GridData; //step #2 进行基础赋值 if (!actionParam.MapData.GetCityDataByTerritoryGid(gridData.Id, out cityData)) return false; if (!actionParam.MapData.GetPlayerDataByCityId(cityData.Id, out playerData)) return false; //step #3 check city是不是player的 if (!TrainUnitActionCheckGridBelongPlayer(actionParam)) return false; //step #4 如果没科技,return if (!TrainUnitActionCheckHasTech(actionParam)) return false; //step #5 如果城市满员 //if (TrainUnitActionCheckCityFullPop(actionParam)) return false; //step #6如果格子上面有单位,不能生产,不显示 if (TrainUnitActionCheckUnitOnGrid(actionParam)) return false; //step #7判断钱够不够 //if(!TrainUnitActionCheckMoneyEnough(actionParam)) return false //step #8 只处理非英雄 if (_actionId.UnitType == UnitType.Giant) return false; //----------终于进入正式的特判环节,前面都是通用判断,下面开始进入白名单 //Part 2.1 //红魔馆妖精女仆在树林生产 if (playerData.PlayerForceId == 0 && gridData.Vegetation == Vegetation.Trees && (gridData.Resource == ResourceType.Animal || gridData.Resource == ResourceType.None) && _actionId.UnitType == UnitType.Warrior) return true; //Part 2.2 //军营产兵 if (gridData.Resource == ResourceType.Military) { //step #1 如果水生unit,不行 if(TrainUnitActionCheckWaterUnit()) return false; //step #2 如果是伟人,return if (_actionId.UnitType == UnitType.Giant) return false; return true; } } return false; } public override bool ExecuteViewBefore(CommonActionParams actionParams) { return false; } public override bool ExecuteViewAfter(CommonActionParams actionParams) { return false; } } public class TrainUnitActionTrainGiant : TrainUnitAction { private GridData _finalGrid; private CityData _finalCity; private UnitData _newUnit; public TrainUnitActionTrainGiant(CommonActionId id) : base(id){} //确认英雄的冷却cd private bool CheckGiantHasColdTime(CommonActionParams actionParam) { if (actionParam.PlayerData == null) return true; if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitType.Giant, _actionId.GiantType, 0, out var info)) return true; if (actionParam.PlayerData.giantPenalty[(uint)info.ChessType] > 0) return true; return false; } //判断场上的giant是否已经有一个了(会处理芙兰这种quartet的情况) private bool CheckGiantHasOne(CommonActionParams actionParam) { //获取unitTypeInfo,level=0时的信息 if(!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_actionId.UnitType, _actionId.GiantType,_actionId.UnitLevel, out var Lv0Info)) return true; //确认玩家最新的hero的unitLevel,获得level=realLv的info var realLv = Table.Instance.GiantExpToLevel(actionParam.PlayerData.giantExp[(uint)Lv0Info.ChessType]); if (!TrainUnitActionCheckHasTech(actionParam)) realLv = 0; if(!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_actionId.UnitType, _actionId.GiantType,(uint)realLv, out var info)) return true; //如果有Unique且全场已经有1个了 if (info.Skills.Contains(SkillType.UNIQUE)) { if (Main.PlayerLogic.GetMapUnitTypeCount(actionParam.MapData, _actionId.UnitType, _actionId.GiantType) > 0) return true; } //如果有DUO且全场已经有2个了 if (info.Skills.Contains(SkillType.DUO)) { if(Main.PlayerLogic.GetMapUnitTypeCount(actionParam.MapData,_actionId.UnitType, _actionId.GiantType) > 1) return true; } //如果有TRIO且全场已经有3个了 if (info.Skills.Contains(SkillType.TRIO)) { if(Main.PlayerLogic.GetMapUnitTypeCount(actionParam.MapData,_actionId.UnitType, _actionId.GiantType) > 2) return true; } //如果有QUARTER且全场已经有4个了 if (info.Skills.Contains(SkillType.QUARTET)) { if(Main.PlayerLogic.GetMapUnitTypeCount(actionParam.MapData,_actionId.UnitType, _actionId.GiantType) > 3) return true; } return false; } public override bool Execute(CommonActionParams actionParams, bool isMoment) { //step #0 鲁棒性检查 if (!CheckCan(actionParams)) return false; //step #1 获得准确的gridData和对应的cityData //step #1 part1 如果是city产英雄 if (actionParams.MainObjectType == MainObjectType.City) { _finalCity = actionParams.CityData; //从city处获得准确的gridData if (!actionParams.MapData.GetGridDataByCityId(actionParams.CityData.Id, out _finalGrid)) return false; } //step #1 part2 否则如果是grid产英雄 if (actionParams.MainObjectType == MainObjectType.Grid) { //从actionParams获得准确的gridData _finalGrid = actionParams.GridData; if (actionParams.CityData != null) _finalCity = actionParams.CityData; else actionParams.MapData.GetCityDataByTerritoryGid(_finalGrid.Id, out _finalCity); } if (_finalGrid == null) return false; //step #2 确定giant的真实level var realLv = actionParams.MapData.GetGiantRealLv(_actionId.GiantType,actionParams.PlayerData); //如果还没拥有科技,那只能是lv0 if (!TrainUnitActionCheckHasTech(actionParams)) realLv = 0; //step #3 生产新单位 _newUnit = actionParams.MapData.AddUnitData(_finalGrid.Id,_finalCity.Id,_actionId.UnitType,_actionId.GiantType,realLv); //step #4 更新新单位周围的视野 Main.PlayerLogic.UpdateSight(actionParams.MapData,actionParams.PlayerData,actionParams.MapData.GridMap.GetAroundGridIdList(_newUnit.GetSightRange(),_finalGrid)); return true; } public override bool CheckCan(CommonActionParams actionParam) { //step #0 基础鲁棒性 (playerData不能为空 不是英雄则直接排除 if(_actionId.UnitType != UnitType.Giant) return false; if (!TrainUnitActionCheckBaseData(actionParam)) return false; GridData gridData; PlayerData playerData; CityData cityData; //Part1 如果是城市产英雄 if (actionParam.MainObjectType == MainObjectType.City) { //step #1 city产兵的特殊鲁棒性 if (actionParam.CityData == null) return false; //step #2 check player操作的city 是不是自己的city,存储gridData if (!TrainUnitActionCheckCityBelongPlayer(actionParam)) return false; //step #3 赋值gridData(city的位置) if (!actionParam.MapData.GetGridDataByCityId(actionParam.CityData.Id, out gridData)) return false; //step #4如果没科技,且不是首发英雄,return if(!TrainUnitActionCheckHasTech(actionParam) && actionParam.PlayerData.FirstHero != _actionId.GiantType) return false; //step #5 确认城市是否满员 if (TrainUnitActionCheckCityFullPop(actionParam)) return false; //step #6 如果城市上面有单位,不能生产,不显示 if (TrainUnitActionCheckUnitOnCity(actionParam)) return false; //step #7 如果英雄在冷却cd if (CheckGiantHasColdTime(actionParam)) return false; //step #8 如果英雄违反了UNIQUE或类似的技能如QUARTET if (CheckGiantHasOne(actionParam)) return false; return true; } //Part2 如果是grid产英雄 if (actionParam.MainObjectType == MainObjectType.Grid) { //step #1 确认基础鲁棒性 if (actionParam.GridData == null) return false; gridData = actionParam.GridData; //step #2 进行基础赋值 if (!actionParam.MapData.GetCityDataByTerritoryGid(gridData.Id, out cityData)) return false; if (!actionParam.MapData.GetPlayerDataByCityId(cityData.Id, out playerData)) return false; //step #3 check grid是不是player的 if (!TrainUnitActionCheckGridBelongPlayer(actionParam)) return false; //step #4如果没科技,且不是首发英雄,return if(!TrainUnitActionCheckHasTech(actionParam) && actionParam.PlayerData.FirstHero != _actionId.GiantType) return false; //step #5 如果城市满员 if (TrainUnitActionCheckCityFullPop(actionParam)) return false; //step #6如果格子上面有单位,不能生产,不显示 if (TrainUnitActionCheckUnitOnGrid(actionParam)) return false; //step #7 如果英雄在冷却cd if (CheckGiantHasColdTime(actionParam)) return false; //step #8 如果英雄违反了UNIQUE或类似的技能如QUARTET if (CheckGiantHasOne(actionParam)) return false; if (_actionId.UnitType == UnitType.Giant && gridData.Resource == ResourceType.Military) return true; //Part 2.3 //下面全部是神像产兵 if (_actionId.UnitType == UnitType.Giant && _actionId.GiantType == GiantType.EgyptianFlandre && playerData.PlayerForceId == 0 && playerData.PlayerCivId == 0 && gridData.Resource == ResourceType.Temple) return true; if (_actionId.UnitType == UnitType.Giant && _actionId.GiantType == GiantType.EgyptianPatchouli && playerData.PlayerForceId == 0 && playerData.PlayerCivId == 0 && gridData.Resource == ResourceType.ForestTemple) return true; if (_actionId.UnitType == UnitType.Giant && _actionId.GiantType == GiantType.EgyptianMeiling && playerData.PlayerForceId == 0 && playerData.PlayerCivId == 0 && gridData.Resource == ResourceType.MountainTemple) return true; if (_actionId.UnitType == UnitType.Giant && _actionId.GiantType == GiantType.EgyptianSakuya && playerData.PlayerForceId == 0 && playerData.PlayerCivId == 0 && gridData.Resource == ResourceType.WaterTemple) return true; if (_actionId.UnitType == UnitType.Giant && _actionId.GiantType == GiantType.EgyptianRemilia && playerData.PlayerForceId == 0 && playerData.PlayerCivId == 0 && gridData.Resource == ResourceType.KingTemple) return true; } return false; } public override bool CheckShow(CommonActionParams actionParam) { //step #0 基础鲁棒性 (playerData不能为空 不是英雄则直接排除 if(_actionId.UnitType != UnitType.Giant) return false; if (!TrainUnitActionCheckBaseData(actionParam)) return false; GridData gridData; PlayerData playerData; CityData cityData; //Part1 如果是城市产英雄 if (actionParam.MainObjectType == MainObjectType.City) { //step #1 city产兵的特殊鲁棒性 if (actionParam.CityData == null) return false; //step #2 check player操作的city 是不是自己的city,存储gridData if (!TrainUnitActionCheckCityBelongPlayer(actionParam)) return false; //step #3 赋值gridData(city的位置) if (!actionParam.MapData.GetGridDataByCityId(actionParam.CityData.Id, out gridData)) return false; //step #4如果没科技,且不是首发英雄,return if(!TrainUnitActionCheckHasTech(actionParam) && actionParam.PlayerData.FirstHero != _actionId.GiantType) return false; //step #5 确认城市是否满员 //if (TrainUnitActionCheckCityFullPop(actionParam)) return false; //step #6 如果城市上面有单位,不能生产,不显示 if (TrainUnitActionCheckUnitOnCity(actionParam)) return false; //step #7 如果英雄在冷却cd //if (CheckGiantHasColdTime(actionParam)) return false; //step #8 如果英雄违反了UNIQUE或类似的技能如QUARTET if (CheckGiantHasOne(actionParam)) return false; return true; } //Part2 如果是grid产英雄 if (actionParam.MainObjectType == MainObjectType.Grid) { //step #1 确认基础鲁棒性 if (actionParam.GridData == null) return false; gridData = actionParam.GridData; //step #2 进行基础赋值 if (!actionParam.MapData.GetCityDataByTerritoryGid(gridData.Id, out cityData)) return false; if (!actionParam.MapData.GetPlayerDataByCityId(cityData.Id, out playerData)) return false; //step #3 check grid是不是player的 if (!TrainUnitActionCheckGridBelongPlayer(actionParam)) return false; //step #4如果没科技,且不是首发英雄,return if(!TrainUnitActionCheckHasTech(actionParam) && actionParam.PlayerData.FirstHero != _actionId.GiantType) return false; //step #5 如果城市满员 //if (TrainUnitActionCheckCityFullPop(actionParam)) return false; //step #6如果格子上面有单位,不能生产,不显示 if (TrainUnitActionCheckUnitOnGrid(actionParam)) return false; //step #7 如果英雄在冷却cd //if (CheckGiantHasColdTime(actionParam)) return false; //step #8 如果英雄违反了UNIQUE或类似的技能如QUARTET if (CheckGiantHasOne(actionParam)) return false; if (_actionId.UnitType == UnitType.Giant && gridData.Resource == ResourceType.Military) return true; //Part 2.3 //下面全部是神像产兵 if (_actionId.UnitType == UnitType.Giant && _actionId.GiantType == GiantType.EgyptianFlandre && playerData.PlayerForceId == 0 && playerData.PlayerCivId == 0 && gridData.Resource == ResourceType.Temple) return true; if (_actionId.UnitType == UnitType.Giant && _actionId.GiantType == GiantType.EgyptianPatchouli && playerData.PlayerForceId == 0 && playerData.PlayerCivId == 0 && gridData.Resource == ResourceType.ForestTemple) return true; if (_actionId.UnitType == UnitType.Giant && _actionId.GiantType == GiantType.EgyptianMeiling && playerData.PlayerForceId == 0 && playerData.PlayerCivId == 0 && gridData.Resource == ResourceType.MountainTemple) return true; if (_actionId.UnitType == UnitType.Giant && _actionId.GiantType == GiantType.EgyptianSakuya && playerData.PlayerForceId == 0 && playerData.PlayerCivId == 0 && gridData.Resource == ResourceType.WaterTemple) return true; if (_actionId.UnitType == UnitType.Giant && _actionId.GiantType == GiantType.EgyptianRemilia && playerData.PlayerForceId == 0 && playerData.PlayerCivId == 0 && gridData.Resource == ResourceType.KingTemple) return true; } return false; } public override bool ExecuteViewBefore(CommonActionParams actionParams) { return false; } public override bool ExecuteViewAfter(CommonActionParams actionParams) { //step #0 如果不是真map 不做动画 if (Main.MapData != actionParams.MapData) return false; //step #1 更新产兵的格子的renderMark _finalCity.CityInfoRenderMark = true; //step #2 增加得分,然后处理得分动画 var v1 = Table.Instance.GridToWorld(_finalGrid); int score = GetCost() * 5; if (actionParams.PlayerData.Id == actionParams.MapData.PlayerMap.SelfPlayerData.Id) { var faithPanel = GameObject.Find("UICanvas/TopBarPanel/FaithPanel/Icon").transform; var endPos = faithPanel.position; MapRenderer.Instance.ProjectileManager.CreateProjectile(v1,endPos,ProjectileType.Faith,ProjectileMoveType.CoinParabola,score); } AchievementDataManager.Instance.OnTrainUnit(actionParams.MapData, actionParams.PlayerData, actionParams.CityData, _newUnit); return false; } } }