User:Kernelmethod/Sandbox: Difference between revisions

Jump to navigation Jump to search
Start adding section on population tables
mNo edit summary
(Start adding section on population tables)
Line 96: Line 96:
* <code>ObjectBlueprints/Creatures.xml</code>: definitions of all of the creatures that exist in Caves of Qud.
* <code>ObjectBlueprints/Creatures.xml</code>: definitions of all of the creatures that exist in Caves of Qud.
* <code>ObjectBlueprints/Items.xml</code>: definitions of all of the items available in Caves of Qud.
* <code>ObjectBlueprints/Items.xml</code>: definitions of all of the items available in Caves of Qud.
* <code>PopulationTables.xml</code>: contains ''population tables'', which are used to figure out when and where creatures should spawn.
* <code>Skills.xml</code>: contains all of the skill trees provided by Caves of Qud, and abilities within those trees.
* <code>Skills.xml</code>: contains all of the skill trees provided by Caves of Qud, and abilities within those trees.
* <code>Quests.xml</code>: lays out the steps and rewards for non-procedurally generated quests.
* <code>Quests.xml</code>: lays out the steps and rewards for non-procedurally generated quests.
Line 109: Line 110:
|}
|}


We'll start by creating a mod that doesn't actually do anything. To do that, go to Caves of Qud's "offline mods" folder; you can find the location of this folder for your operating system by looking at the page of [[file locations]]. Inside this folder (it should be named <code>Mods</code>), create a folder called <code>SnapjawMage</code>. The first file we're going to create for our mod will be a '''''manifest file'''''; this contains metadata such as our mod's title, a description of the mod, and its version. Create a file called <code>manifest.json</code> inside the <code>SnapjawMage/</code> folder, and paste in the following contents:
We'll start by creating a mod that doesn't actually do anything. To do that, go to Caves of Qud's "offline mods" folder; you can find the location of this folder for your operating system by looking at the page of [[file locations]]. Inside this folder (it should be named <code>Mods</code>), create a folder called <code>Snapjaw-Mages</code>. The first file we're going to create for our mod will be a '''''manifest file'''''; this contains metadata such as our mod's title, a description of the mod, and its version. Create a file called <code>manifest.json</code> inside the <code>Snapjaw-Mages/</code> folder, and paste in the following contents:


<syntaxhighlight lang="json">
<syntaxhighlight lang="json">
Line 136: Line 137:


<syntaxhighlight lang="text">
<syntaxhighlight lang="text">
SnapjawMage
Snapjaw-Mages
├── manifest.json
├── manifest.json
└── preview.png
└── preview.png
Line 170: Line 171:


<syntaxhighlight lang="text">
<syntaxhighlight lang="text">
SnapjawMage
Snapjaw-Mages
├── manifest.json
├── manifest.json
├── ObjectBlueprints
├── ObjectBlueprints
Line 284: Line 285:


<syntaxhighlight lang="text">
<syntaxhighlight lang="text">
SnapjawMage
Snapjaw-Mage
├── manifest.json
├── manifest.json
├── ObjectBlueprints
├── ObjectBlueprints
Line 434: Line 435:


<syntaxhighlight lang="text">
<syntaxhighlight lang="text">
SnapjawMage
Snapjaw-Mages
├── manifest.json
├── manifest.json
├── ObjectBlueprints
├── ObjectBlueprints
Line 700: Line 701:
[[File:Snapjaw_Mages_--_mage_tome_equipped.webp|600px]]
[[File:Snapjaw_Mages_--_mage_tome_equipped.webp|600px]]


== Going forward ==
== Controlling spawning: population tables ==


Congrats! You reached the end of the tutorial!
We've successfully added our mages and given them magical tomes. There's still one thing missing: our mages currently won't spawn in-game unless we use wishes.
 
Caves of Qud uses '''''population tables''''' to decide when to spawn different items and creatures. Here's an example of one such population table (which you can find in the game data in <code>PopulationTables.xml</code>):
 
