/* * @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; //这里是所有BuildAction派生子类的实现模块 namespace Logic.Action { //GridMisc行为逻辑类,包括Destroy, ClearForest GrowForest BurnForest public class GridMiscAction : ActionLogicBase { public GridMiscAction(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { if (actionParams.PlayerData == null || actionParams.GridData == null) return false; if (!Table.Instance.ActionDataAssets.GetActionInfo(_actionId, out var actionInfo)) return false; if (!CheckCan(actionParams)) return false; //处理grow forest if (_actionId.GridMiscActionType == GridMiscActionType.GrowForest) { actionParams.PlayerData.PlayerWealth -= actionInfo.Cost; actionParams.GridData.Resource = ResourceType.None; actionParams.GridData.Vegetation = Vegetation.Trees; actionParams.GridData.Renderer(actionParams.MapData)?.SetUpdateGrid(true); //Step #1 处理因为树林变化带来的上方单位防御状态变化的情况 if (actionParams.MapData.GetUnitDataByGid(actionParams.GridData.Id, out var unit)) unit.RenderMark = true; //Step #2 如果player拥有bambooMove技能,更新城市连通性 if (actionParams.PlayerData.TechTree.CheckIfHasTechAtom(TechAtom.KaguyaFrenchBambooMove)) Main.PlayerLogic.UpdateCityConnect(actionParams.MapData,actionParams.PlayerData); //更新所有领土内的levelbuilding Main.PlayerLogic.UpdateTerritoryAllBuildingLevel(actionParams.MapData,actionParams.PlayerData.Id); return true; } //处理clear forest if (_actionId.GridMiscActionType == GridMiscActionType.ClearForest) { actionParams.PlayerData.PlayerWealth -= actionInfo.Cost; actionParams.GridData.Resource = ResourceType.None; actionParams.GridData.Vegetation = Vegetation.None; actionParams.GridData.Renderer(actionParams.MapData)?.SetUpdateGrid(true); //处理因为树林变化带来的上方单位防御状态变化的情况 if (actionParams.MapData.GetUnitDataByGid(actionParams.GridData.Id, out var unit)) unit.RenderMark = true; //更新所有领土内的levelbuilding Main.PlayerLogic.UpdateTerritoryAllBuildingLevel(actionParams.MapData,actionParams.PlayerData.Id); return true; } //处理 burn forest if (_actionId.GridMiscActionType == GridMiscActionType.BurnForest) { actionParams.PlayerData.PlayerWealth -= actionInfo.Cost; actionParams.GridData.Vegetation = Vegetation.None; actionParams.GridData.Resource = ResourceType.Crop; actionParams.GridData.Renderer(actionParams.MapData)?.SetUpdateGrid(true); //更新所有领土内的levelbuilding Main.PlayerLogic.UpdateTerritoryAllBuildingLevel(actionParams.MapData,actionParams.PlayerData.Id); return true; } //TODO Destroy整个改成更鲁棒的写法,不要逐一判断了,全部刷一遍levelbuilding就行了 //处理Destroy if (_actionId.GridMiscActionType == GridMiscActionType.Destroy) { //Debug.Log($"执行拆除!目标是{actionParams.GridData.Resource}"); if (!Table.Instance.GridAndResourceDataAssets.GetResourceInfo(actionParams.GridData.Resource, out var resourceInfo)) return false; //如果destroy的位置是无主地块 if (!actionParams.MapData.GetCityDataByTerritoryGid(actionParams.GridData.Id, out var cityData)) return false; var destroyGrid = actionParams.GridData; if (actionParams.GridData.Resource == ResourceType.Farm || actionParams.GridData.Resource == ResourceType.Mine || actionParams.GridData.Resource == ResourceType.LumberHut) { //在已经拆除前,记录下来周围的什么样的milllike建筑要被同时更新 ResourceType needUpdate = Table.Instance.GridAndResourceDataAssets.GetMillLikeRelative(actionParams.GridData.Resource); //Main.CityLogic.CityUpdateExp(actionParams.MapData, cityData, -resourceInfo.Exp); Main.CityLogic.CityExpDecrease(); actionParams.GridData.Resource = actionParams.GridData.ResourceUnderBuilding; actionParams.GridData.ResourceUnderBuilding = ResourceType.None; //更新周围的milllike建筑 var gridDataList1 = Main.PlayerLogic.GetPlayerResourceNearbyList(actionParams.MapData, actionParams.PlayerData, actionParams.GridData, needUpdate); //Debug.Log($"执行拆除!目标影响到了周围的{needUpdate},数量有是{gridDataList1.Count}"); foreach (var gridData1 in gridDataList1) { Main.CityLogic.UpdateGridBuildingData(actionParams.MapData, gridData1); //还要额外连带影响附近的market var gridDataList2 = Main.PlayerLogic.GetPlayerResourceNearbyList(actionParams.MapData, actionParams.PlayerData, gridData1, ResourceType.Market); foreach (var gridData2 in gridDataList2) Main.CityLogic.UpdateGridBuildingData(actionParams.MapData, gridData2); } } //处理windmill sawmill forge else if (actionParams.GridData.Resource == ResourceType.Windmill || actionParams.GridData.Resource == ResourceType.Forge || actionParams.GridData.Resource == ResourceType.Sawmill) { //对应城市先丢失exp //Main.CityLogic.CityUpdateExp(actionParams.MapData, cityData, -actionParams.GridData.buildingLevel * (actionParams.GridData.Resource == ResourceType.Forge ? 2 : 1)); Main.CityLogic.CityExpDecrease(); //删除格子的内容 actionParams.GridData.Resource = actionParams.GridData.ResourceUnderBuilding; actionParams.GridData.ResourceUnderBuilding = ResourceType.None; actionParams.GridData.buildingLevel = 0; //更新周围的market情况 var gridDataList = Main.PlayerLogic.GetPlayerResourceNearbyList(actionParams.MapData, actionParams.PlayerData, actionParams.GridData, ResourceType.Market); foreach (var gridData in gridDataList) Main.CityLogic.UpdateGridBuildingData(actionParams.MapData, gridData); //更新周围的academy情况 gridDataList = Main.PlayerLogic.GetPlayerResourceNearbyList(actionParams.MapData, actionParams.PlayerData, actionParams.GridData, ResourceType.Academy); foreach (var gridData in gridDataList) Main.CityLogic.UpdateGridBuildingData(actionParams.MapData, gridData); } //处理market else if (actionParams.GridData.Resource == ResourceType.Market) { actionParams.GridData.Resource = actionParams.GridData.ResourceUnderBuilding; actionParams.GridData.ResourceUnderBuilding = ResourceType.None; actionParams.GridData.buildingLevel = 0; } //处理港口和桥梁 else if(actionParams.GridData.Resource == ResourceType.Port || actionParams.GridData.Resource == ResourceType.Bridge) { //Main.CityLogic.CityUpdateExp(actionParams.MapData, cityData, -resourceInfo.Exp); Main.CityLogic.CityExpDecrease(); actionParams.GridData.Resource = actionParams.GridData.ResourceUnderBuilding; actionParams.GridData.ResourceUnderBuilding = ResourceType.None; Main.PlayerLogic.UpdateCityConnect(actionParams.MapData,actionParams.PlayerData); } //处理保护区 辉夜庭院等 else if (actionParams.GridData.Resource is ResourceType.Preserve or ResourceType.KaguyaFrenchYard) { actionParams.GridData.Resource = actionParams.GridData.ResourceUnderBuilding; actionParams.GridData.ResourceUnderBuilding = ResourceType.None; //更新所有领土内的levelbuilding Main.PlayerLogic.UpdateTerritoryAllBuildingLevel(actionParams.MapData,actionParams.PlayerData.Id); } //处理其他情况 else { actionParams.GridData.Resource = actionParams.GridData.ResourceUnderBuilding; actionParams.GridData.ResourceUnderBuilding = ResourceType.None; //Main.CityLogic.CityUpdateExp(actionParams.MapData, cityData, -resourceInfo.Exp); Main.CityLogic.CityExpDecrease(); } //如果上面有unit,更新对应的rendermakr if (actionParams.MapData.GetUnitDataByGid(actionParams.GridData.Id, out var unit)) unit.RenderMark = true; //保险起见,全部跑一遍builddinglevel的更新 (例如lumberhut destroy影响周围的保护区) Main.PlayerLogic.UpdateTerritoryAllBuildingLevel(actionParams.MapData,actionParams.PlayerData.Id); cityData.SetCityRenderer(actionParams.MapData); actionParams.GridData.Renderer(actionParams.MapData)?.SetUpdateGrid(true); //播放雾效 destroyGrid.Renderer(actionParams.MapData)?.PlayVFX(new GridVFXParams(GridVFXType.Fog)); return true; } return false; } public override bool CheckCan(CommonActionParams actionParams) { //如果是unit或者city来执行gridMisc操作,直接return false if (actionParams.MainObjectType != MainObjectType.Grid) return false; if (actionParams.GridData == null) return false; //如果没有对应科技,return false if (!actionParams.PlayerData.TechTree.CheckActionCan(_actionId)) return false; //如果有非联盟的敌人站在上面 if (actionParams.MapData.GetUnitDataByGid(actionParams.GridData.Id, out var unit) && !actionParams.MapData.CheckUnitIdBelongPlayerIdUnion(unit.Id, actionParams.PlayerData.Id)) return false; //如果在有主领土,判断是敌人还是自己 if (actionParams.MapData.GetPlayerDataByTerritoryGridId(actionParams.GridData.Id, out var playerData)) { //在敌人领土上,直接return false if (playerData != actionParams.PlayerData) return false; } //如果在无主领土 return false else return false; //判断钱够不够 if (GetCost() > actionParams.PlayerData.PlayerWealth) return false; //处理grow forest if (_actionId.GridMiscActionType == GridMiscActionType.GrowForest) { //如果不是crop或者none的land,直接return false if (actionParams.GridData.Terrain != TerrainType.Land ||(actionParams.GridData.Resource != ResourceType.None && actionParams.GridData.Resource != ResourceType.Crop && actionParams.GridData.Resource != ResourceType.Fruit)) return false; if (actionParams.GridData.Feature == TerrainFeature.Mountain) return false; if (actionParams.GridData.Vegetation == Vegetation.Trees) return false; return true; } //处理clear forest 和 burn forest if (_actionId.GridMiscActionType == GridMiscActionType.ClearForest || _actionId.GridMiscActionType == GridMiscActionType.BurnForest ) { //如果没有树林 或者 树林已经不是none或animal return false if (actionParams.GridData.Vegetation != Vegetation.Trees || (actionParams.GridData.Resource != ResourceType.None && actionParams.GridData.Resource != ResourceType.Animal)) return false; return true; } //处理Destroy if (_actionId.GridMiscActionType == GridMiscActionType.Destroy) { if (actionParams.GridData.Resource is ResourceType.Temple or ResourceType.ForestTemple or ResourceType.MountainTemple or ResourceType.WaterTemple or ResourceType.KingTemple or ResourceType.Windmill or ResourceType.Sawmill or ResourceType.Forge or ResourceType.LumberHut or ResourceType.Farm or ResourceType.Mine or ResourceType.Port or ResourceType.Market or ResourceType.Wonder or ResourceType.Academy or ResourceType.Preserve or ResourceType.Military or ResourceType.NavalBase or ResourceType.KaguyaFrenchYard) return true; //如果是桥梁,上面不能有人 if (actionParams.GridData.Resource is ResourceType.Bridge) { if (actionParams.MapData.GetUnitDataByGid(actionParams.GridData.Id, out var _)) return false; return true; } return false; } return false; } public override bool CheckShow(CommonActionParams actionParams) { //如果是unit或者city来执行gridMisc操作,直接return false if (actionParams.MainObjectType != MainObjectType.Grid) return false; if (actionParams.GridData == null) return false; //如果没有对应科技,return false if (!actionParams.PlayerData.TechTree.CheckActionCan(_actionId)) return false; //如果有非联盟的敌人站在上面 if (actionParams.MapData.GetUnitDataByGid(actionParams.GridData.Id, out var unit) && !actionParams.MapData.CheckUnitIdBelongPlayerIdUnion(unit.Id, actionParams.PlayerData.Id)) return false; //如果在有主领土,判断是敌人还是自己 if (actionParams.MapData.GetPlayerDataByTerritoryGridId(actionParams.GridData.Id, out var playerData)) { //在敌人领土上,直接return false if (playerData != actionParams.PlayerData) return false; } //如果在无主领土 return false else return false; //CheckShow 不需要判断金钱够不够 //if (GetCost() > actionParams.PlayerData.PlayerWealth) // return false; //处理grow forest if (_actionId.GridMiscActionType == GridMiscActionType.GrowForest) { //如果不是crop或者none的land,直接return false if (actionParams.GridData.Terrain != TerrainType.Land ||(actionParams.GridData.Resource != ResourceType.None && actionParams.GridData.Resource != ResourceType.Crop && actionParams.GridData.Resource != ResourceType.Fruit)) return false; if (actionParams.GridData.Feature == TerrainFeature.Mountain) return false; if (actionParams.GridData.Vegetation == Vegetation.Trees) return false; return true; } //处理clear forest 和 burn forest if (_actionId.GridMiscActionType == GridMiscActionType.ClearForest || _actionId.GridMiscActionType == GridMiscActionType.BurnForest ) { //如果没有树林 或者 树林已经不是none或animal return false if (actionParams.GridData.Vegetation != Vegetation.Trees || (actionParams.GridData.Resource != ResourceType.None && actionParams.GridData.Resource != ResourceType.Animal)) return false; return true; } //处理Destroy if (_actionId.GridMiscActionType == GridMiscActionType.Destroy) { if (actionParams.GridData.Resource is ResourceType.Temple or ResourceType.ForestTemple or ResourceType.MountainTemple or ResourceType.WaterTemple or ResourceType.KingTemple or ResourceType.Windmill or ResourceType.Sawmill or ResourceType.Forge or ResourceType.LumberHut or ResourceType.Farm or ResourceType.Mine or ResourceType.Port or ResourceType.Market or ResourceType.Wonder or ResourceType.Academy or ResourceType.Preserve or ResourceType.Military or ResourceType.NavalBase or ResourceType.KaguyaFrenchYard) return true; //如果是桥梁,上面不能有人 if (actionParams.GridData.Resource is ResourceType.Bridge) { if (actionParams.MapData.GetUnitDataByGid(actionParams.GridData.Id, out var _)) return false; return true; } return false; } return false; } public override ActionShowState CheckShowState(CommonActionParams actionParams) { return ActionShowState.None; } public override bool ExecuteViewBefore(CommonActionParams actionParams) { return false; } public override bool ExecuteViewAfter(CommonActionParams actionParams) { return false; } //付钱 protected bool GridMiscActionPayMoney(CommonActionParams actionParam) { if (actionParam.PlayerData.PlayerWealth - GetCost() < 0) return false; actionParam.PlayerData.PlayerWealth -= GetCost(); return true; } //确认是否满足基本信息 protected bool GridMiscActionCheckBaseInfo(CommonActionParams actionParam) { //如果是unit或者city来执行gridMisc操作,直接return false if (actionParam.MainObjectType != MainObjectType.Grid) return false; if (actionParam.GridData == null) return false; return true; } //确认是否有科技 protected bool GridMiscActionCheckHasTech(CommonActionParams actionParam) { //如果没有对应科技,return false if (!actionParam.PlayerData.TechTree.CheckActionCan(_actionId)) return false; return true; } //确认是否有钱 protected bool GridMiscActionCheckHasMoney(CommonActionParams actionParam) { //如果是upgradeTemple这种带参数的gridMisc,走这里 if (_actionId.GridMiscActionType == GridMiscActionType.UpgradeTemple) { if (GetCost(actionParam.GridData.buildingLevel) > actionParam.PlayerData.PlayerWealth) return false; return true; } //否则走这里 if (GetCost() > actionParam.PlayerData.PlayerWealth) return false; return true; } //确认是否在自己领土 protected bool GridMiscActionCheckInTerritory(CommonActionParams actionParam) { //如果在有主领土,判断是敌人还是自己 if (actionParam.MapData.GetPlayerDataByTerritoryGridId(actionParam.GridData.Id, out var playerData) && playerData == actionParam.PlayerData) return true; return false; } //确认是否有敌人占领 protected bool GridMiscActionCheckEnemyOccupy(CommonActionParams actionParam) { //如果有非联盟的敌人站在上面 if (actionParam.MapData.GetUnitDataByGid(actionParam.GridData.Id, out var unit) && !actionParam.MapData.CheckUnitIdBelongPlayerIdUnion(unit.Id, actionParam.PlayerData.Id)) return true; return false; } //确认该城市的唯一性并获得对应的building level protected bool GridMiscActionCheckHasOne(CommonActionParams actionParam,out int level) { if(actionParam.MapData.GetCityDataByTerritoryGid(actionParam.GridData.Id,out var city) && Main.CityLogic.GetBuildingLevelByCity(actionParam.MapData,city,_actionId.ResourceType,out level)) return true; level = 0; return false; } } public class GridMiscActionUpgradeTemple : GridMiscAction { public GridMiscActionUpgradeTemple(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { if (!CheckCan(actionParams)) return false; //step #1 扣钱 actionParams.PlayerData.PlayerWealth -= GetCost(actionParams.GridData.buildingLevel); //step #2 办事 升级temple actionParams.GridData.buildingLevel++; return true; } public override bool CheckCan(CommonActionParams actionParam) { //step #1 check基本信息 if (!GridMiscActionCheckBaseInfo(actionParam)) return false; //Step #2 check是否是temple if (!(actionParam.GridData.Resource is ResourceType.Temple or ResourceType.KingTemple or ResourceType.MountainTemple or ResourceType.WaterTemple or ResourceType.ForestTemple)) return false; //step #3 check是否有科技 if (!GridMiscActionCheckHasTech(actionParam)) return false; //step #4 check是否有钱 if (!GridMiscActionCheckHasMoney(actionParam)) return false; //step #5 check是否在我方领土 if (!GridMiscActionCheckInTerritory(actionParam)) return false; //step #6 check是否有敌人占领 if (GridMiscActionCheckEnemyOccupy(actionParam)) return false; //step #7 check 是否已经满级 if (actionParam.GridData.buildingLevel >= 5) return false; return true; } public override bool CheckShow(CommonActionParams actionParam) { //step #1 check基本信息 if (!GridMiscActionCheckBaseInfo(actionParam)) return false; //Step #2 check是否是temple if (!(actionParam.GridData.Resource is ResourceType.Temple or ResourceType.KingTemple or ResourceType.MountainTemple or ResourceType.WaterTemple or ResourceType.ForestTemple)) return false; //step #3 check是否有科技 if (!GridMiscActionCheckHasTech(actionParam)) return false; //step #4 check是否有钱 //if (!GridMiscActionCheckHasMoney(actionParam)) return false; //step #5 check是否在我方领土 if (!GridMiscActionCheckInTerritory(actionParam)) return false; //step #6 check是否有敌人占领 if (GridMiscActionCheckEnemyOccupy(actionParam)) return false; //step #7 check 是否已经满级 if (actionParam.GridData.buildingLevel >= 5) return false; return true; } public override bool ExecuteViewBefore(CommonActionParams actionParams) { return true; } public override bool ExecuteViewAfter(CommonActionParams actionParams) { //如果不是真mapdata在播放动画 if (Main.MapData != actionParams.MapData) return false; //更新地块视觉,播放烟雾特效 actionParams.GridData.Renderer(actionParams.MapData)?.SetUpdateGrid(true); actionParams.GridData.SetGridVFXRenderMark(new GridVFXRenderMark(GridVFXType.Fog)); return true; } } public class GridMiscActionGrowTreeOutside : GridMiscAction { public GridMiscActionGrowTreeOutside(CommonActionId id) : base(id) { } protected override bool Execute(CommonActionParams actionParams) { //if (!CheckCan(actionParams)) return false; //step #1 办事 种树 actionParams.GridData.Resource = ResourceType.None; actionParams.GridData.Vegetation = Vegetation.Trees; //Step #2 如果player拥有bambooMove技能,更新城市连通性 if (actionParams.PlayerData.TechTree.CheckIfHasTechAtom(TechAtom.KaguyaFrenchBambooMove)) Main.PlayerLogic.UpdateCityConnect(actionParams.MapData,actionParams.PlayerData); //Step #3 处理因为树林变化带来的上方单位防御状态变化的情况 if (actionParams.MapData.GetUnitDataByGid(actionParams.GridData.Id, out var unit)) unit.RenderMark = true; //Step #4 更改视觉 actionParams.GridData.Renderer(actionParams.MapData)?.SetUpdateGrid(true); actionParams.GridData.Renderer(actionParams.MapData)?.PlayVFX(new GridVFXParams(GridVFXType.Fog)); //step #5 扣钱 actionParams.PlayerData.PlayerWealth -= GetCost(); return true; } public override bool CheckCan(CommonActionParams actionParam) { //step #1 check基本信息 if (!GridMiscActionCheckBaseInfo(actionParam)) return false; //Step #2 check是否是中立领土,且terrain必须是land,Vegetarion必须是none,feature 必须不是mountain,resource只能是none fruit crop if (actionParam.MapData.GetPlayerDataByTerritoryGridId(actionParam.GridId, out var _)) return false; if (actionParam.GridData.Terrain != TerrainType.Land) return false; if (actionParam.GridData.Feature == TerrainFeature.Mountain) return false; if (!(actionParam.GridData.Resource is ResourceType.None or ResourceType.Fruit or ResourceType.Crop)) return false; if (actionParam.GridData.Vegetation == Vegetation.Trees) return false; //Step #3 if (!GridMiscActionCheckHasTech(actionParam)) return false; //step #4 check是否有钱 if (!GridMiscActionCheckHasMoney(actionParam)) return false; //step #5 check是否有敌人占领 if (GridMiscActionCheckEnemyOccupy(actionParam)) return false; return true; } public override bool CheckShow(CommonActionParams actionParam) { //step #1 check基本信息 if (!GridMiscActionCheckBaseInfo(actionParam)) return false; //Step #2 check是否是中立领土,且terrain必须是land,Vegetarion必须是none,feature 必须不是mountain,resource只能是none fruit crop if (actionParam.MapData.GetPlayerDataByTerritoryGridId(actionParam.GridId, out var _)) return false; if (actionParam.GridData.Terrain != TerrainType.Land) return false; if (actionParam.GridData.Feature == TerrainFeature.Mountain) return false; if (!(actionParam.GridData.Resource is ResourceType.None or ResourceType.Fruit or ResourceType.Crop)) return false; if (actionParam.GridData.Vegetation == Vegetation.Trees) return false; //Step #3 if (!GridMiscActionCheckHasTech(actionParam)) return false; //step #4 check是否有钱 这步不需要,没钱也可以show //if (!GridMiscActionCheckHasMoney(actionParam)) return false; //step #5 check是否有敌人占领 if (GridMiscActionCheckEnemyOccupy(actionParam)) return false; return true; } public override bool ExecuteViewBefore(CommonActionParams actionParams) { return true; } public override bool ExecuteViewAfter(CommonActionParams actionParams) { return true; } } }