refactor(burgs): centralize burg management logic in Burgs module

Moved burg-related functions like `removeBurg`, `changeGroup`, and `toggleCapital` into the Burgs module to improve code organization and maintainability. Updated all references to these functions across the codebase. This change reduces duplication and ensures consistent behavior for burg management operations.
This commit is contained in:
Azgaar 2025-04-17 01:03:14 +02:00
parent a5939be6e2
commit fd9e010153
12 changed files with 213 additions and 215 deletions

View file

@ -314,11 +314,18 @@ window.Burgs = (() => {
function defineGroup(burg, populations) { function defineGroup(burg, populations) {
if (burg.lock) { if (burg.lock) {
// locked bugrgs: don't change group if it still exists // locked burgs: don't change group if it still exists
const group = options.burgs.groups.find(g => g.name === burg.group); const group = options.burgs.groups.find(g => g.name === burg.group);
if (group) return; if (group) return;
} }
const defaultGroup = options.burgs.groups.find(g => g.isDefault);
if (!defaultGroup) {
ERROR & console.error("No default group defined");
return;
}
burg.group = defaultGroup.name;
for (const group of options.burgs.groups) { for (const group of options.burgs.groups) {
if (!group.active) continue; if (!group.active) continue;
@ -348,8 +355,7 @@ window.Burgs = (() => {
if (!isFit) continue; if (!isFit) continue;
} }
// apply fitting or default group burg.group = group.name; // apply fitting group
burg.group = group.name;
return; return;
} }
} }
@ -404,7 +410,7 @@ window.Burgs = (() => {
const temple = +burg.temple; const temple = +burg.temple;
const shantytown = +burg.shanty; const shantytown = +burg.shanty;
const style = "bw"; const style = "natural";
const url = new URL("https://watabou.github.io/city-generator/"); const url = new URL("https://watabou.github.io/city-generator/");
url.search = new URLSearchParams({ url.search = new URLSearchParams({
@ -476,7 +482,7 @@ window.Burgs = (() => {
const style = (() => { const style = (() => {
if ([1, 2].includes(biome)) return "sand"; if ([1, 2].includes(biome)) return "sand";
if (temp <= 5 || [9, 10, 11].includes(biome)) return "snow"; if (temp <= 5 || [9, 10, 11].includes(biome)) return "snow";
return "minimal"; return "default";
})(); })();
const url = new URL("https://watabou.github.io/village-generator/"); const url = new URL("https://watabou.github.io/village-generator/");
@ -556,5 +562,38 @@ window.Burgs = (() => {
return burgId; return burgId;
} }
return {generate, getDefaultGroups, specify, defineGroup, getPreview, getType, add}; function changeGroup(burg, group) {
if (group) {
burg.group = group;
} else {
const validBurgs = pack.burgs.filter(b => b.i && !b.removed);
const populations = validBurgs.map(b => b.population).sort((a, b) => a - b);
defineGroup(burg, populations);
}
drawBurgIcon(burg);
drawBurgLabel(burg);
}
function remove(burgId) {
const burg = pack.burgs[burgId];
if (!burg) return tip(`Burg ${burgId} not found`, false, "error");
pack.cells.burg[burg.cell] = 0;
burg.removed = true;
const noteId = notes.findIndex(note => note.id === `burg${burgId}`);
if (noteId !== -1) notes.splice(noteId, 1);
if (burg.coa) {
byId("burgCOA" + burgId)?.remove();
emblems.select(`#burgEmblems > use[data-i='${burgId}']`).remove();
delete burg.coa;
}
removeBurgIcon(burg.i);
removeBurgLabel(burg.i);
}
return {generate, getDefaultGroups, specify, defineGroup, getPreview, getType, add, changeGroup, remove};
})(); })();

View file

@ -603,7 +603,7 @@ function stateRemove(stateId) {
burg.state = 0; burg.state = 0;
if (burg.capital) { if (burg.capital) {
burg.capital = 0; burg.capital = 0;
moveBurgToGroup(burg.i, "town"); Burgs.changeGroup(burg);
} }
} }
}); });
@ -1181,30 +1181,30 @@ function addState() {
if (cells.h[center] < 20) if (cells.h[center] < 20)
return tip("You cannot place state into the water. Please click on a land cell", false, "error"); return tip("You cannot place state into the water. Please click on a land cell", false, "error");
let burg = cells.burg[center]; let burgId = cells.burg[center];
if (burg && burgs[burg].capital) if (burgId && burgs[burgId].capital)
return tip("Existing capital cannot be selected as a new state capital! Select other cell", false, "error"); return tip("Existing capital cannot be selected as a new state capital! Select other cell", false, "error");
if (!burg) burg = Burgs.add(point); if (!burgId) burgId = Burgs.add(point);
const oldState = cells.state[center]; const oldState = cells.state[center];
const newState = states.length; const newState = states.length;
// turn burg into a capital // turn burg into a capital
burgs[burg].capital = 1; burgs[burgId].capital = 1;
burgs[burg].state = newState; burgs[burgId].state = newState;
moveBurgToGroup(burg, "city"); Burgs.changeGroup(burgs[burgId]);
if (d3.event.shiftKey === false) exitAddStateMode(); if (d3.event.shiftKey === false) exitAddStateMode();
const culture = cells.culture[center]; const culture = cells.culture[center];
const basename = center % 5 === 0 ? burgs[burg].name : Names.getCulture(culture); const basename = center % 5 === 0 ? burgs[burgId].name : Names.getCulture(culture);
const name = Names.getState(basename, culture); const name = Names.getState(basename, culture);
const color = getRandomColor(); const color = getRandomColor();
// generate emblem // generate emblem
const cultureType = pack.cultures[culture].type; const cultureType = pack.cultures[culture].type;
const coa = COA.generate(burgs[burg].coa, 0.4, null, cultureType); const coa = COA.generate(burgs[burgId].coa, 0.4, null, cultureType);
coa.shield = COA.getShield(culture, null); coa.shield = COA.getShield(culture, null);
// update diplomacy and reverse relations // update diplomacy and reverse relations
@ -1244,7 +1244,7 @@ function addState() {
provinces: [], provinces: [],
color, color,
expansionism: 0.5, expansionism: 0.5,
capital: burg, capital: burgId,
type: "Generic", type: "Generic",
center, center,
culture, culture,
@ -1380,19 +1380,19 @@ function openStateMergeDialog() {
}); });
// reassing burgs // reassing burgs
pack.burgs.forEach(b => { pack.burgs.forEach(burg => {
if (statesToMerge.includes(b.state)) { if (statesToMerge.includes(burg.state)) {
if (b.capital) { if (burg.capital) {
moveBurgToGroup(b.i, "town"); burg.capital = 0;
b.capital = 0; Burgs.changeGroup(burg);
} }
b.state = rulingStateId; burg.state = rulingStateId;
} }
}); });
// reassign provinces // reassign provinces
pack.provinces.forEach((p, i) => { pack.provinces.forEach(province => {
if (statesToMerge.includes(p.state)) p.state = rulingStateId; if (statesToMerge.includes(province.state)) province.state = rulingStateId;
}); });
// reassing cells // reassing cells

View file

@ -618,14 +618,12 @@ async function parseLoadedData(data, mapVersion) {
if (!state.i && capitalBurgs.length) { if (!state.i && capitalBurgs.length) {
ERROR && ERROR &&
console.error( console.error(
`[Data integrity] Neutral burgs (${capitalBurgs `[Data integrity] Neutral burgs (${capitalBurgs.map(b => b.i).join(", ")}) marked as capitals`
.map(b => b.i)
.join(", ")}) marked as capitals. Moving them to town`
); );
capitalBurgs.forEach(burg => { capitalBurgs.forEach(burg => {
burg.capital = 0; burg.capital = 0;
moveBurgToGroup(burg.i, "town"); Burgs.changeGroup(burg);
}); });
return; return;
@ -634,23 +632,23 @@ async function parseLoadedData(data, mapVersion) {
if (capitalBurgs.length > 1) { if (capitalBurgs.length > 1) {
const message = `[Data integrity] State ${state.i} has multiple capitals (${capitalBurgs const message = `[Data integrity] State ${state.i} has multiple capitals (${capitalBurgs
.map(b => b.i) .map(b => b.i)
.join(", ")}) assigned. Keeping the first as capital and moving others to town`; .join(", ")}) assigned. Keeping the first as capital and moving others`;
ERROR && console.error(message); ERROR && console.error(message);
capitalBurgs.forEach((burg, i) => { capitalBurgs.forEach((burg, i) => {
if (!i) return; if (!i) return;
burg.capital = 0; burg.capital = 0;
moveBurgToGroup(burg.i, "town"); Burgs.changeGroup(burg);
}); });
return; return;
} }
if (state.i && stateBurgs.length && !capitalBurgs.length) { if (state.i && stateBurgs.length && !capitalBurgs.length) {
ERROR && ERROR && console.error(`[Data integrity] State ${state.i} has no capital. Making the first burg capital`);
console.error(`[Data integrity] State ${state.i} has no capital. Assigning the first burg as capital`); const capital = stateBurgs[0];
stateBurgs[0].capital = 1; capital.capital = 1;
moveBurgToGroup(stateBurgs[0].i, "city"); Burgs.changeGroup(capital);
} }
}); });

View file

@ -8,11 +8,11 @@ function drawBurgIcons() {
const burgsInGroup = pack.burgs.filter(b => b.group === name && !b.removed); const burgsInGroup = pack.burgs.filter(b => b.group === name && !b.removed);
if (!burgsInGroup.length) continue; if (!burgsInGroup.length) continue;
const burgGroup = document.querySelector("#burgIcons > g#" + name); const iconsGroup = document.querySelector("#burgIcons > g#" + name);
if (!burgGroup) continue; if (!iconsGroup) continue;
const icon = burgGroup.dataset.icon || "#icon-circle"; const icon = iconsGroup.dataset.icon || "#icon-circle";
burgGroup.innerHTML = burgsInGroup iconsGroup.innerHTML = burgsInGroup
.map(b => `<use id="burg${b.i}" data-id="${b.i}" href="${icon}" x="${b.x}" y="${b.y}"></use>`) .map(b => `<use id="burg${b.i}" data-id="${b.i}" href="${icon}" x="${b.x}" y="${b.y}"></use>`)
.join(""); .join("");
@ -31,10 +31,16 @@ function drawBurgIcons() {
} }
function drawBurgIcon(burg) { function drawBurgIcon(burg) {
removeBurgIcon(burg.i);
const iconGroup = burgIcons.select("#" + burg.group);
if (iconGroup.empty()) return;
const icon = iconGroup.attr("data-icon") || "#icon-circle";
burgIcons burgIcons
.select("#" + burg.group) .select("#" + burg.group)
.append("use") .append("use")
.attr("href", "#icon-circle") .attr("href", icon)
.attr("id", "burg" + burg.i) .attr("id", "burg" + burg.i)
.attr("data-id", burg.i) .attr("data-id", burg.i)
.attr("x", burg.x) .attr("x", burg.x)
@ -52,41 +58,49 @@ function drawBurgIcon(burg) {
} }
} }
function removeBurgIcon(burgId) {
const existingIcon = document.getElementById("burg" + burgId);
if (existingIcon) existingIcon.remove();
const existingAnchor = document.getElementById("anchor" + burgId);
if (existingAnchor) existingAnchor.remove();
}
function createIconGroups() { function createIconGroups() {
// save existing styles and remove all groups // save existing styles and remove all groups
const defaultIconStyle = style.burgIcons.town || Object.values(style.burgIcons)[0];
document.querySelectorAll("g#burgIcons > g").forEach(group => { document.querySelectorAll("g#burgIcons > g").forEach(group => {
const groupStyle = Object.keys(defaultIconStyle).reduce((acc, key) => { style.burgIcons[group.id] = Array.from(group.attributes).reduce((acc, attribute) => {
acc[key] = group.getAttribute(key); acc[attribute.name] = attribute.value;
return acc; return acc;
}, {}); }, {});
style.burgIcons[group.id] = groupStyle;
group.remove(); group.remove();
}); });
const defaultAnchorStyle = style.anchors.town || Object.values(style.anchors)[0];
document.querySelectorAll("g#anchors > g").forEach(group => { document.querySelectorAll("g#anchors > g").forEach(group => {
const groupStyle = Object.keys(defaultAnchorStyle).reduce((acc, key) => { style.anchors[group.id] = Array.from(group.attributes).reduce((acc, attribute) => {
acc[key] = group.getAttribute(key); acc[attribute.name] = attribute.value;
return acc; return acc;
}, {}); }, {});
style.anchors[group.id] = groupStyle;
group.remove(); group.remove();
}); });
// create groups for each burg group and apply stored or default style // create groups for each burg group and apply stored or default style
const defaultIconStyle = style.burgIcons.town || Object.values(style.burgIcons)[0];
const defaultAnchorStyle = style.anchors.town || Object.values(style.anchors)[0];
const sortedGroups = [...options.burgs.groups].sort((a, b) => a.order - b.order); const sortedGroups = [...options.burgs.groups].sort((a, b) => a.order - b.order);
for (const {name} of sortedGroups) { for (const {name} of sortedGroups) {
const burgGroup = burgIcons.append("g").attr("id", name); const burgGroup = burgIcons.append("g");
const iconStyles = style.burgIcons[name] || defaultIconStyle; const iconStyles = style.burgIcons[name] || defaultIconStyle;
Object.entries(iconStyles).forEach(([key, value]) => { Object.entries(iconStyles).forEach(([key, value]) => {
burgGroup.attr(key, value); burgGroup.attr(key, value);
}); });
burgGroup.attr("id", name);
const anchorGroup = anchors.append("g").attr("id", name); const anchorGroup = anchors.append("g");
const anchorStyles = style.anchors[name] || defaultAnchorStyle; const anchorStyles = style.anchors[name] || defaultAnchorStyle;
Object.entries(anchorStyles).forEach(([key, value]) => { Object.entries(anchorStyles).forEach(([key, value]) => {
anchorGroup.attr(key, value); anchorGroup.attr(key, value);
}); });
anchorGroup.attr("id", name);
} }
} }

