New to Quest JS and have a few technical queries for a new game

I'm trying to design and create a new game in QuestJS where player actions on a specific NPC character have a % chance of working so I need a way of updating the HereVerbs of all the Verbs on both the Player verbs (need to find out how to get those to show anyway) and the NPC and object verbs. They should update the display of the % on a function request.

I have the formula to calculate the % chance already so I just need assistance with how I go about displaying the % on the verb description displayed to the user when they click on the NPC or other room objects if thr NPC is in the same room as the player.


This is a bit trickier than it might appear at first glance because when you click a verb in the side pane, it builds and runs the command as if you typed it into the command line, so by modifying the verb to display the chance of success, you end up modifying the command itself. On top of that, % is a reserved character, so if you include it in the verb, it'll really confuse the parser. For example, if the verb was "Take (50%)" and the item name was "Bauble", what would end up being sent to the parser is "Take (50Bauble)".

To get around this, you need to modify the io.clickItemAction() function to extract the percent from the command before sending it to the parser. Then, to modify the verbs, you just need to add a function to verbFunctions that removes and adds the verb to keep the percent up to date. Here's an example.

game.percent = 50
const newVerb = "Gamble"

createItem("ima_enpici", NPC(true),
{ 
  alias:"Ima Enpici",
  loc:"lounge",
  examine:"An NPC with a chance of doing something.", 
  afterCreation:function(o) {
    o.verbFunctions.push(function(o, verbList) {
      const gamble_index = verbList.findIndex(verb => /Gamble \([\d]{1,3}\)/i.test(verb))
      if (gamble_index > -1) {
        verbList.splice(gamble_index, 1);
      }
      verbList.push(`${newVerb} (${game.percent}%)`)
    }) 
  },
  gamble:function(p){
    if (random.chance(game.percent)){
      msg ("Your gamble succeeded.")
    } else {
      msg ("Your gamble failed.")
    }
  }
});

io.clickItemAction = function(itemName, action) {
  if (io.disableLevel) return
  const item = w[itemName];
  if (/\w+ \([\d]{1,3}%\)/i.test(action)){
    const arr = / \([\d]{1,3}%\)/g.exec(action)
    action = action.replace(arr[0], "")
  }
  const cmd = action.includes('%') ? action.replace('%', item.alias) : action + ' ' + item.alias
  runCmd(cmd)
}

commands.unshift(new Cmd(newVerb, {
  regex:new RegExp('^' + newVerb.toLowerCase() + ' (.+)$'),
  attName:newVerb.toLowerCase(),
  objects:[
    {scope: parser.isHere},
  ],
  defmsg:"{pv:item:'be:true} not something you can do that with.",
}))

The only simpler way would be to not display the % but provide a prompt to the user with it and a continue or not selection before properly performing the action after the user has selected the action/entered the command prompt.

But visually getting it to work your way would be better but I'm not sure exactly where I can modify io.clickItemAction(), is that in one of the game library files?


