Status Attributes

I've not been here that long; but I've noticed more than a few threads from people having problems with statusattributes. Mostly because people do something that seems intuitive, but doesn't actually work.

And it seems to me that if if it could be made so that the "obvious" behaviour actually worked, that would save a lot of people some trouble. Maybe something like this.

Modifications made:

  • If the value in the statusattributes dictionary doesn't have a ! in it, add " !" to the end. Because an entry in the statusattributes pane that doesn't display its value is pretty useless.
    • Exception: If the attribute is a boolean true, display it as it is. If false, hide the line.
  • If the key in the statusattributes dictionary is "player.hitpoints" or similar, behave sensibly. It's very unlikely that anyone intended to specify an attribute name with a dot in.
    • The script I've used here will behave oddly if you give it a key like "game.player.attack.hitpoints" - making it behave sensibly in these cases would take more code; and I can think of a couple of edge cases where this might actually do what the player wants, but my English skills aren't currently up to explaining.
  <function name="AddStatusAttributesForElement" parameters="status, element, statusAttributes" type="string">
    <![CDATA[
    if (statusAttributes <> null) {
      foreach (attr, statusAttributes) {
        if (LengthOf(status) > 0) {
          if (not EndsWith(status, "\n")) {
            status = status + "\n"
          }
        }
        // This is a slightly awkward way of doing it; to ensure that it doesn't break on attribute names which actually contain a dot (if that's legal?)
        value = GetAttribute(element, attr)
        if ((Instr(attr, ".") > 0) and (value = null)) {
          obj = element
          components = Split (attr, ".")
          foreach (c, components) {
            if (obj = null) {
              obj = element
            }
            if (HasObject(obj, c)) {
              obj = GetAttribute(obj, c)
              value = obj
            }
            else {
              if (HasAttribute(obj, c)) {
                value = GetAttribute(obj, c)
              }
              obj = GetObject(c)
            }
          }
        }
        status = status + FormatStatusAttribute(attr, value, StringDictionaryItem(statusAttributes, attr))
      }
    }
    return (status)
    ]]>
  </function>

  <function name="FormatStatusAttribute" parameters="attr, value, format" type="string">
    if (LengthOf(format) = 0) {
      return (CapFirst(attr) + ": " + value)
    } else {
      if (TypeOf(value) = "int" and attr = "money" and HasString(game, "moneyformat")) {
        value = DisplayMoney(value)
      }
      else if (TypeOf(value) = "int" or TypeOf(value) = "double") {
        value = ToString(value)
      }
      else if (TypeOf(value) = "null") {
        value = ""
      }
      if (Instr(format, "!") = 0) {
        if (TypeOf(value) = "boolean") {
          if (value) {
            return (format)
          }
          else {
            return ("")
          }
        }
        else {
          format = format + " !"
        }
      }
      return (Replace(format, "!", value))
    }
  </function>

(started spacing out, panic attack in the middle of writing this, so sorry if I made any dumb mistakes)


This is a good idea. I have changed the first a bit, so it will cope with "player.hits" but will also "parent.alias", i.e, the attribute of an object attribute, and also with "dog.barks", an attribute of another specific object.

Also added another function to make adding status attributes easier (for on-line uses).

  <function name="AddStatusAttributesForElement" parameters="status, element, statusAttributes" type="string"><![CDATA[
    if (statusAttributes <> null) {
      foreach (attr, statusAttributes) {
        if (LengthOf(status) > 0) {
          if (not EndsWith(status, "\n")) {
            status = status + "\n"
          }
        }
        value = GetAttribute(element, attr)
        // If that failed, can we guess what it should be?
        if ((Instr(attr, ".") > 0) and Equal(value, null)) {
          components = Split (attr, ".")
          objname = StringListItem(components, 0)
          obj = GetAttribute(element, objname)
          if (obj = null) {
            obj = GetObject(objname)
          }
          if (obj = null) {
            error ("Not finding an attribute that corresponds to " + attr)
          }
          value = GetAttribute(obj, StringListItem(components, 1))
        }
        status = status + FormatStatusAttribute(attr, value, StringDictionaryItem(statusAttributes, attr))
      }
    }
    return (status)
  ]]></function>


  <function name="FormatStatusAttribute" parameters="attr, value, format" type="string">
    if (LengthOf(format) = 0) {
      return (CapFirst(attr) + ": " + value)
    }
    else {
      if (TypeOf(value) = "int" and attr = "money" and HasString(game, "moneyformat")) {
        value = DisplayMoney(value)
      }
      else if (TypeOf(value) = "int" or TypeOf(value) = "double") {
        value = ToString(value)
      }
      else if (TypeOf(value) = "null") {
        value = ""
      }
      if (Instr(format, "!") = 0) {
        if (TypeOf(value) = "boolean") {
          if (value) {
            return (format)
          }
          else {
            return ("")
          }
        }
        else {
          format = format + " !"
        }
      }
      return (Replace(format, "!", value))
    }
  </function>


  <function name="SetStatusAtt" parameters="att, format">
    if (format = null or format = "") {
      format = CapFirst(att) + ": !"
    }
    else if (Instr(format, "!") = 0) {
      format = format + "!"
    }
    if (HasAttribute(game.pov, att)) {
      if (not HasAttribute(game.pov, "statusattributes")) {
        game.pov.statusattributes = NewStringDictionary()
      }
      dictionary add (game.pov.statusattributes, att, format)
    }
    else if (HasAttribute(game, att)) {
      if (not HasAttribute(game, "statusattributes")) {
        game.statusattributes = NewStringDictionary()
      }
      dictionary add (game.statusattributes, att, format)
    }
    else {
      error ("Neither game nor game.pov (player) have an attribute called " + att)
    }
  </function>

I looked at keys like equipped weapon.attack for if the player has object attributes; but then went on to thinking about parent.parent.alias and parent.parent.parent.alias to display the name of the region and country you're exploring … probably not something used often, but that's why I went for the loop.

Think your version is more comprehensible :)


Now I look at it, I wonder if it might also be beneficial to return "" for attributes that are null.


The SetStatusAtt function looks useful :) Maybe also useful to have it check for a dot in the att passed to it, so that you can use it with other objects if you want to.


Still an issue with this, that I hadn't previously noticed.
If a status attribute is set to a boolean but the expression contains a !, it will generate an error (Error running script: Error compiling expression 'Replace(format, "!", value)': FunctionCallElement: Could find not function 'Replace(String; String; Boolean)').

Should either have the special behaviour for booleans before the if (Instr(format, "!") = 0) { check; or if there is a ! in the format string, replace it with a string "true" or "false".

Yet again, I'm feeling really frustrated because I can't override functions on the web editor; looks like I'll have to do a whole load of javascript trickery to get a status pane working anyway.


Log in to post a reply.

Support

Forums