private void SetIsTargetObjective(ICombatant combatant) { Main.LogDebug($"[SetUnitsInRegionToBeTaggedObjectiveTargetsResult] Setting isObjectiveTarget '{IsObjectiveTarget}' for '{combatant.GameRep.name} - {combatant.DisplayName}'"); ObstructionGameLogic obstructionGameLogic = combatant.GameRep.GetComponent <ObstructionGameLogic>(); obstructionGameLogic.isObjectiveTarget = true; if (Type == "Building") { BattleTech.Building building = combatant as BattleTech.Building; AccessTools.Field(typeof(BattleTech.Building), "isObjectiveTarget").SetValue(building, true); building.BuildingRep.IsTargetable = true; } CombatHUDInWorldElementMgr inworldElementManager = GameObject.Find("uixPrfPanl_HUD(Clone)").GetComponent <CombatHUDInWorldElementMgr>(); AccessTools.Method(typeof(CombatHUDInWorldElementMgr), "AddTickMark").Invoke(inworldElementManager, new object[] { combatant }); AccessTools.Method(typeof(CombatHUDInWorldElementMgr), "AddInWorldActorElements").Invoke(inworldElementManager, new object[] { combatant }); if (Type == "Building") { CombatHUDNumFlagHex numFlagEx = inworldElementManager.GetNumFlagForCombatant(combatant); CombatHUDFloatieStackActor floatie = inworldElementManager.GetFloatieStackForCombatant(combatant); numFlagEx.anchorPosition = CombatHUDInWorldScalingActorInfo.AnchorPosition.Feet; floatie.anchorPosition = CombatHUDInWorldScalingActorInfo.AnchorPosition.Feet; } }
public static void Postfix(Building __instance) { List <MapEncounterLayerDataCell> cells = ObstructionGameLogic.GetObstructionFromBuilding( __instance , UnityGameInstance.BattleTechGame.Combat.ItemRegistry) .occupiedCells; foreach (var cell in cells) { if (cell.relatedTerrainCell is MapTerrainDataCellEx ex) { ex.UpdateWaterHeight(); } } }
public void ResetAllBuildingData() { Main.LogDebug($"[EncounterDataManager.ResetAllBuildingData] Resetting all old building data"); List <BuildingRepresentation> buildingsInMap = GameObjextExtensions.GetBuildingsInMap(); foreach (BuildingRepresentation buildingRep in buildingsInMap) { BattleTech.Building building = buildingRep.ParentBuilding; if (building != null) { AccessTools.Field(typeof(BattleTech.Building), "isObjectiveTarget").SetValue(building, false); AccessTools.Field(typeof(BattleTech.Building), "isObjectiveActive").SetValue(building, false); building.objectiveGUIDS.Clear(); } ObstructionGameLogic obstructionGameLogic = buildingRep.GetComponent <ObstructionGameLogic>(); if (obstructionGameLogic != null) { obstructionGameLogic.isObjectiveTarget = false; } } }
public override void Trigger(MessageCenterMessage inMessage, string triggeringName) { Main.LogDebug($"[SetIsObjectiveTargetByTagResult] Setting IsObjectiveTarget '{IsObjectiveTarget}' with tags '{String.Concat(Tags)}'"); List <ICombatant> combatants = ObjectiveGameLogic.GetTaggedCombatants(UnityGameInstance.BattleTechGame.Combat, new TagSet(Tags)); Main.LogDebug($"[SetIsObjectiveTargetByTagResult] Found '{combatants.Count}' combatants"); foreach (ICombatant combatant in combatants) { BattleTech.Building building = combatant as BattleTech.Building; if (building != null) { Main.LogDebug($"[SetIsObjectiveTargetByTagResult] Found building '{building.GameRep.name} - {building.DisplayName}'"); ObstructionGameLogic obstructionGameLogic = building.GameRep.GetComponent <ObstructionGameLogic>(); obstructionGameLogic.isObjectiveTarget = true; AccessTools.Field(typeof(BattleTech.Building), "isObjectiveTarget").SetValue(combatant, true); } CombatHUDInWorldElementMgr inworldElementManager = GameObject.Find("uixPrfPanl_HUD(Clone)").GetComponent <CombatHUDInWorldElementMgr>(); AccessTools.Method(typeof(CombatHUDInWorldElementMgr), "AddTickMark").Invoke(inworldElementManager, new object[] { combatant }); AccessTools.Method(typeof(CombatHUDInWorldElementMgr), "AddInWorldActorElements").Invoke(inworldElementManager, new object[] { combatant }); } }
static void Postfix(LineOfSight __instance, Point p0, float height0, Point p1, float height1, Vector3 unitDelta, string targetGuid, ref float __result, CombatGameState ___Combat) { if (ModState.CurrentTurretForLOS == null) { return; } if (p0.X == p1.X && p0.Z == p1.Z) { __result = 0f; return; } if (!___Combat.MapMetaData.IsWithinBounds(p0) || !___Combat.MapMetaData.IsWithinBounds(p1)) { __result = float.MaxValue; return; } float numCellsX = Mathf.Abs(unitDelta.x) * (float)MapMetaDataExporter.cellSize; float numCellsY = Mathf.Abs(unitDelta.z) * (float)MapMetaDataExporter.cellSize; float lineDeltaX = (float)(p1.X - p0.X); float lineDeltaZ = (float)(p1.Z - p0.Z); float greatestDivisor = Mathf.Max(Mathf.Abs(lineDeltaX), Mathf.Abs(lineDeltaZ)); float stepHeight = (height1 - height0) / greatestDivisor; float sumVisionCost = 0f; Traverse projectedHeightAtT = Traverse.Create(__instance).Method("getProjectedHeightAt", new Type[] { typeof(Point), typeof(float), typeof(Point), typeof(float) }); Traverse visCostOfCellT = Traverse.Create(__instance).Method("visCostOfCell", new Type[] { typeof(MapTerrainDataCell), typeof(float) }); string shellBuildingGUID = ModState.AmbushTurretGUIDtoBuilding[ModState.CurrentTurretForLOS.GUID].GUID; EncounterLayerData encounterLayerData = ___Combat.EncounterLayerData; List <Point> list = BresenhamLineUtil.BresenhamLine(p0, p1); for (int i = 1; i < list.Count; i++) { float stepDelta; if (list[i].X != list[i - 1].X) { stepDelta = numCellsX; } else { stepDelta = numCellsY; } // Increment vision cost only slightly if it's inside our shell building if (encounterLayerData.mapEncounterLayerDataCells[list[i].Z, list[i].X].HasSpecifiedBuilding(shellBuildingGUID)) { Mod.Log.Trace?.Write($" Point x={list[i].X} z={list[i].Z} is inside the shell building, adding vision cost normally."); sumVisionCost += stepDelta; } else { float projectedHeightAt = projectedHeightAtT.GetValue <float>(new object[] { p0, height0, list[i], stepHeight }); MapTerrainDataCell mapTerrainDataCell = ___Combat.MapMetaData.mapTerrainDataCells[list[i].Z, list[i].X]; if (mapTerrainDataCell.cachedHeight > projectedHeightAt) { if (mapTerrainDataCell.MapEncounterLayerDataCell.HasBuilding) { for (int j = 0; j < mapTerrainDataCell.MapEncounterLayerDataCell.buildingList.Count; j++) { if (ObstructionGameLogic.GuidsMatchObjectOrRep(mapTerrainDataCell.MapEncounterLayerDataCell.buildingList[j].buildingGuid, targetGuid)) { __result = sumVisionCost; return; } } } __result = float.MaxValue; return; } sumVisionCost += visCostOfCellT.GetValue <float>(new object[] { mapTerrainDataCell, projectedHeightAt }) * stepDelta; } } __result = sumVisionCost; return; }
public void GenerateEncounterLayerBuildingData() { Main.Logger.LogDebug($"[EncounterDataManager.GenerateEncounterLayerBuildingData] Generating building data"); Terrain terrain = Terrain.activeTerrain; float terrainZSize = terrain.terrainData.size.z; float terrainXSize = terrain.terrainData.size.x; Vector3 terrainPosition = terrain.transform.position; float halfMapCellSize = (float)MapMetaDataExporter.cellSize / 2f; int halfMapCellSizeInt = MapMetaDataExporter.cellSize / 2; EncounterLayerParent encounterLayerParent = MissionControl.Instance.EncounterLayerParent; EncounterLayerData encounterLayerData = MissionControl.Instance.EncounterLayerData; MapMetaDataExporter mapMetaExporter = encounterLayerParent.GetComponent <MapMetaDataExporter>(); MapMetaData mapMetaData = UnityGameInstance.BattleTechGame.Combat.MapMetaData; Vector3 raycastOrigin = new Vector3(0f, 1000f, 0f); // Lookups Dictionary <string, int> regionRaycastHits = new Dictionary <string, int>(); List <RegionGameLogic> regionGameObjectList = new List <RegionGameLogic>(); List <ObstructionGameLogic> obstructionGameObjectList = new List <ObstructionGameLogic>(); // Marks only the ObstructionGameLogic objects for ray tracing for performance reasons AccessTools.Method(typeof(MapMetaDataExporter), "MarkCellsForRaycasting").Invoke(mapMetaExporter, new object[] { mapMetaData.mapTerrainDataCells, (int)terrain.transform.position.x, (int)terrain.transform.position.z }); // TODO: Maybe wipe region building lists. Not sure if I really need/want this yet RegionGameLogic[] componentsInChildren = encounterLayerData.GetComponentsInChildren <RegionGameLogic>(); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].InitRegionForRayCasting(); } // Iterate over the Z cell range for (float i = halfMapCellSize; i < terrainZSize; i += (float)MapMetaDataExporter.cellSize) { int zCellIndex = (int)i / MapMetaDataExporter.cellSize; // Iterate over the X cell range for (float j = halfMapCellSize; j < terrainXSize; j += (float)MapMetaDataExporter.cellSize) { int xCellIndex = (int)j / MapMetaDataExporter.cellSize; MapEncounterLayerDataCell mapEncounterLayerDataCell = new MapEncounterLayerDataCell(); if (mapMetaData.mapTerrainDataCells[zCellIndex, xCellIndex].doRayCast) { int hitIndex = 0; regionRaycastHits.Clear(); regionGameObjectList.Clear(); obstructionGameObjectList.Clear(); for (int k = -halfMapCellSizeInt; k < halfMapCellSizeInt; k++) { raycastOrigin.z = i + (float)k + terrainPosition.z; for (int l = -halfMapCellSizeInt; l < halfMapCellSizeInt; l++) { raycastOrigin.x = j + (float)l + terrainPosition.x; RaycastHit[] raycastHits = Physics.RaycastAll(raycastOrigin, Vector3.down); List <ObstructionGameLogic> list3 = new List <ObstructionGameLogic>(); // Go through all the raycasts at Z,X of the terrain by cell size (middle of cell) // Then find any regions hit, record the number of hits/cells the region has for (int m = 0; m < raycastHits.Length; m++) { RegionGameLogic regionGameLogic = raycastHits[m].transform.GetComponent <RegionGameLogic>(); if (regionGameLogic != null) { if (!regionRaycastHits.ContainsKey(regionGameLogic.encounterObjectGuid)) { regionRaycastHits[regionGameLogic.encounterObjectGuid] = 1; } else { string encounterObjectGuid = regionGameLogic.encounterObjectGuid; regionRaycastHits[encounterObjectGuid]++; } // Cache the region in the lookup if (!regionGameObjectList.Contains(regionGameLogic)) { regionGameObjectList.Add(regionGameLogic); } } ObstructionGameLogic obstructionGameLogicInParent = raycastHits[m].transform.GetComponentInParent <ObstructionGameLogic>(); if (obstructionGameLogicInParent != null && raycastHits[m].point.y > mapMetaData.mapTerrainDataCells[zCellIndex, xCellIndex].terrainHeight) { if (obstructionGameLogicInParent.IsBuildingHitAddWorthy) { if (!obstructionGameObjectList.Contains(obstructionGameLogicInParent)) { obstructionGameObjectList.Add(obstructionGameLogicInParent); } } Vector3 normal = raycastHits[m].normal; BuildingRaycastHit buildingRaycastHit = new BuildingRaycastHit { buildingSteepness = 90f - 57.29578f * Mathf.Atan2(normal.y, Mathf.Sqrt(normal.x * normal.x + normal.z * normal.z)), buildingHeight = raycastHits[m].point.y, buildingGuid = obstructionGameLogicInParent.encounterObjectGuid, hitIndex = hitIndex }; mapEncounterLayerDataCell.AddBuildingHit(buildingRaycastHit); } } hitIndex++; } } // For all the regions detected, if it exists in 10 or more cells - add the region to the map encounter layer data (this is vanilla... why?!) // And all all obstruction games logics to the region foreach (RegionGameLogic regionGameLogic in regionGameObjectList) { if (regionRaycastHits[regionGameLogic.encounterObjectGuid] >= 10) { mapEncounterLayerDataCell.AddRegion(regionGameLogic); foreach (ObstructionGameLogic obstructionGameLogic in obstructionGameObjectList) { regionGameLogic.AddBuildingGuidToRegion(obstructionGameLogic.encounterObjectGuid); } } } mapEncounterLayerDataCell.AverageTheBuildingHits(); mapEncounterLayerDataCell.SortBuildingListByHeight(); } encounterLayerData.mapEncounterLayerDataCells[zCellIndex, xCellIndex] = mapEncounterLayerDataCell; encounterLayerData.mapEncounterLayerDataCells[zCellIndex, xCellIndex].relatedTerrainCell = mapMetaData.mapTerrainDataCells[zCellIndex, xCellIndex]; mapMetaData.mapTerrainDataCells[zCellIndex, xCellIndex].MapEncounterLayerDataCell = mapEncounterLayerDataCell; } } }