示例#1
0
        public override void Generate(Map map)
        {
            if (!PrepareCarefully.Instance.Active)
            {
                Find.Scenario.GenerateIntoMap(map);
                return;
            }
            else
            {
                ReplaceColonists();

                ScenPart_PlayerPawnsArriveMethod arriveMethodPart = null;
                foreach (ScenPart current in Find.Scenario.AllParts)
                {
                    ScenPart_StartingThing_Defined        startingThings  = current as ScenPart_StartingThing_Defined;
                    ScenPart_ScatterThingsNearPlayerStart thingsNearStart = current as ScenPart_ScatterThingsNearPlayerStart;
                    ScenPart_StartingAnimal          animal       = current as ScenPart_StartingAnimal;
                    ScenPart_PlayerPawnsArriveMethod arriveMethod = current as ScenPart_PlayerPawnsArriveMethod;
                    if (arriveMethod != null)
                    {
                        arriveMethodPart = arriveMethod;
                    }
                    if (startingThings == null && thingsNearStart == null && animal == null && arriveMethod == null)
                    {
                        current.GenerateIntoMap(map);
                    }
                }

                SpawnColonistsWithEquipment(map, arriveMethodPart);
                ApplyColonistHealthCustomizations();
                PrepForMapGen();
                SpawnStartingResources(map);
            }
        }
示例#2
0
        public override void Generate()
        {
            if (!PrepareCarefully.Instance.Active)
            {
                Find.Scenario.GenerateIntoMap();
                return;
            }
            else
            {
                ReplaceColonists();

                // TODO: Alpha 14
                // Do all of the scenario steps except the ones that place equipment and resources.
                // Skip those an figure out how to add customized equipment.  Need to separate equipment
                // placed with colonists ("equipment") and equipment scattered near colonists ("resources").\
                ScenPart_PlayerPawnsArriveMethod arriveMethodPart = null;
                foreach (ScenPart current in Find.Scenario.AllParts)
                {
                    ScenPart_StartingThing_Defined        startingThings  = current as ScenPart_StartingThing_Defined;
                    ScenPart_ScatterThingsNearPlayerStart thingsNearStart = current as ScenPart_ScatterThingsNearPlayerStart;
                    ScenPart_StartingAnimal          animal       = current as ScenPart_StartingAnimal;
                    ScenPart_PlayerPawnsArriveMethod arriveMethod = current as ScenPart_PlayerPawnsArriveMethod;
                    if (arriveMethod != null)
                    {
                        arriveMethodPart = arriveMethod;
                    }
                    if (startingThings == null && thingsNearStart == null && animal == null && arriveMethod == null)
                    {
                        current.GenerateIntoMap();
                    }
                }

                SpawnColonistsWithEquipment(arriveMethodPart);
                ApplyColonistHealthCustomizations();
                PrepForMapGen();
                SpawnStartingResources();
            }
        }
