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

@ -1178,13 +1178,6 @@ div.states>input {
border: 0;
}
div.states>input.stateColor {
width: .9em;
height: .9em;
padding: 0px;
margin-right: -1px;
}
div.states div {
width: 3.2em;
}
@ -1425,10 +1418,21 @@ div.states > div.biomeArea {
width: 5em;
}
.zoneFill {
rect.fillRect {
stroke: #666666;
stroke-width: 2;
cursor: pointer;
}
#militaryBody div.states > div {
width: 4em;
}
#militaryBody div.states > input.militaryArmy {
width: 5em;
}
#militaryBody div.states > input.militaryFleet {
width: 3.3em;
}
#picker text {

View file

@ -1544,7 +1544,7 @@
</td>
<td>
<i data-tip="Show seed history to apply a previous seed" id="optionsMapHistory" class="icon-history"></i>
<i data-tip="Copy map seed as URL. It will produce the same map only if map was generated with default options" id="optionsCopySeed" class="icon-docs"></i>
<i data-tip="Copy map seed as URL. It will produce the same map only if options are default or the same" id="optionsCopySeed" class="icon-docs"></i>
</td>
</tr>
@ -1807,6 +1807,7 @@
<p>Click to overview:</p>
<button id="overviewBurgsButton" data-tip="Click to open Burgs Overview. Shortcut: Shift + T">Burgs</button>
<button id="overviewRiversButton" data-tip="Click to open Rivers Overview. Shortcut: Shift + V">Rivers</button>
<!-- <button id="overviewMilitaryButton" data-tip="Click to open Military Forces Overview. Shortcut: Shift + M">Military</button> -->
<button id="overviewCellsButton" data-tip="Click to open Cell details view. Shortcut: Shift + E">Cells</button>
<!-- <button id="overviewLandmassedButton" data-tip="Click to open Landmasses Overview. Shortcut: Shift + L">Landmasses</button> -->
<!-- <button id="overviewWaterbodiesButton" data-tip="Click to open Waterbodies Overview. Shortcut: Shift + W">Waterbodies</button> -->
@ -3211,6 +3212,31 @@
</div>
</div>
<div id="militaryOverview" class="dialog stable" style="display: none">
<div id="militaryHeader" class="header">
<div style="left:1.4em" data-tip="State name. Click to sort" class="sortable alphabetically" data-sortby="state">State&nbsp;</div>
<div style="left: 7.8em" data-tip="State infantry number. Click to sort" class="sortable" data-sortby="infantry">Infantry&nbsp;</div>
<div style="left: 13em" data-tip="State archers number. Click to sort" class="sortable" data-sortby="archers">Archers&nbsp;</div>
<div style="left: 18em" data-tip="State cavalry number. Click to sort" class="sortable" data-sortby="cavalry">Cavalry&nbsp;</div>
<div style="left: 23em" data-tip="Number of ships in navy. Click to sort" class="sortable" data-sortby="fleet">Fleet&nbsp;</div>
<div style="left: 27em" data-tip="Total military personnel (including ships crew). Click to sort" class="sortable icon-sort-number-down" data-sortby="total">Total&nbsp;</div>
<div style="left: 31.4em" data-tip="Military personnel rate (% of state population). Depends on diplomatic situation. Click to sort" class="sortable" data-sortby="rate">Rate&nbsp;</div>
<div style="left: 36em" data-tip="State manpower (reserve). Click to sort" class="sortable" data-sortby="reserve">Reserve&nbsp;</div>
</div>
<div id="militaryBody" class="table" data-type="absolute"></div>
<div id="militaryFooter" class="totalLine">
<div data-tip="States number" style="margin-left: 4px">States:&nbsp;<span id="militaryFooterStates">0</span></div>
<div data-tip="Average military per state" style="margin-left: 14px">Average military:&nbsp;<span id="militaryFooterAverage">0</span></div>
</div>
<div id="militaryBottom">
<button id="militaryOverviewRefresh" data-tip="Refresh the Editor" class="icon-cw"></button>
<button id="militaryExport" data-tip="Save military-related data as a text file (.csv)" class="icon-download"></button>
</div>
</div>
<div id="styleSaver" class="dialog stable textual" style="display: none">
<div id="styleSaverHeader" style="padding:2px 0">
<span>Preset name:</span>
@ -3415,6 +3441,7 @@
<script defer src="modules/ui/zones-editor.js"></script>
<script defer src="modules/ui/burgs-overview.js"></script>
<script defer src="modules/ui/rivers-overview.js"></script>
<!-- <script defer src="modules/ui/military-overview.js"></script> -->
<script defer src="modules/ui/editors.js"></script>
<script defer src="modules/ui/3d.js"></script>
<script defer src="libs/quantize.min.js"></script>

78
main.js
View file