<syntaxhighlight lang="xml">
<population Name="SaltMarshZoneGlobals">
  <table Name="StandardSurfaceGlobals" />
  <object Chance="90" Number="160-200" Blueprint="Watervine" />
  <object Chance="90" Number="90-130" Blueprint="Brinestalk" />
  <object Chance="50" Number="6-16" Blueprint="Dogthorn Tree" />
  <object Chance="25" Number="1-4" Blueprint="Witchwood Tree" />
  <object Chance="5" Number="1-4" Blueprint="Starapple Tree" />
 
  <object Chance="50" Blueprint="Croc" />
  <object Chance="75" Number="2d6" Blueprint ="Glowpad" Hint="Aquatic" />
  <object Chance="75" Number="2d4" Blueprint ="Glowfish" Hint="Aquatic" />
  <object Chance="50" Number="2d6" Blueprint ="GiantDragonfly" />
  <group Chance="4" Name="ManySnapjaws" Style="pickeach">
    <table Name="SnapjawParty1" Number="4" />
  </group>
</population>
</syntaxhighlight>
 
This table is used in the [[salt marsh]] to help decide what animals and plants should be spawned. Let's take a look at a few of these lines:
 
* <code>&lt;table Name="StandardSurfaceGlobals" /&gt;</code>: this says that the <code>SaltMarshZoneGlobals</code> table should include all of the contents of another table called <code>StandardSurfaceGlobals</code>. You can find the definition of that table in <code>PopulationTables.xml</code>; it does things like add a chance of a {{favilink|Mechanimist pilgrim}} spawning in each zone.
* <code>&lt;object Chance="50" Blueprint="Croc" /&gt;</code>: this adds a 50% chance of a {{favilink|Croc}} spawning in a given zone.
* <code>&lt;group Chance="4" Name="ManySnapjaws" Style="pickeach"&gt;...&lt;/group&gt;</code>: this defines a "group" in the table. The usage here says (roughly speaking) that there's a 4% chance that we sample some creatures from the <code>SnapjawParty1</code> table.


{| style = "margin: 1em;font-family:Source Code Pro;"
=== Adding snapjaw mages to population tables ===
| style = "padding:0em 1em;"| [[File:Mopango_pilgrim.png|40px]]
| style= "color:#155352" | <
| style = "border:1px solid #155352;padding:0.5em 1em;" | Woohoo!
|}


{| style = "margin: 1em;font-family:Source Code Pro;"
There are a few different snapjaw-related population tables in the data files -- <code>SnapjawParty0</code>, <code>SnapjawParty1</code>, <code>SnapjawParty1-with-Warlord</code>, and <code>SnapjawParty2</code>. Each of these tables is used for different encounters with snapjaws.
| style = "padding:0em 1em;"| [[File:Sprouting orb.png|40px]]
| style= "color:#155352" | <
| style = "border:1px solid #155352;padding:0.5em 1em;" | I'm ready to go face these mages in magical combat.
|}


For posterity's sake, here's how our mod folder should be structured at the end:
In your <code>Snapjaw-Mage</code> mod folder, create a new file called <code>PopulationTables.xml</code>:


<syntaxhighlight lang="xml">
<syntaxhighlight lang="text">
SnapjawMage
Snapjaw-Mages
├── manifest.json
├── manifest.json
├── ObjectBlueprints
├── ObjectBlueprints
│   ├── Creatures.xml
│   ├── Creatures.xml
│   └── Items.xml
│   └── Items.xml
├── PopulationTables.xml
├── preview.png
├── preview.png
└── Textures
└── Textures
Line 730: Line 751:
</syntaxhighlight>
</syntaxhighlight>


Here's what my <code>Creatures.xml</code> contained:
Within this file, start by adding the following:


<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8" ?>
<objects>
<populations>
  <object Name="Pyovya_SnapjawMage_Snapjaw Mage" Inherits="Snapjaw">
</populations>
    <part Name="Description" Short="A tattered robe and decaying hat are all that protect =pronouns.possessive= thin layer of grizzled fur from the forces of nature. But behind that furtive glance, =pronouns.subjective= =verb:prepare:afterpronoun= an elemental spell, deployed at a moment's notice against threats to =pronouns.objective= and =pronouns.possessive= kin. =pronouns.Subjective= =verb:understand:afterpronoun= not the power that =pronouns.subjective= =verb:wield:afterpronoun=; and that only makes =pronouns.objective= all the more dangerous." />
</syntaxhighlight>
    <part Name="Render" DisplayName="snapjaw mage" Tile="Pyovya_SnapjawMage/snapjaw_mage.png" ColorString="&amp;O" DetailColor="Y" />


    <inventoryobject Blueprint="Walking Stick" Number="1" />
