Potential Buildings

Welp, this week was extremely busy but I managed to hammer through the 2x2 building code :3
Now we can have 2x2 buildings in the country side or in town. The hang up was getting rotation working for each section and the buildings as a whole. I’m not saying that its perfect but I haven’t encountered any bugs in the last few maps. The biggest issue that might hold off 2x2 per-defined buildings is that roads have a bad habit of cutting through buildings whenever they are along the most direct path between two points. It isn’t too bad but the more populated the countryside gets the more common it is.

3x3 predefined buildings are going to rely on a new function also… from what I’ve seen it is going to be easier to define 3x3 map buildings like
.123. .aAa.
.456. .aaa.
.789. as opposed to .aaa.
This way every building tile has its own entry, creating a bit of clutter but I don’t see an easy alternative. Either implementation will we be possible so no need to alter any existing buildings. (As a note, all of this we be behind the scenes so you won’t actually be able to tell the difference)

More good news, Tilion’s Public Works is almost in game. I’ll throw up an image tonight and try and work on spawns tomorrow. Thanks Tilion for all of the advice. I’ll be sure to include all I can.

Thanks Grackle, you should see your work popping up with the sarcophagi. (Which I’ll probably submit with the Public Works this weekend)

[quote=“LazyCat, post:40, topic:913”][/quote]
Thanks, I intend to add second+ stories to many of the buildings but I’m holding off a bit until multiple floors are polished out and implemented for the regular builds. I know one of the dev’s (?) was working on it a month or so ago but I haven’t heard much about it since then. If you have a good implementation, you might want to get the dev’s to look at it. You’ll get muli-level buildings all the sooner that way :smiley: Unfortunately I haven’t actually played any of the metal gear solid games. When I was little I had the nes version but that’s about it. Sorry :slight_smile:

Edit:
Public Works, open bay garages and construction supply in the yard. I couldn’t fit a decent shower room in without a bit of strange geometry so I ended up putting the lockers in the common hall and made a large bathroom. I could cut the yard down a bit in size but then we may have a lot less room to spawn vehicles. The locked room with valuable equipment is the one with no windows towards the rear of the building. (It seems to have spawned the oven in the lounge as a book case… but that’s fixed.)

Looks nice, acidia, and I’m glad to hear that you got 2x2 buildings sorted out :). Can’t wait to see how these work in-game!

I think since you are working on that part of code already you would be the best one to do it, to merge it with your own build and then it will consequently be merged with the main trunk with all the rest of it.

Here is what I did to make shelters have both the basement and two upper floors. I think it should be fairly easy to generalize the whole thing based on this “template”, expand for other buildings and combine with your own code.

1.) overmap.h

#define OVERMAP_HEIGHT 5 

2.) overmap.h

[code]enum oter_id {
.
.
.
ot_sky, ot_shelter_over, ot_shelter_over2,

ot_tutorial,
num_ter_types
};[/code]

  1. overmap.h

[code]const oter_t oterlist[num_ter_types] = {
.
.
.

  • {“evac shelter”, ‘+’, c_white, 2, no_extras, true, false},
  • {“evac shelter”, ‘+’, c_white, 2, no_extras, true, true},
    .
    .
    .
    {“sky”, ‘8’, c_ltcyan, 2, no_extras, false, false},
    {“evac shelter”, ‘+’, c_white, 2, no_extras, true, true}, //shelter z= 1
    {“evac shelter”, ‘+’, c_white, 2, no_extras, true, false}, //shelte z= 2

{“tutorial room”, ‘O’, c_cyan, 5, no_extras, false, false}
};
[/code]

4.) overmap.cpp

[code]void overmap::init_layers()
{
layer = new map_layer[OVERMAP_LAYERS];
for(int z = 0; z < OVERMAP_LAYERS; ++z) {

	oter_id default_type = (z < OVERMAP_DEPTH) ? ot_rock : ot_field;

	if(z > OVERMAP_DEPTH)
		default_type= ot_sky;

	for(int i = 0; i < OMAPX; ++i) {
		for(int j = 0; j < OMAPY; ++j) {
			layer[z].terrain[i][j] = default_type;
			layer[z].visible[i][j] = false;
		}
	}
}

}[/code]

  1. overmap.cpp

