How do I add number of verbs besides alias like donkey (3)?

So I like to decorate my games with uninteractable objects, which is also referred as scenery
This becomes a problem quickly, when you have 100 scenery objects in your game, your players are just mindlessly clicking everything to search for the objects that actually have any verbs to interact with.

There are a few ways of design to solve this problem, even though I like the (3) idea most as it shows how many possible interactions there are.

  1. Number of verbs besides alias like donkey (3)
  2. Change the font color of the object names, black = uninteractable, green = interactable, as you might have thought, not everyone likes the game to be too colorful and everyone likes different color
  3. Skip making scenery objects, and add a print message on describing the scenery of that room
  4. A separate container at the bottom of player's inventory and at the bottom of map inventory, create a new custom box, all objects in this box are automatically classified as scenery objects, so players will not waste time to click on them

Understand that I want a code that automatically shows objects are interactable in the whole game at all rooms, my games can have like 100 rooms, and it would be chore to write codes for all of them.
From the above design solutions, there are actually further complications:

  1. When you add verbs besides alias like donkey level 2, it might overwrite any alias coding you have done before, including gameplay codes which checks for alias, when you change the alias, donkey level 2 becomes donkey (3), and any existing codes that requires that exact alias may fail, or that you are erasing away helpful aliases like level 2
  2. Font color have no problems, just that some people can't see colors clearly enough
  3. This is probably my plan b, if nobody helps me to code, the thing is that objects on right hand side feels more intuitive while messages seems skippable unnecessaries according to my playstyle though
  4. This is possibly the most ideal solution, there are no flaws, but it probably requires advanced coding knowledge

But, you can mark objects as scenery objects, and then they're not shown as links to click on in the quest engine... So that already existing system could work with what you said about adding a print message mentioning them. Then people would read them in the description, and if they choose to type "look sceneryobject" they would get whatever more detailed description you gave the object. or the default "it looks ordinary" whatever that is in your game. So every object where you choose "scenery" on the object's setup tab will not show up as a link, but is reachable and visible. You'd just add it to your room description text.

However, I think it's also a fun idea to make a separate "inventory" window to display the scenery objects. You could use the existing Second Inventory library by Pixie https://github.com/ThePix/quest/wiki/Library:-Second-inventory and then, rather than having just one room that you'd "set" as the inventory room, you would do something like make the game's "before room enter" script switch to whatever scenery room corresponds to the room your player is entering. This then would mean you'd make 2 rooms for every room. "Library" and "Libraryscenery" where those objects would end up in Inventory pane 2.

In one of my games, I have an Inv2 and Inv3 because one pane houses magic and the other houses verses. So you can create as many extra panes as you need with Pixie's lib, just changing the names in a couple of places on the base code.

Here's hoping this helps you narrow down from your options. Also, If you're lucky, MrAngel will help you brainstorm. He's a Quest Genius and almost always has the best solutions.


Thanks for the help Ip Man

I still like the idea of number of verbs besides alias, because if the code is doable, you only need one code for the whole game,
also that it might be able to automatically update objects that were previously uninteractable/0 verbs, but due to a game event, it is now interactable/3 verbs
The main worry still exist, that it might override any existing game coding that makes use of alias like

  1. donkey level 2, 70% hp
    (When overiden, it becomes donkey (3), the level 2 and 70% hp disappeared)
  2. if rng = 3, donkey.alias = "donkey kong"
    (When overiden, it becomes donkey (3), the kong disappeared)
  3. donkey.name = "donkey" but donkey.alias = "", game creator was lazy to write out donkey alias, because it is basically the same words as the donkey name, and it would take a lot of effort to write out same alias = name for all objects

But, you can mark objects as scenery objects, and then they're not shown as links to click on in the quest engine... So that already existing system could work with what you said about adding a print message mentioning them. Then people would read them in the description, and if they choose to type "look sceneryobject" they would get whatever more detailed description you gave the object. or the default "it looks ordinary" whatever that is in your game. So every object where you choose "scenery" on the object's setup tab will not show up as a link, but is reachable and visible. You'd just add it to your room description text.

Generally I am a lazy game creator and expect my players to be lazy as well, so nobody will click at look at verb or type in look at command parser for most of my mundane objects
So generally, I use a scenery generator, to randomize each room's outlook to make travelling more fun, while the players doesn't really have to interact it, but this would be an issue for players unfamiliar with my game, they will probably be clicking all of the room objects trying to find out which object is interactable

