User:Kernelmethod/Sandbox: Difference between revisions

From Caves of Qud Wiki
Jump to navigation Jump to search
(Create initial sketch of the Snapjaw Wizards tutorial.)
 
m (Add some XML fragments to the static encounters section)
 
(38 intermediate revisions by the same user not shown)
Line 1: Line 1:
Modding Tutorial: ''Snapjaw Wizards!''
== Tutorial: Mage Towers (static and dynamic encounters) ==


Welcome! If you're looking to get started with modding Caves of Qud, this tutorial is a good place to start.
Potential ideas for an encounters tutorial:


In this tutorial, we're going to add a new creature to the game -- the great and mystical '''''snapjaw wizard'''''. Along the way we're going to be helped by my friends {{qud text|&MRulimispruce, legendary sprouting orb}} and {{qud text|&MPyovya, legendary mopango}}.
* Static/dynamic locations
* Adding secrets during worldgen
* Zone builders


{| style = "margin: 1em;font-family:Source Code Pro;"
Some potential references:
| style = "padding:0em 1em;"| [[File:Sprouting orb.png|40px]]
| style= "color:#155352" | <
| style = "border:1px solid #155352;padding:0.5em 1em;" | Howdy!
|}


{| style = "margin: 1em;font-family:Source Code Pro;"
* {{favilink|Flattened remains}}
| style = "padding:0em 1em;"| [[File:Mopango_pilgrim.png|40px]]
* {{favilink|Ancient bones}} in the {{favilink|waterlogged tunnel}}
| style= "color:#155352" | <
* {{favilink|Stopsvalinn}}
| style = "border:1px solid #155352;padding:0.5em 1em;" | Let's get started!
* {{favilink|Oddly-hued Glowpad}}
|}
* {{favilink|Ruin of House Isner}}
* {{favilink|Bey Lah}}


== Getting started ==
Other:


TODO:
* https://bitbucket.org/bbucklew/cavesofqud-public-issue-tracker/issues/9458/modding-feature-request-allow-for-merging
* Setting up development environment
* Where to find game files.
* Player.log
* How to perform a wish
* The _Quickstart game option


Prerequisites:
Static encounters section can be done with just XML; dynamic encounters section will require some C# experience.
* Have played through a good chunk of Qud


== Basic concepts ==
== Adding static encounters ==


=== XML ===
* Editing cell definition in Worlds.xml
* Add a new population table to a cell.
* Create a map template with the map editor.


* What is XML?
<syntaxhighlight lang="XML">
* Tags vs attributes
 
=== Wishes ===
 
== Creating a mod ==
 
* Adding new mod with <code>manifest.json</code> to the <code>Mods/</code> folder.
* At the end of this section, modders should have a no-op mod that appears in their mods list.
 
<syntaxhighlight lang="text">
SnapjawWizard
├── manifest.json
└── preview.png
</syntaxhighlight>
 
== Your first creature ==
 
=== Adding a new creature to <code>Creatures.xml</code> ===
 
In your mod directory, create a new folder called <code>ObjectBlueprints/</code>, and within that folder open up a new file in your text editor called <code>Creatures.xml</code>. Let's start by adding the following to <code>Creatures.xml</code>:
 
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8" ?>
<objects>
<objects>
</objects>
  <!--
</syntaxhighlight>
    Due to an outstanding bug in the way the Hills zonebuilder works, your
    terrain object *must* have the word "Hills" somewhere in its name.


Save this file! Before continuing, make sure your mod directory looks something like this:
    https://bitbucket.org/bbucklew/cavesofqud-public-issue-tracker/issues/10902
 
  -->
<syntaxhighlight lang="text">
  <object Name="Pyovya_SnapjawMage_TerrainMageHills" Inherits="TerrainHills">
SnapjawWizard
    <part Name="Render" DisplayName="mage's tower" RenderString="227" ColorString="&amp;K" DetailColor="m" Tile="Pyovya_SnapjawMage/mage_tower.png" />