[code]bool overmap::generate_sub(int const z)
{
.
.
.

  • else if (ter(i, j, z + 1) == ot_shelter)
  • else if (ter(i, j, 0) == ot_shelter)
    shelter_points.push_back( point(i, j) );
    .
    .
    .
    for (int i = 0; i < shelter_points.size(); i++)
    {
    if(z == -1)
    {
    ter(shelter_points[i].x, shelter_points[i].y, z) = ot_shelter_under;
    requires_sub = true;
    }
    else
    if(z == -2)
    {
    ter(shelter_points[i].x, shelter_points[i].y, 1) = ot_shelter_over; // z= 1
    requires_sub = true;
    }
    else
    if(z == -3)
    ter(shelter_points[i].x, shelter_points[i].y, 2) = ot_shelter_over2; // z= 2
    }[/code]
  1. mapdata.h

[code]enum ter_id {
.
.
.
t_air,

num_terrain_types
};
[/code]

  1. mapdata.h

const ter_t terlist[num_terrain_types] = { . . . {"bunch of air", '.', c_ltcyan, 2, tr_airhole, mfb(transparent)} };

  1. mapgen.h

[code]void map::draw_map
.
.
.
case ot_sky:
for (int i = 0; i < SEEX * 2; i++) {
for (int j = 0; j < SEEY * 2; j++) {
ter(i, j) = t_air;
}
}
break;

case ot_shelter_over:
{
for (int i = 0; i < SEEX2; i++) {
for (int j = 0; j < SEEY
2; j++)
ter(i, j) = t_air;
}

square(this, t_floor_red, 0, 0, 5, 2);
line(this, t_wall_h, 1, 0, 2, 0);
line(this, t_wall_h, 1, 2, 2, 2);
line(this, t_wall_v, 0, 0, 0, 2);
line(this, t_wall_v, 2, 2, 2, 0);
ter(2, 1) = t_door_locked;

ter(1, 1) = t_stairs_up;

square(this, t_floor, 4, 4, SEEX * 2 - 5, SEEY * 2 - 5);

line(this, t_wall_h, 4, 4, SEEX * 2 - 5, 4);
line(this, t_wall_h, 4, SEEY * 2 - 5, SEEX * 2 - 5, SEEY * 2 - 5);

line(this, t_pavement, SEEX+4, 3, SEEX * 2 - 4, 3);
line(this, t_pavement, SEEX * 2 - 4, 4, SEEX * 2 - 4, 11);
line(this, t_pavement, SEEX * 2 - 4, 14, SEEX * 2 - 4, 19);

line(this, t_pavement, SEEX * 2 - 5, SEEY * 2 - 4, SEEX+1, SEEY * 2 - 4);
line(this, t_pavement, SEEX-3, SEEY * 2 - 4, 3, 20);

line(this, t_sidewalk, 3, 19, 3, 15);
line(this, t_sidewalk, 3, 10, 3, 5);

line(this, t_wall_v, 4, 5, 4, SEEY * 2 - 6);
line(this, t_wall_v, 7, 5, 7, SEEY * 2 - 6);

line(this, t_wall_v, SEEX * 2 - 5, 5, SEEX * 2 - 5, SEEY * 2 - 6);
line(this, t_wall_v, SEEX * 2 - 8, 5, SEEX * 2 - 8, SEEY * 2 - 6);

ter(16, 11) = t_door_c;
ter(15, 13) = t_bookcase;
ter(15, 14) = t_rack;
ter(15, 14) = t_locker;
ter(15, 9) = t_table;
ter(15, 5) = t_dresser;

ter(8, 7) = t_dresser;
ter(7, 11) = t_door_c;
ter(8, 10) = t_locker;
ter(8, 11) = t_bookcase;
ter(8, 12) = t_bookcase;
ter(8, 18) = t_chair;
ter(9, 12) = t_crate_c;

ter(11, 18) = t_locker;
ter(12,18) = t_bookcase;

ter(SEEX+2, 4) = t_curtains;
ter(SEEX+3, 4) = t_curtains;

ter(SEEX-4, 4) = t_curtains;
ter(SEEX-3, 4) = t_window_domestic;

ter(5, 17) = t_stairs_up;
ter(15, 18) = t_stairs_down;

add_graffiti(g, 14, 15, "I write this message...\n\
              with my own blood...\n\
     if you want to jump...\n\
         ...try pressing SHIFT+X.");

add_item(5, 5, g->itypes[itm_mp3], 0);
add_item(17, 18, g->itypes[itm_crowbar], 0);
}
break;

case ot_shelter_over2:
{
// Init to air;
for (int i = 0; i < SEEX2; i++) {
for (int j = 0; j < SEEY
2; j++)
ter(i, j) = t_air;
}

square(this, t_pavement, 0, 0, 2, 2);
ter(0, 1) = t_stairs_down;

square(this, t_pavement, 4, 4, SEEX * 2 - 5, SEEY * 2 - 5);
ter(5, 18) = t_stairs_down;

add_item(14+rng(-2,2), 14+rng(-2,2), g->itypes[itm_law_packed], 0);
for(int i= 0; i < 5; i++)
add_item(14+rng(-2,2), 14+rng(-2,2), g->itypes[itm_66mm_HEAT], 0);

}
break;[/code]

  1. trap.h

[code]enum trap_id {
.
.
.
tr_airhole,

num_trap_types
};

struct trapfunc {
.
.
.
void airhole (game *g, int x, int y);
};

struct trapfuncm {
.
.
.
void airhole(game *g, monster *z, int x, int y);
};[/code]

  1. trapdef.cpp

void game::init_traps() { . . . TRAP("airhole", '.', c_ltcyan, 0, 99, 99, &trapfunc::airhole, &trapfuncm::airhole, itm_null, NULL); }

  1. trapfunc.cpp

[code]void trapfunc::airhole(game *g, int x, int y)
{
g->add_msg(“You fall down a level!”);
g->vertical_move(-1, true);
}

void trapfuncm::airhole(game *g, monster *z, int x, int y)
{
g->add_msg(“The %s falls down a level!”, z->name().c_str());
g->kill_mon(g->mon_at(x, y));
}[/code]

There, easy! Let me know if anything is unclear or needs further explanation.

The @LazyCat epic post is epic.
Do you mind if your awesome ideas would be merged with main branch?

It looks really odd for me that z=-2 and z=-3 corresponds to aboveground levels of shelter while z=-1 corresponds to underground level in generate_sub subroutine.

[quote=“uzername, post:44, topic:913”]The @LazyCat epic post is epic.
Do you mind if your awesome ideas would be merged with main branch?

It looks really odd for me that z=-2 and z=-3 corresponds to aboveground levels of shelter while z=-1 corresponds to underground level in generate_sub subroutine.[/quote]

I don’t mind, I’d prefer it would be merged.

Yeah, z-2=z+1, that seemed as the quickest and cleanest way to do it without re-designing the whole thing. I did try to generalize first so to make +z levels fit more naturally with the rest of the code, but it seemed that would require many little changes all over the place and I didn’t wan’t to risk screwing some other parts of code until I can make sure the basic concept of it works first, which was easier to test as more isolated block of code.

If someone wants to take that code and submit it, plus associated content, to the main Git repo, then it’ll get reviewed as normal.

One thing that does need to be addressed, though, is monster interaction with the “airholes”. GlyphGryph tested it and said that monster corpses ended up floating in midair. Given that proper handling of falling monsters wouldn’t require a total overhaul of any system, I’d at the very least want to see monster corpses (and loot!) appearing on the correct level.

[quote=“Soron, post:46, topic:913”]If someone wants to take that code and submit it, plus associated content, to the main Git repo, then it’ll get reviewed as normal.

One thing that does need to be addressed, though, is monster interaction with the “airholes”. GlyphGryph tested it and said that monster corpses ended up floating in midair. Given that proper handling of falling monsters wouldn’t require a total overhaul of any system, I’d at the very least want to see monster corpses (and loot!) appearing on the correct level.[/quote]

Corpses and loot stay to float when monsters fall in normal holes as well, try missile silo. Fix that for ordinary “hole” and you will automatically fix it for “airhole”. I don’t think it’s too bad so I can’t be bothered. I’d like to have levels designed first, then it will be more interesting to test and chase whatever such bugs.

Soooo… fine I’ll submit it.

Check the pull que in a bit to see it everything went well.
I’m looking forward to getting proper z-levels in :slight_smile:

That’s fine for testing and development, but I do want to see some of those bugs fixed before incorporation into mainline :P. Loot (that’s NOT from dead monsters) I can possibly ignore, because it requires a larger fix, but having falling monsters that don’t actually fall is something I’d consider a severe bug.

Acidia: the 2x2 buildings seem to mostly work well, although I’ve got a few questions before I merge them in.

[quote=“acidia, post:41, topic:913”]Tilion’s Public Works is almost in game. I’ll throw up an image tonight and try and work on spawns tomorrow. Thanks Tilion for all of the advice. I’ll be sure to include all I can.

Public Works, open bay garages and construction supply in the yard. I couldn’t fit a decent shower room in without a bit of strange geometry so I ended up putting the lockers in the common hall and made a large bathroom. I could cut the yard down a bit in size but then we may have a lot less room to spawn vehicles. The locked room with valuable equipment is the one with no windows towards the rear of the building. (It seems to have spawned the oven in the lounge as a book case… but that’s fixed.)
[/quote]

Simply superb. Love all the work you’re doing (and though I used to be technically minded, more than half of it boggles me nowadays) and great to see what you’ve come up with from my little idea. I’ll be keeping an eye out for further developments (if you can use some of my other stuff) and I can’t wait to stumble across one o’ these in-game at some time down the line along with all the other great additions you’re making!

They die when they step on it, and that’s where they leave their corpse and belongings. It is not really related to z-levels but rather handling of trap function, or monster walking function. It can be fixed or not fixed completely independently of addition of above ground levels. It’s probably easy one line fix. For instance we could just remove all the items from the tile they died on and not bother to drop anything on the level below.

Deleting but not dropping…yep, that’s Lazy all right. Wanna be treated like the second half of your callsign too?

[quote=“acidia, post:48, topic:913”]Soooo… fine I’ll submit it.

Check the pull que in a bit to see it everything went well.
I’m looking forward to getting proper z-levels in :)[/quote]

