Inventory view customisation

This forum is for the Lua scriptable clone of DM/CSB called Dungeon Strikes Back by Sophia. Use DSB to build your own highly customised games.

Moderator: Sophia

Forum rules
Please read the Forum rules and policies before posting.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Inventory view customisation

Post by Gambit37 »

Me again! :D

I'm re-designing the DM inventory screen, and have thought of some ways to improve it. However, I don't know how to code this in DSB. This is what I want to do:
  1. Add an extra button to the inventory screen
  2. Display a custom sub-renderer when the button is clicked. (I also want the sub-renderer to stay open after the button is clicked)
  3. Allow interaction (clicks) within the new subrenderers (ie, get user input and respond to it, like in a full-screen renderer)
Please would it be possible to get some help with this? (I'm probably OK with parts of #2, but the other stuff doesn't seem to have any examples anywhere that I can find...)
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Inventory view customisation

Post by Sophia »

Adding buttons is accomplished via dsb_msgzone, which has some examples (albeit somewhat opaque ones) in base/render.lua. You'll probably want to write your own h_custom_inventory function of the form:

Code: Select all

function h_custom_inventory(bmp, who, name_draw_type, final)
   if (final == true) then
      -- add dsb_msgzone or whatever here
   end
   return false
end
You actually asked about dsb_msgzone some years ago, in this thread. The method of using a function_caller still works, of course, although there is more information on the "correct" approach on the wiki now.

You can then have a your own h_custom_mainsub that checks some variable that was set by the msgzone and overrides the main subrenderer for however long it takes; it can of course have its own dsb_msgzone calls that add more buttons.

I understand that this is all still probably a bit unclear so feel free to ask questions!
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

Wow, I'd totally forgotten I'd asked about this before...! :shock: 6 years ago!

I understand these hooks slightly better now. It was clever of you to allow the text to be added to, rather than obliterated by a custom function :)

But back to the issue of adding a button to the inventory. Lets check my understanding: If I want a new button in my inventory that, for example, pops up a full screen renderer, then I think I need these various moving parts:

1) A new user defined system message, eg, SYS_MYSCREEN = 32
2) Within the new inventory hook, add a message zone for this message (should the third number be 0?)

Code: Select all

function h_custom_inventory(bmp, who, name_draw_type, final)
   if (final == true) then
      dsb_msgzone(bmp, SYSTEM, 0, x, y, w, h, SYS_MYSCREEN)
   end
   return false
end
3) A new system function for SYS_MYSCREEN to do the full screen renderer.

^^ This is the bit I've no idea about ^^^

In that old thread you said "Then, write sys_system_message, which by default does nothing, to handle your message." I don't follow this bit, please could you elaborate in the context of my example? How should this be named, and what parameters will it accept?

I think I'm more or less getting there, but need a bit more help. Thank you :)
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Inventory view customisation

Post by Sophia »

The third parameter is the zone id. If two zones on the same screen have the same zone id, then the first one will get replaced. You can specify AUTOMATIC and DSB will assign you a unique id so you can be sure this won't happen, which is probably what you want to do in this case.

Your sys_system_message function will probably look like this:

Code: Select all

function sys_system_message(msg, data, ext_data)
	if (msg == SYS_MYSCREEN) then
		-- do whatever!
	end

	return nil
end
If you want to pop up a fullscreen renderer, that's where you'd put your call to dsb_fullscreen for example.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

Superb, thanks for clarifying. That's the last piece of the puzzle I was missing. I think I can now do all the stuff I was aiming to! Fantastic, thank you. :)
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

Regarding sub-renderers: can you point me in the right direction for how to create msgzones and responses for a tabbed interface? How would I do something like this, where each tab responds to a click and displays different information? I'm still not 100% sure how to send a msgzone message back into the sub-renderer itself?

Image

EDIT: After looking at the moneybox example on the test dungeon, I think I can see how to do it. Send the messages to the SR instance, but with a data parameter for each "tab", then respond to the value of that tab with some code to draw the relevant page of data, eg:

Code: Select all

