This commit is contained in:
Azgaar 2019-12-15 13:50:09 +03:00
parent 07bc3dee33
commit e3e2de9e9b
15 changed files with 255 additions and 32 deletions

View file

@ -35,7 +35,7 @@ function editBiomes() {
body.addEventListener("click", function(ev) {
const el = ev.target, cl = el.classList;
if (cl.contains("zoneFill")) biomeChangeColor(el); else
if (cl.contains("fillRect")) biomeChangeColor(el); else
if (cl.contains("icon-info-circled")) openWiki(el); else
if (cl.contains("icon-trash-empty")) removeCustomBiome(el);
if (customization === 6) selectBiomeOnLineClick(el);
@ -87,7 +87,7 @@ function editBiomes() {
lines += `<div class="states biomes" data-id="${i}" data-name="${b.name[i]}" data-habitability="${b.habitability[i]}"
data-cells=${b.cells[i]} data-area=${area} data-population=${population} data-color=${b.color[i]}>
<svg data-tip="Biomes fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${b.color[i]}" class="zoneFill"></svg>
<svg data-tip="Biomes fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${b.color[i]}" class="fillRect pointer"></svg>
<input data-tip="Biome name. Click and type to change" class="biomeName" value="${b.name[i]}" autocorrect="off" spellcheck="false">
<span data-tip="Biome habitability percent" class="hide">%</span>
<input data-tip="Biome habitability percent. Click and set new value to change" type="number" min=0 max=9999 class="biomeHabitability hide" value=${b.habitability[i]}>
@ -230,7 +230,7 @@ function editBiomes() {
const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value;
const line = `<div class="states biomes" data-id="${i}" data-name="${b.name[i]}" data-habitability=${b.habitability[i]} data-cells=0 data-area=0 data-population=0 data-color=${b.color[i]}>
<svg data-tip="Biomes fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${b.color[i]}" class="zoneFill"></svg>
<svg data-tip="Biomes fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${b.color[i]}" class="fillRect pointer"></svg>
<input data-tip="Biome name. Click and type to change" class="biomeName" value="${b.name[i]}" autocorrect="off" spellcheck="false">
<span data-tip="Biome habitability percent" class="hide">%</span>
<input data-tip="Biome habitability percent. Click and set new value to change" type="number" min=0 max=9999 step=1 class="biomeHabitability hide" value=${b.habitability[i]}>

View file

@ -92,7 +92,7 @@ function editCultures() {
lines += `<div class="states cultures" data-id=${c.i} data-name="${c.name}" data-color="${c.color}" data-cells=${c.cells}
data-area=${area} data-population=${population} data-base=${c.base} data-type=${c.type} data-expansionism=${c.expansionism}>
<svg data-tip="Culture fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${c.color}" class="zoneFill"></svg>
<svg data-tip="Culture fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${c.color}" class="fillRect pointer"></svg>
<input data-tip="Culture name. Click and type to change" class="cultureName" value="${c.name}" autocorrect="off" spellcheck="false">
<span data-tip="Cells count" class="icon-check-empty hide"></span>
<div data-tip="Cells count" class="stateCells hide">${c.cells}</div>
@ -122,7 +122,7 @@ function editCultures() {
body.querySelectorAll("div.cultures").forEach(el => el.addEventListener("mouseenter", ev => cultureHighlightOn(ev)));
body.querySelectorAll("div.cultures").forEach(el => el.addEventListener("mouseleave", ev => cultureHighlightOff(ev)));
body.querySelectorAll("div.states").forEach(el => el.addEventListener("click", selectCultureOnLineClick));
body.querySelectorAll("rect.zoneFill").forEach(el => el.addEventListener("click", cultureChangeColor));
body.querySelectorAll("rect.fillRect").forEach(el => el.addEventListener("click", cultureChangeColor));
body.querySelectorAll("div > input.cultureName").forEach(el => el.addEventListener("input", cultureChangeName));
body.querySelectorAll("div > input.statePower").forEach(el => el.addEventListener("input", cultureChangeExpansionism));
body.querySelectorAll("div > select.cultureType").forEach(el => el.addEventListener("change", cultureChangeType));

View file

@ -70,7 +70,7 @@ function editDiplomacy() {
lines += `<div class="states" data-id=${s.i} data-name="${s.fullName}" data-relations="${relation}">
<div data-tip="${tipSelect}" style="width:12em">${s.fullName}</div>
<svg data-tip="${tipChange}" width=".9em" height=".9em" style="margin-bottom:-1px" class="changeRelations">
<rect x="0" y="0" width="100%" height="100%" fill="${color}" class="zoneFill" style="pointer-events: none"></rect>
<rect x="0" y="0" width="100%" height="100%" fill="${color}" class="fillRect pointer" style="pointer-events: none"></rect>
</svg>
<input data-tip="${tipChange}" class="changeRelations diplomacyRelations" value="${relation}" readonly/>
</div>`;

View file

@ -341,6 +341,7 @@ document.addEventListener("keyup", event => {
else if (shift && key === 79) editNotes(); // Shift + "O" to edit Notes
else if (shift && key === 84) overviewBurgs(); // Shift + "T" to open Burgs overview
else if (shift && key === 86) overviewRivers(); // Shift + "V" to open Rivers overview
//else if (shift && key === 77) overviewMilitary(); // Shift + "M" to open Military overview
else if (shift && key === 69) viewCellDetails(); // Shift + "E" to open Cell Details
else if (shift && key === 49) toggleAddBurg(); // Shift + "1" to click to add Burg

View file

@ -0,0 +1,111 @@
"use strict";
function overviewMilitary() {
if (customization) return;
closeDialogs("#militaryOverview, .stable");
if (!layerIsOn("toggleStates")) toggleStates();
if (!layerIsOn("toggleBorders")) toggleBorders();
const body = document.getElementById("militaryBody");
militaryOverviewAddLines();
$("#militaryOverview").dialog();
if (modules.overviewMilitary) return;
modules.overviewMilitary = true;
$("#militaryOverview").dialog({
title: "Military Overview", resizable: false, width: fitContent(),
position: {my: "right top", at: "right-10 top+10", of: "svg", collision: "fit"}
});
// add listeners
document.getElementById("militaryOverviewRefresh").addEventListener("click", militaryOverviewAddLines);
document.getElementById("militaryExport").addEventListener("click", downloadMilitaryData);
// add line for each river
function militaryOverviewAddLines() {
body.innerHTML = "";
let lines = "", militaryTotal = 0;
const states = pack.states.filter(s => s.i && !s.removed);
const popRate = +populationRate.value;
for (const s of states) {
const total = (s.military.infantry + s.military.cavalry + s.military.archers + s.military.fleet / 10);
const rate = total / (s.rural + s.urban * urbanization.value) * 100;
militaryTotal += total;
lines += `<div class="states" data-id=${s.i} data-state="${s.name}" data-infantry="${s.military.infantry}"
data-archers="${s.military.archers}" data-cavalry="${s.military.cavalry}" data-reserve="${s.military.reserve}"
data-fleet="${s.military.fleet}" data-rate="${rate}" data-total="${total}">
<svg data-tip="State color" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${s.color}" class="fillRect"></svg>
<input data-tip="State name" class="stateName" value="${s.name}" readonly>
<input data-tip="State infantry number" type="number" class="militaryArmy" min=0 step=1 value="${rn(s.military.infantry * popRate)}">
<input data-tip="State archers number" type="number" class="militaryArmy" min=0 step=1 value="${rn(s.military.archers * popRate)}">
<input data-tip="State cavalry number" type="number" class="militaryArmy" min=0 step=1 value="${rn(s.military.cavalry * popRate)}">
<input data-tip="Number of ships in state navy" class="militaryFleet" type="number" min=0 step=1 value="${s.military.fleet}">
<div data-tip="Total military personnel (including ships crew)">${si(total * popRate)}</div>
<div data-tip="Armed forces personnel (% of state population). Depends on diplomatic situation">${rn(rate, 2)}%</div>
<div data-tip="State manpower (reserve)">${si(s.military.reserve * popRate)}</div>
</div>`;
}
body.insertAdjacentHTML("beforeend", lines);
// update footer
militaryFooterStates.innerHTML = states.length;
militaryFooterAverage.innerHTML = si(militaryTotal / states.length * popRate);
// add listeners
body.querySelectorAll("div.states").forEach(el => el.addEventListener("mouseenter", ev => stateHighlightOn(ev)));
body.querySelectorAll("div.states").forEach(el => el.addEventListener("mouseleave", ev => stateHighlightOff(ev)));
applySorting(militaryHeader);
}
function stateHighlightOn(event) {
if (!layerIsOn("toggleStates")) return;
const state = +event.target.dataset.id;
if (customization || !state) return;
const path = regions.select("#state"+state).attr("d");
debug.append("path").attr("class", "highlight").attr("d", path)
.attr("fill", "none").attr("stroke", "red").attr("stroke-width", 1).attr("opacity", 1)
.attr("filter", "url(#blur1)").call(transition);
}
function transition(path) {
const duration = (path.node().getTotalLength() + 5000) / 2;
path.transition().duration(duration).attrTween("stroke-dasharray", tweenDash);
}
function tweenDash() {
const l = this.getTotalLength();
const i = d3.interpolateString("0," + l, l + "," + l);
return t => i(t);
}
function removePath(path) {
path.transition().duration(1000).attr("opacity", 0).remove();
}
function stateHighlightOff() {
debug.selectAll(".highlight").each(function(el) {
d3.select(this).call(removePath);
});
}
function downloadMilitaryData() {
let data = "Id,River,Type,Length,Basin\n"; // headers
body.querySelectorAll(":scope > div").forEach(function(el) {
data += el.dataset.id + ",";
data += el.dataset.name + ",";
data += el.dataset.type + ",";
data += el.querySelector(".biomeArea").innerHTML + ",";
data += el.dataset.basin + "\n";
});
const name = getFileName("Military") + ".csv";
downloadFile(data, name);
}
}

View file

@ -219,11 +219,12 @@ function restoreDefaultZoomExtent() {
}
function copyMapURL() {
const search = `?seed=${optionsSeed.value}&width=${graphWidth}&height=${graphHeight}`;
const locked = document.querySelectorAll("i.icon-lock").length; // check if some options are locked
const search = `?seed=${optionsSeed.value}&width=${graphWidth}&height=${graphHeight}${locked?'':'&options=default'}`;
navigator.clipboard.writeText("https://azgaar.github.io/Fantasy-Map-Generator/"+search)
.then(() => {
tip("Map URL is copied to clipboard", false, "success", 3000);
window.history.pushState({}, null, search);
//window.history.pushState({}, null, search);
})
.catch(err => tip("Could not copy URL: "+err, false, "error", 5000));
}
@ -323,12 +324,13 @@ function applyStoredOptions() {
const height = +params.get("height");
if (width) mapWidthInput.value = width;
if (height) mapHeightInput.value = height;
//window.history.pushState({}, null, "?");
}
// randomize options if randomization is allowed (not locked or default=1)
// randomize options if randomization is allowed (not locked or options='default')
function randomizeOptions() {
Math.seedrandom(seed); // reset seed to initial one
const randomize = new URL(window.location.href).searchParams.get("seed"); // ignore stored options if seed is provided
const randomize = new URL(window.location.href).searchParams.get("options") === "default"; // ignore stored options
// 'Options' settings
if (randomize || !locked("template")) randomizeHeightmapTemplate();

View file

@ -35,7 +35,7 @@ function editProvinces() {
body.addEventListener("click", function(ev) {
if (customization) return;
const el = ev.target, cl = el.classList, line = el.parentNode, p = +line.dataset.id;
if (cl.contains("zoneFill")) changeFill(el); else
if (cl.contains("fillRect")) changeFill(el); else
if (cl.contains("name")) editProvinceName(p); else
if (cl.contains("icon-fleur")) provinceOpenCOA(ev, p); else
if (cl.contains("icon-star-empty")) capitalZoomIn(p); else
@ -114,7 +114,7 @@ function editProvinces() {
const separable = p.burg && p.burg !== pack.states[p.state].capital;
const focused = defs.select("#fog #focusProvince"+p.i).size();
lines += `<div class="states" data-id=${p.i} data-name=${p.name} data-form=${p.formName} data-color="${p.color}" data-capital="${capital}" data-state="${stateName}" data-area=${area} data-population=${population}>
<svg data-tip="Province fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${p.color}" class="zoneFill"></svg>
<svg data-tip="Province fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${p.color}" class="fillRect pointer"></svg>
<input data-tip="Province name. Click to change" class="name pointer" value="${p.name}" readonly>
<span data-tip="Click to open province COA in the Iron Arachne Heraldry Generator. Ctrl + click to change the seed" class="icon-fleur pointer hide"></span>
<input data-tip="Province form name. Click to change" class="name pointer hide" value="${p.formName}" readonly>

View file

@ -73,7 +73,7 @@ function editReligions() {
if (r.i) {
lines += `<div class="states religions" data-id=${r.i} data-name="${r.name}" data-color="${r.color}" data-area=${area}
data-population=${population} data-type=${r.type} data-form=${r.form} data-deity="${r.deity?r.deity:''}" data-expansionism=${r.expansionism}>
<svg data-tip="Religion fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${r.color}" class="zoneFill"></svg>
<svg data-tip="Religion fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${r.color}" class="fillRect pointer"></svg>
<input data-tip="Religion name. Click and type to change" class="religionName" value="${r.name}" autocorrect="off" spellcheck="false">
<select data-tip="Religion type" class="religionType">${getTypeOptions(r.type)}</select>
<input data-tip="Religion form" class="religionForm hide" value="${r.form}" autocorrect="off" spellcheck="false">
@ -118,7 +118,7 @@ function editReligions() {
body.querySelectorAll("div.religions").forEach(el => el.addEventListener("mouseenter", ev => religionHighlightOn(ev)));
body.querySelectorAll("div.religions").forEach(el => el.addEventListener("mouseleave", ev => religionHighlightOff(ev)));
body.querySelectorAll("div.states").forEach(el => el.addEventListener("click", selectReligionOnLineClick));
body.querySelectorAll("rect.zoneFill").forEach(el => el.addEventListener("click", religionChangeColor));
body.querySelectorAll("rect.fillRect").forEach(el => el.addEventListener("click", religionChangeColor));
body.querySelectorAll("div > input.religionName").forEach(el => el.addEventListener("input", religionChangeName));
body.querySelectorAll("div > select.religionType").forEach(el => el.addEventListener("change", religionChangeType));
body.querySelectorAll("div > input.religionForm").forEach(el => el.addEventListener("input", religionChangeForm));

View file

@ -40,7 +40,7 @@ function editStates() {
body.addEventListener("click", function(ev) {
const el = ev.target, cl = el.classList, line = el.parentNode, state = +line.dataset.id;
if (cl.contains("zoneFill")) stateChangeFill(el); else
if (cl.contains("fillRect")) stateChangeFill(el); else
if (cl.contains("name")) editStateName(state); else
if (cl.contains("icon-fleur")) stateOpenCOA(ev, state); else
if (cl.contains("icon-star-empty")) stateCapitalZoomIn(state); else
@ -112,9 +112,9 @@ function editStates() {
const capital = pack.burgs[s.capital].name;
lines += `<div class="states" data-id=${s.i} data-name="${s.name}" data-form="${s.formName}" data-capital="${capital}" data-color="${s.color}" data-cells=${s.cells}
data-area=${area} data-population=${population} data-burgs=${s.burgs} data-culture=${pack.cultures[s.culture].name} data-type=${s.type} data-expansionism=${s.expansionism}>
<svg data-tip="State fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${s.color}" class="zoneFill"></svg>
<svg data-tip="State fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${s.color}" class="fillRect pointer"></svg>
<input data-tip="State name. Click to change" class="stateName name pointer" value="${s.name}" readonly>
<span data-tip="Click to open state COA in the Iron Arachne Heraldry Generator. Ctrl + click to change the seed" class="icon-fleur pointer hide"></span>
<span data-tip="Click to open state COA in the Iron Arachne Heraldry Generator. Ctrl + click to change the seed" class="icon-fleur pointer hide"></span>
<input data-tip="State form name. Click to change" class="stateForm name pointer" value="${s.formName}" readonly>
<span data-tip="State capital. Click to zoom into view" class="icon-star-empty pointer hide"></span>
<input data-tip="Capital name. Click and type to rename" class="stateCapital hide" value="${capital}" autocorrect="off" spellcheck="false"/>

View file

@ -20,6 +20,7 @@ toolsContent.addEventListener("click", function(event) {
if (button === "editZonesButton") editZones(); else
if (button === "overviewBurgsButton") overviewBurgs(); else
if (button === "overviewRiversButton") overviewRivers(); else
if (button === "overviewMilitaryButton") overviewMilitary(); else
if (button === "overviewCellsButton") viewCellDetails();
// Click to Regenerate buttons

View file

@ -31,7 +31,7 @@ function editZones() {
if (cl.contains("icon-trash-empty")) {zoneRemove(zone); return;}
if (cl.contains("icon-eye")) {toggleVisibility(el); return;}
if (cl.contains("icon-pin")) {focusOnZone(zone, cl); return;}
if (cl.contains("zoneFill")) {changeFill(el); return;}
if (cl.contains("fillRect")) {changeFill(el); return;}
if (customization) selectZone(el);
});
@ -58,7 +58,7 @@ function editZones() {
const focused = defs.select("#fog #focus"+this.id).size();
lines += `<div class="states" data-id="${this.id}" data-fill="${fill}" data-description="${description}" data-cells=${c.length} data-area=${area} data-population=${population}>
<svg data-tip="Zone fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${fill}" class="zoneFill"></svg>
<svg data-tip="Zone fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${fill}" class="fillRect pointer"></svg>
<input data-tip="Zone description. Click and type to change" class="religionName" value="${description}" autocorrect="off" spellcheck="false">
<span data-tip="Cells count" class="icon-check-empty hide"></span>
<div data-tip="Cells count" class="stateCells hide">${c.length}</div>
@ -314,7 +314,7 @@ function editZones() {
const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value;
const line = `<div class="states" data-id="${id}" data-fill="${fill}" data-description="${description}" data-cells=0 data-area=0 data-population=0>
<svg data-tip="Zone fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${fill}" class="zoneFill"></svg>
<svg data-tip="Zone fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${fill}" class="fillRect pointer"></svg>
<input data-tip="Zone description. Click and type to change" class="religionName" value="${description}" autocorrect="off" spellcheck="false">
<span data-tip="Cells count" class="icon-check-empty hide"></span>
<div data-tip="Cells count" class="stateCells hide">0</div>

View file

@ -396,9 +396,8 @@ function getAdjective(string) {
const end = string.slice(-1); // last letter of string
if (end === "a") return string += "n";
if (end === "i") return string += "an";
if (end === "o") return string = trimVowels(string) + "an";
if (end === "c" || end === "y" || end === "u") return string += "an";
if (vowel(end) || end === "c") return string += "an"; // ceiuy
if (end === "m" || end === "n") return string += "ese";
if (end === "q") return string += "i";
return trimVowels(string) + "ian";