However, I think it's also a fun idea to make a separate "inventory" window to display the scenery objects. You could use the existing Second Inventory library by Pixie https://github.com/ThePix/quest/wiki/Library:-Second-inventory and then, rather than having just one room that you'd "set" as the inventory room, you would do something like make the game's "before room enter" script switch to whatever scenery room corresponds to the room your player is entering. This then would mean you'd make 2 rooms for every room. "Library" and "Libraryscenery" where those objects would end up in Inventory pane 2.

As usual, I had a hard time dealing with library
After a long time, generally the fix was to create a room named "spells_known" (Yeah I might be english blind, have some problems with reading)
The second fix was to move objects out of the room "spells_known" rather than making them invisible, because hiding them does not do anything, they still appear

So rather than making 2 rooms for every room, which sounds like self abuse, I had something like this
This code is placed at when entering a new room

if (game.pov.parent = room) {
  if (RandomChance(50)) {
    MoveObject (kangaroo, spells_unknown)
  }
  else {
    MoveObject (kangaroo, spells_known)
  }
}
UpdateInv2

Yeah, dun forget about UpdateInv2 at the end of code, I already know you will forget about it, daeun
And before the code, you need to move all available scenery objects out of the room to hide them


Another walkaround solution is to create an object named scenery in the required rooms
Copy and paste the following code on entering specific rooms

scenery.alias = scenery.name+ ": "
if (RandomChance(100)) {
  scenery.alias = scenery.alias+ "floor"
}
if (RandomChance(40)) {
  scenery.alias = scenery.alias+ ",table"
}
if (RandomChance(40)) {
  scenery.alias = scenery.alias+ ",windows"
}
if (RandomChance(40)) {
  scenery.alias = scenery.alias+ ",coffee"
}
if (RandomChance(40)) {
  scenery.alias = scenery.alias+ ",madam"
}
if (RandomChance(40)) {
  scenery.alias = scenery.alias+ ",table"
}
.

Although I dun like this, it does have its positive qualities

  1. Easy to code and modify
  2. New players that dunno will still click on it, but they will at most be clicking only 1 scenery object per room, which is better than 5 scenery objects per room
  3. Does not conflict with existing game codes, as it is only attributed towards that 1 scenery object
  4. It uses up less slots on the right hand panel, unlike multiple objects which uses 1 horizontal slot for each object

The limitations

  1. Players still can't easily see the number of verbs before clicking on objects, as the code only modifies that 1 scenery object while leaving all of the other objects untouched and unupgraded

So the code to access the number of verbs, whether a certain verb exists and changing of the verb can create a list of intermediate coding solutions like

Pseudo code

  1. Checking for all objects in the game, if number of verb = 0, it is a scenery object,
    then if player is a balrog, he is allowed to destroy any of these objects, resulting in "destroyed table" from the original object "table".
  2. Automatically reduce the number of verbs to players, if player is an archer, "melee fight" and "block" verb are automatically removed
    If player switch his bow to an elven longsword, add in the verbs "melee fight" and "block"
  3. So if a boss enemy appeared, disable all verbs and exits in the room, so the players will not leave the room, get health potions, switch weapons, get an npc ally and return back to fight the boss, so unrealistic, lol
  4. If a player is much lower level than the enemy like 20 or more levels, automatically disable the verb "fight"
    (I know that computer games have level 40 over the enemy's forehead, but this feels unrealistic for me, when you see a crocodile in real life, it is not going ot have a level 20 over its forehead to tell you that it is dangerous, lol)
  5. If a player becomes better at the game and unlock more milestones, automatically increase the number of risky verbs available like "mount on the dragon enemy", "persuade the lich enemy that you are not their enemy" and "bargain for 50% for this shop item"
  6. One code shortcut for inputting verbs into all npc and enemies objects, if npc level 1 , input "basic shop" verb, if npc level 2, input "weaponry shop" verb, if npc level 3, input "spell and stat tome shop" verb, if objects have hp, it becomes an enemy, and it gains "fight" verb for players to fight with
  7. If a player allies with any 1 of the four factions, he will be unable to do "trading" verb with enemy factions and will be instead be given "fight" verb to force them to battle
  8. Depending on a player's light source, the player will be able to see more and more verbs, on light source 1, player can see "look at" verb on catapult, on light source 2, player can see "place rock" verb on catapult, on light source 3, player can see "kill assassin hiding behind" verb on catapult

In short, this is just to convince you to help me write out the code to access the number of verbs, whether a certain verb already exists and changing of the verb


I had a small success

Verbs are just script attributes

based on https://docs.textadventures.co.uk/quest/using_verbs.html

object.displayverbs = ListCombine(object.displayverbs, Split("Attack"))

https://docs.textadventures.co.uk/quest/display_verbs.html


Script when entering a room:

foreach (objectx, ScopeVisible()) {
  if (HasAttribute(objectx, "fight")) {
  }
  else {
    if (HasAttribute(objectx, "hp stat")) {
      objectx.displayverbs = ListCombine(objectx.displayverbs, Split("fight"))
      objectx.fight => {
        msg ("You deal 1 damage to donkey<br/>Donkey retaliates with 2 damage")
      }
    }
  }
}

I now have a moderate success

Script when entering a room:

foreach (objectx, ScopeVisible()) {
  objectx.verbcountstat = 0
  if (HasAttribute(objectx, "fight")) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }
  if (HasAttribute(objectx, "trade")) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }
  if (HasAttribute(objectx, "ride")) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }
  objectx.alias = objectx.name+" ("+ objectx.verbcountstat+")"
}

