User:Kernelmethod/Sandbox: Difference between revisions

no edit summary
No edit summary
No edit summary
Line 41: Line 41:
=== XML ===
=== XML ===


'''XML''' (the e'''X'''tended '''M'''arkup '''L'''anguage) is a type of ''markup language'', which (loosely speaking) is a text-based document format that can be read and interpreted by a program. Caves of Qud makes extensive use of XML for things like defining creatures, quests, items, conversations, and more. We'll be working with XML a lot throughout this tutorial, so it's helpful to have a little familiarity with XML first.
'''XML''' (the e'''X'''tended '''M'''arkup '''L'''anguage) is a type of ''markup language'', which (loosely speaking) is a text-based format that can be understood by a program. Caves of Qud makes extensive use of XML for things like defining creatures, quests, items, conversations, and more. We'll be working with XML a lot throughout this tutorial, so it's helpful to have a little familiarity with XML first.


You can check out the [https://en.wikipedia.org/wiki/XML| Wikipedia page on XML] if you want to learn more. Here's some basic terminology you should be familiar with: in the XML snippet below,
You can check out the [https://en.wikipedia.org/wiki/XML| Wikipedia page on XML] if you want to learn more. Here's some basic terminology you should be familiar with: in the XML snippet below,
Line 49: Line 49:
</syntaxhighlight>
</syntaxhighlight>


<code>foo</code> is what's called an '''XML tag'''. Meanwhile, <code>bar</code> is an '''attribute''', which (in this case) has been assigned the value <code>baz</code>.
<code>foo</code> is an '''XML tag'''. Meanwhile, <code>bar</code> is an '''attribute''', which (in this case) has been assigned the value <code>baz</code>.


You may also see '''comments''' here and there. A comment consists of one or more lines of text between <code>&lt;!--</code> and <code>--&gt;</code>, such as the following:
You may also see '''comments''' here and there. A comment consists of one or more lines of text between <code>&lt;!--</code> and <code>--&gt;</code>, such as the following:
Line 103: Line 103:
We should also get a preview image for the mod. I've made one that you can use here:
We should also get a preview image for the mod. I've made one that you can use here:


IMAGE DOWNLOAD LINK
https://github.com/kernelmethod/QudMods/blob/SnapjawMage/SnapjawMage/SnapjawMage/preview.png


Download this image and place it in the <code>SnapjawMage/</code> folder, so that now your folder looks like this:
Download this image and place it in the <code>SnapjawMage/</code> folder, so that now your folder looks like this:
Line 241: Line 241:
Ah, alright, fair enough. Well in that case, feel free to download the tile that I've already made for you here:
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
https://github.com/kernelmethod/QudMods/blob/SnapjawMage/SnapjawMage/SnapjawMage/Textures/Pyovya_SnapjawMage/snapjaw_mage.png


In your mod directory, create a new folder called <code>Textures/</code>; in that folder, create a new subfolder called <code>Pyovya_SnapjawMage/</code>; and in there, create another subfolder called <code>Creatures/</code>. Save <code>snapjaw_mage.png</code> there, so that your mod folder now looks like this:
In your mod directory, create a new folder called <code>Textures/</code>; in that folder, create a new subfolder called <code>Pyovya_SnapjawMage/</code>; and in there, create another subfolder called <code>Creatures/</code>. Save <code>snapjaw_mage.png</code> there, so that your mod folder now looks like this:
Line 298: Line 298:
<!-- Raise willpower to reduce the cooldowns of abilities -->
<!-- Raise willpower to reduce the cooldowns of abilities -->
<stat Name="Willpower" Value="17" />
<stat Name="Willpower" Value="17" />
</syntaxhighlight>
=== Minor details ===
TODO
<syntaxhighlight lang="xml">
<property Name="Role" Value="Artillery" />
</syntaxhighlight>
TODO
<syntaxhighlight lang="xml">
<tag Name="DynamicObjectsTable:Snapjaws" />
<tag Name="AggregateWith" Value="Pyovya_SnapjawMage_Snapjaw Mage" />
</syntaxhighlight>
</syntaxhighlight>


Line 339: Line 324:
     <stat Name="Ego" Value="17" />
     <stat Name="Ego" Value="17" />
     <stat Name="Willpower" Value="17" />
     <stat Name="Willpower" Value="17" />
    <property Name="Role" Value="Artillery" />
    <tag Name="DynamicObjectsTable:Snapjaws" />
    <tag Name="AggregateWith" Value="Pyovya_SnapjawMage_Snapjaw Mage" />
   </object>
   </object>
</objects>
</objects>
Line 410: Line 391:
== Creating new items ==
== Creating new items ==


We've now successfully added a {{qud text|&Ysnapjaw &Rfire &Ymage}} and a {{qud text|&Ysnapjaw &Cice &Ymage}}. We're also going to give them two new items: a {{qud text|&Ytome of &Rfire}} and a {{qud text|&Ytome of &Cice}}. These will function as less powerful versions of the {{favilink|flamethrower}} and {{favilink|freeze ray}}, respectively.
We've now successfully added a {{qud text|&Ysnapjaw &Rfire &Ymage}} and a {{qud text|&Ysnapjaw &Cice &Ymage}}. We're also going to give them two new items: a {{qud text|&Ytome of &Rfire}} and a {{qud text|&Ytome of &Cice}}. These new weapons will be magical spell books that function as less powerful versions of the {{favilink|flamethrower}} and {{favilink|freeze ray}}, respectively.


Start by creating a new file <code>Items.xml</code> in the <code>ObjectBlueprints/</code> folder:
Start by creating a new file <code>Items.xml</code> in the <code>ObjectBlueprints/</code> folder:
Line 418: Line 399:
├── manifest.json
├── manifest.json
├── ObjectBlueprints
├── ObjectBlueprints
│   ├── Creatures.xml
│  ├── Creatures.xml
│   └── Items.xml
│  └── Items.xml
├── preview.png
├── preview.png
└── Textures
└── Textures
Line 488: Line 469:
=== Using existing items as a template ===
=== Using existing items as a template ===


Now, we know that we want these items to function like a {{favilink|flamethrower}} and {{favilink|freeze ray}}, but we probably need to iron out some more details first. For instance: should our new missile weapons use ammo? Or energy cells?
Now, we know that we want these items to function like a {{favilink|flamethrower}} and {{favilink|freeze ray}}, but we probably need to iron out some more details first.


{| style = "margin: 1em;font-family:Source Code Pro;"
{| style = "margin: 1em;font-family:Source Code Pro;"
Line 496: Line 477:
|}
|}


I have no clue, but I'm going to go with the assumption that they don't. Instead, let's set up our tomes of fire and ice so that they have a ten-turn cooldown between uses.
That's a good question. If we wanted, we could set up our new missile weapons to use some kind of ammo, or pull from an energy cell. I'm actually going to go with a third option -- let's set up our tomes of fire and ice so that they don't use any kind of ammo or energy, but instead just have a plain 10-turn cooldown.


The other thing that we have to figure out is what kind of projectile each of these items shoots out. Let's take a look at how the game defines the flamethrower and freeze ray objects. Looking at the [[file locations]], navigate in your file browser to where the game's data files are stored. Once you're in that folder, go to <code>ObjectBlueprints/</code> and open up the <code>Items.xml</code> file. Then search for <code>Flamethrower</code> and <code>Freeze Ray</code>; you should find the following XML for each of them.
We must also figure out what kind of projectile each of these items shoots. Let's take a look at how the game defines the flamethrower and freeze ray objects. Looking at the [[file locations]], navigate in your file browser to where the game's data files are stored. Once you're in that folder, go to <code>ObjectBlueprints/</code> and open up the <code>Items.xml</code> file. Then search for <code>Flamethrower</code> and <code>Freeze Ray</code>; you should find the following XML for each of them.


<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
Line 588: Line 569:
     <part Name="Render" DisplayName="tome of {{R|fire}}" Tile="Items/sw_book_1.bmp" ColorString="&amp;R" DetailColor="Y" />
     <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="MissileWeapon" AmmoChar="f" ShotsPerAction="1" AmmoPerAction="1" ShotsPerAnimation="1" WeaponAccuracy="0" />
     <part Name="CooldownAmmoLoader" Cooldown="10" Readout="true" ProjectileObject="FlamethrowerProjectile" />
     <part Name="CooldownAmmoLoader" Cooldown="10" Readout="true" ProjectileObject="ProjectileFlamethrower" />


     <tag Name="MissileFireSound" Value="flamethrower" />
     <tag Name="MissileFireSound" Value="flamethrower" />
Line 596: Line 577:
     <part Name="Render" DisplayName="tome of {{C|ice}}" Tile="Items/sw_book_1.bmp" ColorString="&amp;C" DetailColor="Y" />
     <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="MissileWeapon" AmmoChar="FR" ShotsPerAction="1" AmmoPerAction="1" ShotsPerAnimation="1" WeaponAccuracy="0" />
     <part Name="CooldownAmmoLoader" Cooldown="10" Readout="true" ProjectileObject="FreezeRayProjectile" />
     <part Name="CooldownAmmoLoader" Cooldown="10" Readout="true" ProjectileObject="ProjectileFreezeRay" />


     <tag Name="MissileFireSound" Value="hiss_low" />
     <tag Name="MissileFireSound" Value="hiss_low" />
Line 612: Line 593:
| style = "border:1px solid #155352;padding:0.5em 1em;" | I burnt down all of Joppa with my tome of fire! Take that, Ualraig.
| style = "border:1px solid #155352;padding:0.5em 1em;" | I burnt down all of Joppa with my tome of fire! Take that, Ualraig.
|}
|}
Ah, hm, yeah, maybe using the same projectile that {{favilink|flamethrower}} and {{favilink|freeze ray}} use isn't the greatest idea. Those are both mid- to late-game items, and we want our new snapjaws to be early-game enemies.
Let's fix that by creating some new projectile types that operate in the same way as <code>ProjectileFlamethrower</code> and <code>FreezeRayProjectile</code>, but are a little bit weaker. First, let's look up how these projectiles are defined in the game's data files, and then copy that over to our <code>Items.xml</code>. We'll rename these projectiles <code>Pyovya_SnapjawMage_FireTomeProjectile</code> and <code>Pyovya_SnapjawMage_IceTomeProjectile</code>.
<syntaxhighlight lang="xml">
<!-- Copied from ProjectileFlamethrower -->
<object Name="Pyovya_SnapjawMage_FireTomeProjectile" Inherits="TemporaryProjectile">
  <part Name="Render" DisplayName="{{R|stream of flame}}" ColorString="&amp;R" />
  <part Name="Projectile" BasePenetration="15" BaseDamage="1d2" Attributes="Heat Fire" ColorString="&amp;R" PassByVerb="whoosh" />
  <part Name="TemperatureOnHit" Amount="4d20" Max="false" OnWielderHit="true" />
  <part Name="TemperatureOnEntering" Amount="8d20" Max="false" OnWielderHit="true" />
</object>
<!-- Copied from ProjectileFreezeRay -->
<object Name="Pyovya_SnapjawMage_IceTomeProjectile" Inherits="TemporaryProjectile">
  <part Name="Render" DisplayName="{{C|energy beam}}" ColorString="&amp;B" />
  <part Name="Projectile" BaseDamage="1d4" Attributes="Cold NonPenetrating" ColorString="&amp;B" PassByVerb="crackle" />
  <part Name="TemperatureOnHit" Amount="-190" Max="false" OnWielderHit="true" />
  <part Name="TemperatureOnEntering" Amount="-190" Max="false" OnWielderHit="true" />
</object>
</syntaxhighlight>
Let's make some changes to the penetration, base damage, and temperature changes of each of these items. Here's what I set mine to, but go ahead and try tweaking these numbers to different values:
<syntaxhighlight lang="xml">
<object Name="Pyovya_SnapjawMage_ProjectileFireTome" Inherits="TemporaryProjectile">
  <part Name="Render" DisplayName="{{R|stream of flame}}" ColorString="&amp;R" />
  <part Name="Projectile" BasePenetration="4" BaseDamage="1d4" Attributes="Heat Fire" ColorString="&amp;R" PassByVerb="whoosh" />
  <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">
  <part Name="Render" DisplayName="{{C|streak of ice}}" ColorString="&amp;B" />
  <part Name="Projectile" BasePenetration="4" BaseDamage="1d4" Attributes="Cold" ColorString="&amp;B" PassByVerb="crackle" />
  <part Name="TemperatureOnHit" Amount="-4d20" Max="false" OnWielderHit="true" />
  <part Name="TemperatureOnEntering" Amount="-8d20" Max="false" OnWielderHit="true" />
</object>
</syntaxhighlight>
Now you can change the <code>CooldownAmmoLoader</code> part of your {{qud text|&Ytome of &Rfire}} and {{qud text|&Ytome of &Cice}} objects to use this new projectile.


=== Wrapping up ===
=== Wrapping up ===
We can't forget to give our mages their new weapons! Go back to <code>Creatures.xml</code>, and add the following XML tag to <code>Pyovya_SnapjawMage_Fire Mage</code>:
<syntaxhighlight lang="xml">
<inventoryobject Blueprint="Pyovya_SnapjawMage_Fire Tome" Number="1" />
</syntaxhighlight>
You should also add the {{qud chat|tome of &Cice}} to the <code>Pyovya_SnapjawMage_Fire Mage's</code> inventory:
<syntaxhighlight lang="xml">
<inventoryobject Blueprint="Pyovya_SnapjawMage_Ice Tome" Number="1" />
</syntaxhighlight>


== Going forward ==
== Going forward ==
Line 630: Line 665:
| style = "border:1px solid #155352;padding:0.5em 1em;" | I'm ready to go face these mages in magical combat.
| 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:
<syntaxhighlight lang="xml">
SnapjawMage
├── manifest.json
├── ObjectBlueprints
│   ├── Creatures.xml
│   └── Items.xml
├── preview.png
└── Textures
    └── Pyovya_SnapjawMage
        └── snapjaw_mage.png
</syntaxhighlight>
Here's what my <code>Creatures.xml</code> contained:
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="utf-8" ?>
<objects>
  <object Name="Pyovya_SnapjawMage_Snapjaw Mage" Inherits="Snapjaw">
    <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." />
    <part Name="Render" DisplayName="snapjaw mage" Tile="Pyovya_SnapjawMage/snapjaw_mage.png" ColorString="&amp;O" DetailColor="Y" />
    <inventoryobject Blueprint="Walking Stick" Number="1" />
    <inventoryobject Blueprint="Woven Tunic" Number="1" />
    <inventoryobject Blueprint="Sandals" Number="1" />
    <inventoryobject Blueprint="StandaloneMarkovBook" Number="1-2" Chance="10" />
    <skill Name="Cudgel" />
    <stat Name="Hitpoints" Value="15" />
    <stat Name="DV" Value="4" />
    <stat Name="Ego" Value="17" />
    <stat Name="Willpower" Value="17" />
    <tag Name="BaseObject" Value="*noinherit" />
  </object>
  <object Name="Pyovya_SnapjawMage_Fire Mage" Inherits="Pyovya_SnapjawMage_Snapjaw Mage">
    <part Name="Render" DisplayName="snapjaw mage of {{R|fire}}" 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">
    <part Name="Render" DisplayName="snapjaw mage of {{C|ice}}" 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">
<?xml version="1.0" encoding="utf-8" ?>
<objects>
  <!-- Weapons -->
  <object Name="Pyovya_SnapjawMage_Magic Tome" Inherits="BaseMissileWeapon">
    <!-- We borrow the same description that StandaloneMarkovBook uses -->
    <part Name="Description" Short="Crip pages of goatskin vellum are bound into a codex." />
    <part Name="Physics" Weight="1" UsesTwoSlots="true" />
    <part Name="Commerce" Value="80" />
    <tag Name="Tier" Value="2" />
    <tag Name="Mods" Value="" />
    <tag Name="BaseObject" Value="*noinherit" />
  </object>
  <object Name="Pyovya_SnapjawMage_Fire Tome" Inherits="Pyovya_SnapjawMage_Magic Tome">
    <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" />
  </object>
  <object Name="Pyovya_SnapjawMage_Ice Tome" Inherits="Pyovya_SnapjawMage_Magic Tome">
    <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" />
  </object>
  <!-- Projectiles -->
  <object Name="Pyovya_SnapjawMage_ProjectileFireTome" Inherits="TemporaryProjectile">
    <part Name="Render" DisplayName="{{R|stream of flame}}" ColorString="&amp;R" />
    <part Name="Projectile" BasePenetration="4" BaseDamage="1d4" Attributes="Heat Fire" ColorString="&amp;R" PassByVerb="whoosh" />
    <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">
    <part Name="Render" DisplayName="{{C|streak of ice}}" ColorString="&amp;B" />
    <part Name="Projectile" BasePenetration="4" BaseDamage="1d4" Attributes="Cold" ColorString="&amp;B" PassByVerb="crackle" />
    <part Name="TemperatureOnHit" Amount="-4d20" Max="false" OnWielderHit="true" />
    <part Name="TemperatureOnEntering" Amount="-8d20" Max="false" OnWielderHit="true" />
  </object>
</objects>
</syntaxhighlight>


=== Extra challenge ===
=== Extra challenge ===
Line 638: Line 775:
* When you're creating your {{qud text|&Ytome of &Welectricity}}, start by having it shoot <code>ProjectileElectroPistol</code>; this is the projectile that is shot by an {{favilink|arc winder}}. Once you're ready, create your own version of this projectile by referring to how <code>ProjectileElectroPistol</code> is implemented in the game's version of <code>ObjectBlueprints/Items.xml</code>.
* When you're creating your {{qud text|&Ytome of &Welectricity}}, start by having it shoot <code>ProjectileElectroPistol</code>; this is the projectile that is shot by an {{favilink|arc winder}}. Once you're ready, create your own version of this projectile by referring to how <code>ProjectileElectroPistol</code> is implemented in the game's version of <code>ObjectBlueprints/Items.xml</code>.


=== Learning from the game's data files ===
=== Next steps ===


{| style = "margin: 1em;font-family:Source Code Pro;"
{| style = "margin: 1em;font-family:Source Code Pro;"
Line 645: Line 782:
| style = "border:1px solid #155352;padding:0.5em 1em;" | What should I do if I want to start designing my own creatures?
| style = "border:1px solid #155352;padding:0.5em 1em;" | What should I do if I want to start designing my own creatures?
|}
|}
TODO
== Scratchpad ==
Lingering notes that will be removed before the final version:
* How much should we discuss population tables beyond the <code>DynamicObjectsTable</code> tag? Should we write some more in an appendix?


[[Category:Guides]]
[[Category:Guides]]