Now, we need to modify the contents of the four tables that we listed previously:
    <inventoryobject Blueprint="Cloth Robe" Number="1" />
    <inventoryobject Blueprint="Sandals" Number="1" />
    <inventoryobject Blueprint="StandaloneMarkovBook" Number="1-2" Chance="10" />


    <skill Name="Cudgel" />
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="utf-8" ?>
<populations>
  <population Name="SnapjawParty0" Load="Merge">
  </population>
  <population Name="SnapjawParty1" Load="Merge">
  </population>
  <population Name="SnapjawParty1-with-Warlord" Load="Merge">
  </population>
  <population Name="SnapjawParty0" Load="Merge">
  </population>
</populations>
</syntaxhighlight>


    <stat Name="Hitpoints" Value="15" />
{| style = "margin: 1em;font-family:Source Code Pro;"
    <stat Name="DV" Value="4" />
| style = "padding:0em 1em;"| [[File:Sprouting orb.png|40px]]
    <stat Name="Ego" Value="17" />
| style= "color:#155352" | <
    <stat Name="Willpower" Value="17" />
| style = "border:1px solid #155352;padding:0.5em 1em;" | What does <code>Load="Merge"</code> do?
|}


    <tag Name="BaseObject" Value="*noinherit" />
{| style = "margin: 1em;font-family:Source Code Pro;"
  </object>
| style = "padding:0em 1em;"| [[File:Mopango_pilgrim.png|40px]]
| style= "color:#155352" | <
| style = "border:1px solid #155352;padding:0.5em 1em;" | We need to specify <code>Load="Merge"</code> to tell Caves of Qud that we want to merge new XML into an existing table called (for example) <code>SnapjawParty0</code>. This prevents us from creating a new population table called <code>SnapjawParty0</code> that overwrites the old one.


  <object Name="Pyovya_SnapjawMage_Fire Mage" Inherits="Pyovya_SnapjawMage_Snapjaw Mage">
It's possible to use <code>Load="Merge"</code> to modify the contents of most of the game's XML files.
    <part Name="Render" DisplayName="snapjaw {{R|fire}} mage" Tile="Pyovya_SnapjawMage/snapjaw_mage.png" ColorString="&amp;O" DetailColor="R" />
|}
    <mutation Name="Pyrokinesis" Level="1" />
    <inventoryobject Blueprint="Pyovya_SnapjawMage_Fire Tome" Number="1" />
  </object>


  <object Name="Pyovya_SnapjawMage_Ice Mage" Inherits="Pyovya_SnapjawMage_Snapjaw Mage">
Each of these tables has a group named <code>Creatures</code>, for instance:
    <part Name="Render" DisplayName="snapjaw {{C|ice}} mage" Tile="Pyovya_SnapjawMage/snapjaw_mage.png" ColorString="&amp;O" DetailColor="C" />
    <mutation Name="Cryokinesis" Level="1" />
    <inventoryobject Blueprint="Pyovya_SnapjawMage_Ice Tome" Number="1" />
  </object>
</objects>
</syntaxhighlight>
 
... and here's my <code>Items.xml</code>:


<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="utf-8" ?>
<population Name="SnapjawParty0">
<objects>
  <group Name="Creatures" Style="pickeach">
  <!-- Weapons -->
    <object Chance="100" Number="1-3" Blueprint="Snapjaw Scavenger 0" />
  <object Name="Pyovya_SnapjawMage_Magic Tome" Inherits="BaseMissileWeapon">
    <object Chance="75" Number="1-3" Blueprint="Snapjaw Scavenger 0" />
     <!-- We borrow the same description that StandaloneMarkovBook uses -->
    <object Chance="25" Number="1-3" Blueprint="Snapjaw Hunter 0" />
     <part Name="Description" Short="Crisp pages of goatskin vellum are bound into a codex." />
    <object Chance="2" Number="1" Blueprint="Snapjaw Shotgunner 0" />
     <part Name="Physics" Weight="1" UsesTwoSlots="true" />
    <object Chance="15" Number="1" Blueprint="Snapjaw Brute 0" />
     <part Name="Commerce" Value="80" />
     <object Chance="10,3" Number="1" Blueprint="Snapjaw Warrior 0" />
     <object Chance="10" Number="1" Blueprint="Snapjaw Warlord 0" />
     <object Chance="3" Number="1" Blueprint="Snapjaw Hero 0" />
    <table Name="HumanoidEnvironmentFeatures" Chance="25" />
     <table Name="SnapjawParty0" Chance="10" />
  </group>
