Creating Dwarf-oriented RPG

Hi all!

In this topic I will post my progress at making dwarf-RPG, which is means that it setting lies in underground world. Also, I probably will be asking for help here, because I'm started using Quest not so long ago, and not yet learned this engine properly.

Current progress:

  1. Monsters
    a) Health, max health
    b) Attack
    c) Random descriptions of monsters and their attacks
    d) Attacks with preparation
    e) Loot

  2. Character
    a) Health, max health
    b) Energy, max energy
    c) Attack
    d) Money
    e) Full status command
    f) Сharacteristics - strength, agility, intelligence, vitality, armour
    g) Armor
    h) Jewelry
    i) Shields
    j) Inventory size

  3. Items
    a) Melee weapons
    b) Ranged weapons
    c) Magic weapons
    d) Food, potions

  4. Locations
    a) Safe zones
    b) Chests
    c) Fast travels

Not yet made:

  1. Several turns buffs from food and potions
  2. Shops
  3. Level system
  4. Quests
  5. Illustration of combat
  6. Monster respawn after some time
  7. Bank
  8. Loss of % of money after death and resurrection in nearest town
  9. NPC
  10. Bosses
  11. Interrupting attacks with preparation
  12. Music and ambience in locations

Optionally:

  1. Crafting system
  2. Farming system
  3. Several savefiles
  4. Sound accompaniment of combat

Just looking at the code you posted, it seems that the DoAttack function is missing a parameter.
I'd guess the 4th parameter is named "firearm".

You'll need to go to the DoAttack function and add another parameter at the bottom of the list.


Thank you! It worked!


It seems that I again messed something. Pistol is shooting, but the bullets count do not lowering. Would appreciate any help!

Code:

<!--Saved by Quest 5.7.6606.27193-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="11">
    <gameid>7b6e3407-e81b-4f7b-b470-6c3a3f9f5b45</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <feature_advancedscripts />
    <unresolvedcommandhandler type="script">
      msg ("Er, what..?")
      game.notarealturn = true
    </unresolvedcommandhandler>
    <start type="script">
      // List of attackers
      player.attackers = NewObjectList()
      player.ammo = 35
      // Status attributes
      WeaponUpdate
      player.statusattributes = NewStringDictionary()
      dictionary add (player.statusattributes, "hitpoints", "Hit points: !")
      dictionary add (player.statusattributes, "ammo", "Spare ammo: !")
      dictionary add (player.statusattributes, "equippedname", "Weapon: !")
      dictionary add (player.statusattributes, "ammonote", "Ammo: !")
    </start>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <beforefirstenter type="script">
      SpawnZombie (this)
      SpawnZombie (this)
    </beforefirstenter>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
      <feature_startscript />
      <attr name="_initialise_" type="script"><![CDATA[
        player.alias = "you"
        player.hitpoints = 250
        player.damage = 3
        player.attack = 0
        player.defence = 0
        player.armour = 0
        player.changedhitpoints => {
          if (player.hitpoints > 0) {
            msg ("Hits points now " + player.hitpoints)
          }
          else {
            msg ("You are dead!")
            finish
          }
        }
      ]]></attr>
    </object>
    <object name="spade">
      <inherit name="editor_object" />
      <listalias>spade</listalias>
      <inventoryverbs type="stringlist">
        <value>Look at</value>
        <value>equip</value>
        <value>Drop</value>
      </inventoryverbs>
      <feature_startscript />
      <take />
      <attr name="_initialise_" type="script">
        this.damage = "1d6"
        this.attack = 3
      </attr>
    </object>
    <object name="pistol">
      <inherit name="editor_object" />
      <listalias>pistol</listalias>
      <inventoryverbs type="stringlist">
        <value>Look at</value>
        <value>equip</value>
        <value>Drop</value>
        <value>reload</value>
      </inventoryverbs>
      <feature_startscript />
      <take />
      <look>Good for shooting zombies. Ammo: {pistol.ammo}/{pistol.ammomax}</look>
      <attr name="_initialise_" type="script">
        this.damage = "2"
        this.attack = 0
        this.firearmdamage = "2d8"
        this.firearmattack = 3
        this.ammo = 3
        this.ammomax = 6
      </attr>
      <ontake type="script">
      </ontake>
    </object>
  </object>
  <command>
    <pattern>attack #object#</pattern>
    <script>
      if (not HasBoolean(object, "dead")) {
        msg ("That's not something you can attack.")
      }
      else if (object.dead) {
        msg ("That one is already dead.")
      }
      else {
        if (player.equipped = null) {
          DoAttack (player, player, object, false)
        }
        else {
          DoAttack (player, player.equipped, object, false)
        }
      }
    </script>
  </command>
  <command>
    <pattern>equip #object#</pattern>
    <script>
      if (HasBoolean(object, "dead")) {
        msg ("That's not something you can wield.")
      }
      else if (not HasAttribute(object, "damage")) {
        msg ("That's not something you can wield.")
      }
      else if (not object.parent = player) {
        msg ("You are not carrying it.")
      }
      else if (object = player.equipped) {
        msg ("You already have.")
      }
      else {
        if (player.equipped = null) {
          msg ("You equip your " + GetDisplayAlias(object) + ".")
        }
        else {
          msg ("You put away your " + GetDisplayAlias(player.equipped) + " and equip your " + GetDisplayAlias(object) + ".")
          list add (player.equipped.inventoryverbs, "Equip")
          list remove (player.equipped.inventoryverbs, "Unequip")
          player.equipped.listalias = Replace(player.equipped.listalias, " (equipped)", "")
        }
        player.equipped = object
        list add (object.inventoryverbs, "Unequip")
        list remove (object.inventoryverbs, "Equip")
        object.listalias = object.listalias + " (equipped)"
        WeaponUpdate
      }
    </script>
  </command>
  <command>
    <pattern>unequip #object#</pattern>
    <script>
      if (not object = player.equipped) {
        msg ("You are not wielding it.")
      }
      else {
        msg ("You put away your spade.")
        player.equipped = null
        list add (object.inventoryverbs, "Equip")
        list remove (object.inventoryverbs, "Unequip")
        object.listalias = Replace(object.listalias, " (equipped)", "")
        WeaponUpdate
      }
    </script>
  </command>
  <turnscript name="attackturnscript">
    <enabled />
    <script>
      if (not GetBoolean(game, "notarealturn")) {
        list = NewObjectList()
        foreach (obj, GetDirectChildren(player.parent)) {
          if (HasBoolean(obj, "dead")) {
            if (not obj.dead) {
              DoAttack (obj, obj, player, false)
              list add (list, obj)
            }
          }
        }
        foreach (obj, ListExclude(player.attackers, list)) {
          if (not obj.dead and RandomChance(80)) {
            obj.parent = player.parent
            msg (CapFirst(obj.alias) + " shambles into the area.")
            list add (list, obj)
          }
        }
        player.attackers = list
      }
      game.notarealturn = false
    </script>
  </turnscript>
  <command>
    <pattern>shoot #object#</pattern>
    <script><![CDATA[
      if (not HasBoolean(object, "dead")) {
        msg ("That's not something you need to shoot.")
      }
      else if (object.dead) {
        msg ("That one is already dead.")
      }
      else if (player.equipped = null) {
        msg ("You don't have a firearm equipped.")
      }
      else if (not HasInt(player.equipped, "ammo")) {
        msg ("You can't shoot a " + GetDisplayAlias(player.equipped) + ".")
      }
      else if (not player.equipped.ammo > 0) {
        msg ("You aim your " + GetDisplayAlias(player.equipped) + " and pull the trigger. Click. No ammo loaded.")
      }
      else {
        DoAttack (player, player.equipped, object, false)
        WeaponUpdate
      }
    ]]></script>
  </command>
  <command>
    <pattern>reload #object#</pattern>
    <script><![CDATA[
      if (not HasInt(object, "ammo")) {
        msg ("You can't reload a " + GetDisplayAlias(player.equipped) + ".")
      }
      else if (player.ammo < 1) {
        msg ("You have no ammo.")
      }
      else {
        bullets = object.ammomax - object.ammo
        if (bullets > player.ammo) {
          bullets = player.ammo
        }
        player.ammo = player.ammo - bullets
        object.ammo = object.ammo + bullets
        msg ("You put " + bullets + " bullets in it.")
        WeaponUpdate
      }
    ]]></script>
  </command>
  <function name="SpawnZombie" parameters="room"><![CDATA[
    if (HasInt(game, "crittercount")) {
      game.crittercount = game.crittercount + 1
    }
    else {
      game.crittercount = 1
    }
    create ("critter" + game.crittercount)
    obj = GetObject("critter" + game.crittercount)
    obj.parent = room
    obj.displayverbs = Split("Look at;Attack;Shoot", ";")
    obj.dead = false
    obj.changedhitpoints => {
      if (this.hitpoints < 1) {
        msg ("It is dead!")
        this.dead = true
      }
    }
    names = Split("decipit;decomposing;shambling;disgusting;filthy;falling-apart", ";")
    obj.alias = StringListItem(names, game.crittercount % ListCount(names)) + " zombie"
    obj.listalias = CapFirst(obj.alias)
    obj.look = ProcessText("A " + obj.alias + ", {random:covered in maggots:missing an arm:one eye hanging out}.")
    obj.hitpoints = 10
    obj.damage = 1
    obj.attack = 0
    obj.defence = 0
    obj.armour = 0
  ]]></function>
  <function name="DoAttack" parameters="attacker, weapon, target, firearm"><![CDATA[
    if (firearm) {
      damageatt = "firearmdamage"
      attackatt = "firearmattack"
      weapon.ammo = weapon.ammo - 1
    }
    else {
      damageatt = "damage"
      attackatt = "attack"
    }
    roll = GetRandomInt(1, 20) + weapon.attack - target.defence
    damage = DiceRoll(weapon.damage) * (100 - target.armour) / 100
    if (damage < 1) {
      damage = 1
    }
    if (roll > 15) {
      damage = damage * 3
      msg (CapFirst(attacker.alias) + " attacks " + target.alias + " and gets a critical (" + damage + " hits)!")
      target.hitpoints = target.hitpoints - damage
    }
    else if (roll > 10) {
      msg (CapFirst(attacker.alias) + " attacks " + target.alias + " and hit (" + damage + " hits).")
      target.hitpoints = target.hitpoints - damage
    }
    else {
      msg (CapFirst(attacker.alias) + " attacks " + target.alias + " and misses...")
      WeaponUpdate
    }
  ]]></function>
  <function name="WeaponUpdate">
    if (player.equipped = null) {
      player.equippedname = "-"
      player.ammonote = "-"
    }
    else {
      player.equippedname = Replace (player.equipped.listalias, " (equipped)", "")
      if (not HasAttribute(player.equipped, "ammo")) {
        player.ammonote = "-"
      }
      else {
        player.ammonote = player.equipped.ammo + "/" + player.equipped.ammomax
      }
    }
  </function>
</asl>


In the shoot command, you have the line:

  • DoAttack (player, player.equipped, object, false)

The last parameter "firearm" tells the DoAttack command whether you want to fire the pistol, or hit the zombie with it. So in the "shoot" command, you want to change that "false" to "true"


Actaully it is false. Or that's how The Pixie set it up.


Thank you, Mrangel, it worked!


Okay, moving on individual attack descriptions... It seems what Quest need descriptions for attack without any weapon and because it lacks these descriptions it shows error, when I try to hit zombie without weapon. But this part of tutorial is missing in Pixie's tutorial, that's strange.

Error:

Error running script: Error compiling expression 'Replace(s, "#Attacker#", CapFirst(GetDisplayAlias(attacker)))': FunctionCallElement: Could find not function 'Replace(Object; String; String)'

I tried to add "this.critdesc", "this.attackdesc" and "this.missdesc" to player's initialisation script, but this didint done anything. How should I do to add these descriptions? Would appreciate any help!

Code:

<!--Saved by Quest 5.7.6606.27193-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="11">
    <gameid>7b6e3407-e81b-4f7b-b470-6c3a3f9f5b45</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <feature_advancedscripts />
    <unresolvedcommandhandler type="script">
      msg ("Er, what..?")
      game.notarealturn = true
    </unresolvedcommandhandler>
    <start type="script">
      // List of attackers
      player.attackers = NewObjectList()
      player.ammo = 35
      // Status attributes
      WeaponUpdate
      player.statusattributes = NewStringDictionary()
      dictionary add (player.statusattributes, "hitpoints", "Hit points: !")
      dictionary add (player.statusattributes, "ammo", "Spare ammo: !")
      dictionary add (player.statusattributes, "equippedname", "Weapon: !")
      dictionary add (player.statusattributes, "ammonote", "Ammo: !")
    </start>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <beforefirstenter type="script">
      SpawnZombie (this)
      SpawnZombie (this)
    </beforefirstenter>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
      <feature_startscript />
      <attr name="_initialise_" type="script"><![CDATA[
        player.alias = "you"
        player.hitpoints = 250
        player.damage = 0
        player.attack = 3
        player.defence = 0
        player.armour = 0
        player.changedhitpoints => {
          if (player.hitpoints > 0) {
            msg ("Hits points now " + player.hitpoints)
          }
          else {
            msg ("You are dead!")
            finish
          }
        }
      ]]></attr>
    </object>
    <object name="spade">
      <inherit name="editor_object" />
      <listalias>spade</listalias>
      <inventoryverbs type="stringlist">
        <value>Look at</value>
        <value>equip</value>
        <value>Drop</value>
      </inventoryverbs>
      <feature_startscript />
      <take />
      <attr name="_initialise_" type="script">
        this.damage = "1d6"
        this.attack = 3
        this.critdesc = "You smash the spade down on #target# (#hits# hits)."
        this.attackdesc = "You swing the spade at #target# (#hits# hits)."
        this.missdesc = "You swing wildly and entirely miss #target#."
      </attr>
    </object>
    <object name="pistol">
      <inherit name="editor_object" />
      <listalias>pistol</listalias>
      <inventoryverbs type="stringlist">
        <value>Look at</value>
        <value>equip</value>
        <value>Drop</value>
        <value>reload</value>
      </inventoryverbs>
      <feature_startscript />
      <take />
      <look>Good for shooting zombies. Ammo: {pistol.ammo}/{pistol.ammomax}</look>
      <attr name="_initialise_" type="script">
        this.damage = "2"
        this.attack = 0
        this.firearmdamage = "2d8"
        this.firearmattack = 3
        this.ammo = 3
        this.ammomax = 6
        this.critdesc = "A well placed shot with the pistol on #target# (#hits# hits)."
        this.attackdesc = "You shot the pistol at #target# (#hits# hits)."
        this.missdesc = "You shoot wildly and entirely miss #target#."
      </attr>
      <ontake type="script">
      </ontake>
    </object>
  </object>
  <command>
    <pattern>attack #object#</pattern>
    <script>
      if (not HasBoolean(object, "dead")) {
        msg ("That's not something you can attack.")
      }
      else if (object.dead) {
        msg ("That one is already dead.")
      }
      else {
        if (player.equipped = null) {
          DoAttack (player, player, object, false)
        }
        else {
          DoAttack (player, player.equipped, object, false)
        }
      }
    </script>
  </command>
  <command>
    <pattern>equip #object#</pattern>
    <script>
      if (HasBoolean(object, "dead")) {
        msg ("That's not something you can wield.")
      }
      else if (not HasAttribute(object, "damage")) {
        msg ("That's not something you can wield.")
      }
      else if (not object.parent = player) {
        msg ("You are not carrying it.")
      }
      else if (object = player.equipped) {
        msg ("You already have.")
      }
      else {
        if (player.equipped = null) {
          msg ("You equip your " + GetDisplayAlias(object) + ".")
        }
        else {
          msg ("You put away your " + GetDisplayAlias(player.equipped) + " and equip your " + GetDisplayAlias(object) + ".")
          list add (player.equipped.inventoryverbs, "Equip")
          list remove (player.equipped.inventoryverbs, "Unequip")
          player.equipped.listalias = Replace(player.equipped.listalias, " (equipped)", "")
        }
        player.equipped = object
        list add (object.inventoryverbs, "Unequip")
        list remove (object.inventoryverbs, "Equip")
        object.listalias = object.listalias + " (equipped)"
        WeaponUpdate
      }
    </script>
  </command>
  <command>
    <pattern>unequip #object#</pattern>
    <script>
      if (not object = player.equipped) {
        msg ("You are not wielding it.")
      }
      else {
        msg ("You put away your spade.")
        player.equipped = null
        list add (object.inventoryverbs, "Equip")
        list remove (object.inventoryverbs, "Unequip")
        object.listalias = Replace(object.listalias, " (equipped)", "")
        WeaponUpdate
      }
    </script>
  </command>
  <turnscript name="attackturnscript">
    <enabled />
    <script>
      if (not GetBoolean(game, "notarealturn")) {
        list = NewObjectList()
        foreach (obj, GetDirectChildren(player.parent)) {
          if (HasBoolean(obj, "dead")) {
            if (not obj.dead) {
              DoAttack (obj, obj, player, false)
              list add (list, obj)
            }
          }
        }
        foreach (obj, ListExclude(player.attackers, list)) {
          if (not obj.dead and RandomChance(80)) {
            obj.parent = player.parent
            msg (CapFirst(obj.alias) + " shambles into the area.")
            list add (list, obj)
          }
        }
        player.attackers = list
      }
      game.notarealturn = false
    </script>
  </turnscript>
  <command>
    <pattern>shoot #object#</pattern>
    <script><![CDATA[
      if (not HasBoolean(object, "dead")) {
        msg ("That's not something you need to shoot.")
      }
      else if (object.dead) {
        msg ("That one is already dead.")
      }
      else if (player.equipped = null) {
        msg ("You don't have a firearm equipped.")
      }
      else if (not HasInt(player.equipped, "ammo")) {
        msg ("You can't shoot a " + GetDisplayAlias(player.equipped) + ".")
      }
      else if (not player.equipped.ammo > 0) {
        msg ("You aim your " + GetDisplayAlias(player.equipped) + " and pull the trigger. Click. No ammo loaded.")
      }
      else {
        DoAttack (player, player.equipped, object, true)
        WeaponUpdate
      }
    ]]></script>
  </command>
  <command>
    <pattern>reload #object#</pattern>
    <script><![CDATA[
      if (not HasInt(object, "ammo")) {
        msg ("You can't reload a " + GetDisplayAlias(player.equipped) + ".")
      }
      else if (player.ammo < 1) {
        msg ("You have no ammo.")
      }
      else {
        bullets = object.ammomax - object.ammo
        if (bullets > player.ammo) {
          bullets = player.ammo
        }
        player.ammo = player.ammo - bullets
        object.ammo = object.ammo + bullets
        msg ("You put " + bullets + " bullets in it.")
        WeaponUpdate
      }
    ]]></script>
  </command>
  <function name="SpawnZombie" parameters="room"><![CDATA[
    if (HasInt(game, "crittercount")) {
      game.crittercount = game.crittercount + 1
    }
    else {
      game.crittercount = 1
    }
    create ("critter" + game.crittercount)
    obj = GetObject("critter" + game.crittercount)
    obj.parent = room
    obj.displayverbs = Split("Look at;Attack;Shoot", ";")
    obj.dead = false
    obj.changedhitpoints => {
      if (this.hitpoints < 1) {
        msg ("It is dead!")
        this.dead = true
      }
    }
    names = Split("decipit;decomposing;shambling;disgusting;filthy;falling-apart", ";")
    obj.alias = StringListItem(names, game.crittercount % ListCount(names)) + " zombie"
    obj.listalias = CapFirst(obj.alias)
    obj.look = ProcessText("A " + obj.alias + ", {random:covered in maggots:missing an arm:one eye hanging out}.")
    obj.hitpoints = 10
    obj.damage = 1
    obj.attack = 0
    obj.defence = 0
    obj.armour = 0
    obj.critdesc = "A well-placed blow by #attacker# sends you reeling (#hits# hits)."
    obj.attackdesc = "#Attacker# has hit you (#hits# hits)."
    obj.missdesc = "#Attacker# misses you."
  ]]></function>
  <function name="DoAttack" parameters="attacker, weapon, target, firearm"><![CDATA[
    if (firearm) {
      damageatt = "firearmdamage"
      attackatt = "firearmattack"
      weapon.ammo = weapon.ammo - 1
    }
    else {
      damageatt = "damage"
      attackatt = "attack"
    }
    roll = GetRandomInt(1, 20) + weapon.attack - target.defence
    damage = DiceRoll(weapon.damage) * (100 - target.armour) / 100
    if (damage < 1) {
      damage = 1
    }
    if (roll > 15) {
      damage = damage * 3
      AttackReport (weapon.critdesc, attacker, target, damage)
      target.hitpoints = target.hitpoints - damage
    }
    else if (roll > 10) {
      AttackReport (weapon.attackdesc, attacker, target, damage)
      target.hitpoints = target.hitpoints - damage
    }
    else {
      AttackReport (weapon.missdesc, attacker, target, 0)
    }
  ]]></function>
  <function name="WeaponUpdate">
    if (player.equipped = null) {
      player.equippedname = "-"
      player.ammonote = "-"
    }
    else {
      player.equippedname = Replace (player.equipped.listalias, " (equipped)", "")
      if (not HasAttribute(player.equipped, "ammo")) {
        player.ammonote = "-"
      }
      else {
        player.ammonote = player.equipped.ammo + "/" + player.equipped.ammomax
      }
    }
  </function>
  <function name="AttackReport" parameters="s, attacker, target, hits">
    s = Replace(s, "#Attacker#", CapFirst(GetDisplayAlias(attacker)))
    s = Replace(s, "#attacker#", GetDisplayAlias(attacker))
    s = Replace(s, "#Target#", CapFirst(GetDisplayAlias(target)))
    s = Replace(s, "#target#", GetDisplayAlias(target))
    s = Replace(s, "#hits#", "" + hits)
    msg (s)
  </function>
</asl>

You'll have to add something like this:

player.critdesc = "You attack #target# with your bare hands and get a critical (#hits# hits)."
player.attackdesc = "You attack #target# with your bare hands and hit (#hits# hits)."
player.missdesc = "You swing wildly and entirely miss #target#."

Adding a this.critdesc thing works too. I just think it's easier this way.


personally, you should have an 'unarmed' (as your no weapon) Object, just like you'd have a 'katana' (weapon) Object, as this will (should, meh) work with Pixie's combat library, instead of you having to manually code in your own combat stuff for dealing with not using a weapon. As this lets you easily give it values/attributes and etc abilities if you want to have some advanced 'unarmed' combat (different types of punches, kicks, claws, "power fists", "spiked/brass knuckles", "pointed/spiked/dagger boots", and etc unarmed attacks/abilities, for example like in Fallout 1+2 games --- haven't played/seen Fallout 3+4, sighs).

(the same should be done for armor and/or clothing equipment, as well, for when "naked: without armor/clothing", an 'unarmed or unarmored, or naked' armor/clothing Object)


Thanks, it worked. It seems that it did not worked when I tried simply because I added these strings after this:

if (player.hitpoints > 0) {
    msg ("Hits points now " + player.hitpoints)
  }
  else {
    msg ("You are dead!")
    finish

But after I added them before HP strings, all worked. Thank you again!


I finished Pixie's tutorial, thanks to you, guys! It was quite helpful to understand some basics of making an RPG. So, now I'm trying to develop the idea further.

I added command "status" for player, which shows health, ammo, weapon and etc. There I have a first question. What should I do to add in command not only player's current HP, but and the max amount of his HP?

Also I little modified command "look", so now Quest do not consider it as a combat turn. There I have a second question. How can I add current and max HP's of enemy to his look description? I tried to modify this string in SpawnZombie function with adding "obj.hitpoints" and "this.hitpoint", but it doesn't do anything.

obj.look = "A " + obj.alias + ", {random:covered in maggots:missing an arm:one eye hanging out}."

Well, it do... I can add words and sentences, but I cannot display current and max HP's of the enemy.

Would appreciate any help!

Whole code:

<!--Saved by Quest 5.7.6606.27193-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Dwarf World">
    <inherit name="theme_novella" />
    <gameid>7b6e3407-e81b-4f7b-b470-6c3a3f9f5b45</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <feature_advancedscripts />
    <showmoney />
    <defaultfontsize type="int">14</defaultfontsize>
    <backgroundimage>33 2.png</backgroundimage>
    <deactivatecommandlinks type="boolean">false</deactivatecommandlinks>
    <defaultfont>'Lucida Console', Monaco, monospace</defaultfont>
    <defaultbackground>#000000</defaultbackground>
    <defaultlinkforeground>#FFFFB5</defaultlinkforeground>
    <menufont>'Lucida Console', Monaco, monospace</menufont>
    <menubackground>Black</menubackground>
    <menuforeground>White</menuforeground>
    <menuhoverbackground>Black</menuhoverbackground>
    <underlinehyperlinks type="boolean">false</underlinehyperlinks>
    <showcommandbar />
    <customwidth type="int">1200</customwidth>
    <feature_pictureframe />
    <borderlesscursor />
    <defaultforeground>#7BC67B</defaultforeground>
    <unresolvedcommandhandler type="script">
      msg ("Er, what..?")
      game.notarealturn = true
    </unresolvedcommandhandler>
    <start type="script">
      // List of attackers
      player.attackers = NewObjectList()
      player.ammo = 35
      // Status attributes
      WeaponUpdate
      player.statusattributes = NewStringDictionary()
      dictionary add (player.statusattributes, "hitpoints", "Hit points: !")
      dictionary add (player.statusattributes, "ammo", "Spare ammo: !")
      dictionary add (player.statusattributes, "equippedname", "Weapon: !")
      dictionary add (player.statusattributes, "ammonote", "Ammo: !")
    </start>
    <roomenter type="script">
    </roomenter>
    <object name="monsterattacks">
      <inherit name="editor_room" />
      <object name="vomitattack">
        <inherit name="editor_object" />
        <listalias type="string"></listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = "2d6"
          this.attack = 0
          this.critdesc = "#Attacker# spews noxious vomit all over you (#hits# hits)."
          this.attackdesc = "#Attacker# vomits over you (#hits# hits)."
          this.missdesc = "You narrowly avoid the foul vomit from #attacker#."
        </attr>
      </object>
      <object name="vomitreadying">
        <inherit name="editor_object" />
        <listalias type="string"></listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = "0"
          this.attack = -100
          this.critdesc = ""
          this.attackdesc = ""
          this.missdesc = "#Attacker#'s abdomen is gurgling alarmingly."
        </attr>
      </object>
      <object name="talonattack">
        <inherit name="editor_object" />
        <listalias type="string"></listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = "2d6"
          this.attack = 0
          this.critdesc = "#Attacker# strikes you with a monstrous blow (#hits# hits)."
          this.attackdesc = "#Attacker# scratch you by claws (#hits# hits)."
          this.missdesc = "You barely avoid the clawed hand from #attacker#."
        </attr>
      </object>
      <object name="kickattack">
        <inherit name="editor_object" />
        <listalias type="string"></listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = "2d6"
          this.attack = 0
          this.critdesc = "#Attacker# furiously kicks you in leg (#hits# hits)."
          this.attackdesc = "#Attacker# kicks you (#hits# hits)."
          this.missdesc = "You faintly avoid the kick from #attacker#."
        </attr>
      </object>
    </object>
    <object name="Loot">
      <inherit name="editor_room" />
      <object name="treasureroom">
        <inherit name="editor_room" />
        <object name="Pick">
          <inherit name="editor_object" />
          <listalias>Pick</listalias>
          <inventoryverbs type="stringlist">
            <value>Look at</value>
            <value>equip</value>
            <value>Drop</value>
          </inventoryverbs>
          <feature_startscript />
          <take />
          <attr name="_initialise_" type="script">
            this.damage = "1d6"
            this.attack = 3
            this.critdesc = "You smash the pick down on #target# (#hits# hits)."
            this.attackdesc = "You swing the pick at #target# (#hits# hits)."
            this.missdesc = "You swing wildly and entirely miss #target# with your pick."
          </attr>
        </object>
        <object name="Axe">
          <inherit name="editor_object" />
          <listalias>Axe</listalias>
          <inventoryverbs type="stringlist">
            <value>Look at</value>
            <value>equip</value>
            <value>Drop</value>
          </inventoryverbs>
          <feature_startscript />
          <take />
          <attr name="_initialise_" type="script">
            this.damage = "1d6"
            this.attack = 3
            this.critdesc = "You smash the axe down on #target# (#hits# hits)."
            this.attackdesc = "You swing the axe at #target# (#hits# hits)."
            this.missdesc = "You swing wildly and entirely miss #target# with your axe."
          </attr>
        </object>
      </object>
    </object>
  </game>
  <command name="look">
    <pattern type="string">^look$|^l$</pattern>
    <script>
      ShowRoomDescription
      game.notarealturn = true
    </script>
  </command>
  <command name="lookat">
    <pattern>look at #object#; look #object#; x #object#; examine #object#; exam #object#; ex #object#</pattern>
    <script>
      if (GetBoolean(object, "hidechildren")) {
        object.hidechildren = false
      }
      if (TypeOf(object, "look") = "script") {
        do (object, "look")
      }
      else {
        lookdesc = ""
        if (HasString(object, "look")) {
          lookdesc = object.look
        }
        if (LengthOf(lookdesc) = 0) {
          lookdesc = Template("DefaultObjectDescription")
        }
        if (GetBoolean(object, "switchedon")) {
          if (HasString(object, "switchedondesc")) {
            lookdesc = lookdesc + " " + object.switchedondesc
          }
        }
        else {
          if (HasString(object, "switchedoffdesc")) {
            lookdesc = lookdesc + " " + object.switchedoffdesc
          }
        }
        isDark = CheckDarkness()
        if (isDark and not GetBoolean(object, "lightsource")) {
          lookdesc = DynamicTemplate("LookAtDarkness", object)
        }
        msg (lookdesc)
      }
      ListObjectContents (object)
      game.notarealturn = true
    </script>
  </command>
  <object name="room">
    <inherit name="editor_room" />
    <beforefirstenter type="script">
      SpawnZombie (this)
      SpawnZombie (this)
    </beforefirstenter>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
      <feature_startscript />
      <attr name="_initialise_" type="script"><![CDATA[
        player.alias = "you"
        player.hitpoints = 250
        player.damage = 0
        player.attack = 3
        player.defence = 0
        player.armour = 0
        player.money = 10
        this.critdesc = "You attack #target# with your bare hands and get a critical (#hits# hits)."
        this.attackdesc = "You attack #target# with your bare hands and hit (#hits# hits)."
        this.missdesc = "You swing wildly and entirely miss #target#."
        player.changedhitpoints => {
          if (player.hitpoints > 0) {
            msg ("Hits points now " + player.hitpoints)
          }
          else {
            msg ("You are dead!")
            finish
          }
        }
      ]]></attr>
    </object>
    <object name="spade">
      <inherit name="editor_object" />
      <listalias>spade</listalias>
      <inventoryverbs type="stringlist">
        <value>Look at</value>
        <value>equip</value>
        <value>Drop</value>
      </inventoryverbs>
      <feature_startscript />
      <take />
      <attr name="_initialise_" type="script">
        this.damage = "1d6"
        this.attack = 3
        this.critdesc = "You smash the spade down on #target# (#hits# hits)."
        this.attackdesc = "You swing the spade at #target# (#hits# hits)."
        this.missdesc = "You swing wildly and entirely miss #target#."
      </attr>
    </object>
    <object name="pistol">
      <inherit name="editor_object" />
      <listalias>pistol</listalias>
      <inventoryverbs type="stringlist">
        <value>Look at</value>
        <value>equip</value>
        <value>Drop</value>
        <value>reload</value>
      </inventoryverbs>
      <feature_startscript />
      <take />
      <look>Good for shooting zombies. Ammo: {pistol.ammo}/{pistol.ammomax}</look>
      <attr name="_initialise_" type="script">
        this.damage = "2"
        this.attack = 0
        this.firearmdamage = "2d8"
        this.firearmattack = 3
        this.ammo = 3
        this.ammomax = 6
        this.critdesc = "A well placed shot with the pistol on #target# (#hits# hits)."
        this.attackdesc = "You shot the pistol at #target# (#hits# hits)."
        this.missdesc = "You shoot wildly and entirely miss #target#."
      </attr>
      <ontake type="script">
      </ontake>
    </object>
    <exit alias="east" to="safezone">
      <inherit name="eastdirection" />
      <runscript />
      <script type="script">
        player.attackers = NewObjectList()
        msg ("You slam the door, safe at last!")
        player.parent = this.to
      </script>
    </exit>
    <object name="chest">
      <inherit name="editor_object" />
      <feature_startscript />
      <displayverbs type="stringlist">
        <value>Look at</value>
        <value>Search</value>
      </displayverbs>
      <attr name="_initialise_" type="script"><![CDATA[
        this.searchscript => {
          msg ("You found a shiny chunk of gold ore.")
          gold ore.visible = true
        }
      ]]></attr>
    </object>
    <object name="gold ore">
      <inherit name="editor_object" />
      <visible type="boolean">false</visible>
      <take />
    </object>
  </object>
  <command>
    <pattern>attack #object#</pattern>
    <script>
      if (not HasBoolean(object, "dead")) {
        msg ("That's not something you can attack.")
      }
      else if (object.dead) {
        msg ("That one is already dead.")
      }
      else {
        if (player.equipped = null) {
          DoAttack (player, player, object, false)
        }
        else {
          DoAttack (player, player.equipped, object, false)
        }
      }
    </script>
  </command>
  <command>
    <pattern>equip #object#</pattern>
    <script>
      if (HasBoolean(object, "dead")) {
        msg ("That's not something you can wield.")
      }
      else if (not HasAttribute(object, "damage")) {
        msg ("That's not something you can wield.")
      }
      else if (not object.parent = player) {
        msg ("You are not carrying it.")
      }
      else if (object = player.equipped) {
        msg ("You already have.")
      }
      else {
        if (player.equipped = null) {
          msg ("You equip your " + GetDisplayAlias(object) + ".")
        }
        else {
          msg ("You put away your " + GetDisplayAlias(player.equipped) + " and equip your " + GetDisplayAlias(object) + ".")
          list add (player.equipped.inventoryverbs, "Equip")
          list remove (player.equipped.inventoryverbs, "Unequip")
          player.equipped.listalias = Replace(player.equipped.listalias, " (equipped)", "")
        }
        player.equipped = object
        list add (object.inventoryverbs, "Unequip")
        list remove (object.inventoryverbs, "Equip")
        object.listalias = object.listalias + " (equipped)"
        WeaponUpdate
      }
    </script>
  </command>
  <command>
    <pattern>unequip #object#</pattern>
    <script>
      if (not object = player.equipped) {
        msg ("You are not wielding it.")
      }
      else {
        msg ("You put away your spade.")
        player.equipped = null
        list add (object.inventoryverbs, "Equip")
        list remove (object.inventoryverbs, "Unequip")
        object.listalias = Replace(object.listalias, " (equipped)", "")
        WeaponUpdate
      }
    </script>
  </command>
  <turnscript name="attackturnscript">
    <enabled />
    <script>
      if (not GetBoolean(game, "notarealturn")) {
        list = NewObjectList()
        foreach (obj, GetDirectChildren(player.parent)) {
          if (HasBoolean(obj, "dead")) {
            if (not obj.dead) {
              if (HasScript(obj, "selectweapon")) {
                do (obj, "selectweapon")
              }
              if (HasObject(obj, "weapon")) {
                DoAttack (obj, obj.weapon, player, false)
              }
              else {
                DoAttack (obj, obj, player, false)
              }
              list add (list, obj)
            }
          }
        }
        foreach (obj, ListExclude(player.attackers, list)) {
          if (not obj.dead and RandomChance(80)) {
            obj.parent = player.parent
            msg (CapFirst(obj.alias) + " shambles into the area.")
            list add (list, obj)
          }
        }
        player.attackers = list
      }
      game.notarealturn = false
    </script>
  </turnscript>
  <command>
    <pattern>shoot #object#</pattern>
    <script><![CDATA[
      if (not HasBoolean(object, "dead")) {
        msg ("That's not something you need to shoot.")
      }
      else if (object.dead) {
        msg ("That one is already dead.")
      }
      else if (player.equipped = null) {
        msg ("You don't have a firearm equipped.")
      }
      else if (not HasInt(player.equipped, "ammo")) {
        msg ("You can't shoot a " + GetDisplayAlias(player.equipped) + ".")
      }
      else if (not player.equipped.ammo > 0) {
        msg ("You aim your " + GetDisplayAlias(player.equipped) + " and pull the trigger. Click. No ammo loaded.")
      }
      else {
        DoAttack (player, player.equipped, object, true)
        WeaponUpdate
      }
    ]]></script>
  </command>
  <command>
    <pattern>reload #object#</pattern>
    <script><![CDATA[
      if (not HasInt(object, "ammo")) {
        msg ("You can't reload a " + GetDisplayAlias(player.equipped) + ".")
      }
      else if (player.ammo < 1) {
        msg ("You have no ammo.")
      }
      else {
        bullets = object.ammomax - object.ammo
        if (bullets > player.ammo) {
          bullets = player.ammo
        }
        player.ammo = player.ammo - bullets
        object.ammo = object.ammo + bullets
        msg ("You put " + bullets + " bullets in it.")
        WeaponUpdate
      }
    ]]></script>
  </command>
  <object name="safezone">
    <inherit name="editor_room" />
    <exit alias="west" to="room">
      <inherit name="westdirection" />
      <runscript />
      <script type="script">
        player.attackers = NewObjectList()
        msg ("You slam the door, safe at last!")
        player.parent = this.to
      </script>
    </exit>
  </object>
  <command>
    <pattern>search #object#</pattern>
    <script>
      if (not HasScript(object, "searchscript")) {
        msg ("There's nothing of interest there.")
      }
      else if (GetBoolean(object, "searched")) {
        msg ("You find nothing more.")
      }
      else if (not GetBoolean(object, "dead") and HasBoolean(object, "dead")) {
        msg ("That's moving too much for you to search!")
      }
      else {
        do (object, "searchscript")
        object.searched = true
      }
    </script>
  </command>
  <command name="status">
    <pattern>status</pattern>
    <script>
      msg ("Your health is " + player.hitpoints)
      msg ("Your money is " + player.money + " coins")
      msg ("Your weapon is " + player.equippedname)
      msg ("Your ammo loaded is " + player.ammonote)
      msg ("Your spare ammo is " + player.ammo)
      game.notarealturn = true
    </script>
  </command>
  <function name="SpawnZombie" parameters="room"><![CDATA[
    if (HasInt(game, "crittercount")) {
      game.crittercount = game.crittercount + 1
    }
    else {
      game.crittercount = 1
    }
    create ("critter" + game.crittercount)
    obj = GetObject("critter" + game.crittercount)
    obj.parent = room
    obj.displayverbs = Split("Look at;Attack;Shoot", ";")
    obj.dead = false
    obj.changedhitpoints => {
      if (this.hitpoints < 1) {
        msg ("It is dead!")
        this.dead = true
        this.displayverbs = Split("Look at;Search", ";")
      }
    }
    names = Split("decipit;decomposing;shambling;disgusting;filthy;falling-apart", ";")
    obj.alias = StringListItem(names, game.crittercount % ListCount(names)) + " zombie"
    obj.listalias = CapFirst(obj.alias)
    obj.look = "A " + obj.alias + ", {random:covered in maggots:missing an arm:one eye hanging out}."
    obj.hitpoints = 2
    obj.damage = 1
    obj.attack = 0
    obj.defence = 0
    obj.armour = 0
    obj.critdesc = "A well-placed blow by #attacker# sends you reeling (#hits# hits)."
    obj.attackdesc = "#Attacker# has hit you (#hits# hits)."
    obj.missdesc = "{random:#Attacker# attacks you and <b>misses1</b>:#Attacker# attacks you and <b>misses2</b>:#Attacker# attacks you and <b>misses3</b>}"
    obj.selectweapon => {
      if (this.weapon = vomitreadying) {
        this.weapon = vomitattack
      }
      else {
        this.weapon = GetObject(PickOneString("vomitreadying;talonattack;kickattack;talonattack;kickattack"))
      }
    }
    obj.searchscript => {
      money = GetRandomInt(1, 50)
      msg ("You find " + DisplayMoney(money) + ".")
      player.money = player.money + money
      if (RandomChance (50) = true) {
        o = PickOneChild(treasureroom)
        msg ("You also find " + GetDisplayName(o) + ".")
        CloneObjectAndMoveHere (o)
      }
    }
  ]]></function>
  <function name="DoAttack" parameters="attacker, weapon, target, firearm"><![CDATA[
    if (firearm) {
      damageatt = "firearmdamage"
      attackatt = "firearmattack"
      weapon.ammo = weapon.ammo - 1
    }
    else {
      damageatt = "damage"
      attackatt = "attack"
    }
    roll = GetRandomInt(1, 20) + weapon.attack - target.defence
    damage = DiceRoll(weapon.damage) * (100 - target.armour) / 100
    if (damage < 1) {
      damage = 1
    }
    if (roll > 15) {
      damage = damage * 3
      AttackReport (weapon.critdesc, attacker, target, damage)
      target.hitpoints = target.hitpoints - damage
    }
    else if (roll > 10) {
      AttackReport (weapon.attackdesc, attacker, target, damage)
      target.hitpoints = target.hitpoints - damage
    }
    else {
      AttackReport (weapon.missdesc, attacker, target, 0)
    }
  ]]></function>
  <function name="WeaponUpdate">
    if (player.equipped = null) {
      player.equippedname = "bare hands"
      player.ammonote = "-"
    }
    else {
      player.equippedname = Replace (player.equipped.listalias, " (equipped)", "")
      if (not HasAttribute(player.equipped, "ammo")) {
        player.ammonote = "-"
      }
      else {
        player.ammonote = player.equipped.ammo + "/" + player.equipped.ammomax
      }
    }
  </function>
  <function name="AttackReport" parameters="s, attacker, target, hits">
    s = Replace(s, "#Attacker#", CapFirst(GetDisplayAlias(attacker)))
    s = Replace(s, "#attacker#", GetDisplayAlias(attacker))
    s = Replace(s, "#Target#", CapFirst(GetDisplayAlias(target)))
    s = Replace(s, "#target#", GetDisplayAlias(target))
    s = Replace(s, "#hits#", "" + hits)
    msg (s)
  </function>
</asl>

P.S. hegemonkhan, I tried to use Pixie's combat library, but it seems to have some errors in it (or it's silly me :D), at least in part of adding "armour" parametr to clothing (though, it adds defence correctly). So, I decided to use his libraries as theoretical basis for my game, but try to do my own system, to better understand the whole engine.


here's a link (really detailed step by step walkthrough demo game making guide) on using the built-in 'statusattributes' String Dictionary Attribute (doing: cur/max life/mana, etc):

http://textadventures.co.uk/forum/quest/topic/5387/i-really-need-help#37375

and here's a bunch of links (guides) to get started with learning quest and its coding:

http://textadventures.co.uk/forum/general/topic/ljjm32av4e2t9ot49k478g/help#710be61e-eae1-4af1-8363-520cc718ba1c

here's my own combat code (all credit goes to pertex as I used his combat code and its structure as the basis for mine) that you can study (it was done a long time ago when I was learning combat coding myself, so it's really bad code, it has some mistakes and has some un-needed code, and I got confused with my abbreviated elemental damage/defense-resistance attributes, argh. I learned to never ever use abrevs from that point on, lol):

