Allow full text response to ShowMenu - KVonGit/quest5-stuff GitHub Wiki

Normally, when a menu appears, we must either click the option or enter the number of the option.

These modified functions should also allow us to type the option's full text.

  <function name="ResolveNameFromList" parameters="variable, value, objtype, scope, secondaryscope, nodisambiguating" type="object"><![CDATA[
    // Modified by KV
    if (not IsDefined("nodisambiguating")) {
      nodisambiguating = false
    }
    value = Trim(LCase(value))
    fullmatches = NewObjectList()
    partialmatches = NewObjectList()
    foreach (obj, scope) {
      name = LCase(GetDisplayAlias(obj))
      CompareNames (name, value, obj, fullmatches, partialmatches)
      if (obj.alt <> null) {
        foreach (altname, obj.alt) {
          CompareNames (LCase(altname), value, obj, fullmatches, partialmatches)
        }
      }
    }
    // allow referring to objects from the previous command by gender or article
    if (objtype = "object" and game.lastobjects <> null) {
      foreach (obj, game.lastobjects) {
        CompareNames (LCase(obj.article), value, obj, fullmatches, partialmatches)
        CompareNames (LCase(obj.gender), value, obj, fullmatches, partialmatches)
      }
    }
    // Also check the secondary scope, but only if we have not found anything yet
    if (ListCount(fullmatches) = 0 and ListCount(partialmatches) = 0 and not secondaryscope = null) {
      foreach (obj, secondaryscope) {
        name = LCase(GetDisplayAlias(obj))
        CompareNames (name, value, obj, fullmatches, partialmatches)
        if (obj.alt <> null) {
          foreach (altname, obj.alt) {
            CompareNames (LCase(altname), value, obj, fullmatches, partialmatches)
          }
        }
      }
    }
    if (ListCount(fullmatches) = 1) {
      return (ListItem(fullmatches, 0))
    }
    else if (ListCount(fullmatches) = 0 and ListCount(partialmatches) = 1) {
      return (ListItem(partialmatches, 0))
    }
    else if (ListCount(fullmatches) + ListCount(partialmatches) = 0) {
      return (null)
    }
    else if (not nodisambiguating) {
      // Added this line to resolve issue with new FinishTurn setup in 580
      game.disambiguating = true
      candidates = ListCompact(ListCombine(fullmatches, partialmatches))
      if (LengthOf(variable) > 0) {
        // single object command, so after showing the menu, add the object to game.pov.currentcommandresolvedelements
        game.pov.currentcommandpendingvariable = variable
        ShowMenu (DynamicTemplate("DisambiguateMenu", value), candidates, true) {
          varname = game.pov.currentcommandpendingvariable
          game.pov.currentcommandpendingvariable = null
          if (result <> null) {
            AddToResolvedNames (varname, GetObject(result))
          }
        }
      }
      else {
        // multi-object command, so after showing the menu, add the object to the list
        game.pov.currentcommandmultiobjectpending = true
        ShowMenu (DynamicTemplate("DisambiguateMenu", value), candidates, true) {
          if (result <> null) {
            list add (game.pov.currentcommandpendingobjectlist, GetObject(result))
            ResolveNextNameListItem
          }
        }
      }
      return (null)
    }
    return (null)
  ]]></function>
  <function name="ResolveName" parameters="variable, value, objtype, nodisambiguating" type="object"><![CDATA[
    // Modified by KV
    if (not IsDefined("nodisambiguating")) {
      nodisambiguating = false
    }
    found = false
    if (game.pov.commandmetadata <> null) {
      if (DictionaryContains(game.pov.commandmetadata, value)) {
        result = GetObject(StringDictionaryItem(game.pov.commandmetadata, value))
        if (result <> null) {
          if (ListContains(ScopeVisible(), result)) {
            found = true
            return (result)
          }
        }
      }
    }
    if (not found) {
      value = LCase(value)
      result = ResolveNameInternal(variable, value, objtype, nodisambiguating)
      if (result <> null) {
        return (result)
      }
      else {
        // TO DO: Check this behaviour. We only want to try ignoring prefixes if we have definitely got an unresolved name.
        foreach (prefix, game.parserignoreprefixes) {
          if (StartsWith(value, prefix + " ")) {
            result = ResolveNameInternal(variable, Mid(value, LengthOf(prefix) + 1), objtype, nodisambiguating)
          }
        }
        if (result = null and LengthOf(variable) = 0 and not GetBoolean(game.pov, "currentcommandmultiobjectpending")) {
          UnresolvedCommand (value, game.pov.currentcommandpendingvariable)
        }
        return (result)
      }
    }
  ]]></function>
  <function name="ResolveNameInternal" parameters="variable, value, objtype, nodisambiguating" type="object">
    // Modified by KV
    if (not IsDefined("nodisambiguating")) {
      nodisambiguating = false
    }
    game.pov.currentcommandmultiobjectpending = false
    scope = GetScope(variable, value, objtype)
    if (HasString(game.pov.currentcommandpattern, "scope")) {
      secondaryscope = ScopeVisible()
    }
    else {
      secondaryscope = null
    }
    return (ResolveNameFromList(variable, value, objtype, scope, secondaryscope, nodisambiguating))
  </function>
  <function name="HandleMenuTextResponse" parameters="input" type="boolean"><![CDATA[
    // Modified by KV
    handled = false
    if (IsInt(input)) {
      number = ToInt(input)
      if (number > 0 and number <= ListCount(game.menuoptionskeys)) {
        handled = true
        if (not GetBoolean(game, "notranscript") and GetBoolean(game, "savetranscript")) {
          JS.SaveTranscript ("<span><br/>> " + SafeXML(input) + "<br/></span>")
        }
        ShowMenuResponse (StringListItem(game.menuoptionskeys, number - 1))
      }
    }
    else if (TypeOf (game.menuoptions) = "stringdictionary") {
      foreach (opt, game.menuoptions) {
        val = StringDictionaryItem(game.menuoptions, opt)
        if (LCase(input) = LCase(val)) {
          handled = true
          if (not GetBoolean(game, "notranscript") and GetBoolean(game, "savetranscript")) {
            JS.SaveTranscript ("<span><br/>> " + SafeXML(input) + "<br/></span>")
          }
          ShowMenuResponse (opt)
        }
      }
    }
    else if (GetBoolean (game, "disambiguating")) {
      // Hide the current menu now, else it will never go away.
      // HideOutputSection (game.menuoutputsection)
      obj = ResolveName("object", input, "object", true)
      if (obj <> null) {
        handled = true
        if (not GetBoolean(game, "notranscript") and GetBoolean(game, "savetranscript")) {
          JS.SaveTranscript ("<span><br/>> " + SafeXML(input) + "<br/></span>")
        }
        ShowMenuResponse (obj.name)
      }
      else {
        // If we make it here, we will see a second disambiguation menu appear, then both menus immediately disappear
        game.disambiguating = false
      }
    }
    else {
      i = 0
      foreach (opt, game.menuoptionskeys) {
        if (LCase(input) = LCase(opt)) {
          handled = true
          if (not GetBoolean(game, "notranscript") and GetBoolean(game, "savetranscript")) {
            JS.SaveTranscript ("<span><br/>> " + SafeXML(input) + "<br/></span>")
          }
          ShowMenuResponse (StringListItem(game.menuoptionskeys, i))
        }
        i = i + 1
      }
    }
    return (handled)
  ]]></function>

Test game: https://textadventures.co.uk/games/view/ix7vvbrlpeoja2ftwtotta/hack-showmenu

⚠️ **GitHub.com Fallback** ⚠️