├── manifest.json
    <part Name="Description" Short="The secluded abode of an accomplished magician lays against the rolling hillscape. At night, one can hear their lonely howls emanating from the ruined tower." />
├── ObjectBlueprints
    <!--
│   └── Creatures.xml
      Remove the RandomTile part inherited from TerrainHills so that our tile doesn't
└── preview.png
      get replaced with a random hills tile.
</syntaxhighlight>
    -->
 
    <removepart Name="RandomTile" />
With that out of the way, let's start adding our new snapjaw wizard to <code>Creatures.xml</code>:
    <!--
 
      We modify grammatical usage of the terrain's name so that when we pass it by
<syntaxhighlight lang="xml">
      on the world map, it says that we pass by "a mage's tower" rather than "some
<?xml version="1.0" encoding="utf-8" ?>
      mage's tower" or "a set of mage's tower".
<objects>
    -->
  <object Name="Pyovya_SnapjawWizard_Snapjaw Wizard" Inherits="Snapjaw">
    <xtagGrammar Proper="false" massNoun="false" />
    <tag Name="Gender" Value="*delete" />
   </object>
   </object>
</objects>
</objects>
</syntaxhighlight>
</syntaxhighlight>


Let's break this down:
<syntaxhighlight lang="XML">
* The <code>object</code> tag tells Qud that we want to add a new creature.
* The <code>Name</code> attribute is a unique identifier for our new creature (it's not the name of the creature as it appears in-game -- we'll get to that shortly). You'll use this identifier whenever you want to wish for a new snapjaw wizard.
* The <code>Inherits</code> attribute says that our new creature should "inherit" all of the properties of the <code>Snapjaw</code> creature.
 
{| style = "margin: 1em;font-family:Source Code Pro;"
| style = "padding:0em 1em;"| [[File:Sprouting orb.png|40px]]
| style= "color:#155352" | <
| style = "border:1px solid #155352;padding:0.5em 1em;" | Hey, why'd you add the <code>Pyovya_SnapjawWizard</code> bit to the front of the name of the creature? Why not just call it a <code>Snapjaw Wizard</code>?
|}
 
{| style = "margin: 1em;font-family:Source Code Pro;"
| style = "padding:0em 1em;"| [[File:Mopango_pilgrim.png|40px]]
| style= "color:#155352" | <
| style = "border:1px solid #155352;padding:0.5em 1em;" | When writing a mod, it's common courtesy to prefix unique identifiers with your name, an underscore <code>_</code>, followed by the mod's name. This ensures that if somebody else writes their own Snapjaw Wizard mod, your mod won't conflict with theirs.
|}
 
So far we haven't actually added anything to our new creature; for all intents and purposes it's a plain ol' snapjaw. Let's change that by adding some parts.
 
{| style = "margin: 1em;font-family:Source Code Pro;"
| style = "padding:0em 1em;"| [[File:Sprouting orb.png|40px]]
| style= "color:#155352" | <
| style = "border:1px solid #155352;padding:0.5em 1em;" | What's a part?
|}
 
{| style = "margin: 1em;font-family:Source Code Pro;"
| style = "padding:0em 1em;"| [[File:Mopango_pilgrim.png|40px]]
| style= "color:#155352" | <
| style = "border:1px solid #155352;padding:0.5em 1em;" | A '''''part''''' is a special piece of code that can be added to a creature to modify its appearance, behavior, stats, and any number of other things. There are a ''lot'' of parts -- over a thousand! You won't need to worry about most of them; many of them are highly-customized bits of code written for just one or two creatures. For instance, there's a <code>CryptSitterBehavior</code> part that is used exclusively by {{favilink|crypt sitter|plural}}.
|}
 
We're going to add two new parts to our creature: <code>Render</code> and <code>Description</code>.
 
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8" ?>
<objects>
<worlds>
   <object Name="Pyovya_SnapjawWizard_Snapjaw Wizard" Inherits="Snapjaw">
   <world Name="JoppaWorld" Load="Merge">
     <part Name="Description" Short="A great hero of the snapjaws." />
     <cell Name="Pyovya_SnapjawMage_MageTower" Inherits="Hills" ApplyTo="Pyovya_SnapjawMage_TerrainMageHills" Mutable="false">
    <part Name="Render" DisplayName="snapjaw wizard" Tile="Assets_Content_Textures_Creatures_sw_snapjaw_warrior.bmp" ColorString="&amp;Y" DetailColor="R" />
      <!-- New zone containing the mage's tower -->
   </object>
      <zone Level="10" x="1" y="1" IndefiniteArticle="a" Name="mage's tower" HasWeather="true" WindSpeed="0-60" WindDirections="N,NW,NW,W,W,SW,S,SE" WindDuration="50-3000">
</objects>
      </zone>
    </cell>
   </world>
</worlds>
</syntaxhighlight>
</syntaxhighlight>


Before I did into the new XML we've added, save <code>Creatures.xml</code>. Reload your mods, start a new game and wish for a <code>Pyovya_SnapjawWizard_Snapjaw Wizard</code>. You should a new snapjaw like the one below show up:
<syntaxhighlight lang="XML">
 
<?xml version="1.0" encoding="utf-8"?>
(IMAGE HERE, INCLUDING DESCRIPTION OF SNAPJAW)
<Map Width="80" Height="25">
 
  <cell X="19" Y="23">
Congrats! You've successfully added a snapjaw wizard to your game.
    <object Name="Pyovya_SnapjawMage_TerrainMageHills"></object>
 
  </cell>
{| style = "margin: 1em;font-family:Source Code Pro;"
</Map>
| style = "padding:0em 1em;"| [[File:Sprouting orb.png|40px]]
| style= "color:#155352" | <
| style = "border:1px solid #155352;padding:0.5em 1em;" | I did?
|}
 
Well, it's still a little bare-bones, but you have indeed created a new creature called a <code>snapjaw wizard</code> and spawned it in your game! Give yourself a pat on the back, Rulimispruce.
 
{| style = "margin: 1em;font-family:Source Code Pro;"
| style = "padding:0em 1em;"| [[File:Sprouting orb.png|40px]]
| style= "color:#155352" | <
| style = "border:1px solid #155352;padding:0.5em 1em;" | *rustling noises*
|}
 
Now, back to the parts that you just added:
 
* The <code>Description</code> part changes (as you might guess) the description of the creature when you look at it.
* The <code>Render</code> attribute changes the creature's appearance, as well as its name (as it appears in-game). This tag has the following attributes:
** <code>DisplayName</code>: how the creature's name is displayed in-game.
** <code>Tile</code>: a .png or .bmp ("bitmap") image that's used to display the creature. Check out [[Modding:Tiles]] for more information. In the snippet above, I just used the tile for {{favilink|snapjaw warrior|plural}} to get us started.
** <code>ColorString</code> and <code>DetailColor</code>: these are the primary and secondary colors used to color in the tile that you supply. You can look at [[Modding:Colors & Object Rendering]] for a full list of all of the available colors; in this case, we used <code>Y</code> (white) as the primary color and <code>M</code> (magenta) as the detail color.
 
=== Using custom tiles ===
 
Instead of having our snapjaw wizards look like off-color snapjaw warriors, let's add a snazzy new tile to the game to use for our wizards! Just pop open a pixel editor, create a 16px x 24px black-and-white tile, save it as a --
 
{| style = "margin: 1em;font-family:Source Code Pro;"
| style = "padding:0em 1em;"| [[File:Sprouting orb.png|40px]]
| style= "color:#155352" | <
| style = "border:1px solid #155352;padding:0.5em 1em;" | I'm just a lil old sprouting orb, I don't know how to do any of those things.
|}
 
Ah, alright, fair enough. Well in that case, feel free to download the tile that I've already made for you here:
 
DOWNLOAD LINK FOR NEW TILE
 
In your mod directory, create a new folder called <code>Textures/</code>; in that folder, create a new subfolder called <code>Pyovya_SnapjawWizard/</code>; and in there, create another subfolder called <code>Creatures/</code>. Save <code>snapjaw_wizard.png</code> there, so that your mod folder now looks like this:
 
