diff --git a/index.css b/index.css
index c2e10c4a..9cdcbbe6 100644
--- a/index.css
+++ b/index.css
@@ -1411,11 +1411,16 @@ div.states > .statePopulation {
width: 3em;
}
+div.states:hover > .hiddenIcon {
+ visibility: visible !important;
+}
+
div.states .icon-pencil,
div.states .icon-trash-empty,
div.states .icon-eye,
div.states .icon-pin,
-div.states .icon-flag-empty {
+div.states .icon-flag-empty,
+div.states .icon-cw {
cursor: pointer;
}
diff --git a/index.html b/index.html
index 4bf6025b..cf279ba1 100644
--- a/index.html
+++ b/index.html
@@ -2708,6 +2708,7 @@
+
@@ -2806,13 +2807,13 @@
diff --git a/modules/burgs-and-states.js b/modules/burgs-and-states.js
index 45842e5d..6b8a814c 100644
--- a/modules/burgs-and-states.js
+++ b/modules/burgs-and-states.js
@@ -679,8 +679,8 @@ window.BurgsAndStates = (function () {
// calculate states data like area, population etc.
const collectStatistics = function () {
TIME && console.time("collectStatistics");
- const cells = pack.cells,
- states = pack.states;
+ const {cells, states} = pack;
+
states.forEach(s => {
if (s.removed) return;
s.cells = s.area = s.burgs = s.rural = s.urban = 0;
diff --git a/modules/names-generator.js b/modules/names-generator.js
index 444a4901..2de294a1 100644
--- a/modules/names-generator.js
+++ b/modules/names-generator.js
@@ -128,20 +128,14 @@ window.Names = (function () {
// generate name for culture
const getCulture = function (culture, min, max, dupl) {
- if (culture === undefined) {
- ERROR && console.error("Please define a culture");
- return;
- }
+ if (culture === undefined) return ERROR && console.error("Please define a culture");
const base = pack.cultures[culture].base;
return getBase(base, min, max, dupl);
};
// generate short name for culture
const getCultureShort = function (culture) {
- if (culture === undefined) {
- ERROR && console.error("Please define a culture");
- return;
- }
+ if (culture === undefined) return ERROR && console.error("Please define a culture");
return getBaseShort(pack.cultures[culture].base);
};
@@ -157,55 +151,75 @@ window.Names = (function () {
};
// generate state name based on capital or random name and culture-specific suffix
- // prettier-ignore
- const getState = function(name, culture, base) {
- if (name === undefined) {ERROR && console.error("Please define a base name"); return;}
- if (culture === undefined && base === undefined) {ERROR && console.error("Please define a culture"); return;}
+ const getState = function (name, culture, base) {
+ if (name === undefined) return ERROR && console.error("Please define a base name");
+ if (culture === undefined && base === undefined) return ERROR && console.error("Please define a culture");
if (base === undefined) base = pack.cultures[culture].base;
// exclude endings inappropriate for states name
if (name.includes(" ")) name = capitalize(name.replace(/ /g, "").toLowerCase()); // don't allow multiword state names
- if (name.length > 6 && name.slice(-4) === "berg") name = name.slice(0,-4); // remove -berg for any
- if (name.length > 5 && name.slice(-3) === "ton") name = name.slice(0,-3); // remove -ton for any
+ if (name.length > 6 && name.slice(-4) === "berg") name = name.slice(0, -4); // remove -berg for any
+ if (name.length > 5 && name.slice(-3) === "ton") name = name.slice(0, -3); // remove -ton for any
- if (base === 5 && ["sk", "ev", "ov"].includes(name.slice(-2))) name = name.slice(0,-2); // remove -sk/-ev/-ov for Ruthenian
- else if (base === 12) return vowel(name.slice(-1)) ? name : name + "u"; // Japanese ends on any vowel or -u
- else if (base === 18 && P(.4)) name = vowel(name.slice(0,1).toLowerCase()) ? "Al" + name.toLowerCase() : "Al " + name; // Arabic starts with -Al
+ if (base === 5 && ["sk", "ev", "ov"].includes(name.slice(-2))) name = name.slice(0, -2);
+ // remove -sk/-ev/-ov for Ruthenian
+ else if (base === 12) return vowel(name.slice(-1)) ? name : name + "u";
+ // Japanese ends on any vowel or -u
+ else if (base === 18 && P(0.4)) name = vowel(name.slice(0, 1).toLowerCase()) ? "Al" + name.toLowerCase() : "Al " + name; // Arabic starts with -Al
// no suffix for fantasy bases
if (base > 32 && base < 42) return name;
// define if suffix should be used
if (name.length > 3 && vowel(name.slice(-1))) {
- if (vowel(name.slice(-2,-1)) && P(.85)) name = name.slice(0,-2); // 85% for vv
- else if (P(.7)) name = name.slice(0,-1); // ~60% for cv
+ if (vowel(name.slice(-2, -1)) && P(0.85)) name = name.slice(0, -2);
+ // 85% for vv
+ else if (P(0.7)) name = name.slice(0, -1);
+ // ~60% for cv
else return name;
- } else if (P(.4)) return name; // 60% for cc and vc
+ } else if (P(0.4)) return name; // 60% for cc and vc
// define suffix
let suffix = "ia"; // standard suffix
- const rnd = Math.random(), l = name.length;
- if (base === 3 && rnd < .03 && l < 7) suffix = "terra"; // Italian
- else if (base === 4 && rnd < .03 && l < 7) suffix = "terra"; // Spanish
- else if (base === 13 && rnd < .03 && l < 7) suffix = "terra"; // Portuguese
- else if (base === 2 && rnd < .03 && l < 7) suffix = "terre"; // French
- else if (base === 0 && rnd < .5 && l < 7) suffix = "land"; // German
- else if (base === 1 && rnd < .4 && l < 7 ) suffix = "land"; // English
- else if (base === 6 && rnd < .3 && l < 7) suffix = "land"; // Nordic
- else if (base === 32 && rnd < .1 && l < 7) suffix = "land"; // generic Human
- else if (base === 7 && rnd < .1) suffix = "eia"; // Greek
- else if (base === 9 && rnd < .35) suffix = "maa"; // Finnic
- else if (base === 15 && rnd < .4 && l < 6) suffix = "orszag"; // Hungarian
- else if (base === 16) suffix = rnd < .6 ? "stan" : "ya"; // Turkish
- else if (base === 10) suffix = "guk"; // Korean
- else if (base === 11) suffix = " Guo"; // Chinese
- else if (base === 14) suffix = rnd < .5 && l < 6 ? "tlan" : "co"; // Nahuatl
- else if (base === 17 && rnd < .8) suffix = "a"; // Berber
- else if (base === 18 && rnd < .8) suffix = "a"; // Arabic
+ const rnd = Math.random(),
+ l = name.length;
+ if (base === 3 && rnd < 0.03 && l < 7) suffix = "terra";
+ // Italian
+ else if (base === 4 && rnd < 0.03 && l < 7) suffix = "terra";
+ // Spanish
+ else if (base === 13 && rnd < 0.03 && l < 7) suffix = "terra";
+ // Portuguese
+ else if (base === 2 && rnd < 0.03 && l < 7) suffix = "terre";
+ // French
+ else if (base === 0 && rnd < 0.5 && l < 7) suffix = "land";
+ // German
+ else if (base === 1 && rnd < 0.4 && l < 7) suffix = "land";
+ // English
+ else if (base === 6 && rnd < 0.3 && l < 7) suffix = "land";
+ // Nordic
+ else if (base === 32 && rnd < 0.1 && l < 7) suffix = "land";
+ // generic Human
+ else if (base === 7 && rnd < 0.1) suffix = "eia";
+ // Greek
+ else if (base === 9 && rnd < 0.35) suffix = "maa";
+ // Finnic
+ else if (base === 15 && rnd < 0.4 && l < 6) suffix = "orszag";
+ // Hungarian
+ else if (base === 16) suffix = rnd < 0.6 ? "stan" : "ya";
+ // Turkish
+ else if (base === 10) suffix = "guk";
+ // Korean
+ else if (base === 11) suffix = " Guo";
+ // Chinese
+ else if (base === 14) suffix = rnd < 0.5 && l < 6 ? "tlan" : "co";
+ // Nahuatl
+ else if (base === 17 && rnd < 0.8) suffix = "a";
+ // Berber
+ else if (base === 18 && rnd < 0.8) suffix = "a"; // Arabic
return validateSuffix(name, suffix);
- }
+ };
function validateSuffix(name, suffix) {
if (name.slice(-1 * suffix.length) === suffix) return name; // no suffix if name already ends with it
diff --git a/modules/ui/cultures-editor.js b/modules/ui/cultures-editor.js
index 75aa2223..74c73535 100644
--- a/modules/ui/cultures-editor.js
+++ b/modules/ui/cultures-editor.js
@@ -62,9 +62,9 @@ function editCultures() {
// add line for each culture
function culturesEditorAddLines() {
const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value;
- let lines = "",
- totalArea = 0,
- totalPopulation = 0;
+ let lines = "";
+ let totalArea = 0;
+ let totalPopulation = 0;
const emblemShapeGroup = document.getElementById("emblemShape").selectedOptions[0].parentNode.label;
const selectShape = emblemShapeGroup === "Diversiform";
@@ -84,7 +84,8 @@ function editCultures() {
lines += `
-
+
+
${c.cells}
@@ -96,19 +97,28 @@ function editCultures() {
${si(population)}
- ${selectShape ? `
` : ""}
+ ${
+ selectShape
+ ? `
`
+ : ""
+ }
`;
continue;
}
lines += `
-
+
+
${c.cells}
-
+
${si(area) + unit}
@@ -116,7 +126,11 @@ function editCultures() {
${si(population)}
- ${selectShape ? `
` : ""}
+ ${
+ selectShape
+ ? `
`
+ : ""
+ }
`;
}
@@ -136,6 +150,7 @@ function editCultures() {
body.querySelectorAll("div.states").forEach(el => el.addEventListener("click", selectCultureOnLineClick));
body.querySelectorAll("rect.fillRect").forEach(el => el.addEventListener("click", cultureChangeColor));
body.querySelectorAll("div > input.cultureName").forEach(el => el.addEventListener("input", cultureChangeName));
+ body.querySelectorAll("div > span.icon-cw").forEach(el => el.addEventListener("click", cultureRegenerateName));
body.querySelectorAll("div > input.statePower").forEach(el => el.addEventListener("input", cultureChangeExpansionism));
body.querySelectorAll("div > select.cultureType").forEach(el => el.addEventListener("change", cultureChangeType));
body.querySelectorAll("div > select.cultureBase").forEach(el => el.addEventListener("change", cultureChangeBase));
@@ -258,6 +273,13 @@ function editCultures() {
);
}
+ function cultureRegenerateName() {
+ const culture = +this.parentNode.dataset.id;
+ const name = Names.getCultureShort(culture);
+ this.parentNode.querySelector("input.cultureName").value = name;
+ pack.cultures[culture].name = name;
+ }
+
function cultureChangeExpansionism() {
const culture = +this.parentNode.dataset.id;
this.parentNode.dataset.expansionism = this.value;
@@ -526,7 +548,13 @@ function editCultures() {
// prepare svg
alertMessage.innerHTML = "
";
- const svg = d3.select("#alertMessage").insert("svg", "#cultureInfo").attr("id", "hierarchy").attr("width", width).attr("height", height).style("text-anchor", "middle");
+ const svg = d3
+ .select("#alertMessage")
+ .insert("svg", "#cultureInfo")
+ .attr("id", "hierarchy")
+ .attr("width", width)
+ .attr("height", height)
+ .style("text-anchor", "middle");
const graph = svg.append("g").attr("transform", `translate(10, -45)`);
const links = graph.append("g").attr("fill", "none").attr("stroke", "#aaaaaa");
const nodes = graph.append("g");
@@ -540,7 +568,24 @@ function editCultures() {
.enter()
.append("path")
.attr("d", d => {
- return "M" + d.source.x + "," + d.source.y + "C" + d.source.x + "," + (d.source.y * 3 + d.target.y) / 4 + " " + d.target.x + "," + (d.source.y * 2 + d.target.y) / 3 + " " + d.target.x + "," + d.target.y;
+ return (
+ "M" +
+ d.source.x +
+ "," +
+ d.source.y +
+ "C" +
+ d.source.x +
+ "," +
+ (d.source.y * 3 + d.target.y) / 4 +
+ " " +
+ d.target.x +
+ "," +
+ (d.source.y * 2 + d.target.y) / 3 +
+ " " +
+ d.target.x +
+ "," +
+ d.target.y
+ );
});
const node = nodes
@@ -661,7 +706,11 @@ function editCultures() {
$("#culturesEditor").dialog({position: {my: "right top", at: "right-10 top+10", of: "svg"}});
tip("Click on culture to select, drag the circle to change culture", true);
- viewbox.style("cursor", "crosshair").on("click", selectCultureOnMapClick).call(d3.drag().on("start", dragCultureBrush)).on("touchmove mousemove", moveCultureBrush);
+ viewbox
+ .style("cursor", "crosshair")
+ .on("click", selectCultureOnMapClick)
+ .call(d3.drag().on("start", dragCultureBrush))
+ .on("touchmove mousemove", moveCultureBrush);
body.querySelector("div").classList.add("selected");
}
@@ -712,7 +761,14 @@ function editCultures() {
// change of append new element
if (exists.size()) exists.attr("data-culture", cultureNew).attr("fill", color).attr("stroke", color);
- else temp.append("polygon").attr("data-cell", i).attr("data-culture", cultureNew).attr("points", getPackPolygon(i)).attr("fill", color).attr("stroke", color);
+ else
+ temp
+ .append("polygon")
+ .attr("data-cell", i)
+ .attr("data-culture", cultureNew)
+ .attr("points", getPackPolygon(i))
+ .attr("fill", color)
+ .attr("stroke", color);
});
}
diff --git a/modules/ui/provinces-editor.js b/modules/ui/provinces-editor.js
index 7987a56b..84eca9b0 100644
--- a/modules/ui/provinces-editor.js
+++ b/modules/ui/provinces-editor.js
@@ -34,6 +34,7 @@ function editProvinces() {
document.getElementById("provincesManually").addEventListener("click", enterProvincesManualAssignent);
document.getElementById("provincesManuallyApply").addEventListener("click", applyProvincesManualAssignent);
document.getElementById("provincesManuallyCancel").addEventListener("click", () => exitProvincesManualAssignment());
+ document.getElementById("provincesRelease").addEventListener("click", triggerProvincesRelease);
document.getElementById("provincesAdd").addEventListener("click", enterAddProvinceMode);
document.getElementById("provincesRecolor").addEventListener("click", recolorProvinces);
@@ -129,19 +130,27 @@ function editProvinces() {
const separable = p.burg && p.burg !== pack.states[p.state].capital;
const focused = defs.select("#fog #focusProvince" + p.i).size();
COArenderer.trigger("provinceCOA" + p.i, p.coa);
- lines += `
-
+ lines += `
`;
@@ -222,74 +231,64 @@ function editProvinces() {
function capitalZoomIn(p) {
const capital = pack.provinces[p].burg;
const l = burgLabels.select("[data-id='" + capital + "']");
- const x = +l.attr("x"),
- y = +l.attr("y");
+ const x = +l.attr("x");
+ const y = +l.attr("y");
zoomTo(x, y, 8, 2000);
}
function triggerIndependencePromps(p) {
- alertMessage.innerHTML = "Are you sure you want to declare province independence?
It will turn province into a new state";
- $("#alert").dialog({
- resizable: false,
+ confirmationDialog({
title: "Declare independence",
- buttons: {
- Declare: function () {
- declareProvinceIndependence(p);
- $(this).dialog("close");
- },
- Cancel: function () {
- $(this).dialog("close");
- }
+ message: "Are you sure you want to declare province independence?
It will turn province into a new state",
+ confirm: "Declare",
+ onConfirm: () => {
+ const [oldStateId, newStateId] = declareProvinceIndependence(p);
+ updateStatesPostRelease([oldStateId], [newStateId]);
}
});
}
- function declareProvinceIndependence(p) {
- const states = pack.states,
- provinces = pack.provinces,
- cells = pack.cells;
- if (provinces[p].burgs.some(b => pack.burgs[b].capital)) {
- tip("Cannot declare independence of a province having capital burg. Please change capital first", false, "error");
- return;
- }
+ function declareProvinceIndependence(provinceId) {
+ const {states, provinces, cells, burgs} = pack;
+ const province = provinces[provinceId];
+ const {name, burg: burgId, burgs: provinceBurgs} = province;
- const oldState = pack.provinces[p].state;
- const newState = pack.states.length;
+ if (provinceBurgs.some(b => burgs[b].capital))
+ return tip("Cannot declare independence of a province having capital burg. Please change capital first", false, "error");
+ if (!burgId) return tip("Cannot declare independence of a province without burg", false, "error");
+
+ const oldStateId = province.state;
+ const newStateId = states.length;
// turn province burg into a capital
- const burg = provinces[p].burg;
- if (!burg) return;
- pack.burgs[burg].capital = 1;
- moveBurgToGroup(burg, "cities");
+ burgs[burgId].capital = 1;
+ moveBurgToGroup(burgId, "cities");
// move all burgs to a new state
- provinces[p].burgs.forEach(b => (pack.burgs[b].state = newState));
+ province.burgs.forEach(b => (burgs[b].state = newStateId));
// difine new state attributes
- const center = pack.burgs[burg].cell;
- const culture = pack.burgs[burg].culture;
- const name = provinces[p].name;
+ const {cell: center, culture} = burgs[burgId];
const color = getRandomColor();
-
- const coa = provinces[p].coa;
- const coaEl = document.getElementById("provinceCOA" + p);
- if (coaEl) coaEl.id = "stateCOA" + newState;
- emblems.select(`#provinceEmblems > use[data-i='${p}']`).remove();
+ const coa = province.coa;
+ const coaEl = document.getElementById("provinceCOA" + provinceId);
+ if (coaEl) coaEl.id = "stateCOA" + newStateId;
+ emblems.select(`#provinceEmblems > use[data-i='${provinceId}']`).remove();
// update cells
cells.i
- .filter(i => cells.province[i] === p)
+ .filter(i => cells.province[i] === provinceId)
.forEach(i => {
cells.province[i] = 0;
- cells.state[i] = newState;
+ cells.state[i] = newStateId;
});
// update diplomacy and reverse relations
const diplomacy = states.map(s => {
if (!s.i || s.removed) return "x";
- let relations = states[oldState].diplomacy[s.i]; // relations between Nth state and old overlord
- if (s.i === oldState) relations = "Enemy";
- // new state is Enemy to its old overlord
+ let relations = states[oldStateId].diplomacy[s.i]; // relations between Nth state and old overlord
+ // new state is Enemy to its old owner
+ if (s.i === oldStateId) relations = "Enemy";
else if (relations === "Ally") relations = "Suspicion";
else if (relations === "Friendly") relations = "Suspicion";
else if (relations === "Suspicion") relations = "Neutral";
@@ -301,28 +300,51 @@ function editProvinces() {
return relations;
});
diplomacy.push("x");
- states[0].diplomacy.push([`Independance declaration`, `${name} declared its independance from ${states[oldState].name}`]);
+ states[0].diplomacy.push([`Independance declaration`, `${name} declared its independance from ${states[oldStateId].name}`]);
// create new state
- states.push({i: newState, name, diplomacy, provinces: [], color, expansionism: 0.5, capital: burg, type: "Generic", center, culture, military: [], alert: 1, coa});
- BurgsAndStates.collectStatistics();
- BurgsAndStates.defineStateForms([newState]);
-
- if (layerIsOn("toggleProvinces")) toggleProvinces();
- if (!layerIsOn("toggleStates")) toggleStates();
- else drawStates();
- if (!layerIsOn("toggleBorders")) toggleBorders();
- else drawBorders();
- BurgsAndStates.drawStateLabels([newState, oldState]);
+ states.push({
+ i: newStateId,
+ name,
+ diplomacy,
+ provinces: [],
+ color,
+ expansionism: 0.5,
+ capital: burgId,
+ type: "Generic",
+ center,
+ culture,
+ military: [],
+ alert: 1,
+ coa
+ });
// remove old province
- unfog("focusProvince" + p);
- if (states[oldState].provinces.includes(p)) states[oldState].provinces.splice(states[oldState].provinces.indexOf(p), 1);
- provinces[p] = {i: p, removed: true};
+ states[oldStateId].provinces = states[oldStateId].provinces.filter(p => p !== provinceId);
+ provinces[provinceId] = {i: provinceId, removed: true};
- // draw emblem
- COArenderer.add("state", newState, coa, pack.states[newState].pole[0], pack.states[newState].pole[1]);
+ return [oldStateId, newStateId];
+ }
+ function updateStatesPostRelease(oldStates, newStates) {
+ const allStates = unique([...oldStates, ...newStates]);
+
+ layerIsOn("toggleProvinces") && toggleProvinces();
+ layerIsOn("toggleStates") ? drawStates() : toggleStates();
+ layerIsOn("toggleBorders") ? drawBorders() : toggleBorders();
+
+ BurgsAndStates.collectStatistics();
+ BurgsAndStates.defineStateForms(newStates);
+ BurgsAndStates.drawStateLabels(allStates);
+
+ // redraw emblems
+ allStates.forEach(stateId => {
+ emblems.select(`#stateEmblems > use[data-i='${stateId}']`)?.remove();
+ const {coa, pole} = pack.states[stateId];
+ COArenderer.add("state", stateId, coa, ...pole);
+ });
+
+ unfog();
closeDialogs();
editStates();
}
@@ -541,7 +563,17 @@ function editProvinces() {
const provinces = pack.provinces
.filter(p => p.i && !p.removed)
.map(p => {
- return {id: p.i + states.length - 1, i: p.i, state: p.state, color: p.color, name: p.name, fullName: p.fullName, area: p.area, urban: p.urban, rural: p.rural};
+ return {
+ id: p.i + states.length - 1,
+ i: p.i,
+ state: p.state,
+ color: p.color,
+ name: p.name,
+ fullName: p.fullName,
+ area: p.area,
+ urban: p.urban,
+ rural: p.rural
+ };
});
const data = states.concat(provinces);
const root = d3
@@ -564,7 +596,13 @@ function editProvinces() {
`;
alertMessage.innerHTML += `
`;
- const svg = d3.select("#alertMessage").insert("svg", "#provinceInfo").attr("id", "provincesTree").attr("width", width).attr("height", height).attr("font-size", "10px");
+ const svg = d3
+ .select("#alertMessage")
+ .insert("svg", "#provinceInfo")
+ .attr("id", "provincesTree")
+ .attr("width", width)
+ .attr("height", height)
+ .attr("font-size", "10px");
const graph = svg.append("g").attr("transform", `translate(10, 0)`);
document.getElementById("provincesTreeType").addEventListener("change", updateChart);
@@ -589,7 +627,14 @@ function editProvinces() {
const rural = rn(d.data.rural * populationRate);
const urban = rn(d.data.urban * populationRate * urbanization);
- const value = provincesTreeType.value === "area" ? "Area: " + area : provincesTreeType.value === "rural" ? "Rural population: " + si(rural) : provincesTreeType.value === "urban" ? "Urban population: " + si(urban) : "Population: " + si(rural + urban);
+ const value =
+ provincesTreeType.value === "area"
+ ? "Area: " + area
+ : provincesTreeType.value === "rural"
+ ? "Rural population: " + si(rural)
+ : provincesTreeType.value === "urban"
+ ? "Urban population: " + si(urban)
+ : "Population: " + si(rural + urban);
provinceInfo.innerHTML = `${name}. ${state}. ${value}`;
provinceHighlightOn(ev);
@@ -637,7 +682,8 @@ function editProvinces() {
}
function updateChart() {
- const value = this.value === "area" ? d => d.area : this.value === "rural" ? d => d.rural : this.value === "urban" ? d => d.urban : d => d.rural + d.urban;
+ const value =
+ this.value === "area" ? d => d.area : this.value === "rural" ? d => d.rural : this.value === "urban" ? d => d.urban : d => d.rural + d.urban;
root.sum(value);
node.data(treeLayout(root).leaves());
@@ -681,6 +727,34 @@ function editProvinces() {
provs.selectAll("text").call(d3.drag().on("drag", dragLabel)).classed("draggable", true);
}
+ function triggerProvincesRelease() {
+ confirmationDialog({
+ title: "Release provinces",
+ message: `Are you sure you want to release all provinces?
+ It will turn all separable provinces into independent states.
+ Capital province and provinces without any burgs will state as they are`,
+ confirm: "Release",
+ onConfirm: () => {
+ const oldStateIds = [];
+ const newStateIds = [];
+
+ body.querySelectorAll(":scope > div").forEach(el => {
+ const provinceId = +el.dataset.id;
+ const province = pack.provinces[provinceId];
+ if (!province.burg) return;
+ if (province.burg === pack.states[province.state].capital) return;
+ if (province.burgs.some(burgId => pack.burgs[burgId].capital)) return;
+
+ const [oldStateId, newStateId] = declareProvinceIndependence(provinceId);
+ oldStateIds.push(oldStateId);
+ newStateIds.push(newStateId);
+ });
+
+ updateStatesPostRelease(unique(oldStateIds), newStateIds);
+ }
+ });
+ }
+
function enterProvincesManualAssignent() {
if (!layerIsOn("toggleProvinces")) toggleProvinces();
if (!layerIsOn("toggleBorders")) toggleBorders();
@@ -783,7 +857,13 @@ function editProvinces() {
if (pack.cells.province[i] === provinceNew) exists.remove();
else exists.attr("data-province", provinceNew).attr("fill", fill);
} else {
- temp.append("polygon").attr("points", getPackPolygon(i)).attr("data-cell", i).attr("data-province", provinceNew).attr("fill", fill).attr("stroke", "#555");
+ temp
+ .append("polygon")
+ .attr("points", getPackPolygon(i))
+ .attr("data-cell", i)
+ .attr("data-province", provinceNew)
+ .attr("fill", fill)
+ .attr("stroke", "#555");
}
});
}
@@ -839,10 +919,8 @@ function editProvinces() {
}
function enterAddProvinceMode() {
- if (this.classList.contains("pressed")) {
- exitAddProvinceMode();
- return;
- }
+ if (this.classList.contains("pressed")) return exitAddProvinceMode();
+
customization = 12;
this.classList.add("pressed");
tip("Click on the map to place a new province center", true);
@@ -851,24 +929,17 @@ function editProvinces() {
}
function addProvince() {
- const cells = pack.cells,
- provinces = pack.provinces;
+ const {cells, provinces} = pack;
const point = d3.mouse(this);
const center = findCell(point[0], point[1]);
- if (cells.h[center] < 20) {
- tip("You cannot place province into the water. Please click on a land cell", false, "error");
- return;
- }
+ if (cells.h[center] < 20) return tip("You cannot place province into the water. Please click on a land cell", false, "error");
+
const oldProvince = cells.province[center];
- if (oldProvince && provinces[oldProvince].center === center) {
- tip("The cell is already a center of a different province. Select other cell", false, "error");
- return;
- }
+ if (oldProvince && provinces[oldProvince].center === center)
+ return tip("The cell is already a center of a different province. Select other cell", false, "error");
+
const state = cells.state[center];
- if (!state) {
- tip("You cannot create a province in neutral lands. Please assign this land to a state first", false, "error");
- return;
- }
+ if (!state) return tip("You cannot create a province in neutral lands. Please assign this land to a state first", false, "error");
if (d3.event.shiftKey === false) exitAddProvinceMode();
@@ -879,8 +950,8 @@ function editProvinces() {
const name = burg ? pack.burgs[burg].name : Names.getState(Names.getCultureShort(c), c);
const formName = oldProvince ? provinces[oldProvince].formName : "Province";
const fullName = name + " " + formName;
- const stateColor = pack.states[state].color,
- rndColor = getRandomColor();
+ const stateColor = pack.states[state].color;
+ const rndColor = getRandomColor();
const color = stateColor[0] === "#" ? d3.color(d3.interpolate(stateColor, rndColor)(0.2)).hex() : rndColor;
// generate emblem
diff --git a/modules/ui/states-editor.js b/modules/ui/states-editor.js
index cada04ae..bf75010d 100644
--- a/modules/ui/states-editor.js
+++ b/modules/ui/states-editor.js
@@ -514,6 +514,7 @@ function editStates() {
pack.cells.province.forEach((pr, i) => {
if (pr === p) pack.cells.province[i] = 0;
});
+
const coaId = "provinceCOA" + p;
if (document.getElementById(coaId)) document.getElementById(coaId).remove();
emblems.select(`#provinceEmblems > use[data-i='${p}']`).remove();
@@ -901,7 +902,7 @@ function editStates() {
states[newOwnerId].provinces.push(provinceId);
} else {
// new owner is neutral => remove province
- provinces[provinceId] = {removed: true};
+ provinces[provinceId] = {i: provinceId, removed: true};
provinceCells.forEach(i => {
cells.province[i] = 0;
});
@@ -922,7 +923,7 @@ function editStates() {
// province center is captured by neutrals => remove state
if (!stateId) {
- provinces[provinceId] = {removed: true};
+ provinces[provinceId] = {i: provinceId, removed: true};
stateProvinceCells.forEach(i => {
cells.province[i] = 0;
});
diff --git a/utils/arrayUtils.js b/utils/arrayUtils.js
index c9a0d074..854800ce 100644
--- a/utils/arrayUtils.js
+++ b/utils/arrayUtils.js
@@ -11,3 +11,7 @@ function common(a, b) {
const setB = new Set(b);
return [...new Set(a)].filter(a => setB.has(a));
}
+
+function unique(array) {
+ return [...new Set(array)];
+}