Trouble with changing attributes on inventory objects

When I update the ammo attribute on an object during an attack, and then try to update the alias of that object to show lower ammo in inventory, it's showing "0 ammo" instead of the amount of Ammo that the object has after everything is done running.

Or maybe the system is working well enough that the weapon functions as if it's getting loaded properly, but the "ammo" on the object being loaded into it is changing to 0 instead of incrementing down each attack?

I've been working a system within Pixie's CombatLib to deal with using ammo in the weapons. The library has a built in method of refusing to let the player attack if the weapon has 0 for its ammo attribute. But that was essentially it. So i created ranged weapon types and ammo types that have ammo attributes. I also use a system of Booleans to help recognize how to treat the different sub-types in the scripts. (the difference between something like a gun, a bow, or a wand).

But I can't seem to track down what's wrong to make the new alias in inventory show an unexpected 0 instead of what I think the ammo amount for the ammo object is.

The attack script that begins all of the changes is Pixie's built-in one, but I've added to the system by modifying what happens for "OutofAmmo()" and also added a "FireRangedWeapon()" function. These two calls in the attack script work together with attributes and scripts on the rangedweapon and ammo types.

For Firearms and Wand/Rods there's a different system of replenishing the ammo, the player must use a "load" command. That seems to work fine with updating the inventory, and I think it's because of how commands function differently with the inventory than how scripts run during a turnscript work.

If it helps, here's what my changed code currently looks like:

This doattack script on a monster runs when the player types "attack monster"

    <doattack type="script"><![CDATA[
      if (OutOfAmmo()) {
        do (this, "outofammo")
      }
      else if (this.dead) {
        // s = GetDisplayAlias(this)
        // msg("The " + Mid(s, 1, LengthOf(s) - 7) + " is already dead.")
        msg ("The " + GetDisplayAlias(this) + " is already dead.")
      }
      else {
        if (DoesInherit(game.pov.equipped, "rangedweapon")) {
          FireRangedWeapon
        }
        SneakUpdate (5)
        do (this, "settoattack")
        attackroll = GetRandomInt (1, 20) + GetAttack(this)
        if (this.noncorporeal and GetElement(game.pov.equipped) = null) {
          if (game.pov.equipped.nonweapon) {
            msg ("You attack the " + GetDisplayAlias(this) + ", and pass straight through it!")
          }
          else {
            msg ("You swing your " + GetDisplayAlias(game.pov.equipped) + " and it goes straight through the " + GetDisplayAlias(this) + "!")
          }
        }
        else if (attackroll > 10) {
          damage = GetDamage (game.pov.equipped, game.pov.strength / 2 + this.temp_damage + game.pov.damagebonus, this)
          this.hitpoints = this.hitpoints - damage
          if (this.hitpoints > 0) {
            if (game.pov.equipped.nonweapon) {
              msg ("You attack and hit, doing " + damage + " points of damage (" + this.hitpoints + " hits left). " + this.hurtbyweapon)
            }
            else {
              msg (this.temp_desc + " " + GetDisplayAlias(game.pov.equipped) + " and hit, doing " + damage + " points of damage (" + this.hitpoints + " hits left). " + this.hurtbyweapon)
            }
            if (HasScript(this, "onweaponhit")) {
              do (this, "onweaponhit")
            }
            if (HasObject(game.pov.equipped, "venom")) {
              if (this.poisonimmunity) {
                if (HasString(this, "poisonimmunitymsg")) {
                  msg (this.poisonimmunitymsg)
                }
                else {
                  msg ("The " + GetDisplayAlias(this) + " is immune to your blade venom.")
                }
              }
              else {
                game.pov.target = this
                do (game.pov.equipped.venom, "effect")
              }
              game.pov.equipped.venom = null
            }
          }
          else {
            if (game.pov.equipped.nonweapon) {
              msg ("You attack and hit, doing " + damage + " points of damage. " + this.death)
            }
            else {
              msg (this.temp_desc + " " + GetDisplayAlias(game.pov.equipped) + " and hit, doing " + damage + " points of damage. " + this.death)
            }
            do (this, "makedead")
          }
        }
        else {
          if (game.pov.equipped.nonweapon) {
            msg ("You attack and miss.")
          }
          else {
            msg ("You swing your " + GetDisplayAlias(game.pov.equipped) + " and miss.")
          }
        }
        if (HasObject(game.pov, "secondary_attack")) {
          do (this, "secondaryattack")
        }
      }
    ]]></doattack>

So the FireRangedWeapon() is very simple


  <function name="FireRangedWeapon">
    game.pov.equipped.ammo = game.pov.equipped.ammo - 1
  </function>

The ammo in player inventory is


    <object name="arrows">
      <inherit name="editor_object" />
      <inherit name="ammo" />
      <feature_combat />
      <ammo type="int">4</ammo>
      <take />
      <takemsg>You pick up the ammunition</takemsg>
      <dropmsg>You drop the ammunition</dropmsg>
      <feature_usegive />
      <use type="boolean">false</use>
      <firearmammo type="boolean">false</firearmammo>
      <alias>arrows</alias>
      <magicammo type="boolean">false</magicammo>
      <bowammo />
      <selfuseanything type="script">
        if (HasAttribute(obj, "ammo")) {
          obj.ammo = obj.ammo + this.ammo
        }
        else {
          msg ("Try using your ammo in a ranged weapon...")
        }
      </selfuseanything>
      <changedammo type="script">
        if (not GetBoolean(this, "magicammo")) {
          firsttime {
            this.oldalias = this.alias
            this.newalias = this.ammo + " " + this.oldalias
            SetAlias (this, this.newalias)
          }
          otherwise {
            this.newalias = this.ammo + " " + this.oldalias
            SetAlias (this, this.newalias)
          }
        }
      </changedammo>
      <selfuseon type="scriptdictionary">
        <item key="player">
          msg ("You can't use the ammo on yourself, silly.  Try using it in a ranged weapon...")
        </item>
      </selfuseon>
      <visible />
    </object>
  </object>