示例#3
0
        protected void ReplaceScenarioParts(Scenario actualScenario, Scenario vanillaFriendlyScenario)
        {
            // Create a lookup of all of the scenario types that we want to replace.
            HashSet <string> scenarioPartsToReplace = new HashSet <string>()
            {
                typeof(RimWorld.ScenPart_StartingThing_Defined).FullName,
                typeof(RimWorld.ScenPart_ScatterThingsNearPlayerStart).FullName,
                typeof(RimWorld.ScenPart_StartingAnimal).FullName
            };

            // Create lists to hold the new scenario parts.
            List <ScenPart> actualScenarioParts          = new List <ScenPart>();
            List <ScenPart> vanillaFriendlyScenarioParts = new List <ScenPart>();

            // Get the list of parts from the original scenario.  The actual scenario and the vanilla-friendly
            // scenario will both be copies of the original scenario and equivalent at this point, so we only
            // need to look at the parts in one of them.
            FieldInfo       partsField    = typeof(Scenario).GetField("parts", BindingFlags.NonPublic | BindingFlags.Instance);
            List <ScenPart> originalParts = (List <ScenPart>)partsField.GetValue(actualScenario);

            // Replace the pawn count in the configure pawns scenario part to reflect the number of
            // pawns that were selected in Prepare Carefully.
            foreach (var part in originalParts)
            {
                ScenPart_ConfigPage_ConfigureStartingPawns configurePawnPart = part as ScenPart_ConfigPage_ConfigureStartingPawns;
                if (configurePawnPart == null)
                {
                    continue;
                }
                configurePawnPart.pawnCount = Find.GameInitData.startingPawnCount;
            }

            // Fill in each part list with only the scenario parts that we're not going to replace.
            foreach (var part in originalParts)
            {
                if (!scenarioPartsToReplace.Contains(part.GetType().FullName))
                {
                    actualScenarioParts.Add(part);
                    vanillaFriendlyScenarioParts.Add(part);
                }
            }

            // Sort the equipment from highest count to lowest so that gear is less likely to get blocked
            // if there's a bulk item included.  If you don't do this, then a large number of an item (meals,
            // for example) could fill up the spawn area right away and then the rest of the items would have
            // nowhere to spawn.
            PrepareCarefully.Instance.Equipment.Sort((EquipmentSelection a, EquipmentSelection b) => {
                return(a.Count.CompareTo(b.Count));
            });

            // Create all of the scatter things scenario parts that we need.  Make note of the maximum number of stacks
            // that could be created.  We must use a custom scatter scenario part because we need to customize the spawn
            // radius when there are large numbers of resources.
            List <ScenPart_CustomScatterThingsNearPlayerStart> scatterParts = new List <ScenPart_CustomScatterThingsNearPlayerStart>();
            int scatterStackCount = 0;

            foreach (var e in PrepareCarefully.Instance.Equipment)
            {
                if (e.record.animal)
                {
                    continue;
                }
                if (!PlayerStartsWith(e))
                {
                    int stacks = Mathf.CeilToInt((float)e.Count / (float)e.ThingDef.stackLimit);
                    scatterStackCount += stacks;
                    ScenPart_CustomScatterThingsNearPlayerStart part = new ScenPart_CustomScatterThingsNearPlayerStart();
                    part.ThingDef = e.ThingDef;
                    part.StuffDef = e.StuffDef;
                    part.Count    = e.Count;
                    scatterParts.Add(part);

                    ScenPart_ScatterThingsNearPlayerStart vanillaPart = new ScenPart_ScatterThingsNearPlayerStart();
                    vanillaPart.def = ScenPartDefOf.ScatterThingsNearPlayerStart;
                    vanillaPart.SetPrivateField("thingDef", e.ThingDef);
                    vanillaPart.SetPrivateField("stuff", e.StuffDef);
                    vanillaPart.SetPrivateField("count", e.Count);
                    vanillaFriendlyScenarioParts.Add(vanillaPart);
                }
            }

            // Get the non-public fields that we'll need to set on the new starting thing scenario parts
            // that we're going to add.
            FieldInfo thingDefField = typeof(ScenPart_StartingThing_Defined).GetField("thingDef", BindingFlags.Instance | BindingFlags.NonPublic);
            FieldInfo stuffField    = typeof(ScenPart_StartingThing_Defined).GetField("stuff", BindingFlags.Instance | BindingFlags.NonPublic);
            FieldInfo countField    = typeof(ScenPart_StartingThing_Defined).GetField("count", BindingFlags.Instance | BindingFlags.NonPublic);

            // Go through all of the equipment that's meant to spawn as a starting thing.  We'll try to add
            // a starting thing scenario part for each, but we're keeping track of the overall density of
            // things that will be spawned into the area (based on stack count and spawn area radius).  If
            // the density is too high, we'll add the things as scattered nearby scenario parts instead.
            float radius     = 7.5f;
            float area       = Mathf.PI * radius * radius;
            float maxDensity = 0.25f;
            int   maxStacks  = Mathf.FloorToInt(maxDensity * area);
            int   stackCount = 0;

            foreach (var e in PrepareCarefully.Instance.Equipment)
            {
                if (e.record.animal)
                {
                    continue;
                }
                if (PlayerStartsWith(e))
                {
                    int scatterCount = 0;
                    int nearCount    = e.Count;

                    // If the number of stacks added by this part will push us over the density
                    // limit, then we split the stacks into two scenario parts, one that spawns
                    // as a starting thing and the other that scatters nearby.
                    int nearStacks = Mathf.CeilToInt((float)nearCount / (float)e.ThingDef.stackLimit);
                    if (nearStacks + stackCount > maxStacks)
                    {
                        int availableStacks = maxStacks - stackCount;
                        nearCount    = availableStacks * e.ThingDef.stackLimit;
                        scatterCount = e.Count - nearCount;
                    }
                    if (nearCount > 0)
                    {
                        stackCount += Mathf.CeilToInt((float)nearCount / (float)e.ThingDef.stackLimit);
                        ScenPart_StartingThing_Defined part = new ScenPart_StartingThing_Defined();
                        // Be sure to set the def, since that doesn't happen automatically.  Failing to do so will
                        // cause null pointer exceptions when trying to sort the scenario parts when creating the
                        // description to display in the "Scenario Summary."
                        part.def = ScenPartDefOf.StartingThing_Defined;
                        thingDefField.SetValue(part, e.ThingDef);
                        stuffField.SetValue(part, e.StuffDef);
                        countField.SetValue(part, nearCount);
                        actualScenarioParts.Add(part);
                        vanillaFriendlyScenarioParts.Add(part);
                    }
                    if (scatterCount > 0)
                    {
                        scatterCount += Mathf.CeilToInt((float)scatterCount / (float)e.ThingDef.stackLimit);
                        ScenPart_CustomScatterThingsNearPlayerStart part = new ScenPart_CustomScatterThingsNearPlayerStart();
                        part.ThingDef = e.ThingDef;
                        part.StuffDef = e.StuffDef;
                        part.Count    = scatterCount;
                        scatterParts.Add(part);

                        ScenPart_ScatterThingsNearPlayerStart vanillaPart = new ScenPart_ScatterThingsNearPlayerStart();
                        vanillaPart.def = ScenPartDefOf.ScatterThingsNearPlayerStart;
                        vanillaPart.SetPrivateField("thingDef", e.ThingDef);
                        vanillaPart.SetPrivateField("stuff", e.StuffDef);
                        vanillaPart.SetPrivateField("count", scatterCount);
                        vanillaFriendlyScenarioParts.Add(vanillaPart);
                    }
                }
            }

            // Create parts to spawn the animals.  We can't use the default starting animal scenario part,
            // because it doesn't allow us to choose a gender.
            Dictionary <PawnKindDef, int> animalKindCounts = new Dictionary <PawnKindDef, int>();

            foreach (var e in PrepareCarefully.Instance.Equipment)
            {
                if (e.record.animal)
                {
                    PawnKindDef           animalKindDef = (from td in DefDatabase <PawnKindDef> .AllDefs where td.race == e.ThingDef select td).FirstOrDefault();
                    ScenPart_CustomAnimal part          = new ScenPart_CustomAnimal();
                    part.Count   = e.count;
                    part.Gender  = e.Gender;
                    part.KindDef = animalKindDef;
                    actualScenarioParts.Add(part);

                    if (animalKindCounts.ContainsKey(animalKindDef))
                    {
                        int count = animalKindCounts[animalKindDef];
                        animalKindCounts[animalKindDef] = count + e.count;
                    }
                    else
                    {
                        animalKindCounts.Add(animalKindDef, e.count);
                    }
                }
            }

            // The vanilla starting animal part does not distinguish between genders, so we combine
            // the custom parts into a single vanilla part for each animal kind.
            foreach (var animalKindDef in animalKindCounts.Keys)
            {
                ScenPart_StartingAnimal vanillaPart = new ScenPart_StartingAnimal();
                vanillaPart.def = ScenPartDefOf.StartingAnimal;
                vanillaPart.SetPrivateField("animalKind", animalKindDef);
                vanillaPart.SetPrivateField("count", animalKindCounts[animalKindDef]);
                vanillaFriendlyScenarioParts.Add(vanillaPart);
            }

            // We figure out how dense the spawn area will be after spawning all of the scattered things.
            // We'll target a maximum density and increase the spawn radius if we're over that density.
            stackCount += scatterStackCount;
            float originalRadius = 12f;

            radius     = originalRadius;
            maxDensity = 0.35f;
            bool evaluate = true;

            while (evaluate)
            {
                float density = GetSpawnAreaDensity(radius, stackCount);
                if (density > maxDensity)
                {
                    radius += 1f;
                }
                else
                {
                    evaluate = false;
                }
            }
            int addedRadius = (int)(radius - originalRadius);

            // For each scatter part, we set our custom radius before adding the part to the scenario.
            foreach (var part in scatterParts)
            {
                part.Radius = addedRadius;
                actualScenarioParts.Add(part);
            }

            // Set the new part lists on the two scenarios.
            actualScenario.SetPrivateField("parts", actualScenarioParts);
            vanillaFriendlyScenario.SetPrivateField("parts", vanillaFriendlyScenarioParts);
        }
示例#4
0
        protected void InitializeDefaultEquipment()
        {
            // Go through all of the scenario steps that scatter resources near the player starting location and add
            // them to the resource/equipment list.
            foreach (ScenPart part in Verse.Find.Scenario.AllParts)
            {
                ScenPart_ScatterThingsNearPlayerStart nearPlayerStart = part as ScenPart_ScatterThingsNearPlayerStart;
                if (nearPlayerStart != null)
                {
                    FieldInfo              thingDefField = typeof(ScenPart_ScatterThingsNearPlayerStart).GetField("thingDef", BindingFlags.Instance | BindingFlags.NonPublic);
                    FieldInfo              stuffDefField = typeof(ScenPart_ScatterThingsNearPlayerStart).GetField("stuff", BindingFlags.Instance | BindingFlags.NonPublic);
                    FieldInfo              countField    = typeof(ScenPart_ScatterThingsNearPlayerStart).GetField("count", BindingFlags.Instance | BindingFlags.NonPublic);
                    ThingDef               thingDef      = (ThingDef)thingDefField.GetValue(nearPlayerStart);
                    ThingDef               stuffDef      = (ThingDef)stuffDefField.GetValue(nearPlayerStart);
                    int                    count         = (int)countField.GetValue(nearPlayerStart);
                    EquipmentKey           key           = new EquipmentKey(thingDef, stuffDef);
                    EquipmentDatabaseEntry entry         = equipmentDatabase[key];
                    if (entry == null)
                    {
                        entry = AddNonStandardScenarioEquipmentEntry(key);
                    }
                    if (entry != null)
                    {
                        AddEquipment(entry, count);
                    }
                }

                // Go through all of the scenario steps that place starting equipment with the colonists and
                // add them to the resource/equipment list.
                ScenPart_StartingThing_Defined startingThing = part as ScenPart_StartingThing_Defined;
                if (startingThing != null)
                {
                    FieldInfo              thingDefField = typeof(ScenPart_StartingThing_Defined).GetField("thingDef", BindingFlags.Instance | BindingFlags.NonPublic);
                    FieldInfo              stuffDefField = typeof(ScenPart_StartingThing_Defined).GetField("stuff", BindingFlags.Instance | BindingFlags.NonPublic);
                    FieldInfo              countField    = typeof(ScenPart_StartingThing_Defined).GetField("count", BindingFlags.Instance | BindingFlags.NonPublic);
                    ThingDef               thingDef      = (ThingDef)thingDefField.GetValue(startingThing);
                    ThingDef               stuffDef      = (ThingDef)stuffDefField.GetValue(startingThing);
                    int                    count         = (int)countField.GetValue(startingThing);
                    EquipmentKey           key           = new EquipmentKey(thingDef, stuffDef);
                    EquipmentDatabaseEntry entry         = equipmentDatabase[key];
                    if (entry == null)
                    {
                        entry = AddNonStandardScenarioEquipmentEntry(key);
                    }
                    if (entry != null)
                    {
                        AddEquipment(entry, count);
                    }
                }

                // Go through all of the scenario steps that spawn a pet and add the pet to the equipment/resource
                // list.
                ScenPart_StartingAnimal animal = part as ScenPart_StartingAnimal;
                if (animal != null)
                {
                    FieldInfo animalCountField = typeof(ScenPart_StartingAnimal).GetField("count", BindingFlags.Instance | BindingFlags.NonPublic);
                    int       count            = (int)animalCountField.GetValue(animal);
                    for (int i = 0; i < count; i++)
                    {
                        AddEquipment(RandomPet(animal));
                    }
                }
            }
        }
