Modding:Encounters and Population: Difference between revisions

m
Add some info about the population:findblueprint and population:generate wishes
imported>CaptainTechnicality54384
(→‎Extending Encounter Tables: Adding Syntax highlighting)
m (Add some info about the population:findblueprint and population:generate wishes)
 
(12 intermediate revisions by 5 users not shown)
Line 1: Line 1:
[[Category:Modding]]
[[Category:Modding]]{{Modding Info}}
There are two primary population systems in Caves of Qud, the legacy EncounterTables.xml system, and the ZoneTemplates.xml+PopulationTables.xml system. EncounterTables is older and we prefer to use zone templates + population tables these days, but much of the game is still populated via EncounterTables.xml.
There are two primary population systems in Caves of Qud, the legacy <code>EncounterTables.xml</code> system, and the <code>ZoneTemplates.xml</code>+<code>PopulationTables.xml</code> system. Encounter tables are an older system and we prefer to use zone templates + population tables these days, but much of the game is still populated via <code>EncounterTables.xml</code>.


Like ObjectTables, EncounterTables.xml supports Load="Merge" in the object root tag. This will append entries to that particular table instead of overwriting.
Like <code>ObjectBlueprints.xml</code>, both the <code>EncounterTables.xml</code> and the <code>PopulationTables.xml</code> support use of the <code>Load="Merge"</code> attribute to merge content into existing tables defined by the base game files. This will append entries to the specified table instead of overwriting it.


PopulationTables currently do not support modding, but many zone template encounters draw objects from dynamically created population tables. Check out the following tags in ObjectBlueprints.xml to see them in use: DynamicObjectsTable, ExcludeFromDynamicEncounters. Some dynamic population tables are created based on the base type of the object, so new objects will begin appearing immediately in areas generated with dynamic population tables unless they are tagged with ExcludeFromDynamicEncounters.
Many zone template encounters draw objects from dynamically created population tables. Check out the following tags in <code>ObjectBlueprints.xml</code> to see them in use: <code>DynamicObjectsTable</code>, <code>ExcludeFromDynamicEncounters</code>. Some dynamic population tables are created based on the base type of the object, so new objects will begin appearing immediately in areas generated with dynamic population tables unless they are tagged with <code>ExcludeFromDynamicEncounters</code>. Refer to the section below for more information about Dynamic population tables.


The unaffiliated cave systems are the only areas currently heavily populated with the template+population system.
The unaffiliated cave systems are one area that is heavily populated with the zone template+population system.


== Extending Encounter Tables ==
== Extending Encounter Tables ==
You may add new entries to existing encounter tables by including encountertables.xml in your mod, using an existing table name and setting the Load="Merge" property on the encountertable tag.
You may add new entries to existing encounter tables by including <code>EncounterTables.xml</code> in your mod, using an existing table name and setting the <code>Load="Merge"</code> property on the encountertable tag.


'''Adding "My New Ammo" to the "Ammo 1" built-in encounter table'''
'''Adding "My New Ammo" to the "Ammo 1" built-in encounter table'''
Line 21: Line 21:
</encountertables>
</encountertables>
</syntaxhighlight>
</syntaxhighlight>
==Extending Population Tables==
To modify existing populations, you can take a similar approach. For example, the following could be used in a mod's <code>PopulationTables.xml</code> file to add a new type of Wristblade Legendary merchant lair:
<syntaxhighlight lang="xml">
  <population Name="GenericLairOwner" Load="Merge">
    <group Name="Options" Load="Merge">  <!-- Add the Load="Merge" attribute to each nested group, mimicking the base game's PopulationTables.xml structure -->
      <object Blueprint="WristbladeMerchant" Weight="20" /> <!-- Insert your new item! -->
    </group>
  </population>
</syntaxhighlight>
Of course, this would also need to be supplemented with an ObjectBlueprints.xml that defines the new "WristbladeMerchant". It would likely inherit from "BaseMerchant" and have the appropriate parts defined, similar to other legendary merchants.
=== Full Example Usage ===
Here is some example XML from a mod that creates a fully functional Six Day Stilt vendor using a combination of <code>Load="Merge"</code> tables and new tables defined by the mod. This is everything that's needed in the mod's PopulationTables.xml file, though this won't work by itself. It would also require an ObjectBlueprints.xml to define the various Blueprint objects that are not included here.
<syntaxhighlight lang="xml">
  <!-- Merge new YoyoWinderTent into the game's StiltTents population table -->
  <population Name="StiltTents" Load="Merge">
    <group Name="Types" Load="Merge">
      <table Name="YoyoWinderTent" Weight="4" />
    </group>
  </population>
  <!-- Define the YoyoWinderTent -->
  <population Name="YoyoWinderTent">
    <group Name="Contents" Style="pickeach">
      <object Blueprint="YoyoWinder" Number="1" Hint="Interior" />
      <table Name="YoyoWinderTentContents" />
    </group>
  </population>
  <population Name="YoyoSigns">
    <group Name="Items" Style="pickone">
      <object Blueprint="YoyoSign1" Number="1" Hint="OutsideDoor:1" />
      <object Blueprint="YoyoSign2" Number="1" Hint="OutsideDoor:1" />
      <object Blueprint="YoyoSign3" Number="1" Hint="OutsideDoor:1" />
    </group>
  </population>
  <population Name="YoyoWinderTentContents">
    <group Name="Contents" Style="pickeach">
      <object Blueprint="Torchpost" Number="1" Hint="InsideCorner" />
      <table Name="YoyoSigns" />
      <object Blueprint="Torchpost" Number="1-2" Hint="OutsideDoor:2" />
      <object Blueprint="YoyoWinder Workbench" Number="1-2" Hint="AlongInsideWall" />
      <object Blueprint="Woven Basket" Number="1" />
      <object Blueprint="YoyoWinder Workbench" Number="1" />
      <object Blueprint="Yoyo Oil Pitcher" Number="1-2" Hint="AlongInsideWall" />
      <object Blueprint="Yoyo String Plastifer 3" Number="1" Chance="15" />
      <object Blueprint="Yoyo String Elastyne 3" Number="1" Chance="35" />
      <object Blueprint="Yoyo String Elastyne 5" Number="1" Chance="20" />
      <object Blueprint="Chest" Number="1-2" Hint="AlongInsideWall" />
    </group>
  </population>
</syntaxhighlight>
== Dynamic Tables ==
The game sometimes uses dynamically generated population tables, which are constructed from objects in ObjectBlueprints.xml.
There are three methods of constructing dynamic tables:
* Through the use of <code>DynamicObjectsTable</code>, which identifies all of the objects that have been tagged as belonging to a particular table.
* Through inheritance and the use of <code>DynamicInheritsTable</code>.
* Through <code>DynamicSemanticTable</code>, which collects all objects that are in the intersection of a set of categories.
=== DynamicObjectsTable ===
A <code>DynamicObjectsTable</code> contains all objects that have been tagged as belonging to that table. Here's an example from the definition of {{favilink|shrewd baboon}} in <code>ObjectBlueprints/Creatures.xml</code>:
<syntaxhighlight lang="xml">
<object Name="Shrewd Baboon" Inherits="Baboon">
  <part Name="Render" DisplayName="shrewd baboon" ColorString="&amp;B" />
  <stat Name="AV" Value="3" />
  <stat Name="Intelligence" Boost="1" />
  <stat Name="Hitpoints" Value="20" />
  <property Name="Role" Value="Leader" />
  <tag Name="DynamicObjectsTable:Baboons" />
</object>
</syntaxhighlight>
Shrewd baboon has been given <code>&lt;tag Name="DynamicObjectsTable:Baboons" /&gt;</code>, so it automatically belongs to the <code>Baboons</code> dynamic objects table.
=== DynamicInheritsTable ===
A <code>DynamicInheritsTable</code> contains all objects that inherit from another object. For example, here's the population table for <code>GritGateWorkbench</code> population table, which is used to generate the contents of the {{favilink|workbench|plural}} that appear in {{favilink|Grit Gate}}:
<syntaxhighlight lang="xml">
<population Name="GritGateWorkbench">
  <group Name="GritGateWorkbench" Style="pickeach">
    <table Name="DynamicInheritsTable:Tool" Chance="15" />
    <table Name="Junk {zonetier}" Chance="15" />
    <table Name="DynamicObjectsTable:EnergyCells" Chance="15" />
  </group>
</population>
</syntaxhighlight>
This population table has a 15% chance of generating an item from the <code>DynamicInheritsTable:Tool</code> table, which includes any item that is descended (through inheritance) from <code>Tool</code>. This includes {{favilink|basic toolkit|plural}}, {{favilink|advanced toolkit|plural}}, {{favilink|pickaxe|plural}}, and several other items.
A <code>DynamicInheritsTable</code> can be weighted based on the tier of an item by appending <code>:Tier&lt;zonetier&gt;</code>.
For example, <code>DynamicInheritsTable:BaseLongBlade:Tier5</code> will give a weight of 1000 to items of the specified tier, a weight of 100 to items one tier above or below that, a weight of 10 to items two tiers above or below that, and a weight of 1 to all other items. This results in a population table being constructed by the game similar to the following:
{| class="wikitable"
! Item
! Weight
|-
| {{favilink id|Long Sword}}
| 1
|-
| {{favilink id|Two-Handed Sword}}
| 1
|-
| {{favilink id|Long Sword2}}
| 1
|-
| {{favilink id|Long Sword2th}}
| 1
|-
| {{favilink id|Steel Long Sword}}
| 1
|-
| {{favilink id|Steel Long Swordth}}
| 1
|-
| {{favilink id|Long Sword3}}
| 10
|-
| {{favilink id|Long Sword3th}}
| 10
|-
| {{favilink id|Long Sword4}}
| 100
|-
| {{favilink id|Long Sword4th}}
| 100
|-
| {{favilink id|Long Sword5}}
| 1000
|-
| {{favilink id|Long Sword5th}}
| 1000
|-
| {{favilink id|Long Sword6}}
| 100
|-
| {{favilink id|Long Sword6th}}
| 100
|-
| {{favilink id|Long Sword7}}
| 10
|-
| {{favilink id|Long Sword7th}}
| 10
|-
| {{favilink id|Long Sword8}}
| 1
|-
| {{favilink id|Long Sword8th}}
| 1
|-
| {{favilink id|Vibro Blade}}
| 1000
|}
=== DynamicSemanticTable ===
A <code>DynamicSemanticTable</code> can generate any object within an intersecting list of categories. Consider the population table for the ruined ward section of {{favilink|Bethesda Susa}}:
<syntaxhighlight lang="xml">
<population Name="BethesdaSusaRuinedWard">
  <!-- Skipping over most of the contents of this table... -->
  <table Chance="80" Number="1-8" Name="DynamicSemanticTable:Medical,Furniture:4:6" Hint="AlongWall" />
  <table Chance="60" Number="1-4" Name="DynamicSemanticTable:Professional,Furniture:2:5" Hint="AlongWall" />
  <table Chance="5" Number="1-3" Name="DynamicSemanticTable:Torture,Furniture:1:5" Hint="AlongWall" />
  <table Chance="5" Number="1-2" Name="DynamicSemanticTable:Child,Furniture:1:5" Hint="AlongWall" />
  <table Chance="5" Number="1-2" Name="DynamicSemanticTable:Normality,Furniture" Hint="AlongWall" />
</population>
</syntaxhighlight>
Picking out one line of this, <code>DynamicSemanticTable:Medical,Furniture:4:6</code> is a dynamic table which includes objects that have both <code>&lt;stag Name="Medical" /&gt;</code> and <code>&lt;stag Name="Furniture" /&gt;</code> in their definition. The <code>4:6</code> bit will weight objects more heavily as their tier gets closer to 4 or their tech tier gets closer to 6.
=== Excluding objects from dynamic tables ===
Finally, it's possible to explicitly exclude an object from all dynamic tables by adding the following tag to it:
<syntaxhighlight lang="xml">
<tag Name="ExcludeFromDynamicEncounters" />
</syntaxhighlight>
This is especially helpful when creating unique or rare NPCs and items, who aren't expected to simply appear in random zones. It is also useful when defining base objects, who serve as a template on which to construct other objects but should not themselves appear in-game.
== Debugging population tables ==
There are two [[wishes]] available to make it easier to determine what objects appear in population tables:
* <code>population:findblueprint:&lt;blueprint&gt;</code>: shows the probability of a particular blueprint appearing at least once for every population table.
* <code>population:generate:&lt;table&gt;#&lt;amount&gt;</code>: generates a given population table the specified number of times, and then shows the frequency of various blueprints among the generated objects.
Both wishes are compatible with dynamic tables.


== Additional Info ==
== Additional Info ==
Here's a thread on Steam where I discuss using encounter and population tables: http://steamcommunity.com/app/333640/discussions/3/358415738194955181/
{{Cleanup |The information from the Steam thread needs to be integrated into this article.}}
Here's a thread on Steam where Brian discusses using encounter and population tables: http://steamcommunity.com/app/333640/discussions/3/358415738194955181/
 
{{Modding Navbox}}