Level size, offsets etc.

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.
Post Reply
User avatar
Joramun
Mon Master
Posts: 925
Joined: Thu May 25, 2006 7:05 pm
Location: The Universe

Level size, offsets etc.

Post by Joramun »

Note: this discussion arise from the "DDM bug report and suggestions" topic, where Par and RemyR pointedly made remarks about level size etc.

1/
I wonder how does DSB react if levels in the same dungeon have a different size... I'm going to try, but as anyone who has opened DM and CSB lua files might see, I assumed for RTSB that all levels had to be the same size.
(Otherwise, I would have cut the extra rows on east and south sides)

2/
DSB doesn't use (x,y) offsets, so you'd have to implement them by hand in the pit/staircase coordinate system.

3/
There is no such thing as a vertical order implemented in the code, aside from the fact pits/stairs "teleport" you by one level by default. So you can also set a stair / pit to "teleport" you anywhere.
(e.g. a pit that falls on itself)
(Note : this can be done for stairs, meanwhile pits currently use only the default (x,y,lev+1) target coordinates -- but you can always override the base code for pits and change their behavior to match those of stairs)

4/
In the case anyone would fancy doing it (I did), You can define level numbers by names and design your dungeon non linearly without having to care about vertical order.
(e.g in startup.lua : HALL_OF_CHAMPION = 0, HELL = 14, and then :
dsb_text2map(HALL_OF_CHAMPION ...) etc. )

5/
What happens if one implements level X+1 before level X in the code ?
(I have to try that, too)
What Is Your Quest ?
User avatar
Parallax
DMwiki contributor
Posts: 424
Joined: Mon Aug 28, 2006 7:56 pm
Location: Back in New Jersey

Post by Parallax »

with respect to point 4/, let me add that you don't even have to have a level 0, a level 1 etc... You can start your dungeon at level 100 if you feel like it. In fact, if you have disconnected areas, it might be a good idea to have the first area reserve levels 100-199, the next one levels 200-299, etc...

For DDM, it seems that level number could actually be a property of a level, much like xp multiplier or light level. I mean, ultimately it's up to RemyR, I'm just saying.
User avatar
Joramun
Mon Master
Posts: 925
Joined: Thu May 25, 2006 7:05 pm
Location: The Universe

Post by Joramun »

Parallax wrote: I mean, ultimately it's up to RemyR, I'm just saying.
Yeah, I'm just saying, too. :wink:

But what happens is that we're the lobby of consumers.
It's a very powerful assembly of people that whine about everything that's not perfect and cheap, or free. We want to CONSUME everything.
What Is Your Quest ?
Remy
Craftsman
Posts: 111
Joined: Wed Sep 05, 2007 5:24 pm
Contact:

Post by Remy »

I've already done some of this testing - I had to because of certain ways DDM works.

Levels can be different sizes, and they can be coded in any order you want. The only caveat to that is that you must create the level first before you can do anything to it, such as assigning it a wallset or spawning anything on it.
There's also a problem with spawning pits. It's not just their behavioral code, they simply can't be spawned unless there's a level below them and that level has open space matching their position (i.e. - they don't drop onto a wall). If you want to have "weird" pits, you have to do a bit of tricky coding - use a fake-pit with a trigger, which triggers a teleporter on the same tile and a floor damager on the tile located at the "landing" position.

DDM already stores a level's positional number, which does not neccesarily match it's index number in the dungeon's Level collection (which is probably just gibberish to most of you, but it means it already exists as a seperate and editable property). I've just never exposed it because I didn't think anyone would have a reason to change it.
I'd have to test it, but exposing it shouldn't be a problem. The only wierdness that may result is in the Up Level and Down Level arrows on the toolbar - they navigate through the dungeon's level collection by it's order, not the order of a level's LevelNum property. You'll see the screwyness at once though, if you've reordered the levels. The tab label at the top of a map page (and the listing in the dungeon listing panel) uses the actual LevelNum. So you might see "Level: 1" -> "Level: 3" -> "Level: 2" while looking at the navigation.
And another technical note - levels are written to code by there index position in the dungeon's collection, so if you've assigned them different numbers, they will be generated out-of-order. Again, this is fine as far as DDM and DSB compatibility, since DDM doesn't start spawning items until all the levels are coded. It also doesn't assign a wallset until the level is created, and it uses the LevelNum property to do so.
User avatar
Sophia
Concise and Honest
Posts: 4240
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Post by Sophia »

DSB has a rather openended model for defining levels, as with many other things.

All levels are assumed to be vertically stacked, with (0,0) being the base for all levels. This concept is relatively abstract, though. As has been pointed out, stairs can already be pointed anywhere, and through some not-too-difficult overriding of the base code, it's possible to redefine the increasing of the level number as "up" instead of "down," or create pits that can also go anywhere, or whatever else.

You don't have to define level 1 before you define level 2, or anything like that. If you create a level more than one number higher than the currently existing level, DSB will have no problem with it. DSB will happily accept definitions for level 0 and level 99, and leave all of the levels in between undefined-- just don't try to go to them!

So, your ideas of using symbolic level numbers or leaving large areas undefined for future expansion are both good. :)

Tech Note: Strictly speaking, the levels are in an array, so the levels will be defined, but they'll be regarded as 0x0 and, as such, any square you access will be regarded as outside of the level. It should also be noted that the amount of memory used by a blank level is trivial (under 50 bytes), so you shouldn't hesitate to use large blank spaces if it make design easier.
RemyR wrote:If you want to have "weird" pits, you have to do a bit of tricky coding - use a fake-pit with a trigger, which triggers a teleporter on the same tile and a floor damager on the tile located at the "landing" position.
No! This is how you do it in engines that don't let you define object archetypes completely from scratch and give them arbitrary behavior! :P
In the long run, it'd be easier to code up your own "weirdpit" archetype that had destination exvars, like a teleporter. ;)
Remy
Craftsman
Posts: 111
Joined: Wed Sep 05, 2007 5:24 pm
Contact:

Post by Remy »

In the long run, it'd be easier to code up your own "weirdpit" archetype that had destination exvars, like a teleporter
Oh, sure, if you want to do it the right way, but who wants to do that? :)

And, by the way, I just did a few tests, and I'm wrong about the whole "pits must have a level below them" thing. I'm not really sure where I came up with that, but you can spawn pits on a bottom level just fine; it won't crash until you step on them.

And, because I was bored, here's some code for a telepit - which is basically a teleporter that looks like a pit and hurts you if you step on it.

Code: Select all

obj.telepit = {
	type="FLOORFLAT",
	class="PIT",
	same_square=gfx.pit_front[0],
	front=gfx.pit_front[1],
	front_med=gfx.pit_front[2],
	front_far=gfx.pit_front[3],
	near_side=gfx.pit_side[0],
	side=gfx.pit_side[1],
	side_med=gfx.pit_side[2],
	side_far=gfx.pit_side[3],
	no_monsters=pit_no_monsters
}

function obj.telepit:on_trigger(id, what)
        if (what) then
                local lev, xc, yc, face = dsb_get_coords(what)
                if(exvar[id].lev) then
                        lev = exvar[id].lev
                else
                        lev = lev + 1
                end
                if(exvar[id].x and exvar[id].y) then
                        xc = exvar[id].x
                        yc = exvar[id].y
                end
                if(exvar[id].face) then
                        face = exvar[id].face
                end
                if(exvar[id].spin) then
                        face = (face + exvar[id].spin) % 4
                end

                arch = dsb_find_arch(what)

                if (arch.type == "THING") then
                        local fly = dsb_get_flystate(what)
                        if (not fly) then
                                dsb_move(what, lev, xc, yc, face)
                        end
                elseif (arch.type == "MONSTER") then
                        if (not arch.hover) then
                                dsb_move(what, lev, xc, yc, face)
                        end
                end
        else
                dsb_sound(snd.scream)
                dsb_delay_func(1, dsb_lock_game)
                dsb_delay_func(5, function()
                        local lev, xc, yc, face = dsb_party_coords()
                        dsb_unlock_game()
                        if(exvar[id].lev) then
                                lev = exvar[id].lev
                        else
                                lev = lev + 1
                        end
                        if(exvar[id].x and exvar[id].y) then
                                xc = exvar[id].x
                                yc = exvar[id].y
                        end
                        if(exvar[id].face) then
                                face = exvar[id].face
                        end
                        if(exvar[id].spin) then
                                face = (face + exvar[id].spin) % 4
                        end
                        dsb_party_place(lev, xc, yc, face)
                        pit_damage(20)
                end)
        end
end
Note, that while you don't need to specify all the exvars, if you specify an 'x' you must specify a 'y', and vice versa, otherwise they'll be ignored.
Another Note: this code must be included in "\(Dungeon)\objects.lua" - for some reason 'startup.lua' and any files it calls through 'lua_manifest' don't have access to the obj table.
User avatar
Sophia
Concise and Honest
Posts: 4240
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Post by Sophia »

RemyR wrote:And, by the way, I just did a few tests, and I'm wrong about the whole "pits must have a level below them" thing. I'm not really sure where I came up with that
My guess would be from using spawn_pit with a non-false value for the ceiling pit parameter. It will automatically create a ceiling pit on the level below, and will result in an error if there is no level below. :)
User avatar
Parallax
DMwiki contributor
Posts: 424
Joined: Mon Aug 28, 2006 7:56 pm
Location: Back in New Jersey

Post by Parallax »

Thanks for the telepit, RemyR, I like it.
Remy
Craftsman
Posts: 111
Joined: Wed Sep 05, 2007 5:24 pm
Contact:

Post by Remy »

My guess would be from using spawn_pit with a non-false value for the ceiling pit parameter
Oh, yeah....

Which reminds me, that code above won't work with spawn_pit. In fact, there's no way to chain it to a ceiling pit during it's spawn, since it relies on exvars, which can only be assigned after a spawn.
So, I wrote a function to cover it, as well as a override for method_climb_down that works with the tele_pit (yes, it got a new name, too).

It's too long to post as code, so you can Download here.
It's basically the same code, except for the name change, and it also supports seperate 'x' and 'y' exvars (which really makes no sense, but it made the coding easier) and the 'damage' exvar to vary the amount of damage the pitfall causes (for emulating long pitfalls - default is still 20).

To attach ceiling pits, you'll have to include a call to fix_tpits() at the end of your 'dungeon.lua' code.
Post Reply