handle_schematics/handle_schematics_misc.lua

108 lines
3.3 KiB
Lua

-- helper function; sorts by the second element of the table
local function handle_schematics_comp(a,b)
if (a[2] > b[2]) then
return true;
end
end
-- create a statistic about how frequent each node name occoured
handle_schematics.count_nodes = function( data )
local statistic = {};
-- make sure all node names are counted (air may sometimes be included without occouring)
for id=1, #data.nodenames do
statistic[ id ] = { id, 0};
end
for z = 1, data.size.z do
for y = 1, data.size.y do
for x = 1, data.size.x do
local a = data.scm_data_cache[y][x][z];
if( a ) then
local id = 0;
if( type( a )=='table' ) then
id = a[1];
else
id = a;
end
if( statistic[ id ] and statistic[ id ][ 2 ] ) then
statistic[ id ] = { id, statistic[ id ][ 2 ]+1 };
end
end
end
end
end
table.sort( statistic, handle_schematics_comp );
return statistic;
end
-- this function makes sure that the building will always extend to the right and in front of the build chest
handle_schematics.translate_param2_to_rotation = function( param2, mirror, start_pos, orig_max, rotated, burried, orients, yoff )
-- mg_villages stores available rotations of buildings in orients={0,1,2,3] format
if( orients and #orients and orients[1]~=0) then
-- reset rotated - else we'd apply it twice
rotated = 0;
if( orients[1]==1 ) then
rotated = rotated + 90;
elseif( orients[1]==2 ) then
rotated = rotated + 180;
elseif( orients[1]==3 ) then
rotated = rotated + 270;
end
if( rotated >= 360 ) then
rotated = rotated % 360;
end
end
local max = {x=orig_max.x, y=orig_max.y, z=orig_max.z};
-- if the schematic has been saved in a rotated way, swapping x and z may be necessary
if( rotated==90 or rotated==270) then
max.x = orig_max.z;
max.z = orig_max.x;
end
-- the building may have a cellar or something alike
if( burried and burried ~= 0 and yoff == nil ) then
start_pos.y = start_pos.y - burried;
end
-- make sure the building always extends forward and to the right of the player
local rotate = 0;
if( param2 == 0 ) then rotate = 270; if( mirror==1 ) then start_pos.x = start_pos.x - max.x + max.z; end -- z gets larger
elseif( param2 == 1 ) then rotate = 0; start_pos.z = start_pos.z - max.z; -- x gets larger
elseif( param2 == 2 ) then rotate = 90; start_pos.z = start_pos.z - max.x;
if( mirror==0 ) then start_pos.x = start_pos.x - max.z; -- z gets smaller
else start_pos.x = start_pos.x - max.x; end
elseif( param2 == 3 ) then rotate = 180; start_pos.x = start_pos.x - max.x; -- x gets smaller
end
if( param2 == 1 or param2 == 0) then
start_pos.z = start_pos.z + 1;
elseif( param2 == 1 or param2 == 2 ) then
start_pos.x = start_pos.x + 1;
end
if( param2 == 1 ) then
start_pos.x = start_pos.x + 1;
end
rotate = rotate + rotated;
-- make sure the rotation does not reach or exceed 360 degree
if( rotate >= 360 ) then
rotate = rotate - 360;
end
-- rotate dimensions when needed
if( param2==0 or param2==2) then
local tmp = max.x;
max.x = max.z;
max.z = tmp;
end
return { rotate=rotate, start_pos = {x=start_pos.x, y=start_pos.y, z=start_pos.z},
end_pos = {x=(start_pos.x+max.x-1), y=(start_pos.y+max.y-1), z=(start_pos.z+max.z-1) },
max = {x=max.x, y=max.y, z=max.z}};
end