dsb_msgzone(sr, SYSTEM, AUTOMATIC, X1, Y1, W, H, M_NEXTTICK, 1)
dsb_msgzone(sr, SYSTEM, AUTOMATIC, X2, Y2, W, H, M_NEXTTICK, 2)
dsb_msgzone(sr, SYSTEM, AUTOMATIC, X3, Y3, W, H, M_NEXTTICK, 3)
Is this the right approach?

Also, are subrenderers still restricted to 246x146? If I wrote a whole bunch of new replacements, could they be custom sizes?
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

I don't want to overload this thread with too many questions at a time, but I'm having problems with a custom msg zone.

I tried adding an extra button & message zone to the custom inventory hook. The bitmap is drawn correctly, but the msgzone doesn't work and generates four identical errors in the log file:

LUA ERROR: dmredux/code/hooks.lua:24: dsb_msgzone: Invalid msgzone target

What I've got:

1) A new global SYS_OPTIONS = 1
2) My changes to h_custom_inventory in my own hooks.lua:

Code: Select all

function h_custom_inventory(bmp, who, name_draw_type, final)
	-- Custom rendering and msgzones
	if (final == true) then
		-- Options Button
		dsb_bitmap_draw(gfx.ui_icon_options, bmp, 390, 8, false)
		dsb_msgzone(bmp, SYSTEM, AUTOMATIC, 390, 8, 20, 20, SYS_OPTIONS)
	end
	-- Normal rendering
	return false
end
3) A function call for that message in sys_system_message:

Code: Select all

function sys_system_message(msg, data, ext_data)
	-- Options Screen
	if (msg == SYS_OPTIONS) then
		mhf_options()
	end
	return nil
end
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Inventory view customisation

Post by Sophia »

That msgzone error is probably a bug in DSB. I'll investigate it and let you know.
(I'll answer the rest once I've sorted out this bug!)
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

If it helps, the msgzone and custom sys message works perfectly if I embed it in the sys_render_other function. So the bug might be specific to the inventory renderer?
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Inventory view customisation

Post by Sophia »

This is actually sort of a mess. Expect 0.71 soon. :roll: :oops:
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

Cool, now that the msg_zone thing is fixed in 0.71, I'll repost my earlier enquiry as I think it got missed:

Regarding sub-renderers: can you point me in the right direction for how to create msgzones and responses for a tabbed interface? How would I do something like this, where each tab responds to a click and displays different information? I'm still not 100% sure how to send a msgzone message back into the sub-renderer itself?

Image

EDIT: After looking at the moneybox example on the test dungeon, I think I can see how to do it. Send the messages to the SR instance, but with a data parameter for each "tab", then respond to the value of that tab with some code to draw the relevant page of data, eg:

Code: Select all

dsb_msgzone(sr, SYSTEM, AUTOMATIC, X1, Y1, W, H, M_NEXTTICK, 1)
dsb_msgzone(sr, SYSTEM, AUTOMATIC, X2, Y2, W, H, M_NEXTTICK, 2)
dsb_msgzone(sr, SYSTEM, AUTOMATIC, X3, Y3, W, H, M_NEXTTICK, 3)
Is this the right approach?

Also, are subrenderers still restricted to 246x146? If I wrote a whole bunch of new replacements, could they be custom sizes?
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Inventory view customisation

Post by Sophia »

It was not missed! Bug fixes took priority.

Anyway, another thing that I'd do if I were starting DSB over today is dispense with all the specialized object types and just make everything an object instance: party members, conditions, subrenderers, etc. However, since subrenderers are not instances, you can't send them messages, so your method won't work.

Instead, define a new system message, like SYS_SWITCHTAB, and send that as your message in the tabs' msgzones. System messages can send two parameters so you could also send who as a parameter if you don't want to force everyone's inventory to be looking at the same tab at the same time. In sys_system_message add code to handle this case, and store the displayed tab in a variable. If you're doing it per-character you could store it as a ch_exvar, which is like an exvar for characters. Regardless, you can use that variable in your renderer (which is probably h_custom_mainsub but I don't know exactly what you are doing with it) and draw the correct tab.

Subrenderers are still 246x146 mostly because there was no compelling reason to support any other size. I guess it depends on what you want to actually do.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

Aha, right, I think I understand all that. Nice solution, thank you :)
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