So you made the two level shelter work in your build?

I’m not sure how much “proper” it can be made without redesigning the rest of the code as well. What in particular do you think needs to be more proper? Is there anything missing for you to start adding upper levels to other buildings? I’m looking forward too, so just tell me what you need and we’ll sort it out so you can do your thing.

Why can you have z-2 levels correspond to second story buildings if there are places (temples, mines, labs) that go to z-2 via staircase?

Please take the argument about lazycat’s laziness etc elsewhere, this is acacia’s awesome thread about awesome buildings.

It’s just the way the loop goes through initialisation, but the floor itself is then actually mapped to +1 layer, while the basement for example is mapped to -1 layer, so you can have both.

[quote=“LazyCat, post:53, topic:913”][/quote]

Fear not, if it works roughly as well as the basement system does now then it should be good enough to add buildings to. I’ll knock out a mullti-level building this weekend and it can be the test bed for working out any kinks in the system. Quick question, in the code does “OVERMAP_HEIGHT 5” limit the number of floors to 5 with the first floor starting as #1 or does that mean 5 levels between underground layers and above ground? I’ll get around to designing the building now and implementing it when I’m a bit more awake.

Fear not, if it works roughly as well as the basement system does now then it should be good enough to add buildings to. I’ll knock out a mullti-level building this weekend and it can be the test bed for working out any kinks in the system. Quick question, in the code does “OVERMAP_HEIGHT 5” limit the number of floors to 5 with the first floor starting as #1 or does that mean 5 levels between underground layers and above ground? I’ll get around to designing the building now and implementing it when I’m a bit more awake.[/quote]

It’s just like adding lower levels. It’s only that loop which initializes all the layers counts from zero into negative values so you have to map -1 to +1, -2 to +2 and so on, or alternatively change how the whole loop works, but I don’t think it’s necessary since each area has to be initialized separately anyway.

What I did with shelter to have both basement and upper levels is I mapped first sub-map count (-1) to be underground basement on layer -1, and then mapped second and third count (-2 and -3) to be first and second floor on layer +1 and +2.

There is define for both how deep down and how far up you want to build.

#define OVERMAP_DEPTH 10
#define OVERMAP_HEIGHT 5

That would give you at least 9 levels below ground and four levels above ground, or more likely 10 below and 5 above, not sure how limits are coded. Define one level more than what you plan to use and you don’t have to worry about it. It was not me who made that, someone else was obviously preparing the code for above ground levels and coded all those limits taking both DEPTH and HEIGHT defines into account.

Kevin tidied up the code a little (mainly updated it to the current version, since LazyCat’s code was written for something like 0.3 - lots of behind-the-scenes changes since then). His update is available here: https://github.com/kevingranade/Cataclysm-DDA/tree/z-level-kludge

Still needs a bit of work before it’s ready for mainline, though. It sounded like Kevin wants to see it possible to interact with other z-levels, such as sniping zombies from an upstairs window. I know that I want to see monsters actually drop when they’re supposed, before I’ll consider merging it.

Sorry for the likely silly question.

How exactly do you put these buildings together and then render them in-game for testing?

I’d be interested in submitting some buildings myself.