I've been playing Night Raider doing research on similar games recently. More fun than it looks if you like hoarding items, very grindy (as expected from Chinese developer?) and too easy though.
I made a loot generation system, it's basically a linked list of entries. An entry can either select one from the child entries, roll for all the child entries separately, spawn an item, or defer to another drop table. It can also repeat the action between min/max times. I can create a fairly complex varieties of things with this, and I'm hoping it's easily moddable this way too. Another action I'll probably add later is rolling for random child entries until a desired total "value"/score is reached. That way if you want a super valuable treasure chest or whatever, you could just add a bunch of random items into a list and it'll keep spawning them randomly until a value quota is reached.
Here's how the loot in webm related is made:
int id0 = 0, id1 = 0, id2 = 0, id3 = 0, id4 = 0;
id0 = create(0, (Entry){.id="ammo_box", .minmax={1,1}, .action=SELECT});
id1 = create(id0, (Entry){.weight=2, .minmax={1,1}, .action=ROLL_ALL});
id2 = create(id1, (Entry){.chance=1, .minmax={1,1}, .action=SELECT});
id3 = create(id2, (Entry){.weight=2, .minmax={1,1}, .action=ITEM, .item="pistol"});
id3 = create(id2, (Entry){.weight=1, .minmax={1,1}, .action=ITEM, .item="pistol2"});
id2 = create(id1, (Entry){.chance=1, .minmax={20,1000}, .action=ITEM, .item="ammo__pistol"});
id2 = create(id1, (Entry){.chance=0.5, .minmax={10,200}, .action=ITEM, .item="ammo__pistol_subsonic"});
id1 = create(id0, (Entry){.weight=1, .minmax={1,1}, .action=ROLL_ALL});
id2 = create(id1, (Entry){.chance=1, .minmax={1,1}, .action=ITEM, .item="shotgun"});
id2 = create(id1, (Entry){.chance=1, .minmax={2,200}, .action=ITEM, .item="ammo__shot"});
id1 = create(id0, (Entry){.weight=0.5, .minmax={1,1}, .action=ROLL_ALL});
id2 = create(id1, (Entry){.chance=1, .minmax={1,1}, .action=ITEM, .item="assrifle"});
id2 = create(id1, (Entry){.chance=1, .minmax={10,500}, .action=ITEM, .item="ammo__assault"});
Vec2i pos = vec2i(1, 1);
spawn_prop(map, pos, get_propinfo("wardrobe"), false, false, false);
spawn_droptable_into_prop(map, pos, get_droptable("ammo_box"));
The droptable creation part is super annoyingly ugly, but I don't know of a better way to structure it without parsing information from text. The most annoying part is having to keep track of the IDs, I have to do that so I can add an entry inside another entry. It's fine if modifying the table afterwards is a bit awkward, but having to initialize a new table this way is annoying.