public static bool PopulateSaveableUpgrades(VehicleDef def, bool hardReset = false)
 {
     try
     {
         if (hardReset)
         {
             VehicleMod.settings.upgrades.upgradeSettings.Remove(def.defName);
         }
         if (def.HasComp(typeof(CompUpgradeTree)))
         {
             if (!VehicleMod.settings.upgrades.upgradeSettings.TryGetValue(def.defName, out var currentUpgradeDict))
             {
                 VehicleMod.settings.upgrades.upgradeSettings.Add(def.defName, new Dictionary <SaveableField, SavedField <object> >());
                 currentUpgradeDict = VehicleMod.settings.upgrades.upgradeSettings[def.defName];
                 foreach (UpgradeNode node in def.GetSortedCompProperties <CompProperties_UpgradeTree>().upgrades)
                 {
                     IterateUpgradeNode(def, node, ref currentUpgradeDict);
                 }
                 //Redundancy only
                 VehicleMod.settings.upgrades.upgradeSettings[def.defName] = currentUpgradeDict;
             }
         }
     }
     catch (Exception ex)
     {
         Log.Error($"Failed to populate upgrade settings for {def.defName}. Exception=\"{ex.Message}\"\nInnerException=\"{ex.InnerException}\"");
         return(false);
     }
     return(true);
 }
示例#2
0
 public void Initialize(VehicleDef def)
 {
     if (!cells.NullOrEmpty())
     {
         Hitbox = cells;
     }
     else
     {
         CellRect       rect  = CellRect.CenteredOn(new IntVec3(0, 0, 0), def.Size.x, def.Size.z);
         List <IntVec3> cells = new List <IntVec3>();
         if (side == VehicleComponentPosition.Body)
         {
             cells = rect.Cells.ToList();
         }
         else if (side == VehicleComponentPosition.BodyNoOverlap)
         {
             foreach (var cell in rect.Cells.Where(c => !def.components.Where(cp => noOverlapWith.Contains(cp.hitbox.side)).Any(cp => cp.hitbox.Contains(c))))
             {
                 cells.Add(new IntVec3(cell.x, 0, cell.z));
             }
         }
         else
         {
             cells = rect.GetEdgeCells(RotationFromSide(side)).ToList();
         }
         List <IntVec2> intVec2s = new List <IntVec2>();
         foreach (IntVec3 cell in cells)
         {
             intVec2s.Add(new IntVec2(cell.x, cell.z));
         }
         Hitbox = intVec2s;
     }
 }
