A thought for making ShowMenu more intuitive
mrangel
18 Oct 2018, 08:30Hi!
Here's a function that could be used with ShowMenu when handling an objectlist.
Using this for disambiguation menus would be really neat :)
Two features:
-
If an object has an attribute
equivalent_attributes
(a string of attribute names separated with semicolons), then multiple objects in which those attributes match are removed from the list. For example, if a player types "eat apple" and there are 3 identical apples on the table, you don't want a disambiguation menu asking them to choose "apple", "apple", or "apple".I originally thought of removing duplicate items from the menu if they have the same prototype; but then realised you could have an apple with some attribute to make it either red or green, cloned from the same base object. So this method allows an object to specify which objects it should be considered identical to. A good value might typically be
"prototype;parent"
. -
Where multiple objects have the same alias, look through their
alt
attributes to see if there is a distinct name that only applies to one of them.
<function name="FindUniqueNames" parameters="objects" type="stringdictionary">
filtered_objects = NewObjectList()
names_for_object = NewDictionary()
duplicate_names = NewStringList()
all_names = NewStringList()
foreach (obj, objects) {
redundant = false
if (ListContains (filtered_objects, obj)) {
redundant = true
}
else if (HasString (obj, "equivalent_attributes")) {
attrs = obj.equivalent_attributes
possibles = FilterByAttribute (filtered_objects, "equivalent_attributes", attrs)
foreach (attr, Split (attrs)) {
possibles = FilterByAttribute (possibles, attr, GetAttribute (obj, attr))
}
if (ListCount (possibles) > 0) {
redundant = true
}
}
if (not redundant) {
list add (filtered_objects, obj)
names = NewStringList()
list add (names, GetDisplayAlias(obj))
if (HasAttribute (obj, "alt")) {
names = ListCombine (names, obj.alt)
}
// could add stuff here to generate alternate names like "Hat (on hatstand)", "Hat (in inventory)", "Hat (worn)", or "Lamp (switched on)"
foreach (name, names) {
if (not ListContains (all_names, name)) {
list remove (all_names, name)
}
else if (not ListContains (duplicate_names, name)) {
list add (duplicate_names, name)
}
}
dictionary add (names_for_object, obj.name, names)
}
}
result = NewStringDictionary()
names_used = NewStringList()
foreach (key, names_for_object) {
names = DictionaryItem (names_for_object, key)
unames = ListExclude (names, duplicate_names)
if (ListCount (unames) = 0) {
unames = ListExclude (names, names_used)
if (ListCount (unames) = 0) {
unames = names
}
}
myname = ListItem (unames, 0)
dictionary add (result, key, myname)
list add (names_used, myname)
}
return result
</function>
OK, I've not finished polishing this (or tested it), but I need to get back to actual work and stop procrastinating with things that happened to cross my mind.