Yes, that function is in /lib/_io.js. You can either modify it there or you can overwrite it in one of the files that gets loaded later, like code.js or data.js. If you paste my example into your data.js file (you may need to change the NPC's loc to something that exists in your project), you can try it out to see how it works.


That does seem to work how I want but I'm not sure how to adjust your code to add multiple verbs, and ones that are setup based on the NPC's current room location.

So for instance "Watch TV with" and "Snuggle up with" in the Lounge and "Eat with" and "Drink with" in the Kitchen.


This isn't necessarily the best way to accomplish what you're looking for, but it follows the same pattern. First, we create an array of objects that contain the name, location, and chance of success for each verb, then we iterate through that array when setting up the new commands and when adding the verbs to the NPC.

game.gambleChance = 50
game.eatChance = 80
game.tvChance = 30

const newVerbs = [
  {name: "Gamble", chance:function(){return game.gambleChance}},
  {name: "Eat with", loc: "kitchen", chance:function(){return game.eatChance}},
  {name: "Watch TV with", loc: "lounge", chance:function(){return game.tvChance}}
]

createItem("ima_enpici", NPC(true),
{ 
  alias:"Ima Enpici",
  loc:"lounge",
  examine:"An NPC with a chance of doing something.", 
  afterCreation:function(o) {
    o.verbFunctions.push(function(o, verbList) {
      for (let verb of newVerbs){
        const verb_regex = new RegExp(`${verb.name} \([\d]{1,3}\)`)
        const verb_index = verbList.findIndex(v => verb_regex.test(v))
        if (verb_index > -1){
          verbList.splice(verb_index, 1);
        }
        if (!verb.loc || verb.loc === o.loc){
          verbList.push(`${verb.name} (${verb.chance()}%)`)
        }
      }
    })
  },
  gamble:function(p){
    if (random.chance(game.gambleChance)){
      msg ("Your gamble succeeded.")
    } else {
      msg ("Your gamble failed.")
    }
  },
  eatwith:function(p){
    if (random.chance(game.eatChance)){
      msg ("You eat with {nm:ima_enpici}.")
    } else {
      msg ("You failed to eat with {nm:ima_enpici}.")
    }
  },
  watchtvwith:function(p){
    if (random.chance(game.tvChance)){
      msg ("You watch TV with {nm:ima_enpici}.")
    } else {
      msg ("You failed to watch TV with {nm:ima_enpici}.")
    }
  }
});

for (let verb of newVerbs){
  new Cmd(verb.name, {
    regex:new RegExp('^' + verb.name.toLowerCase() + ' (.+)$'),
    attName:verb.name.toLowerCase().replace(/ /g, ''),
    objects:[
      {scope: parser.isHere},
    ],
    defmsg:"{pv:item:'be:true} not something you can do that with.",
  })
}

This was my attempt while I was waiting for your response, it closely resembles the method I am already trying to use in regards a set const list of actions and their perc chances plus a method to get the NPC to follow you around to get them into the next room.

"use strict"

game.watchPercent = 50
game.snugglePercent = 30
game.eatWithPercent = 70
game.drinkWithPercent = 40

const newVerb = "Watch TV";
const newVerb2 = "Snuggle With";

const ACTION_WATCHTV = 0;
const ACTION_SNUGGLE = 1;
const ACTION_EATWITH = 2;
const ACTION_DRINKWITH = 3;


createItem("me", PLAYER(), {
  loc:"Lounge",
  synonyms:['me', 'myself'],
  examine: "Just a regular guy.",
  isBeingFollowed: false,
})

createRoom("Lounge", {
	desc:"The lounge is has a comfy looking sofa and a large TV.",
	beforeEnter: function()
	{
		setNPCVerbs()
	}, 
    east: new Exit("Kitchen"),	
})

createRoom("Kitchen", {
	desc:"The kitchen is a modern, slickly designed food space.",
	beforeEnter: function()
	{
		setNPCVerbs()
	},
    west: new Exit("Lounge"),	
})

createItem("ima_enpici", NPC(true),
{ 
  alias:"Ima Enpici",
  loc:"Lounge",
  examine:"An NPC with a chance of doing something.",
  actions: [ACTION_WATCHTV,ACTION_SNUGGLE,ACTION_EATWITH,ACTION_DRINKWITH],
  afterCreation:function(o) {

  },
  watchtv:function(chancePerc){
    if (random.chance(chancePerc)){
      msg ("They watched TV with you.")
    } else {
      msg ("They didn't watch TV with you.")
    }
  },
  snugglewith:function(chancePerc){
    if (random.chance(chancePerc)){
      msg ("They snuggled with you.")
    } else {
      msg ("They didn't snuggle with you.")
    }
  },
  eatwith:function(chancePerc){
    if (random.chance(chancePerc)){
      msg ("They ate dinner with you.")
    } else {
      msg ("They didn't eat dinner with you.")
    }
  }, 
  drinkwith:function(chancePerc){
    if (random.chance(chancePerc)){
      msg ("They drank with you.")
    } else {
      msg ("They didn't drink with you.")
    }
  }, 
  followplayer: function() {
		if (w.me.isBeingFollowed) {
			msg ("Your NPC friend is already following you")
		} 
		else {
			this.setLeader(player)
			msg ("You ask your NPC friend to follow you")
			w.me.isBeingFollowed = true
		}
	},
	unfollowplayer: function() {
		if (w.me.isBeingFollowed) {
			w.ima_enpici.setLeader()
			w.me.isBeingFollowed = false
			msg ("You ask your NPC friend to stop following you")
		}
		else {
			msg ("Your NPC friend isn't following you anyway")
		}
	},  
});

io.clickItemAction = function(itemName, action) {
  if (io.disableLevel) return
  const item = w[itemName];
  if (/\w+ \([\d]{1,3}%\)/i.test(action)){
    const arr = / \([\d]{1,3}%\)/g.exec(action)
    action = action.replace(arr[0], "")
  }
  const cmd = action.includes('%') ? action.replace('%', item.alias) : action + ' ' + item.alias
  runCmd(cmd)
}

commands.unshift(new Cmd(newVerb, {
  regex:new RegExp('^' + newVerb.toLowerCase() + ' (.+)$'),
  attName:newVerb.toLowerCase(),
  objects:[
    {scope: parser.isHere},
  ],
  defmsg:"{pv:item:'be:true} not something you can do that with.",
}))

function setNPCVerbs() {
	var NPCVerbs = [];
	var NPCVerb = "";
	var ActionPerc = 0;
	w.ima_enpici.hereVerbs = [];
	
	switch(w.ima_enpici.loc) {
		case "Lounge": 
			NPCVerbs.push("Watch TV with", "Snuggle with");
		break;
		case "Kitchen":
			NPCVerbs.push("Eat with", "Drink with");
		break;
	}
	w.ima_enpici.hereVerbs.push("follow player", "unfollow player")
    w.ima_enpici.verbFunctions.push(function(o, verbList) {
      const gamble_index = verbList.findIndex(verb => /Watch TV\([\d]{1,3}\)/i.test(verb))
      if (gamble_index > -1) {
        verbList.splice(gamble_index, 1);
      }
	  for (NPCVerb in NPCVerbs) {
		  switch (NPCVerb) {
			case "Watch TV with":
				ActionPerc = getActionPerc(ACTION_WATCHTV);
				break;
			case "Snuggle with":
				ActionPerc = getActionPerc(ACTION_SNUGGLEWITH);
				break;
			case "Eat with":
				ActionPerc = getActionPerc(ACTION_EATWITH);
				break;
			case "Drink with":
				ActionPerc = getActionPerc(ACTION_DRINKWITH);
				break;
		  }
		  verbList.push(`${NPCVerb} (${ActionPerc}%)`)
	  }
    }) 
}

function getActionPerc(action) {

	var actionPerc = 0;
	
	switch (action) {
		case ACTION_WATCHTV:
			actionPerc = game.watchPercent
			break;
		case ACTION_SNUGGLE:
			actionPerc = game.snugglePercent
			break;
		case ACTION_EATWITH:
			actionPerc = game.eatWithPercent
			break;
		case ACTION_DRINKWITH:
			actionPerc = game.drinkWithPercent
			break;			
	}
	return actionPerc
}

I will take some time looking at your version later to see how I went wrong, and if you have suggestions on improving your own version based on my approach I would really appreciate it and all the work you've done so far with this!


I see what you were doing with calling setNPCVerbs() each time the player enters a room. It makes sense and you could probably get it working with a few minor adjustments, however, I'd recommend using the verbFunctions array instead, for a couple reasons. First, maybe later on, this or another NPC will move between rooms independently. If the verbs are only ever set when the player enters a room, they could get out of sync. Second, you'd need to find another way to update the chance in the description, if it can change while the player stays within one room. Since each function in the verbFunctions array is already executing every turn, that solves both of these problems.

My main piece of advice looking over your code would be to remember that you need to add a command for each new verb that you're adding to the game. You've already added the functions on the NPC, and you've added the verbs to their hereVerbs, but you also need to add a command so the parser knows how to connect those two pieces of code.

new Cmd("Follow", {
    regex:new RegExp('^' + "Follow".toLowerCase() + ' (.+)$'),
    attName:"Follow".toLowerCase().replace(/ /g, ''),
    objects:[
      {scope: parser.isHere},
    ],
    defmsg:"{pv:item:'be:true} not something you can do that with.",
  })

One thing I'm not clear on is how to do verbs that are on the player themselves, or does the player only every get to interact through other objects? If its something like a "yawn" or "burp" action that when the NPC isn't present wouldn't have a % chance represented but if they are in the same room they would.


I get some issues with the Follow and Unfollow commands, I added these verbs that don't need a chance but my new command isn't being registered and I get the following message in the Console "Command was [Ask to follow Ima Enpici]" but clicking on the verb.

"use strict"

game.gambleChance = 50
game.tvChance = 50
game.snuggleChance = 30
game.eatChance = 70
game.drinkChance = 40

const ACTION_WATCHTV = 0;
const ACTION_SNUGGLE = 1;
const ACTION_EATWITH = 2;
const ACTION_DRINKWITH = 3;

const newVerbs = [
  {name: "Gamble with", chance:function(){return game.gambleChance}},
  {name: "Eat with", loc: "kitchen", chance:function(){return game.eatChance}},
  {name: "Drink with", loc: "kitchen", chance:function(){return game.drinkChance}},  
  {name: "Watch TV with", loc: "lounge", chance:function(){return game.tvChance}},
  {name: "Snuggle up with", loc: "lounge", chance:function(){return game.snuggleChance}}   
]

for (let verb of newVerbs){
  new Cmd(verb.name, {
    regex:new RegExp('^' + verb.name.toLowerCase() + ' (.+)$'),
    attName:verb.name.toLowerCase().replace(/ /g, ''),
    objects:[
      {scope: parser.isHere},
    ],
    defmsg:"{pv:item:'be:true} not something you can do that with.",
  })
} 

createItem("me", PLAYER(), {
  loc:"lounge",
  synonyms:['me', 'myself'],
  examine: "Just a regular guy.",
  isBeingFollowed: false,
})

createRoom("lounge", {
	desc:"The lounge is has a comfy looking sofa and a large TV.",
    east: new Exit("kitchen"),	
})

createRoom("kitchen", {
	desc:"The kitchen is a modern, slickly designed food space.",
    west: new Exit("lounge"),	
})

createItem("ima_enpici", NPC(true),
{ 
  alias:"Ima Enpici",
  loc:"lounge",
  examine:"An NPC with a chance of doing something.",
  actions: [ACTION_WATCHTV,ACTION_SNUGGLE,ACTION_EATWITH,ACTION_DRINKWITH],
  afterCreation:function(o) {
    o.verbFunctions.push(function(o, verbList) {
      for (let verb of newVerbs){
        const verb_regex = new RegExp(`${verb.name} \([\d]{1,3}\)`)
        const verb_index = verbList.findIndex(v => verb_regex.test(v))
        if (verb_index > -1){
          verbList.splice(verb_index, 1);
        }
        if (!verb.loc || verb.loc === o.loc){
          verbList.push(`${verb.name} (${verb.chance()}%)`)
        }
      }
	  // Add permanent verbs
  	verbList.push("Ask to follow")
	verbList.push("Ask to unfollow")
    })
  },
  watchtvwith:function(chancePerc){
    if (random.chance(chancePerc)){
      msg ("You watched TV with {nm:ima_enpici}.")
    } else {
      msg ("You failed to watch TV with {nm:ima_enpici}.")
    }
  },
  snugglewith:function(chancePerc){
    if (random.chance(chancePerc)){
      msg ("You snuggled with {nm:ima_enpici}.")
    } else {
      msg ("You failed to snuggle with {nm:ima_enpici}.")
    }
  },
  eatwith:function(chancePerc){
    if (random.chance(chancePerc)){
      msg ("They ate dinner with you.")
    } else {
      msg ("They didn't eat dinner with you.")
    }
  }, 
  drinkwith:function(chancePerc){
    if (random.chance(chancePerc)){
      msg ("They drank with you.")
    } else {
      msg ("They didn't drink with you.")
    }
  },
  gamble:function(chancePerc){
    if (random.chance(chancePerc)){
      msg ("{nm:ima_enpici} gambled with you.")
    } else {
      msg ("{nm:ima_enpici} didn't gamble with you.")
    }
  },
  follow: function() {
		if (w.me.isBeingFollowed) {
			msg ("{nm:ima_enpici} is already following you")
		} 
		else {
			this.setLeader(player)
			msg ("{nm:ima_enpici} is now following you")
			w.me.isBeingFollowed = true
		}
  },
  unfollow: function() {
		if (w.me.isBeingFollowed) {
			w.ima_enpici.setLeader()
			w.me.isBeingFollowed = false
			msg ("{nm:ima_enpici} is no longer following you")
		}
		else {
			msg ("{nm:ima_enpici} isn't following you anyway")
		}
	},  
});

io.clickItemAction = function(itemName, action) {
  if (io.disableLevel) return
  const item = w[itemName];
  if (/\w+ \([\d]{1,3}%\)/i.test(action)){
    const arr = / \([\d]{1,3}%\)/g.exec(action)
    action = action.replace(arr[0], "")
  }
  const cmd = action.includes('%') ? action.replace('%', item.alias) : action + ' ' + item.alias
  runCmd(cmd)
}

new Cmd("Follow", {
    regex:new RegExp('^' + "Follow".toLowerCase() + ' (.+)$'),
    attName:"Follow".toLowerCase().replace(/ /g, ''),
    objects:[
      {scope: parser.isHere},
    ],
    defmsg:"{pv:item:'be:true} not something you can do that with.",
})

new Cmd("Unfollow", {
    regex:new RegExp('^' + "Unfollow".toLowerCase() + ' (.+)$'),
    attName:"Unfollow".toLowerCase().replace(/ /g, ''),
    objects:[
      {scope: parser.isHere},
    ],
    defmsg:"{pv:item:'be:true} not something you can do that with.",
})
  

When you create a command, the regex property decides whether the command that's passed to the parser will match. So if you want the verb displayed in the side pane to read "Ask to follow", the regex needs to be regex:new RegExp('^' + "Ask to follow".toLowerCase() + ' (.+)$'),

Also, I noticed your functions on the NPC probably aren't doing what you want them to do. The parameter that you're calling chancePerc isn't being passed the chance as an argument, it's an object that contains some information about the command. You could update the command to pass the chance through to the function, but that seems needlessly complicated since you're already storing those values elsewhere. So this might work better.

watchtvwith:function(p){
    if (random.chance(game.tvChance)){
      msg ("You watched TV with {nm:ima_enpici}.")
    } else {
      msg ("You failed to watch TV with {nm:ima_enpici}.")
    }
  },

What is the "p" in the args list of the function meant to represent? Is it the player object? Your shorthand is not that clear sorry. Also what about "nm" on the msg?


If you're ever curious about what a variable is, you can always examine it by adding a line like this. This is useful for debugging what the values of variables are if your code isn't working the way you think it should, all you have to do is check the console in your dev tools to see what is printed.
console.log(p)

In this case, the p parameter contains two objects, char and item. Here's an abridged version of what gets printed. If you wanted to have a more generic function, you could use p.char and p.item to refer to the character that initiated the action, and the item they acted upon, respectively.

{
  "char": {
    "name": "me",
    "loc": "lounge",
    "synonyms": [
      "me",
      "myself"
    ],
    "examine": "Just a regular guy.",
    "isBeingFollowed": false,
    "alias": "me"
  },
  "item": {
    "name": "ima_enpici",
    "npc": true,
    "isFemale": true,
    "alias": "Ima Enpici",
    "loc": "lounge",
    "examine": "An NPC with a chance of doing something.",
    "actions": [
      0,
      1,
      2,
      3
    ]
}

This page of the wiki has some good information about text processor directives, including nm.
https://github.com/ThePix/QuestJS/wiki/Using-Parameters-with-the-Text-Processor


Okay thanks. One last question hopefully please.

I'm trying to get the verb to display A) itself and B) its percentage chance based on condition parameters of the verb list itself, or by functions that can work off dynamically altered values but some or if not all the verbs no longer display at all. I use displayAction() for working out whether to display the action verb (in this case Snuggle) based on the new "action" parameter on the on the newVerbs[] itself and there's also a hardcoded boolean flag called displayPerc for deciding whether to push the % onto the verb, so for ones like Follow and Unfollow that don't need a percentage chance to work it makes sense not to show anything for it.

"use strict"

game.tvChance = 50
game.snuggleChance = 30
game.eatChance = 70
game.drinkChance = 40

const ACTION_WATCHTV = 0;
const ACTION_SNUGGLE = 1;
const ACTION_EATWITH = 2;
const ACTION_DRINKWITH = 3;
const ACTION_TOFOLLOW=4;
const ACTION_TOUNFOLLOW=5;

const newVerbs = [
  {name: "Eat with", action: ACTION_EATWITH, loc: "kitchen", chance:function(){return game.eatChance}, displayPerc: true},
  {name: "Drink with", action: ACTION_DRINKWITH, loc: "kitchen", chance:function(){return game.drinkChance}, displayPerc: true},  
  {name: "Snuggle up with", action: ACTION_SNUGGLE, loc: "lounge", chance:function(){return getSnuggleChance()}, displayPerc: true},
  {name: "Watch TV with", action: ACTION_WATCHTV, loc: "lounge", displayPerc: false},
  {name: "Ask to follow", action: ACTION_TOFOLLOW, displayPerc: false},
  {name: "Ask to unfollow", action: ACTION_TOUNFOLLOW,displayPerc: false}  
]

for (let verb of newVerbs){
  new Cmd(verb.name, {
    regex:new RegExp('^' + verb.name.toLowerCase() + ' (.+)$'),
    attName:verb.name.toLowerCase().replace(/ /g, ''),
    objects:[
      {scope: parser.isHere},
    ],
    defmsg:"{pv:item:'be:true} not something you can do that with.",
  })
} 

function displayAction(action) {
	var displayAction = true
	
	switch (action) {
		case ACTION_SNUGGLE:
			displayAction = false
			break;			
	}
	
	return displayAction
}

createItem("me", PLAYER(), {
  loc:"lounge",
  synonyms:['me', 'myself'],
  examine: "Just a regular guy.",
  isBeingFollowed: false,
})

createRoom("lounge", {
	desc:"The lounge is has a comfy looking sofa and a large TV.",
    east: new Exit("kitchen"),	
})

createRoom("kitchen", {
	desc:"The kitchen is a modern, slickly designed food space.",
    west: new Exit("lounge"),	
})

createItem("ima_enpici", NPC(true),
{ 
  alias:"Ima Enpici",
  loc:"lounge",
  examine:"An NPC with a chance of doing something.",
  afterCreation:function(o) {
    o.verbFunctions.push(function(o, verbList) {
      for (let verb of newVerbs){
		const verb_regex = new RegExp(`${verb.name} \([\d]{1,3}\)`)
		const verb_index = verbList.findIndex(v => verb_regex.test(v))
		console.log("Verb index: " + verb_index)
		if (verb_index > -1){
			// Not found
			console.log("Verb index " + verb_index + " was spliced")
			verbList.splice(verb_index, 1);
			continue;
		}
		if (!displayAction(verb.action)) {
			// Hide the action
			console.log("Verb action: " + verb.action + "was not displayed")
			verbList.splice(verb_index, 1);
			continue;
		}
		else {
			console.log("Verb action: " + verb.action + "was displayed")
		}
		console.log("Display perc: " + verb.displayPerc)
		console.log("Verb chance: " + verb.chance)
		// Display the action percentage chance
		if (verb.displayPerc) {
			if (!verb.loc || verb.loc === o.loc){
			  verbList.push(`${verb.name} (${verb.chance()}%)`)
			}
		}
      }
    })
  },
  watchtvwith:function(player){
    if (random.chance(game.tvChance)){
      msg ("You watched TV with {nm:ima_enpici}.")
    } else {
      msg ("You failed to watch TV with {nm:ima_enpici}.")
    }
  },
  snugglewith:function(player){
    if (random.chance(game.snuggleChance)){
      msg ("You snuggled with {nm:ima_enpici}.")
    } else {
      msg ("You failed to snuggle with {nm:ima_enpici}.")
    }
  },
  eatwith:function(player){
    if (random.chance(game.eatChance)){
      msg ("They ate dinner with you.")
    } else {
      msg ("They didn't eat dinner with you.")
    }
  }, 
  drinkwith:function(player){
    if (random.chance(game.drinkChance)){
      msg ("They drank with you.")
    } else {
      msg ("They didn't drink with you.")
    }
  },  
  follow: function(player) {
		if (w.me.isBeingFollowed) {
			msg ("{nm:ima_enpici} is already following you")
		} 
		else {
			this.setLeader(w.me)
			msg ("{nm:ima_enpici} is now following you")
			w.me.isBeingFollowed = true
		}
  },
  unfollow: function(player) {
		if (w.me.isBeingFollowed) {
			w.ima_enpici.setLeader()
			w.me.isBeingFollowed = false
			msg ("{nm:ima_enpici} is no longer following you")
		}
		else {
			msg ("{nm:ima_enpici} isn't following you anyway")
		}
	},  
});

io.clickItemAction = function(itemName, action) {
  if (io.disableLevel) return
  const item = w[itemName];
  if (/\w+ \([\d]{1,3}%\)/i.test(action)){
    const arr = / \([\d]{1,3}%\)/g.exec(action)
    action = action.replace(arr[0], "")
  }
  const cmd = action.includes('%') ? action.replace('%', item.alias) : action + ' ' + item.alias
  runCmd(cmd)
}

new Cmd("Follow", {
    regex:new RegExp('^' + "Ask to follow".toLowerCase() + ' (.+)$'),
    attName:"Follow".toLowerCase().replace(/ /g, ''),
    objects:[
      {scope: parser.isHere},
    ],
    defmsg:"{pv:item:'be:true} not something you can do that with.",
})

new Cmd("Unfollow", {
    regex:new RegExp('^' + "Ask to unfollow".toLowerCase() + ' (.+)$'),
    attName:"Unfollow".toLowerCase().replace(/ /g, ''),
    objects:[
      {scope: parser.isHere},
    ],
    defmsg:"{pv:item:'be:true} not something you can do that with.",
})

I think most of the problem was in the verbFunction. You want the whole thing to execute every time, and when you used the continue keyword, it would jump to the next verb in the array.

afterCreation:function(o) {
    o.verbFunctions.push(function(o, verbList) {
      for (let verb of newVerbs){
        const verb_regex = new RegExp(`${verb.name}( \([\d]{1,3}\))?`)
        const verb_index = verbList.findIndex(v => verb_regex.test(v))
        console.log("Verb index: " + verb_index)
        if (verb_index > -1){
          // Found
          verbList.splice(verb_index, 1);
        }
        // Display the action percentage chance
        if (displayAction(verb.action) && (!verb.loc || verb.loc === o.loc)){
          if (verb.displayPerc){
            verbList.push(`${verb.name} (${verb.chance()}%)`)
          } else {
            verbList.push(`${verb.name}`)
          }
        }
      }
    })
  },

The other thing is that, since you're adding all of your custom verbs in that array, the function names need to match the verb names exactly.

asktofollow: function(player) {
		if (w.me.isBeingFollowed) {
			msg ("{nm:ima_enpici} is already following you")
		} 
		else {
			this.setLeader(w.me)
			msg ("{nm:ima_enpici} is now following you")
			w.me.isBeingFollowed = true
		}
  },
  asktounfollow: function(player) {
		if (w.me.isBeingFollowed) {
			w.ima_enpici.setLeader()
			w.me.isBeingFollowed = false
			msg ("{nm:ima_enpici} is no longer following you")
		}
		else {
			msg ("{nm:ima_enpici} isn't following you anyway")
		}
	},

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

Support

Forums