<syntaxhighlight lang="text">
SnapjawWizard
├── manifest.json
├── ObjectBlueprints
│   └── Creatures.xml
├── preview.png
└── Textures
    └── Pyovya_SnapjawWizard
        └── snapjaw_wizard.png
</syntaxhighlight>
 
Now, let's change the <code>Render</code> part for our wizards to use this new tile:
 
<syntaxhighlight lang="xml">
<part Name="Render" DisplayName="snapjaw wizard" Tile="Pyovya_Snapjaw/snapjaw_wizard.png" ColorString="&amp;Y" DetailColor="R" />
</syntaxhighlight>
</syntaxhighlight>


Now when you spawn a snapjaw hero, it'll look something like this:
== Your first dynamic encounter ==


IMAGE
=== World generation ===


Cool!
* Locate zone to place tower
 
* Place creature
=== Filling out your new creature ===
 
Let's keep adding some more stuff to our snapjaw wizard to round them out a bit more. First of all, like any good wizard, they need a {{favilink|walking stick}} and some [[book|books]]. Let's give them some clothes to equip while we're at it. Add the following XML to your creature:
 
<syntaxhighlight lang="xml">
<inventoryobject Blueprint="Walking Stick" />
<inventoryobject Blueprint="Woven Tunic" Number="1" />
<inventoryobject Blueprint="Sandals" Number="1" />
<inventoryobject Blueprint="StandaloneMarkovBook" Number="2-3" />
</syntaxhighlight>
 
Let's give our wizard the [[Cudgel]] skill as well, so that they're a little bit better at fighting with that walking stick:
 
<syntaxhighlight lang="xml">
<skill Name="Cudgel" />
</syntaxhighlight>
 
TODO: stats
 
TODO
 
<syntaxhighlight lang="xml">
<property Name="Role" Value="Artillery" />
</syntaxhighlight>
 
TODO
 
<syntaxhighlight lang="xml">
<tag Name="DynamicObjectsTable:Snapjaws" />
<tag Name="AggregateWith" Value="Pyovya_SnapjawWizard_Snapjaw Wizard" />
<tag Name="BaseObject" Value="*noinherit" />
</syntaxhighlight>
 
FINAL VERSION OF CREATURE XML BEFORE GOING TO THE NEXT SECTION
 
=== Using your creature as a base: Elemental Wizards ===
 
{| style = "margin: 1em;font-family:Source Code Pro;"
| style = "padding:0em 1em;"| [[File:Sprouting orb.png|40px]]
| style= "color:#155352" | <
| style = "border:1px solid #155352;padding:0.5em 1em;" | Hold up a second. How is this creature a wizard? It doesn't have any kind of magic spells!
|}
 
I was just getting to that!
 
So far, we've sketched out most of the properties, skills, and stats that a snapjaw wizard should have. Now we're going to create two types of wizards: '''''fire wizards''''' and '''''ice wizards'''''. Under your definition of the <code>Pyovya_SnapjawWizard_Snapjaw Wizard</code> creature in <code>Creatures.xml</code>, add two new creatures:
 
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="utf-8" ?>
<objects>
  <!--
  Skipped: the XML that defines the "Pyovya_SnapjawWizard_Snapjaw Wizard" creature
  -->
 
  <object Name="Pyovya_SnapjawWizard_Flame Wizard" Inherits="Pyovya_SnapjawWizard_Snapjaw Wizard">
  </object>
 
  <object Name="Pyovya_SnapjawWizard_Ice Wizard" Inherits="Pyovya_SnapjawWizard_Snapjaw Wizard">
  </object>
</objects>
</syntaxhighlight>
 
Referencing the [[Modding:Colors & Object Rendering]] page, we're going to change our fire wizard's detail color to red. We're also going to give them the {{favilink|Flaming Ray}} mutation:
 
<syntaxhighlight lang="xml">
<object Name="Pyovya_SnapjawWizard_Flame Wizard" Inherits="Pyovya_SnapjawWizard_Snapjaw Wizard">
  <part Name="Render" DisplayName="snapjaw wizard of {{R|fire}}" Tile="Pyovya_SnapjawWizard/snapjaw_wizard.png" ColorString="&amp;Y" DetailColor="R" />
  <mutation Name="FlamingHands" Level="1" BodyPartType="Hands" CreateObject="false" />
</object>
</syntaxhighlight>
 
TODO: explain syntax for changing text color.
 
TODO: explain what's going on in the <code><mutation></code> tag.
 
<syntaxhighlight lang="xml">
<object Name="Pyovya_SnapjawWizard_Ice Wizard" Inherits="Pyovya_SnapjawWizard_Snapjaw Wizard">
  <part Name="Render" DisplayName="snapjaw wizard of {{C|ice}}" Tile="Pyovya_SnapjawWizard/snapjaw_wizard.png" ColorString="&amp;Y" DetailColor="R" />
  <mutation Name="FreezingHands" Level="1" BodyPartType="Hands" CreateObject="false" />
</object>
</syntaxhighlight>


TODO:
=== Zone builders ===
* Inherit from the Snapjaw Hero
* Add mutations, change colors


[[Category:Guides]]
* Place walls and items
* Add map template.

Latest revision as of 01:13, 5 March 2024

Tutorial: Mage Towers (static and dynamic encounters)

Potential ideas for an encounters tutorial:

  • Static/dynamic locations
  • Adding secrets during worldgen
  • Zone builders

Some potential references:

Other:

Static encounters section can be done with just XML; dynamic encounters section will require some C# experience.

Adding static encounters

  • Editing cell definition in Worlds.xml
  • Add a new population table to a cell.
  • Create a map template with the map editor.
<?xml version="1.0" encoding="utf-8" ?>
<objects>
  <!--
    Due to an outstanding bug in the way the Hills zonebuilder works, your
    terrain object *must* have the word "Hills" somewhere in its name.

    https://bitbucket.org/bbucklew/cavesofqud-public-issue-tracker/issues/10902
  -->
  <object Name="Pyovya_SnapjawMage_TerrainMageHills" Inherits="TerrainHills">
    <part Name="Render" DisplayName="mage's tower" RenderString="227" ColorString="&amp;K" DetailColor="m" Tile="Pyovya_SnapjawMage/mage_tower.png" />
    <part Name="Description" Short="The secluded abode of an accomplished magician lays against the rolling hillscape. At night, one can hear their lonely howls emanating from the ruined tower." />
    <!--
      Remove the RandomTile part inherited from TerrainHills so that our tile doesn't
      get replaced with a random hills tile.
    -->
    <removepart Name="RandomTile" />
    <!--
      We modify grammatical usage of the terrain's name so that when we pass it by
      on the world map, it says that we pass by "a mage's tower" rather than "some
      mage's tower" or "a set of mage's tower".
    -->
    <xtagGrammar Proper="false" massNoun="false" />
    <tag Name="Gender" Value="*delete" />
  </object>
</objects>
<?xml version="1.0" encoding="utf-8" ?>
<worlds>
  <world Name="JoppaWorld" Load="Merge">
    <cell Name="Pyovya_SnapjawMage_MageTower" Inherits="Hills" ApplyTo="Pyovya_SnapjawMage_TerrainMageHills" Mutable="false">
      <!-- New zone containing the mage's tower -->
      <zone Level="10" x="1" y="1" IndefiniteArticle="a" Name="mage's tower" HasWeather="true" WindSpeed="0-60" WindDirections="N,NW,NW,W,W,SW,S,SE" WindDuration="50-3000">
      </zone>
    </cell>
  </world>
</worlds>
<?xml version="1.0" encoding="utf-8"?>
<Map Width="80" Height="25">
  <cell X="19" Y="23">
    <object Name="Pyovya_SnapjawMage_TerrainMageHills"></object>
  </cell>
</Map>

Your first dynamic encounter

World generation

  • Locate zone to place tower
  • Place creature

Zone builders

  • Place walls and items
  • Add map template.