And the weapon being used in the attack is


    <object name="Bow">
      <inherit name="rangedweapon" />
      <price type="int">5</price>
      <feature_combat />
      <scenery type="boolean">false</scenery>
      <ammo type="int">1</ammo>
      <nonweapon />
      <bowweapon />
      <projectileweapon type="boolean">false</projectileweapon>
      <firearm type="boolean">false</firearm>
      <magicchargedweapon type="boolean">false</magicchargedweapon>
      <maxammo type="int">3</maxammo>
    </object>

and the rangedweapon type is


  <type name="rangedweapon">
    <inherit name="editor_object" />
    <inherit name="weapon" />
    <feature_combat />
    <price type="int">1</price>
    <attacktype>Arrow</attacktype>
    <nonweapon type="boolean">false</nonweapon>
    <ammo type="int">0</ammo>
    <bowweapon type="boolean">false</bowweapon>
    <projectileweapon type="boolean">false</projectileweapon>
    <firearm type="boolean">false</firearm>
    <magicchargedweapon type="boolean">false</magicchargedweapon>
    <outofammo type="script"><![CDATA[
      if (GetBoolean(this, "bowweapon")) {
        foreach (obj, ScopeInventory()) {
          if (GetBoolean(obj, "bowammo")) {
            obj = obj
            if (obj.ammo > 0) {
              obj.ammo = obj.ammo -1
              this.ammo = this.ammo +1
            }
          }
          else {
            msg ("Your " + GetDisplayAlias(game.pov.equipped) + " has nothing left to fire!")
          }
        }
      }
      else if (GetBoolean(this, "projectileweapon")) {
        msg ("There's nothing you can shoot from your " + GetDisplayAlias(game.pov.equipped) + " !")
      }
      else if (GetBoolean(this, "firearm")) {
        msg ("Your " + GetDisplayAlias(game.pov.equipped) + " is out of ammo!")
      }
      else if (GetBoolean(this, "magicchargedweapon")) {
        msg ("Your " + GetDisplayAlias(game.pov.equipped) + " is out of charges!")
      }
      else {
        msg ("Your " + GetDisplayAlias(game.pov.equipped) + " is empty!")
      }
    ]]></outofammo>
    <changedammo type="script"><![CDATA[
      if (GetBoolean(this, "bowweapon")) {
        foreach (obj, ScopeInventory()) {
          if (GetBoolean(obj, "bowammo")) {
            obj = obj
            if (obj.ammo > 0) {
              obj.ammo = obj.ammo -1
              this.ammo = this.ammo +1
            }
            else {
            }
          }
          else {
          }
        }
        if (this.ammo = 0) {
          msg ("You fire your last shot from your " + GetDisplayAlias(game.pov.equipped) + " !")
        }
      }
      else if (GetBoolean(this, "projectileweapon")) {
        msg ("There's nothing you can shoot from your " + GetDisplayAlias(game.pov.equipped) + " !")
        foreach (obj, ScopeInventory()) {
          if (GetBoolean(obj, "projectileammo")) {
            if (obj.ammo > 0) {
              obj.ammo = obj.ammo - 1
              this.ammo = this.ammo +1
            }
            else {
              RemoveObject (obj)
            }
          }
          else {
          }
        }
        if (this.ammo = 0) {
          msg ("You have nothing left to use with your " + GetDisplayAlias(game.pov.equipped) + " !")
        }
      }
      else if (GetBoolean(this, "firearm")) {
        if (this.ammo = 0) {
          msg ("Your " + GetDisplayAlias(game.pov.equipped) + " is out of ammo!")
        }
      }
      else if (GetBoolean(this, "magicchargedweapon")) {
        if (this.ammo = 0) {
          msg ("Your " + GetDisplayAlias(game.pov.equipped) + " is out of charges!")
        }
      }
      else {
        if (this.ammo = 0) {
          msg ("Your " + GetDisplayAlias(game.pov.equipped) + " is empty!")
        }
      }
    ]]></changedammo>
  </type>

Can anyone tell what might be wrong here? The changed ammo scripts and outofammo scripts in this scenario should subtract one from the arrows in inventory and then change the alias to "3 arrows" the first time, then "2 arrows" etc. But for some reason it changes it once to "0 arrows" and stays that way until the weapon is completely empty. I also wanted a "remove item" added to take the arrows away once the ammo in them was zero, but that was removing them on first fire. Yet the attacks worked as if they were still there until all the rounds depleted and then gave the correct empty message.

Please and thanks for any help or advice.


I figured it all out!

I was pretty foolish having changedammo change the ammo... doh! It cycled through until the ammo was at zero, and gave the last result for having run out upon the first use. That's what the main issue was. I scoured my code for way too long looking for "ammo" and trying to find where the math went wrong on the attribute, without seeing that I'd created a loop. thank goodness it terminated when the ammo changed to zero, or else it the game would still be running an endless cycle of subtracting ammo from the ammo and adding ammo to the rangedweapon!

Another issue is that I had things inside the foreach that didn't need to be, because I didn't know how to reference the found object for other scripts. Solved that by creating an object attribute ammosource for game.pov.equipped which will be set depending upon what's going on.

I rearranged the system a bit, and got it doing exactly what I want now. If anyone is curious, just let me know before this topic expires haha. Or message me and I'll share what I've got.


Log in to post a reply.

Support

Forums