From 95c6af8993434c55866bf803b5d8d8464fc8df1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Montero=20Lamas?= Date: Thu, 12 Sep 2024 01:23:50 +0200 Subject: [PATCH 01/61] added names to the random names of zones (#1128) * added names of zones added names for rebels, invasion and animals. * deleted suggested names - deleted siege and subjugation from zones.generator.js const subtype = rw * fixed invationCells spelling Fixed invationCells to invasionCells. Is invasion with s. * update versioning and index.html --- index.html | 2 +- modules/zones-generator.js | 23 +++++++++++++++-------- versioning.js | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/index.html b/index.html index 4bc61652..9f84bab1 100644 --- a/index.html +++ b/index.html @@ -8070,7 +8070,7 @@ - + diff --git a/modules/zones-generator.js b/modules/zones-generator.js index e0923615..ca8e2b30 100644 --- a/modules/zones-generator.js +++ b/modules/zones-generator.js @@ -50,14 +50,14 @@ window.Zones = (function () { const startCell = ra(borderCells); if (startCell === undefined) return; - const invationCells = []; + const invasionCells = []; const queue = [startCell]; const maxCells = rand(5, 30); while (queue.length) { const cellId = P(0.4) ? queue.shift() : queue.pop(); - invationCells.push(cellId); - if (invationCells.length >= maxCells) break; + invasionCells.push(cellId); + if (invasionCells.length >= maxCells) break; cells.c[cellId].forEach(neibCellId => { if (usedCells[neibCellId]) return; @@ -73,11 +73,15 @@ window.Zones = (function () { Conquest: 3, Incursion: 2, Intervention: 2, - Subjugation: 1, + Assault: 1, Foray: 1, - Skirmishes: 1, + Intrusion: 1, + Irruption: 1, + Offensive: 1, Pillaging: 1, - Raid: 1 + Plunder: 1, + Raid: 1, + Skirmishes: 1 }); const name = getAdjective(states[attacker].name) + " " + subtype; @@ -120,10 +124,13 @@ window.Zones = (function () { Insurrection: 2, Mutineers: 1, Insurgents: 1, + Rebellion: 1, + Renegades: 1, + Revolters: 1, + Revolutionaries: 1, Rioters: 1, Separatists: 1, Secessionists: 1, - Rebellion: 1, Conspiracy: 1 }); @@ -226,7 +233,7 @@ window.Zones = (function () { const name = `${(() => { const model = rw({color: 2, animal: 1, adjective: 1}); if (model === "color") return ra(["Amber", "Azure", "Black", "Blue", "Brown", "Crimson", "Emerald", "Golden", "Green", "Grey", "Orange", "Pink", "Purple", "Red", "Ruby", "Scarlet", "Silver", "Violet", "White", "Yellow"]); - if (model === "animal") return ra(["Ape", "Bear", "Bird", "Boar", "Cat", "Cow", "Dog", "Fox", "Horse", "Lion", "Pig", "Rat", "Raven", "Sheep", "Spider", "Tiger", "Viper", "Wolf", "Worm", "Wyrm"]); + if (model === "animal") return ra(["Ape", "Bear", "Bird", "Boar", "Cat", "Cow", "Deer", "Dog", "Fox", "Goat", "Horse", "Lion", "Pig", "Rat", "Raven", "Sheep", "Spider", "Tiger", "Viper", "Wolf", "Worm", "Wyrm"]); if (model === "adjective") return ra(["Blind", "Bloody", "Brutal", "Burning", "Deadly", "Fatal", "Furious", "Great", "Grim", "Horrible", "Invisible", "Lethal", "Loud", "Mortal", "Savage", "Severe", "Silent", "Unknown", "Venomous", "Vicious"]); })()} ${rw({Fever: 5, Plague: 3, Cough: 3, Flu: 2, Pox: 2, Cholera: 2, Typhoid: 2, Leprosy: 1, Smallpox: 1, Pestilence: 1, Consumption: 1, Malaria: 1, Dropsy: 1})}`; diff --git a/versioning.js b/versioning.js index 6f8bf5f7..f89a5780 100644 --- a/versioning.js +++ b/versioning.js @@ -12,7 +12,7 @@ * * Example: 1.102.2 -> Major version 1, Minor version 102, Patch version 2 */ -const VERSION = "1.103.5"; +const VERSION = "1.103.6"; if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format or parsing function"); { From 0187bba76c792b9e7ad9c25f47d30110c4cc8a24 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Thu, 12 Sep 2024 11:25:53 +0200 Subject: [PATCH 02/61] hotfix: 1.103.7 --- index.html | 2 +- modules/zones-generator.js | 2 +- versioning.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 9f84bab1..cd1112aa 100644 --- a/index.html +++ b/index.html @@ -8070,7 +8070,7 @@ - + diff --git a/modules/zones-generator.js b/modules/zones-generator.js index ca8e2b30..7e8ec94b 100644 --- a/modules/zones-generator.js +++ b/modules/zones-generator.js @@ -85,7 +85,7 @@ window.Zones = (function () { }); const name = getAdjective(states[attacker].name) + " " + subtype; - pack.zones.push({i: pack.zones.length, name, type: "Invasion", cells: invationCells, color: "url(#hatch1)"}); + pack.zones.push({i: pack.zones.length, name, type: "Invasion", cells: invasionCells, color: "url(#hatch1)"}); } function addRebels(usedCells) { diff --git a/versioning.js b/versioning.js index f89a5780..fe86508b 100644 --- a/versioning.js +++ b/versioning.js @@ -12,7 +12,7 @@ * * Example: 1.102.2 -> Major version 1, Minor version 102, Patch version 2 */ -const VERSION = "1.103.6"; +const VERSION = "1.103.7"; if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format or parsing function"); { From ec993d1a9ba5f25af2852e18f6574898966b35ed Mon Sep 17 00:00:00 2001 From: Azgaar Date: Thu, 12 Sep 2024 12:55:31 +0200 Subject: [PATCH 03/61] fix: #1129 --- index.html | 2 +- modules/routes-generator.js | 5 +---- modules/ui/route-group-editor.js | 9 ++++----- versioning.js | 2 +- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/index.html b/index.html index cd1112aa..931174f1 100644 --- a/index.html +++ b/index.html @@ -8098,7 +8098,7 @@ - + diff --git a/modules/routes-generator.js b/modules/routes-generator.js index 044f0cf4..edd41b4f 100644 --- a/modules/routes-generator.js +++ b/modules/routes-generator.js @@ -725,10 +725,7 @@ window.Routes = (function () { } pack.routes = pack.routes.filter(r => r.i !== route.i); - viewbox - .select("#routes") - .select("#route" + route.i) - .remove(); + viewbox.select("#route" + route.i).remove(); } return { diff --git a/modules/ui/route-group-editor.js b/modules/ui/route-group-editor.js index 370058c1..8450e299 100644 --- a/modules/ui/route-group-editor.js +++ b/modules/ui/route-group-editor.js @@ -18,7 +18,7 @@ function editRouteGroups() { // add listeners byId("routeGroupsEditorAdd").addEventListener("click", addGroup); byId("routeGroupsEditorBody").on("click", ev => { - const group = ev.target.parentNode.dataset.id; + const group = ev.target.closest(".states")?.dataset.id; if (ev.target.classList.contains("editStyle")) editStyle("routes", group); else if (ev.target.classList.contains("removeGroup")) removeGroup(group); }); @@ -72,12 +72,11 @@ function editRouteGroups() { confirmationDialog({ title: "Remove route group", message: - "Are you sure you want to remove the entire route group? All routes in this group will be removed. This action can't be reverted.", + "Are you sure you want to remove the entire route group? All routes in this group will be removed.
This action can't be reverted", confirm: "Remove", onConfirm: () => { - const routes = pack.routes.filter(r => r.group === group); - routes.forEach(r => Routes.remove(r)); - if (DEFAULT_GROUPS.includes(group)) routes.select(`#${group}`).remove(); + pack.routes.filter(r => r.group === group).forEach(Routes.remove); + if (!DEFAULT_GROUPS.includes(group)) routes.select(`#${group}`).remove(); addLines(); } }); diff --git a/versioning.js b/versioning.js index fe86508b..47719a09 100644 --- a/versioning.js +++ b/versioning.js @@ -12,7 +12,7 @@ * * Example: 1.102.2 -> Major version 1, Minor version 102, Patch version 2 */ -const VERSION = "1.103.7"; +const VERSION = "1.103.8"; if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format or parsing function"); { From 05de284e020139fa22c3a9a943b7a522fc1f3cac Mon Sep 17 00:00:00 2001 From: Azgaar Date: Fri, 20 Sep 2024 12:20:27 +0200 Subject: [PATCH 04/61] Refactor layers rendering (#1120) * feat: render states - use global fn * feat: render states - separate pole detection from layer render * feat: render provinces * chore: unify drawFillWithGap * refactor: drawIce * refactor: drawBorders * refactor: drawHeightmap * refactor: drawTemperature * refactor: drawBiomes * refactor: drawPrec * refactor: drawPrecipitation * refactor: drawPopulation * refactor: drawCells * refactor: geColor * refactor: drawMarkers * refactor: drawScaleBar * refactor: drawScaleBar * refactor: drawMilitary * refactor: pump version to 1.104.00 * refactor: pump version to 1.104.00 * refactor: drawCoastline and createDefaultRuler * refactor: drawCoastline * refactor: Features module start * refactor: features - define distance fields * feat: drawFeatures * feat: drawIce don't hide * feat: detect coastline - fix issue with border feature * feat: separate labels rendering from generation process * feat: auto-update and restore layers * refactor - change layers * refactor - sort layers * fix: regenerate burgs to re-render layers * fix: getColor is not defined * fix: burgs overview - don't auto-show labels on hover * fix: redraw population on change * refactor: improve tooltip logic for burg labels and icons * chore: pump version to 1.104.0 * fefactor: edit coastline and lake * fix: minot fixes * fix: submap --------- Co-authored-by: Azgaar --- index.css | 16 +- index.html | 102 +- libs/simplify.js | 103 ++ main.js | 328 +--- modules/burgs-and-states.js | 375 +--- modules/dynamic/auto-update.js | 24 +- modules/dynamic/editors/cultures-editor.js | 1 + modules/dynamic/editors/religions-editor.js | 1 + modules/dynamic/editors/states-editor.js | 23 +- modules/features.js | 255 +++ modules/io/export.js | 2 + modules/io/load.js | 12 +- modules/lakes.js | 174 +- modules/military-generator.js | 136 +- modules/provinces-generator.js | 257 +++ modules/renderers/draw-borders.js | 120 ++ modules/renderers/draw-burg-icons.js | 69 + modules/renderers/draw-burg-labels.js | 39 + modules/renderers/draw-emblems.js | 129 ++ modules/renderers/draw-features.js | 61 + modules/renderers/draw-heightmap.js | 144 ++ modules/renderers/draw-markers.js | 50 + modules/renderers/draw-military.js | 126 ++ modules/renderers/draw-scalebar.js | 101 ++ .../{state-labels.js => draw-state-labels.js} | 4 +- modules/renderers/draw-temperature.js | 104 ++ modules/river-generator.js | 6 +- modules/submap.js | 101 +- modules/ui/3d.js | 5 +- modules/ui/battle-screen.js | 4 +- modules/ui/burg-editor.js | 2 +- modules/ui/burgs-overview.js | 6 +- modules/ui/coastline-editor.js | 151 +- modules/ui/editors.js | 26 +- modules/ui/general.js | 18 +- modules/ui/heightmap-editor.js | 34 +- modules/ui/hotkeys.js | 6 +- modules/ui/lakes-editor.js | 138 +- modules/ui/layers.js | 1578 +++-------------- modules/ui/measurers.js | 29 + modules/ui/provinces-editor.js | 116 +- modules/ui/regiment-editor.js | 4 +- modules/ui/regiments-overview.js | 2 +- modules/ui/style.js | 7 +- modules/ui/submap.js | 3 +- modules/ui/tools.js | 40 +- modules/ui/units-editor.js | 4 +- modules/ui/world-configurator.js | 6 +- modules/ui/zones-editor.js | 1 + utils/commonUtils.js | 1 + utils/pathUtils.js | 140 +- versioning.js | 2 +- 52 files changed, 2473 insertions(+), 2713 deletions(-) create mode 100644 libs/simplify.js create mode 100644 modules/features.js create mode 100644 modules/provinces-generator.js create mode 100644 modules/renderers/draw-borders.js create mode 100644 modules/renderers/draw-burg-icons.js create mode 100644 modules/renderers/draw-burg-labels.js create mode 100644 modules/renderers/draw-emblems.js create mode 100644 modules/renderers/draw-features.js create mode 100644 modules/renderers/draw-heightmap.js create mode 100644 modules/renderers/draw-markers.js create mode 100644 modules/renderers/draw-military.js create mode 100644 modules/renderers/draw-scalebar.js rename modules/renderers/{state-labels.js => draw-state-labels.js} (99%) create mode 100644 modules/renderers/draw-temperature.js diff --git a/index.css b/index.css index eb1e82fc..49ecd8f0 100644 --- a/index.css +++ b/index.css @@ -122,10 +122,6 @@ a { fill: none; } -#biomes { - stroke-width: 0.7; -} - #landmass { mask: url(#land); fill-rule: evenodd; @@ -190,20 +186,12 @@ t, font-size: 0.8em; } -#statesBody { - stroke-width: 3; -} - #statesHalo { fill: none; stroke-linecap: round; stroke-linejoin: round; } -#provincesBody { - stroke-width: 0.2; -} - #statesBody, #provincesBody, #relig, @@ -733,7 +721,7 @@ input[type="color"]::-webkit-color-swatch-wrapper { #toolsContent > .grid { display: grid; - grid-template-columns: repeat(4, 1fr); + grid-template-columns: repeat(3, 1fr); margin: 0.2em 0; } @@ -780,7 +768,7 @@ fieldset { text-overflow: ellipsis; } -.tabcontent .buttonoff { +.tabcontent li.buttonoff { background-color: var(--bg-disabled); color: #444444aa; } diff --git a/index.html b/index.html index 931174f1..6fcaf3c5 100644 --- a/index.html +++ b/index.html @@ -138,7 +138,7 @@ } - + @@ -344,6 +344,10 @@ + + + + @@ -351,9 +355,6 @@ - - - @@ -438,7 +439,7 @@ + + + + + Speaker voice @@ -8062,10 +8072,9 @@ - - - - + + + diff --git a/libs/openwidget.min.js b/libs/openwidget.min.js new file mode 100644 index 00000000..89583d8f --- /dev/null +++ b/libs/openwidget.min.js @@ -0,0 +1 @@ +window.__ow=window.__ow||{},window.__ow.organizationId="7bb02e70-bcef-4861-a4e6-d259b0d10e24",window.__ow.integration_name="manual_settings",window.__ow.product_name="openwidget",function(n,e,t){function o(n){return c._h?c._h.apply(null,n):c._q.push(n)}var c={_q:[],_h:null,_v:"2.0",on:function(){o(["on",t.call(arguments)])},once:function(){o(["once",t.call(arguments)])},off:function(){o(["off",t.call(arguments)])},get:function(){if(!c._h)throw Error("[OpenWidget] You can't use getters before load.");return o(["get",t.call(arguments)])},call:function(){o(["call",t.call(arguments)])},init:function(){var n=e.createElement("script");n.async=!0,n.type="text/javascript",n.src="https://cdn.openwidget.com/openwidget.js",e.head.appendChild(n)}};n.__ow.asyncInit||c.init(),n.OpenWidget=n.OpenWidget||c}(window,document,[].slice); \ No newline at end of file diff --git a/main.js b/main.js index ca6f1ca1..eeff1f71 100644 --- a/main.js +++ b/main.js @@ -317,7 +317,8 @@ async function generateMapOnLoad() { applyLayersPreset(); // apply saved layers preset and reder layers drawLayers(); fitMapToScreen(); - focusOn(); // focus on point, cell or burg from MFCG based on url searchParams + focusOn(); // based on searchParams focus on point, cell or burg from MFCG + toggleAssistant(); } // focus on coordinates, cell or burg provided in searchParams @@ -367,6 +368,31 @@ function focusOn() { } } +let isAssistantLoaded = false; +function toggleAssistant() { + const assistantContainer = byId("chat-widget-container"); + const showAssistant = byId("azgaarAssistant").value === "show"; + + if (showAssistant) { + if (isAssistantLoaded) { + assistantContainer.style.display = "block"; + } else { + import("./libs/openwidget.min.js").then(() => { + isAssistantLoaded = true; + setTimeout(() => { + const bubble = byId("chat-widget-minimized"); + if (bubble) { + bubble.dataset.tip = "Click to open the Assistant"; + bubble.on("mouseover", showDataTip); + } + }, 5000); + }); + } + } else if (isAssistantLoaded) { + assistantContainer.style.display = "none"; + } +} + // find burg for MFCG and focus on it function findBurgForMFCG(params) { const cells = pack.cells, diff --git a/modules/ui/options.js b/modules/ui/options.js index a6640aed..1ac4c8ad 100644 --- a/modules/ui/options.js +++ b/modules/ui/options.js @@ -148,6 +148,7 @@ optionsContent.addEventListener("change", event => { else if (id === "yearInput") changeYear(); else if (id === "eraInput") changeEra(); else if (id === "stateLabelsModeInput") options.stateLabelsMode = value; + else if (id === "azgaarAssistant") toggleAssistant(); }); optionsContent.addEventListener("click", event => { @@ -446,6 +447,7 @@ function changeDialogsTheme(themeColor, transparency) { }; const theme = [ + {name: "--bg-opacity", value: alpha}, {name: "--bg-main", h, s, l, alpha}, {name: "--bg-lighter", h, s, l: l + 0.02, alpha}, {name: "--bg-light", h, s: s - 0.02, l: l + 0.06, alpha}, @@ -458,8 +460,9 @@ function changeDialogsTheme(themeColor, transparency) { ]; const sx = document.documentElement.style; - theme.forEach(({name, h, s, l, alpha}) => { - sx.setProperty(name, getRGBA(h, s, l, alpha)); + theme.forEach(({name, value, h, s, l, alpha}) => { + if (value !== undefined) sx.setProperty(name, value); + else sx.setProperty(name, getRGBA(h, s, l, alpha)); }); } diff --git a/versioning.js b/versioning.js index bf3deac2..afa76381 100644 --- a/versioning.js +++ b/versioning.js @@ -12,7 +12,7 @@ * * Example: 1.102.2 -> Major version 1, Minor version 102, Patch version 2 */ -const VERSION = "1.104.15"; +const VERSION = "1.105.0"; if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format or parsing function"); { @@ -36,6 +36,7 @@ if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format o
    Latest changes: +
  • Azgaar Bot to answer questions and provide help
  • Labels: ability to set letter spacing
  • Zones update
  • Notes Editor: on-demand AI text generation
  • From b66874ddda47e8a5b9ae5216526e97bfaa2557bd Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sun, 22 Sep 2024 18:20:22 +0200 Subject: [PATCH 21/61] feat: battles - move Regiments back to init position after the battle --- modules/ui/battle-screen.js | 122 ++++++++++++++++-------------------- versioning.js | 4 +- 2 files changed, 56 insertions(+), 70 deletions(-) diff --git a/modules/ui/battle-screen.js b/modules/ui/battle-screen.js index 8c595a80..f2e47452 100644 --- a/modules/ui/battle-screen.js +++ b/modules/ui/battle-screen.js @@ -36,45 +36,31 @@ class Battle { modules.Battle = true; // add listeners - document.getElementById("battleType").addEventListener("click", ev => this.toggleChange(ev)); - document - .getElementById("battleType") - .nextElementSibling.addEventListener("click", ev => Battle.prototype.context.changeType(ev)); - document - .getElementById("battleNameShow") - .addEventListener("click", () => Battle.prototype.context.showNameSection()); - document - .getElementById("battleNamePlace") - .addEventListener("change", ev => (Battle.prototype.context.place = ev.target.value)); - document.getElementById("battleNameFull").addEventListener("change", ev => Battle.prototype.context.changeName(ev)); - document - .getElementById("battleNameCulture") - .addEventListener("click", () => Battle.prototype.context.generateName("culture")); - document - .getElementById("battleNameRandom") - .addEventListener("click", () => Battle.prototype.context.generateName("random")); - document.getElementById("battleNameHide").addEventListener("click", this.hideNameSection); - document.getElementById("battleAddRegiment").addEventListener("click", this.addSide); - document.getElementById("battleRoll").addEventListener("click", () => Battle.prototype.context.randomize()); - document.getElementById("battleRun").addEventListener("click", () => Battle.prototype.context.run()); - document.getElementById("battleApply").addEventListener("click", () => Battle.prototype.context.applyResults()); - document.getElementById("battleCancel").addEventListener("click", () => Battle.prototype.context.cancelResults()); - document.getElementById("battleWiki").addEventListener("click", () => wiki("Battle-Simulator")); + byId("battleType").on("click", ev => this.toggleChange(ev)); + byId("battleType").nextElementSibling.on("click", ev => Battle.prototype.context.changeType(ev)); + byId("battleNameShow").on("click", () => Battle.prototype.context.showNameSection()); + byId("battleNamePlace").on("change", ev => (Battle.prototype.context.place = ev.target.value)); + byId("battleNameFull").on("change", ev => Battle.prototype.context.changeName(ev)); + byId("battleNameCulture").on("click", () => Battle.prototype.context.generateName("culture")); + byId("battleNameRandom").on("click", () => Battle.prototype.context.generateName("random")); + byId("battleNameHide").on("click", this.hideNameSection); + byId("battleAddRegiment").on("click", this.addSide); + byId("battleRoll").on("click", () => Battle.prototype.context.randomize()); + byId("battleRun").on("click", () => Battle.prototype.context.run()); + byId("battleApply").on("click", () => Battle.prototype.context.applyResults()); + byId("battleCancel").on("click", () => Battle.prototype.context.cancelResults()); + byId("battleWiki").on("click", () => wiki("Battle-Simulator")); - document.getElementById("battlePhase_attackers").addEventListener("click", ev => this.toggleChange(ev)); - document - .getElementById("battlePhase_attackers") - .nextElementSibling.addEventListener("click", ev => Battle.prototype.context.changePhase(ev, "attackers")); - document.getElementById("battlePhase_defenders").addEventListener("click", ev => this.toggleChange(ev)); - document - .getElementById("battlePhase_defenders") - .nextElementSibling.addEventListener("click", ev => Battle.prototype.context.changePhase(ev, "defenders")); - document - .getElementById("battleDie_attackers") - .addEventListener("click", () => Battle.prototype.context.rollDie("attackers")); - document - .getElementById("battleDie_defenders") - .addEventListener("click", () => Battle.prototype.context.rollDie("defenders")); + byId("battlePhase_attackers").on("click", ev => this.toggleChange(ev)); + byId("battlePhase_attackers").nextElementSibling.on("click", ev => + Battle.prototype.context.changePhase(ev, "attackers") + ); + byId("battlePhase_defenders").on("click", ev => this.toggleChange(ev)); + byId("battlePhase_defenders").nextElementSibling.on("click", ev => + Battle.prototype.context.changePhase(ev, "defenders") + ); + byId("battleDie_attackers").on("click", () => Battle.prototype.context.rollDie("attackers")); + byId("battleDie_defenders").on("click", () => Battle.prototype.context.rollDie("defenders")); } defineType() { @@ -97,20 +83,16 @@ class Battle { } setType() { - document.getElementById("battleType").className = "icon-button-" + this.type; + byId("battleType").className = "icon-button-" + this.type; - const sideSpecific = document.getElementById("battlePhases_" + this.type + "_attackers"); - const attackers = sideSpecific - ? sideSpecific.content - : document.getElementById("battlePhases_" + this.type).content; - const defenders = sideSpecific - ? document.getElementById("battlePhases_" + this.type + "_defenders").content - : attackers; + const sideSpecific = byId("battlePhases_" + this.type + "_attackers"); + const attackers = sideSpecific ? sideSpecific.content : byId("battlePhases_" + this.type).content; + const defenders = sideSpecific ? byId("battlePhases_" + this.type + "_defenders").content : attackers; - document.getElementById("battlePhase_attackers").nextElementSibling.innerHTML = ""; - document.getElementById("battlePhase_defenders").nextElementSibling.innerHTML = ""; - document.getElementById("battlePhase_attackers").nextElementSibling.append(attackers.cloneNode(true)); - document.getElementById("battlePhase_defenders").nextElementSibling.append(defenders.cloneNode(true)); + byId("battlePhase_attackers").nextElementSibling.innerHTML = ""; + byId("battlePhase_defenders").nextElementSibling.innerHTML = ""; + byId("battlePhase_attackers").nextElementSibling.append(attackers.cloneNode(true)); + byId("battlePhase_defenders").nextElementSibling.append(defenders.cloneNode(true)); } definePlace() { @@ -200,7 +182,7 @@ class Battle { } addSide() { - const body = document.getElementById("regimentSelectorBody"); + const body = byId("regimentSelectorBody"); const context = Battle.prototype.context; const regiments = pack.states .filter(s => s.military && !s.removed) @@ -246,7 +228,7 @@ class Battle { }); applySorting(regimentSelectorHeader); - body.addEventListener("click", selectLine); + body.on("click", selectLine); function selectLine(ev) { if (ev.target.className === "inactive") { @@ -289,15 +271,15 @@ class Battle { showNameSection() { document.querySelectorAll("#battleBottom > button").forEach(el => (el.style.display = "none")); - document.getElementById("battleNameSection").style.display = "inline-block"; + byId("battleNameSection").style.display = "inline-block"; - document.getElementById("battleNamePlace").value = this.place; - document.getElementById("battleNameFull").value = this.name; + byId("battleNamePlace").value = this.place; + byId("battleNameFull").value = this.name; } hideNameSection() { document.querySelectorAll("#battleBottom > button").forEach(el => (el.style.display = "inline-block")); - document.getElementById("battleNameSection").style.display = "none"; + byId("battleNameSection").style.display = "none"; } changeName(ev) { @@ -310,8 +292,8 @@ class Battle { type === "culture" ? Names.getCulture(pack.cells.culture[this.cell], null, null, "") : Names.getBase(rand(nameBases.length - 1)); - document.getElementById("battleNamePlace").value = this.place = place; - document.getElementById("battleNameFull").value = this.name = this.defineName(); + byId("battleNamePlace").value = this.place = place; + byId("battleNameFull").value = this.name = this.defineName(); $("#battleScreen").dialog({title: this.name}); } @@ -495,7 +477,7 @@ class Battle { this[side].power = d3.sum(options.military.map(u => (forces[u.name] || 0) * u.power * scheme[phase][u.type])) / adjuster; const UIvalue = this[side].power ? Math.max(this[side].power | 0, 1) : 0; - document.getElementById("battlePower_" + side).innerHTML = UIvalue; + byId("battlePower_" + side).innerHTML = UIvalue; } getInitialMorale() { @@ -509,7 +491,7 @@ class Battle { } updateMorale(side) { - const morale = document.getElementById("battleMorale_" + side); + const morale = byId("battleMorale_" + side); morale.dataset.tip = morale.dataset.tip.replace(morale.value, ""); morale.value = this[side].morale | 0; morale.dataset.tip += morale.value; @@ -524,7 +506,7 @@ class Battle { } rollDie(side) { - const el = document.getElementById("battleDie_" + side); + const el = byId("battleDie_" + side); const prev = +el.innerHTML; do { el.innerHTML = rand(1, 6); @@ -672,11 +654,11 @@ class Battle { this.attackers.phase = phase[0]; this.defenders.phase = phase[1]; - const buttonA = document.getElementById("battlePhase_attackers"); + const buttonA = byId("battlePhase_attackers"); buttonA.className = "icon-button-" + this.attackers.phase; buttonA.dataset.tip = buttonA.nextElementSibling.querySelector("[data-phase='" + phase[0] + "']").dataset.tip; - const buttonD = document.getElementById("battlePhase_defenders"); + const buttonD = byId("battlePhase_defenders"); buttonD.className = "icon-button-" + this.defenders.phase; buttonD.dataset.tip = buttonD.nextElementSibling.querySelector("[data-phase='" + phase[1] + "']").dataset.tip; } @@ -760,7 +742,7 @@ class Battle { updateTable(side) { for (const r of this[side].regiments) { - const tbody = document.getElementById("battle" + r.state + "-" + r.i); + const tbody = byId("battle" + r.state + "-" + r.i); const battleCasualties = tbody.querySelector(".battleCasualties"); const battleSurvivors = tbody.querySelector(".battleSurvivors"); @@ -794,7 +776,7 @@ class Battle { button.style.opacity = 0.5; div.style.display = "block"; - document.getElementsByTagName("body")[0].addEventListener("click", hideSection, {once: true}); + document.getElementsByTagName("body")[0].on("click", hideSection, {once: true}); } changeType(ev) { @@ -811,7 +793,7 @@ class Battle { changePhase(ev, side) { if (ev.target.tagName !== "BUTTON") return; const phase = (this[side].phase = ev.target.dataset.phase); - const button = document.getElementById("battlePhase_" + side); + const button = byId("battlePhase_" + side); button.className = "icon-button-" + phase; button.dataset.tip = ev.target.dataset.tip; this.calculateStrength(side); @@ -873,6 +855,8 @@ class Battle { r.u = Object.assign({}, r.survivors); r.a = d3.sum(Object.values(r.u)); // reg total armies.select(`g#${id} > text`).text(Military.getTotal(r)); // update reg box + + moveRegiment(r, r.px, r.py); // move regiment back to initial position } const i = last(pack.markers)?.i + 1 || 0; @@ -881,7 +865,7 @@ class Battle { const marker = {i, x: this.x, y: this.y, cell: this.cell, icon: "⚔️", type: "battlefields", dy: 52}; pack.markers.push(marker); const markerHTML = drawMarker(marker); - document.getElementById("markers").insertAdjacentHTML("beforeend", markerHTML); + byId("markers").insertAdjacentHTML("beforeend", markerHTML); } const getSide = (regs, n) => @@ -909,7 +893,9 @@ class Battle { cancelResults() { // move regiments back to initial positions - this.attackers.regiments.concat(this.defenders.regiments).forEach(r => moveRegiment(r, r.px, r.py)); + this.attackers.regiments.forEach(r => moveRegiment(r, r.px, r.py)); + this.defenders.regiments.forEach(r => moveRegiment(r, r.px, r.py)); + $("#battleScreen").dialog("close"); this.cleanData(); } diff --git a/versioning.js b/versioning.js index afa76381..c5afab7d 100644 --- a/versioning.js +++ b/versioning.js @@ -12,7 +12,7 @@ * * Example: 1.102.2 -> Major version 1, Minor version 102, Patch version 2 */ -const VERSION = "1.105.0"; +const VERSION = "1.105.1"; if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format or parsing function"); { @@ -38,7 +38,7 @@ if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format o Latest changes:
  • Azgaar Bot to answer questions and provide help
  • Labels: ability to set letter spacing
  • -
  • Zones update
  • +
  • Zones performance improvement
  • Notes Editor: on-demand AI text generation
  • New style preset: Dark Seas
  • New routes generation algorithm
  • From ea27276558bd07d4f5acb3c5e1046cfa83434d7f Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sun, 22 Sep 2024 20:07:55 +0200 Subject: [PATCH 22/61] fix: disable double-click on heightmap edit --- index.css | 5 +++++ index.html | 10 ++++------ main.js | 7 +++---- modules/ui/editors.js | 1 + modules/ui/heightmap-editor.js | 2 ++ versioning.js | 2 +- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/index.css b/index.css index b36a0716..08c8828e 100644 --- a/index.css +++ b/index.css @@ -673,6 +673,7 @@ input[type="color"]::-webkit-color-swatch-wrapper { border: none; padding: 0.45em 0.75em; margin: 0.4em 0; + white-space: nowrap; font-family: var(--monospace); animation: glowing 2s infinite; } @@ -2388,6 +2389,10 @@ svg.button { } } +#chat-widget-container { + user-select: none; +} + #chat-widget-minimized { animation: fadeIn 1s ease-in; transform: scale(0.65); diff --git a/index.html b/index.html index e3154e9e..f11e26a6 100644 --- a/index.html +++ b/index.html @@ -2418,9 +2418,7 @@
    - +
    @@ -8074,14 +8072,14 @@ - + - + - + diff --git a/main.js b/main.js index eeff1f71..7afe4cf6 100644 --- a/main.js +++ b/main.js @@ -170,7 +170,7 @@ let scale = 1; let viewX = 0; let viewY = 0; -function onZoom() { +const onZoom = debounce(function () { const {k, x, y} = d3.event.transform; const isScaleChanged = Boolean(scale - k); @@ -182,9 +182,8 @@ function onZoom() { viewY = y; handleZoom(isScaleChanged, isPositionChanged); -} -const onZoomDebouced = debounce(onZoom, 50); -const zoom = d3.zoom().scaleExtent([1, 20]).on("zoom", onZoomDebouced); +}, 50); +const zoom = d3.zoom().scaleExtent([1, 20]).on("zoom", onZoom); // default options, based on Earth data let options = { diff --git a/modules/ui/editors.js b/modules/ui/editors.js index cb7b07c4..dd742aed 100644 --- a/modules/ui/editors.js +++ b/modules/ui/editors.js @@ -8,6 +8,7 @@ function restoreDefaultEvents() { svg.call(zoom); viewbox.style("cursor", "default").on(".drag", null).on("click", clicked).on("touchmove mousemove", onMouseMove); legend.call(d3.drag().on("start", dragLegendBox)); + svg.call(zoom); } // handle viewbox click diff --git a/modules/ui/heightmap-editor.js b/modules/ui/heightmap-editor.js index 015303bf..20fa201c 100644 --- a/modules/ui/heightmap-editor.js +++ b/modules/ui/heightmap-editor.js @@ -112,7 +112,9 @@ function editHeightmap(options) { layersPreset.value = "heightmap"; layersPreset.disabled = true; mockHeightmap(); + viewbox.on("touchmove mousemove", moveCursor); + svg.on("dblclick.zoom", null); if (tool === "templateEditor") openTemplateEditor(); else if (tool === "imageConverter") openImageConverter(); diff --git a/versioning.js b/versioning.js index c5afab7d..d45d29a1 100644 --- a/versioning.js +++ b/versioning.js @@ -12,7 +12,7 @@ * * Example: 1.102.2 -> Major version 1, Minor version 102, Patch version 2 */ -const VERSION = "1.105.1"; +const VERSION = "1.105.2"; if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format or parsing function"); { From b12760781122d64b0f2e8d6d374353a11f51ed78 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Mon, 23 Sep 2024 12:35:16 +0200 Subject: [PATCH 23/61] chore: supporters update --- modules/dynamic/supporters.js | 3 ++- versioning.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/dynamic/supporters.js b/modules/dynamic/supporters.js index d6f9019a..3ca64da0 100644 --- a/modules/dynamic/supporters.js +++ b/modules/dynamic/supporters.js @@ -582,4 +582,5 @@ Marmalade_MacGuffin James Benware FortunesFaded breadsticks -Murderbits`; +Murderbits +Ben Jones`; diff --git a/versioning.js b/versioning.js index d45d29a1..85a1f8bb 100644 --- a/versioning.js +++ b/versioning.js @@ -12,7 +12,7 @@ * * Example: 1.102.2 -> Major version 1, Minor version 102, Patch version 2 */ -const VERSION = "1.105.2"; +const VERSION = "1.105.3"; if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format or parsing function"); { From ba3a9d15986361e1bb09ec0da954ac48475a3a37 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Mon, 23 Sep 2024 12:52:56 +0200 Subject: [PATCH 24/61] chore: set libs version --- index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index f11e26a6..da856572 100644 --- a/index.html +++ b/index.html @@ -8062,10 +8062,10 @@ - - - - + + + + From 879cf6b6921b42c10b0297cf749177e24d192e41 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Wed, 25 Sep 2024 12:13:16 +0200 Subject: [PATCH 25/61] fix: typo --- index.html | 2 +- modules/ui/world-configurator.js | 2 +- versioning.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index da856572..4ebd35b5 100644 --- a/index.html +++ b/index.html @@ -8078,7 +8078,7 @@ - + diff --git a/modules/ui/world-configurator.js b/modules/ui/world-configurator.js index ef762e2b..0b5abab0 100644 --- a/modules/ui/world-configurator.js +++ b/modules/ui/world-configurator.js @@ -15,7 +15,7 @@ function editWorld() { pane.insertAdjacentHTML("afterbegin", checkbox); const button = this.parentElement.querySelector(".ui-dialog-buttonset > button"); - button.on("mousemove", () => tip("Apply curreny settings to the map")); + button.on("mousemove", () => tip("Apply current settings to the map")); }, close: function () { $(this).dialog("destroy"); diff --git a/versioning.js b/versioning.js index 85a1f8bb..e6b4739d 100644 --- a/versioning.js +++ b/versioning.js @@ -12,7 +12,7 @@ * * Example: 1.102.2 -> Major version 1, Minor version 102, Patch version 2 */ -const VERSION = "1.105.3"; +const VERSION = "1.105.4"; if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format or parsing function"); { From 949a486bf8f4e5ca6eb7cd8de96346e128ef2c6e Mon Sep 17 00:00:00 2001 From: Azgaar Date: Wed, 25 Sep 2024 13:18:22 +0200 Subject: [PATCH 26/61] fix: redraw features on load --- index.html | 2 +- modules/dynamic/auto-update.js | 22 +++++++++++++--------- modules/io/load.js | 2 +- versioning.js | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/index.html b/index.html index 4ebd35b5..19f80e5e 100644 --- a/index.html +++ b/index.html @@ -8118,7 +8118,7 @@ - + diff --git a/modules/dynamic/auto-update.js b/modules/dynamic/auto-update.js index 0a6dcd24..e14e594f 100644 --- a/modules/dynamic/auto-update.js +++ b/modules/dynamic/auto-update.js @@ -946,19 +946,23 @@ export function resolveVersionConflicts(mapVersion) { // v1.104.00 separated pole of inaccessibility detection from layer rendering BurgsAndStates.getPoles(); Provinces.getPoles(); - - // v1.104.00 removed some layers from initial render - viewbox.select("#icons").style("display", null); - viewbox.select("#ice").style("display", null); - - // v1.104.00 added featurePaths to defs - const featurePaths = defs.select("#featurePaths"); - if (!featurePaths.size()) defs.append("g").attr("id", "featurePaths"); } if (isOlderThan("1.105.0")) { - // v1.104.0 introduced some bugs + // v1.104.0 introduced some bugs with layers visibility + viewbox.select("#icons").style("display", null); + viewbox.select("#ice").style("display", null); viewbox.select("#regions").style("display", null); viewbox.select("#armies").style("display", null); } + + if (isOlderThan("1.106.0")) { + // v1.104.0 introduced bugs with coastlines. Redraw features + defs.select("#featurePaths").remove(); + defs.append("g").attr("id", "featurePaths"); + defs.select("#land").selectAll("path, use").remove(); + defs.select("#water").selectAll("path, use").remove(); + viewbox.select("#coastline").selectAll("path, use").remove(); + drawFeatures(); + } } diff --git a/modules/io/load.js b/modules/io/load.js index c455fb52..a3f39913 100644 --- a/modules/io/load.js +++ b/modules/io/load.js @@ -459,7 +459,7 @@ async function parseLoadedData(data, mapVersion) { { // dynamically import and run auto-update script - const {resolveVersionConflicts} = await import("../dynamic/auto-update.js?v=1.104.12"); + const {resolveVersionConflicts} = await import("../dynamic/auto-update.js?v=1.105.5"); resolveVersionConflicts(mapVersion); } diff --git a/versioning.js b/versioning.js index e6b4739d..87fabf96 100644 --- a/versioning.js +++ b/versioning.js @@ -12,7 +12,7 @@ * * Example: 1.102.2 -> Major version 1, Minor version 102, Patch version 2 */ -const VERSION = "1.105.4"; +const VERSION = "1.105.5"; if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format or parsing function"); { From 84c326e347374301317fcf8c527da43c2c17ca97 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Wed, 25 Sep 2024 17:05:31 +0200 Subject: [PATCH 27/61] fix: issue with feature vertex being out of bound --- index.html | 4 ++-- libs/simplify.js | 6 +++--- utils/pathUtils.js | 2 +- versioning.js | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/index.html b/index.html index 19f80e5e..df07d894 100644 --- a/index.html +++ b/index.html @@ -8039,7 +8039,7 @@ - + @@ -8065,7 +8065,7 @@ - + diff --git a/libs/simplify.js b/libs/simplify.js index ecae2ba9..e4086e53 100644 --- a/libs/simplify.js +++ b/libs/simplify.js @@ -42,8 +42,9 @@ const newPoints = [prevPoint]; let point; - for (let i = 1, len = points.length; i < len; i++) { + for (let i = 1; i < points.length; i++) { point = points[i]; + if (!point) continue; if (getSqDist(point, prevPoint) > sqTolerance) { newPoints.push(point); @@ -51,8 +52,7 @@ } } - if (point && prevPoint !== point) newPoints.push(point); - + if (prevPoint !== point) newPoints.push(point); return newPoints; } diff --git a/utils/pathUtils.js b/utils/pathUtils.js index 57667233..4f023595 100644 --- a/utils/pathUtils.js +++ b/utils/pathUtils.js @@ -158,7 +158,7 @@ function connectVertices({vertices, startingVertex, ofSameType, addToChecked, cl else if (v2 !== previous && c2 !== c3) next = v2; else if (v3 !== previous && c1 !== c3) next = v3; - if (!vertices.c[next]) { + if (next >= vertices.c.length) { ERROR && console.error("ConnectVertices: next vertex is out of bounds"); break; } diff --git a/versioning.js b/versioning.js index 87fabf96..0afaecdd 100644 --- a/versioning.js +++ b/versioning.js @@ -12,7 +12,7 @@ * * Example: 1.102.2 -> Major version 1, Minor version 102, Patch version 2 */ -const VERSION = "1.105.5"; +const VERSION = "1.105.6"; if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format or parsing function"); { From c04fb2bfcae07b16829f26b5ecfc0b35004921e7 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Fri, 27 Sep 2024 13:32:22 +0200 Subject: [PATCH 28/61] refactor: burg types --- index.css | 14 -------------- index.html | 10 +++++----- modules/burgs-and-states.js | 25 ++++++++++++++++--------- modules/ui/burgs-overview.js | 15 ++++++++------- versioning.js | 2 +- 5 files changed, 30 insertions(+), 36 deletions(-) diff --git a/index.css b/index.css index 08c8828e..0244eb23 100644 --- a/index.css +++ b/index.css @@ -1511,20 +1511,6 @@ div.states > .burgCulture { width: 6em; } -div.states .burgPopulation { - width: 4.8em; -} - -div.states .burgType { - width: 3em; -} - -div.states .burgType > span { - padding: 0 1px; - color: #6e5e66; - transition: 0.2s; -} - div.states span.inactive { color: #c6c2c2; } diff --git a/index.html b/index.html index df07d894..1d9727ba 100644 --- a/index.html +++ b/index.html @@ -138,7 +138,7 @@ } - + @@ -5280,7 +5280,7 @@
    @@ -5751,6 +5769,83 @@ + + + +