示例#5
0
        protected void InitializeDefaultEquipment()
        {
            // Go through all of the scenario steps that scatter resources near the player starting location and add
            // them to the resource/equipment list.
            foreach (ScenPart part in Verse.Find.Scenario.AllParts)
            {
                ScenPart_ScatterThingsNearPlayerStart nearPlayerStart = part as ScenPart_ScatterThingsNearPlayerStart;
                if (nearPlayerStart != null)
                {
                    FieldInfo thingDefField = typeof(ScenPart_ScatterThingsNearPlayerStart).GetField("thingDef", BindingFlags.Instance | BindingFlags.NonPublic);
                    FieldInfo stuffDefField = typeof(ScenPart_ScatterThingsNearPlayerStart).GetField("stuff", BindingFlags.Instance | BindingFlags.NonPublic);
                    FieldInfo countField    = typeof(ScenPart_ScatterThingsNearPlayerStart).GetField("count", BindingFlags.Instance | BindingFlags.NonPublic);
                    ThingDef  thingDef      = (ThingDef)thingDefField.GetValue(nearPlayerStart);
                    ThingDef  stuffDef      = (ThingDef)stuffDefField.GetValue(nearPlayerStart);
                    equipmentDatabase.PreloadDefinition(stuffDef);
                    equipmentDatabase.PreloadDefinition(thingDef);
                    int             count  = (int)countField.GetValue(nearPlayerStart);
                    EquipmentKey    key    = new EquipmentKey(thingDef, stuffDef);
                    EquipmentRecord record = equipmentDatabase.LookupEquipmentRecord(key);
                    if (record == null)
                    {
                        Logger.Warning("Couldn't initialize all scenario equipment.  Didn't find an equipment entry for " + thingDef.defName);
                        record = AddNonStandardScenarioEquipmentEntry(key);
                    }
                    if (record != null)
                    {
                        AddEquipment(record, count);
                    }
                }

                // Go through all of the scenario steps that place starting equipment with the colonists and
                // add them to the resource/equipment list.
                ScenPart_StartingThing_Defined startingThing = part as ScenPart_StartingThing_Defined;
                if (startingThing != null)
                {
                    FieldInfo thingDefField = typeof(ScenPart_StartingThing_Defined).GetField("thingDef", BindingFlags.Instance | BindingFlags.NonPublic);
                    FieldInfo stuffDefField = typeof(ScenPart_StartingThing_Defined).GetField("stuff", BindingFlags.Instance | BindingFlags.NonPublic);
                    FieldInfo countField    = typeof(ScenPart_StartingThing_Defined).GetField("count", BindingFlags.Instance | BindingFlags.NonPublic);
                    ThingDef  thingDef      = (ThingDef)thingDefField.GetValue(startingThing);
                    ThingDef  stuffDef      = (ThingDef)stuffDefField.GetValue(startingThing);
                    equipmentDatabase.PreloadDefinition(stuffDef);
                    equipmentDatabase.PreloadDefinition(thingDef);
                    int             count = (int)countField.GetValue(startingThing);
                    EquipmentKey    key   = new EquipmentKey(thingDef, stuffDef);
                    EquipmentRecord entry = equipmentDatabase.LookupEquipmentRecord(key);
                    if (entry == null)
                    {
                        Logger.Warning("Couldn't initialize all scenario equipment.  Didn't find an equipment entry for " + thingDef.defName);
                        entry = AddNonStandardScenarioEquipmentEntry(key);
                    }
                    if (entry != null)
                    {
                        AddEquipment(entry, count);
                    }
                }

                // Go through all of the scenario steps that spawn a pet and add the pet to the equipment/resource
                // list.
                ScenPart_StartingAnimal animal = part as ScenPart_StartingAnimal;
                if (animal != null)
                {
                    FieldInfo animalCountField = typeof(ScenPart_StartingAnimal).GetField("count", BindingFlags.Instance | BindingFlags.NonPublic);
                    int       count            = (int)animalCountField.GetValue(animal);
                    for (int i = 0; i < count; i++)
                    {
                        PawnKindDef animalKindDef = RandomPet(animal);
                        equipmentDatabase.PreloadDefinition(animalKindDef.race);

                        List <EquipmentRecord> entries = PrepareCarefully.Instance.EquipmentDatabase.Animals.FindAll((EquipmentRecord e) => {
                            return(e.def == animalKindDef.race);
                        });
                        EquipmentRecord entry = null;
                        if (entries.Count > 0)
                        {
                            entry = entries.RandomElement();
                        }
                        if (entry != null)
                        {
                            AddEquipment(entry);
                        }
                        else
                        {
                            Logger.Warning("Failed to add the expected scenario animal to list of selected equipment");
                        }
                    }
                }
            }
        }