public static RegionGameLogic CreateRegion(GameObject parent, string regionGameLogicGuid, string objectiveGuid, string name, string regionDefId, float radius = 0) { GameObject regionGo = CreateRegionGameObject(parent, name); float regionRadius = (radius > 0) ? radius : DEFAULT_REGION_RADIUS; MeshCollider collider = regionGo.AddComponent <MeshCollider>(); MeshFilter mf = regionGo.AddComponent <MeshFilter>(); Mesh mesh = MeshTools.CreateHexigon(regionRadius); collider.sharedMesh = mesh; mf.mesh = mesh; regionGo.AddComponent <TerrainDataChangeDetection>(); regionGo.AddComponent <SnapToTerrain>(); regionGo.AddComponent <MeshRenderer>(); RegionGameLogic regionGameLogic = regionGo.AddComponent <RegionGameLogic>(); regionGameLogic.encounterObjectGuid = regionGameLogicGuid; regionGameLogic.radius = regionRadius; regionGameLogic.regionDefId = regionDefId; regionGameLogic.alwaysShowRegionWhenActive = true; CreateRegionPointGameObject(regionGo, $"RegionPoint1", new Vector3(0, 0, regionRadius)); // North CreateRegionPointGameObject(regionGo, $"RegionPoint2", new Vector3(regionRadius, 0, regionRadius / 2f)); // North-East CreateRegionPointGameObject(regionGo, $"RegionPoint3", new Vector3(regionRadius, 0, -(regionRadius / 2f))); // South-East CreateRegionPointGameObject(regionGo, $"RegionPoint4", new Vector3(0, 0, -regionRadius)); // South CreateRegionPointGameObject(regionGo, $"RegionPoint5", new Vector3(-regionRadius, 0, -(regionRadius / 2f))); // South-West CreateRegionPointGameObject(regionGo, $"RegionPoint6", new Vector3(-regionRadius, 0, regionRadius / 2f)); // North-West return(regionGameLogic); }
private void RegenerateRegion(GameObject regionGo) { CombatGameState combatState = UnityGameInstance.BattleTechGame.Combat; RegionGameLogic regionGameLogic = regionGo.GetComponent <RegionGameLogic>(); List <Vector3> meshPoints = new List <Vector3>(); // Get all region points and fix the y height foreach (Transform t in regionGo.transform) { if (t.gameObject.name.StartsWith("RegionPoint")) { Vector3 position = t.position; float height = combatState.MapMetaData.GetLerpedHeightAt(position); Vector3 fixedHeightPosition = new Vector3(position.x, height, position.z); t.position = fixedHeightPosition; meshPoints.Add(t.localPosition); } } // Create new mesh from points and set to collider and mesh filter MeshCollider collider = regionGo.GetComponent <MeshCollider>(); MeshFilter mf = regionGo.GetComponent <MeshFilter>(); Mesh mesh = MeshTools.CreateHexigon(REGION_RADIUS, meshPoints); collider.sharedMesh = mesh; mf.mesh = mesh; List <MapEncounterLayerDataCell> cells = SceneUtils.GetMapEncounterLayerDataCellsWithinCollider(regionGo); for (int i = 0; i < cells.Count; i++) { MapEncounterLayerDataCell cell = cells[i]; cell.AddRegion(regionGameLogic); } }
public override void Trigger(MessageCenterMessage inMessage, string triggeringName) { Main.LogDebug("[PositionRegion] Positioning Region..."); GameObject regionGo = GameObject.Find(RegionName); CombatGameState combatState = UnityGameInstance.BattleTechGame.Combat; Team playerTeam = combatState.LocalPlayerTeam; Vector3 centerOfTeamMass = GetCenterOfTeamMass(playerTeam, true); Vector3 possiblePosition = Vector3.zero; AbstractActor actor = combatState.AllActors.First((AbstractActor x) => x.TeamId == playerTeam.GUID); while (possiblePosition == Vector3.zero || !PathFinderManager.Instance.IsSpawnValid(regionGo, possiblePosition, actor.GameRep.transform.position, UnitType.Mech, $"PositionRegionResult.{RegionName}")) { Main.LogDebug($"[PositionRegion] {(possiblePosition == Vector3.zero ? "Finding possible position..." : "Trying again to find a possible position...")}"); possiblePosition = SceneUtils.GetRandomPositionFromTarget(centerOfTeamMass, Main.Settings.DynamicWithdraw.MinDistanceForZone, Main.Settings.DynamicWithdraw.MaxDistanceForZone); } regionGo.transform.position = possiblePosition; // Debug // GameObjextExtensions.CreateDebugPoint("DEBUGCenterofTeamMassGizmo", centerOfTeamMass, Color.red); // GameObjextExtensions.CreateDebugPoint("DEBUGDynamicWithdrawCenter", regionGo.transform.position, Color.blue); RegionGameLogic regionGameLogic = regionGo.GetComponent <RegionGameLogic>(); regionGameLogic.Regenerate(); }
public static RegionGameLogic CreateWithdrawRegion(GameObject parent, string regionGameLogicGuid, string objectiveGuid, string name = null) { GameObject withdrawRegionGo = CreateWithdrawRegionGameObject(parent, name); MeshCollider collider = withdrawRegionGo.AddComponent <MeshCollider>(); MeshFilter mf = withdrawRegionGo.AddComponent <MeshFilter>(); Mesh mesh = MeshTools.CreateHexigon(REGION_RADIUS); collider.sharedMesh = mesh; mf.mesh = mesh; withdrawRegionGo.AddComponent <TerrainDataChangeDetection>(); withdrawRegionGo.AddComponent <SnapToTerrain>(); withdrawRegionGo.AddComponent <MeshRenderer>(); RegionGameLogic regionGameLogic = withdrawRegionGo.AddComponent <RegionGameLogic>(); regionGameLogic.encounterObjectGuid = regionGameLogicGuid; regionGameLogic.radius = REGION_RADIUS; regionGameLogic.regionDefId = "regionDef_EvacZone"; regionGameLogic.alwaysShowRegionWhenActive = true; CreateRegionPointGameObject(withdrawRegionGo, $"RegionPoint1", new Vector3(0, 0, REGION_RADIUS)); // North CreateRegionPointGameObject(withdrawRegionGo, $"RegionPoint2", new Vector3(REGION_RADIUS, 0, REGION_RADIUS / 2f)); // North-East CreateRegionPointGameObject(withdrawRegionGo, $"RegionPoint3", new Vector3(REGION_RADIUS, 0, -(REGION_RADIUS / 2f))); // South-East CreateRegionPointGameObject(withdrawRegionGo, $"RegionPoint4", new Vector3(0, 0, -REGION_RADIUS)); // South CreateRegionPointGameObject(withdrawRegionGo, $"RegionPoint5", new Vector3(-REGION_RADIUS, 0, -(REGION_RADIUS / 2f))); // South-West CreateRegionPointGameObject(withdrawRegionGo, $"RegionPoint6", new Vector3(-REGION_RADIUS, 0, REGION_RADIUS / 2f)); // North-West return(regionGameLogic); }
static void Postfix(RegionGameLogic __instance) { if (GizmoManager.GetInstance().IsGizmoModeActive&& GizmoManager.GetInstance().IsGizmoRegionModeActive) { MeshRenderer component = __instance.GetComponent <MeshRenderer>(); if (component != null) { component.enabled = true; } } }
public static void RemoveRegion(this MapEncounterLayerDataCell layerDataCell, RegionGameLogic regionGameLogic) { if (layerDataCell.regionGuidList == null) { return; } if (layerDataCell.regionGuidList.Contains(regionGameLogic.encounterObjectGuid)) { layerDataCell.regionGuidList.Remove(regionGameLogic.encounterObjectGuid); } }
public static void Regenerate(this RegionGameLogic regionGameLogic) { GameObject regionGo = regionGameLogic.gameObject; CombatGameState combatState = UnityGameInstance.BattleTechGame.Combat; List <Vector3> meshPoints = new List <Vector3>(); // Remove old region location from layer data cells List <MapEncounterLayerDataCell> beforeCells = SceneUtils.GetMapEncounterLayerDataCellsWithinCollider(regionGo); for (int i = 0; i < beforeCells.Count; i++) { MapEncounterLayerDataCell cell = beforeCells[i]; cell.RemoveRegion(regionGameLogic); } // Get all region points and fix the y height foreach (Transform t in regionGo.transform) { if (t.gameObject.name.StartsWith("RegionPoint")) { Vector3 position = t.position; float height = combatState.MapMetaData.GetLerpedHeightAt(position); Vector3 fixedHeightPosition = new Vector3(position.x, height, position.z); t.position = fixedHeightPosition; meshPoints.Add(t.localPosition); } } // Create new mesh from points and set to collider and mesh filter MeshCollider collider = regionGo.GetComponent <MeshCollider>(); MeshFilter mf = regionGo.GetComponent <MeshFilter>(); Mesh mesh = MeshTools.CreateHexigon(regionGameLogic.radius, meshPoints); collider.sharedMesh = mesh; mf.mesh = mesh; List <MapEncounterLayerDataCell> afterCells = SceneUtils.GetMapEncounterLayerDataCellsWithinCollider(regionGo); for (int i = 0; i < afterCells.Count; i++) { MapEncounterLayerDataCell cell = afterCells[i]; cell.AddRegion(regionGameLogic); } }
private void TagUnitsInRegion() { Main.LogDebug($"[SetUnitsInRegionToBeTaggedObjectiveTargetsResult] Tagging '{NumberOfUnits}' '{Type}' in region '{RegionGuid}'"); RegionGameLogic regionGameLogic = UnityGameInstance.BattleTechGame.Combat.ItemRegistry.GetItemByGUID <RegionGameLogic>(RegionGuid); if (regionGameLogic == null) { Main.Logger.LogError($"[SetUnitsInRegionToBeTaggedObjectiveTargetsResult] Region Not Found for Guid '{RegionGuid}'"); return; } if (Type == "Building") { List <BuildingRepresentation> buildingsInMap = GameObjextExtensions.GetBuildingsInMap(); Main.LogDebug($"[SetUnitsInRegionToBeTaggedObjectiveTargetsResult] Collected '{buildingsInMap.Count}' buildings to check."); if (NumberOfUnits > 0) { buildingsInMap.Shuffle(); } foreach (BuildingRepresentation building in buildingsInMap) { bool isBuildingInRegion = RegionUtil.PointInRegion(UnityGameInstance.BattleTechGame.Combat, building.transform.position, RegionGuid); if (isBuildingInRegion) { Main.LogDebug($"[SetUnitsInRegionToBeTaggedObjectiveTargetsResult] Found building '{building.gameObject.name}' in region!"); building.ParentBuilding.EncounterTags.UnionWith(Tags); SetTeam(building.ParentBuilding); SetIsTargetObjective(building.ParentBuilding); if (HasReachedUnitLimit()) { break; } } } } else { Main.LogDebug($"[SetUnitsInRegionToBeTaggedObjectiveTargetsResult] Tagging '{Type}' Not Yet Supported. Use 'TagUnitsInRegion'"); } }
public void BuildNormal() { string regionGuid = objective["Guid"].ToString(); string objectiveGuid = objective["ObjectiveGuid"].ToString(); float radius = objective.ContainsKey("Radius") ? (float)objective["Radius"] : (float)0; RegionGameLogic regionLogic = RegionFactory.CreateRegion(this.parent, regionGuid, objectiveGuid, this.name, regionDefId, radius); GameObject regionGo = regionLogic.gameObject; if (position != null) { SetPosition(regionGo, position); } if (rotation != null) { SetRotation(regionGo, rotation); } regionLogic.Regenerate(); }
public static List <MapEncounterLayerDataCell> GetMapEncounterLayerDataCellsWithinCollider(GameObject regionGo) { MeshCollider collider = regionGo.GetComponent <MeshCollider>(); RegionGameLogic regionGameLogic = regionGo.GetComponent <RegionGameLogic>(); List <MapEncounterLayerDataCell> cells = new List <MapEncounterLayerDataCell>(); Vector3 colliderExtents = collider.bounds.extents; Vector3 colliderCenter = collider.bounds.center; EncounterLayerData encounterLayerData = MissionControl.MissionControl.Instance.EncounterLayerData; int cellX = encounterLayerData.GetXIndex(colliderCenter.x); int cellZ = encounterLayerData.GetZIndex(colliderCenter.z); // Add center MapEncounterLayerDataCell layerDataCell = GetOrCreateEncounterLayerDataCell(cellX, cellZ); cells.Add(layerDataCell); float bottom = colliderCenter.x - colliderExtents.x; float top = colliderCenter.x + colliderExtents.x; float left = colliderCenter.z - colliderExtents.z; float right = colliderCenter.z + colliderExtents.z; for (float i = bottom; i < top; i += 0.5f) { for (float j = left; j < right; j += 0.5f) { cellX = encounterLayerData.GetXIndex(i); cellZ = encounterLayerData.GetZIndex(j); layerDataCell = GetOrCreateEncounterLayerDataCell(cellX, cellZ); if (layerDataCell != null) { cells.Add(layerDataCell); } } } return(cells); }
override protected BehaviorTreeResults Tick() { string regionGUID = RegionUtil.GetStayInsideRegionGUID(unit); if (regionGUID == null) { return(new BehaviorTreeResults(BehaviorNodeState.Failure)); } if (unit.IsInRegion(regionGUID)) { return(new BehaviorTreeResults(BehaviorNodeState.Success)); } ITaggedItem item = unit.Combat.ItemRegistry.GetItemByGUID(regionGUID); if (item == null) { Debug.Log("no item with GUID: " + regionGUID); return(new BehaviorTreeResults(BehaviorNodeState.Failure)); } RegionGameLogic region = item as RegionGameLogic; if (region == null) { Debug.Log("item is not region: " + regionGUID); return(new BehaviorTreeResults(BehaviorNodeState.Failure)); } // TODO: find a point inside the region, for now using the average of all vertices. int numPoints = region.regionPointList.Length; Vector3 destination = new Vector3(); for (int pointIndex = 0; pointIndex < numPoints; ++pointIndex) { destination += region.regionPointList[pointIndex].Position; } if (numPoints == 0) { Debug.Log("no points in region: " + regionGUID); return(new BehaviorTreeResults(BehaviorNodeState.Failure)); } destination = RoutingUtil.Decrowd(destination * 1.0f / numPoints, unit); destination = RegionUtil.MaybeClipMovementDestinationToStayInsideRegion(unit, destination); var cell = unit.Combat.MapMetaData.GetCellAt(destination); destination.y = cell.cachedHeight; if ((destination - unit.CurrentPosition).magnitude < 1) { // already close (should probably have been caught, above) return(new BehaviorTreeResults(BehaviorNodeState.Success)); } bool shouldSprint = unit.CanSprint; //float sprintRange = Mathf.Max(unit.MaxSprintDistance, unit.MaxWalkDistance); float moveRange = unit.MaxWalkDistance; if ((destination - unit.CurrentPosition).magnitude < moveRange) { shouldSprint = false; } if (shouldSprint) { unit.Pathing.SetSprinting(); } else { unit.Pathing.SetWalking(); } unit.Pathing.UpdateAIPath(destination, destination, shouldSprint ? MoveType.Sprinting : MoveType.Walking); Vector3 destinationThisTurn = unit.Pathing.ResultDestination; float movementBudget = unit.Pathing.MaxCost; PathNodeGrid grid = unit.Pathing.CurrentGrid; Vector3 successorPoint = destination; var longRangeToShorRangeDistanceThreshold = unit.BehaviorTree.GetBehaviorVariableValue(BehaviorVariableName.Float_LongRangeToShortRangeDistanceThreshold).FloatVal; if (grid.GetValidPathNodeAt(destinationThisTurn, movementBudget) == null || (destinationThisTurn - destination).magnitude > longRangeToShorRangeDistanceThreshold) { List <AbstractActor> lanceUnits = AIUtil.GetLanceUnits(unit.Combat, unit.LanceId); List <Vector3> path = DynamicLongRangePathfinder.GetDynamicPathToDestination(destination, movementBudget, unit, shouldSprint, lanceUnits, grid, 0); if (path == null || path.Count == 0) { return(new BehaviorTreeResults(BehaviorNodeState.Failure)); } destinationThisTurn = path[path.Count - 1]; Vector2 flatDestination = new Vector2(destination.x, destination.z); float currentClosestPointInRegionDistance = float.MaxValue; Vector3?closestPoint = null; for (int i = 0; i < path.Count; ++i) { Vector3 pointOnPath = path[i]; if (RegionUtil.PointInRegion(unit.Combat, pointOnPath, regionGUID)) { var distance = (flatDestination - new Vector2(pointOnPath.x, pointOnPath.z)).sqrMagnitude; if (distance < currentClosestPointInRegionDistance) { currentClosestPointInRegionDistance = distance; closestPoint = pointOnPath; } } } if (closestPoint != null) { destinationThisTurn = closestPoint.Value; } } Vector3 cur = unit.CurrentPosition; AIUtil.LogAI(string.Format("issuing order from [{0} {1} {2}] to [{3} {4} {5}] looking at [{6} {7} {8}]", cur.x, cur.y, cur.z, destinationThisTurn.x, destinationThisTurn.y, destinationThisTurn.z, successorPoint.x, successorPoint.y, successorPoint.z )); BehaviorTreeResults results = new BehaviorTreeResults(BehaviorNodeState.Success); MovementOrderInfo mvtOrderInfo = new MovementOrderInfo(destinationThisTurn, successorPoint); mvtOrderInfo.IsSprinting = shouldSprint; results.orderInfo = mvtOrderInfo; results.debugOrderString = string.Format("{0}: dest:{1} sprint:{2}", this.name, destination, mvtOrderInfo.IsSprinting); return(results); }
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; } } }