224 lines
10 KiB
JavaScript
224 lines
10 KiB
JavaScript
"use strict";
|
|
|
|
const ElevatorsBuilder = (function(){
|
|
|
|
const ElevatorsBuilder = function(hollow_bond){
|
|
|
|
const is_near_hole = (chunk, xf, yf, zf, xt, yt, zt) => {
|
|
|
|
const area_xf = xf - hollow_bond.elevator_margin_hole,
|
|
area_xt = xt + hollow_bond.elevator_margin_hole,
|
|
area_zf = zf - hollow_bond.elevator_margin_hole,
|
|
area_zt = zt + hollow_bond.elevator_margin_hole;
|
|
|
|
for(const box of chunk.occupancy)
|
|
if(box.type == "hole")
|
|
if(yf < box.yt && yt > box.yf && area_xf < box.xt && area_xt > box.xf && area_zf < box.zt && area_zt > box.zf)
|
|
return true;
|
|
return false;
|
|
};
|
|
|
|
const is_clearance_free = (chunk, x, y, z, facing, clearance_depth) => {
|
|
|
|
const size = hollow_bond.elevator_size || 2;
|
|
let cxf = x,
|
|
cxt = x + size,
|
|
czf = z,
|
|
czt = z + size;
|
|
|
|
switch(facing){
|
|
case "north":
|
|
czt = z;
|
|
czf = z - clearance_depth;
|
|
break;
|
|
case "south":
|
|
czf = z + size;
|
|
czt = czf + clearance_depth;
|
|
break;
|
|
case "west":
|
|
cxt = x;
|
|
cxf = x - clearance_depth;
|
|
break;
|
|
case "east":
|
|
cxf = x + size;
|
|
cxt = cxf + clearance_depth;
|
|
break;
|
|
};
|
|
|
|
return (
|
|
!(cxf < chunk.xf || cxt > chunk.xt || czf < chunk.zf || czt > chunk.zt) &&
|
|
!is_near_hole(chunk, cxf, y, czf, cxt, y + 1, czt, 0) &&
|
|
!chunk.is_occupied(cxf, y, czf, cxt, y + 1, czt)
|
|
);
|
|
};
|
|
|
|
const add = (chunk, inputs) => {
|
|
|
|
const id = ElevatorModel.get_id(inputs.x, inputs.y, inputs.z),
|
|
elevator = (
|
|
chunk.elevators[id] ||
|
|
hollow_bond.map.elevators[id] ||
|
|
new ElevatorModel(hollow_bond, Object.assign({}, inputs))
|
|
);
|
|
|
|
chunk.elevators[id] = elevator;
|
|
|
|
chunk.occupy(
|
|
elevator.x,
|
|
elevator.y,
|
|
elevator.z,
|
|
elevator.x + hollow_bond.elevator_size,
|
|
elevator.y + 1,
|
|
elevator.z + hollow_bond.elevator_size,
|
|
"elevator",
|
|
elevator.group_id
|
|
);
|
|
|
|
return elevator;
|
|
};
|
|
|
|
this.generate_seam = chunk => {
|
|
|
|
[[chunk.yf, "down"], [chunk.yt, "up"]].forEach(([plane_y, neighbor]) => {
|
|
if(!chunk.neighbors[neighbor])
|
|
return;
|
|
|
|
const networks = Math.floor(hollow_bond.hash.seam_elevator(chunk.xf, plane_y, chunk.zf, chunk.xt, chunk.zt, 0) * hollow_bond.elevator_networks_count); // e.g. 0 a 2 redes por frontera
|
|
|
|
for(let net_i = 0; net_i < networks; net_i ++){
|
|
|
|
const group_id = `net_${chunk.xf}_${plane_y}_${chunk.zf}_${net_i}`,
|
|
stops_count = Common.random_decay(
|
|
hollow_bond.hash.seam_elevator(chunk.xf, plane_y, chunk.zf, chunk.xt, chunk.zt, net_i * 10 + 1),
|
|
hollow_bond.elevator_minimum_floors,
|
|
hollow_bond.elevator_maximum_floors,
|
|
hollow_bond.elevator_floors_decay
|
|
),
|
|
network_stops = [];
|
|
|
|
for(let stop_i = 0; stop_i < stops_count; stop_i ++){
|
|
|
|
const hash_offset = net_i * 100 + stop_i * 6,
|
|
floor_y = plane_y - 25 + Math.floor(hollow_bond.hash.seam_elevator(chunk.xf, plane_y, chunk.zf, chunk.xt, chunk.zt, hash_offset + 2) * 50),
|
|
available_x = hollow_bond.chunk_size - hollow_bond.elevator_size - hollow_bond.elevator_margin_border * 2,
|
|
available_z = hollow_bond.chunk_size - hollow_bond.elevator_size - hollow_bond.elevator_margin_border * 2;
|
|
|
|
if(available_x <= 0 || available_z <= 0)
|
|
continue;
|
|
|
|
const elevator_x = chunk.xf + hollow_bond.elevator_margin_border + Math.floor(hollow_bond.hash.seam_elevator(chunk.xf, plane_y, chunk.zf, chunk.xt, chunk.zt, hash_offset + 3) * available_x),
|
|
elevator_z = chunk.zf + hollow_bond.elevator_margin_border + Math.floor(hollow_bond.hash.seam_elevator(chunk.xf, plane_y, chunk.zf, chunk.xt, chunk.zt, hash_offset + 4) * available_z),
|
|
facing = ["north", "south", "east", "west"][Math.floor(hollow_bond.hash.seam_elevator(chunk.xf, plane_y, chunk.zf, chunk.xt, chunk.zt, hash_offset + 5) * 4)];
|
|
|
|
network_stops.push({
|
|
group_id : group_id,
|
|
x : elevator_x,
|
|
y : floor_y,
|
|
z : elevator_z,
|
|
facing : facing,
|
|
floor : stop_i
|
|
});
|
|
|
|
floor_y >= chunk.yf && floor_y < chunk.yt &&
|
|
!is_near_hole(chunk, elevator_x, floor_y, elevator_z, elevator_x + hollow_bond.elevator_size, floor_y + 1, elevator_z + hollow_bond.elevator_size, hollow_bond.elevator_margin_hole) &&
|
|
!chunk.is_occupied(elevator_x, floor_y, elevator_z, elevator_x + hollow_bond.elevator_size, floor_y + 1, elevator_z + hollow_bond.elevator_size) &&
|
|
is_clearance_free(chunk, elevator_x, floor_y, elevator_z, facing, hollow_bond.room_minimum_size) &&
|
|
add(chunk, {
|
|
group_id : group_id,
|
|
x : elevator_x,
|
|
y : floor_y,
|
|
z : elevator_z,
|
|
facing : facing,
|
|
floors_from : Math.min(...network_stops),
|
|
floors_count : network_stops.length,
|
|
stops : network_stops,
|
|
floor : stop_i
|
|
});
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
return chunk.elevators;
|
|
};
|
|
|
|
this.generate_internal = chunk => {
|
|
|
|
const networks_count = 1 + Math.floor(hollow_bond.hash.elevator(chunk.xf, chunk.yf, chunk.zf, chunk.xt, chunk.yt, chunk.zt, 100) * (hollow_bond.elevator_internal_networks || 3));
|
|
|
|
for(let net = 0; net < networks_count; net ++){
|
|
|
|
const net_base_i = 200 + (net * 50),
|
|
stops_count = Common.random_decay(
|
|
hollow_bond.hash.elevator(chunk.xf, chunk.yf, chunk.zf, chunk.xt, chunk.yt, chunk.zt, net_base_i),
|
|
hollow_bond.elevator_minimum_floors,
|
|
hollow_bond.elevator_maximum_floors,
|
|
hollow_bond.elevator_floors_decay
|
|
),
|
|
group_id = `el_internal_${chunk.x}_${chunk.y}_${chunk.z}_${net}`,
|
|
group_cabins = [],
|
|
available_x = hollow_bond.chunk_size - hollow_bond.elevator_size - hollow_bond.elevator_margin_border * 2,
|
|
available_z = hollow_bond.chunk_size - hollow_bond.elevator_size - hollow_bond.elevator_margin_border * 2,
|
|
available_y = hollow_bond.chunk_size - 2;
|
|
|
|
if(available_x <= 0 || available_z <= 0 || available_y <= 0)
|
|
continue;
|
|
|
|
for(let stops = 0; stops < stops_count; stops ++){
|
|
|
|
const cabin_i = net_base_i + 1 + stops * 5,
|
|
elevator_x = chunk.xf + hollow_bond.elevator_margin_border + Math.floor(hollow_bond.hash.elevator(chunk.xf, chunk.yf, chunk.zf, chunk.xt, chunk.yt, chunk.zt, cabin_i + 1) * available_x),
|
|
elevator_y = chunk.yf + 1 + Math.floor(hollow_bond.hash.elevator(chunk.xf, chunk.yf, chunk.zf, chunk.xt, chunk.yt, chunk.zt, cabin_i + 2) * available_y),
|
|
elevator_z = chunk.zf + hollow_bond.elevator_margin_border + Math.floor(hollow_bond.hash.elevator(chunk.xf, chunk.yf, chunk.zf, chunk.xt, chunk.yt, chunk.zt, cabin_i + 3) * available_z),
|
|
facing = ["north", "south", "east", "west"][Math.floor(hollow_bond.hash.elevator(chunk.xf, chunk.yf, chunk.zf, chunk.xt, chunk.yt, chunk.zt, cabin_i + 4) * 4)];
|
|
|
|
if(
|
|
is_near_hole(chunk, elevator_x, elevator_y, elevator_z, elevator_x + hollow_bond.elevator_size, elevator_y + 1, elevator_z + hollow_bond.elevator_size, hollow_bond.elevator_margin_hole) ||
|
|
chunk.is_occupied(elevator_x, elevator_y, elevator_z, elevator_x + hollow_bond.elevator_size, elevator_y + 1, elevator_z + hollow_bond.elevator_size) ||
|
|
!is_clearance_free(chunk, elevator_x, elevator_y, elevator_z, facing, hollow_bond.room_minimum_size)
|
|
)
|
|
continue;
|
|
|
|
chunk.occupy(elevator_x, elevator_y, elevator_z, elevator_x + hollow_bond.elevator_size, elevator_y + 1, elevator_z + hollow_bond.elevator_size, "elevator", group_id);
|
|
|
|
group_cabins.push({
|
|
x : elevator_x,
|
|
y : elevator_y,
|
|
z : elevator_z,
|
|
facing : facing,
|
|
floor : stops
|
|
});
|
|
|
|
};
|
|
|
|
if(group_cabins.length >= 2){
|
|
|
|
const stops = group_cabins.map(cabin => cabin.y);
|
|
|
|
group_cabins.forEach(cabin => {
|
|
add(chunk, {
|
|
group_id : group_id,
|
|
x : cabin.x,
|
|
y : cabin.y,
|
|
z : cabin.z,
|
|
facing : cabin.facing,
|
|
floors_from : Math.min(...stops),
|
|
floors_count : stops.length,
|
|
stops : stops,
|
|
floor : cabin.floor
|
|
});
|
|
});
|
|
|
|
};
|
|
|
|
};
|
|
|
|
return chunk.elevators;
|
|
};
|
|
|
|
};
|
|
|
|
return ElevatorsBuilder;
|
|
})(); |