Questions about DSB/ESB

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
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Questions about DSB/ESB

Post by Sophia »

Once a table has been defined for export, DSB will save the entire table.

DSB will also save all exvar values with the dungeon. Exvars also set the messages and targets of buttons and triggers, so, if they were not saved, the entire dungeon would basically cease to function. So, if something isn't getting saved properly, I think the problem is in your code somewhere.

As for "important_exvars", that's used by ESB, not DSB, in order to define the ordering of the list of exvars in the editor. It places "important" ones at the top, in the order defined, and then puts any others in alphabetical order beneath those.
User avatar
Lord_BoNes
Jack of all trades
Posts: 1064
Joined: Mon Dec 01, 2008 12:36 pm
Location: Ararat, Australia.

Re: Questions about DSB/ESB

Post by Lord_BoNes »

Sophia wrote:So, if something isn't getting saved properly, I think the problem is in your code somewhere.
It seems that you're correct here. The problem was a coding issue :oops:
 
Image

1 death is a tragedy,
10,000,000 deaths is a statistic.
- Joseph Stalin

Check out my Return to Chaos dungeon launcher
And my Dungeon Master Clone
User avatar
ebeneezergude
Expert
Posts: 345
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Questions about DSB/ESB

Post by ebeneezergude »

Lord_BoNes wrote:@Ebeneezergude: Isn't that the job of the "moneybox"? You can store craploads of coins/gems in the thing, and it keeps on storing more :P
Which is basically what Sophia said: making the "stack" a container and doing various tricks...
Oh, sorry, didn't see the "moneybox". A DM2 mechanic?
User avatar
Lord_BoNes
Jack of all trades
Posts: 1064
Joined: Mon Dec 01, 2008 12:36 pm
Location: Ararat, Australia.

Re: Questions about DSB/ESB

Post by Lord_BoNes »

It's not a "DM2 Mechanic" so to speak... it's part of the test dungeon and it requires it's own custom Lua code to work the way it does. As far as DSB is concerned, it's just a bottomless chest that holds coins/gems. Check out the test_dungeon/moneybox.lua to see the code I'm talking about.
 
Image

1 death is a tragedy,
10,000,000 deaths is a statistic.
- Joseph Stalin

Check out my Return to Chaos dungeon launcher
And my Dungeon Master Clone
User avatar
Lord_BoNes
Jack of all trades
Posts: 1064
Joined: Mon Dec 01, 2008 12:36 pm
Location: Ararat, Australia.

Re: Questions about DSB/ESB

Post by Lord_BoNes »

Another question: Is there a way to determine keyboard events (key presses/releases) in DSB? If not, could a pair of new events be introduced sys_key_press and sys_key_release?

EDIT: I'm also looking to intercept keyboard events while in a "fullscreen renderer" (like the dungeon entrance, for instance). Would that be possible?
 
Image

1 death is a tragedy,
10,000,000 deaths is a statistic.
- Joseph Stalin

Check out my Return to Chaos dungeon launcher
And my Dungeon Master Clone
User avatar
Chaos-Shaman
High Lord
Posts: 2642
Joined: Wed May 03, 2006 7:26 pm
Location: The Gates of Hell

Re: Questions about DSB/ESB

Post by Chaos-Shaman »

i should have saw it... yuuup, there's no stopping it now
keep your gor coin handy
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Questions about DSB/ESB

Post by Gambit37 »

I have a really basic question that I'm kinda stumped by: what's the "right" way to find the ID of a specific unique arch that might be placed anywhere in the entire dungeon? I can do all the cell loops and checks, but my main stumbling block is: how do I find out the total number of levels in the dungeon?

EDIT: I totally forgot about dsb_insts() and got hung up on counting the levels first to loop through them.

Although, the question still stands, if I did want to find out the total number of levels, is there a way to do it?
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Questions about DSB/ESB

Post by Sophia »

Actually, no!

There hasn't been a need for it until now. I guess there still isn't, actually. :mrgreen:
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Questions about DSB/ESB

Post by Gambit37 »

No problem, I figured I could just store the highest level number reached when iterating over all the insts: works great.

Another question: are there any performance or stability issues I should be aware of when using functions that call themselves? For example, I wanted to get the random RA door animation back from original DM, so I cloned 4 doors, each with a static bitmap in a different direction, then added this simple function.

It works fine, but I wondered if this is the right approach and if it's OK to do this sort of thing?

Code: Select all

