assigned numbers to roads so that houses can identify the road they belong to; added dirt roads between the fields for medieval villages

This commit is contained in:
Sokomine 2014-08-17 22:41:22 +02:00
parent 8174ef247b
commit 56ef231f96

View File

@ -144,10 +144,15 @@ local function choose_building_rot(l, pr, orient, village_type)
return btype, rotation, bsizex, bsizez
end
local function placeable(bx, bz, bsizex, bsizez, l, exclude_roads)
local function placeable(bx, bz, bsizex, bsizez, l, exclude_roads, orientation)
for _, a in ipairs(l) do
-- with < instead of <=, space_between_buildings can be zero (important for towns where houses are closely packed)
if (a.btype ~= "road" or not exclude_roads) and math.abs(bx+bsizex/2-a.x-a.bsizex/2)<(bsizex+a.bsizex)/2 and math.abs(bz+bsizez/2-a.z-a.bsizez/2)<(bsizez+a.bsizez)/2 then return false end
if (a.btype ~= "road" or not exclude_roads) and math.abs(bx+bsizex/2-a.x-a.bsizex/2)<(bsizex+a.bsizex)/2 and math.abs(bz+bsizez/2-a.z-a.bsizez/2)<(bsizez+a.bsizez)/2 then
-- dirt roads which go at a 90 degree angel to the current road are not a problem
if( not( orientation ) or a.o%2 == orientation%2 ) then
return false
end
end
end
return true
end
@ -164,6 +169,8 @@ local function when(a, b, c)
if a then return b else return c end
end
mg_villages.road_nr = 0;
local function generate_road(village, l, pr, roadsize, rx, rz, rdx, rdz, vnoise, space_between_buildings)
local vx, vz, vh, vs = village.vx, village.vz, village.vh, village.vs
local village_type = village.village_type;
@ -180,6 +187,8 @@ local function generate_road(village, l, pr, roadsize, rx, rz, rdx, rdz, vnoise,
orient1 = 3
orient2 = 1
end
-- we have one more road
mg_villages.road_nr = mg_villages.road_nr + 1;
while mg_villages.inside_village(rx, rz, village, vnoise) and not road_in_building(rx, rz, rdx, rdz, roadsize, l) do
if roadsize > 1 and pr:next(1, 4) == 1 then
--generate_road(vx, vz, vs, vh, l, pr, roadsize-1, rx, rz, math.abs(rdz), math.abs(rdx))
@ -224,7 +233,7 @@ local function generate_road(village, l, pr, roadsize, rx, rz, rdx, rdz, vnoise,
rz = rz + (bsizez+space_between_buildings)*rdz
mx = rx - 2*rdx
mz = rz - 2*rdz
l[#l+1] = {x=bx, y=vh, z=bz, btype=btype, bsizex=bsizex, bsizez=bsizez, brotate = rotation}
l[#l+1] = {x=bx, y=vh, z=bz, btype=btype, bsizex=bsizex, bsizez=bsizez, brotate = rotation, road_nr = mg_villages.road_nr, side=1, o=orient1 }
--end
end
rx = rxx
@ -273,7 +282,7 @@ local function generate_road(village, l, pr, roadsize, rx, rz, rdx, rdz, vnoise,
rz = rz + (bsizez+space_between_buildings)*rdz
m2x = rx - 2*rdx
m2z = rz - 2*rdz
l[#l+1] = {x=bx, y=vh, z=bz, btype=btype, bsizex=bsizex, bsizez=bsizez, brotate = rotation}
l[#l+1] = {x=bx, y=vh, z=bz, btype=btype, bsizex=bsizex, bsizez=bsizez, brotate = rotation, road_nr = mg_villages.road_nr, side=2, o=orient2}
--end
end
if road_in_building(rx, rz, rdx, rdz, roadsize, l) then
@ -294,7 +303,8 @@ local function generate_road(village, l, pr, roadsize, rx, rz, rdx, rdz, vnoise,
rxmax = math.max(rxx, mx)
end
l[#l+1] = {x = rxmin, y = vh, z = rzmin, btype = "road",
bsizex = rxmax - rxmin + 1, bsizez = rzmax - rzmin + 1, brotate = 0}
bsizex = rxmax - rxmin + 1, bsizez = rzmax - rzmin + 1, brotate = 0, road_nr = mg_villages.road_nr}
for _, i in ipairs(calls_to_do) do
local new_roadsize = roadsize - 1
if pr:next(1, 100) <= BIG_ROAD_CHANCE then
@ -375,16 +385,126 @@ local function generate_bpos(village, pr, vnoise, space_between_buildings)
end
rx = rx + 5
calls = {index = 1}
-- the function below is recursive; we need a way to count roads
mg_villages.road_nr = 0;
generate_road(village, l, pr, FIRST_ROADSIZE, rx, rz, 1, 0, vnoise, space_between_buildings)
i = 1
while i < calls.index do
generate_road(unpack(calls[i]))
i = i+1
end
mg_villages.road_nr = 0;
return l
end
-- dirt roads seperate the wheat area around medieval villages into seperate fields and make it look better
mg_villages.generate_dirt_roads = function( village, vnoise, bpos, secondary_dirt_roads )
local dirt_roads = {};
if( not( secondary_dirt_roads)) then
return dirt_roads;
end
for _, pos in ipairs( bpos ) do
local x = pos.x;
local z = pos.z;
local sizex = pos.bsizex;
local sizez = 2;
local orientation = 0;
-- prolong the roads; start with a 3x2 piece of road for testing
if( pos.btype == 'road' ) then
-- the road streches in x direction
if( pos.bsizex > pos.bsizez ) then
sizex = 3; -- start with a road of length 3
sizez = 2;
vx = -1; vz = 0; vsx = 1; vsz = 0;
x = pos.x - sizex;
z = pos.z + math.floor((pos.bsizez-2)/2); -- aim for the middle of the road
orientation = 0;
-- if it is not possible to prolong the road at one end, then try the other
if( not( placeable( x, z, sizex, sizez, bpos, false, nil))) then
x = pos.x + pos.bsizex;
vx = 0;
orientation = 2;
end
-- the road stretches in z direction
else
sizex = 2;
sizez = 3;
vx = 0; vz = -1; vsx = 0; vsz = 1;
x = pos.x + math.floor((pos.bsizex-2)/2); -- aim for the middle of the road
z = pos.z - sizez;
orientation = 1;
if( not( placeable( x, z, sizex, sizez, bpos, false, nil))) then
z = pos.z + pos.bsizez;
vz = 0;
orientation = 3;
end
end
else
if( pos.o == 0 ) then
x = pos.x-pos.side;
z = pos.z-2;
sizex = pos.bsizex+1;
sizez = 2;
vx = 0; vz = 0; vsx = 1; vsz = 0;
elseif( pos.o == 2 ) then
x = pos.x-pos.side+2;
z = pos.z-2;
sizex = pos.bsizex+1;
sizez = 2;
vx = -1; vz = 0; vsx = 1; vsz = 0;
elseif( pos.o == 1 ) then
x = pos.x-2;
z = pos.z-pos.side+2;
sizex = 2;
sizez = pos.bsizez+1;
vx = 0; vz = 1; vsx = 0; vsz = 1;
elseif( pos.o == 3 ) then
x = pos.x-2;
z = pos.z-pos.side;
sizex = 2;
sizez = pos.bsizez+1;
vx = 0; vz = 0; vsx = 0; vsz = 1;
end
orientation = pos.o;
end
-- prolong the dirt road by 1
while( placeable( x, z, sizex, sizez, bpos, false, nil)
and placeable( x, z, sizex, sizez, dirt_roads, false, orientation)
and mg_villages.inside_village_area(x, z, village, vnoise)
and mg_villages.inside_village_area(x+sizex, z+sizez, village, vnoise)) do
sizex = sizex + vsx;
sizez = sizez + vsz;
x = x + vx;
z = z + vz;
end
-- the dirt road may exceed the village boundaries slightly, but it may not interfere with other buildings
if( not( placeable( x, z, sizex, sizez, bpos, false, nil))
or not( placeable( x, z, sizex, sizez, dirt_roads, false, orientation))) then
sizex = sizex - vsx;
sizez = sizez - vsz;
x = x - vx;
z = z - vz;
end
if( placeable( x, z, sizex, sizez, bpos, false, nil)
and placeable( x, z, sizex, sizez, dirt_roads, false, orientation)) then
dirt_roads[#dirt_roads+1] = {x=x, y=village.vh, z=z, btype="dirt_road", bsizex=sizex, bsizez=sizez, brotate = 0, o=orientation}
end
end
return dirt_roads;
end
-- they don't all grow cotton; farming_plus fruits are far more intresting!
-- Note: This function modifies replacements.ids and replacements.table for each building
-- as far as fruits are concerned. It needs to be called before placing a building
@ -819,6 +939,15 @@ mg_villages.generate_village = function(village, vnoise)
-- actually generate the village structure
local bpos = generate_bpos( village, pr_village, vnoise, space_between_buildings)
local secondary_dirt_roads = nil;
-- if there is enough space, add dirt roads between the buildings (those will later be prolonged so that they reach the fields)
if( space_between_buildings >= 2 and village_type == 'medieval') then
secondary_dirt_roads = "dirt_road";
end
local dirt_roads = mg_villages.generate_dirt_roads( village, vnoise, bpos, secondary_dirt_roads );
-- set fruits for all buildings in the village that need it - regardless weather they will be spawned
-- now or later; after the first call to this function here, the village data will be final
for _, pos in ipairs( bpos ) do
@ -837,6 +966,7 @@ mg_villages.generate_village = function(village, vnoise)
village.to_add_data = {};
village.to_add_data.bpos = bpos;
village.to_add_data.replacements = replacements.list;
village.to_add_data.dirt_roads = dirt_roads;
--print('VILLAGE GENREATION: GENERATING NEW VILLAGE Nr. '..tostring( village.nr ));
end
@ -867,7 +997,34 @@ mg_villages.place_buildings = function(village, minp, maxp, data, param2_data, a
-- replacements are in table format for mapgen-based building spawning
generate_building(pos, minp, maxp, data, param2_data, a, pr_village, extranodes, replacements )
end
-- replacements are in list format for minetest.place_schematic(..) type spawning
return { extranodes = extranodes, bpos = bpos, replacements = replacements.list };
return { extranodes = extranodes, bpos = bpos, replacements = replacements.list, dirt_roads = village.to_add_data.dirt_roads };
end
-- add the dirt roads
mg_villages.place_dirt_roads = function(village, minp, maxp, data, param2_data, a, vnoise, c_road_node)
local c_air = minetest.get_content_id( 'air' );
for _, pos in ipairs(village.to_add_data.dirt_roads) do
local param2 = 0;
if( pos.bsizex > 2 ) then
param2 = 1;
end
for x = 0, pos.bsizex-1 do
for z = 0, pos.bsizez-1 do
local ax = pos.x+x;
local az = pos.z+z;
if (ax >= minp.x and ax <= maxp.x) and (ay >= minp.y and ay <= maxp.y) and (az >= minp.z and az <= maxp.z) then
-- roads have a height of 1 block
data[ a:index( ax, pos.y, az)] = c_road_node;
param2_data[ a:index( ax, pos.y, az)] = param2;
-- ...with air above
data[ a:index( ax, pos.y+1, az)] = c_air;
data[ a:index( ax, pos.y+2, az)] = c_air;
end
end
end
end
end