-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Small feature request (UpdateObjectLinks) #1256
Comments
Hello, If you share your code, I can probably help out. You can zip the game file and drop it into a post as an attachment, or:
|
Have made some progress.
The image link doesn't work but the text link does. |
I just copied your code into my game and it works without problems. Could you post a game that shows your problem? |
Yes that’s the annoying thing. I don’t understand what function could have broken it.It seems to use the html inside the link as the object name instead of the data-elementid attribute.On 2 Dec 2024, at 9:09 pm, Pertex ***@***.***> wrote:
I just copied your code into my game and it works without problems. Could you post a game that shows this problem?
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you authored the thread.Message ID: ***@***.***>
|
game here yest"day, Hello,
|
Howdy friend |
Hi, all. What is the issue with Quest's source code? (Not to say there isn't one.) There's a Quest function named
Scanning the HTML document is handled by JS. Let's look at the JS function first. Line 712 is checking every single element with the class
|
function updateObjectLinks(data) { | |
$(".elementmenu").each(function (index, e) { | |
var $e = $(e); | |
var verbs = data[$e.data("elementid")]; | |
if (verbs) { | |
$e.removeClass("disabled"); | |
$e.data("verbs", verbs); | |
// also set attribute so verbs are persisted to savegame | |
$e.attr("data-verbs", verbs); | |
} else { | |
$e.addClass("disabled"); | |
} | |
}); | |
} |
Moving on to the Quest function.
It shows the verb menu but doesn’t work if you click it (I can’t see that) and it’s the only thing I haven’t managed to implement in my own.
UpdateObjectLinks
quest/WorldModel/WorldModel/Core/CoreScopes.aslx
Lines 296 to 314 in 0ccb7f0
<function name="UpdateObjectLinks"> | |
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) | |
} | |
</function> |
Line 299 is building its list/dictionary using things which are visible and in scope (using ScopeVisible()
). It then calls the JS updateObjectLinks
function using that dictionary as the argument.
If something is not visible (or in scope) in Quest, the game will print: I can’t see that.
My friend, the code works in a new game. But in my game it doesn’t work.
Sounds like your object in your game is not in scope (or it's not visible), but the object in the sample game is visible and in scope.
It is in scope and visible I have just checked. It appears to be a bug in jjmenu -this section below:
Note the var text which grabs the entire html of the section.
Now here it seems to send the HTML as the command instead of grabbing the alias using the elementID. |
💯 Image:
Text:
This seems to work, but likely breaks something else: function buildMenuOptions(verbs, text, elementId) {
if(text.indexOf("<")>-1) text = elementId;
var verbsList = verbs.split("/");
var options = [];
var metadata = new Object();
metadata[text] = elementId;
var metadataString = JSON.stringify(metadata);
$.each(verbsList, function (key, value) {
options = options.concat({
title: value,
action: {
callback: function (selectedValue) {
sendCommand(selectedValue.toLowerCase() + " " + text, metadataString);
}
}
});
});
return options;
} |
It isn't supposed to grab the alias from anywhere. It sends the command using the contents of the element as the alias, but attaches a This is only a problem if Easiest solution would be to turn off multi-command mode. If you want that to be on, you could implement a workaround by overriding the core function
and change to something like (off the top of my head)…
This is the simplest solution I can find to make this work without breaking any of the underlying metadata logic; the only side effect is that if the player types |
Looks good. However, you are using For this approach, I think that (in case echo commands is turned on), it would be better to add an extra data element,
to
|
https://textadventures.co.uk/games/view/w8zndngjduykmw66zghqhq/image-in-pane Image in Pane.aslx
<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="Image in Pane">
<gameid>5e690319-ecd0-4177-8b40-341106365053</gameid>
<version>1.0.0</version>
<firstpublished>2024</firstpublished>
<menufont>Georgia, serif</menufont>
<feature_advancedscripts />
<customstatuspane />
<subtitle>v{game.version}</subtitle>
<multiplecommands />
<description><![CDATA[Testing<br/><br/>See https://github.com/textadventures/quest/issues/1256]]></description>
<author>Richard Headkid</author>
<inituserinterface type="script"><![CDATA[
JS.setCustomStatus (Chr(60) + "a id=\"text-adventures-custom-link\" data-index=\"0\" data-elementid=\"TextAdventures\" class=\"cmdlink elementmenu\" data-verb=\"['Use','Drop']\" data-verbs=\"Examine/Take\">" + Chr(60) + "img width=\"100px\" src=\"https://avatars.githubusercontent.com/u/5058951?s=48&v=4\">" + Chr(60) + "/a>")
JS.eval ("function paneButtonClick(target, button) { var selectedListItem = $(target + ' .ui-selected'); var selectedObject = selectedListItem.data('elementname') || selectedListItem.text() || selectedListItem.text(); var selectedElementId = selectedListItem.data('elementid'); var selectedElementName = selectedListItem.data('object') || selectedListItem.text() || selectedListItem.data('elementname'); var verb = button.data('verb'); var metadata = new Object(); metadata[selectedElementName] = selectedElementId; var metadataString = JSON.stringify(metadata); if (selectedObject.length > 0) { var cmd = verb.toLowerCase() + ' ' + selectedElementName; sendCommand(cmd, metadataString);}}")
JS.eval ("function buildMenuOptions(verbs, text, elementId) { if(text.indexOf(\"<\")>-1){ text = elementId;} var verbsList = verbs.split(\"/\"); var options = []; var metadata = new Object(); metadata[text] = elementId; var metadataString = JSON.stringify(metadata); $.each(verbsList, function (key, value) { options = options.concat({ title: value, action: { callback: function (selectedValue) { sendCommand(selectedValue.toLowerCase() + \" \" + text, metadataString); } } });}); return options;}")
]]></inituserinterface>
</game>
<object name="Testing Grounds">
<inherit name="editor_room" />
<isroom />
<usedefaultprefix type="boolean">false</usedefaultprefix>
<prefix>the</prefix>
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="TextAdventures">
<inherit name="editor_object" />
<look><![CDATA[<br/><a target="_blank" href="https://textadventures.co.uk">https://textadventures.co.uk</a>]]></look>
<usedefaultprefix type="boolean">false</usedefaultprefix>
<takemsg>Alex wouldn't like that.</takemsg>
<alias><![CDATA[<img src="https://avatars.githubusercontent.com/u/5058951?s=48&v=4"/>]]></alias>
<listalias><![CDATA[<img width=100 src="https://avatars.githubusercontent.com/u/5058951?s=48&v=4" data-object="TextAdventures" data-elementid="TextAdventures" data-elementname="TextAdventures" data-index="0" data-verbs="['Look at','Take']"/><span style="display:none">TextAdventures</span>]]></listalias>
</object>
</object>
<function name="HandleCommand" parameters="command, metadata"><![CDATA[
handled = false
if (game.menucallback <> null) {
if (HandleMenuTextResponse(command)) {
handled = true
}
else {
if (game.menuallowcancel) {
ClearMenu
}
else {
handled = true
}
}
}
if (not handled) {
StartTurnOutputSection
if (StartsWith (command, "*")) {
// Modified by KV to bypass turn scripts and turn counts, and to print "Noted."
game.suppressturnscripts = true
msg ("")
msg (SafeXML (command))
msg ("Noted.")
// Added for Quest 5.8 - KV
FinishTurn
}
else {
shownlink = false
if (game.echocommand) {
if (metadata <> null and game.enablehyperlinks and game.echohyperlinks) {
foreach (key, metadata) {
if (EndsWith(command, key)) {
objectname = StringDictionaryItem(metadata, key)
object = GetObject(objectname)
if (object <> null) {
msg ("")
msg ("> " + Left(command, LengthOf(command) - LengthOf(key)) + "{object:" + object.name + "}")
shownlink = true
}
}
}
}
if (not shownlink) {
msg ("")
OutputTextRaw ("> " + SafeXML(command))
}
}
if (game.command_newline) {
msg ("")
}
game.pov.commandmetadata = metadata
if (game.multiplecommands) {
foreach (alias, metadata) {
command = Replace (command, alias, Replace (alias, ".", "@@@DOT@@@"))
}
commands = Split(command, ".")
if (ListCount(commands) = 1) {
game.pov.commandqueue = null
HandleSingleCommand (Trim(Replace(command, "@@@DOT@@@", ".")))
}
else {
game.pov.commandqueue = commands
HandleNextCommandQueueItem
}
}
else {
game.pov.commandqueue = null
HandleSingleCommand (Trim(command))
}
}
}
]]></function>
<function name="GetDisplayAlias" parameters="obj" type="string">
if (HasString(obj, "alias")) {
result = ProcessText(obj.alias)
}
else {
result = obj.name
}
return (result)
</function>
<function name="ProcessTextCommand_Object" parameters="section, data" type="string"><![CDATA[
objectname = Mid(section, 8)
text = ""
colon = Instr(objectname, ":")
if (colon > 0) {
text = Mid(objectname, colon + 1)
objectname = Left(objectname, colon - 1)
}
object = ObjectForTextProcessor(objectname)
if (object = null) {
return ("@@@open@@@" + ProcessTextSection(section, data) + "@@@close@@@")
}
else {
if (LengthOf(text) = 0) {
text = SafeXML(GetDisplayAlias(object))
}
if (game.enablehyperlinks) {
linkid = ProcessTextCommand_GetNextLinkId()
colour = ""
if (HasString(object, "linkcolour") and GetUIOption("UseGameColours") = "true") {
colour = object.linkcolour
}
else {
colour = GetLinkTextColour()
}
style = GetCurrentTextFormat(colour)
text = Replace(Replace(text, "<", "<"), ">", ">")
return ("<a id=\"" + linkid + "\" style=\"" + style + "\" class=\"cmdlink elementmenu\" data-elementid=\"" + object.name + "\">" + text + "</a>")
}
else {
return (text)
}
}
]]></function>
</asl> |
Does this part look OK? (It seems to work, but I changed your code just a little.) if (game.multiplecommands) {
foreach (alias, metadata) {
command = Replace (command, alias, Replace (alias, ".", "@@@DOT@@@"))
}
commands = Split(command, ".")
if (ListCount(commands) = 1) {
game.pov.commandqueue = null
HandleSingleCommand (Trim(Replace(command, "@@@DOT@@@", ".")))
}
else {
game.pov.commandqueue = commands
HandleNextCommandQueueItem
}
} |
I think I made it a little more complex than it needs to be because I thought the alias from the object like would be used when echoing commands; but it looks like that always uses the default alias if there's a value in metadata; which seems weird to me. By default, I suspect it will work as intended because the alias passed back from a verb button is never displayed, and the default UI doesn't allow players to send multiple commands using an object link or the inventory panes. So it should work fine. On the other hand… I can see that this structure (the way command metadata is handled differently in 2 places) might be placing unexpected gotchas in the way of a hypothetical future user who wants to tweak the UI (for example, if you wanted to tweak the verbs menu to work with grammars other than "[verb] [object]"). That's probably something to deal with when it becomes relevant; but it's bouncing around in my head now. |
Please continue discussion on #1270 |
Hello I’m working on a game and I added portraits into the custom sidebar pane. I want them to be clickable so I copied the code for verbs menu into it. It shows the verb menu but doesn’t work if you click it (I can’t see that) and it’s the only thing I haven’t managed to implement in my own.
I think UpdateObjectLinks only scans the main body and not the custom pane. The html is identical yet acts differently, the text link works and the portrait link doesn’t. It’s the exact same html?
The text was updated successfully, but these errors were encountered: