using System.Collections.Generic; using Logic.CrashSight; using MongoDB.Driver.Core.Misc; using ParadoxNotion; using UnityEngine; using RuntimeData; using TH1_Anim; using TH1_Anim.Fragments; using TH1_Core.Events; using TH1_Core.Managers; using TH1_Logic.Core; using TH1_Presentation.Sequencer.Task; using TH1Renderer; namespace Logic { public class CityLogic : ICityLogic { bool needExplorer = false; int explorerStepMax = 10; int explorerStep = 0; Vector2Int explorerNowPos = new Vector2Int(); CityData explorerCityData; public void GenerateTribe(MapData mapData, Vector2Int tpos, int cid) { } public void TribeToCity(MapData mapData, PlayerData pd, CityData cd, UnitData ud) { } public void CityRemoveUnitFromList(MapData mapData, int uid, int cid) { } public void CityNewUnit(MapData mapData, int cid, UnitType unitType) { } public void CityExploit(MapData mapData, int cid, Vector2Int tpos, string actionName) { } //-------------------------------------- 构造方法 --------------------------------------// public CityLogic() { } public void Update() { } //-------------------------------------- 城市逻辑相关方法 --------------------------------------// // 更新城市等级 //用来增加城市经验,返回值表示本次升了几级,这里不能处理视觉 private int CityUpdateExp_LogicOnly(MapData mapData, CityData cityData, int exp) { cityData.LevelExp += exp; //cityData.CityInfoRenderer(mapData)?.SetUpdateCityInfo(true); return CityUpdateLevel(mapData, cityData); } //返回是否升级成功 private int CityUpdateLevel(MapData mapData, CityData cityData) { int tmp = cityData.Level; if (!cityData.TryUpgradeCity()) return 0; //cityData.GridRenderer(mapData)?.SetUpdateGrid(true); //cityData.CityInfoRenderer(mapData)?.SetUpdateCityInfo(true); //if (!mapData.GetGridDataByCityId(cityData.Id, out var gridData)) return 0; //gridData.Renderer(mapData)?.SetUpdateCityBuilding(true); var levelUp = cityData.Level - tmp; cityData.CityLevelUpPoint += levelUp; return levelUp; } //城市升级的唯一通用方法 ,处理了logic和view public bool GridGiveCityExp_LogicView(MapData map,PlayerData player,GridData grid,CityData city,int cityExp) { if (map == null || player == null || grid == null || city == null) return false; if (cityExp == 0) return false; int expPerStep = cityExp > 0 ? 1 : -1; var stepCount = Mathf.Abs(cityExp); //如果是真人玩家且exp>0 ,出发一组序列动画 if (player.IsSelfPlayer()) { //接下来需要1exp 1exp的增加来处理城市升级,否则可能出现连续升级城市选择坏掉的情况 for (int i = 0; i < stepCount; i++) { //Step #1逻辑层:处理城市获得cityExp int oldLevel = city.Level; int oldLevelExp = city.LevelExp; int levelup = Main.CityLogic.CityUpdateExp_LogicOnly(map,city,expPerStep); //Step #2 表现层:处理城市获得cityExp的动画 if (map.IsCurrentShowMap()) { if (player.IsSelfPlayer()) { PresentationManager.EnqueueTaskGroupCityExp(expPerStep,oldLevel,oldLevelExp,map,grid,city); //部分grid还需要增加faith /*if(grid.Resource == ResourceType.Wonder) player.AddFaith(300, grid);*/ } } } } //否则就是AI操作,直接更新grid的雾效,然后更新城市的cityInfo和cityBuilding else { int levelup = Main.CityLogic.CityUpdateExp_LogicOnly(map,city,cityExp); if (levelup > 0) { if (map.IsCurrentShowMap()) { //城市升级则播放雾效 city.Grid(Main.MapData)?.Renderer(Main.MapData)?.PlayVFX(new GridVFXParams(GridVFXType.Fog)); city.SetCityRenderer(map); } } } return true; } public bool UpdateGrid_ViewOnly(MapData map,GridData grid) { if (grid.InMainSight()) { //actionParams.GridData.Renderer(actionParams.MapData)?.PlayVFX(new GridVFXParams(GridVFXType.Fog)); PresentationManager.EnqueueGridUpdate(map,grid,GridUpdateType.BuildingUpdate); //var dataGridUpdate = FragmentDataFactory.Create(FragmentType.GridUpdate,GridUpdateType.BuildingUpdate, grid.Renderer(map)); //PresentationManager.EnqueueTask(new FragmentSequencerTask(FragmentFactory.Create(FragmentType.GridUpdate,dataGridUpdate))); //这里还可以处理如果有单位再上面的情况 if (map.GetUnitDataByGid(grid.Id, out var unit)) unit.Renderer(map)?.InstantUpdateUnit(true); } return true; } public bool CityExpDecrease() { return true; } // 将一个城市设置为首都 public void SetCapital(MapData mapData, uint cid) { if (!mapData.CityMap.GetCityById(cid, out CityData cityData)) return; cityData.SetCapital(true,mapData); } //更新grid的buildinglevel,并且顺带会更新城市的exp,用于例如种田后旁边的谷仓也升级 连带的城市升级行动序列 public bool UpdateGridBuildingData_LogicView(MapData mapData, GridData gridData) { //Step #1 计算最新的buildinglevel CalcGridBuildingLevel(mapData, gridData, gridData.Resource, out var level); if (!mapData.GetPlayerDataByTerritoryGridId(gridData.Id, out var player)) return false; if (!Table.Instance.GridAndResourceDataAssets.GetResourceInfo(gridData.Resource, out var resourceInfo)) { LogSystem.LogError($"CityLogic UpdateGridBuildingData can't find data asset of resource{gridData.Resource}"); return false; } //Step #2 计算这次的差量变化 int levelDelta = level - gridData.buildingLevel; int delta = (level - gridData.buildingLevel ) * resourceInfo.CityExpPerLevel; gridData.buildingLevel = level; if (!mapData.GetCityDataByTerritoryGid(gridData.Id, out var cityData)) return false; //Step #3 处理给城市经验,逻辑层&视觉层一同处理 if (delta != 0) GridGiveCityExp_LogicView(mapData,player,gridData,cityData,delta); //Step #4 如果仅仅是建筑变化,没有给城市经验,逻辑&视觉处理 if (delta == 0 && levelDelta != 0) { var data = FragmentDataFactory.Create(FragmentType.GridUpdate, GridUpdateType.FogDisappear, gridData.Renderer(mapData),Table.Instance.AnimDataAssets.GridUpdateAnimTime); PresentationManager.EnqueueTask(new FragmentSequencerTask(FragmentFactory.Create(FragmentType.GridUpdate, data))); } return true; } //获得一个city当前的科技点 public int GetCityTechPointPerTurn(MapData mapData, CityData cityData) { int ret = 0; if (GetBuildingLevelByCity(mapData, cityData, ResourceType.Academy, out var academyLevel)) ret = academyLevel; //增加保护区的科技 if (GetBuildingLevelByCity(mapData, cityData, ResourceType.Preserve, out var preserveLevel)) ret += preserveLevel; return ret; } //获得一个city当前的回合钱 public int GetCityStarsPerTurn(MapData mapData, CityData cityData) { //如果城市亏exp,要减少每回合的给钱数 int mins = 0; if (cityData.LevelExp < 0) mins = cityData.LevelExp; int ret = 0; ret = cityData.Level - 1 + cityData.ParkCount + (mapData.GetPlayerDataByCityId(cityData.Id,out var player) && Main.CityLogic.CheckCradleCapital(mapData,player,cityData) ? 1 : 0) + (cityData.Workshop ? 1 : 0) + mins; //增加集市的金钱 if (GetBuildingLevelByCity(mapData, cityData, ResourceType.Market, out var marketLevel)) ret += marketLevel; //增加kaguyaYard的金钱 if (GetBuildingLevelByCity(mapData, cityData, ResourceType.KaguyaFrenchYard, out var kaguyaYardLevel)) ret += kaguyaYardLevel; if (ret < 0) ret = 0; return ret; } //获得一个city当前的某种building的level public bool GetBuildingLevelByCity(MapData mapData, CityData cityData, ResourceType buildingType, out int level) { foreach (var gridId in cityData.Territory.TerritoryArea) { if (!mapData.GridMap.GetGridDataByGid(gridId, out var gridData)) continue; if (gridData.Resource == buildingType) { level = gridData.buildingLevel; return true; } } level = 0; return false; } // 城市升级领土 public void CityLevelUpActionExpand(MapData mapData, CityData cityData) { if (!mapData.GetGridDataByCityId(cityData.Id, out var gridData)) return; if (!mapData.GetPlayerDataByCityId(cityData.Id, out var playerData)) return; var aroundGridList = mapData.GridMap.GetAroundGridData(2, 2, gridData); Main.PlayerLogic.UpdateSight_LogicView(mapData,playerData,mapData.GridMap.GetAroundGridIdList(2,gridData)); var newTerritoryArea = new List(); foreach (var aroundGrid in aroundGridList) { if (mapData.GetPlayerDataByTerritoryGridId(aroundGrid.Id, out var playerData1)) continue; newTerritoryArea.Add(aroundGrid.Id); var t = new GridVFXParams(GridVFXType.Flag); t.CivId = playerData.PlayerCivId; aroundGrid.Renderer(mapData)?.PlayVFX(t); } cityData.Territory.UpdateTerritory(newTerritoryArea); var playerTerritoryGridIdSet = mapData.GetPlayerTerritoryGridIdSet(playerData.Id); foreach (var gridId in playerTerritoryGridIdSet) { if (!mapData.GridMap.GetGridDataByGid(gridId, out var gridData1)) continue; gridData1.Renderer(mapData)?.InstantUpdateGrid(true); } } // 查询如果gridData上有buildingType,那么它的level会是多少,bool返回他能否建设在这个位置 public bool CalcGridBuildingLevel(MapData mapData, GridData gridData,ResourceType buildingType,out int level) { if(!Table.Instance.GridAndResourceDataAssets.GetResourceInfo(buildingType,out var resourceInfo)) { LogSystem.LogError($"CityLogic CalcGridBuildingLevel cant get resourceInfo dataasset of {buildingType}"); level = 0; return false; } if (!resourceInfo.HasLevel) { level = 0; return false; } //获得周围一圈的grid,必须是我方 var aroundGridList = mapData.GridMap.GetAroundGridData(1,1,gridData); level = 0; bool ret = false; foreach (var grid in aroundGridList) { //如果就是中间这个格子,跳过 //if (grid == gridData) continue; //如果无主或者不是和gridData相同的领土,直接continue if (!mapData.GetPlayerDataByTerritoryGridId(grid.Id, out var playerData) || playerData != gridData.Player(mapData)) continue; //鲁棒性 + 获得该grid的cityData if (!mapData.GetCityDataByTerritoryGid(grid.Id, out var targetCityData)) continue; //处理market的情况 if (buildingType == ResourceType.Market) { if (grid.Resource is ResourceType.Forge or ResourceType.Windmill or ResourceType.Sawmill or ResourceType.Preserve or ResourceType.EgyptianIrrigation) { level += grid.buildingLevel; ret = true; } if (level > 8) level = 8; } //处理windmill forge话sawmill的情况 if ((grid.Resource == ResourceType.Farm && buildingType == ResourceType.Windmill) || (grid.Resource == ResourceType.Mine && buildingType == ResourceType.Forge) || (grid.Resource == ResourceType.LumberHut && buildingType == ResourceType.Sawmill)) { level++; ret = true; } //处理preserve if (grid.Vegetation == Vegetation.Trees && buildingType == ResourceType.Preserve) if (grid.Resource is ResourceType.None or ResourceType.Animal or ResourceType.Preserve) { level++; ret = true; } //处理academy if (buildingType == ResourceType.Academy) { if (grid.Feature == TerrainFeature.Mountain) { level++; ret = true; } if (grid.Resource == ResourceType.Preserve) { level+= grid.buildingLevel; ret = true; } if (grid.Resource == ResourceType.Forge) { level+= grid.buildingLevel; ret = true; } } //处理kaguyafrench yard if (buildingType == ResourceType.KaguyaFrenchYard) { if (grid.Resource == ResourceType.Animal) { level++; ret = true; } } //处理egyptianirrigation if (buildingType == ResourceType.EgyptianIrrigation) { if (grid.Resource == ResourceType.Farm) { level++; ret = true; } } } if (level > resourceInfo.MaxLevel) level = resourceInfo.MaxLevel; return ret; } //查询grid周围是否有某种resource public bool CheckAroundGridHasSomeResourceBelongPlayer(MapData mapData, GridData gridData,PlayerData playerData, ResourceType buildingType) { //step #1 获得周围一圈的grid,不管是不是我方 var aroundGridList = mapData.GridMap.GetAroundGridData(1,1,gridData); //step #2 逐一判断每个周围的grid foreach (var grid in aroundGridList) { //如果不是player的领土,continue if (!mapData.CheckIfGidBelongPid(grid.Id, mapData.PlayerMap.SelfPlayerId)) continue; if (grid.Resource == ResourceType.Port) return true; } return false; } //确认一个城市是不是当前玩家的原始首都 public bool CheckCradleCapital(MapData map,PlayerData player,CityData city) { return player.CradleCityId == city.Id && city.IsCapital && map.GetPlayerDataByCityId(city.Id, out var player2) && player2.Id == player.Id; } } }