https://textadventures.co.uk/forum/quest/topic/3348/noobie-hks-help-me-thread#22485 (Pertex' cleaned my combat code up a bit, so this is the best to look for trying to study/understand it, you got to download it though)

if you don't want to download pertex' cleaned up code of mine, then here (but it's going to be harder to study/understand as it's really messy and got mistakes and lots of un-needed code):

https://textadventures.co.uk/forum/quest/topic/3348/noobie-hks-help-me-thread#22483

and lastly, here's the bloody (sorry about this) legend/key for my abrevs (I've learned to never ever use abrevs ever since, lol):

https://textadventures.co.uk/forum/quest/topic/3348/noobie-hks-help-me-thread#22486


ask if you got any questions, or need help or explanation of anything


Also I little modified command "look", so now Quest do not consider it as a combat turn. There I have a second question. How can I add current and max HP's of enemy to his look description? I tried to modify this string in SpawnZombie function with adding "obj.hitpoints" and "this.hitpoint", but it doesn't do anything.

obj.look = "A " + obj.alias + ", {random:covered in maggots:missing an arm:one eye hanging out}."

OK ... when you call SpawnZombie, it sets the "look" description to that string. So the object's look attribute is actually something like A shambling zombie, {random:covered in maggots:missing an arm:one eye hanging out}.

This is relevant. Variables added using the + obj.alias + syntax are converted into text when SpawnZombie is run. So if you do + obj.hitpoints + here, that will be the zombie's hitpoints at that point in SpawnZombie, which is before they've been set.

