Tutorials: wallsets and custom monsters, objects, 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.
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Question on alcoves please! I have created a new custom alcove, copying the base alcove obj. code , but objects placed "in" the alcove don't sit at the correct height. Is there a way to define the height an object is seen at when placed in an alcove? Many thanks!
User avatar
Sophia
Concise and Honest
Posts: 4306
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Sophia »

Not directly. Objects in alcoves are always drawn at 15/16 the total height of the alcove, because that looked right for DM and I didn't ever delve into alcoves that looked substantially different.
User avatar
Gambit37
Should eat more pies
Posts: 13766
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Gambit37 »

Wasn't there a demo of different sized alcoves in the test dungeon? Perhaps investigate that example and see if it can be adapted?
User avatar
Sophia
Concise and Honest
Posts: 4306
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Sophia »

I wasn't inclined to fix this but the more I look at this code the more I hate it. Expect 0.84 soon.
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Well, short term fix was I noticed I had a lot of transparency outside the actual alcove graphic in the bitmap, I cut this off and the 15/16 rule has put the objects back into position...! Thanks.
User avatar
Sophia
Concise and Honest
Posts: 4306
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Sophia »

DSB 0.84 will add a y_subtract_denominator property, and the standard alcoves will have a value of 16. The height of the alcove will be divided by this number and then subtracted from the y position of any objects in the alcove. A value of 0 will subtract 0.

There are some limits to doing it this way, of course. A value of 1 subtracts the full height, a value of 2 is halfway down, a value of 3 is 2/3 of the way down, and so on, so this really only has any resolution at all for items at the bottom of the alcove. This is how it normally works so it should be fine for most cases. I'm not opposed to adding absolute pixel offsets but that is more work, so I don't really want to bother if nobody's actually going to use them.
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Thanks Sophia, this sounds good. My particular alcove graphic has a visible lip at the bottom edge, effectively like a very slightly protruding shelf with some thickness. So this makes the bottom of the alcove bitmap lower then the ‘surface’ of the alcove that the object is placed on. Your proposed amendment above would go a long way to fine tuning the object placement in respect of this. Thank you.
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Sophia wrote: Wed Jan 22, 2025 9:15 pm Ah, I see now. The food_type property is the archetype that is actually dropped. It doesn't even have to actually be food, it can drop any object. You can use the properties min_food and max_food to specify the values; if you want "sometimes none" you can set min_food to 0.

When a monster dies, its on_die function is called, which is setup_food_drop in this case. This places the food into the monster's inventory. Then the engine deletes the monster instance and drops its inventory onto the floor, so the food is dropped.
Quick question on this mechanic: Is it possible to drop more than one type of food or object?
User avatar
Gambit37
Should eat more pies
Posts: 13766
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Gambit37 »

I've now unarchived my DSB project and have been going through it to understand what I have left to do. It's a lot! Anyway, I can now answer your question. Monsters that drop objects just need a couple of properties setup, eg, to drop multiple items use a table listing the items in drop_item_type:

Code: Select all

obj.skeleton = {
        [...]
        on_die=setup_item_drop,
	drop_item_type={ "falchion", "shield_wood" },
        [...]
}
To drop a single item, use the name of the item in quotes, eg, the golem has this:

Code: Select all

drop_item_type="club_stone",
Note that on_die=setup_item_drop overrides the food drop mechanic, so if you also want to drop food you can add it to the table, or write your own function to do cleverer things. Have a look in the monster.lua file in the base folder to see the various monster specific drop functions.
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Thanks Gambit, ah yes of course, the Skeleton! Silly me,I should have remembered and checked that before asking. All makes sense, thank you.
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Sophia wrote: Sat Jan 18, 2025 11:26 pm Right, viewangle allows you to specify what directions an object is visible from, so by stacking up multiple instances in a square with different viewangle values, it will look like something that looks different depending on the direction.

The simplest way is to set the archetype's viewangle property to a direction: NORTH, SOUTH, EAST, or WEST. This will make any instances of the archetype visible from only that direction.

Alternatively, if you want an object to be visible from multiple directions, you can specify viewangle as a table of bools, in the order north, east, south, west. So, for example:

Code: Select all

obj.myobj.viewangle = { true, false, true, false }
This object is only visible if you are north or south; it is invisible from the east or west.
Thinking about this for a sec.... potential stupid idea alert: would it be possible to use a Monster for an "object", keep the monster totally static, unkillable, it does nothing other than be decoration, and then utilise it's abilty to have a FRONT, BACK, and SIDE graphic... so as to simulate the above, but with only one "object"? It's a bit hacky, but... just curious! I might try it.. :D
User avatar
Gambit37
Should eat more pies
Posts: 13766
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Gambit37 »

I have an immobile invisible monster that I use to create destructible obstacles, so I think your idea should work. You might get some issues with offsets though.

Another way would be to create the four objects in Lua, but only place one of them in ESB. Then write a small function that spawns the three other objects and attach that function to the on_spawn method of the first object.
User avatar
Sophia
Concise and Honest
Posts: 4306
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Sophia »

Take a look at create_linked_object and how it is used by pits to spawn their ceiling pits as an example. It could be used as-is or as a basis to write your own code.
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Sophia wrote: Sat Jan 18, 2025 7:59 pm Splitting code off to more .lua files is what the lua_manifest is for. You can include files there and they will be loaded by DSB.
Ok - so I thought I understood this at the time, but evidently I didn't! I was today trying to split out my various objects and graphics items into more discrete and manageable sub lua files. My Startup.lua reads like this, splitting the code into GFX files for the bitmaps, and OBJ files for the various object descriptions:

Code: Select all

lua_manifest = {
	"DH_GFX_Dungeon.lua",
	"DH_GFX_Monsters.lua",
	"DH_GFX_Things.lua",
	"DH_GFX_wallsets.lua",
	"DH_OBJ_Floor Items.lua",
	"DH_OBJ_Misc_UI.lua",
	"DH_OBJ_Monsters.lua",
	"DH_OBJ_TH_Armour.lua",
	"DH_OBJ_TH_Food.lua",
	"DH_OBJ_TH_Items.lua",
	"DH_OBJ_TH_Weapons.lua",
	"DH_OBJ_Wallitems.lua",
}
Like before, I can load the dungeon in ESB, but none of the assets appear there, and when I run DSB it says: FATAL LUA ERROR.... DH_OBH_Floor Items .... attempt to index global 'obj' (a nil value). I had this error back here viewtopic.php?p=164711#p164711, but I thought that was because I had entered the objects.lua into the manifest, when I removed it as you suggested, everything worked.

Now I'm not sure what I'm doing wrong. Could you possibly explain it to me in simple steps? (...and sorry for not understanding something probably super basic..)

Or is it simply that object definitions cannot appear in any file other than objects.lua?

Many thanks! :)
User avatar
Sophia
Concise and Honest
Posts: 4306
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Sophia »

Strictly speaking, object definitions can't appear in any file other than objects.lua, but there's a workaround. You can use dsb_import_arch. Just ignore the field where you're supposed to specify the arch's name and import whatever code you want.

Add lines like this to objects.lua:

Code: Select all

dsb_import_arch("DH_OBJ_Floor_Items.lua", "")
--etc.
EDIT: Fixed syntax.
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Thank you so much, Sophia. I have added the objects.lua which now contains only the dsb_import_arch lines (one per OBJ lua), changed the manifest in startup to omit any of the OBJ references, but now I get an error message saying that a file is not found, but it doesn’t tell me which file, it just mentions the folder location that the dungeon (and all other lua files) is in. Feel like I’m missing something basic, but I don’t know what! Any ideas what this might be?
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Ah, I noticed in test dungeon it’s potentially more like this; lua file first, then optionally an object in that file:

Code: Select all

dsb_import_arch("DH_OBJ_Floor_Items.lua", “”)
I changed it round to this, I think they’re loading ok but I have a couple of (I think) unrelated errors I still need to fix (finding the right assets)
User avatar
Sophia
Concise and Honest
Posts: 4306
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Sophia »

Ah, yes. I hadn't actually used that function in a couple years. :oops: I'm glad you figured it out!

I've fixed my initial post above in case anyone stumbling across it gets confused.
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Awesome, I have it all working smoothly now, it's much easier to manage all the different code.

I managed to make the static monster hack work also. Working out pretty well on initial test. Example use is a freestanding statue or gargoyle. Might try it also for damageable barrel or urn (stores objects, releases them when hit for damage). Will see if I can also use med and far graphics for the monster bitmaps, to see if I can tone it in a bit better at distance. Gambit, offsets seem to be ok.

Only issue is, an object placed on the same tile as the static monster cannot be picked up.... !
User avatar
Sophia
Concise and Honest
Posts: 4306
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Sophia »

You can set no_stopclicks to true in a monster's archetype to allow objects to be picked up from its tile.
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Ahhh, useful, thanks. Is it possible to stop objects going into a tile entirely?
User avatar
Sophia
Concise and Honest
Posts: 4306
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Sophia »

The simplest way to do that is to just put an invisible wall on the tile.
User avatar
Gambit37
Should eat more pies
Posts: 13766
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Gambit37 »

Sophia wrote: Sun Feb 02, 2025 1:31 am You can set no_stopclicks to true in a monster's archetype to allow objects to be picked up from its tile.
Oh my goodness. First time I've heard of this. Gamechanger!
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Well. The plus side is I just discovered the 2x mode… can’t believe I wasn’t aware of this until just yesterday. The down side… I need to sharpen up my graphics skills a bit more now, and the micro adjustments via offsets and tweaks of graphics just got a bit harder….
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Am just considering how to organise the bitmaps:
Sophia wrote: Sat Jan 18, 2025 7:59 pm
A simple way is to concatenate a string like this:

Code: Select all

local path = "folder/pics/"
gfx.my_bmp = dsb_get_bitmap("MY_BITMAP", path .. "my_bitmap.png")
This makes things shorter and makes it easier to change paths.
Can this work by specifying local path, local path2, local path3, etc?

Code: Select all

local path = "folder/pics1/"
local path2 = "folder/pics2/"
local path3 = "folder/pics3/"

gfx.my_bmp = dsb_get_bitmap("MY_BITMAP", path .. "my_bitmap.png")
gfx.my_other_bmp = dsb_get_bitmap("MY_BITMAP", path2 .. "my_bitmap.png")
gfx.an_other_bmp = dsb_get_bitmap("MY_BITMAP", path3 .. "my_bitmap.png")
Ie, is the word "path" after "local" simply a label?

Or, can I enter several paths?

Code: Select all

local path = "folder/pics1/"
local path = "folder/pics2/"
local path = "folder/pics3/"

gfx.my_bmp = dsb_get_bitmap("MY_BITMAP", path .. "my_bitmap.png")
gfx.my_other_bmp = dsb_get_bitmap("MY_BITMAP", path .. "my_bitmap.png")
gfx.an_other_bmp = dsb_get_bitmap("MY_BITMAP", path .. "my_bitmap.png")
... where each of the three bitmaps is in a different "pics" folder?

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

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Sophia »

It's a single variable. Your second example will keep overwriting path. I'd recommend doing it like this:

Code: Select all

local paths = {
   "folder/pics1/",
   "folder/pics2/",
   "folder/pics3/"
}

gfx.my_bmp = dsb_get_bitmap("MY_BITMAP", paths[1] .. "my_bitmap.png")
gfx.my_other_bmp = dsb_get_bitmap("MY_BITMAP", paths[2] .. "my_bitmap.png")
gfx.an_other_bmp = dsb_get_bitmap("MY_BITMAP", paths[3] .. "my_bitmap.png")
If you actually wanted it to work like your second code, you could write a function for that, though.

Code: Select all

local n = 0
local paths = {
   "folder/pics1/",
   "folder/pics2/",
   "folder/pics3/"
}
local function autopath()
   n = n + 1
   return paths[n]
end

gfx.my_bmp = dsb_get_bitmap("MY_BITMAP", autopath() .. "my_bitmap.png")
gfx.my_other_bmp = dsb_get_bitmap("MY_BITMAP", autopath() .. "my_bitmap.png")
gfx.an_other_bmp = dsb_get_bitmap("MY_BITMAP", autopath() .. "my_bitmap.png")
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Thank you so much. I see how it works now. Weighing this up against the other option using the graphics.cfg. Really appreciate your help in explaining all this.
User avatar
Gambit37
Should eat more pies
Posts: 13766
Joined: Wed May 31, 2000 1:57 pm
Location: Location, Location
Contact:

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Gambit37 »

My project has ended up a mixture of stuff in the graphics.cfg and then a ton of new stuff organised via chunked files called in the manifest. It's pretty messy and could do with an overhaul. With hindsight, I should have used the graphics.cfg for all the direct replacements, and then only added new files for new custom graphics that don't map to the existing images. Another way is to not use the graphics.cfg at all and instead specify everything in custom new override files (which is how I originally started) but that seems to increase loading time.

Right now I've got such a messy mixture that I can't remember where anything is, and this is one reason why I'm struggling to restart the project: do I spend time reorganising with the benefit of hindsight, or just leave it chaotic and finish everything that's missing and broken first? No right or wrong answer really, I guess we all just find ways that work for us...?
User avatar
Sophia
Concise and Honest
Posts: 4306
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Sophia »

Gambit37 wrote: Tue Feb 04, 2025 12:00 pm Another way is to not use the graphics.cfg at all and instead specify everything in custom new override files (which is how I originally started) but that seems to increase loading time.
It does. If you put everything into new files, then it loads the DM image in base/, trashes the DM image, and then loads your custom image. This rather inefficient process is one big reason why being able to directly substitute images via graphics.cfg exists.
User avatar
Ser Xav
Lo Master
Posts: 449
Joined: Mon Jan 21, 2013 10:58 pm
Location: I see walls stretching off into the darkness...

Re: Tutorials: wallsets and custom monsters, objects, etc

Post by Ser Xav »

Sophia wrote: Sat Jan 18, 2025 7:59 pm
If you want to delve a little bit more into Lua code you can use the graphics_paths table, which is defined in graphics.cfg. DSB can't automatically scan or anything like that, but you can generate this table of key:value pairs corresponding long names with short names however you want to, so you can concatenate strings to automatically build paths or whatever else. For example, this code has the same effect:

Code: Select all

-- In graphics.cfg
graphics_paths = {
   MY_BITMAP = "folder/pics/my_bitmap.png"
}

Code: Select all


-- In your normal code
gfx.my_bmp = dsb_get_bitmap("MY_BITMAP")
Using graphics_paths also allows you to replace existing bitmaps without reloading anything or changing any code, because you can just change the path to the bitmap.
So I am attempting this method to see how it works out. I think I've set it all up succesfully. I have created the graphics.cfg which is sitting in same folder as the dungeon.lua. All the paths are correct, as is the graphics_path = { ... example couple of lines below (from a much bigger list):

Code: Select all

graphics_paths = {
	DOOR_POWER_01 = "X:\00_DM_Project_2025\DSB_DarkHalls\DUNGEON\DH_GFX\01_DOORS\DOOR_POWER_01.PNG",
	DOOR_WOODEN_03 = "X:\00_DM_Project_2025\DSB_DarkHalls\DUNGEON\DH_GFX\01_DOORS\DOOR_WOODEN_03.PNG",
	SENTINEL_01 = "X:\00_DM_Project_2025\DSB_DarkHalls\DUNGEON\DH_GFX\05_MONSTERS\SENTINEL_01.PNG",
My objects.lua is pulling in individual .lua files for objects and monsters:

Code: Select all

dsb_import_arch("DH_OBJ_Monsters.lua", "")
dsb_import_arch("DH_OBJ_TH_Items.lua", "")
etc
etc
The graphics .lua files are coming from the manifest in startup.lua:

Code: Select all

lua_manifest = {
	"DH_GFX_Monsters.lua",
	"DH_GFX_Things.lua",
etc
etc
}
When I try to run my project in DSB, I get the error: Bitmap not found: SENTINEL_01 (X:) . It's obviously not seeing the SENTINEL_01.png. I don't know why this is, as the file is correctly named, the path is correctly listed (I think), all references to it are correct, the uppercase/lowercases are consistent.

Also, I don't know if the problem is with the file, or with the process. In graphics.cfg, the filepath is in the middle of a much bigger list alphabetically, in the DH_GFX_monsters.lua it's listed first. I've --commented out the object and gfx references with it in all files, to try to omit it from the loading process, but oddly it reports the same error regardless.

I know I always say I think I'm probably doing something obvious wrong (I'll get some t-shirts printed), but... I don't know what the error is. Am I doing the path incorrectly?

Any ideas? :) Thank you!
Post Reply