public static Vector3 PatherTweenedPosRoot(VehicleCaravan caravan) { WorldGrid worldGrid = Find.WorldGrid; if (!caravan.Spawned) { return(worldGrid.GetTileCenter(caravan.Tile)); } if (caravan.vPather.Moving) { float num; if (!caravan.vPather.IsNextTilePassable()) { num = 0f; } else { num = 1f - caravan.vPather.nextTileCostLeft / caravan.vPather.nextTileCostTotal; } int tileID; if (caravan.vPather.nextTile == caravan.Tile && caravan.vPather.previousTileForDrawingIfInDoubt != -1) { tileID = caravan.vPather.previousTileForDrawingIfInDoubt; } else { tileID = caravan.Tile; } return(worldGrid.GetTileCenter(caravan.vPather.nextTile) * num + worldGrid.GetTileCenter(tileID) * (1f - num)); } return(worldGrid.GetTileCenter(caravan.Tile)); }
public static int CostToMove(VehicleCaravan caravan, int start, int end, int?ticksAbs = null, StringBuilder explanation = null, string caravanTicksPerMoveExplanation = null) { int caravanTicksPerMove = caravan.TicksPerMove; if (start == end) { return(0); } if (explanation != null) { explanation.Append(caravanTicksPerMoveExplanation); explanation.AppendLine(); } StringBuilder stringBuilder = (explanation != null) ? new StringBuilder() : null; float num = float.MaxValue; foreach (VehicleDef vehicle in caravan.UniqueVehicleDefsInCaravan().ToList()) { float numTmp = WorldVehiclePathGrid.CalculatedMovementDifficultyAt(end, vehicle, ticksAbs, stringBuilder); if (numTmp < num) { num = numTmp; } } float roadMovementDifficultyMultiplier = GetRoadMovementDifficultyMultiplier(caravan, start, end, stringBuilder); if (explanation != null) { explanation.AppendLine(); explanation.Append("TileMovementDifficulty".Translate() + ":"); explanation.AppendLine(); explanation.Append(stringBuilder.ToString().Indented(" ")); explanation.AppendLine(); explanation.Append(" = " + (num * roadMovementDifficultyMultiplier).ToString("0.#")); } int num2 = (int)(caravanTicksPerMove * num * roadMovementDifficultyMultiplier); num2 = Mathf.Clamp(num2, 1, MaxMoveTicks); if (explanation != null) { explanation.AppendLine(); explanation.AppendLine(); explanation.Append("FinalCaravanMovementSpeed".Translate() + ":"); int num3 = Mathf.CeilToInt(num2 / 1f); explanation.AppendLine(); explanation.Append(string.Concat(new string[] { " ", (60000f / caravanTicksPerMove).ToString("0.#"), " / ", (num * roadMovementDifficultyMultiplier).ToString("0.#"), " = ", (60000f / num3).ToString("0.#"), " " }) + "TilesPerDay".Translate()); } return(num2); }
private static bool DrawPosCollides(VehicleCaravan caravan) { Vector3 a = PatherTweenedPosRoot(caravan); float num = Find.WorldGrid.averageTileSize * BaseDistToCollide; List <VehicleCaravan> caravans = Find.WorldObjects.Caravans.Where(c => c is VehicleCaravan).Cast <VehicleCaravan>().ToList(); for (int i = 0; i < caravans.Count; i++) { VehicleCaravan caravan2 = caravans[i]; if (caravan2 != caravan && Vector3.Distance(a, PatherTweenedPosRoot(caravan2)) < num) { return(true); } } return(false); }
/// <summary> /// Create VehicleCaravan on World Map /// </summary> /// <param name="pawns"></param> /// <param name="faction"></param> /// <param name="startingTile"></param> /// <param name="addToWorldPawnsIfNotAlready"></param> /// <returns></returns> public static VehicleCaravan MakeVehicleCaravan(IEnumerable <Pawn> pawns, Faction faction, int startingTile, bool addToWorldPawnsIfNotAlready) { if (startingTile < 0 && addToWorldPawnsIfNotAlready) { Log.Warning("Tried to create a caravan but chose not to spawn a caravan but pass pawns to world. This can cause bugs because pawns can be discarded."); } List <Pawn> tmpPawns = new List <Pawn>(); tmpPawns.AddRange(pawns); VehicleCaravan caravan = (VehicleCaravan)WorldObjectMaker.MakeWorldObject(WorldObjectDefOfVehicles.VehicleCaravan); if (startingTile >= 0) { caravan.Tile = startingTile; } caravan.SetFaction(faction); if (startingTile >= 0) { Find.WorldObjects.Add(caravan); } for (int i = 0; i < tmpPawns.Count; i++) { Pawn pawn = tmpPawns[i]; if (pawn.Dead) { Log.Warning("Tried to form a caravan with a dead pawn " + pawn); } else { caravan.AddPawn(pawn, addToWorldPawnsIfNotAlready); if (addToWorldPawnsIfNotAlready && !pawn.IsWorldPawn()) { Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Decide); } } } caravan.Name = CaravanNameGenerator.GenerateCaravanName(caravan); caravan.SetUniqueId(Find.UniqueIDsManager.GetNextCaravanID()); return(caravan); }
public static Vector3 CaravanCollisionPosOffsetFor(VehicleCaravan caravan) { if (!caravan.Spawned) { return(Vector3.zero); } bool flag = caravan.Spawned && caravan.vPather.Moving; float d = BaseRadius * Find.WorldGrid.averageTileSize; if (!flag || caravan.vPather.nextTile == caravan.vPather.Destination) { int num; if (flag) { num = caravan.vPather.nextTile; } else { num = caravan.Tile; } GetCaravansStandingAtOrAboutToStandAt(num, out int num2, out int vertexIndex, caravan); if (num2 == 0) { return(Vector3.zero); } return(WorldRendererUtility.ProjectOnQuadTangentialToPlanet(Find.WorldGrid.GetTileCenter(num), GenGeo.RegularPolygonVertexPosition(num2, vertexIndex) * d)); } else { if (DrawPosCollides(caravan)) { Rand.PushState(); Rand.Seed = caravan.ID; float f = Rand.Range(0f, 360f); Rand.PopState(); Vector2 point = new Vector2(Mathf.Cos(f), Mathf.Sin(f)) * d; return(WorldRendererUtility.ProjectOnQuadTangentialToPlanet(PatherTweenedPosRoot(caravan), point)); } return(Vector3.zero); } }
private static void GetCaravansStandingAtOrAboutToStandAt(int tile, out int caravansCount, out int caravansWithLowerIdCount, VehicleCaravan forCaravan) { caravansCount = 0; caravansWithLowerIdCount = 0; List <VehicleCaravan> caravans = Find.WorldObjects.Caravans.Where(v => v is VehicleCaravan).Cast <VehicleCaravan>().ToList(); int i = 0; while (i < caravans.Count) { VehicleCaravan caravan = caravans[i]; if (caravan.Tile != tile) { if (caravan.vPather.Moving && caravan.vPather.nextTile == caravan.vPather.Destination) { if (caravan.vPather.Destination == tile) { goto IL_68; } } } else if (!caravan.vPather.Moving) { goto IL_68; } IL_82: i++; continue; IL_68: caravansCount++; if (caravan.ID < forCaravan.ID) { caravansWithLowerIdCount++; goto IL_82; } goto IL_82; } }
public WorldPath FindPath(int startTile, int destTile, VehicleCaravan caravan, Func <float, bool> terminator = null) { if (startTile < 0) { Log.Error(string.Concat(new object[] { "Tried to FindPath with invalid start tile ", startTile, ", caravan= ", caravan })); return(WorldPath.NotFound); } if (destTile < 0) { Log.Error(string.Concat(new object[] { "Tried to FindPath with invalid dest tile ", destTile, ", caravan= ", caravan })); return(WorldPath.NotFound); } if (!WorldVehicleReachability.Instance.CanReach(caravan, destTile)) { return(WorldPath.NotFound); } World world = Find.World; WorldGrid grid = world.grid; List <int> tileIDToNeighbors_offsets = grid.tileIDToNeighbors_offsets; List <int> tileIDToNeighbors_values = grid.tileIDToNeighbors_values; Vector3 normalized = grid.GetTileCenter(destTile).normalized; Dictionary <VehicleDef, float[]> movementDifficulty = WorldVehiclePathGrid.Instance.movementDifficulty; int num = 0; int num2 = (caravan != null) ? caravan.TicksPerMove : 3300; int num3 = CalculateHeuristicStrength(startTile, destTile); statusOpenValue += 2; statusClosedValue += 2; if (statusClosedValue >= 65435) { ResetStatuses(); } calcGrid[startTile].knownCost = 0; calcGrid[startTile].heuristicCost = 0; calcGrid[startTile].costNodeCost = 0; calcGrid[startTile].parentTile = startTile; calcGrid[startTile].status = statusOpenValue; openList.Clear(); openList.Push(new CostNode(startTile, 0)); while (openList.Count > 0) { CostNode costNode = openList.Pop(); if (costNode.cost == calcGrid[costNode.tile].costNodeCost) { int tile = costNode.tile; if (calcGrid[tile].status != statusClosedValue) { if (tile == destTile) { return(FinalizedPath(tile)); } if (num > SearchLimit) { Log.Warning(string.Concat(new object[] { caravan, " pathing from ", startTile, " to ", destTile, " hit search limit of ", SearchLimit, " tiles." })); return(WorldPath.NotFound); } int num4 = (tile + 1 < tileIDToNeighbors_offsets.Count) ? tileIDToNeighbors_offsets[tile + 1] : tileIDToNeighbors_values.Count; for (int i = tileIDToNeighbors_offsets[tile]; i < num4; i++) { int num5 = tileIDToNeighbors_values[i]; if (calcGrid[num5].status != statusClosedValue && caravan.UniqueVehicleDefsInCaravan().All(v => WorldVehiclePathGrid.Instance.Passable(num5, v)) && (!caravan.HasBoat() || !(Find.World.CoastDirectionAt(num5).IsValid&& num5 != destTile))) { float highestTerrainCost = caravan.UniqueVehicleDefsInCaravan().Max(v => movementDifficulty[v][num5]); int num6 = (int)(num2 * highestTerrainCost * VehicleCaravan_PathFollower.GetRoadMovementDifficultyMultiplier(caravan, tile, num5, null)) + calcGrid[tile].knownCost; ushort status = calcGrid[num5].status; if ((status != statusClosedValue && status != statusOpenValue) || calcGrid[num5].knownCost > num6) { Vector3 tileCenter = grid.GetTileCenter(num5); if (status != statusClosedValue && status != statusOpenValue) { float num7 = grid.ApproxDistanceInTiles(GenMath.SphericalDistance(tileCenter.normalized, normalized)); calcGrid[num5].heuristicCost = Mathf.RoundToInt(num2 * num7 * num3 * BestRoadDiscount); } int num8 = num6 + calcGrid[num5].heuristicCost; calcGrid[num5].parentTile = tile; calcGrid[num5].knownCost = num6; calcGrid[num5].status = statusOpenValue; calcGrid[num5].costNodeCost = num8; openList.Push(new CostNode(num5, num8)); } } } num++; calcGrid[tile].status = statusClosedValue; if (terminator != null && terminator(calcGrid[tile].costNodeCost)) { return(WorldPath.NotFound); } } } } Log.Warning(string.Concat(new object[] { caravan, " pathing from ", startTile, " to ", destTile, " ran out of tiles to process." })); return(WorldPath.NotFound); }
/// <summary> /// Despawn all <paramref name="pawns"/> and create VehicleCaravan WorldObject on World map /// </summary> /// <param name="pawns"></param> /// <param name="faction"></param> /// <param name="exitFromTile"></param> /// <param name="directionTile"></param> /// <param name="destinationTile"></param> /// <param name="sendMessage"></param> public static VehicleCaravan ExitMapAndCreateVehicleCaravan(IEnumerable <Pawn> pawns, Faction faction, int exitFromTile, int directionTile, int destinationTile, bool sendMessage = true) { if (!GenWorldClosest.TryFindClosestPassableTile(exitFromTile, out exitFromTile)) { Log.Error("Could not find any passable tile for a new caravan."); return(null); } if (Find.World.Impassable(directionTile)) { directionTile = exitFromTile; } List <Pawn> tmpPawns = new List <Pawn>(); tmpPawns.AddRange(pawns); Map map = null; for (int i = 0; i < tmpPawns.Count; i++) { AddCaravanExitTaleIfShould(tmpPawns[i]); map = tmpPawns[i].MapHeld; if (map != null) { break; } } VehicleCaravan caravan = MakeVehicleCaravan(tmpPawns, faction, exitFromTile, false); Rot4 exitDir = (map != null) ? Find.WorldGrid.GetRotFromTo(exitFromTile, directionTile) : Rot4.Invalid; for (int j = 0; j < tmpPawns.Count; j++) { tmpPawns[j].ExitMap(false, exitDir); } List <Pawn> pawnsListForReading = caravan.PawnsListForReading; for (int k = 0; k < pawnsListForReading.Count; k++) { if (!pawnsListForReading[k].IsWorldPawn()) { Find.WorldPawns.PassToWorld(pawnsListForReading[k], PawnDiscardDecideMode.Decide); } } if (map != null) { map.Parent.Notify_CaravanFormed(caravan); map.retainedCaravanData.Notify_CaravanFormed(caravan); } if (!caravan.vPather.Moving && caravan.Tile != directionTile) { caravan.vPather.StartPath(directionTile, null, true, true); caravan.vPather.nextTileCostLeft /= 2f; caravan.tweener.ResetTweenedPosToRoot(); } if (destinationTile != -1) { List <FloatMenuOption> list = FloatMenuMakerWorld.ChoicesAtFor(destinationTile, caravan); if (list.NotNullAndAny((FloatMenuOption x) => !x.Disabled)) { list.First((FloatMenuOption x) => !x.Disabled).action(); } else { caravan.vPather.StartPath(destinationTile, null, true, true); } } if (sendMessage) { TaggedString taggedString = "MessageFormedCaravan".Translate(caravan.Name).CapitalizeFirst(); if (caravan.vPather.Moving && caravan.vPather.ArrivalAction != null) { taggedString += " " + "MessageFormedCaravan_Orders".Translate() + ": " + caravan.vPather.ArrivalAction.Label + "."; } Messages.Message(taggedString, caravan, MessageTypeDefOf.TaskCompletion, true); } return(caravan); }
public VehicleCaravan_Tweener(VehicleCaravan caravan) { this.caravan = caravan; }
public static float GetRoadMovementDifficultyMultiplier(VehicleCaravan caravan, int fromTile, int toTile, StringBuilder explanation = null) { List <VehicleDef> vehicleDefs = caravan.UniqueVehicleDefsInCaravan().ToList(); return(GetRoadMovementDifficultyMultiplier(vehicleDefs, fromTile, toTile, explanation)); }
public static int CostToMove(VehicleCaravan caravan, int start, int end, int?ticksAbs = null) { return(CostToMove(caravan, start, end, ticksAbs, null, null)); }
public VehicleCaravan_PathFollower(VehicleCaravan caravan) { this.caravan = caravan; }