RPG Library: Getting started - ThePix/QuestJS GitHub Wiki

Let us create a simple RPG, to see what can be done and how. I would advise you first to go though the basic tutorial, so you have some familiarity with Quest 6. However, you must read the first page, which describes how to set up the files.

https://github.com/ThePix/QuestJS/wiki/Tutorial-1:-First-steps

So now you have a settings.js file, you can add this line, which will tell Quest to include the RPG library file.

settings.customLibraries.push({
  folder:'rpg', 
  files:[
    "lang-en", "rpg", "skill", "attack", "item_templates",
    "npc_templates", "commands", "spells", "weapons", "agenda",
  ],
})

Now go to the data.js file. We need to change the player because there are all sorts of extra bits required for a player in an RPG, so we have to use the RPG_PLAYER template rather than PLAYER. The player needs to look something like this:

createItem("me", RPG_PLAYER(), {
  loc:"lounge",
  regex:/^(me|myself|player)$/,
  health:100,
  offensiveBonus_spell:5,
  offensiveBonus:3,
  defensiveBonus:1,
  examine:'Just some guy.',
})

Quest will give the player a "maxHealth" equal to the original health. It will use "offensiveBonus_spell", and "offensiveBonus" to determine skills at casting spells and at combat in general, while "defensiveBonus" is how easily the player dodges.

Let us give the player a weapon, shield and some armour. The WEAPON template needs to be given the damage the weapon does as a parameter, in standard RPG format, while the SHIELD template needs a number, the bonus it gives to the "defensiveBonus" attribute. Armour is just any WEARABLE item with an "armour" attribute.

Armour in QuestJS serves to reduce damage. The armour for all items worn is totalled, then divided by settings.armourScaling, which defaults to 10. This is multiplied by the number of dice in the attack roll (minimum of one), and this is deducted from the damage (again, minimum of one). For example, if the armour is 2, for a weapon that does d8+2, it will reduce damage by 2; for a weapon doing 3d6 the armour will reduce damage by 6. This means some weapons are good against armoured foes, others good against unarmoured.

createItem("knife", WEAPON("d4+2"), {
  loc:"me",
})

createItem("target shield", SHIELD(2), {
  loc:"me",
})

createItem("helmet", WEARABLE(2, ['head']), {
  loc:"me",
  armour:10,
})

The player must EQUIP a weapon or shield to get any benefit from using it, and must WEAR armour.

Monsters

Now we need something to fight. We need to use the RPG_NPC template, or one derived from it, which is based on the standard RPG_TEMPLATE that RPG_PLAYER uses, but extends it somewhat. It takes a Boolean as a parameter; true if female.

createItem("goblin", RPG_NPC(false), {
  loc:"lounge",
  damage:"d8",
  health:40,
  ex:"A rather small green humanoid; hairless and dressed in rags.",
})

Note that the description should be added with the "ex" attribute, rather than "examine" - the template has a built-in "examine", that will use "ex", but add some extra information.

RPG_NPCs can either use weapons or can be considered weapons themselves - generally the latter is easier. This RPG_NPC therefore has a "damage" attribute set as well as health.

By default, RPG_NPCs are automatically hostile, but you can add an "isHostile" function to modify that. This example simply returns false, unless the player has a flag, "hasStolenCarrot" set to true. Note that they only attack if they have a target too.

createItem("rabbit", RPG_NPC(false), {
  loc:"lounge",
  damage:"2d4",
  health:20,
  isHostile:function() { return player.hasStolenCarrot },
})

The player can ATTACK an RPG_NPC.

Attacks

Before we get to spells it is worth discussing what an attack actually does. When a character makes an attack, an Attack object is created, with certain attributes, depending on the attack - specifically, the attacker, the primary target and the skill/weapon/spell used. The Attack object is passed around allowing various things to modify it. For example, if the attack was generated by a spell or skill, then that gets the first opportunity to modify the attack, then the attacker has a go; perhaps the character has a great skill at this attack, that would be applied at this point.

The Attack object will then be cloned, with a clone assigned to each target. Now the target gets the chance to modify the attack; perhaps the target has a special protection to this type of attack. Finally the attack is actually resolved, and damage applied if applicable.

The details are discussed more here.

Spells and Skills

Spells are stored in SPELLBOOKs. Well, actually only the name is stored there, the spell itself is elsewhere. The SPELLBOOK template should, therefore, be given a list of spells as a parameter.

createItem("spellbook", SPELLBOOK(["Fireball", "Stoneskin", "Steelskin", "Lightning bolt", "Ice shard"]), {
  loc:"lounge",
});

So now we need some spells. This is rather more complicated, because there is so much a spell can potentially do and details are given elsewhere. QuestJS gives you a bunch of built-in spells, in the file rpg/spells.js, so we can just use them.

No need to limit flashy moves to wizards, you can give fighters special skills too. They behave very much like spells, so see the previous link.

So now you should be able to go into the game and kill that goblin with the dagger or learn a spell and use that.