View file

@ -33,11 +33,14 @@ function drawBurgLabels() {
} }
function drawBurgLabel(burg) { function drawBurgLabel(burg) {
const group = burgLabels.select("#" + burg.group); removeBurgLabel(burg.i);
const labelGroup = burgLabels.select("#" + burg.group);
if (labelGroup.empty()) return;
const dx = labelGroup.attr("data-dx") || 0; const dx = labelGroup.attr("data-dx") || 0;
const dy = labelGroup.attr("data-dy") || 0; const dy = labelGroup.attr("data-dy") || 0;
group labelGroup
.append("text") .append("text")
.attr("text-rendering", "optimizeSpeed") .attr("text-rendering", "optimizeSpeed")
.attr("id", "burgLabel" + burg.i) .attr("id", "burgLabel" + burg.i)
@ -49,26 +52,30 @@ function drawBurgLabel(burg) {
.text(burg.name); .text(burg.name);
} }
function createLabelGroups() { function removeBurgLabel(burgId) {
const defaultStyle = style.burgLabels.town || Object.values(style.burgLabels)[0]; const existingLabel = document.getElementById("burgLabel" + burgId);
if (existingLabel) existingLabel.remove();
}
function createLabelGroups() {
// save existing styles and remove all groups // save existing styles and remove all groups
document.querySelectorAll("g#burgLabels > g").forEach(group => { document.querySelectorAll("g#burgLabels > g").forEach(group => {
const groupStyle = Object.keys(defaultStyle).reduce((acc, key) => { style.burgLabels[group.id] = Array.from(group.attributes).reduce((acc, attribute) => {
acc[key] = group.getAttribute(key); acc[attribute.name] = attribute.value;
return acc; return acc;
}, {}); }, {});
style.burgLabels[group.id] = groupStyle;
group.remove(); group.remove();
}); });
// create groups for each burg group and apply stored or default style // create groups for each burg group and apply stored or default style
const defaultStyle = style.burgLabels.town || Object.values(style.burgLabels)[0];
const sortedGroups = [...options.burgs.groups].sort((a, b) => a.order - b.order); const sortedGroups = [...options.burgs.groups].sort((a, b) => a.order - b.order);
for (const {name} of sortedGroups) { for (const {name} of sortedGroups) {
const group = burgLabels.append("g").attr("id", name); const group = burgLabels.append("g");
const styles = style.burgLabels[name] || defaultStyle; const styles = style.burgLabels[name] || defaultStyle;
Object.entries(styles).forEach(([key, value]) => { Object.entries(styles).forEach(([key, value]) => {
group.attr(key, value); group.attr(key, value);
}); });
group.attr("id", name);
} }
} }

View file

@ -83,20 +83,13 @@ function editBurg(id) {
byId("burgElevation").innerHTML = getHeight(pack.cells.h[b.cell]); byId("burgElevation").innerHTML = getHeight(pack.cells.h[b.cell]);
// toggle features // toggle features
if (b.capital) byId("burgCapital").classList.remove("inactive"); byId("burgCapital").classList.toggle("inactive", !b.capital);
else byId("burgCapital").classList.add("inactive"); byId("burgPort").classList.toggle("inactive", !b.port);
if (b.port) byId("burgPort").classList.remove("inactive"); byId("burgCitadel").classList.toggle("inactive", !b.citadel);
else byId("burgPort").classList.add("inactive"); byId("burgWalls").classList.toggle("inactive", !b.walls);
if (b.citadel) byId("burgCitadel").classList.remove("inactive"); byId("burgPlaza").classList.toggle("inactive", !b.plaza);
else byId("burgCitadel").classList.add("inactive"); byId("burgTemple").classList.toggle("inactive", !b.temple);
if (b.walls) byId("burgWalls").classList.remove("inactive"); byId("burgShanty").classList.toggle("inactive", !b.shanty);
else byId("burgWalls").classList.add("inactive");
if (b.plaza) byId("burgPlaza").classList.remove("inactive");
else byId("burgPlaza").classList.add("inactive");
if (b.temple) byId("burgTemple").classList.remove("inactive");
else byId("burgTemple").classList.add("inactive");
if (b.shanty) byId("burgShanty").classList.remove("inactive");
else byId("burgShanty").classList.add("inactive");
updateBurgLockIcon(); updateBurgLockIcon();
@ -135,8 +128,8 @@ function editBurg(id) {
function changeGroup() { function changeGroup() {
const id = +elSelected.attr("data-id"); const id = +elSelected.attr("data-id");
pack.burgs[id].group = this.value; const burg = pack.burgs[id];
moveBurgToGroup(id, this.value); Burgs.changeGroup(burg, this.value);
} }
function changeType() { function changeType() {
@ -165,21 +158,68 @@ function editBurg(id) {
} }
function toggleFeature() { function toggleFeature() {
const id = +elSelected.attr("data-id"); const burgId = +elSelected.attr("data-id");
const burg = pack.burgs[id]; const burg = pack.burgs[burgId];
const feature = this.dataset.feature;
const turnOn = this.classList.contains("inactive");
if (feature === "port") togglePort(id);
else if (feature === "capital") toggleCapital(id);
else burg[feature] = +turnOn;
if (burg[feature]) this.classList.remove("inactive");
else if (!burg[feature]) this.classList.add("inactive");
if (burg.port) byId("burgEditAnchorStyle").style.display = "inline-block"; const feature = this.dataset.feature;
else byId("burgEditAnchorStyle").style.display = "none"; const value = Number(this.classList.contains("inactive"));
if (feature === "port") togglePort(burgId);
else if (feature === "capital") toggleCapital(burgId);
else burg[feature] = value;
this.classList.toggle("inactive", !burg[feature]);
byId("burgEditAnchorStyle").style.display = burg.port ? "inline-block" : "none";
updateBurgPreview(burg); updateBurgPreview(burg);
} }
function togglePort(burgId) {
const burg = pack.burgs[burgId];
if (burg.port) {
burg.port = 0;
const anchor = document.querySelector("#anchors [data-id='" + burgId + "']");
if (anchor) anchor.remove();
} else {
const haven = pack.cells.haven[burg.cell];
if (!haven) tip("Port haven is not found, system won't be able to make a searoute", false, "warn");
const portFeature = haven ? pack.cells.f[haven] : -1;
burg.port = portFeature;
anchors
.select("#" + burg.group)
.append("use")
.attr("href", "#icon-anchor")
.attr("id", "anchor" + burg.i)
.attr("data-id", burg.i)
.attr("x", burg.x)
.attr("y", burg.y);
}
}
function toggleCapital(burgId) {
const {burgs, states} = pack;
if (burgs[burgId].capital)
return tip("To change capital please assign a capital status to another burg of this state", false, "error");
const stateId = burgs[burgId].state;
if (!stateId) return tip("Neutral lands cannot have a capital", false, "error");
const oldCapitalId = states[stateId].capital;
states[stateId].capital = burgId;
states[stateId].center = burgs[burgId].cell;
const capital = burgs[burgId];
capital.capital = 1;
Burgs.changeGroup(capital);
const oldCapital = burgs[oldCapitalId];
oldCapital.capital = 0;
Burgs.changeGroup(oldCapital);
}
function toggleBurgLockButton() { function toggleBurgLockButton() {
const id = +elSelected.attr("data-id"); const id = +elSelected.attr("data-id");
const burg = pack.burgs[id]; const burg = pack.burgs[id];
@ -354,10 +394,11 @@ function editBurg(id) {
} }
function removeSelectedBurg() { function removeSelectedBurg() {
const id = +elSelected.attr("data-id"); const burgId = +elSelected.attr("data-id");
if (pack.burgs[id].capital) { const burg = pack.burgs[burgId];
alertMessage.innerHTML = /* html */ `You cannot remove the burg as it is a state capital.<br /><br />
You can change the capital using Burgs Editor (shift + T)`; if (burg.capital) {
alertMessage.innerHTML = /* html */ `You cannot remove the capital. You must change the state capital first`;
$("#alert").dialog({ $("#alert").dialog({
resizable: false, resizable: false,
title: "Remove burg", title: "Remove burg",
@ -373,7 +414,7 @@ function editBurg(id) {
message: "Are you sure you want to remove the burg? <br>This action cannot be reverted", message: "Are you sure you want to remove the burg? <br>This action cannot be reverted",
confirm: "Remove", confirm: "Remove",
onConfirm: () => { onConfirm: () => {
removeBurg(id); // see Editors module Burgs.remove(burgId);
$("#burgEditor").dialog("close"); $("#burgEditor").dialog("close");
} }
}); });

View file

@ -234,7 +234,7 @@ function editBurgGroups() {
if (lines.length < 2) return tip("At least one group should be defined", false, "error"); if (lines.length < 2) return tip("At least one group should be defined", false, "error");
confirmationDialog({ confirmationDialog({
title: this.dataset.tip, title: "Remove group",
message: message:
"Are you sure you want to remove the group? <br>This WON'T change the burgs unless the changes are applied", "Are you sure you want to remove the group? <br>This WON'T change the burgs unless the changes are applied",
confirm: "Remove", confirm: "Remove",

View file

@ -182,16 +182,16 @@ function overviewBurgs(settings = {stateId: null, cultureId: null}) {
} }
function triggerBurgRemove() { function triggerBurgRemove() {
const burg = +this.parentNode.dataset.id; const burgId = +this.parentNode.dataset.id;
if (pack.burgs[burg].capital) if (pack.burgs[burgId].capital)
return tip("You cannot remove the capital. Please change the capital first", false, "error"); return tip("You cannot remove the capital. Please change the state capital first", false, "error");
confirmationDialog({ confirmationDialog({
title: "Remove burg", title: "Remove burg",
message: "Are you sure you want to remove the burg? <br>This action cannot be reverted", message: "Are you sure you want to remove the burg? <br>This action cannot be reverted",
confirm: "Remove", confirm: "Remove",
onConfirm: () => { onConfirm: () => {
removeBurg(burg); Burgs.remove(burgId);
burgsOverviewAddLines(); burgsOverviewAddLines();
} }
}); });
@ -536,16 +536,14 @@ function overviewBurgs(settings = {stateId: null, cultureId: null}) {
title: `Remove ${number} burgs`, title: `Remove ${number} burgs`,
message: ` message: `
Are you sure you want to remove all <i>unlocked</i> burgs except for capitals? Are you sure you want to remove all <i>unlocked</i> burgs except for capitals?
<br><i>To remove a capital you have to remove a state first</i>`, <br><i>To remove a capital you have to remove its state first</i>`,
confirm: "Remove", confirm: "Remove",
onConfirm: removeAllBurgs onConfirm: () => {
}); pack.burgs.filter(b => b.i && !(b.capital || b.lock)).forEach(b => Burgs.remove(b.i));
}
function removeAllBurgs() {
pack.burgs.filter(b => b.i && !(b.capital || b.lock)).forEach(b => removeBurg(b.i));
burgsOverviewAddLines(); burgsOverviewAddLines();
} }
});
}
function toggleLockAll() { function toggleLockAll() {
const activeBurgs = pack.burgs.filter(b => b.i && !b.removed); const activeBurgs = pack.burgs.filter(b => b.i && !b.removed);

View file

@ -128,108 +128,6 @@ function applySorting(headers) {
.forEach(line => list.appendChild(line)); .forEach(line => list.appendChild(line));
} }
function moveBurgToGroup(id, g) {
const label = document.querySelector(`#burgLabels [data-id='${id}']`);
const icon = document.querySelector(`#burgIcons [data-id='${id}']`);
const anchor = document.querySelector(`#anchors [data-id='${id}']`);
if (!label || !icon) return tip("Cannot find label or icon for burg " + id, false, "error");
document.querySelector("#burgLabels > #" + g).appendChild(label);
document.querySelector("#burgIcons > #" + g).appendChild(icon);
if (anchor) document.querySelector("#anchors > #" + g).appendChild(anchor);
icon.setAttribute("href", icon.parentElement.dataset.icon);
const {dx, dy} = label.parentElement.dataset;
dx ? label.setAttribute("dx", dx + "em") : label.removeAttribute("dx");
dy ? label.setAttribute("dy", dy + "em") : label.removeAttribute("dy");
}
function moveAllBurgsToGroup(fromGroup, toGroup) {
const groupToMove = document.querySelector(`#burgIcons #${fromGroup}`);
const burgsToMove = Array.from(groupToMove.children).map(x => x.dataset.id);
addBurgsGroup(toGroup);
burgsToMove.forEach(x => moveBurgToGroup(x, toGroup));
}
function addBurgsGroup(group) {
if (document.querySelector(`#burgLabels > #${group}`)) return;
const labelCopy = document.querySelector("#burgLabels > #town").cloneNode(false);
const iconCopy = document.querySelector("#burgIcons > #town").cloneNode(false);
const anchorCopy = document.querySelector("#anchors > #town").cloneNode(false);
// FIXME: using the same id is against the spec!
document.querySelector("#burgLabels").appendChild(labelCopy).id = group;
document.querySelector("#burgIcons").appendChild(iconCopy).id = group;
document.querySelector("#anchors").appendChild(anchorCopy).id = group;
}
function removeBurg(id) {
document.querySelector("#burgLabels [data-id='" + id + "']")?.remove();
document.querySelector("#burgIcons [data-id='" + id + "']")?.remove();
document.querySelector("#anchors [data-id='" + id + "']")?.remove();
const cells = pack.cells;
const burg = pack.burgs[id];
burg.removed = true;
cells.burg[burg.cell] = 0;
const noteId = notes.findIndex(note => note.id === `burg${id}`);
if (noteId !== -1) notes.splice(noteId, 1);
if (burg.coa) {
const coaId = "burgCOA" + id;
if (byId(coaId)) byId(coaId).remove();
emblems.select(`#burgEmblems > use[data-i='${id}']`).remove();
delete burg.coa; // remove to save data
}
}
function toggleCapital(burgId) {
const {burgs, states} = pack;
if (burgs[burgId].capital)
return tip("To change capital please assign a capital status to another burg of this state", false, "error");
const stateId = burgs[burgId].state;
if (!stateId) return tip("Neutral lands cannot have a capital", false, "error");
const prevCapitalId = states[stateId].capital;
states[stateId].capital = burgId;
states[stateId].center = burgs[burgId].cell;
burgs[burgId].capital = 1;
burgs[prevCapitalId].capital = 0;
moveBurgToGroup(burgId, "city");
moveBurgToGroup(prevCapitalId, "town");
}
function togglePort(burg) {
const anchor = document.querySelector("#anchors [data-id='" + burg + "']");
if (anchor) anchor.remove();
const b = pack.burgs[burg];
if (b.port) {
b.port = 0;
return;
} // not a port anymore
const haven = pack.cells.haven[b.cell];
const port = haven ? pack.cells.f[haven] : -1;
if (!haven) tip("Port haven is not found, system won't be able to make a searoute", false, "warn");
b.port = port;
const g = b.capital ? "city" : "town";
const group = anchors.select("g#" + g);
const size = +group.attr("size");
group
.append("use")
.attr("xlink:href", "#icon-anchor")
.attr("data-id", burg)
.attr("x", rn(b.x - size * 0.47, 2))
.attr("y", rn(b.y - size * 0.47, 2))
.attr("width", size)
.attr("height", size);
}
// draw legend box // draw legend box
function drawLegend(name, data) { function drawLegend(name, data) {
legend.selectAll("*").remove(); // fully redraw every time legend.selectAll("*").remove(); // fully redraw every time

View file

@ -409,7 +409,7 @@ function editHeightmap(options) {
b.feature = pack.cells.f[b.cell]; b.feature = pack.cells.f[b.cell];
pack.cells.burg[b.cell] = b.i; pack.cells.burg[b.cell] = b.i;
if (!b.capital && pack.cells.h[b.cell] < 20) removeBurg(b.i); if (!b.capital && pack.cells.h[b.cell] < 20) Burgs.remove(b.i);
if (b.capital) pack.states[b.state].center = b.cell; if (b.capital) pack.states[b.state].center = b.cell;
} }

View file

@ -296,8 +296,9 @@ function editProvinces() {
const newStateId = states.length; const newStateId = states.length;
// turn province burg into a capital // turn province burg into a capital
burgs[burgId].capital = 1; const capital = burgs[burgId];
moveBurgToGroup(burgId, "city"); capital.capital = 1;
Burgs.changeGroup(capital);
// move all burgs to a new state // move all burgs to a new state
province.burgs.forEach(b => (burgs[b].state = newStateId)); province.burgs.forEach(b => (burgs[b].state = newStateId));

View file

@ -213,11 +213,11 @@ function recreateStates() {
// turn all old capitals into town, except for the capitals of locked states // turn all old capitals into town, except for the capitals of locked states
for (const burg of validBurgs) { for (const burg of validBurgs) {
if (!burg.capital) continue; if (burg.capital) {
if (lockedStatesCapitals.includes(burg.i)) continue; if (lockedStatesCapitals.includes(burg.i)) continue;
moveBurgToGroup(burg.i, "town");
burg.capital = 0; burg.capital = 0;
Burgs.changeGroup(burg);
}
} }
// remove labels and emblems for non-locked states // remove labels and emblems for non-locked states
@ -304,7 +304,7 @@ function recreateStates() {
burg.capital = 1; burg.capital = 1;
capital = burg; capital = burg;
capitalsTree.add([x, y]); capitalsTree.add([x, y]);
moveBurgToGroup(burg.i, "city"); Burgs.changeGroup(capital);
break; break;
} }
@ -436,9 +436,11 @@ function regenerateBurgs() {
const burgId = Burgs.add([x, y]); const burgId = Burgs.add([x, y]);
s.capital = burgId; s.capital = burgId;
s.center = pack.burgs[burgId].cell; s.center = pack.burgs[burgId].cell;
pack.burgs[burgId].capital = 1;
pack.burgs[burgId].state = s.i; const burg = pack.burgs[burgId];
moveBurgToGroup(burgId, "city"); burg.state = s.i;
burg.capital = 1;
Burgs.changeGroup(burg);
}); });
features.forEach(f => { features.forEach(f => {