function mhf_animate_door_ra(self, id)
	local timer = dsb_rand(1,4)
	local door = dsb_rand(1,4)
	dsb_delay_func(timer, function()
		dsb_qswap(id, "door_ra" .. door)
		mhf_animate_door_ra(self, id)
	end)	
end
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Questions about DSB/ESB

Post by Sophia »

That's clever, but it's unfortunately not going to work. You aren't running into any recursion issues and there is nothing inherently wrong with setting that up that way, but the problem is that DSB doesn't bother to try to serialize lambda functions, so it's not going to survive a save and load.

You'd need to use messages, probably. This could also be something that you might want a master "ra door controller" object in the dungeon that handles all of the swaps rather than a bunch of messages flying around each door autonomously.

Or I could just make animations support a randomized frame delay... :?
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Questions about DSB/ESB

Post by Gambit37 »

Cool, thanks for the insight. I thought there might be something weird I wasn't aware of. While the function worked OK, it felt wrong!

I'll investigate how to do the master RA Door controller you suggested. Is that something I'd need a trigger controller in the dungeon for, or would it be better to do it all in Lua?
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Questions about DSB/ESB

Post by Sophia »

You could build it entirely with dungeon mechanics for that authentic DM feel, but you'd end up with the sort of crazy mess of mechanics and actuators that made me add Lua scripting as such an integral part of the game in the first place. :mrgreen:

My suggestion is to make a ra_door_controller arch and place one (and only one) inst of that somewhere in the dungeon. Send it a next tick message from somewhere else to get things going, and then give it a msg_handler for that message that uses dsb_insts to grab a list of all of the ra doors in the dungeon (it need only do this once and store them away, unless you think you're going to be dynamically creating and destroying doors!) and randomize them, then it can send itself a next tick message in a tick or two and do it all again.

I can help you with the actual code if needed but this should hopefully be enough to get you started.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Questions about DSB/ESB

Post by Gambit37 »

Great, thanks, I'll investigate and see if I can get it working with messages.

Another question: How would I increase the default quiver area from 4 items to 6? Or add an extra slot to the pouch?
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Questions about DSB/ESB

Post by Sophia »

You'd need to edit the inventory_info table in base/inventory_info.lua and define some new slots. The current quiver slots are sequential but there is no rule they have to be, so I'd recommend just putting your new slots in at the end. You can start at MAX_INV_SLOTS. (Don't redefine this variable though, even if you're adding more slots; it's somewhat poorly named)

In DSB 0.69, it won't search your new slots for ammo, but I was already planning on changing that for 0.70, so I'll just give you the DSB 0.70 code right now. You don't need to add this to your dungeon because it'll be part of the base code in the next DSB, so for now just replace search_quiv_for_ammo in base/methods.lua with the following code:

Code: Select all

function search_quiv_for_ammo(who, need_type)
	local qloclist = inventory_info.quiver_locations
	local ploclist = inventory_info.pouch_locations
	
	-- fall back to the hardcoded list
	if (not qloclist) then qloclist = { INV_QUIVER, INV_QUIV2, INV_QUIV3, INV_QUIV4 } end
	if (not ploclist) then ploclst =  { INV_POUCH, INV_POUCH2 } end
	
	local qammo
	qammo = search_llist_for_ammo(who, need_type, qloclist, false)
	if (not qammo) then
	    qammo = search_llist_for_ammo(who, need_type, ploclist, false)
	    if (not qammo) then
	        qammo = search_llist_for_ammo(who, need_type, qloclist, true)
		end
	end
	return qammo
end
After making that change, you'll be able to add quiver_locations to your inventory_info and DSB will search for ammo in the new locations. For example, if you added INV_QUIV5 and INV_QUIV6 slots, you just need to add this line:

Code: Select all

inventory_info.quiver_locations = { INV_QUIVER, INV_QUIV2, INV_QUIV3, INV_QUIV4, INV_QUIV5, INV_QUIV6 }
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Questions about DSB/ESB

Post by Gambit37 »

That's so cool, thank you :)
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Questions about DSB/ESB

Post by Gambit37 »

I have the RA door thing half working: I can get all the doors to show a different image after a randomised delay, but they all share the same delay so are in sync with each other, which isn't what I want. It does still work after a save/load though, which is great :)

I'm not sure how to send each door a different delay, so that each door is independently qswapped from all the others at a different time?
EDIT: Hmm, I'm looking at two RA doors next to each other and they are in fact animating out-of-sync with each other. Which is what I want, but I don't understand how that's happening, lol!

These are the various bits of code I have so far, firstly I defined a global to store the ID of the RA door controller:

Code: Select all

radoor_controller = 0
Then the controller arch definition:

Code: Select all

obj.radoor_controller = {
	type="FLOORFLAT",
	class="MECHANICS",
	msg_handler=mhf_radoor_msg_handler
}
Then the message handler:

Code: Select all

mhf_radoor_msg_handler = {
	[M_NEXTTICK] = "mhf_swap_radoors",
	[M_ACTIVATE] = "mhf_swap_radoors",
	[M_TOGGLE] = "mhf_swap_radoors"
}
Then my setup function (which runs as part of the game startup) looks for the controller and any RA doors, and stores the RA door IDs in the controller:

Code: Select all

function mhf_setup_radoor_controller()
	
	local radoor_ids = {}

	-- Look for RA doors and a RA door controller in the dungeon:
	for id in dsb_insts() do
		local arch = dsb_find_arch(id)
		if (arch == obj.radoor_controller) then
			radoor_controller = id
		elseif (arch == obj.door_ra) then
			table.insert(radoor_ids, id)
		end
	end

	-- If we have a controller and some RA doors, then store the
	-- RA door ids in an exvar on the controller, and send an
	-- initial message to the controller to get it started:
	if (radoor_controller and (table.getn(radoor_ids) > 0)) then
		use_exvar(radoor_controller)
		exvar[radoor_controller].door_ids = radoor_ids
		dsb_msg(1, radoor_controller, M_NEXTTICK, 0)
	end

end
Finally the function called by the message handler to do the qswapping:

Code: Select all

function mhf_swap_radoors()

 	-- Loop through all the RA doors we stored earlier,
 	-- and qswap each door for a random "flip" direction:

 	local door_ids = exvar[radoor_controller].door_ids

 	for id = 1, table.getn(door_ids) do
		local door = dsb_rand(1,4)
		dsb_qswap(door_ids[id], "door_ra" .. door)
 	end

 	-- Repeat this function with a random delay:
 	local timer = dsb_rand(1,6)
	dsb_msg(timer, radoor_controller, M_NEXTTICK, 0)

end
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Questions about DSB/ESB

Post by Sophia »

The radoor_controller global isn't needed, actually. Every message handler function is actually passed three parameters: id which is the id of the inst that got the message, data which is the data parameter, and sender which is the id of the inst that sent the message. So this code is equivalent (and more robust):

Code: Select all

function mhf_swap_radoors(id, data, sender)
 	if (not exvar[id]) then return end
 	local door_ids = exvar[id].door_ids
 	-- etc etc
end
The code swaps all doors at the same random interval, so all swaps are synchronized. The reason any given two doors might appear to be out of sync is that your code makes no guarantee that the image swapped to is different from the door's current image. So 25% of the time, there will be no visible swap. You can actually take advantage of this in order to decrease the amount of apparent synchronization.

Code: Select all

 	
 	for i = 1, table.getn(door_ids) do
 		if (dsb_rand(1, 2) == 1) then
			local door_arch = dsb_find_arch(door_ids[i])
			local doorname = nil
			while (not doorname or obj[doorname] == door_arch) do
				doorname =  "door_ra" .. dsb_rand(1,4)
			end
			dsb_qswap(door_ids[i], doorname)
		end
 	end

 	-- Repeat this function with a random delay:
 	local timer = dsb_rand(1,3)
	dsb_msg(timer, id, M_NEXTTICK, 0)
This reduces the swap interval by half but also adds a 50% chance the door won't be swapped at all. I've also made sure the swap is to a different arch. You can play with these numbers to get the kind of effect you want, I think.

EDIT: Fixed the code.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Questions about DSB/ESB

Post by Gambit37 »

Cool, thank you for the revisions, these work great :)

Regarding setting the ID of an INST to a global variable:

I have a unique arch object that I'm using to store gameplay data. I have a dsb_insts() loop in my startup that looks for that arch/inst, and assign its ID to a global variable store_data. I can then refer to this in many other functions when I want to store long-term variables, by using exvar[store_data].variable etc. (I ended up preferring this over exporting variables: for some reason an object in the dungeon that stores all my data seems to make more sense to me conceptually, and seems easier to manage.)

Anyway, the approach seems to work fine, but I'm aware it's possibly fragile and "not the DSB way".

So what would be a more robust solution? Do I need to use dsb_insts() to look for my arch/inst every time I want to refer to it in another function? This seemed like a performance issue to me which is why I was avoiding it, but is that the best way? Or is there another best-practice method I should be using?
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Questions about DSB/ESB

Post by Sophia »

The "best" solution is probably to store the data in an exported table. That is:

Code: Select all

dsb_export("data_table")
data_table = {
    some_number = 1,
    some_string = "hello",
    -- etc.
}
If you don't want to do that for whatever reason, then your approach works fine.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Questions about DSB/ESB

Post by Gambit37 »

Cool, thanks, yeah for some reason I couldn't get my head around exports in the context of program flow and resuming save games. I've never been able to get that stop/start sound channel thing to work as a result. (Could really do with a stop_all_sounds() function to be honest!).

Anyway, next questions.

(1) What, if anything, can be customised about the width/height of the console? (And what is the default expected size?)
(2) Would it be possible to add support for custom sized party order icons? I'd like to use the ones from DM2, but they're bigger than those in DM.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Questions about DSB/ESB

Post by Gambit37 »

Quick question about #1 above: There's a note in the wiki about dsb_textformat() controlling the y offsets for the console.

I've been using this function to create wrapping text in other contexts. Can I also use it somehow to auto-wrap text in the console created by dsb_write()?

Or does the output of DSB write always need to be manually created? (IE, I need to use some kind of line-splitting function, as currently used in scrolls?)
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Questions about DSB/ESB

Post by Sophia »

Although a "console" is the modern term for what you would call the lines of text at the bottom of DSB's screen, it's actually pretty threadbare. It's just text dumped to a certain location on the screen. There is currently no support for word wrapping of anything of that sort.

The easiest approach would probably be to write a wrapper function that may make multiple calls to dsb_write if you pass it a long line of text. If this is sufficient, I can probably come up with something without too much trouble.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Questions about DSB/ESB

Post by Gambit37 »

Thank you, but not to worry, I found an example of what I needed on StackOverflow :)
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Questions about DSB/ESB