</population>
</syntaxhighlight>


    <tag Name="Tier" Value="2" />
So we'll also have our <code>PopulationTables.xml</code> merge new XML into each of these groups:
    <tag Name="Mods" Value="" />
    <tag Name="BaseObject" Value="*noinherit" />
  </object>


  <object Name="Pyovya_SnapjawMage_Fire Tome" Inherits="Pyovya_SnapjawMage_Magic Tome">
=== Dynamic population tables ===
    <part Name="Render" DisplayName="tome of {{R|fire}}" Tile="Items/sw_book_1.bmp" ColorString="&amp;R" DetailColor="Y" />
    <part Name="MissileWeapon" AmmoChar="f" ShotsPerAction="1" AmmoPerAction="1" ShotsPerAnimation="1" WeaponAccuracy="0" />
    <part Name="CooldownAmmoLoader" Cooldown="10" Readout="true" ProjectileObject="Pyovya_SnapjawMage_ProjectileFireTome" />


    <tag Name="MissileFireSound" Value="flamethrower" />
So far, the tables we've been working with have been '''''static''''' -- they're pre-defined based on the contents of <code>PopulationTables.xml</code>. It's also possible to generate a '''''dynamic''''' population table, by giving creatures and items a <code>DynamicObjectsTable</code> tag.
  </object>


  <object Name="Pyovya_SnapjawMage_Ice Tome" Inherits="Pyovya_SnapjawMage_Magic Tome">
== Conclusion ==
    <part Name="Render" DisplayName="tome of {{C|ice}}" Tile="Items/sw_book_1.bmp" ColorString="&amp;C" DetailColor="Y" />
    <part Name="MissileWeapon" AmmoChar="FR" ShotsPerAction="1" AmmoPerAction="1" ShotsPerAnimation="1" WeaponAccuracy="0" />
    <part Name="CooldownAmmoLoader" Cooldown="10" Readout="true" ProjectileObject="Pyovya_SnapjawMage_ProjectileIceTome" />


    <tag Name="MissileFireSound" Value="hiss_low" />
Congrats! You reached the end of the tutorial!
  </object>


  <!-- Projectiles -->
{| style = "margin: 1em;font-family:Source Code Pro;"
  <object Name="Pyovya_SnapjawMage_ProjectileFireTome" Inherits="TemporaryProjectile">
| style = "padding:0em 1em;"| [[File:Mopango_pilgrim.png|40px]]
    <part Name="Render" DisplayName="{{R|stream of flame}}" ColorString="&amp;R" />
| style= "color:#155352" | <
    <part Name="Projectile" BasePenetration="4" BaseDamage="1d4" Attributes="Heat Fire" ColorString="&amp;R" PassByVerb="whoosh" />
| style = "border:1px solid #155352;padding:0.5em 1em;" | Woohoo!
    <part Name="TemperatureOnHit" Amount="4d20" Max="false" OnWielderHit="true" />
|}
    <part Name="TemperatureOnEntering" Amount="8d20" Max="false" OnWielderHit="true" />
  </object>


  <object Name="Pyovya_SnapjawMage_ProjectileIceTome" Inherits="TemporaryProjectile">
{| style = "margin: 1em;font-family:Source Code Pro;"
    <part Name="Render" DisplayName="{{C|streak of ice}}" ColorString="&amp;B" />
| style = "padding:0em 1em;"| [[File:Sprouting orb.png|40px]]
    <part Name="Projectile" BasePenetration="4" BaseDamage="1d4" Attributes="Cold" ColorString="&amp;B" PassByVerb="crackle" />
| style= "color:#155352" | <
    <part Name="TemperatureOnHit" Amount="-4d20" Max="false" OnWielderHit="true" />
| style = "border:1px solid #155352;padding:0.5em 1em;" | I'm ready to go face these mages in magical combat.
    <part Name="TemperatureOnEntering" Amount="-8d20" Max="false" OnWielderHit="true" />
|}
  </object>
</objects>
</syntaxhighlight>


=== Extra challenge ===
=== Extra challenge ===

Navigation menu