Something I'm struggling with in the inventory is lack of space. In an effort to get more, I've considered splitting the whole area into separate panels accessible by separate icons. However, I'm not sure if DSB can handle it:

Some questions:
  1. Can the backpack/pouch items be made hidden and inactive, then re-enabled when a button(msgzone) is clicked? IE, within some kind of tabbed interface?
  2. Could I conceivably override the entire inventory, and activate my own full-screen replacement? I know this puts the game in pause mode and therefore removes the real-time element while looking in your backpack... I just want to know if it's possible in theory? (Basically, could I have the user moving items between their inventory dropzones while in a full screen renderer?)
No worries if this isn't possible, I just want to understand if it's something worth experimenting with.
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Inventory view customisation

Post by Sophia »

Both of these are doable!

The first option is probably better because then you don't have to redo all that logic yourself, and it still feels like the DM inventory.

So, about the first option, there is no explicit option to hide inventory items, but inventory_info doesn't include any bounds checking on the Lua side, so you could just set the x coordinate to -100 or something and that slot will seemingly vanish. You could also store the existing coordinate somewhere in the table to get it back later. Something like this (untested, though)

Code: Select all

function hide_slot(s)
   inventory_info[s].realx = inventory_info[s].x
   inventory_info[s].x = -100
end

function show_slot(s)
   inventory_info[s].x = inventory_info[s].realx
end
After you've done all the changes to inventory_info you want, you have to call dsb_update_inventory_info() to tell the engine to flush its caches and stuff, or you'll probably have big problems.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

Ah, a creative and sneaky solution, I like it! :)
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

Oops, so much for my creative idea, I just realised that if I do this approach, then it would be impossible to get stuff out of a chest because if the backpack slots are hidden, where would the player drop the items they took from the chest? I'll have to carefully determine if there's a workable layout for this.

The main problem is the fixed size for subrenderers: it's very hard to make any changes to the inventory layout when all the subrenderers share the same size and position. Is there any way around that?
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Inventory view customisation

Post by Sophia »

The subrenderer position can already be changed in inventory_info. I could make it so you could change the size too but that would more or less break everything that uses subrenderers. It could be a lot of work for you.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

Not to worry! It's become very clear to me that FTL must have iterated the hell out of this UI (Doug said as much when I interviewed him years ago.) They must have tried every possible permutation that would give them the maximum amount of functionality in the minimum amount of space. It's so precisely configured (and actually quite elegant) that trying to "improve" it is basically impossible without taking a completely different approach.

I've decided to leave it mostly alone now and will just implement a small subset of changes that I think *will* improve it a little. That said, I *do* have some ideas for a totally different approach, but that will have to wait for another project ;-)
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

Returning to this, I can't get the "add a simple button to the inventory" to work. I'm using the method outlined previously

Code: Select all


global.lua
SYS_OPTIONS = 32

hooks.lua
function h_custom_inventory(bmp, who, name_draw_type, final)
	-- Custom rendering and msgzones
	if (final == true) then
		dsb_bitmap_draw(gfx.ui_icon_options, bmp, 300, 8, false)
		dsb_msgzone(bmp, SYSTEM, 50 + dsb_char_ppos(who), 300, 8, 20, 20, SYS_OPTIONS)
	end
	-- Normal rendering
	return false
end

sys.lua
function sys_system_message(msg, data, ext_data)
	if (msg == SYS_OPTIONS) then
		mhf_options()
	end
	return nil
end

This does render my "options" bitmap when viewing an inventory, but the message zone is extremely flaky. It doesn't matter whether it's AUTOMATIC or using specific numbers as in the example above, it only works reliably for the champion who's inventory is first viewed (although the actual pixels that respond to the clicks seem to be a bit, uh, flexible -- sometimes have to click further left or right than expected!). For other champions, the button either doesn't work at all, or only very occasionally respond to a click.

Any ideas on why these msgzones aren't reliable?

(Incidentally, is there a way of getting msgzones to render their size/position onscreen for debugging to see exactly where they are? Would save lots of guess work.)
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

Additional info: it seems the message zones for my new button are more receptive (and reliable) once I've moved something into the champion's hand! Seems to be something weird going on here...
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Inventory view customisation

Post by Sophia »

None of this makes any sense at first glance so I think I am going to need you to send me something that reproduces the problem. :)
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

Heh, I thought you would say that. :) OK, is it safer to send you the entire project? It's big, but perhaps there's other weird stuff I've done that's causing the issue and so you might need all of it.
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Inventory view customisation

Post by Sophia »

If that's easiest I can work with that!

EDIT: Oh, if you want the clickzones to be visible, you can add "Debug = 1" to the "[Settings]" section of dsb.ini.
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Inventory view customisation

Post by Sophia »

I poked around in the code and found a possible culprit. Try this new exe and see if that fixes your issues. If it doesn't work then I will need to look at your dungeon.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

I'd just prepped a zip of my dungeon to send you, came back and saw your test exe... tried it out and it seems to fix all the problems! Awesome, thank you! :D What was the problem, out of interest?

Do you still want my dungeon at all, happy to send if it's still useful?

(EDIT: Just tried the debug mode with 0.75 and 0.75a -- in 0.75 the msgzone flickers on and off and changes its state randomly depending on which champion is being viewed and whether they have something in hand or not. In 0.75a there's no flickering and it behaves exactly as I'd expect. Curious bug, thanks for tracking it down and squashing it, it was driving me nuts -- I thought my code was wrong!)
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Inventory view customisation

Post by Sophia »

Gambit37 wrote: Thu Mar 05, 2020 11:42 pmWhat was the problem, out of interest?
Versions of DSB prior to 0.71 couldn't target the inventory screen directly with Lua clickzones; that fix is actually a bit earlier in this thread. But anyway, when I added that, I left some code in the subrenderer handler related to clickzones (that wasn't supposed to be there anymore) so every time the subrenderer bitmap got destroyed, the clickzones got destroyed too, which is why they'd flicker on and off.
Gambit37 wrote: Thu Mar 05, 2020 11:42 pmDo you still want my dungeon at all, happy to send if it's still useful?
Thanks but I don't think I need it if the new exe works properly.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

Regarding custom message zones in subrenderers (discussed above), I get an error if I use one inside an original subrenderer function eg, sys_render_mainsub(who), or inside its related custom subrenderer function, eg h_custom_mainsub(who, final).

I've tried adding a msgzone in both cases, such as:

Code: Select all

dsb_msgzone(sr, SYSTEM, 12, 0, 2, 30, 36, SYS_CHANGE_INVENTORY_TAB, 1, who)
But DSB generates an error:

Code: Select all

LUA ERROR: dmxtra/code/ui_render.lua:736: dsb_msgzone: Invalid msgzone target
If I create a msg zone over a bitmap, it works fine, eg inside function sys_render_inventory_text(bmp, who, name_draw_type). But any function that renders a sub renderer using dsb_subrenderer_target() creates the error above when I add a msg zone inside it.

Not sure if I'm doing something wrong, or if there's a bug here?
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Inventory view customisation

Post by Sophia »

It's probably a bug. For historical reasons (i.e., a bunch of ugly code from like 10 years ago that I don't feel like ripping out and rewriting) any "subrenderer" not associated with an inst in the hand is handled totally differently, because Lua formerly didn't have access to that stuff all. There's still a relic of this in DSB's resurrection and reincarnation interface, which is still not exposed to Lua for a similar reason. Anyway, dsb_msgzone was never updated with this expanded idea of what a "subrenderer" was so it thought you were passing it an invalid bitmap.

Here is another new exe that should fix it.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Inventory view customisation

Post by Gambit37 »

Thanks for the speedy update! Unfortunately that version crashes as soon as I try to view the inventory (whether or not I've defined any new message zones in the subrendrerer)

Code: Select all

PROGRAM CRASH!
Location: 0 9 9
Reason: Segmentation Fault
Stack Dump:
DSBmain
DSBgameloop
render_inventory_view
call_lua_inventory_renderer
lua.dsb_msgzone
Post Reply