mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
v1.22.31
This commit is contained in:
parent
f684996f82
commit
bc6b8cdafe
18 changed files with 111 additions and 111 deletions
12
main.js
12
main.js
|
|
@ -610,7 +610,7 @@ function markFeatures() {
|
||||||
queue.push(e);
|
queue.push(e);
|
||||||
}
|
}
|
||||||
if (land && !eLand) {
|
if (land && !eLand) {
|
||||||
cells.t[q] = 1;
|
cells.t[q] = 1;
|
||||||
cells.t[e] = -1;
|
cells.t[e] = -1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -1055,7 +1055,7 @@ function reMarkFeatures() {
|
||||||
const type = land ? "island" : border ? "ocean" : "lake";
|
const type = land ? "island" : border ? "ocean" : "lake";
|
||||||
let group;
|
let group;
|
||||||
if (type === "lake") group = defineLakeGroup(start, cellNumber);
|
if (type === "lake") group = defineLakeGroup(start, cellNumber);
|
||||||
else if (type === "ocean") group = "ocean";
|
else if (type === "ocean") group = "ocean";
|
||||||
else if (type === "island") group = defineIslandGroup(start, cellNumber);
|
else if (type === "island") group = defineIslandGroup(start, cellNumber);
|
||||||
features.push({i, land, border, type, cells: cellNumber, firstCell: start, group});
|
features.push({i, land, border, type, cells: cellNumber, firstCell: start, group});
|
||||||
queue[0] = cells.f.findIndex(f => !f); // find unmarked cell
|
queue[0] = cells.f.findIndex(f => !f); // find unmarked cell
|
||||||
|
|
@ -1163,7 +1163,7 @@ function rankCells() {
|
||||||
console.timeEnd('rankCells');
|
console.timeEnd('rankCells');
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate army and fleet based on state cells polulation
|
// calculate army and fleet based on state cells polulation
|
||||||
function calculateMilitaryForces() {
|
function calculateMilitaryForces() {
|
||||||
const cells = pack.cells, states = pack.states;
|
const cells = pack.cells, states = pack.states;
|
||||||
const valid = states.filter(s => s.i && !s.removed); // valid states
|
const valid = states.filter(s => s.i && !s.removed); // valid states
|
||||||
|
|
@ -1185,7 +1185,7 @@ function calculateMilitaryForces() {
|
||||||
if ([1, 2, 3, 4].includes(cells.biome[i])) {cavalry *= 3; infantry /= 5; archers /= 2;} else // "nomadic" biomes have lots of cavalry
|
if ([1, 2, 3, 4].includes(cells.biome[i])) {cavalry *= 3; infantry /= 5; archers /= 2;} else // "nomadic" biomes have lots of cavalry
|
||||||
if ([7, 8, 9, 12].includes(cells.biome[i])) {cavalry /= 2.5; infantry *= 1.2; archers *= 1.2;} // "wet" biomes have reduced number of cavalry
|
if ([7, 8, 9, 12].includes(cells.biome[i])) {cavalry /= 2.5; infantry *= 1.2; archers *= 1.2;} // "wet" biomes have reduced number of cavalry
|
||||||
|
|
||||||
s.military.infantry += infantry;
|
s.military.infantry += infantry;
|
||||||
s.military.archers += archers;
|
s.military.archers += archers;
|
||||||
s.military.cavalry += cavalry;
|
s.military.cavalry += cavalry;
|
||||||
s.military.reserve += m * 3 + cells.pop[i] * .02; // reserve is ~5% of population
|
s.military.reserve += m * 3 + cells.pop[i] * .02; // reserve is ~5% of population
|
||||||
|
|
@ -1490,7 +1490,7 @@ function addZones(number = 1) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const invasion = rw({"Invasion":4, "Occupation":3, "Raid":2, "Conquest":2,
|
const invasion = rw({"Invasion":4, "Occupation":3, "Raid":2, "Conquest":2,
|
||||||
"Subjugation":1, "Foray":1, "Skirmishes":1, "Incursion":2, "Pillaging":1, "Intervention":1});
|
"Subjugation":1, "Foray":1, "Skirmishes":1, "Incursion":2, "Pillaging":1, "Intervention":1});
|
||||||
const name = getAdjective(invader.name) + " " + invasion;
|
const name = getAdjective(invader.name) + " " + invasion;
|
||||||
data.push({name, type:"Invasion", cells:cellsArray, fill:"url(#hatch1)"});
|
data.push({name, type:"Invasion", cells:cellsArray, fill:"url(#hatch1)"});
|
||||||
|
|
@ -1518,7 +1518,7 @@ function addZones(number = 1) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const rebels = rw({"Rebels":5, "Insurgents":2, "Mutineers":1, "Rioters":1, "Separatists":1,
|
const rebels = rw({"Rebels":5, "Insurgents":2, "Mutineers":1, "Rioters":1, "Separatists":1,
|
||||||
"Secessionists":1, "Insurrection":2, "Rebellion":1, "Conspiracy":2});
|
"Secessionists":1, "Insurrection":2, "Rebellion":1, "Conspiracy":2});
|
||||||
const name = getAdjective(states[neib].name) + " " + rebels;
|
const name = getAdjective(states[neib].name) + " " + rebels;
|
||||||
data.push({name, type:"Rebels", cells:cellsArray, fill:"url(#hatch3)"});
|
data.push({name, type:"Rebels", cells:cellsArray, fill:"url(#hatch3)"});
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
|
|
||||||
if (sorted.length < count * 10) {
|
if (sorted.length < count * 10) {
|
||||||
count = Math.floor(sorted.length / 10);
|
count = Math.floor(sorted.length / 10);
|
||||||
if (!count) {console.warn(`There is no populated cells. Cannot generate states`); return burgs;}
|
if (!count) {console.warn(`There is no populated cells. Cannot generate states`); return burgs;}
|
||||||
else {console.warn(`Not enought populated cells (${sorted.length}). Will generate only ${count} states`);}
|
else {console.warn(`Not enought populated cells (${sorted.length}). Will generate only ${count} states`);}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,7 +92,7 @@
|
||||||
states.push({i, color: colors[i-1], name, expansionism, capital: i, type, center: b.cell, culture: b.culture});
|
states.push({i, color: colors[i-1], name, expansionism, capital: i, type, center: b.cell, culture: b.culture});
|
||||||
cells.burg[b.cell] = i;
|
cells.burg[b.cell] = i;
|
||||||
});
|
});
|
||||||
|
|
||||||
console.timeEnd('createStates');
|
console.timeEnd('createStates');
|
||||||
return states;
|
return states;
|
||||||
}
|
}
|
||||||
|
|
@ -219,11 +219,11 @@
|
||||||
capitalLabels.selectAll("text").data(capitals).enter()
|
capitalLabels.selectAll("text").data(capitals).enter()
|
||||||
.append("text").attr("id", d => "burgLabel"+d.i).attr("data-id", d => d.i)
|
.append("text").attr("id", d => "burgLabel"+d.i).attr("data-id", d => d.i)
|
||||||
.attr("x", d => d.x).attr("y", d => d.y).attr("dy", `${capitalSize * -1.5}px`).text(d => d.name);
|
.attr("x", d => d.x).attr("y", d => d.y).attr("dy", `${capitalSize * -1.5}px`).text(d => d.name);
|
||||||
|
|
||||||
capitalAnchors.selectAll("use").data(capitals.filter(c => c.port)).enter()
|
capitalAnchors.selectAll("use").data(capitals.filter(c => c.port)).enter()
|
||||||
.append("use").attr("xlink:href", "#icon-anchor").attr("data-id", d => d.i)
|
.append("use").attr("xlink:href", "#icon-anchor").attr("data-id", d => d.i)
|
||||||
.attr("x", d => rn(d.x - caSize * .47, 2)).attr("y", d => rn(d.y - caSize * .47, 2))
|
.attr("x", d => rn(d.x - caSize * .47, 2)).attr("y", d => rn(d.y - caSize * .47, 2))
|
||||||
.attr("width", caSize).attr("height", caSize);
|
.attr("width", caSize).attr("height", caSize);
|
||||||
|
|
||||||
// towns
|
// towns
|
||||||
const towns = pack.burgs.filter(b => b.i && !b.capital);
|
const towns = pack.burgs.filter(b => b.i && !b.capital);
|
||||||
|
|
@ -260,7 +260,7 @@
|
||||||
states.filter(s => s.i && !s.removed).forEach(function(s) {
|
states.filter(s => s.i && !s.removed).forEach(function(s) {
|
||||||
cells.state[burgs[s.capital].cell] = s.i;
|
cells.state[burgs[s.capital].cell] = s.i;
|
||||||
const b = cells.biome[cultures[s.culture].center]; // native biome
|
const b = cells.biome[cultures[s.culture].center]; // native biome
|
||||||
queue.queue({e:s.center, p:0, s:s.i, b});
|
queue.queue({e:s.center, p:0, s:s.i, b});
|
||||||
cost[s.center] = 1;
|
cost[s.center] = 1;
|
||||||
});
|
});
|
||||||
const neutral = cells.i.length / 5000 * 2000 * neutralInput.value * statesNeutral.value; // limit cost for state growth
|
const neutral = cells.i.length / 5000 * 2000 * neutralInput.value * statesNeutral.value; // limit cost for state growth
|
||||||
|
|
@ -312,7 +312,7 @@
|
||||||
|
|
||||||
function getRiverCost(r, i, type) {
|
function getRiverCost(r, i, type) {
|
||||||
if (type === "River") return r ? 0 : 100; // penalty for river cultures
|
if (type === "River") return r ? 0 : 100; // penalty for river cultures
|
||||||
if (!r) return 0; // no penalty for others if there is no river
|
if (!r) return 0; // no penalty for others if there is no river
|
||||||
return Math.min(Math.max(cells.fl[i] / 10, 20), 100) // river penalty from 20 to 100 based on flux
|
return Math.min(Math.max(cells.fl[i] / 10, 20), 100) // river penalty from 20 to 100 based on flux
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -372,7 +372,7 @@
|
||||||
|
|
||||||
function getHull(start, state, maxLake) {
|
function getHull(start, state, maxLake) {
|
||||||
const queue = [start], hull = new Set();
|
const queue = [start], hull = new Set();
|
||||||
|
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
const q = queue.pop();
|
const q = queue.pop();
|
||||||
const nQ = cells.c[q].filter(c => cells.state[c] === state);
|
const nQ = cells.c[q].filter(c => cells.state[c] === state);
|
||||||
|
|
@ -388,7 +388,7 @@
|
||||||
queue.push(c);
|
queue.push(c);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return hull;
|
return hull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -414,7 +414,7 @@
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
const next = queue.dequeue(), n = next.e, p = next.p;
|
const next = queue.dequeue(), n = next.e, p = next.p;
|
||||||
if (n === end) break;
|
if (n === end) break;
|
||||||
|
|
||||||
for (const v of c.v[n]) {
|
for (const v of c.v[n]) {
|
||||||
if (v === -1) continue;
|
if (v === -1) continue;
|
||||||
const totalCost = p + (inside[v] ? 1 : 100);
|
const totalCost = p + (inside[v] ? 1 : 100);
|
||||||
|
|
@ -436,7 +436,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void function drawLabels() {
|
void function drawLabels() {
|
||||||
const g = labels.select("#states"), t = defs.select("#textPaths");
|
const g = labels.select("#states"), t = defs.select("#textPaths");
|
||||||
const displayed = layerIsOn("toggleLabels");
|
const displayed = layerIsOn("toggleLabels");
|
||||||
|
|
@ -553,7 +553,7 @@
|
||||||
states[s].area += cells.area[i];
|
states[s].area += cells.area[i];
|
||||||
states[s].rural += cells.pop[i];
|
states[s].rural += cells.pop[i];
|
||||||
if (cells.burg[i]) {
|
if (cells.burg[i]) {
|
||||||
states[s].urban += pack.burgs[cells.burg[i]].population;
|
states[s].urban += pack.burgs[cells.burg[i]].population;
|
||||||
states[s].burgs++;
|
states[s].burgs++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -995,8 +995,8 @@
|
||||||
console.timeEnd("generateProvinces");
|
console.timeEnd("generateProvinces");
|
||||||
}
|
}
|
||||||
|
|
||||||
return {generate, expandStates, normalizeStates, assignColors,
|
return {generate, expandStates, normalizeStates, assignColors,
|
||||||
drawBurgs, specifyBurgs, defineBurgFeatures, drawStateLabels, collectStatistics,
|
drawBurgs, specifyBurgs, defineBurgFeatures, drawStateLabels, collectStatistics,
|
||||||
generateDiplomacy, defineStateForms, getFullName, generateProvinces};
|
generateDiplomacy, defineStateForms, getFullName, generateProvinces};
|
||||||
|
|
||||||
})));
|
})));
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
}(this, (function () {'use strict';
|
}(this, (function () {'use strict';
|
||||||
|
|
||||||
let cells;
|
let cells;
|
||||||
|
|
||||||
const generate = function() {
|
const generate = function() {
|
||||||
console.time('generateCultures');
|
console.time('generateCultures');
|
||||||
cells = pack.cells;
|
cells = pack.cells;
|
||||||
|
|
@ -99,7 +99,7 @@
|
||||||
if (b === 3 || b === 9 || b === 10) return "Hunting"; // high penalty in non-native biomes
|
if (b === 3 || b === 9 || b === 10) return "Hunting"; // high penalty in non-native biomes
|
||||||
return "Generic";
|
return "Generic";
|
||||||
}
|
}
|
||||||
|
|
||||||
function defineCultureExpansionism(type) {
|
function defineCultureExpansionism(type) {
|
||||||
let base = 1; // Generic
|
let base = 1; // Generic
|
||||||
if (type === "Lake") base = .8; else
|
if (type === "Lake") base = .8; else
|
||||||
|
|
@ -348,7 +348,7 @@
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// expand cultures across the map (Dijkstra-like algorithm)
|
// expand cultures across the map (Dijkstra-like algorithm)
|
||||||
const expand = function() {
|
const expand = function() {
|
||||||
console.time('expandCultures');
|
console.time('expandCultures');
|
||||||
cells = pack.cells;
|
cells = pack.cells;
|
||||||
|
|
@ -358,7 +358,7 @@
|
||||||
if (!c.i || c.removed) return;
|
if (!c.i || c.removed) return;
|
||||||
queue.queue({e:c.center, p:0, c:c.i});
|
queue.queue({e:c.center, p:0, c:c.i});
|
||||||
});
|
});
|
||||||
|
|
||||||
const neutral = cells.i.length / 5000 * 3000 * neutralInput.value; // limit cost for culture growth
|
const neutral = cells.i.length / 5000 * 3000 * neutralInput.value; // limit cost for culture growth
|
||||||
const cost = [];
|
const cost = [];
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
|
|
@ -413,7 +413,7 @@
|
||||||
|
|
||||||
function getRiverCost(r, i, type) {
|
function getRiverCost(r, i, type) {
|
||||||
if (type === "River") return r ? 0 : 100; // penalty for river cultures
|
if (type === "River") return r ? 0 : 100; // penalty for river cultures
|
||||||
if (!r) return 0; // no penalty for others if there is no river
|
if (!r) return 0; // no penalty for others if there is no river
|
||||||
return Math.min(Math.max(cells.fl[i] / 10, 20), 100) // river penalty from 20 to 100 based on flux
|
return Math.min(Math.max(cells.fl[i] / 10, 20), 100) // river penalty from 20 to 100 based on flux
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,7 @@
|
||||||
// find start and end points
|
// find start and end points
|
||||||
const startX = getPointInRange(rangeX, graphWidth);
|
const startX = getPointInRange(rangeX, graphWidth);
|
||||||
const startY = getPointInRange(rangeY, graphHeight);
|
const startY = getPointInRange(rangeY, graphHeight);
|
||||||
|
|
||||||
let dist = 0, limit = 0, endX, endY;
|
let dist = 0, limit = 0, endX, endY;
|
||||||
do {
|
do {
|
||||||
endX = Math.random() * graphWidth * .8 + graphWidth * .1;
|
endX = Math.random() * graphWidth * .8 + graphWidth * .1;
|
||||||
|
|
@ -382,7 +382,7 @@
|
||||||
limit++;
|
limit++;
|
||||||
} while ((dist < graphWidth / 8 || dist > graphWidth / 2) && limit < 50)
|
} while ((dist < graphWidth / 8 || dist > graphWidth / 2) && limit < 50)
|
||||||
|
|
||||||
let range = getRange(start, findGridCell(endX, endY));
|
let range = getRange(start, findGridCell(endX, endY));
|
||||||
|
|
||||||
// get main ridge
|
// get main ridge
|
||||||
function getRange(cur, end) {
|
function getRange(cur, end) {
|
||||||
|
|
@ -452,7 +452,7 @@
|
||||||
|
|
||||||
function getRange(cur, end) {
|
function getRange(cur, end) {
|
||||||
const range = [];
|
const range = [];
|
||||||
|
|
||||||
while (cur !== end) {
|
while (cur !== end) {
|
||||||
let min = Infinity;
|
let min = Infinity;
|
||||||
cells.c[cur].forEach(function(e) {
|
cells.c[cur].forEach(function(e) {
|
||||||
|
|
@ -465,7 +465,7 @@
|
||||||
|
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
const step = .1 / width;
|
const step = .1 / width;
|
||||||
|
|
||||||
while (width > 0) {
|
while (width > 0) {
|
||||||
|
|
@ -512,7 +512,7 @@
|
||||||
const max = range.split("-")[1]/100 || 100;
|
const max = range.split("-")[1]/100 || 100;
|
||||||
return rand(min * length, max * length);
|
return rand(min * length, max * length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {generate, addHill, addRange, addTrough, addStrait, addPit, smooth, modify};
|
return {generate, addHill, addRange, addTrough, addStrait, addPit, smooth, modify};
|
||||||
|
|
||||||
})));
|
})));
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,8 @@
|
||||||
|
|
||||||
const data = chains[base];
|
const data = chains[base];
|
||||||
if (!data || data[" "] === undefined) {
|
if (!data || data[" "] === undefined) {
|
||||||
tip("Namesbase " + base + " is incorrect. Please check in namesbase editor", false, "error");
|
tip("Namesbase " + base + " is incorrect. Please check in namesbase editor", false, "error");
|
||||||
console.error("Namebase " + base + " is incorrect!");
|
console.error("Namebase " + base + " is incorrect!");
|
||||||
return "ERROR";
|
return "ERROR";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,7 +115,7 @@
|
||||||
// generate short name for base
|
// generate short name for base
|
||||||
const getBaseShort = function(base) {
|
const getBaseShort = function(base) {
|
||||||
if (nameBases[base] === undefined) {
|
if (nameBases[base] === undefined) {
|
||||||
tip(`Namebase for culture ${pack.cultures[culture].name} does not exist.
|
tip(`Namebase for culture ${pack.cultures[culture].name} does not exist.
|
||||||
Please upload custom namebases of change the base in Cultures Editor`, false, "error");
|
Please upload custom namebases of change the base in Cultures Editor`, false, "error");
|
||||||
base = 1;
|
base = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -148,7 +148,7 @@
|
||||||
else if (P(.7)) name = name.slice(0,-1); // ~60% for cv
|
else if (P(.7)) name = name.slice(0,-1); // ~60% for cv
|
||||||
else return name;
|
else return name;
|
||||||
} else if (P(.4)) return name; // 60% for cc and vc
|
} else if (P(.4)) return name; // 60% for cc and vc
|
||||||
|
|
||||||
// define suffix
|
// define suffix
|
||||||
let suffix = "ia"; // standard suffix
|
let suffix = "ia"; // standard suffix
|
||||||
|
|
||||||
|
|
@ -202,7 +202,7 @@
|
||||||
if (suffix === "land" && name.length > 6) name = name.slice(0, -(name.length-5));
|
if (suffix === "land" && name.length > 6) name = name.slice(0, -(name.length-5));
|
||||||
return validateSuffix(name, suffix);
|
return validateSuffix(name, suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
const getNameBases = function() {
|
const getNameBases = function() {
|
||||||
// name, min length, max length, letters to allow duplication, multi-word name rate
|
// name, min length, max length, letters to allow duplication, multi-word name rate
|
||||||
return [
|
return [
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@
|
||||||
chain.push(chain[0]); // push first vertex as the last one
|
chain.push(chain[0]); // push first vertex as the last one
|
||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OceanLayers;
|
return OceanLayers;
|
||||||
|
|
||||||
})));
|
})));
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
for (const i of cells.i) {
|
for (const i of cells.i) {
|
||||||
const height = cells.h[i];
|
const height = cells.h[i];
|
||||||
if (height < 20) continue; // no icons on water
|
if (height < 20) continue; // no icons on water
|
||||||
if (cells.r[i]) continue; // no icons on rivers
|
if (cells.r[i]) continue; // no icons on rivers
|
||||||
const b = cells.biome[i];
|
const b = cells.biome[i];
|
||||||
if (height < 50 && biomesData.iconsDensity[b] === 0) continue; // no icons for this biome
|
if (height < 50 && biomesData.iconsDensity[b] === 0) continue; // no icons for this biome
|
||||||
const polygon = getPackPolygon(i);
|
const polygon = getPackPolygon(i);
|
||||||
|
|
@ -42,7 +42,7 @@
|
||||||
function placeReliefIcons(i) {
|
function placeReliefIcons(i) {
|
||||||
const radius = 2 / density;
|
const radius = 2 / density;
|
||||||
const [icon, h] = getReliefIcon(i, height);
|
const [icon, h] = getReliefIcon(i, height);
|
||||||
|
|
||||||
for (const [cx, cy] of poissonDiscSampler(e[0], e[1], e[2], e[3], radius)) {
|
for (const [cx, cy] of poissonDiscSampler(e[0], e[1], e[2], e[3], radius)) {
|
||||||
if (!d3.polygonContains(polygon, [cx, cy])) continue;
|
if (!d3.polygonContains(polygon, [cx, cy])) continue;
|
||||||
relief.push({i: icon, x: rn(cx-h, 2), y: rn(cy-h, 2), s: h*2});
|
relief.push({i: icon, x: rn(cx-h, 2), y: rn(cy-h, 2), s: h*2});
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
}(this, (function () {'use strict';
|
}(this, (function () {'use strict';
|
||||||
|
|
||||||
// name generation approach and relative chance to be selected
|
// name generation approach and relative chance to be selected
|
||||||
const approach = {"Number":1, "Being":3, "Adjective":5, "Color + Animal":5,
|
const approach = {"Number":1, "Being":3, "Adjective":5, "Color + Animal":5,
|
||||||
"Adjective + Animal":5, "Adjective + Being":5, "Adjective + Genitive":1,
|
"Adjective + Animal":5, "Adjective + Being":5, "Adjective + Genitive":1,
|
||||||
"Color + Being":3, "Color + Genitive":3, "Being + of + Genitive":2, "Being + of the + Genitive":1,
|
"Color + Being":3, "Color + Genitive":3, "Being + of + Genitive":2, "Being + of the + Genitive":1,
|
||||||
"Animal + of + Genitive":1, "Adjective + Being + of + Genitive":2, "Adjective + Animal + of + Genitive":2};
|
"Animal + of + Genitive":1, "Adjective + Being + of + Genitive":2, "Adjective + Animal + of + Genitive":2};
|
||||||
|
|
||||||
// turn weighted array into simple array
|
// turn weighted array into simple array
|
||||||
|
|
@ -237,7 +237,7 @@
|
||||||
religions.filter(r => r.type === "Heresy").forEach(r => {
|
religions.filter(r => r.type === "Heresy").forEach(r => {
|
||||||
const b = cells.religion[r.center]; // "base" religion id
|
const b = cells.religion[r.center]; // "base" religion id
|
||||||
cells.religion[r.center] = r.i; // heresy id
|
cells.religion[r.center] = r.i; // heresy id
|
||||||
queue.queue({e:r.center, p:0, r:r.i, b});
|
queue.queue({e:r.center, p:0, r:r.i, b});
|
||||||
cost[r.center] = 1;
|
cost[r.center] = 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -308,10 +308,10 @@
|
||||||
if (a === "Adjective + Being") return ra(base.adjective) + " " + ra(base.being);
|
if (a === "Adjective + Being") return ra(base.adjective) + " " + ra(base.being);
|
||||||
if (a === "Adjective + Genitive") return ra(base.adjective) + " " + ra(base.genitive);
|
if (a === "Adjective + Genitive") return ra(base.adjective) + " " + ra(base.genitive);
|
||||||
if (a === "Color + Being") return ra(base.color) + " " + ra(base.being);
|
if (a === "Color + Being") return ra(base.color) + " " + ra(base.being);
|
||||||
if (a === "Color + Genitive") return ra(base.color) + " " + ra(base.genitive);
|
if (a === "Color + Genitive") return ra(base.color) + " " + ra(base.genitive);
|
||||||
if (a === "Being + of + Genitive") return ra(base.being) + " of " + ra(base.genitive);
|
if (a === "Being + of + Genitive") return ra(base.being) + " of " + ra(base.genitive);
|
||||||
if (a === "Being + of the + Genitive") return ra(base.being) + " of the " + ra(base.theGenitive);
|
if (a === "Being + of the + Genitive") return ra(base.being) + " of the " + ra(base.theGenitive);
|
||||||
if (a === "Animal + of + Genitive") return ra(base.animal) + " of " + ra(base.genitive);
|
if (a === "Animal + of + Genitive") return ra(base.animal) + " of " + ra(base.genitive);
|
||||||
if (a === "Adjective + Being + of + Genitive") return ra(base.adjective) + " " + ra(base.being) + " of " + ra(base.genitive);
|
if (a === "Adjective + Being + of + Genitive") return ra(base.adjective) + " " + ra(base.being) + " of " + ra(base.genitive);
|
||||||
if (a === "Adjective + Animal + of + Genitive") return ra(base.adjective) + " " + ra(base.animal) + " of " + ra(base.genitive);
|
if (a === "Adjective + Animal + of + Genitive") return ra(base.adjective) + " " + ra(base.animal) + " of " + ra(base.genitive);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,9 +44,9 @@
|
||||||
if (cells.r[i]) {
|
if (cells.r[i]) {
|
||||||
const to = [];
|
const to = [];
|
||||||
const min = Math.min(y, graphHeight - y, x, graphWidth - x);
|
const min = Math.min(y, graphHeight - y, x, graphWidth - x);
|
||||||
if (min === y) {to[0] = x; to[1] = 0;} else
|
if (min === y) {to[0] = x; to[1] = 0;} else
|
||||||
if (min === graphHeight - y) {to[0] = x; to[1] = graphHeight;} else
|
if (min === graphHeight - y) {to[0] = x; to[1] = graphHeight;} else
|
||||||
if (min === x) {to[0] = 0; to[1] = y;} else
|
if (min === x) {to[0] = 0; to[1] = y;} else
|
||||||
if (min === graphWidth - x) {to[0] = graphWidth; to[1] = y;}
|
if (min === graphWidth - x) {to[0] = graphWidth; to[1] = y;}
|
||||||
riversData.push({river: cells.r[i], cell: i, x: to[0], y: to[1]});
|
riversData.push({river: cells.r[i], cell: i, x: to[0], y: to[1]});
|
||||||
}
|
}
|
||||||
|
|
@ -59,14 +59,14 @@
|
||||||
// allow only one river can flow thought a lake
|
// allow only one river can flow thought a lake
|
||||||
const cf = features[cells.f[i]]; // current cell feature
|
const cf = features[cells.f[i]]; // current cell feature
|
||||||
if (cf.river && cf.river !== cells.r[i]) {
|
if (cf.river && cf.river !== cells.r[i]) {
|
||||||
cells.fl[i] = 0;
|
cells.fl[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cells.fl[i] < 30) {
|
if (cells.fl[i] < 30) {
|
||||||
if (h[min] >= 20) cells.fl[min] += cells.fl[i];
|
if (h[min] >= 20) cells.fl[min] += cells.fl[i];
|
||||||
return; // flux is too small to operate as river
|
return; // flux is too small to operate as river
|
||||||
}
|
}
|
||||||
|
|
||||||
// Proclaim a new river
|
// Proclaim a new river
|
||||||
if (!cells.r[i]) {
|
if (!cells.r[i]) {
|
||||||
cells.r[i] = riverNext;
|
cells.r[i] = riverNext;
|
||||||
|
|
@ -165,14 +165,14 @@
|
||||||
const addMeandring = function(segments, rndFactor = 0.3) {
|
const addMeandring = function(segments, rndFactor = 0.3) {
|
||||||
const riverEnhanced = []; // to store enhanced segments
|
const riverEnhanced = []; // to store enhanced segments
|
||||||
let side = 1; // to control meandring direction
|
let side = 1; // to control meandring direction
|
||||||
|
|
||||||
for (let s = 0; s < segments.length; s++) {
|
for (let s = 0; s < segments.length; s++) {
|
||||||
const sX = segments[s].x, sY = segments[s].y; // segment start coordinates
|
const sX = segments[s].x, sY = segments[s].y; // segment start coordinates
|
||||||
const c = pack.cells.conf[segments[s].cell] || 0; // if segment is river confluence
|
const c = pack.cells.conf[segments[s].cell] || 0; // if segment is river confluence
|
||||||
riverEnhanced.push([sX, sY, c]);
|
riverEnhanced.push([sX, sY, c]);
|
||||||
|
|
||||||
if (s+1 === segments.length) break; // do not enhance last segment
|
if (s+1 === segments.length) break; // do not enhance last segment
|
||||||
|
|
||||||
const eX = segments[s+1].x, eY = segments[s+1].y; // segment end coordinates
|
const eX = segments[s+1].x, eY = segments[s+1].y; // segment end coordinates
|
||||||
const angle = Math.atan2(eY - sY, eX - sX);
|
const angle = Math.atan2(eY - sY, eX - sX);
|
||||||
const sin = Math.sin(angle), cos = Math.cos(angle);
|
const sin = Math.sin(angle), cos = Math.cos(angle);
|
||||||
|
|
@ -194,13 +194,13 @@
|
||||||
const p1y = (sY + eY) / 2 + side * cos * meandr;
|
const p1y = (sY + eY) / 2 + side * cos * meandr;
|
||||||
riverEnhanced.push([p1x, p1y]);
|
riverEnhanced.push([p1x, p1y]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return riverEnhanced;
|
return riverEnhanced;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPath = function(points, width = 1, increment = 1) {
|
const getPath = function(points, width = 1, increment = 1) {
|
||||||
let offset, extraOffset = .1; // starting river width (to make river source visible)
|
let offset, extraOffset = .1; // starting river width (to make river source visible)
|
||||||
const riverLength = points.reduce((s, v, i, p) => s + (i ? Math.hypot(v[0] - p[i-1][0], v[1] - p[i-1][1]) : 0), 0); // summ of segments length
|
const riverLength = points.reduce((s, v, i, p) => s + (i ? Math.hypot(v[0] - p[i-1][0], v[1] - p[i-1][1]) : 0), 0); // summ of segments length
|
||||||
const widening = rn((1000 + (riverLength * 30)) * increment);
|
const widening = rn((1000 + (riverLength * 30)) * increment);
|
||||||
const riverPointsLeft = [], riverPointsRight = []; // store points on both sides to build a valid polygon
|
const riverPointsLeft = [], riverPointsRight = []; // store points on both sides to build a valid polygon
|
||||||
|
|
@ -215,7 +215,7 @@
|
||||||
riverPointsLeft.push([xLeft, yLeft]);
|
riverPointsLeft.push([xLeft, yLeft]);
|
||||||
let xRight = x + sin * extraOffset, yRight = y + -cos * extraOffset;
|
let xRight = x + sin * extraOffset, yRight = y + -cos * extraOffset;
|
||||||
riverPointsRight.unshift([xRight, yRight]);
|
riverPointsRight.unshift([xRight, yRight]);
|
||||||
|
|
||||||
// middle points
|
// middle points
|
||||||
for (let p = 1; p < last; p++) {
|
for (let p = 1; p < last; p++) {
|
||||||
x = points[p][0], y = points[p][1], c = points[p][2] || 0;
|
x = points[p][0], y = points[p][1], c = points[p][2] || 0;
|
||||||
|
|
@ -231,7 +231,7 @@
|
||||||
xRight = x + sin * offset, yRight = y + -cos * offset;
|
xRight = x + sin * offset, yRight = y + -cos * offset;
|
||||||
riverPointsRight.unshift([xRight, yRight]);
|
riverPointsRight.unshift([xRight, yRight]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// end point
|
// end point
|
||||||
x = points[last][0], y = points[last][1], c = points[last][2];
|
x = points[last][0], y = points[last][1], c = points[last][2];
|
||||||
if (c) extraOffset += Math.atan(c * 10 / widening); // add extra width on river confluence
|
if (c) extraOffset += Math.atan(c * 10 / widening); // add extra width on river confluence
|
||||||
|
|
@ -241,7 +241,7 @@
|
||||||
riverPointsLeft.push([xLeft, yLeft]);
|
riverPointsLeft.push([xLeft, yLeft]);
|
||||||
xRight = x + sin * offset, yRight = y + -cos * offset;
|
xRight = x + sin * offset, yRight = y + -cos * offset;
|
||||||
riverPointsRight.unshift([xRight, yRight]);
|
riverPointsRight.unshift([xRight, yRight]);
|
||||||
|
|
||||||
// generate polygon path and return
|
// generate polygon path and return
|
||||||
lineGen.curve(d3.curveCatmullRom.alpha(0.1));
|
lineGen.curve(d3.curveCatmullRom.alpha(0.1));
|
||||||
const right = lineGen(riverPointsRight);
|
const right = lineGen(riverPointsRight);
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@
|
||||||
|
|
||||||
// main routes
|
// main routes
|
||||||
roads.selectAll("path").data(main).enter().append("path")
|
roads.selectAll("path").data(main).enter().append("path")
|
||||||
.attr("id", (d, i) => "road" + i)
|
.attr("id", (d, i) => "road" + i)
|
||||||
.attr("d", d => round(lineGen(d.map(c => {
|
.attr("d", d => round(lineGen(d.map(c => {
|
||||||
const b = cells.burg[c];
|
const b = cells.burg[c];
|
||||||
const x = b ? burgs[b].x : cells.p[c][0];
|
const x = b ? burgs[b].x : cells.p[c][0];
|
||||||
|
|
@ -125,7 +125,7 @@
|
||||||
|
|
||||||
// small routes
|
// small routes
|
||||||
trails.selectAll("path").data(small).enter().append("path")
|
trails.selectAll("path").data(small).enter().append("path")
|
||||||
.attr("id", (d, i) => "trail" + i)
|
.attr("id", (d, i) => "trail" + i)
|
||||||
.attr("d", d => round(lineGen(d.map(c => {
|
.attr("d", d => round(lineGen(d.map(c => {
|
||||||
const b = cells.burg[c];
|
const b = cells.burg[c];
|
||||||
const x = b ? burgs[b].x : cells.p[c][0];
|
const x = b ? burgs[b].x : cells.p[c][0];
|
||||||
|
|
@ -136,7 +136,7 @@
|
||||||
// ocean routes
|
// ocean routes
|
||||||
lineGen.curve(d3.curveBundle.beta(1));
|
lineGen.curve(d3.curveBundle.beta(1));
|
||||||
searoutes.selectAll("path").data(ocean).enter().append("path")
|
searoutes.selectAll("path").data(ocean).enter().append("path")
|
||||||
.attr("id", (d, i) => "searoute" + i)
|
.attr("id", (d, i) => "searoute" + i)
|
||||||
.attr("d", d => round(lineGen(d.map(c => {
|
.attr("d", d => round(lineGen(d.map(c => {
|
||||||
const b = cells.burg[c];
|
const b = cells.burg[c];
|
||||||
const x = b ? burgs[b].x : cells.p[c][0];
|
const x = b ? burgs[b].x : cells.p[c][0];
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@
|
||||||
}(this, (function () {'use strict';
|
}(this, (function () {'use strict';
|
||||||
|
|
||||||
// set default options
|
// set default options
|
||||||
const options = {scale: 50, lightness: .7, shadow: .5, sun: {x: 100, y: 600, z: 1000}, rotateMesh: 0, rotateGlobe: .5,
|
const options = {scale: 50, lightness: .7, shadow: .5, sun: {x: 100, y: 600, z: 1000}, rotateMesh: 0, rotateGlobe: .5,
|
||||||
skyColor: "#9ecef5", waterColor: "#53679f", extendedWater: 0, resolution: 2};
|
skyColor: "#9ecef5", waterColor: "#53679f", extendedWater: 0, resolution: 2};
|
||||||
|
|
||||||
// set variables
|
// set variables
|
||||||
let Renderer, scene, camera, controls, animationFrame, material, texture,
|
let Renderer, scene, camera, controls, animationFrame, material, texture,
|
||||||
geometry, mesh, ambientLight, spotLight, waterPlane, waterMaterial, waterMesh;
|
geometry, mesh, ambientLight, spotLight, waterPlane, waterMaterial, waterMesh;
|
||||||
|
|
||||||
// initiate 3d scene
|
// initiate 3d scene
|
||||||
|
|
@ -157,7 +157,7 @@ async function newMesh(canvas) {
|
||||||
// controls
|
// controls
|
||||||
controls = await OrbitControls(camera, canvas);
|
controls = await OrbitControls(camera, canvas);
|
||||||
controls.enableKeys = false;
|
controls.enableKeys = false;
|
||||||
controls.minDistance = 10;
|
controls.minDistance = 10;
|
||||||
controls.maxDistance = 1000;
|
controls.maxDistance = 1000;
|
||||||
controls.maxPolarAngle = Math.PI/2;
|
controls.maxPolarAngle = Math.PI/2;
|
||||||
controls.autoRotate = Boolean(options.rotateMesh);
|
controls.autoRotate = Boolean(options.rotateMesh);
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ function editBiomes() {
|
||||||
const color = biomesData.color[biome];
|
const color = biomesData.color[biome];
|
||||||
biomes.select("#biome"+biome).transition().attr("stroke-width", .7).attr("stroke", color);
|
biomes.select("#biome"+biome).transition().attr("stroke-width", .7).attr("stroke", color);
|
||||||
}
|
}
|
||||||
|
|
||||||
function biomeChangeColor(el) {
|
function biomeChangeColor(el) {
|
||||||
const currentFill = el.getAttribute("fill");
|
const currentFill = el.getAttribute("fill");
|
||||||
const biome = +el.parentNode.parentNode.dataset.id;
|
const biome = +el.parentNode.parentNode.dataset.id;
|
||||||
|
|
@ -145,7 +145,7 @@ function editBiomes() {
|
||||||
|
|
||||||
openPicker(currentFill, callback);
|
openPicker(currentFill, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
function biomeChangeName(el) {
|
function biomeChangeName(el) {
|
||||||
const biome = +el.parentNode.dataset.id;
|
const biome = +el.parentNode.dataset.id;
|
||||||
el.parentNode.dataset.name = el.value;
|
el.parentNode.dataset.name = el.value;
|
||||||
|
|
@ -200,12 +200,12 @@ function editBiomes() {
|
||||||
body.dataset.type = "percentage";
|
body.dataset.type = "percentage";
|
||||||
const totalCells = +biomesFooterCells.innerHTML;
|
const totalCells = +biomesFooterCells.innerHTML;
|
||||||
const totalArea = +biomesFooterArea.dataset.area;
|
const totalArea = +biomesFooterArea.dataset.area;
|
||||||
const totalPopulation = +biomesFooterPopulation.dataset.population;
|
const totalPopulation = +biomesFooterPopulation.dataset.population;
|
||||||
|
|
||||||
body.querySelectorAll(":scope> div").forEach(function(el) {
|
body.querySelectorAll(":scope> div").forEach(function(el) {
|
||||||
el.querySelector(".biomeCells").innerHTML = rn(+el.dataset.cells / totalCells * 100) + "%";
|
el.querySelector(".biomeCells").innerHTML = rn(+el.dataset.cells / totalCells * 100) + "%";
|
||||||
el.querySelector(".biomeArea").innerHTML = rn(+el.dataset.area / totalArea * 100) + "%";
|
el.querySelector(".biomeArea").innerHTML = rn(+el.dataset.area / totalArea * 100) + "%";
|
||||||
el.querySelector(".biomePopulation").innerHTML = rn(+el.dataset.population / totalPopulation * 100) + "%";
|
el.querySelector(".biomePopulation").innerHTML = rn(+el.dataset.population / totalPopulation * 100) + "%";
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
body.dataset.type = "absolute";
|
body.dataset.type = "absolute";
|
||||||
|
|
@ -314,7 +314,7 @@ function editBiomes() {
|
||||||
const biome = assigned.size() ? +assigned.attr("data-biome") : pack.cells.biome[i];
|
const biome = assigned.size() ? +assigned.attr("data-biome") : pack.cells.biome[i];
|
||||||
|
|
||||||
body.querySelector("div.selected").classList.remove("selected");
|
body.querySelector("div.selected").classList.remove("selected");
|
||||||
body.querySelector("div[data-id='"+biome+"']").classList.add("selected");
|
body.querySelector("div[data-id='"+biome+"']").classList.add("selected");
|
||||||
}
|
}
|
||||||
|
|
||||||
function dragBiomeBrush() {
|
function dragBiomeBrush() {
|
||||||
|
|
@ -324,7 +324,7 @@ function editBiomes() {
|
||||||
if (!d3.event.dx && !d3.event.dy) return;
|
if (!d3.event.dx && !d3.event.dy) return;
|
||||||
const p = d3.mouse(this);
|
const p = d3.mouse(this);
|
||||||
moveCircle(p[0], p[1], r);
|
moveCircle(p[0], p[1], r);
|
||||||
|
|
||||||
const found = r > 5 ? findAll(p[0], p[1], r) : [findCell(p[0], p[1], r)];
|
const found = r > 5 ? findAll(p[0], p[1], r) : [findCell(p[0], p[1], r)];
|
||||||
const selection = found.filter(isLand);
|
const selection = found.filter(isLand);
|
||||||
if (selection) changeBiomeForSelection(selection);
|
if (selection) changeBiomeForSelection(selection);
|
||||||
|
|
@ -356,7 +356,7 @@ function editBiomes() {
|
||||||
const radius = +biomesManuallyBrush.value;
|
const radius = +biomesManuallyBrush.value;
|
||||||
moveCircle(point[0], point[1], radius);
|
moveCircle(point[0], point[1], radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyBiomesChange() {
|
function applyBiomesChange() {
|
||||||
const changed = biomes.select("#temp").selectAll("polygon");
|
const changed = biomes.select("#temp").selectAll("polygon");
|
||||||
changed.each(function() {
|
changed.each(function() {
|
||||||
|
|
@ -364,7 +364,7 @@ function editBiomes() {
|
||||||
const b = +this.dataset.biome;
|
const b = +this.dataset.biome;
|
||||||
pack.cells.biome[i] = b;
|
pack.cells.biome[i] = b;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (changed.size()) {
|
if (changed.size()) {
|
||||||
drawBiomes();
|
drawBiomes();
|
||||||
refreshBiomesEditor();
|
refreshBiomesEditor();
|
||||||
|
|
@ -390,7 +390,7 @@ function editBiomes() {
|
||||||
const selected = document.querySelector("#biomesBody > div.selected");
|
const selected = document.querySelector("#biomesBody > div.selected");
|
||||||
if (selected) selected.classList.remove("selected");
|
if (selected) selected.classList.remove("selected");
|
||||||
}
|
}
|
||||||
|
|
||||||
function restoreInitialBiomes() {
|
function restoreInitialBiomes() {
|
||||||
biomesData = applyDefaultBiomesSystem();
|
biomesData = applyDefaultBiomesSystem();
|
||||||
defineBiomes();
|
defineBiomes();
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ function editBurg(id) {
|
||||||
const of = id ? "svg" : d3.event.target;
|
const of = id ? "svg" : d3.event.target;
|
||||||
|
|
||||||
$("#burgEditor").dialog({
|
$("#burgEditor").dialog({
|
||||||
title: "Edit Burg", resizable: false, close: closeBurgEditor,
|
title: "Edit Burg", resizable: false, close: closeBurgEditor,
|
||||||
position: {my, at, of, collision: "fit"}
|
position: {my, at, of, collision: "fit"}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -56,19 +56,19 @@ function editBurg(id) {
|
||||||
document.getElementById("burgEditAnchorStyle").style.display = +b.port ? "inline-block" : "none";
|
document.getElementById("burgEditAnchorStyle").style.display = +b.port ? "inline-block" : "none";
|
||||||
|
|
||||||
// toggle features
|
// toggle features
|
||||||
if (b.capital) document.getElementById("burgCapital").classList.remove("inactive");
|
if (b.capital) document.getElementById("burgCapital").classList.remove("inactive");
|
||||||
else document.getElementById("burgCapital").classList.add("inactive");
|
else document.getElementById("burgCapital").classList.add("inactive");
|
||||||
if (b.port) document.getElementById("burgPort").classList.remove("inactive");
|
if (b.port) document.getElementById("burgPort").classList.remove("inactive");
|
||||||
else document.getElementById("burgPort").classList.add("inactive");
|
else document.getElementById("burgPort").classList.add("inactive");
|
||||||
if (b.citadel) document.getElementById("burgCitadel").classList.remove("inactive");
|
if (b.citadel) document.getElementById("burgCitadel").classList.remove("inactive");
|
||||||
else document.getElementById("burgCitadel").classList.add("inactive");
|
else document.getElementById("burgCitadel").classList.add("inactive");
|
||||||
if (b.walls) document.getElementById("burgWalls").classList.remove("inactive");
|
if (b.walls) document.getElementById("burgWalls").classList.remove("inactive");
|
||||||
else document.getElementById("burgWalls").classList.add("inactive");
|
else document.getElementById("burgWalls").classList.add("inactive");
|
||||||
if (b.plaza) document.getElementById("burgPlaza").classList.remove("inactive");
|
if (b.plaza) document.getElementById("burgPlaza").classList.remove("inactive");
|
||||||
else document.getElementById("burgPlaza").classList.add("inactive");
|
else document.getElementById("burgPlaza").classList.add("inactive");
|
||||||
if (b.temple) document.getElementById("burgTemple").classList.remove("inactive");
|
if (b.temple) document.getElementById("burgTemple").classList.remove("inactive");
|
||||||
else document.getElementById("burgTemple").classList.add("inactive");
|
else document.getElementById("burgTemple").classList.add("inactive");
|
||||||
if (b.shanty) document.getElementById("burgShanty").classList.remove("inactive");
|
if (b.shanty) document.getElementById("burgShanty").classList.remove("inactive");
|
||||||
else document.getElementById("burgShanty").classList.add("inactive");
|
else document.getElementById("burgShanty").classList.add("inactive");
|
||||||
|
|
||||||
// select group
|
// select group
|
||||||
|
|
@ -102,7 +102,7 @@ function editBurg(id) {
|
||||||
document.getElementById("burgGroupSection").style.display = "none";
|
document.getElementById("burgGroupSection").style.display = "none";
|
||||||
document.getElementById("burgInputGroup").style.display = "none";
|
document.getElementById("burgInputGroup").style.display = "none";
|
||||||
document.getElementById("burgInputGroup").value = "";
|
document.getElementById("burgInputGroup").value = "";
|
||||||
document.getElementById("burgSelectGroup").style.display = "inline-block";
|
document.getElementById("burgSelectGroup").style.display = "inline-block";
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeGroup() {
|
function changeGroup() {
|
||||||
|
|
@ -187,7 +187,7 @@ function editBurg(id) {
|
||||||
const burgsToRemove = burgsInGroup.filter(b => !pack.burgs[b].capital);
|
const burgsToRemove = burgsInGroup.filter(b => !pack.burgs[b].capital);
|
||||||
const capital = burgsToRemove.length < burgsInGroup.length;
|
const capital = burgsToRemove.length < burgsInGroup.length;
|
||||||
|
|
||||||
alertMessage.innerHTML = `Are you sure you want to remove
|
alertMessage.innerHTML = `Are you sure you want to remove
|
||||||
${basic || capital ? "all elements in the group" : "the entire burg group"}?
|
${basic || capital ? "all elements in the group" : "the entire burg group"}?
|
||||||
<br>Please note that capital burgs will not be deleted.
|
<br>Please note that capital burgs will not be deleted.
|
||||||
<br><br>Burgs to be removed: ${burgsToRemove.length}`;
|
<br><br>Burgs to be removed: ${burgsToRemove.length}`;
|
||||||
|
|
@ -243,7 +243,7 @@ function editBurg(id) {
|
||||||
const b = pack.burgs[id];
|
const b = pack.burgs[id];
|
||||||
const feature = this.dataset.feature;
|
const feature = this.dataset.feature;
|
||||||
const turnOn = this.classList.contains("inactive");
|
const turnOn = this.classList.contains("inactive");
|
||||||
if (feature === "port") togglePort(id);
|
if (feature === "port") togglePort(id);
|
||||||
else if(feature === "capital") toggleCapital(id);
|
else if(feature === "capital") toggleCapital(id);
|
||||||
else b[feature] = +turnOn;
|
else b[feature] = +turnOn;
|
||||||
if (b[feature]) this.classList.remove("inactive");
|
if (b[feature]) this.classList.remove("inactive");
|
||||||
|
|
@ -284,7 +284,7 @@ function editBurg(id) {
|
||||||
const defSeed = seed + id.padStart(4, 0);
|
const defSeed = seed + id.padStart(4, 0);
|
||||||
|
|
||||||
if (event.ctrlKey) {
|
if (event.ctrlKey) {
|
||||||
const newSeed = prompt(`Please provide a Medieval Fantasy City Generator seed. `+
|
const newSeed = prompt(`Please provide a Medieval Fantasy City Generator seed. `+
|
||||||
`Seed should be a number. Default seed is FMG map seed + burg id padded to 4 chars with zeros (${defSeed}). `+
|
`Seed should be a number. Default seed is FMG map seed + burg id padded to 4 chars with zeros (${defSeed}). `+
|
||||||
`Please note that if seed is custom, "Overworld" button from MFCG will open a different map`, burg.MFCG || defSeed);
|
`Please note that if seed is custom, "Overworld" button from MFCG will open a different map`, burg.MFCG || defSeed);
|
||||||
if (newSeed) burg.MFCG = newSeed; else return;
|
if (newSeed) burg.MFCG = newSeed; else return;
|
||||||
|
|
@ -315,7 +315,7 @@ function editBurg(id) {
|
||||||
const defSeed = `${seed}-b${id}`;
|
const defSeed = `${seed}-b${id}`;
|
||||||
|
|
||||||
if (event.ctrlKey) {
|
if (event.ctrlKey) {
|
||||||
const newSeed = prompt(`Please provide an Iron Arachne Heraldry Generator seed. `+
|
const newSeed = prompt(`Please provide an Iron Arachne Heraldry Generator seed. `+
|
||||||
`Default seed is a combination of FMG map seed and burg id (${defSeed})`, burg.IAHG || defSeed);
|
`Default seed is a combination of FMG map seed and burg id (${defSeed})`, burg.IAHG || defSeed);
|
||||||
if (newSeed) burg.IAHG = newSeed; else return;
|
if (newSeed) burg.IAHG = newSeed; else return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -344,8 +344,8 @@ function overviewBurgs() {
|
||||||
if (this.value === "provinces") return d.province;
|
if (this.value === "provinces") return d.province;
|
||||||
}
|
}
|
||||||
|
|
||||||
const base = this.value === "states" ? getStatesData()
|
const base = this.value === "states" ? getStatesData()
|
||||||
: this.value === "cultures" ? getCulturesData()
|
: this.value === "cultures" ? getCulturesData()
|
||||||
: this.value === "parent" ? getParentData() : getProvincesData();
|
: this.value === "parent" ? getParentData() : getProvincesData();
|
||||||
burgs.forEach(b => b.id = b.i+base.length-1);
|
burgs.forEach(b => b.id = b.i+base.length-1);
|
||||||
|
|
||||||
|
|
@ -401,7 +401,7 @@ function overviewBurgs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function renameBurgsInBulk() {
|
function renameBurgsInBulk() {
|
||||||
const message = `Download burgs list as a text file, make changes and re-upload the file.
|
const message = `Download burgs list as a text file, make changes and re-upload the file.
|
||||||
If you do not want to change the name, just leave it as is`;
|
If you do not want to change the name, just leave it as is`;
|
||||||
alertMessage.innerHTML = message;
|
alertMessage.innerHTML = message;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ function editCoastline(node = d3.event.target) {
|
||||||
document.getElementById("coastlineGroupsSelection").style.display = "none";
|
document.getElementById("coastlineGroupsSelection").style.display = "none";
|
||||||
document.getElementById("coastlineGroupName").style.display = "none";
|
document.getElementById("coastlineGroupName").style.display = "none";
|
||||||
document.getElementById("coastlineGroupName").value = "";
|
document.getElementById("coastlineGroupName").value = "";
|
||||||
document.getElementById("coastlineGroup").style.display = "inline-block";
|
document.getElementById("coastlineGroup").style.display = "inline-block";
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectCoastlineGroup(node) {
|
function selectCoastlineGroup(node) {
|
||||||
|
|
@ -107,7 +107,7 @@ function editCoastline(node = d3.event.target) {
|
||||||
} else {
|
} else {
|
||||||
coastlineGroupName.style.display = "none";
|
coastlineGroupName.style.display = "none";
|
||||||
coastlineGroup.style.display = "inline-block";
|
coastlineGroup.style.display = "inline-block";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNewGroup() {
|
function createNewGroup() {
|
||||||
|
|
@ -146,7 +146,7 @@ function editCoastline(node = d3.event.target) {
|
||||||
toggleNewGroupInput();
|
toggleNewGroupInput();
|
||||||
document.getElementById("coastlineGroupName").value = "";
|
document.getElementById("coastlineGroupName").value = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeCoastlineGroup() {
|
function removeCoastlineGroup() {
|
||||||
const group = elSelected.node().parentNode.id;
|
const group = elSelected.node().parentNode.id;
|
||||||
if (["sea_island", "lake_island"].includes(group)) {
|
if (["sea_island", "lake_island"].includes(group)) {
|
||||||
|
|
@ -155,7 +155,7 @@ function editCoastline(node = d3.event.target) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const count = elSelected.node().parentNode.childElementCount;
|
const count = elSelected.node().parentNode.childElementCount;
|
||||||
alertMessage.innerHTML = `Are you sure you want to remove the group?
|
alertMessage.innerHTML = `Are you sure you want to remove the group?
|
||||||
All coastline elements of the group (${count}) will be moved under <i>sea_island</i> group`;
|
All coastline elements of the group (${count}) will be moved under <i>sea_island</i> group`;
|
||||||
$("#alert").dialog({resizable: false, title: "Remove coastline group", width:"26em",
|
$("#alert").dialog({resizable: false, title: "Remove coastline group", width:"26em",
|
||||||
buttons: {
|
buttons: {
|
||||||
|
|
|
||||||
|
|
@ -142,13 +142,13 @@ function editCultures() {
|
||||||
types.forEach(t => options += `<option ${type === t ? "selected" : ""} value="${t}">${t}</option>`);
|
types.forEach(t => options += `<option ${type === t ? "selected" : ""} value="${t}">${t}</option>`);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBaseOptions(base) {
|
function getBaseOptions(base) {
|
||||||
let options = "";
|
let options = "";
|
||||||
nameBases.forEach((n, i) => options += `<option ${base === i ? "selected" : ""} value="${i}">${n.name}</option>`);
|
nameBases.forEach((n, i) => options += `<option ${base === i ? "selected" : ""} value="${i}">${n.name}</option>`);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
function cultureHighlightOn(event) {
|
function cultureHighlightOn(event) {
|
||||||
const culture = +event.target.dataset.id;
|
const culture = +event.target.dataset.id;
|
||||||
const info = document.getElementById("cultureInfo");
|
const info = document.getElementById("cultureInfo");
|
||||||
|
|
@ -420,7 +420,7 @@ function editCultures() {
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#alert").dialog({
|
$("#alert").dialog({
|
||||||
title: "Cultures tree", width: fitContent(), resizable: false,
|
title: "Cultures tree", width: fitContent(), resizable: false,
|
||||||
position: {my: "left center", at: "left+10 center", of: "svg"}, buttons: {},
|
position: {my: "left center", at: "left+10 center", of: "svg"}, buttons: {},
|
||||||
close: () => {alertMessage.innerHTML = "";}
|
close: () => {alertMessage.innerHTML = "";}
|
||||||
});
|
});
|
||||||
|
|
@ -471,7 +471,7 @@ function editCultures() {
|
||||||
pack.burgs.forEach(b => b.culture = pack.cells.culture[b.cell]);
|
pack.burgs.forEach(b => b.culture = pack.cells.culture[b.cell]);
|
||||||
refreshCulturesEditor();
|
refreshCulturesEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
function enterCultureManualAssignent() {
|
function enterCultureManualAssignent() {
|
||||||
if (!layerIsOn("toggleCultures")) toggleCultures();
|
if (!layerIsOn("toggleCultures")) toggleCultures();
|
||||||
customization = 4;
|
customization = 4;
|
||||||
|
|
@ -521,7 +521,7 @@ function editCultures() {
|
||||||
if (!d3.event.dx && !d3.event.dy) return;
|
if (!d3.event.dx && !d3.event.dy) return;
|
||||||
const p = d3.mouse(this);
|
const p = d3.mouse(this);
|
||||||
moveCircle(p[0], p[1], r);
|
moveCircle(p[0], p[1], r);
|
||||||
|
|
||||||
const found = r > 5 ? findAll(p[0], p[1], r) : [findCell(p[0], p[1], r)];
|
const found = r > 5 ? findAll(p[0], p[1], r) : [findCell(p[0], p[1], r)];
|
||||||
const selection = found.filter(isLand);
|
const selection = found.filter(isLand);
|
||||||
if (selection) changeCultureForSelection(selection);
|
if (selection) changeCultureForSelection(selection);
|
||||||
|
|
@ -589,7 +589,7 @@ function editCultures() {
|
||||||
const selected = body.querySelector("div.selected");
|
const selected = body.querySelector("div.selected");
|
||||||
if (selected) selected.classList.remove("selected");
|
if (selected) selected.classList.remove("selected");
|
||||||
}
|
}
|
||||||
|
|
||||||
function enterAddCulturesMode() {
|
function enterAddCulturesMode() {
|
||||||
if (this.classList.contains("pressed")) {exitAddCultureMode(); return;};
|
if (this.classList.contains("pressed")) {exitAddCultureMode(); return;};
|
||||||
customization = 9;
|
customization = 9;
|
||||||
|
|
@ -624,7 +624,7 @@ function editCultures() {
|
||||||
function downloadCulturesData() {
|
function downloadCulturesData() {
|
||||||
const unit = areaUnit.value === "square" ? distanceUnitInput.value + "2" : areaUnit.value;
|
const unit = areaUnit.value === "square" ? distanceUnitInput.value + "2" : areaUnit.value;
|
||||||
let data = "Id,Culture,Color,Cells,Expansionism,Type,Area "+unit+",Population,Namesbase\n"; // headers
|
let data = "Id,Culture,Color,Cells,Expansionism,Type,Area "+unit+",Population,Namesbase\n"; // headers
|
||||||
|
|
||||||
body.querySelectorAll(":scope > div").forEach(function(el) {
|
body.querySelectorAll(":scope > div").forEach(function(el) {
|
||||||
data += el.dataset.id + ",";
|
data += el.dataset.id + ",";
|
||||||
data += el.dataset.name + ",";
|
data += el.dataset.name + ",";
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -7,7 +7,7 @@
|
||||||
var Voronoi = function Voronoi(delaunay, points, pointsN) {
|
var Voronoi = function Voronoi(delaunay, points, pointsN) {
|
||||||
const cells = {v: [], c: [], b: []}; // voronoi cells: v = cell vertices, c = adjacent cells, b = near-border cell
|
const cells = {v: [], c: [], b: []}; // voronoi cells: v = cell vertices, c = adjacent cells, b = near-border cell
|
||||||
const vertices = {p: [], v: [], c: []}; // cells vertices: p = vertex coordinates, v = neighboring vertices, c = adjacent cells
|
const vertices = {p: [], v: [], c: []}; // cells vertices: p = vertex coordinates, v = neighboring vertices, c = adjacent cells
|
||||||
|
|
||||||
for (let e=0; e < delaunay.triangles.length; e++) {
|
for (let e=0; e < delaunay.triangles.length; e++) {
|
||||||
|
|
||||||
const p = delaunay.triangles[nextHalfedge(e)];
|
const p = delaunay.triangles[nextHalfedge(e)];
|
||||||
|
|
@ -25,11 +25,11 @@
|
||||||
vertices.c[t] = pointsOfTriangle(t); // vertex: adjacent cells
|
vertices.c[t] = pointsOfTriangle(t); // vertex: adjacent cells
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function pointsOfTriangle(t) {
|
function pointsOfTriangle(t) {
|
||||||
return edgesOfTriangle(t).map(e => delaunay.triangles[e]);
|
return edgesOfTriangle(t).map(e => delaunay.triangles[e]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function trianglesAdjacentToTriangle(t) {
|
function trianglesAdjacentToTriangle(t) {
|
||||||
let triangles = [];
|
let triangles = [];
|
||||||
for (let e of edgesOfTriangle(t)) {
|
for (let e of edgesOfTriangle(t)) {
|
||||||
|
|
@ -53,11 +53,11 @@
|
||||||
let vertices = pointsOfTriangle(t).map(p => points[p]);
|
let vertices = pointsOfTriangle(t).map(p => points[p]);
|
||||||
return circumcenter(vertices[0], vertices[1], vertices[2]);
|
return circumcenter(vertices[0], vertices[1], vertices[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {cells, vertices}
|
return {cells, vertices}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function edgesOfTriangle(t) {return [3*t, 3*t+1, 3*t+2];}
|
function edgesOfTriangle(t) {return [3*t, 3*t+1, 3*t+2];}
|
||||||
|
|
||||||
function triangleOfEdge(e) {return Math.floor(e/3);}
|
function triangleOfEdge(e) {return Math.floor(e/3);}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue