diff --git a/modules/export.js b/modules/export.js index 45081230..27014e65 100644 --- a/modules/export.js +++ b/modules/export.js @@ -450,25 +450,21 @@ function saveGeoJSON_Rivers() { } function saveGeoJSON_Markers() { - // TODO: rework for new markers track("export", "getJSON markers"); - const json = {type: "FeatureCollection", features: []}; - markers.selectAll("use").each(function () { - const coordinates = getQGIScoordinates(this.dataset.x, this.dataset.y); - const id = this.id; - const type = this.dataset.id.substring(1); - const icon = document.getElementById(type).textContent; - const note = notes.length ? notes.find(note => note.id === this.id) : null; - const name = note ? note.name : ""; - const legend = note ? note.legend : ""; - - const feature = {type: "Feature", geometry: {type: "Point", coordinates}, properties: {id, type, icon, name, legend}}; - json.features.push(feature); + const features = pack.markers.map(marker => { + const {i, type, icon, x, y, size, fill, stroke, size} = marker; + const coordinates = getQGIScoordinates(x, y); + const id = `marker${i}`; + const note = notes.find(note => note.id === id); + const properties = {id, type, icon, ...note, size, fill, stroke, size}; + return {type: "Feature", geometry: {type: "Point", coordinates}, properties}; }); - const name = getFileName("Markers") + ".geojson"; - downloadFile(JSON.stringify(json), name, "application/json"); + const json = {type: "FeatureCollection", features}; + + const fileName = getFileName("Markers") + ".geojson"; + downloadFile(JSON.stringify(json), fileName, "application/json"); } function getCellCoordinates(vertices) { diff --git a/modules/load.js b/modules/load.js index 98ce0b44..93af386a 100644 --- a/modules/load.js +++ b/modules/load.js @@ -344,6 +344,7 @@ function parseLoadedData(data) { pack.religions = data[29] ? JSON.parse(data[29]) : [{i: 0, name: "No religion"}]; pack.provinces = data[30] ? JSON.parse(data[30]) : [0]; pack.rivers = data[32] ? JSON.parse(data[32]) : []; + pack.markers = data[35] ? JSON.parse(data[35]) : []; const cells = pack.cells; cells.biome = Uint8Array.from(data[16].split(",")); diff --git a/modules/save.js b/modules/save.js index 040f12cb..6ebda083 100644 --- a/modules/save.js +++ b/modules/save.js @@ -1,5 +1,5 @@ "use strict"; -// Functions to save project as .map file +// functions to save project as .map file // prepare map data for saving function getMapData() { @@ -9,7 +9,32 @@ function getMapData() { const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(); const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator"; const params = [version, license, dateString, seed, graphWidth, graphHeight, mapId].join("|"); - const settings = [distanceUnitInput.value, distanceScaleInput.value, areaUnit.value, heightUnit.value, heightExponentInput.value, temperatureScale.value, barSizeInput.value, barLabel.value, barBackOpacity.value, barBackColor.value, barPosX.value, barPosY.value, populationRate, urbanization, mapSizeOutput.value, latitudeOutput.value, temperatureEquatorOutput.value, temperaturePoleOutput.value, precOutput.value, JSON.stringify(options), mapName.value, +hideLabels.checked, stylePreset.value, +rescaleLabels.checked].join("|"); + const settings = [ + distanceUnitInput.value, + distanceScaleInput.value, + areaUnit.value, + heightUnit.value, + heightExponentInput.value, + temperatureScale.value, + barSizeInput.value, + barLabel.value, + barBackOpacity.value, + barBackColor.value, + barPosX.value, + barPosY.value, + populationRate, + urbanization, + mapSizeOutput.value, + latitudeOutput.value, + temperatureEquatorOutput.value, + temperaturePoleOutput.value, + precOutput.value, + JSON.stringify(options), + mapName.value, + +hideLabels.checked, + stylePreset.value, + +rescaleLabels.checked + ].join("|"); const coords = JSON.stringify(mapCoordinates); const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|"); const notesData = JSON.stringify(notes); @@ -37,6 +62,7 @@ function getMapData() { const religions = JSON.stringify(pack.religions); const provinces = JSON.stringify(pack.provinces); const rivers = JSON.stringify(pack.rivers); + const markers = JSON.stringify(pack.markers); // store name array only if not the same as default const defaultNB = Names.getNameBases(); @@ -51,7 +77,44 @@ function getMapData() { const pop = Array.from(pack.cells.pop).map(p => rn(p, 4)); // data format as below - const mapData = [params, settings, coords, biomes, notesData, serializedSVG, gridGeneral, grid.cells.h, grid.cells.prec, grid.cells.f, grid.cells.t, grid.cells.temp, packFeatures, cultures, states, burgs, pack.cells.biome, pack.cells.burg, pack.cells.conf, pack.cells.culture, pack.cells.fl, pop, pack.cells.r, pack.cells.road, pack.cells.s, pack.cells.state, pack.cells.religion, pack.cells.province, pack.cells.crossroad, religions, provinces, namesData, rivers, rulersString, fonts].join("\r\n"); + const mapData = [ + params, + settings, + coords, + biomes, + notesData, + serializedSVG, + gridGeneral, + grid.cells.h, + grid.cells.prec, + grid.cells.f, + grid.cells.t, + grid.cells.temp, + packFeatures, + cultures, + states, + burgs, + pack.cells.biome, + pack.cells.burg, + pack.cells.conf, + pack.cells.culture, + pack.cells.fl, + pop, + pack.cells.r, + pack.cells.road, + pack.cells.s, + pack.cells.state, + pack.cells.religion, + pack.cells.province, + pack.cells.crossroad, + religions, + provinces, + namesData, + rivers, + rulersString, + fonts, + markers + ].join("\r\n"); TIME && console.timeEnd("createMapData"); return mapData; } @@ -97,7 +160,16 @@ function quickSave() { const saveReminder = function () { if (localStorage.getItem("noReminder")) return; - const message = ["Please don't forget to save your work as a .map file", "Please remember to save work as a .map file", "Saving in .map format will ensure your data won't be lost in case of issues", "Safety is number one priority. Please save the map", "Don't forget to save your map on a regular basis!", "Just a gentle reminder for you to save the map", "Please don't forget to save your progress (saving as .map is the best option)", "Don't want to be reminded about need to save? Press CTRL+Q"]; + const message = [ + "Please don't forget to save your work as a .map file", + "Please remember to save work as a .map file", + "Saving in .map format will ensure your data won't be lost in case of issues", + "Safety is number one priority. Please save the map", + "Don't forget to save your map on a regular basis!", + "Just a gentle reminder for you to save the map", + "Please don't forget to save your progress (saving as .map is the best option)", + "Don't want to be reminded about need to save? Press CTRL+Q" + ]; const interval = 15 * 60 * 1000; // remind every 15 minutes saveReminder.reminder = setInterval(() => { diff --git a/modules/ui/battle-screen.js b/modules/ui/battle-screen.js index 0a70f859..bd76f22c 100644 --- a/modules/ui/battle-screen.js +++ b/modules/ui/battle-screen.js @@ -677,7 +677,22 @@ class Battle { if (note) { const status = side === "attackers" ? battleStatus[0] : battleStatus[1]; const losses = r.a ? Math.abs(d3.sum(Object.values(r.casualties))) / r.a : 1; - const regStatus = losses === 1 ? "is destroyed" : losses > 0.8 ? "is almost completely destroyed" : losses > 0.5 ? "suffered terrible losses" : losses > 0.3 ? "suffered severe losses" : losses > 0.2 ? "suffered heavy losses" : losses > 0.05 ? "suffered significant losses" : losses > 0 ? "suffered unsignificant losses" : "left the battle without loss"; + const regStatus = + losses === 1 + ? "is destroyed" + : losses > 0.8 + ? "is almost completely destroyed" + : losses > 0.5 + ? "suffered terrible losses" + : losses > 0.3 + ? "suffered severe losses" + : losses > 0.2 + ? "suffered heavy losses" + : losses > 0.05 + ? "suffered significant losses" + : losses > 0 + ? "suffered unsignificant losses" + : "left the battle without loss"; const casualties = Object.keys(r.casualties) .map(t => (r.casualties[t] ? `${Math.abs(r.casualties[t])} ${t}` : null)) .filter(c => c); @@ -691,41 +706,32 @@ class Battle { armies.select(`g#${id} > text`).text(Military.getTotal(r)); // update reg box } - // TODO: add updated marker - // append battlefield marker - void (function addMarkerSymbol() { - if (svg.select("#defs-markers").select("#marker_battlefield").size()) return; - const symbol = svg.select("#defs-markers").append("symbol").attr("id", "marker_battlefield").attr("viewBox", "0 0 30 30"); - symbol.append("path").attr("d", "M6,19 l9,10 L24,19").attr("fill", "#000000").attr("stroke", "none"); - symbol.append("circle").attr("cx", 15).attr("cy", 15).attr("r", 10).attr("fill", "#ffffff").attr("stroke", "#000000").attr("stroke-width", 1); - symbol.append("text").attr("x", "50%").attr("y", "52%").attr("fill", "#000000").attr("stroke", "#3200ff").attr("stroke-width", 0).attr("font-size", "12px").attr("dominant-baseline", "central").text("⚔️"); - })(); + const i = last(pack.markers)?.i + 1 || 0; + { + // append battlefield marker + 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); + } - const getSide = (regs, n) => (regs.length > 1 ? `${n ? "regiments" : "forces"} of ${list([...new Set(regs.map(r => pack.states[r.state].name))])}` : getAdjective(pack.states[regs[0].state].name) + " " + regs[0].name); + const getSide = (regs, n) => + regs.length > 1 + ? `${n ? "regiments" : "forces"} of ${list([...new Set(regs.map(r => pack.states[r.state].name))])}` + : getAdjective(pack.states[regs[0].state].name) + " " + regs[0].name; const getLosses = casualties => Math.min(rn(casualties * 100), 100); const status = battleStatus[+P(0.7)]; const result = `The ${this.getTypeName(this.type)} ended in ${status}`; - const legend = `${this.name} took place in ${options.year} ${options.eraShort}. It was fought between ${getSide(this.attackers.regiments, 1)} and ${getSide(this.defenders.regiments, 0)}. ${result}. + const legend = `${this.name} took place in ${options.year} ${options.eraShort}. It was fought between ${getSide(this.attackers.regiments, 1)} and ${getSide( + this.defenders.regiments, + 0 + )}. ${result}. \r\nAttackers losses: ${getLosses(this.attackers.casualties)}%, defenders losses: ${getLosses(this.defenders.casualties)}%`; - const id = getNextId("marker"); - notes.push({id, name: this.name, legend}); + notes.push({id: `marker${i}`, name: this.name, legend}); tip(`${this.name} is over. ${result}`, true, "success", 4000); - markers - .append("use") - .attr("id", id) - .attr("xlink:href", "#marker_battlefield") - .attr("data-id", "#marker_battlefield") - .attr("data-x", this.x) - .attr("data-y", this.y) - .attr("x", this.x - 15) - .attr("y", this.y - 30) - .attr("data-size", 1) - .attr("width", 30) - .attr("height", 30); - $("#battleScreen").dialog("destroy"); this.cleanData(); } diff --git a/modules/ui/markers-overview.js b/modules/ui/markers-overview.js index 6dd0f412..cdcc754c 100644 --- a/modules/ui/markers-overview.js +++ b/modules/ui/markers-overview.js @@ -36,6 +36,7 @@ function overviewMarkers() { if (el.classList.contains("icon-pencil")) return openEditor(i); if (el.classList.contains("locks")) return toggleLockStatus(el, i); if (el.classList.contains("icon-trash-empty")) return triggerRemove(i); + // TODO: hidden attribute } function addLines() {