示例#3
0
        public static float GetCurrentWinterMovementDifficultyOffset(int tile, VehicleDef vehicleDef, int?ticksAbs = null, StringBuilder explanation = null)
        {
            if (ticksAbs == null)
            {
                ticksAbs = new int?(GenTicks.TicksAbs);
            }
            Vector2 vector = Find.WorldGrid.LongLatOf(tile);

            SeasonUtility.GetSeason(GenDate.YearPercent(ticksAbs.Value, vector.x), vector.y, out float num, out float num2, out float num3, out float num4, out float num5, out float num6);
            float num7 = num4 + num6;

            num7 *= Mathf.InverseLerp(MaxTempForWinterOffset, 0f, GenTemperature.GetTemperatureFromSeasonAtTile(ticksAbs.Value, tile));
            if (num7 > 0.01f)
            {
                float num8 = WinterMovementDifficultyOffset * num7;
                if (explanation != null)
                {
                    explanation.AppendLine();
                    explanation.Append("Winter".Translate());
                    if (num7 < 0.999f)
                    {
                        explanation.Append(" (" + num7.ToStringPercent("F0") + ")");
                    }
                    explanation.Append(": ");
                    explanation.Append(num8.ToStringWithSign("0.#"));                     //REDO - Add translated text for winter path cost multiplier
                }
                return(num8 * vehicleDef.properties.winterPathCostMultiplier);
            }
            return(0f);
        }
 public virtual void ResolveReferences(VehicleDef def)
 {
     if (efficiency is null)
     {
         efficiency = new SimpleCurve()
         {
             new CurvePoint(0.25f, 0),
             new CurvePoint(0.35f, 0.35f),
             new CurvePoint(0.75f, 0.75f),
             new CurvePoint(0.85f, 1),
             new CurvePoint(1, 1)
         };
     }
     if (categories is null)
     {
         categories = new List <VehicleStatCategoryDef>();
     }
     if (compClass is null)
     {
         compClass = typeof(VehicleComponent);
     }
     if (!explosionProperties.Empty)
     {
         explosionProperties.Def = DefDatabase <DamageDef> .GetNamed(explosionProperties.damageDef);
     }
     hitbox.Initialize(def);
 }
 public static bool PopulateSaveableFields(VehicleDef def, bool hardReset = false)
 {
     try
     {
         if (hardReset)
         {
             VehicleMod.settings.vehicles.fieldSettings.Remove(def.defName);
         }
         if (!VehicleMod.settings.vehicles.fieldSettings.TryGetValue(def.defName, out var currentDict))
         {
             VehicleMod.settings.vehicles.fieldSettings.Add(def.defName, new Dictionary <SaveableField, SavedField <object> >());
             currentDict = VehicleMod.settings.vehicles.fieldSettings[def.defName];
         }
         IterateTypeFields(def, def.GetType(), def, ref currentDict);
         foreach (CompProperties props in def.comps)
         {
             IterateTypeFields(def, props.GetType(), props, ref currentDict);
         }
         //Redundancy only
         VehicleMod.settings.vehicles.fieldSettings[def.defName] = currentDict;
     }
     catch (Exception ex)
     {
         Log.Error($"Failed to populate field settings for <text>{def.defName}</text>.\nException=\"{ex.Message}\"\nInnerException=\"{ex.InnerException}\"");
         return(false);
     }
     return(true);
 }
        /// <summary>
        /// Generate VehicleSkyfaller with newly generated vehicle
        /// </summary>
        /// <param name="def">test</param>
        /// <param name="vehicleDef"></param>
        /// <param name="faction"></param>
        public static VehicleSkyfaller MakeSkyfaller(ThingDef def, VehicleDef vehicleDef, Faction faction, bool randomizeColors = false, bool randomizeMask = false, bool cleanSlate = true)
        {
            VehicleSkyfaller skyfaller = (VehicleSkyfaller)ThingMaker.MakeThing(def);

            skyfaller.vehicle = VehicleSpawner.GenerateVehicle(new VehicleGenerationRequest(vehicleDef, faction, randomizeColors, randomizeMask, cleanSlate));
            return(skyfaller);
        }
示例#7
0
 public SaveableDefPair(VehicleDef def, FieldInfo field, string uniqueKey, K key, LookMode valueLookMode) : base(def, field)
 {
     this.key           = key;
     defName            = key.defName;
     this.uniqueKey     = uniqueKey;
     this.valueLookMode = valueLookMode;
     keyType            = typeof(K);
 }
示例#8
0
        public void ResolvePostToSettings(VehicleDef def, ref Dictionary <SaveableField, SavedField <object> > currentDict)
        {
            FieldInfo dictField = SettingsCache.GetCachedField(typeof(StatUpgrade), nameof(values));

            foreach (var statUpgrade in values)
            {
                SaveableDefPair <StatUpgradeCategoryDef> saveable = new SaveableDefPair <StatUpgradeCategoryDef>(def, dictField, string.Concat(statUpgrade.Key.defName, "_", upgradeID), statUpgrade.Key, LookMode.Value);
                currentDict.Add(saveable, new SavedField <object>(statUpgrade.Value));
            }
        }
示例#9
0
        public override void DrawStatLister(VehicleDef def, Listing_Settings lister, SaveableField field, float value)
        {
            FloatRange?range = settingListerRange;

            if (range is null)
            {
                range = new FloatRange(-value, value);
            }
            lister.SliderLabeled(def, field, "VehicleMaxArmor".Translate(), "VehicleMaxArmorTooltip".Translate(), string.Empty, string.Empty, value + range.Value.min, value + range.Value.max, 1);
        }
示例#10
0
        public override void DrawStatLister(VehicleDef def, Listing_Settings lister, SaveableField field, float value)
        {
            FloatRange?range = settingListerRange;

            if (range is null)
            {
                range = new FloatRange(-value, value);
            }
            lister.FloatBox(def, field, "VehicleCargoCapacity".Translate(), "VehicleCargoCapacityTooltip".Translate(), string.Empty, value + range.Value.min, value + range.Value.max);
        }
示例#11
0
 public override IEnumerable <string> ConfigErrors(VehicleDef vehicleDef)
 {
     foreach (string error in base.ConfigErrors(vehicleDef))
     {
         yield return(error);
     }
     if (groupKey.NullOrEmpty())
     {
         yield return("<field>groupKey</field> must be populated for a turret of type <type>VehicleTurretAlternating</type>".ConvertRichText());
     }
 }
示例#12
0
 public static object TryGetValue(this VehicleDef def, FieldInfo field)
 {
     if (VehicleMod.settings.vehicles.fieldSettings.TryGetValue(def.defName, out var dict))
     {
         if (dict.TryGetValue(new SaveableField(def, field), out var result))
         {
             return(result.Second);
         }
     }
     Log.Error($"Unable to retrieve {field.Name} for {def.defName} in ModSettings. Is this field posted to settings?");
     return(default);
示例#13
0
 public object GetSettingsValue(VehicleDef def, SaveableField field)
 {
     try
     {
         return(settings switch
         {
             SettingsPage.Vehicles => VehicleMod.settings.vehicles.fieldSettings[def.defName][field].First,
             SettingsPage.Upgrades => VehicleMod.settings.upgrades.upgradeSettings[def.defName][field].First,
             _ => throw new NotSupportedException($"Cannot use Listing_Settings with settings set to {settings}")
         });
     }
示例#14
0
 public static void DrawGhostVehicle(IntVec3 center, Rot8 rot, ThingDef thingDef, Graphic baseGraphic, Color ghostCol, AltitudeLayer drawAltitude, Thing thing = null)
 {
     if (thingDef is VehicleBuildDef def)
     {
         VehicleDef vehicleDef = def.thingToSpawn;
         if (vehicleDef.GetSortedCompProperties <CompProperties_Cannons>() is CompProperties_Cannons props)
         {
             Vector3 loc = GenThing.TrueCenter(center, rot, def.Size, drawAltitude.AltitudeFor());
             vehicleDef.DrawGhostCannonTextures(loc, rot, ghostCol);
         }
     }
 }
示例#15
0
        public void RecalculatePerceivedMovementDifficultyAt(int tile, VehicleDef vehicleDef, int?ticksAbs = null)
        {
            if (!Find.WorldGrid.InBounds(tile))
            {
                return;
            }
            bool flag = PassableFast(tile, vehicleDef);

            movementDifficulty[vehicleDef][tile] = CalculatedMovementDifficultyAt(tile, vehicleDef, ticksAbs, null);
            if (flag != PassableFast(tile, vehicleDef))
            {
                WorldVehicleReachability.Instance.ClearCache();
            }
        }
示例#16
0
        public static void SetVehicleTex(VehicleDef selectedDef)
        {
            if (selectedDef is null)
            {
                selectedVehicleTex = null;
                return;
            }
            var bodyGraphicData = selectedDef.graphicData;
            var graphicData     = new GraphicDataRGB();

            graphicData.CopyFrom(bodyGraphicData);
            graphicInt         = graphicData.Graphic as Graphic_Vehicle;
            selectedVehicleTex = graphicInt.TexAt(Rot8.North);
        }
示例#17
0
        private static void RecalculateHeight(VehicleDef def, int columns = 3)
        {
            float propertySectionHeight = 5;             //Buffer for bottom scrollable

            foreach (var saveableObject in VehicleCompFields)
            {
                if (saveableObject.Value.NullOrEmpty() || saveableObject.Value.All(f => f.TryGetAttribute <PostToSettingsAttribute>(out var settings) && settings.VehicleType != VehicleType.Undefined && settings.VehicleType != def.vehicleType))
                {
                    continue;
                }
                int rows = Mathf.CeilToInt(saveableObject.Value.Count / columns);
                propertySectionHeight += 50 + rows * 16;                 //72
            }
            scrollableViewHeight = propertySectionHeight;
        }
示例#18
0
 public SaveablePair(VehicleDef def, FieldInfo field, string uniqueKey, KeyValuePair <K, V> keyValuePair, LookMode keyLookMode, LookMode valueLookMode) : base(def, field)
 {
     if (keyLookMode == LookMode.Def || valueLookMode == LookMode.Def)
     {
         Log.Warning("Cannot use LookMode.Def for SaveablePair. Would require resolving of Def post-loading. Consider using SaveableDefPair");
         return;
     }
     key                = keyValuePair.Key;
     value              = keyValuePair.Value;
     this.uniqueKey     = uniqueKey;
     this.keyLookMode   = keyLookMode;
     this.valueLookMode = valueLookMode;
     keyType            = typeof(K);
     valueType          = typeof(V);
 }
示例#19
0
        public static float CalculatedMovementDifficultyAt(int tile, VehicleDef vehicleDef, int?ticksAbs = null, StringBuilder explanation = null)
        {
            Tile worldTile = Find.WorldGrid[tile];

            if (explanation != null && explanation.Length > 0)
            {
                explanation.AppendLine();
            }

            if (vehicleDef.CoastalTravel(tile))
            {
                return(vehicleDef.properties.customBiomeCosts[BiomeDefOf.Ocean] / vehicleDef.properties.worldSpeedMultiplier);
            }
            else if (vehicleDef.vehicleType == VehicleType.Sea)
            {
                return(WorldHelper.WaterCovered(tile) ? vehicleDef.properties.customBiomeCosts[worldTile.biome] / vehicleDef.properties.worldSpeedMultiplier : ImpassableMovementDifficulty);
            }
            float biomeCost     = vehicleDef.properties.customBiomeCosts.TryGetValue(worldTile.biome, WorldPathGrid.CalculatedMovementDifficultyAt(tile, false, ticksAbs, explanation));
            float hillinessCost = vehicleDef.properties.customHillinessCosts.TryGetValue(worldTile.hilliness, HillinessMovementDifficultyOffset(worldTile.hilliness));

            if (ImpassableCost(biomeCost) || ImpassableCost(hillinessCost))
            {
                if (explanation != null)
                {
                    explanation.Append("Impassable".Translate());
                }
                return(ImpassableMovementDifficulty);
            }

            float finalBiomeCost = biomeCost / vehicleDef.properties.worldSpeedMultiplier;

            if (explanation != null)
            {
                explanation.Append(worldTile.biome.LabelCap + ": " + biomeCost.ToStringWithSign("0.#"));
            }

            float num3 = finalBiomeCost + hillinessCost;

            if (explanation != null && hillinessCost != 0f)
            {
                explanation.AppendLine();
                explanation.Append(worldTile.hilliness.GetLabelCap() + ": " + hillinessCost.ToStringWithSign("0.#"));
            }
            return(num3 + GetCurrentWinterMovementDifficultyOffset(tile, vehicleDef, new int?(ticksAbs ?? GenTicks.TicksAbs), explanation));
        }
        public static PawnKindDef GenerateImpliedPawnKindDef(VehicleDef vehicleDef)
        {
            PawnKindDef kindDef = new PawnKindDef()
            {
                defName     = vehicleDef.defName + "_PawnKind",
                label       = vehicleDef.label,
                description = vehicleDef.description,
                combatPower = vehicleDef.combatPower,
                race        = vehicleDef,
                lifeStages  = new List <PawnKindLifeStage>()
                {
                    new PawnKindLifeStage()
                }
            };

            vehicleDef.VehicleKindDef = kindDef;
            return(kindDef);
        }
        private void FloodFillAt(int tile, VehicleDef vehicleDef)
        {
            if (!fields.ContainsKey(vehicleDef))
            {
                fields.Add(vehicleDef, new int[Find.WorldGrid.TilesCount]);
            }

            if (!WorldVehiclePathGrid.Instance.Passable(tile, vehicleDef))
            {
                fields[vehicleDef][tile] = impassableFieldID;
                return;
            }

            Find.WorldFloodFiller.FloodFill(tile, (int x) => WorldVehiclePathGrid.Instance.Passable(x, vehicleDef), delegate(int x)
            {
                fields[vehicleDef][x] = nextFieldID;
            }, int.MaxValue, null);
            nextFieldID++;
        }
示例#22
0
        public Dialog_NodeSettings(VehicleDef def, UpgradeNode node, Vector2 origin)
        {
            VehicleDef  = def;
            UpgradeNode = node;

            closeOnClickedOutside  = true;
            closeOnAnyClickOutside = true;
            closeOnCancel          = true;
            doCloseX = true;

            float width  = 400;
            int   rows   = Mathf.Max(1, Mathf.FloorToInt(UpgradeNode.ListerCount / 2f));
            float height = rows * 100 + 50;

            windowSize = new Vector2(width, height);
            drawLoc    = origin;

            Lister = new Listing_Settings(SettingsPage.Upgrades);
        }
示例#23
0
        public VehicleGenerationRequest(VehicleDef vehicleDef, Faction faction, bool randomizeColors = false, bool randomizeMask = false, bool cleanSlate = true)
        {
            Rand.PushState();

            VehicleDef = vehicleDef;
            Faction    = faction;

            if (randomizeColors)
            {
                float r1 = Rand.Range(0.25f, .75f);
                float g1 = Rand.Range(0.25f, .75f);
                float b1 = Rand.Range(0.25f, .75f);
                ColorOne = new Color(r1, g1, b1, 1);
                float r2 = Rand.Range(0.25f, .75f);
                float g2 = Rand.Range(0.25f, .75f);
                float b2 = Rand.Range(0.25f, .75f);
                ColorTwo = new Color(r2, g2, b2, 1);
                float r3 = Rand.Range(0.25f, .75f);
                float g3 = Rand.Range(0.25f, .75f);
                float b3 = Rand.Range(0.25f, .75f);
                ColorThree = new Color(r3, g3, b3, 1);
            }
            else
            {
                ColorOne   = vehicleDef.graphicData.color;
                ColorTwo   = vehicleDef.graphicData.colorTwo;
                ColorThree = vehicleDef.graphicData.colorThree;
            }

            Upgrades   = 0;
            CleanSlate = cleanSlate;
            if (!CleanSlate && vehicleDef.GetSortedCompProperties <CompProperties_UpgradeTree>() is CompProperties_UpgradeTree compProperties_UpgradeTree)
            {
                Upgrades = Rand.Range(0, compProperties_UpgradeTree.upgrades.Count);
            }

            RandomizeMask = randomizeMask;

            Rand.PopState();
        }
示例#24
0
        public override void SettingsWindow(VehicleDef def, Listing_Settings listing)
        {
            FieldInfo dictField = SettingsCache.GetCachedField(typeof(StatUpgrade), nameof(values));

            Rect buttonRect = listing.GetRect(16);

            buttonRect.x      = buttonRect.width - 24;
            buttonRect.width  = 24;
            buttonRect.height = 24;
            listing.Header(label, GameFont.Medium, TextAnchor.MiddleCenter);
            if (Widgets.ButtonImage(buttonRect, VehicleTex.ResetPage))
            {
                SettingsCustomizableFields.PopulateSaveableUpgrades(def, true);
            }
            listing.Gap();

            foreach (var statUpgrade in values)
            {
                SaveableDefPair <StatUpgradeCategoryDef> saveable = new SaveableDefPair <StatUpgradeCategoryDef>(def, dictField, string.Concat(statUpgrade.Key.defName, "_", upgradeID), statUpgrade.Key, LookMode.Value);
                statUpgrade.Key.DrawStatLister(def, listing, saveable, statUpgrade.Value);
            }
        }
 public static void IterateTypeFields(VehicleDef def, Type type, object obj, ref Dictionary <SaveableField, SavedField <object> > currentDict)
 {
     if (VehicleMod.cachedFields.TryGetValue(type, out var fields))
     {
         var dict = VehicleMod.settings.vehicles.fieldSettings[def.defName];
         foreach (FieldInfo field in fields)
         {
             if (field.TryGetAttribute <PostToSettingsAttribute>(out var settings) && settings.ParentHolder)
             {
                 object value = field.GetValue(obj);
                 if (field.FieldType.IsGenericType)
                 {
                     MethodInfo method = field.DeclaringType.GetMethod("ResolvePostToSettings", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
                     if (method != null)
                     {
                         object[] arguments = new object[] { def, currentDict };
                         method.Invoke(obj, arguments);
                         currentDict = (Dictionary <SaveableField, SavedField <object> >)arguments[1];
                     }
                     else
                     {
                         SmashLog.Error($"Unable to generate customizable setting <field>{field.Name}</field> for <text>{def.defName}</text>. Fields of type <type>Dictionary<T></type> must implement ResolvePostToSettings method to be manually resolved.");
                     }
                 }
                 else
                 {
                     IterateTypeFields(def, field.FieldType, value, ref currentDict);
                 }
             }
             else
             {
                 SaveableField saveField = new SaveableField(def, field);
                 if (!dict.TryGetValue(saveField, out var _))
                 {
                     dict.Add(saveField, new SavedField <object>(field.GetValue(obj)));
                 }
             }
         }
示例#26
0
        /// <summary>
        /// Ensures the cellrect inhabited by <paramref name="vehicleDef"/> contains no Things that will block pathing and movement at <paramref name="cell"/>.
        /// </summary>
        /// <param name="pawn"></param>
        /// <param name="c"></param>
        public static bool CellRectStandable(this VehicleDef vehicleDef, Map map, IntVec3 cell, Rot4?rot = null)
        {
            IntVec2 dimensions = vehicleDef.Size;

            if (rot?.IsHorizontal ?? false)
            {
                int x = dimensions.x;
                dimensions.x = dimensions.z;
                dimensions.z = x;
            }
            foreach (IntVec3 cell2 in CellRect.CenteredOn(cell, dimensions.x, dimensions.z))
            {
                if (vehicleDef.IsBoat() && !GenGridVehicles.Standable(cell2, map))
                {
                    return(false);
                }
                else if (!GenGrid.Standable(cell2, map))
                {
                    return(false);
                }
            }
            return(true);
        }
示例#27
0
        public static VehiclePawn SpawnVehicleRandomized(VehicleDef vehicleDef, IntVec3 cell, Map map, Faction faction, Rot4?rot = null, bool autoFill = false)
        {
            if (rot is null)
            {
                rot = Rot4.Random;
            }

            VehiclePawn vehicle = GenerateVehicle(new VehicleGenerationRequest(vehicleDef, faction, true, true));

            vehicle.CompFueledTravel?.Refuel(vehicle.CompFueledTravel.FuelCapacity);
            GenSpawn.Spawn(vehicle, cell, map, rot.Value, WipeMode.FullRefund, false);

            if (autoFill)
            {
                foreach (VehicleHandler handler in vehicle.handlers.Where(h => h.role.handlingTypes.NotNullAndAny()))
                {
                    Pawn pawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(PawnKindDefOf.Colonist, faction));
                    pawn.SetFactionDirect(faction);
                    vehicle.GiveLoadJob(pawn, handler);
                    vehicle.Notify_Boarded(pawn);
                }
            }
            return(vehicle);
        }
示例#28
0
 public SaveableListEntry(VehicleDef def, FieldInfo field, int index) : base(def, field)
 {
     this.index = index;
 }
示例#29
0
 public bool PassableFast(int tile, VehicleDef vehicleDef)
 {
     return(movementDifficulty[vehicleDef][tile] < ImpassableMovementDifficulty);
 }
示例#30
0
 public float PerceivedMovementDifficultyAt(int tile, VehicleDef vehicleDef)
 {
     return(movementDifficulty[vehicleDef][tile]);
 }