Modding:Zone Builders
This page is about modding. See the modding overview for an abstract on modding. |
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:
References
This information is reliable as of patch 2.0.204.92. |
|