"use strict"; function editBurg(id) { if (customization) return; closeDialogs(".stable"); if (!layerIsOn("toggleBurgIcons")) toggleBurgIcons(); if (!layerIsOn("toggleLabels")) toggleLabels(); const burg = id || d3.event.target.dataset.id; elSelected = burgLabels.select("[data-id='" + burg + "']"); burgLabels.selectAll("text").call(d3.drag().on("start", dragBurgLabel)).classed("draggable", true); updateGroupsList(); updateBurgValues(); $("#burgEditor").dialog({ title: "Edit Burg", resizable: false, close: closeBurgEditor, position: {my: "left top", at: "left+10 top+10", of: "svg", collision: "fit"} }); if (modules.editBurg) return; modules.editBurg = true; // add listeners byId("burgName").on("input", changeName); byId("burgNameReRandom").on("click", generateNameRandom); byId("burgGroup").on("change", changeGroup); byId("burgGroupConfigure").on("click", editBurgGroups); byId("burgType").on("change", changeType); byId("burgCulture").on("change", changeCulture); byId("burgNameReCulture").on("click", generateNameCulture); byId("burgPopulation").on("change", changePopulation); burgBody.querySelectorAll(".burgFeature").forEach(el => el.on("click", toggleFeature)); byId("burgLinkOpen").on("click", openBurgLink); byId("burgStyleShow").on("click", showStyleSection); byId("burgStyleHide").on("click", hideStyleSection); byId("burgEditLabelStyle").on("click", editGroupLabelStyle); byId("burgEditIconStyle").on("click", editGroupIconStyle); byId("burgEditAnchorStyle").on("click", editGroupAnchorStyle); byId("burgEmblem").on("click", openEmblemEdit); byId("burgSetPreviewLink").on("click", setCustomPreview); byId("burgEditEmblem").on("click", openEmblemEdit); byId("burgLocate").on("click", zoomIntoBurg); byId("burgRelocate").on("click", toggleRelocateBurg); byId("burglLegend").on("click", editBurgLegend); byId("burgLock").on("click", toggleBurgLockButton); byId("burgRemove").on("click", removeSelectedBurg); byId("burgTemperatureGraph").on("click", showTemperatureGraph); function updateGroupsList() { byId("burgGroup").options.length = 0; // remove all options for (const {name} of options.burgs.groups) { byId("burgGroup").options.add(new Option(name, name)); } } function updateBurgValues() { const id = +elSelected.attr("data-id"); const b = pack.burgs[id]; const province = pack.cells.province[b.cell]; const provinceName = province ? pack.provinces[province].fullName + ", " : ""; const stateName = pack.states[b.state].fullName || pack.states[b.state].name; byId("burgProvinceAndState").innerHTML = provinceName + stateName; byId("burgName").value = b.name; byId("burgGroup").value = b.group; byId("burgType").value = b.type || "Generic"; byId("burgPopulation").value = rn(b.population * populationRate * urbanization); byId("burgEditAnchorStyle").style.display = +b.port ? "inline-block" : "none"; // update list and select culture const cultureSelect = byId("burgCulture"); cultureSelect.options.length = 0; const cultures = pack.cultures.filter(c => !c.removed); cultures.forEach(c => cultureSelect.options.add(new Option(c.name, c.i, false, c.i === b.culture))); const temperature = grid.cells.temp[pack.cells.g[b.cell]]; byId("burgTemperature").innerHTML = convertTemperature(temperature); byId("burgTemperatureLikeIn").dataset.tip = "Average yearly temperature is like in " + getTemperatureLikeness(temperature); byId("burgElevation").innerHTML = getHeight(pack.cells.h[b.cell]); // toggle features byId("burgCapital").classList.toggle("inactive", !b.capital); byId("burgPort").classList.toggle("inactive", !b.port); byId("burgCitadel").classList.toggle("inactive", !b.citadel); byId("burgWalls").classList.toggle("inactive", !b.walls); byId("burgPlaza").classList.toggle("inactive", !b.plaza); byId("burgTemple").classList.toggle("inactive", !b.temple); byId("burgShanty").classList.toggle("inactive", !b.shanty); updateBurgLockIcon(); // set emlem image const coaID = "burgCOA" + id; COArenderer.trigger(coaID, b.coa); byId("burgEmblem").setAttribute("href", "#" + coaID); updateBurgPreview(b); } function dragBurgLabel() { const tr = parseTransform(this.getAttribute("transform")); const dx = +tr[0] - d3.event.x, dy = +tr[1] - d3.event.y; d3.event.on("drag", function () { const x = d3.event.x, y = d3.event.y; this.setAttribute("transform", `translate(${dx + x},${dy + y})`); tip('Use dragging for fine-tuning only, to actually move burg use "Relocate" button', false, "warning"); }); } function changeName() { const id = +elSelected.attr("data-id"); pack.burgs[id].name = burgName.value; elSelected.text(burgName.value); } function generateNameRandom() { const base = rand(nameBases.length - 1); burgName.value = Names.getBase(base); changeName(); } function changeGroup() { const id = +elSelected.attr("data-id"); const burg = pack.burgs[id]; Burgs.changeGroup(burg, this.value); } function changeType() { const id = +elSelected.attr("data-id"); pack.burgs[id].type = this.value; } function changeCulture() { const id = +elSelected.attr("data-id"); pack.burgs[id].culture = +this.value; } function generateNameCulture() { const id = +elSelected.attr("data-id"); const culture = pack.burgs[id].culture; burgName.value = Names.getCulture(culture); changeName(); } function changePopulation() { const id = +elSelected.attr("data-id"); const burg = pack.burgs[id]; pack.burgs[id].population = rn(burgPopulation.value / populationRate / urbanization, 4); updateBurgPreview(burg); } function toggleFeature() { const burgId = +elSelected.attr("data-id"); const burg = pack.burgs[burgId]; const feature = this.dataset.feature; 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); } 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() { const id = +elSelected.attr("data-id"); const burg = pack.burgs[id]; burg.lock = !burg.lock; updateBurgLockIcon(); } function updateBurgLockIcon() { const id = +elSelected.attr("data-id"); const b = pack.burgs[id]; if (b.lock) { byId("burgLock").classList.remove("icon-lock-open"); byId("burgLock").classList.add("icon-lock"); } else { byId("burgLock").classList.remove("icon-lock"); byId("burgLock").classList.add("icon-lock-open"); } } function showStyleSection() { document.querySelectorAll("#burgBottom > button").forEach(el => (el.style.display = "none")); byId("burgStyleSection").style.display = "inline-block"; } function hideStyleSection() { document.querySelectorAll("#burgBottom > button").forEach(el => (el.style.display = "inline-block")); byId("burgStyleSection").style.display = "none"; } function editGroupLabelStyle() { const g = elSelected.node().parentNode.id; closeDialogs(".stable"); editStyle("labels", g); } function editGroupIconStyle() { const g = elSelected.node().parentNode.id; closeDialogs(".stable"); editStyle("burgIcons", g); } function editGroupAnchorStyle() { const g = elSelected.node().parentNode.id; closeDialogs(".stable"); editStyle("anchors", g); } function updateBurgPreview(burg) { const preview = Burgs.getPreview(burg).preview; if (!preview) { byId("burgPreviewSection").style.display = "none"; return; } byId("burgPreviewSection").style.display = "block"; // recreate object to force reload (Chrome bug) const container = byId("burgPreviewObject"); container.innerHTML = ""; const object = document.createElement("object"); object.style.width = "100%"; object.data = preview; container.insertBefore(object, null); } function openBurgLink() { const id = +elSelected.attr("data-id"); const burg = pack.burgs[id]; const link = Burgs.getPreview(burg).link; if (link) openURL(link); } function setCustomPreview() { const id = +elSelected.attr("data-id"); const burg = pack.burgs[id]; prompt( "Provide custom URL to the burg map. It can be a link to a generator or just an image. Leave empty to use the default map preview", {default: Burgs.getPreview(burg).link, required: false}, link => { if (link) burg.link = link; else delete burg.link; updateBurgPreview(burg); } ); } function openEmblemEdit() { const id = +elSelected.attr("data-id"); const burg = pack.burgs[id]; editEmblem("burg", "burgCOA" + id, burg); } function zoomIntoBurg() { const id = +elSelected.attr("data-id"); const burg = pack.burgs[id]; const x = burg.x; const y = burg.y; zoomTo(x, y, 8, 2000); } function toggleRelocateBurg() { const toggler = byId("toggleCells"); byId("burgRelocate").classList.toggle("pressed"); if (byId("burgRelocate").classList.contains("pressed")) { viewbox.style("cursor", "crosshair").on("click", relocateBurgOnClick); tip("Click on map to relocate burg. Hold Shift for continuous move", true); if (!layerIsOn("toggleCells")) { toggleCells(); toggler.dataset.forced = true; } } else { clearMainTip(); viewbox.on("click", clicked).style("cursor", "default"); if (layerIsOn("toggleCells") && toggler.dataset.forced) { toggleCells(); toggler.dataset.forced = false; } } } function relocateBurgOnClick() { const cells = pack.cells; const point = d3.mouse(this); const cellId = findCell(...point); const id = +elSelected.attr("data-id"); const burg = pack.burgs[id]; if (cells.h[cellId] < 20) return tip("Cannot place burg into the water! Select a land cell", false, "error"); if (cells.burg[cellId] && cells.burg[cellId] !== id) return tip("There is already a burg in this cell. Please select a free cell", false, "error"); const newState = cells.state[cellId]; const oldState = burg.state; if (newState !== oldState && burg.capital) return tip("Capital cannot be relocated into another state!", false, "error"); // change UI const x = rn(point[0], 2); const y = rn(point[1], 2); burgIcons.select(`#burg${id}`).attr("x", x).attr("y", y); burgLabels.select(`#burgLabel${id}`).attr("transform", null).attr("x", x).attr("y", y); const anchor = anchors.select("use[data-id='" + id + "']"); if (anchor.size()) { const size = anchor.attr("width"); const xa = rn(x - size * 0.47, 2); const ya = rn(y - size * 0.47, 2); anchor.attr("transform", null).attr("x", xa).attr("y", ya); } // change data cells.burg[burg.cell] = 0; cells.burg[cellId] = id; burg.cell = cellId; burg.state = newState; burg.x = x; burg.y = y; if (burg.capital) pack.states[newState].center = burg.cell; if (d3.event.shiftKey === false) toggleRelocateBurg(); } function editBurgLegend() { const id = elSelected.attr("data-id"); const name = elSelected.text(); editNotes("burg" + id, name); } function showTemperatureGraph() { const id = elSelected.attr("data-id"); showBurgTemperatureGraph(id); } function removeSelectedBurg() { const burgId = +elSelected.attr("data-id"); const burg = pack.burgs[burgId]; if (burg.capital) { alertMessage.innerHTML = /* html */ `You cannot remove the capital. You must change the state capital first`; $("#alert").dialog({ resizable: false, title: "Remove burg", buttons: { Ok: function () { $(this).dialog("close"); } } }); } else { confirmationDialog({ title: "Remove burg", message: "Are you sure you want to remove the burg?
This action cannot be reverted", confirm: "Remove", onConfirm: () => { Burgs.remove(burgId); $("#burgEditor").dialog("close"); } }); } } function closeBurgEditor() { byId("burgRelocate").classList.remove("pressed"); burgLabels.selectAll("text").call(d3.drag().on("drag", null)).classed("draggable", false); unselect(); } } // in °C, array from -1 °C; source: https://en.wikipedia.org/wiki/List_of_city_by_average_temperature const meanTempCityMap = { "-5": "Snag (Yukon)", "-4": "Yellowknife (Canada)", "-3": "Okhotsk (Russia)", "-2": "Fairbanks (Alaska)", "-1": "Nuuk (Greenland)", 0: "Murmansk (Russia)", 1: "Arkhangelsk (Russia)", 2: "Anchorage (Alaska)", 3: "Tromsø (Norway)", 4: "Reykjavik (Iceland)", 5: "Harbin (China)", 6: "Stockholm (Sweden)", 7: "Montreal (Canada)", 8: "Prague (Czechia)", 9: "Copenhagen (Denmark)", 10: "London (England)", 11: "Antwerp (Belgium)", 12: "Paris (France)", 13: "Milan (Italy)", 14: "Washington (D.C.)", 15: "Rome (Italy)", 16: "Dubrovnik (Croatia)", 17: "Lisbon (Portugal)", 18: "Barcelona (Spain)", 19: "Marrakesh (Morocco)", 20: "Alexandria (Egypt)", 21: "Tegucigalpa (Honduras)", 22: "Guangzhou (China)", 23: "Rio de Janeiro (Brazil)", 24: "Dakar (Senegal)", 25: "Miami (USA)", 26: "Jakarta (Indonesia)", 27: "Mogadishu (Somalia)", 28: "Bangkok (Thailand)", 29: "Niamey (Niger)", 30: "Khartoum (Sudan)" }; function getTemperatureLikeness(temperature) { if (temperature < -5) return "Yakutsk (Russia)"; if (temperature > 30) return "Mecca (Saudi Arabia)"; return meanTempCityMap[temperature] || null; }