On the other hand, text processor commands will be used to get the current value of an attribute when you look at the zombie.
BUT
Something like `obj.look = "A " + obj.alias + ", with {obj.hitpoints} HP" will NOT work.

Because the obj variable only exists until the end of SpawnZombie. And you can't use this effectively in the text processor.

So what do you do? You use the name of the actual zombie you're looking at.

obj.look = "A " + obj.alias + ", with {" + obj.name + ".hitpoints} HP."
or something like that.

This means that the object's "look" attribute is something like A shambling zombie with {critter17.hitpoints} HP, which will be displayed correctly when the player looks at it.

I note that in previous versions of the code, you had:

obj.look = ProcessText("A " + obj.alias + ", {random:covered in maggots:missing an arm:one eye hanging out}.")

This would have done the random thing once for each zombie, so if it has an eye hanging out it will still have an eye hanging out the next time you look at it.

If you want to put that back in, so that random descriptions still work like that, you'd have to do it like:

obj.look = ProcessText("A " + obj.alias + " (@@@open@@@" + obj.name + ".hitpoints@@@close@@@HP), {random:covered in maggots:missing an arm:one eye hanging out}.")

The text processor turns @@@open@@@ and @@@close@@@ into { and }, so after running ProcessText, the "look" attribute would be: A shambling zombie ({critter6.hitpoints}HP), with one eye hanging out. The random text is fixed when the zombie is created, but the hitpoints attribute is still checked each time you look at it.


Thank you, mrangel, it worked! I probably messed up with brackets when was trying to rework look system, if not you, I wouldn't even see that.
Thank you, hegemonkhan, I'll read these guides!

My progress at game:

  1. I somehow did a very simple max hitpoints system.
  2. Also I made a drink/eat verbs and objects, which can change player's stats.
  3. Changed zombie's description and stats to level 1 goblin (though, haven't started yet working on the level system)

I decided to rework combat system, adding combat stat "agility", instead of "defence", and also changed damage algorithm but something went not right. When I try to attack, I have this message:

Error running script: Error compiling expression 'GetRandomInt(1, 60) + attacker.agility': SyntaxError: Unexpected character: Line: 1, Column: 47

Whole code:

<!--Saved by Quest 5.7.6606.27193-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Dwarf World">
    <inherit name="theme_novella" />
    <gameid>7b6e3407-e81b-4f7b-b470-6c3a3f9f5b45</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <feature_advancedscripts />
    <showmoney />
    <defaultfontsize type="int">14</defaultfontsize>
    <backgroundimage>33 2.png</backgroundimage>
    <deactivatecommandlinks />
    <defaultfont>'Lucida Console', Monaco, monospace</defaultfont>
    <defaultbackground>#000000</defaultbackground>
    <defaultlinkforeground>#FFFFB5</defaultlinkforeground>
    <menufont>'Lucida Console', Monaco, monospace</menufont>
    <menubackground>Black</menubackground>
    <menuforeground>White</menuforeground>
    <menuhoverbackground>Black</menuhoverbackground>
    <underlinehyperlinks />
    <showcommandbar />
    <customwidth type="int">1200</customwidth>
    <feature_pictureframe />
    <borderlesscursor />
    <defaultforeground>#7BC67B</defaultforeground>
    <unresolvedcommandhandler type="script">
      msg ("Er, what..?")
      game.notarealturn = true
    </unresolvedcommandhandler>
    <start type="script">
      // List of attackers
      player.attackers = NewObjectList()
      player.ammo = 35
      // Status attributes
      WeaponUpdate
      player.statusattributes = NewStringDictionary()
      dictionary add (player.statusattributes, "hitpoints", "Hit points: !")
      dictionary add (player.statusattributes, "ammo", "Spare ammo: !")
      dictionary add (player.statusattributes, "equippedname", "Weapon: !")
      dictionary add (player.statusattributes, "ammonote", "Ammo: !")
    </start>
    <roomenter type="script">
    </roomenter>
    <object name="monsterattacks">
      <inherit name="editor_room" />
      <object name="vomitattack">
        <inherit name="editor_object" />
        <listalias type="string"></listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = 10
          this.critdesc = "#Attacker# spews noxious vomit all over you (#hits# hits)."
          this.attackdesc = "#Attacker# vomits over you (#hits# hits)."
          this.missdesc = "You narrowly avoid the foul vomit from #attacker#."
        </attr>
      </object>
      <object name="vomitreadying">
        <inherit name="editor_object" />
        <listalias type="string"></listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = "0"
          this.agility = -100
          this.critdesc = ""
          this.attackdesc = ""
          this.missdesc = "#Attacker#'s abdomen is gurgling alarmingly."
        </attr>
      </object>
      <object name="talonattack">
        <inherit name="editor_object" />
        <listalias type="string"></listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = 10
          this.critdesc = "#Attacker# strikes you with a monstrous blow (#hits# hits)."
          this.attackdesc = "#Attacker# scratch you by claws (#hits# hits)."
          this.missdesc = "You barely avoid the clawed hand from #attacker#."
        </attr>
      </object>
      <object name="kickattack">
        <inherit name="editor_object" />
        <listalias type="string"></listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = 10
          this.critdesc = "#Attacker# furiously kicks you in leg (#hits# hits)."
          this.attackdesc = "#Attacker# kicks you (#hits# hits)."
          this.missdesc = "You faintly avoid the kick from #attacker#."
        </attr>
      </object>
    </object>
    <object name="Loot">
      <inherit name="editor_room" />
      <object name="treasureroom">
        <inherit name="editor_room" />
        <object name="Pick">
          <inherit name="editor_object" />
          <listalias>Pick</listalias>
          <inventoryverbs type="stringlist">
            <value>Look at</value>
            <value>equip</value>
            <value>Drop</value>
          </inventoryverbs>
          <feature_startscript />
          <take />
          <attr name="_initialise_" type="script">
            this.damage = 8
            this.critdesc = "You smash the pick down on #target# (#hits# hits)."
            this.attackdesc = "You swing the pick at #target# (#hits# hits)."
            this.missdesc = "You swing wildly and entirely miss #target# with your pick."
          </attr>
        </object>
        <object name="Axe">
          <inherit name="editor_object" />
          <listalias>Axe</listalias>
          <inventoryverbs type="stringlist">
            <value>Look at</value>
            <value>equip</value>
            <value>Drop</value>
          </inventoryverbs>
          <feature_startscript />
          <take />
          <attr name="_initialise_" type="script">
            this.damage = 10
            this.critdesc = "You smash the axe down on #target# (#hits# hits)."
            this.attackdesc = "You swing the axe at #target# (#hits# hits)."
            this.missdesc = "You swing wildly and entirely miss #target# with your axe."
          </attr>
        </object>
      </object>
    </object>
  </game>
  <command name="look">
    <pattern type="string">^look$|^l$</pattern>
    <script>
      ShowRoomDescription
      game.notarealturn = true
    </script>
  </command>
  <command name="lookat">
    <pattern>look at #object#; look #object#; x #object#; examine #object#; exam #object#; ex #object#</pattern>
    <script>
      if (GetBoolean(object, "hidechildren")) {
        object.hidechildren = false
      }
      if (TypeOf(object, "look") = "script") {
        do (object, "look")
      }
      else {
        lookdesc = ""
        if (HasString(object, "look")) {
          lookdesc = object.look
        }
        if (LengthOf(lookdesc) = 0) {
          lookdesc = Template("DefaultObjectDescription")
        }
        if (GetBoolean(object, "switchedon")) {
          if (HasString(object, "switchedondesc")) {
            lookdesc = lookdesc + " " + object.switchedondesc
          }
        }
        else {
          if (HasString(object, "switchedoffdesc")) {
            lookdesc = lookdesc + " " + object.switchedoffdesc
          }
        }
        isDark = CheckDarkness()
        if (isDark and not GetBoolean(object, "lightsource")) {
          lookdesc = DynamicTemplate("LookAtDarkness", object)
        }
        msg (lookdesc)
      }
      ListObjectContents (object)
      game.notarealturn = true
    </script>
  </command>
  <object name="room">
    <inherit name="editor_room" />
    <description type="string"></description>
    <descprefix>You are</descprefix>
    <beforefirstenter type="script">
      SpawnGoblin1 (this)
      SpawnGoblin1 (this)
    </beforefirstenter>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
      <feature_startscript />
      <attr name="_initialise_" type="script"><![CDATA[
        player.alias = "you"
        player.hitpoints = 250
        player.maxhitpoints = 260
        player.damage = 3
        player.might = 0
        player.agility = 0
        player.vitality = 0
        player.intellegence = 0
        player.armour = 6
        player.money = 10
        this.critdesc = "You attack #target# with your bare hands and get a critical (#hits# hits)."
        this.attackdesc = "You attack #target# with your bare hands and hit (#hits# hits)."
        this.missdesc = "You swing wildly and entirely miss #target#."
        player.changedhitpoints => {
          if (player.hitpoints > 0) {
            msg ("Hits points now " + player.hitpoints)
          }
          else {
            msg ("You are dead!")
            finish
          }
        }
      ]]></attr>
    </object>
    <object name="spade">
      <inherit name="editor_object" />
      <listalias>spade</listalias>
      <inventoryverbs type="stringlist">
        <value>Look at</value>
        <value>equip</value>
        <value>Drop</value>
      </inventoryverbs>
      <feature_startscript />
      <take />
      <attr name="_initialise_" type="script">
        this.damage = 5
        this.critdesc = "You smash the spade down on #target# (#hits# hits)."
        this.attackdesc = "You swing the spade at #target# (#hits# hits)."
        this.missdesc = "You swing wildly and entirely miss #target#."
      </attr>
    </object>
    <object name="pistol">
      <inherit name="editor_object" />
      <listalias>pistol</listalias>
      <inventoryverbs type="stringlist">
        <value>Look at</value>
        <value>equip</value>
        <value>Drop</value>
        <value>reload</value>
      </inventoryverbs>
      <feature_startscript />
      <take />
      <look>Good for shooting zombies. Ammo: {pistol.ammo}/{pistol.ammomax}</look>
      <attr name="_initialise_" type="script">
        this.damage = "2"
        this.attack = 0
        this.firearmdamage = "2d8"
        this.firearmattack = 3
        this.ammo = 3
        this.ammomax = 6
        this.critdesc = "A well placed shot with the pistol on #target# (#hits# hits)."
        this.attackdesc = "You shot the pistol at #target# (#hits# hits)."
        this.missdesc = "You shoot wildly and entirely miss #target#."
      </attr>
      <ontake type="script">
      </ontake>
    </object>
    <exit alias="east" to="safezone">
      <inherit name="eastdirection" />
      <runscript />
      <script type="script">
        player.attackers = NewObjectList()
        msg ("You slam the door, safe at last!")
        player.parent = this.to
      </script>
    </exit>
    <object name="chest">
      <inherit name="editor_object" />
      <feature_startscript />
      <displayverbs type="stringlist">
        <value>Look at</value>
        <value>Search</value>
      </displayverbs>
      <attr name="_initialise_" type="script"><![CDATA[
        this.searchscript => {
          msg ("You found a shiny chunk of gold ore.")
          gold ore.visible = true
        }
      ]]></attr>
    </object>
    <object name="gold ore">
      <inherit name="editor_object" />
      <visible type="boolean">false</visible>
      <take />
    </object>
  </object>
  <command>
    <pattern>attack #object#</pattern>
    <script>
      if (not HasBoolean(object, "dead")) {
        msg ("That's not something you can attack.")
      }
      else if (object.dead) {
        msg ("That one is already dead.")
      }
      else {
        if (player.equipped = null) {
          DoAttack (player, player, object, false)
        }
        else {
          DoAttack (player, player.equipped, object, false)
        }
      }
    </script>
  </command>
  <command>
    <pattern>equip #object#</pattern>
    <script>
      if (HasBoolean(object, "dead")) {
        msg ("That's not something you can wield.")
      }
      else if (not HasAttribute(object, "damage")) {
        msg ("That's not something you can wield.")
      }
      else if (not object.parent = player) {
        msg ("You are not carrying it.")
      }
      else if (object = player.equipped) {
        msg ("You already have.")
      }
      else {
        if (player.equipped = null) {
          msg ("You equip your " + GetDisplayAlias(object) + ".")
        }
        else {
          msg ("You put away your " + GetDisplayAlias(player.equipped) + " and equip your " + GetDisplayAlias(object) + ".")
          list add (player.equipped.inventoryverbs, "Equip")
          list remove (player.equipped.inventoryverbs, "Unequip")
          player.equipped.listalias = Replace(player.equipped.listalias, " (equipped)", "")
        }
        player.equipped = object
        list add (object.inventoryverbs, "Unequip")
        list remove (object.inventoryverbs, "Equip")
        object.listalias = object.listalias + " (equipped)"
        WeaponUpdate
      }
    </script>
  </command>
  <command>
    <pattern>unequip #object#</pattern>
    <script>
      if (not object = player.equipped) {
        msg ("You are not wielding it.")
      }
      else {
        msg ("You put away your spade.")
        player.equipped = null
        list add (object.inventoryverbs, "Equip")
        list remove (object.inventoryverbs, "Unequip")
        object.listalias = Replace(object.listalias, " (equipped)", "")
        WeaponUpdate
      }
    </script>
  </command>
  <turnscript name="attackturnscript">
    <enabled />
    <script>
      if (not GetBoolean(game, "notarealturn")) {
        list = NewObjectList()
        foreach (obj, GetDirectChildren(player.parent)) {
          if (HasBoolean(obj, "dead")) {
            if (not obj.dead) {
              if (HasScript(obj, "selectweapon")) {
                do (obj, "selectweapon")
              }
              if (HasObject(obj, "weapon")) {
                DoAttack (obj, obj.weapon, player, false)
              }
              else {
                DoAttack (obj, obj, player, false)
              }
              list add (list, obj)
            }
          }
        }
        foreach (obj, ListExclude(player.attackers, list)) {
          if (not obj.dead and RandomChance(80)) {
            obj.parent = player.parent
            msg (CapFirst(obj.alias) + " shambles into the area.")
            list add (list, obj)
          }
        }
        player.attackers = list
      }
      game.notarealturn = false
    </script>
  </turnscript>
  <command>
    <pattern>shoot #object#</pattern>
    <script><![CDATA[
      if (not HasBoolean(object, "dead")) {
        msg ("That's not something you need to shoot.")
      }
      else if (object.dead) {
        msg ("That one is already dead.")
      }
      else if (player.equipped = null) {
        msg ("You don't have a firearm equipped.")
      }
      else if (not HasInt(player.equipped, "ammo")) {
        msg ("You can't shoot a " + GetDisplayAlias(player.equipped) + ".")
      }
      else if (not player.equipped.ammo > 0) {
        msg ("You aim your " + GetDisplayAlias(player.equipped) + " and pull the trigger. Click. No ammo loaded.")
      }
      else {
        DoAttack (player, player.equipped, object, true)
        WeaponUpdate
      }
    ]]></script>
  </command>
  <command>
    <pattern>reload #object#</pattern>
    <script><![CDATA[
      if (not HasInt(object, "ammo")) {
        msg ("You can't reload a " + GetDisplayAlias(player.equipped) + ".")
      }
      else if (player.ammo < 1) {
        msg ("You have no ammo.")
      }
      else {
        bullets = object.ammomax - object.ammo
        if (bullets > player.ammo) {
          bullets = player.ammo
        }
        player.ammo = player.ammo - bullets
        object.ammo = object.ammo + bullets
        msg ("You put " + bullets + " bullets in it.")
        WeaponUpdate
      }
    ]]></script>
  </command>
  <object name="safezone">
    <inherit name="editor_room" />
    <exit alias="west" to="room">
      <inherit name="westdirection" />
      <runscript />
      <script type="script">
        player.attackers = NewObjectList()
        msg ("You slam the door, safe at last!")
        player.parent = this.to
      </script>
    </exit>
    <object name="Dwarven pie">
      <inherit name="editor_object" />
      <take />
      <look>Favorite dwarf's pie, stuffed with gravel and sandstone. Hard as stone. Restore 15 HP, when eaten.</look>
      <eat type="script"><![CDATA[
        msg ("You eat the dwarven pie, receiving 15 health.")
        if (player.hitpoints + 15 > player.maxhitpoints) {
          player.hitpoints = player.maxhitpoints
        }
        else {
          player.hitpoints = player.hitpoints + 15
        }
        this.parent = null
      ]]></eat>
      <ontake type="script">
      </ontake>
    </object>
    <object name="Dwarven beer">
      <inherit name="editor_object" />
      <take />
      <look>Strong dwarven beer from underground wheat and a special mix of mushrooms.</look>
      <drink type="script">
        msg ("You drink strong dwarven beer. Your max health increased by 5!")
        player.maxhitpoints = player.maxhitpoints + 5
        msg ("Max hitpoints now " + player.maxhitpoints)
        this.parent = null
      </drink>
      <ontake type="script">
      </ontake>
    </object>
  </object>
  <command>
    <pattern>search #object#</pattern>
    <script>
      if (not HasScript(object, "searchscript")) {
        msg ("There's nothing of interest there.")
      }
      else if (GetBoolean(object, "searched")) {
        msg ("You find nothing more.")
      }
      else if (not GetBoolean(object, "dead") and HasBoolean(object, "dead")) {
        msg ("That's moving too much for you to search!")
      }
      else {
        do (object, "searchscript")
        object.searched = true
      }
    </script>
  </command>
  <command name="status">
    <pattern>status</pattern>
    <script>
      msg ("Your health is " + player.hitpoints + "/" + player.maxhitpoints)
      msg ("Your money is " + player.money + " coins")
      msg ("Your weapon is " + player.equippedname)
      msg ("Your ammo loaded is " + player.ammonote)
      msg ("Your spare ammo is " + player.ammo)
      game.notarealturn = true
    </script>
  </command>
  <function name="SpawnGoblin1" parameters="room"><![CDATA[
    if (HasInt(game, "crittercount")) {
      game.crittercount = game.crittercount + 1
    }
    else {
      game.crittercount = 1
    }
    create ("critter" + game.crittercount)
    obj = GetObject("critter" + game.crittercount)
    obj.parent = room
    obj.displayverbs = Split("Look at;Attack;Shoot", ";")
    obj.dead = false
    obj.changedhitpoints => {
      if (this.hitpoints < 1) {
        msg ("Goblin falls dead!")
        this.dead = true
        this.displayverbs = Split("Look at;Search", ";")
      }
    }
    names = Split("foul;angry;nasty;fat;filthy;drunk", ";")
    obj.alias = StringListItem(names, game.crittercount % ListCount(names)) + " goblin"
    obj.listalias = CapFirst(obj.alias)
    obj.look = ProcessText("This " + obj.alias + " {random:looks disgusting: stinks like a bunch of socks:without teeth at all}" + " {colour:#FFFFB5:(@@@open@@@" + obj.name + ".hitpoints@@@close@@@/20 HP)}")
    obj.hitpoints = 20
    obj.damage = 10
    obj.agility = 0
    obj.armour = 0
    obj.critdesc = "A well-placed blow by #attacker# sends you reeling (#hits# hits)."
    obj.attackdesc = "#Attacker# has hit you (#hits# hits)."
    obj.missdesc = "{random:#Attacker# attacks you and <b>misses1</b>:#Attacker# attacks you and <b>misses2</b>:#Attacker# attacks you and <b>misses3</b>}"
    obj.selectweapon => {
      if (this.weapon = vomitreadying) {
        this.weapon = vomitattack
      }
      else {
        this.weapon = GetObject(PickOneString("vomitreadying;talonattack;kickattack;talonattack;kickattack"))
      }
    }
    obj.searchscript => {
      money = GetRandomInt(1, 50)
      msg ("You find " + DisplayMoney(money) + ".")
      player.money = player.money + money
      if (RandomChance (50) = true) {
        o = PickOneChild(treasureroom)
        msg ("You also find " + GetDisplayName(o) + ".")
        CloneObjectAndMoveHere (o)
      }
    }
  ]]></function>
  <function name="DoAttack" parameters="attacker, weapon, target, firearm"><![CDATA[
    if (firearm) {
      attackatt = "firearmattack"
      weapon.ammo = weapon.ammo - 1
    }
    else {
      attackatt = "attack"
    }
    roll = GetRandomInt(1, 60) + attacker.agility
    damage = attacker.damage - target.armour
    if (damage < 1) {
      damage = 1
    }
    if (roll > 80) {
      damage = damage * 3
      AttackReport (weapon.critdesc, attacker, target, damage)
      target.hitpoints = target.hitpoints - damage
    }
    else if (roll > 60) {
      damage = damage * 2
      AttackReport (weapon.attackdesc, attacker, target, damage)
      target.hitpoints = target.hitpoints - damage
    }
    else if (roll > 40) {
      damage = damage * 1
      AttackReport (weapon.attackdesc, attacker, target, damage)
      target.hitpoints = target.hitpoints - damage
    }
    else if (roll > 20) {
      damage = damage * 0.5
      AttackReport (weapon.attackdesc, attacker, target, damage)
      target.hitpoints = target.hitpoints - damage
    }
    else {
      AttackReport (weapon.missdesc, attacker, target, 0)
    }
  ]]></function>
  <function name="WeaponUpdate">
    if (player.equipped = null) {
      player.equippedname = "bare hands"
      player.ammonote = "-"
    }
    else {
      player.equippedname = Replace (player.equipped.listalias, " (equipped)", "")
      if (not HasAttribute(player.equipped, "ammo")) {
        player.ammonote = "-"
      }
      else {
        player.ammonote = player.equipped.ammo + "/" + player.equipped.ammomax
      }
    }
  </function>
  <function name="AttackReport" parameters="s, attacker, target, hits">
    s = Replace(s, "#Attacker#", CapFirst(GetDisplayAlias(attacker)))
    s = Replace(s, "#attacker#", GetDisplayAlias(attacker))
    s = Replace(s, "#Target#", CapFirst(GetDisplayAlias(target)))
    s = Replace(s, "#target#", GetDisplayAlias(target))
    s = Replace(s, "#hits#", "" + hits)
    msg (s)
  </function>
</asl>

P.S. Can I change somehow topic's name? It's theme is little bit different now, but I want to continue posting here.
P.P.S. Maybe, next time, I need to post my code not as message, but rather as link to it?


I think if you edit your OP, you can change the topic


unfortunately the error message isn't helping:

Error running script: Error compiling expression 'GetRandomInt(1, 60) + attacker.agility': SyntaxError: Unexpected character: Line: 1, Column: 47

as it says: LINE 1, column 47

obviously it's not the first line and 47th character count (within your first line of code) from the left side, lol

the usual error is a missing 'xml' tag code, and/or, a function's/script's parenthesis (a missing left or right parenthesis, too many/few parenthesis on one side, and/or parenthesis in the wrong placement) and/or a missing curly bracket (left or right):

WHICH UNFORTUNATELY, SCREWS UP / shifts the compilation reading of parts of (or even possibly the entire) game code by quest, and thus the error), for example concept:

Hi my name is hegemonkhan what is your name

but pretend we got an error in it, which causes it not to be in that same (readable/understandable) pattern (its shifted-rotated 1 character to the right, but the spaces remain un-moved):

eh im ynam ei sh egemonkha nwha ti sy ou rnam (you probably could never tell what this was trying to say if you didn't already know what it was, lol)

// the 'xml' tags:

starting tag: <

ending tag: >

missing:  /  ----- in the ending tag of:   '/>' or '</XXX>'

wrong direction (a back slash) of the correct (forward) slash needed (aka: having the wrong slash character): \ ----- in the ending tag of: />

good luck with finding it....

the best thing you can do... is make a backup copy of your game file... and then just start deleting chunks (you got to delete the chunks properly so that the rest of your game code still works) of your code ("divide and conquer" --- delete the entire bottom half of your code, if no error, then the error is in the bottom half of the code, do the same again, delete the bottom half of the code you deleted, and continue this until you can get to finding/knowing where the error is, and if the error is in the code you didn't delete, then continue to delete half of it until you narrow down to being able to find it) until you narrow down where it's at

https://en.wikipedia.org/wiki/Divide_and_conquer_algorithm (this is on programming code algorithms/designs itself, but it works the same for tracking down where your error is)

https://nms.kcl.ac.uk/colin.cooper/teachingmaterial/PAL-PDA/lectures/6A-Divide-Conquer.pdf

http://web.eecs.umich.edu/~aprakash/eecs282/lectures/11-recursion.pdf


in your 'DoAttack' Function, you could try taking out the space in the parenthesis:

from:

roll = GetRandomInt(1, 60) + attacker.agility

to:

roll = GetRandomInt(1,60) + attacker.agility

but, I think quest is able to handle having a space in it... but if not... then hopefully the error (and its the only error --- usually when you got "an error", it's actually a bunch of errors, which you find out as you solve one, only to get another error now being messaged to you --- it can only show one error spot at a time, lol) is solved, lol


the absolute worse is having an accidental space where it causes an error... finding that accidental space is nearly impossible... and usually it doesn't even cross your mind that the error is a $#$#@ accidental space some where.. lol... but even being aware of this error... doesn't help in finding the accidental space... lol

(accidental spaces can happen a lot when you copy and paste code a lot... accidentally highlighting too far... getting extra space/s at the beginning and/or ending of the code you're highlighting, copying, and then pasting... lol)


The issue is in the line roll = GetRandomInt(1, 60) + attacker.agility in the DoAttack function.

The 47th character here is at the end of the line. Your pasted code appears to include three non-printable characters at the end of the line (unless the forum has added them somehow). They are 'dead' characters, which don't take up space but cause an accent to appear over the next character., As they're at the end of the line, you don't see the accent.

I'd suggest you delete these characters; how easy that is will depend on your international input method settings. If all else fails, you can go into code view, delete this line, and type it again.

(Sorry if that doesn't help; I'm panicking over my new book being behind schedule, so am skimming your code looking for a solution as quickly as I can)


Thank you guys for helping me again! I resolved the problem by loading the backup of my code and writing the new part again.

Now I will be more careful with this and will start make backups more often.

Also, I changed the topic's name and first post.


Hi all!

My progress at game:

  1. Addded characteristics (Strength, agility, vitality and intelligence)
  2. Added fast travels
  3. Added armour, jewelry and shields
  4. Added inventory size

I have an problem - I do not know, how to create container, in which I can place and keep my items in-game, since I have inventory size limit. I tried to find such topic on forum, but failed.

Whole code (Presumably, this container should be "Crate" in "safezone5":

<!--Saved by Quest 5.7.6606.27193-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <dynamictemplate name="WearSuccessful">"You put " + object.article + " on."</dynamictemplate>
  <game name="Dwarf World">
    <inherit name="theme_novella" />
    <gameid>7b6e3407-e81b-4f7b-b470-6c3a3f9f5b45</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <feature_advancedscripts />
    <showmoney />
    <defaultfontsize type="int">14</defaultfontsize>
    <backgroundimage>33 2.png</backgroundimage>
    <deactivatecommandlinks />
    <defaultfont>'Lucida Console', Monaco, monospace</defaultfont>
    <defaultbackground>#000000</defaultbackground>
    <defaultlinkforeground>#FFFFB5</defaultlinkforeground>
    <menufont>'Lucida Console', Monaco, monospace</menufont>
    <menubackground>Black</menubackground>
    <menuforeground>White</menuforeground>
    <menuhoverbackground>Black</menuhoverbackground>
    <underlinehyperlinks />
    <showcommandbar />
    <customwidth type="int">1200</customwidth>
    <feature_pictureframe />
    <borderlesscursor />
    <defaultforeground>#7BC67B</defaultforeground>
    <feature_limitinventory />
    <unresolvedcommandhandler type="script">
      msg ("Er, what..?")
      game.notarealturn = true
    </unresolvedcommandhandler>
    <start type="script">
      // List of attackers
      player.attackers = NewObjectList()
      player.ammo = 35
      // Status attributes
      WeaponUpdate
      player.statusattributes = NewStringDictionary()
      dictionary add (player.statusattributes, "hitpoints", "Hit points: !")
      dictionary add (player.statusattributes, "ammo", "Spare ammo: !")
      dictionary add (player.statusattributes, "equippedname", "Weapon: !")
      dictionary add (player.statusattributes, "ammonote", "Ammo: !")
    </start>
    <roomenter type="script">
    </roomenter>
    <object name="Loot">
      <inherit name="editor_room" />
    </object>
  </game>
  <command name="look">
    <pattern type="string">^look$|^l$</pattern>
    <script>
      ShowRoomDescription
      game.notarealturn = true
    </script>
  </command>
  <command name="lookat">
    <pattern>look at #object#; look #object#; x #object#; examine #object#; exam #object#; ex #object#</pattern>
    <script>
      if (GetBoolean(object, "hidechildren")) {
        object.hidechildren = false
      }
      if (TypeOf(object, "look") = "script") {
        do (object, "look")
      }
      else {
        lookdesc = ""
        if (HasString(object, "look")) {
          lookdesc = object.look
        }
        if (LengthOf(lookdesc) = 0) {
          lookdesc = Template("DefaultObjectDescription")
        }
        if (GetBoolean(object, "switchedon")) {
          if (HasString(object, "switchedondesc")) {
            lookdesc = lookdesc + " " + object.switchedondesc
          }
        }
        else {
          if (HasString(object, "switchedoffdesc")) {
            lookdesc = lookdesc + " " + object.switchedoffdesc
          }
        }
        isDark = CheckDarkness()
        if (isDark and not GetBoolean(object, "lightsource")) {
          lookdesc = DynamicTemplate("LookAtDarkness", object)
        }
        msg (lookdesc)
      }
      ListObjectContents (object)
      game.notarealturn = true
    </script>
  </command>
  <command>
    <pattern>attack #object#</pattern>
    <script>
      if (not HasBoolean(object, "dead")) {
        msg ("That's not something you can attack.")
      }
      else if (object.dead) {
        msg ("That one is already dead.")
      }
      else {
        if (player.equipped = null) {
          DoAttack (player, player, object, false, false)
        }
        else {
          DoAttack (player, player.equipped, object, false, false)
        }
      }
    </script>
  </command>
  <command>
    <pattern>equip #object#</pattern>
    <script>
      if (HasBoolean(object, "dead")) {
        msg ("That's not something you can wield.")
      }
      else if (not HasAttribute(object, "damage")) {
        msg ("That's not something you can wield.")
      }
      else if (not object.parent = player) {
        msg ("You are not carrying it.")
      }
      else if (object = player.equipped) {
        msg ("You already have.")
      }
      else {
        if (player.equipped = null) {
          msg ("You equip your " + GetDisplayAlias(object) + ".")
        }
        else {
          msg ("You put away your " + GetDisplayAlias(player.equipped) + " and equip your " + GetDisplayAlias(object) + ".")
          list add (player.equipped.inventoryverbs, "Equip")
          list remove (player.equipped.inventoryverbs, "Unequip")
          player.equipped.listalias = Replace(player.equipped.listalias, " (equipped)", "")
        }
        player.equipped = object
        list add (object.inventoryverbs, "Unequip")
        list remove (object.inventoryverbs, "Equip")
        object.listalias = object.listalias + " (equipped)"
        WeaponUpdate
      }
    </script>
  </command>
  <command>
    <pattern>unequip #object#</pattern>
    <script>
      if (not object = player.equipped) {
        msg ("You are not wielding it.")
      }
      else {
        msg ("You put away your spade.")
        player.equipped = null
        list add (object.inventoryverbs, "Equip")
        list remove (object.inventoryverbs, "Unequip")
        object.listalias = Replace(object.listalias, " (equipped)", "")
        WeaponUpdate
      }
    </script>
  </command>
  <turnscript name="attackturnscript">
    <enabled />
    <script>
      if (not GetBoolean(game, "notarealturn")) {
        list = NewObjectList()
        foreach (obj, GetDirectChildren(player.parent)) {
          if (HasBoolean(obj, "dead")) {
            if (not obj.dead) {
              if (HasScript(obj, "selectweapon")) {
                do (obj, "selectweapon")
              }
              if (HasObject(obj, "weapon")) {
                DoAttack (obj, obj.weapon, player, false, false)
              }
              else {
                DoAttack (obj, obj, player, false)
              }
              list add (list, obj)
            }
          }
        }
        foreach (obj, ListExclude(player.attackers, list)) {
          if (not obj.dead and RandomChance(80)) {
            obj.parent = player.parent
            msg (CapFirst(obj.alias) + " shambles into the area.")
            list add (list, obj)
          }
        }
        player.attackers = list
      }
      game.notarealturn = false
    </script>
  </turnscript>
  <command>
    <pattern>shoot #object#</pattern>
    <script><![CDATA[
      if (not HasBoolean(object, "dead")) {
        msg ("That's not something you need to shoot.")
      }
      else if (object.dead) {
        msg ("That one is already dead.")
      }
      else if (player.equipped = null) {
        msg ("You don't have a ranged weapon equipped.")
      }
      else if (not HasInt(player.equipped, "ammo")) {
        msg ("You can't shoot a " + GetDisplayAlias(player.equipped) + ".")
      }
      else if (not player.equipped.ammo > 0) {
        msg ("You aim your " + GetDisplayAlias(player.equipped) + " and pull the trigger. Click. No ammo loaded.")
      }
      else {
        DoAttack (player, player.equipped, object, true, false)
        WeaponUpdate
      }
    ]]></script>
  </command>
  <command>
    <pattern>reload #object#</pattern>
    <script><![CDATA[
      if (not HasInt(object, "ammo")) {
        msg ("You can't reload a " + GetDisplayAlias(player.equipped) + ".")
      }
      else if (player.ammo < 1) {
        msg ("You have no ammo.")
      }
      else {
        bolts = object.ammomax - object.ammo
        if (bolts > player.ammo) {
          bolts = player.ammo
        }
        player.ammo = player.ammo - bolts
        object.ammo = object.ammo + bolts
        msg ("You put " + bolts + " bolts in it.")
        WeaponUpdate
      }
    ]]></script>
  </command>
  <command>
    <pattern>search #object#</pattern>
    <script>
      if (not HasScript(object, "searchscript")) {
        msg ("There's nothing of interest there.")
      }
      else if (GetBoolean(object, "searched")) {
        msg ("You find nothing more.")
      }
      else if (not GetBoolean(object, "dead") and HasBoolean(object, "dead")) {
        msg ("That's moving too much for you to search!")
      }
      else {
        do (object, "searchscript")
        object.searched = true
      }
    </script>
  </command>
  <command name="status">
    <pattern>status</pattern>
    <script>
      msg ("Your health is " + player.hitpoints + "/" + player.maxhitpoints)
      msg ("Your energy is " + player.energy + "/" + player.maxenergy)
      msg ("Your strength is " + player.strength)
      msg ("Your agility is " + player.agility)
      msg ("Your vitality is " + player.vitality)
      msg ("Your intelligence is " + player.intelligence)
      msg ("Your armour is " + player.armour)
      msg ("Your money is " + player.money + " coins")
      msg ("Your weapon is " + player.equippedname)
      msg ("Your ammo loaded is " + player.ammonote)
      msg ("Your spare ammo is " + player.ammo)
      game.notarealturn = true
    </script>
  </command>
  <object name="Test">
    <inherit name="editor_room" />
    <object name="room">
      <inherit name="editor_room" />
      <description type="string"></description>
      <descprefix>You are in</descprefix>
      <beforefirstenter type="script">
        SpawnZombie (this)
        SpawnZombie (this)
      </beforefirstenter>
      <object name="player">
        <inherit name="editor_object" />
        <inherit name="editor_player" />
        <feature_startscript />
        <containermaxobjects>Your backpack is full!</containermaxobjects>
        <maxvolume type="int">2</maxvolume>
        <containerfullmessage>Your backpack is full!</containerfullmessage>
        <maxobjects type="int">10000</maxobjects>
        <attr name="_initialise_" type="script"><![CDATA[
          player.alias = "you"
          player.hitpoints = 250
          player.maxhitpoints = 260
          player.energy = 50
          player.maxenergy = 60
          player.damage = 5
          player.strength = 0
          player.agility = 0
          player.vitality = 0
          player.intelligence = 0
          player.armour = 0
          player.money = 10
          this.critdesc = "You attack #target# with your bare hands and get a critical (#hits# hits)."
          this.attackdesc = "You attack #target# with your bare hands and hit (#hits# hits)."
          this.missdesc = "You swing wildly and entirely miss #target#."
          player.changedhitpoints => {
            if (player.hitpoints > 0) {
              msg ("Your health is " + player.hitpoints + "/" + player.maxhitpoints)
            }
            else {
              msg ("You are dead!")
              finish
            }
          }
          player.maxhitpoints = player.maxhitpoints + player.vitality * 4
        ]]></attr>
      </object>
      <object name="spade">
        <inherit name="editor_object" />
        <listalias>spade</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = 10
          this.agility = 0
          this.critdesc = "You smash the spade down on #target# (#hits# hits)."
          this.attackdesc = "You swing the spade at #target# (#hits# hits)."
          this.missdesc = "You swing wildly and entirely miss #target#."
        </attr>
      </object>
      <object name="crossbow">
        <inherit name="editor_object" />
        <listalias>pistol</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
          <value>reload</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <look>Good for shooting zombies. Ammo: {crossbow.ammo}/{crossbow.ammomax}</look>
        <attr name="_initialise_" type="script">
          this.damage = 5
          this.agility = 0
          this.rangedamage = 15
          this.rangedagility = 3
          this.ammo = 3
          this.ammomax = 6
          this.critdesc = "A well placed shot with the crossbow on #target# (#hits# hits)."
          this.attackdesc = "You shot the crossbow at #target# (#hits# hits)."
          this.missdesc = "You shoot wildly and entirely miss #target#."
        </attr>
        <ontake type="script">
        </ontake>
      </object>
      <exit alias="east" to="safezone">
        <inherit name="eastdirection" />
        <runscript />
        <script type="script">
          player.attackers = NewObjectList()
          msg ("You slam the door, safe at last!")
          player.parent = this.to
        </script>
      </exit>
      <object name="chest">
        <inherit name="editor_object" />
        <inherit name="container_limited" />
        <feature_startscript />
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Search</value>
        </displayverbs>
        <attr name="feature_container" type="boolean">false</attr>
        <maxobjects type="int">3</maxobjects>
        <hidechildren />
        <listchildren />
        <attr name="_initialise_" type="script"><![CDATA[
          this.searchscript => {
            msg ("You found a shiny chunk of gold ore.")
            gold ore.visible = true
          }
        ]]></attr>
      </object>
      <object name="gold ore">
        <inherit name="editor_object" />
        <visible type="boolean">false</visible>
        <take />
      </object>
      <object name="rune stone">
        <inherit name="editor_object" />
        <listalias>pistol</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <look>In this stone are hidden powerful knowledge of the magic of lightning.</look>
        <attr name="_initialise_" type="script">
          this.damage = 5
          this.agility = 0
          this.runestone = 1
          this.magicdamage = 15
          this.magicagility = 3
          this.critdesc = "A well placed lighting with the rune stone on #target# (#hits# hits)."
          this.attackdesc = "You emit lightning at #target# (#hits# hits)."
          this.missdesc = "You shoot lighting wildly and entirely miss #target#."
        </attr>
        <ontake type="script">
        </ontake>
      </object>
      <object name="helmet of life">
        <inherit name="editor_object" />
        <inherit name="wearable" />
        <listalias>spade</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Wear</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <feature_wearable />
        <attr name="wear_layer" type="int">1</attr>
        <wearmsg>You put the helmet on. You recieved 10 armour and 8 max hitpoints!</wearmsg>
        <removemsg>You put the helmet off. You lost 10 armour and 8 max hitpoints!</removemsg>
        <attr name="_initialise_" type="script">
          this.armour = 10
          this.strength = 0
          this.agility = 0
          this.intelligence = 0
          this.vitality = 2
        </attr>
      </object>
      <object name="shoulders">
        <inherit name="editor_object" />
        <inherit name="wearable" />
        <listalias>spade</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Wear</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <feature_wearable />
        <attr name="wear_layer" type="int">2</attr>
        <wearmsg>You put the shoulders on. You recieved 10 armour!</wearmsg>
        <removemsg>You put the shoulders off. You lost 10 armour!</removemsg>
        <attr name="_initialise_" type="script">
          this.armour = 10
          this.strength = 0
          this.agility = 0
          this.intelligence = 0
          this.vitality = 0
        </attr>
      </object>
      <object name="breastplate">
        <inherit name="editor_object" />
        <inherit name="wearable" />
        <listalias>spade</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Wear</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <feature_wearable />
        <attr name="wear_layer" type="int">3</attr>
        <wearmsg>You put the breastplate on. You recieved 10 armour!</wearmsg>
        <removemsg>You put the breastplate off. You lost 10 armour!</removemsg>
        <attr name="_initialise_" type="script">
          this.armour = 10
          this.strength = 0
          this.agility = 0
          this.intelligence = 0
          this.vitality = 0
        </attr>
      </object>
      <object name="gloves">
        <inherit name="editor_object" />
        <inherit name="wearable" />
        <listalias>spade</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Wear</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <feature_wearable />
        <attr name="wear_layer" type="int">4</attr>
        <wearmsg>You put the gloves on. You recieved 10 armour!</wearmsg>
        <removemsg>You put the gloves off. You lost 10 armour!</removemsg>
        <attr name="_initialise_" type="script">
          this.armour = 10
          this.strength = 0
          this.agility = 0
          this.intelligence = 0
          this.vitality = 0
        </attr>
      </object>
      <object name="leggins">
        <inherit name="editor_object" />
        <inherit name="wearable" />
        <listalias>spade</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Wear</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <feature_wearable />
        <attr name="wear_layer" type="int">5</attr>
        <wearmsg>You put the leggins on. You recieved 10 armour!</wearmsg>
        <removemsg>You put the leggins off. You lost 10 armour!</removemsg>
        <attr name="_initialise_" type="script">
          this.armour = 10
          this.strength = 0
          this.agility = 0
          this.intelligence = 0
          this.vitality = 0
        </attr>
      </object>
      <object name="boots">
        <inherit name="editor_object" />
        <inherit name="wearable" />
        <listalias>spade</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Wear</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <feature_wearable />
        <attr name="wear_layer" type="int">6</attr>
        <wearmsg>You put the boots on. You recieved 10 armour!</wearmsg>
        <removemsg>You put the boots off. You lost 10 armour!</removemsg>
        <attr name="_initialise_" type="script">
          this.armour = 10
          this.strength = 0
          this.agility = 0
          this.intelligence = 0
          this.vitality = 0
        </attr>
      </object>
      <object name="amulet of intelligence">
        <inherit name="editor_object" />
        <inherit name="wearable" />
        <listalias>spade</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Wear</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <feature_wearable />
        <attr name="wear_layer" type="int">7</attr>
        <wearmsg>You put the amulet of intelligence on. You recieved 5 intelligence!</wearmsg>
        <removemsg>You put the amulet of intelligence off. You lost 5  intelligence!</removemsg>
        <attr name="_initialise_" type="script">
          this.armour = 0
          this.strength = 0
          this.agility = 0
          this.intelligence = 5
          this.vitality = 0
        </attr>
      </object>
      <object name="ring of strength">
        <inherit name="editor_object" />
        <inherit name="wearable" />
        <listalias>spade</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Wear</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <feature_wearable />
        <attr name="wear_layer" type="int">8</attr>
        <wearmsg>You put the ring of strength on. You recieved 5 strength!</wearmsg>
        <removemsg>You put the ring of strength off. You lost 5 strength!</removemsg>
        <attr name="_initialise_" type="script">
          this.armour = 0
          this.strength = 5
          this.agility = 0
          this.intelligence = 0
          this.vitality = 0
        </attr>
      </object>
      <object name="bracelet of agility">
        <inherit name="editor_object" />
        <inherit name="wearable" />
        <listalias>spade</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Wear</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <feature_wearable />
        <attr name="wear_layer" type="int">9</attr>
        <wearmsg>You put the bracelet of agility on. You recieved 5 agility!</wearmsg>
        <removemsg>You put the  bracelet of agility off. You lost 5 agility!</removemsg>
        <attr name="_initialise_" type="script">
          this.armour = 0
          this.strength = 0
          this.agility = 5
          this.intelligence = 0
          this.vitality = 0
        </attr>
      </object>
      <object name="Shiny emerald">
        <inherit name="editor_object" />
        <inherit name="wearable" />
        <listalias>spade</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Wear</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <feature_wearable />
        <attr name="wear_layer" type="int">10</attr>
        <wearmsg>You put the shiny emerald into your pocket. You recieved 1 strength, intelligence, agility and vitality!</wearmsg>
        <removemsg>You put the shiny emerald out of your pocket. You lost 1 strength, intelligence, agility and vitality!</removemsg>
        <attr name="_initialise_" type="script">
          this.armour = 0
          this.strength = 1
          this.agility = 1
          this.intelligence = 1
          this.vitality = 1
        </attr>
      </object>
      <object name="Teleport1">
        <inherit name="editor_object" />
        <drop type="boolean">false</drop>
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Teleport to end</value>
        </displayverbs>
        <inventoryverbs type="stringlist" />
        <teleporttoend type="script">
          MoveObject (player, safezone5)
          player.attackers = NewObjectList()
        </teleporttoend>
      </object>
      <object name="wooden shield">
        <inherit name="editor_object" />
        <inherit name="wearable" />
        <listalias>spade</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Wear</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <feature_wearable />
        <attr name="wear_layer" type="int">11</attr>
        <wearmsg>You put the wooden shield on. You recieved 20 armour!</wearmsg>
        <removemsg>You put the wooden shield offt. You lost 20 armour!</removemsg>
        <attr name="_initialise_" type="script">
          this.armour = 20
          this.strength = 0
          this.agility = 0
          this.intelligence = 0
          this.vitality = 0
        </attr>
      </object>
    </object>
    <object name="safezone">
      <inherit name="editor_room" />
      <exit alias="west" to="room">
        <inherit name="westdirection" />
        <runscript />
        <script type="script">
          player.attackers = NewObjectList()
          msg ("You slam the door, safe at last!")
          player.parent = this.to
        </script>
      </exit>
      <object name="dwarven pie">
        <inherit name="editor_object" />
        <take />
        <look>Favorite dwarf's pie, stuffed with gravel and sandstone. Hard as stone. Restore 15 HP, when eaten.</look>
        <eat type="script"><![CDATA[
          msg ("You eat the dwarven pie, receiving 15 health.")
          if (player.hitpoints + 15 > player.maxhitpoints) {
            player.hitpoints = player.maxhitpoints
          }
          else {
            player.hitpoints = player.hitpoints + 15
          }
          this.parent = null
        ]]></eat>
        <ontake type="script">
        </ontake>
      </object>
      <object name="strong beer">
        <inherit name="editor_object" />
        <take />
        <look>Strong dwarven beer from underground wheat and a special mix of mushrooms.</look>
        <drink type="script">
          msg ("You drink strong dwarven beer. Your strength increased by 5!")
          player.strength = player.strength + 5
          msg ("Your strength now " + player.strength)
          this.parent = null
        </drink>
        <ontake type="script">
        </ontake>
      </object>
      <object name="healthy mushroom">
        <inherit name="editor_object" />
        <take />
        <look>Mushroom with a large shiny hat of orange color, in white speckles.</look>
        <eat type="script">
          msg ("You eat the orange mushroom, receiving 5 vitality!")
          player.vitality = player.vitality + 5
          msg ("Your vitality now " + player.vitality)
          this.parent = null
          player.maxhitpoints = player.maxhitpoints + player.vitality * 4
        </eat>
        <ontake type="script">
        </ontake>
      </object>
      <object name="root of Wisdom">
        <inherit name="editor_object" />
        <take />
        <look>Matte white root with sparkling blue veins. Restores 10 energy, when eaten.</look>
        <eat type="script"><![CDATA[
          msg ("You eat the strange root, restoring 10 energy.")
          if (player.energy + 10 > player.maxenergy) {
            player.energy = player.energy
          }
          else {
            player.energy = player.energy + 10
          }
          this.parent = null
          msg ("Your energy is " + player.energy + "/" + player.maxenergy)
        ]]></eat>
        <ontake type="script">
        </ontake>
      </object>
      <exit alias="east" to="safezone2">
        <inherit name="eastdirection" />
      </exit>
    </object>
    <object name="safezone2">
      <inherit name="editor_room" />
      <exit alias="west" to="safezone">
        <inherit name="westdirection" />
      </exit>
      <exit alias="east" to="safezone3">
        <inherit name="eastdirection" />
      </exit>
    </object>
    <object name="safezone3">
      <inherit name="editor_room" />
      <exit alias="west" to="safezone2">
        <inherit name="westdirection" />
      </exit>
      <exit alias="east" to="safezone4">
        <inherit name="eastdirection" />
      </exit>
    </object>
    <object name="safezone4">
      <inherit name="editor_room" />
      <exit alias="west" to="safezone3">
        <inherit name="westdirection" />
      </exit>
      <exit alias="east" to="safezone5">
        <inherit name="eastdirection" />
      </exit>
    </object>
    <object name="safezone5">
      <inherit name="editor_room" />
      <object name="Teleport2">
        <inherit name="editor_object" />
        <drop type="boolean">false</drop>
        <displayverbs type="stringlist">
          <value>Look at</value>
          <value>Teleport to start</value>
        </displayverbs>
        <inventoryverbs type="stringlist" />
        <teleporttostart type="script">
          MoveObject (player, room)
          player.attackers = NewObjectList()
        </teleporttostart>
      </object>
      <exit alias="west" to="safezone4">
        <inherit name="westdirection" />
      </exit>
      <object name="Crate">
        <inherit name="editor_object" />
        <inherit name="container_limited" />
        <displayverbs type="stringlist">
          <value>Look at</value>
        </displayverbs>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
        </inventoryverbs>
        <feature_container />
        <maxobjects type="int">3</maxobjects>
        <attr name="feature_usegive" type="boolean">false</attr>
      </object>
    </object>
  </object>
  <command>
    <pattern>cast #object#</pattern>
    <script><![CDATA[
      if (not HasBoolean(object, "dead")) {
        msg ("That's not something you need to cast.")
      }
      else if (object.dead) {
        msg ("That one is already dead.")
      }
      else if (player.equipped = null) {
        msg ("You don't have a rune weapon equipped.")
      }
      else if (not HasInt(player.equipped, "runestone")) {
        msg ("You can't cast a " + GetDisplayAlias(player.equipped) + ".")
      }
      else if (not player.energy > 0) {
        msg ("You aim your " + GetDisplayAlias(player.equipped) + " and try to cast. T-s-s-s. You have no energy left.")
      }
      else {
        DoAttack (player, player.equipped, object, false, true)
        WeaponUpdate
        msg ("Your energy is " + player.energy + "/" + player.maxenergy)
      }
    ]]></script>
  </command>
  <object name="Code">
    <inherit name="editor_room" />
    <object name="treasureroom">
      <inherit name="editor_room" />
      <object name="Pick">
        <inherit name="editor_object" />
        <listalias>Pick</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = 15
          this.agility = 0
          this.critdesc = "You smash the pick down on #target# (#hits# hits)."
          this.attackdesc = "You swing the pick at #target# (#hits# hits)."
          this.missdesc = "You swing wildly and entirely miss #target# with your pick."
        </attr>
      </object>
      <object name="Axe">
        <inherit name="editor_object" />
        <listalias>Axe</listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = 15
          this.agility = 0
          this.critdesc = "You smash the axe down on #target# (#hits# hits)."
          this.attackdesc = "You swing the axe at #target# (#hits# hits)."
          this.missdesc = "You swing wildly and entirely miss #target# with your axe."
        </attr>
      </object>
    </object>
    <object name="monsterattacks">
      <inherit name="editor_room" />
      <object name="vomitattack">
        <inherit name="editor_object" />
        <listalias type="string"></listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = 10
          this.agility = 0
          this.critdesc = "#Attacker# spews noxious vomit all over you (#hits# hits)."
          this.attackdesc = "#Attacker# vomits over you (#hits# hits)."
          this.missdesc = "You narrowly avoid the foul vomit from #attacker#."
        </attr>
      </object>
      <object name="vomitreadying">
        <inherit name="editor_object" />
        <listalias type="string"></listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = 0
          this.agility = -100
          this.critdesc = ""
          this.attackdesc = ""
          this.missdesc = "#Attacker#'s abdomen is gurgling alarmingly."
        </attr>
      </object>
      <object name="talonattack">
        <inherit name="editor_object" />
        <listalias type="string"></listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = 8
          this.agility = 0
          this.critdesc = "#Attacker# strikes you with a monstrous blow (#hits# hits)."
          this.attackdesc = "#Attacker# scratch you by claws (#hits# hits)."
          this.missdesc = "You barely avoid the clawed hand from #attacker#."
        </attr>
      </object>
      <object name="kickattack">
        <inherit name="editor_object" />
        <listalias type="string"></listalias>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>equip</value>
          <value>Drop</value>
        </inventoryverbs>
        <feature_startscript />
        <take />
        <attr name="_initialise_" type="script">
          this.damage = 8
          this.agility = 0
          this.critdesc = "#Attacker# furiously kicks you in leg (#hits# hits)."
          this.attackdesc = "#Attacker# kicks you (#hits# hits)."
          this.missdesc = "You faintly avoid the kick from #attacker#."
        </attr>
      </object>
    </object>
  </object>
  <verb>
    <property>teleporttostart</property>
    <pattern>teleport to start</pattern>
    <defaultexpression>"You can't teleport to start " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>teleporttoend</property>
    <pattern>teleport to end</pattern>
    <defaultexpression>"You can't teleport to end " + object.article + "."</defaultexpression>
  </verb>
  <verb>
    <property>put</property>
    <pattern>put</pattern>
    <defaultexpression>"You can't put " + object.article + "."</defaultexpression>
  </verb>
  <function name="_DoWear" parameters="object" type="boolean"><![CDATA[
    // Is this possible?
    if (not HasAttribute(object,"worn") or not HasAttribute(object,"wear_slots")) {
      // No, not a garment
      msg (DynamicTemplate("WearUnsuccessful", object))
      return (false)
    }
    if (object.parent = game.pov and object.worn = true) {
      // No, already worn
      msg (DynamicTemplate("AlreadyWearing", object))
      return (false)
    }
    if (not ListContains(ScopeInventory(), object)) {
      // No, not held
      msg (DynamicTemplate("CannotWearIfNotHeld", object))
      return (false)
    }
    // Are other worn garments in the way?
    obj = _GetOuterForGarment(game.pov, object)
    if (not obj = null) {
      if (obj.wear_layer > object.wear_layer or obj.wear_layer = 0 or object.wear_layer = 0) {
        msg (DynamicTemplate("CannotWearOver", obj))
        return (false)
      }
      if (obj.wear_layer = object.wear_layer) {
        msg (DynamicTemplate("CannotWearWith", obj))
        return (false)
      }
    }
    if (not TestGarment(object)) {
      return (false)
    }
    WearGarment (object)
    if (object.wearmsg = null) {
      {
        {
          {
            {
              {
                {
                  {
                    {
                      {
                        {
                          {
                            {
                              P (DynamicTemplate("WearSuccessful",object)
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    else {
      P (object.wearmsg)
      player.armour = player.armour + object.armour
      player.strength = player.strength + object.strength
      player.intelligence = player.intelligence + object.intelligence
      player.maxhitpoints = player.maxhitpoints + player.vitality * 4 + object.vitality *4
      player.vitality = player.vitality + object.vitality
      player.agility = player.agility + object.agility
    }
    // do after
    if (HasScript(object, "onafterwear")) {
      do (object, "onafterwear")
    }
    else if (HasString(object, "onafterwear")) {
      P (object.onafterwear)
    }
    AfterWear
    return (true)
  ]]></function>
  <function name="_DoRemove" parameters="object" type="boolean"><![CDATA[
    if (not ListContains(GetAllChildObjects(game.pov), object)) {
      msg (DynamicTemplate("CannotRemoveIfNotHeld", object))
      return (false)
    }
    if (not GetBoolean(object, "worn")) {
      msg (DynamicTemplate("CannotRemoveIfNotWearing", object))
      return (false)
    }
    if (not GetBoolean(object, "removeable")) {
      if (HasString(object, "notremoveablemessage")) {
        msg (object.notremoveablemessage)
      }
      else {
        msg (DynamicTemplate("NotRemovable", object))
      }
      return (false)
    }
    if (HasInt(game.pov, "maxobjects")) {
      if (ListCount(GetAllChildObjects(game.pov)) >= game.pov.maxobjects) {
        msg (DynamicTemplate("MaxObjectsInInventory", object))
        return (false)
      }
    }
    obj = _GetOuterForGarment(game.pov, object)
    if (not obj = null) {
      if (obj.wear_layer > object.wear_layer) {
        msg (DynamicTemplate("RemoveFirst", obj))
        return (false)
      }
    }
    if (not TestRemove(object)) {
      return (false)
    }
    RemoveGarment (object)
    if (object.removemsg = null) {
      P (DynamicTemplate("RemoveSuccessful",object))
    }
    else {
      P (object.removemsg)
      player.armour = player.armour - object.armour
      player.strength = player.strength - object.strength
      player.intelligence = player.intelligence - object.intelligence
      player.vitality = player.vitality - object.vitality
      player.maxhitpoints = player.maxhitpoints + player.vitality * 4 - object.vitality *4
      player.agility = player.agility - object.agility
    }
    // do after
    if (HasScript(object, "onafterremove")) {
      do (object, "onafterremove")
    }
    else if (HasString(object, "onafterremove")) {
      P (object.onafterremove)
    }
    AfterRemove
    return (true)
  ]]></function>
  <function name="SpawnZombie" parameters="room"><![CDATA[
    if (HasInt(game, "crittercount")) {
      game.crittercount = game.crittercount + 1
    }
    else {
      game.crittercount = 1
    }
    create ("critter" + game.crittercount)
    obj = GetObject("critter" + game.crittercount)
    obj.parent = room
    obj.displayverbs = Split("Look at;Attack;Shoot;Cast", ";")
    obj.dead = false
    obj.changedhitpoints => {
      if (this.hitpoints < 1) {
        msg ("It is dead!")
        this.dead = true
        this.displayverbs = Split("Look at;Search", ";")
      }
    }
    names = Split("decipit;decomposing;shambling;disgusting;filthy;falling-apart", ";")
    obj.alias = StringListItem(names, game.crittercount % ListCount(names)) + " zombie"
    obj.listalias = CapFirst(obj.alias)
    obj.look = ProcessText("A " + obj.alias + ", {random:covered in maggots:missing an arm:with one eye hanging out}" + " {colour:#FFFFB5:(@@@open@@@" + obj.name + ".hitpoints@@@close@@@/20 HP)}")
    obj.hitpoints = 20
    obj.damage = 10
    obj.agility = 0
    obj.strength = 0
    obj.vitality = 0
    obj.intelligence = 0
    obj.armour = 0
    obj.devastdesc = "A devastating blow by #attacker# sends you reeling (#hits# hits)."
    obj.critdesc = "A well-placed blow by #attacker# sends you reeling (#hits# hits)."
    obj.attackdesc = "#Attacker# has hit you (#hits# hits)."
    obj.weakdesc = "#Attacker# has hit you slightly (#hits# hits)."
    obj.missdesc = "{random:#Attacker# attacks you and <b>misses1</b>:#Attacker# attacks you and <b>misses2</b>:#Attacker# attacks you and <b>misses3</b>}"
    obj.selectweapon => {
      if (this.weapon = vomitreadying) {
        this.weapon = vomitattack
      }
      else {
        this.weapon = GetObject(PickOneString("vomitreadying;talonattack;kickattack;talonattack;kickattack"))
      }
    }
    obj.searchscript => {
      money = GetRandomInt(1, 50)
      msg ("You find " + DisplayMoney(money) + ".")
      player.money = player.money + money
      if (RandomChance (50) = true) {
        o = PickOneChild(treasureroom)
        msg ("You also find " + GetDisplayName(o) + ".")
        CloneObjectAndMoveHere (o)
      }
    }
  ]]></function>
  <function name="DoAttack" parameters="attacker, weapon, target, rangearm, magicarm"><![CDATA[
    if (rangearm) {
      damageatt = "rangedamage"
      attackatt = "rangedagility"
      weapon.ammo = weapon.ammo - 1
    }
    else if (magicarm) {
      damageatt = "magicdamage"
      attackatt = "magicagility"
      player.energy = player.energy - 1
    }
    else {
      damageatt = "damage"
      attackatt = "attack"
    }
    roll = GetRandomInt(1, 60) + weapon.agility + attacker.agility
    damage = weapon.damage - target.armour + attacker.strength
    if (damage < 1) {
      damage = 1
    }
    if (roll > 80) {
      damage = damage * 3
      AttackReport (weapon.critdesc, attacker, target, damage)
      target.hitpoints = target.hitpoints - damage
    }
    else if (roll > 60) {
      damage = damage * 2
      AttackReport (weapon.critdesc, attacker, target, damage)
      target.hitpoints = target.hitpoints - damage
    }
    else if (roll > 40) {
      AttackReport (weapon.attackdesc, attacker, target, damage)
      target.hitpoints = target.hitpoints - damage
    }
    else if (roll > 20) {
      damage = damage * 0.5
      AttackReport (weapon.attackdesc, attacker, target, damage)
      target.hitpoints = target.hitpoints - damage
    }
    else {
      AttackReport (weapon.missdesc, attacker, target, 0)
    }
  ]]></function>
  <function name="WeaponUpdate">
    if (player.equipped = null) {
      player.equippedname = "bare hands"
      player.ammonote = "-"
    }
    else {
      player.equippedname = Replace (player.equipped.listalias, " (equipped)", "")
      if (not HasAttribute(player.equipped, "ammo")) {
        player.ammonote = "-"
      }
      else {
        player.ammonote = player.equipped.ammo + "/" + player.equipped.ammomax
      }
    }
  </function>
  <function name="AttackReport" parameters="s, attacker, target, hits">
    s = Replace(s, "#Attacker#", CapFirst(GetDisplayAlias(attacker)))
    s = Replace(s, "#attacker#", GetDisplayAlias(attacker))
    s = Replace(s, "#Target#", CapFirst(GetDisplayAlias(target)))
    s = Replace(s, "#target#", GetDisplayAlias(target))
    s = Replace(s, "#hits#", "" + hits)
    msg (s)
  </function>
</asl>

Would appreciate any help!


ah.. a storage system! hehe :D


conceptually:

think of Objects as like "folders", how does folder organization and management work?

(this 'storage' Object is either: separate from your 'inventory', NOT within the currently controlled Player Object, or contained within your 'inventory', within the currently controlled Player Object, or there's a storage object for each of your Player Objects, contained within each of their inventories, aka within those Player Objects)

storage
-> item storage
->-> consumable item storage
->->-> normal consumable item storage
->->-> battle consumable item storage
->->-> interior consumable item storage
->->-> exterior consumable item storage
->-> non-consumable storage
-> equipment storage
->-> weapon equipment storage
->->-> melee weapon equipment storage
->->->-> sword melee weapon equipment storage
->->->->-> katana object
->->->->-> claymore object
->->->->-> short sword object
->->->->-> long sword object
->->->->-> broad sword object
->->->-> axe melee weapon equipment storage
->->-> projectile weapon equipment storage
->-> armor equipment storage
->-> clothing equipment storage
-> spell storage
->-> fire spell storage
->-> water spell storage
->-> air spell storage
->-> earth spell storage
-> ability storage

also, give your individual Objects a 'type_of_object' (or whatever you want to name/label it as) String Attribute (and/or you can also use the: Object Types / Types / Inherited Attributes / DoesInherit, as well), so you can match them up to the the correct type of storage object, for example:

// a simple brief coding example only:

// create ("katana")
// katana.type_of_object = "sword"

// create ("lance")
// katana.type_of_object = "spear"

// stringlist_variable = split ("katana;lance", ";")
// string_variable = StringListItem (stringlist_variable, GetRandomInt (0,1))
// object_parameter = GetObject (string_variable)

if (object_parameter.type_of_object = "sword") {
  object_parameter.parent = sword_melee_weapon_equiptment_storage_object
} else if (object_parameter.type_of_object = "spear") {
  object_parameter.parent = spear_melee_weapon_equiptment_storage_object
}

now, what are the various actions involved?

searching
checking
creating
viewing
depositing (storing)
withdrawing (removing)
dropping
deleting
sorting
cloning

make/use the 'Command' Element for your actions, or you can add Verbs to individual Objects too


you can read up (google) on:

'programming: data structure and management' if you want to get into much more advanced coding designs...


I'll see if you can do this on your own.... but if not... we'll help you out


Thank you, hegemonkhan.

Well... I done commands which adds and extracts objects from crate, if you are in zone with crate and if in crate is still left some room/or this item is located in crate.

But what I cannot understand - how can I disable normal "take" verb from things, when they are in crate. Because if player will use normal "take" verb, crate will think, that object that was taken, still occupies some place in it, and this will ruin the whole system, sooner or later, because there will be no place left in crates.

Now I will post my code on GitHub, because it's pretty big now.

Code: https://gist.github.com/Goldo-Golderson/8f6fd47ca6b5dc6b97215f3f2662f76a

Would appreciate any help.


I think I must be missing something. The code you posted has an object, 'Crate', which the player can put things into and take them out again.

What else are you trying to do?


For taking things from Crate, player need to use special command "get #object# from crate", which reduses count of "objects" in crate. But when he click on the things in the crate, there is a normal verb "take", which is not reduses count of "objects" in Crate. This means, what crate will be owercrowded, if player will accidentally use the vrong verb "take #object#", instead of "get #object# from crate".

How can I avoid that sort of thing? For example, remove verb "take" from objects, that currently in crate?

I am talking about these strings

        <maxobjects type="int">3</maxobjects>
        <objects type="int">0</objects>

and these

      if (Crate.objects + 1 > 3) {
        msg ("You cannot put " + object.name + " to storage. It is full.")
      }
      else if (game.pov.parent = safezone5) {
        object.parent = Crate
        msg ("You put " + object.name + " to storage.")
        Crate.objects = Crate.objects + 1

and these

      else if (Contains (Crate, object)) {
        msg ("You took " + object.name + " from storage.")
        object.parent = player
        Crate.objects = Crate.objects - 1

the 'Verbs' are actually Script Attributes (with some additional coding to make them have their 'Verb' functionality), and the operating list of Verbs for an Object is controlled by:

the built-in 'displayverbs' and/or 'inventoryverbs' String List Attributes

so, you just add/remove the 'Verb' items from these lists as you desire/need


Pixie's great guides on Verbs, displayverbs, and inventoryverbs:

http://docs.textadventures.co.uk/quest/using_verbs.html

http://docs.textadventures.co.uk/quest/display_verbs.html (displayverbs and inventoryverbs are the same thing: inventoryverbs is merely for when the object is in the inventory: when the object is contained within the currently controlled Player Object, and displayverbs is when its not)


also, I believe that built-into quest is functionality for handling 'take' and 'drop', in that you can set their built-in Booleans to enable/disable them as well, for example:

book.take = true // the 'take' functionality for the 'book' Object is enabled
book.take = false // the 'take' functionality for the 'book' Object is disabled

book.drop = true // the 'drop' functionality for the 'book' Object is enabled
book.drop = false // the 'drop' functionality for the 'book' Object is disabled


ask if you need help with anything


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums