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);
        }
Beispiel #4
0
        /// <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);
        }
Beispiel #8
0
        /// <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);
        }
Beispiel #9
0
 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;
 }