@ -516,6 +516,7 @@ function generate() {
BurgsAndStates.drawStateLabels();
Rivers.specify();
//calculateMilitaryForces();
addMarkers();
addZones();
Names.getMapName();
@ -1162,6 +1163,83 @@ function rankCells() {
console.timeEnd('rankCells');
}
// calculate army and fleet based on state cells polulation
function calculateMilitaryForces() {
const cells = pack.cells, states = pack.states;
const valid = states.filter(s => s.i && !s.removed); // valid states
valid.forEach(s => s.military = {infantry:0, cavalry:0, archers:0, reserve:0, fleet:0});
for (const i of cells.i) {
const s = states[cells.state[i]]; // cell state
if (!s.i || s.removed) continue;
let m = cells.pop[i] / 100; // basic army is 1% of rural population
if (cells.culture[i] !== s.culture) m = s.form === "Union" ? m / 1.2 : m / 2; // non-dominant culture
if (cells.religion[i] !== cells.religion[s.center]) m = s.form === "Theocracy" ? m / 2.2 : m / 1.4; // non-dominant religion
if (cells.f[i] !== cells.f[s.center]) m = s.type === "Naval" ? m / 1.2 : m / 1.8; // different landmass
let infantry = m * .5; // basic infantry is 50% of army
let archers = m * .25; // basic archers is 25% of army
let cavalry = m * .25; // basic cavalry is 25% of army
if ([1, 2, 3, 4].includes(cells.biome[i])) {cavalry *= 3; infantry /= 5; archers /= 2;} else // "nomadic" biomes have lots of cavalry
if ([7, 8, 9, 12].includes(cells.biome[i])) {cavalry /= 2.5; infantry *= 1.2; archers *= 1.2;} // "wet" biomes have reduced number of cavalry
s.military.infantry += infantry;
s.military.archers += archers;
s.military.cavalry += cavalry;
s.military.reserve += m * 3 + cells.pop[i] * .02; // reserve is ~5% of population
}
for (const b of pack.burgs) {
if (!b.i || b.removed || !b.state) continue;
const s = states[b.state]; // burg state
let m = b.population / 50; // basic army is 2% of urban population
if (b.capital) m *= 2; // capital has household troops
if (b.culture !== s.culture) m = s.form === "Union" ? m / 1.2 : m / 2; // non-dominant culture
if (cells.religion[b.cell] !== cells.religion[s.center]) m = s.form === "Theocracy" ? m / 2.2 : m / 1.4; // non-dominant religion
if (cells.f[b.cell] !== cells.f[s.center]) m = s.type === "Naval" ? m / 1.2 : m / 1.8; // different landmass
let infantry = m * .6; // basic infantry is 60% of army
let archers = m * .3; // basic archers is 3% of army
let cavalry = m * .1; // basic cavalry is 10% of army
const biome = cells.biome[b.cell]; // burg biome
if ([1, 2, 3, 4].includes(biome)) {cavalry *= 3; infantry /= 2;} else // "nomadic" biomes have lots of cavalry
if ([7, 8, 9, 12].includes(biome)) {cavalry /= 4; infantry *= 1.2; archers *= 1.4;} // "wet" biomes have reduced number of cavalry
s.military.infantry += infantry;
s.military.archers += archers;
s.military.cavalry += cavalry;
s.military.reserve += m * 2 + b.population * .01; // reserve is ~5% of population
if (!b.port) continue; // only ports have fleet
let ships = b.capital ? b.population / 3 : b.population / 5; // ~1 ship per 5 population points
if (s.type === "Naval") ships *= 1.8; // "naval" states have more ships
s.military.fleet += ~~ships + +P(ships % 1);
}
const expn = d3.sum(valid.map(s => s.expansionism)); // total expansion
const area = d3.sum(valid.map(s => s.area)); // total area
const rate = {x:0, Ally:-.2, Friendly:-.1, Neutral:0, Suspicion:.1, Enemy:1, Unknown:0, Rival:.5, Vassal:.5, Suzerain:-.5};
valid.forEach(s => {
const m = s.military, d = s.diplomacy;
const expansionRate = Math.min(Math.max((s.expansionism / expn) / (s.area / area), .25), 4); // how much state expansionism is relized
const diplomacyRate = d.some(d => d === "Enemy") ? 1 : d.some(d => d === "Rival") ? .8 : d.some(d => d === "Suspicion") ? .5 : .1; // peacefulness
const neighborsRate = Math.min(Math.max(s.neighbors.map(n => n ? pack.states[n].diplomacy[s.i] : "Suspicion").reduce((s, r) => s += rate[r], .5), .3), 3); // neighbors rate
m.alert = rn(expansionRate * diplomacyRate * neighborsRate, 2); // war alert rate (army modifier)
m.infantry = rn(m.infantry * m.alert, 3);
m.cavalry = rn(m.cavalry * m.alert, 3);
m.archers = rn(m.archers * m.alert, 3);
m.reserve = rn(m.reserve, 3);
});
console.table(valid.map(s=>[s.name, s.military.alert, s.military.infantry, s.military.archers, s.military.cavalry, s.military.reserve, rn(s.military.reserve/(s.urban+s.rural)*100,2)+"%", s.military.fleet]));
}
// generate some markers
function addMarkers(number = 1) {
if (!number) return;

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,7 +112,7 @@ 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>
<input data-tip="State form name. Click to change" class="stateForm name pointer" value="${s.formName}" readonly>

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";