"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; })();