Modding:Zone Builders

From Caves of Qud Wiki
Jump to navigation Jump to search
This page is about modding. See the modding overview for an abstract on modding.
This page is about modding. See the modding overview for an abstract on modding.
For best results, it's recommended to have read the following topics before this one:

Zone builders

Zone builders are classes in the XRL.World.ZoneBuilders namespace that are successively applied during the generation of a zone. Each builder operates on a Zone object and changes some attribute of it.

Builders can be added to a given zone by specifying <builder>...</builder> tags in Worlds.xml. For example, the following snippet from Worlds.xml is used to build the zone for Kyakukya and the surrounding zones:

<cell Name="Kyakukya" Inherits="Jungle" ApplyTo="TerrainKyakukya" Mutable="false">
  <zone Level="5-9" x="0-2" y="0-2" Name="sky above Kyakukya" IndefiniteArticle="the">
    <builder Class="Sky"></builder>
  </zone>
  <zone Level="10" x="0-2" y="0-2" Name="outskirts" NameContext="Kyakukya" IndefiniteArticle="some" IncludeStratumInZoneDisplay="false" HasWeather="true" WindSpeed="0-60" WindDirections="N,NW,NW,W,W,SW,S,SE" WindDuration="50-3000">
    <population Table="Kyakukya Outskirts"></population>
  </zone>
  <zone Level="10" x="1" y="1" Name="Kyakukya" ProperName="true" IncludeStratumInZoneDisplay="false" HasWeather="true" WindSpeed="0-60" WindDirections="N,NW,NW,W,W,SW,S,SE" WindDuration="50-3000">
    <map FileName="Kyakukya.rpm"></map>
    <builder Class="Music" Track="Kyakukya" Chance="100"></builder>
    <builder Class="IsCheckpoint" Key="Kyakukya"></builder>
  </zone>
</cell>

This snippet includes several zone builders, such as

  • The Sky builder[1] is used to generate the zones over Kyakukya. This builder effectively does nothing other than add open air to every tile in the zone.
  • The Music builder[2] sets the music track that gets placed in Kyakukya
  • The IsCheckpoint builder[3] registers Kyakukya as a checkpoint for the game to auto-save, for games played in Roleplay or Wander mode.

To determine the builders that were used to generate a zone in-game, you can use the zonebuilders wish.

Creating a custom zone builder

Suppose that you had a custom terrain type called MyTerrain (see Modding:Maps), which you wanted to behave like a salt marsh with a large pit in the center (similar to Rust Wells). You could start by creating a Worlds.xml with the following contents (borrowed from WatervineCell):

<?xml version="1.0" encoding="utf-8" ?>
<worlds>
  <world Name="JoppaWorld" Load="Merge">

    <cell Name="MyName_MyMod_MyCell" Inherits="WatervineCell" ApplyTo="MyTerrain" Mutable="false" >
      <zone Level="10" x="1" y="1" Name="salt marsh" HasWeather="true" WindSpeed="0-50" WindDirections="N,NW,NW,W,W,SW,S,SE" WindDuration="200-3000" AmbientBed="Sounds/Ambiences/amb_bed_marsh" AmbientSounds="amb_scatter_marsh_bird1,amb_scatter_marsh_bird2,amb_scatter_marsh_insect1,amb_scatter_marsh_insect2">
        <builder Class="Watervine"></builder>
        <builder Class="FactionEncounters" Population="SafeFactionPopulation"></builder>
        <builder Class="Music" Track="Overworld1" Chance="10"></builder>
        <builder Class="ZoneTemplate:SaltMarsh"></builder>

        <!-- This is new! -->
        <builder Class="YourName_YourMod_PitBuilder"></builder>
      </zone>
      <zone Level="11-15" x="1" y="1" Name="subterranean salt marsh">
        <builder Class="Strata"></builder>
        <builder Class="Watervine" Underground="true"></builder>
        <builder Class="ZoneTemplate:WatervineCaves"></builder>
        <builder Class="FactionEncounters" Population="SafeFactionPopulation"></builder>
        <builder Class="Music" Track="Overworld1" Chance="10"></builder>

        <!-- This is new! -->
        <builder Class="YourName_YourMod_PitBuilder"></builder>
      </zone>
    </cell>
  </world>
</worlds>

In each zone, we add a new zone builder, YourName_YourMod_PitBuilder, implemented as follows:

using Genkit;

namespace XRL.World.ZoneBuilders {

    /// <summary>
    /// Custom ZoneBuilder that creates a large pit in the center of the zone, similar to
    /// the Rust Wells.
    /// </summary>
    public class YourName_YourMod_PitBuilder : ZoneBuilderSandbox
    {
        public bool BuildZone(Zone Z)
        {
            // Get center of map
            Point2D center = Location2D.get(40, 12).point;

            // Radius of pit is dependent on depth: radius=10 at Z=10, radius=4 at Z=15
            // Radius at each intermediate floor is determined by linearly interpolating between
            // these two values.
            float startFloor = 10f, endFloor = 15f;
            float startRadius = 10f, endRadius = 4f;
            float Radius = ((float)Z.Z - startFloor) * endRadius + (endFloor - (float)Z.Z) * startRadius;
            Radius = Radius / (endFloor - startFloor);

            foreach(Cell C in Z.GetCells())
            {
                if (C.CosmeticDistanceTo(center) > Radius)
                {
                    continue;
                }

                C.RemoveObjects((GameObject o) => true).ForEach(delegate(GameObject o)
                {
                    o.Obliterate();
                });
                C.Clear();
                C.AddObject("Pit");
            }

            Z.FireEvent("FirmPitEdges");
            ZoneBuilderSandbox.EnsureAllVoidsConnected(Z, pathWithNoise: true);

            return true;
        }
   }
}

This creates the zone shown below:

Picture watervine zone with a large pit dug into the center of it, generated by the previous code example.

References

This information is reliable as of patch 2.0.204.92.
  1. XRL.World.ZoneBuilders.Sky
  2. XRL.World.ZoneBuilders.Music
  3. XRL.World.ZoneBuilders.IsCheckpoint