Post by Gambit37 »

Is there a way to change the duration of text displayed by dsb_attack_text()?

Or how would I write my own function to display something in that feedback area, for a specified amount of time?
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Questions about DSB/ESB

Post by Sophia »

Right now, the only way you can change what is shown is by writing your own sys_render_attack_result but then of course you have to override that whole function and you're responsible for everything. If you wouldn't mind going into more detail about what you want then I could perhaps work in a simpler way.

Right now the time that the text is shown is hardcoded, but I could pretty easily add a second parameter to the function to allow you to change that.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Questions about DSB/ESB

Post by Gambit37 »

I'm happy to override the whole function and have done so for this interface I'm working on. However, I had an idea about providing graphical feedback for other actions in this area, so instead of just specifying "damage burst" or "text", I'd like to render some other stuff instead. I don't want to give too much away here, but if you need more details, let me know and I'll send you a private message.

A duration parameter would definitely be useful, too :) It's currently slightly too fast for what I have in mind.
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Questions about DSB/ESB

Post by Sophia »

If you're writing your own custom renderer anyway, it seems like the easiest workaround (and keeps me from having to write any new code) would be to check if certain special text strings are passed and, if so, render special things. For example, you could write a custom sys_render_attack_result that draws Mophus's portrait if it gets passed "_DSBMOPHUS", which you could then pass via dsb_attack_text. This is the easiest way, but doesn't work if you need to pass any parameters of data, though.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Questions about DSB/ESB

Post by Gambit37 »

OK, here's a probably very basic question: how can I make a destructible floorupright? For example, a blocking mound of rubble that can be attacked with a weapon and reduced to stones/boulders. I'm kinda embarrassed I can't work this out as I'm sure it should be pretty easy...?
User avatar
Sophia
Concise and Honest
Posts: 4239
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Questions about DSB/ESB

Post by Sophia »

It's actually not that straightforward because the base code doesn't support weapon attacks against anything other than monsters and doors. The simplest fix might be to just put an invisible door on the square and have it respond to an M_BASH message by doing whatever it is you want. The data parameter of M_BASH is 0 if the door is just getting hit (in DM it goes thud) or 1 if the door should actually get destroyed.
User avatar
Gambit37
Should eat more pies
Posts: 13714
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Questions about DSB/ESB

Post by Gambit37 »

Ah cool, thanks, sounds like that would work. I'll try it out :)
Post Reply