ThePix / QuestJS

A major re-write of Quest that is written in JavaScript and will run in the browser.
MIT License
66 stars 12 forks source link

Change Scripts (A Hack) #55

Closed KVonGit closed 3 years ago

KVonGit commented 3 years ago

Hello.

I think this mod allows change scripts:

function createObject(name, listOfHashes) {
  if (world.isCreated && !settings.saveDisabled) {
    console.log("Attempting to use createObject with `" + name + "` after set up. To ensure games save properly you should use cloneObject to create ites during play.")
    errormsg("Attempting to use createObject with `" + name + "` after set up. To ensure games save properly you should use cloneObject to create ites during play.");
    return null;
  }

  if (/\W/.test(name)) {
    console.log("Attempting to use the disallowed name `" + name + "`; a name can only include letters and digits - no spaces or accented characters. Use the 'alias' attribute to give an item a name with other characters.")
    errormsg("Attempting to use the disallowed name `" + name + "`; a name can only include letters and digits - no spaces or accented characters. Use the 'alias' attribute to give an item a name with other characters.");
    return null;
  }
  if (w[name]) {
    console.log("Attempting to use the name `" + name + "` when there is already an item with that name in the world.")
    errormsg("Attempting to use the name `" + name + "` when there is already an item with that name in the world.");
    return null;
  }
  if (typeof listOfHashes.unshift !== 'function') {
    console.log("The list of hashes for `" + name + "` is not what I was expecting. Found:")
    console.log(listOfHashes)
    console.log('Maybe you meant to use createItem?')
    errormsg("The list of hashes for `" + name + "` is not what I was expecting. Look at the console for more.");
    return null;
  }

  listOfHashes.unshift(DEFAULT_OBJECT);

  const item = { 
    name:name,
  };

  for (let hash of listOfHashes) {
    for (let key in hash) {
      //item[key] = hash[key];
      item['default' + key] = hash[key]
      if (typeof(hash[key]) != 'function' && typeof(hash[key]) != 'object'){
        Object.defineProperty(item, key, {
          get: function() { return this['default' + key]; },
          set: function(newValue) {
            this[key + 'Bak'] = this['default' + key]
            if (this[key + 'OnChange']) this[key + 'OnChange']({_this:this, newValue:newValue})
              this['default' + key] = newValue
            }
        });
      }else{
       item[key] = hash[key];
     }
    }
  }

  // Give every object an alias and list alias (used in the inventories)
  if (!item.alias) item.alias = item.name.replace(/_/g, " ");
  if (!item.listalias) item.listalias = sentenceCase(item.alias);
  if (!item.getListAlias) item.getListAlias = function(loc) { return this.listalias; };
  if (!item.pluralAlias) item.pluralAlias = item.alias + "s";
  if (item.pluralAlias === '*') item.pluralAlias = item.alias;

  item.verbFunctions = [function(o, verbList) {
    verbList.push(lang.verbs.examine)
    if (o.use !== undefined) verbList.push(lang.verbs.use)
  }]
  item.nameModifierFunctions = []
  for (let hash of listOfHashes) {
    if (hash.onCreation) hash.onCreation(item)
  }

  //world.data.push(item);
  w[name] = item;
  return item;
}

"use strict"

createItem("me", PLAYER(), {
  loc:"lounge",
  regex:/^(me|myself|player)$/,
  examine: "Just a regular guy.",
  hitpoints:100,
  alias:'Honeytoes'
})

createRoom("lounge", {
  desc:"The lounge is boring, the author really needs to put stuff in it.",
})

w.me.hitpointsOnChange = (stuff) => {
  let { _this, newValue } = stuff
  msg("Change script!");
  msg((`Old hitpoints: ${_this.hitpointsBak}, New hitpoints: ${newValue}`))
}

setTimeout(()=>{w.me.hitpoints = 30}, 5000)

image


EDIT

...and I don't update the system after changing the hitpoints in that example, so (as it normally works without this hack), the change does not truly take affect in the game until a turn is taken:

image

KVonGit commented 3 years ago

Closing this, as it is not actually an issue. If I was thinking clearly, I would have posted this elsewhere.

ThePix commented 3 years ago

I would consider a feature selection to be an issue, so feel free to post stuff like this here.

KVonGit commented 3 years ago

This modification doesn't seem to break anything.

There has to be something I'm overlooking -- an unknown unknown.

ThePix commented 3 years ago

There may be an issue if you try to override an attribute in a template.

createItem("glass_cabinet", CONTAINER(true),  {
  examine:"A cabinet with a glass front.",
  transparent:true,
  loc:'lounge',
)

I get an error: "Uncaught TypeError: Cannot redefine property: transparent"

KVonGit commented 3 years ago

Huh.

I'll have to learn why that happens.

KVonGit commented 3 years ago

I don't know why, but it doesn't throw the error if I do it this way:

createItem("glass_cabinet", CONTAINER(true),  {
  examine:"A cabinet with a glass front.",
  loc:'lounge'
})

w.glass_cabinet.transparent = true

EDIT

I bet it's because of this.

KVonGit commented 3 years ago

Okay. I left the function modified (as shown above), and I created that glass cabinet like this with no errors, but now it doesn't update its verbs in the pane.

newItem("glass_cabinet", CONTAINER(true),  {
  examine:"A cabinet with a glass front.",
  loc:'lounge',
  transparent: true
})

//w.glass_cabinet.transparent = true

function newItem(wName, ...atts){
  //console.log(atts)
  let obj = createItem(wName)
  if (!atts) return obj
  atts.forEach(att => {
      Object.keys(att).forEach(key =>{
      obj[key] = att[key]
    })
  })
}

image


Isn't change script functionality the last big obstacle when converting from Quest 5 to Quest 6? In other words, do you even want to be able to add change scripts?

ThePix commented 3 years ago

Isn't change script functionality the last big obstacle when converting from Quest 5 to Quest 6? In other words, do you even want to be able to add change scripts?

In theory, yes. In practice, there are plenty of other obstacles, and I am not convinced this is especially important. How much do Quest 5 games actually use them? Do people ask about them on the forum much?

KVonGit commented 3 years ago

I am not convinced this is especially important. How much do Quest 5 games actually use them? Do people ask about them on the forum much?

Now that you ask, I can only remember mrangel talking about them.

Hmm. I hereby declare this issue: closed.