The issue with this, is that if I have too many verbs like 100 different verbs, I probably have to write a long code as well, so if someone can help directly source the verb names from the verb folder, that would be great, I am guess this have to do with for each loop and dictionary, which I am unfamiliar with

Also, as stated previously, this can conflict with internal game codes like

Copied and pasted from previous statement

  1. donkey level 2, 70% hp
    (When overiden, it becomes donkey (3), the level 2 and 70% hp disappeared)
  2. if rng = 3, donkey.alias = "donkey kong"
    (When overiden, it becomes donkey (3), the kong disappeared)
  3. donkey.name = "donkey" but donkey.alias = "", game creator was lazy to write out donkey alias, because it is basically the same words as the donkey name, and it would take a lot of effort to write out same alias = name for all objects
4. Also, that if you have multiple objects of the same name, the quest app will force you to use goblin, goblin2, goblin3, thus this code becomes ugly as it will show it as goblin3 (3) instead of the better one: goblin (3)

If you use objectx.alias = objectx.alias + verbcount = it will show it correctly as goblin (3),
but the next time you enter the room, it will become goblin (3) (3), and it will keep adding on and on, which is hard to interpret


I might have solved the problem the way I want it to be,
rather than putting number of verbs to all objects like donkey (3),
I will only put number of verbs to scenery objects, objects that do not have a single verb,
and let the players automatically realise that the others are interactable,

In short it should be like this:
Flower (0)
Dirt path (0)
NPC Jerry (0)
Dog
Shovel

Thus, the player will eventually find out that (0) means it have no verbs, and that dog and shovel are interactable, because I do not change their aliases, their in game code stays untouched, so I guess, problem solved?


So the below code looks like it works, but it still conflicts with 2 issues

  1. Residential area1 (0), Residential area2 (0), Residential area3 (0), Residential area4 (0)
    (Because the game code takes objectx.name and that objects can't have two of the same names, automatically applying a number beside it, which makes it looks ugly.)
  2. It conflicts with scenery generator, I am not sure what is happening, but random stuffs are spawning instead

Script when entering a new room

foreach (objectx, ScopeVisible()) {
  objectx.verbcountstat = 0
  if (ListContains(objectx.displayverbs, "Take")) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }
  if (HasAttribute(objectx, "speak")) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }
  if (HasAttribute(objectx, "look")) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }
  if (HasAttribute(objectx, "buy")) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }
  if (objectx.feature_usegive = true) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }
  if (HasAttribute(objectx, "catch")) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }
  if (HasAttribute(objectx, "hunt")) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }
  if (objectx.verbcountstat=0) {
    objectx.alias = objectx.name+" ("+ objectx.verbcountstat+")"
  }
}

Scenery generator that got conflicted

foreach (object, GetDirectChildren (game.pov.parent)) {
  if (object.alias = "red squirrel") {
    object.parent = null
  }
  if (object.alias = "swaying grass") {
    object.parent = null
  }
  if (object.alias = "girl in dress") {
    object.parent = null
  }
}
MakeObjectVisible (picnic object)
if (RandomChance(12)) {
  picnic object.alias = "red squirrel"
  CloneObjectAndMoveHere (picnic object)
}
if (RandomChance(12)) {
  picnic object.alias = "swaying grass"
  CloneObjectAndMoveHere (picnic object)
}
if (RandomChance(12)) {
  picnic object.alias = "girl in dress"
  CloneObjectAndMoveHere (picnic object)
}

The original code of the scenery generator is 50 times longer, so perhaps the longness is creating trouble
If you look at it, both scenery generator and numberofverbs generator generates when entering a room,
while the long code is triggering, it accidentally conflicts with numberofverbs generator creating random stuffs

But I am still not sure what is the fix, how do I control a code to load before the other code?
Scenery generators loads when entering specific room
Numberofverbs generator loads when entering all rooms


Delaying the scenery generator for 2 seconds seems to give some insights on what is happening,
basically the second time the player enters the room, the numberofverbs generator changes the aliases of the scenery objects, therefore the scenery generator was not able to clear those objects

So how am I going to clear those objects with random names?

I tried a lot of methods, and realized the issue is not about clearing random names, or rather to disable random names from appearing in the first place, which random names are being generated because clone generator makes use of object.names + "" and numberofverbs makes use of object.names + "", therefore they override each other
So despite all the attempts, there is only one true solution which is to directly write (0) on the clone generator for each objects, and have it not being targeted by numberofverbs generator

Same goes for the Residential area1 (0), Residential area2 (0), Residential area3 (0), Residential area4 (0),
we need to give it a made up attribute like object.skipverbstat, and modify numberofverbs generator to skip any objects that have skipverbstat

Overall, this seems like a lot of work compared to just manually add (0) to aliases to objects


If you just want to find out the number of verbs that can be used on an object, you can do that quite easily. You could do something like:

verbcount = 0
foreach (verb, game.verbattributes) {
  if (HasAttribute (object, verb)) {
    verbcount = verbcount + 1
  }
}

However, this won't tell you if an object is really interactable or not, because it only checks verbs – it doesn't check for commands like "take" or "look at".
You could make those special cases – but then, would you want it to include objects that you can't take but the player might try to? There might be objects in a game that aren't supposed to be taken because that would be silly (maybe scenery objects like trees), but also objects that can't be taken because they're nailed down; where trying to take them gives the player information. So should "Take" be included in the number of verbs or not?

One way to do this would be modifying the built-in javascript function updateObjectLinks, which is responsible for building the pop-up menu of verbs for clickable object links. Then, the number would just show how many items will appear in that little menu, but I think that might be what you want. Then, if you don't want "Take" and "Look at" to be counted, you can just remove them from an object's displayverbs.

The function would look something like:

function updateObjectLinks(data) {
    $(".elementmenu").each(function (index, e) {
        var $e = $(e);
        $e.children(".verbcount").remove();
        var verbs = data[$e.data("elementid")];
        if (verbs) {
            $e.removeClass("disabled");
            $e.data("verbs", verbs);
            $e.attr("data-verbs", verbs);
            $("<small>", {class: "verbcount"}).text(" ("+verbs.split("/").length+")").appendTo($e);
        } else {
            $e.addClass("disabled");
        }
    });
}

Or, in a form you can just paste into Quest's UI Initialisation script:

JS.eval("updateObjectLinks=function(d){$('.elementmenu').each(function(e,a){var t=$(a);t.children('.verbcount').remove();a=d[t.data('elementid')];a?(t.removeClass('disabled'),t.data('verbs',a),t.attr('data-verbs',a),$('<small>',{class:'verbcount'}).text(' ('+a.split('/').length+')').appendTo(t)):t.addClass('disabled')})};")

That's off the top of my head, but it might do something like what you want.


I combine your first code into a working minimalist code

Script when entering a room

foreach (objectx, ScopeVisible()) {
  verbcount = 0
  foreach (verb, game.verbattributes) {
    if (HasAttribute (objectx, verb)) {
      verbcount = verbcount + 1
    }
  }
  objectx.alias = objectx.name+" ("+ verbcount+")"
}

The following code seems to work on my current game, but somehow it failed to combine with your code

  if (ListContains(objectx.displayverbs, "Take")) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }
  if (HasAttribute(objectx, "speak")) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }
  if (HasAttribute(objectx, "look")) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }
  if (HasAttribute(objectx, "buy")) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }
  if (objectx.feature_usegive = true) {
    objectx.verbcountstat = objectx.verbcountstat+1
  }

There might be objects in a game that aren't supposed to be taken because that would be silly (maybe scenery objects like trees), but also objects that can't be taken because they're nailed down; where trying to take them gives the player information. So should "Take" be included in the number of verbs or not?

I guess you are talking about change of situation, from my perspective, I would like it to be like an example scenario 1. Scenery Tree (0) can't be interacted 2. Player gets an axe from another room, and return to this room 3. Scenery tree becomes (1), and it now have a "chop tree" verb 4. (I purposefully require player to move to another room as I know the verb only updates on enter room.)

Your second code can't be used, it might be due to my coding inexperience

  1. I tried creating a custom function
  2. Copy and paste into main game's code view
  3. Copy over updateObjectLinks from internal function and edit it to your code
    Also my updateObjectLinks looks really different from yours,
    considering if you are asking me to just add in green text from your code,
    but I did tried copying everything over as well
if (game.enablehyperlinks) {
  data = NewStringDictionary()
  foreach (object, ScopeVisible()) {
    dictionary add (data, object.name, Join(GetDisplayVerbs(object), "/"))
  }
  JS.updateObjectLinks (data)
  exits = NewStringList()
  foreach (exit, ScopeExits()) {
    list add (exits, exit.name)
  }
  JS.updateExitLinks (exits)
  commands = NewStringList()
  foreach (cmd, ScopeCommands()) {
    list add (commands, cmd.name)
  }
  JS.updateCommandLinks (commands)
}

Your last code works brilliantly, but it is giving a message rather than changing the objects aliases, or perhaps that is the intention? Since this might probably stops it from interfering with any in game codes that makes use of aliases


This is probably my final favourite code, although if new commands pops up, I might meet into potential problems again

  1. On first try, we can see only apple (1), despite the default look at and take, two verbs
  2. On removal of take verb, it is now apple (0)
  3. This means look at verb, requires stuffs to be written on before it becomes apple (2), which is why my current game work
  4. Clicking and unclicking use verb feature, increases and decreases, thus we now have apple (3)
    But display verb of use is not shown on outside of inventory, use verb is only show in inventory, which may confuse player, but I am going to continue onwards
  5. Unfortunately buy verb gives 2 extra verbs, because it automatically adds in purchase verb as well which is not being displayed, this does looks confusing even to me
  6. Speak from convlib seems to add 2 new extra verbs as well, the other verb is talk which is not shown and confusing even to me

This just makes me wants to return to my alternative walkaround, which is to just add (0) to scenery objects,
but if anyone wants a code that can calculate the number of verbs, you might want this final code

foreach (objectx, ScopeVisible()) {
  verbcount = 0
  foreach (verb, game.verbattributes) {
    if (HasAttribute (objectx, verb)) {
      verbcount = verbcount + 1
    }
  }
  if (ListContains(objectx.displayverbs, "Take")) {
    verbcount = verbcount + 1
  }
  if (HasAttribute(objectx, "speak")) {
    verbcount = verbcount + 1
  }
  if (HasAttribute(objectx, "look")) {
    verbcount = verbcount + 1
  }
  if (HasAttribute(objectx, "buy")) {
    verbcount = verbcount + 1
  }
  if (objectx.feature_usegive = true) {
    verbcount = verbcount + 1
  }
  objectx.alias = objectx.name+" ("+ verbcount+")"
}

For mrangel's last code
I get

You can see an apple (1), an apple1 (2), an apple2 (2), an apple3 (2), an apple4 (3) and apple5 (4).

It is almost accurate until the apple3, the code does not counts in the use verb


After a good night's sleep, my brain seems to work better
This final code be better

foreach (objectx, ScopeVisible()) {
  verbcount = 0
  foreach (verb, game.verbattributes) {
    if (HasAttribute (objectx, verb)) {
      verbcount = verbcount + 1
    }
  }
  if (ListContains(objectx.displayverbs, "Take")) {
    verbcount = verbcount + 1
  }
  if (HasAttribute(objectx, "look")) {
    verbcount = verbcount + 1
  }
  if (objectx.feature_usegive = true) {
    verbcount = verbcount + 1
  }
  objectx.alias = objectx.name+" ("+ verbcount+")"
}

I am going to guess mrangel's foreach verb game code loop already counts in Speak verb and Buy verb, even though it does not appears on the quest app's left hand side inside the Verbs folder


But of course, this game code is going to interfere with in game codes that makes use of objects.aliases, so apparently my refreshed mind have a new idea
Pseudocode
Main code gives us alias1
Numberofverbs generator gives us alias2

When entering all rooms,
all objects.alias = all objects.alias1 + all objects.alias2

But yeah, it is hard to redo my current game with 100+ rooms for now, so both of these codes will have to be delayed to the future, while currently I just use the scenery objects = (0) trick first
But if you run into any issue, maybe you can post it first and let the amazing mrangel take a look


Small demostration available at
https://textadventures.co.uk/games/view/57zl3sqjdeoeuqwqok9r5q/test


Log in to post a reply.

Support

Forums