diff --git a/index.html b/index.html index 19795b6a..cb550137 100644 --- a/index.html +++ b/index.html @@ -7864,10 +7864,10 @@ - + - + @@ -7886,7 +7886,7 @@ - + diff --git a/main.js b/main.js index 82787684..e201f7fe 100644 --- a/main.js +++ b/main.js @@ -2038,6 +2038,8 @@ const regenerateMap = debounce(async function (options) { customization = 0; resetZoom(1000); undraw(); + pack.religions = []; + pack.cultures = []; await generate(options); restoreLayers(); if (ThreeD.options.isOn) ThreeD.redraw(); diff --git a/modules/cultures-generator.js b/modules/cultures-generator.js index b167b88e..1c0e07a7 100644 --- a/modules/cultures-generator.js +++ b/modules/cultures-generator.js @@ -118,8 +118,8 @@ window.Cultures = (function () { function selectCultures(culturesNumber) { let def = getDefault(culturesNumber); - const cultures = []; + pack.cultures?.forEach(function (culture) { if (culture.lock) cultures.push(culture); }); diff --git a/modules/dynamic/editors/cultures-editor.js b/modules/dynamic/editors/cultures-editor.js index 3f8018d6..ac323573 100644 --- a/modules/dynamic/editors/cultures-editor.js +++ b/modules/dynamic/editors/cultures-editor.js @@ -519,10 +519,11 @@ function cultureRegenerateBurgs() { } function removeCulture(cultureId) { + // and the Folk religion cults.select("#culture" + cultureId).remove(); debug.select("#cultureCenter" + cultureId).remove(); - const {burgs, states, cells, cultures} = pack; + const {burgs, states, cells, cultures, religions} = pack; burgs.filter(b => b.culture == cultureId).forEach(b => (b.culture = 0)); states.forEach(s => { @@ -531,7 +532,11 @@ function removeCulture(cultureId) { cells.culture.forEach((c, i) => { if (c === cultureId) cells.culture[i] = 0; }); + cells.religion.forEach((r, i) => { + if (r === cultureId) cells.religion[i] = 0; + }) cultures[cultureId].removed = true; + religions[cultureId].removed = true; cultures .filter(c => c.i && !c.removed) @@ -539,6 +544,12 @@ function removeCulture(cultureId) { c.origins = c.origins.filter(origin => origin !== cultureId); if (!c.origins.length) c.origins = [0]; }); + religions + .filter(r => r.i && !r.removed) + .forEach(r => { + r.origins = r.origins.filter(origin => origin !== cultureId); + if (!r.origins.length) r.origins = [0]; + }); refreshCulturesEditor(); } @@ -548,7 +559,7 @@ function cultureRemovePrompt() { const cultureId = +this.parentNode.dataset.id; confirmationDialog({ title: "Remove culture", - message: "Are you sure you want to remove the culture?
This action cannot be reverted", + message: "Are you sure you want to remove the culture?
The linked folk religion will also be removed.
This action cannot be reverted", confirm: "Remove", onConfirm: () => removeCulture(cultureId) }); @@ -823,6 +834,7 @@ function addCulture() { if (d3.event.shiftKey === false) exitAddCultureMode(); Cultures.add(center); + Religions.addFolk(center); drawCultureCenters(); culturesEditorAddLines(); diff --git a/modules/dynamic/editors/religions-editor.js b/modules/dynamic/editors/religions-editor.js index 45d9886f..8a92addc 100644 --- a/modules/dynamic/editors/religions-editor.js +++ b/modules/dynamic/editors/religions-editor.js @@ -3,11 +3,11 @@ addListeners(); export function open() { closeDialogs("#religionsEditor, .stable"); + if (!layerIsOn("toggleReligions")) toggleReligions(); if (layerIsOn("toggleStates")) toggleStates(); if (layerIsOn("toggleBiomes")) toggleBiomes(); if (layerIsOn("toggleCultures")) toggleCultures(); if (layerIsOn("toggleProvinces")) toggleProvinces(); - if (!layerIsOn("toggleReligions")) toggleReligions(); refreshReligionsEditor(); drawReligionCenters(); @@ -23,13 +23,15 @@ export function open() { function insertEditorHtml() { const editorHtml = /* html */ `
-
+
Religion 
Type 
Form 
Supreme Deity 
Area 
Believers 
+
Potential 
+
Expansion 
@@ -88,6 +90,11 @@ function insertEditorHtml() {
+ + + + +
`; @@ -109,6 +116,7 @@ function addListeners() { byId("religionsManuallyCancel").on("click", () => exitReligionsManualAssignment()); byId("religionsAdd").on("click", enterAddReligionMode); byId("religionsExport").on("click", downloadReligionsCsv); + byId("religionsRecalculate").on("click", () => recalculateReligions(true)); } function refreshReligionsEditor() { @@ -166,6 +174,7 @@ function religionsEditorAddLines() { data-type="" data-form="" data-deity="" + data-expansion="" data-expansionism="" > @@ -181,6 +190,9 @@ function religionsEditorAddLines() {
${si(area) + unit}
${si(population)}
+ + + `; continue; } @@ -195,14 +207,21 @@ function religionsEditorAddLines() { data-type="${r.type}" data-form="${r.form}" data-deity="${r.deity || ""}" + data-expansion="${r.expansion}" data-expansionism="${r.expansionism}" > - ${getTypeOptions(r.type)} - + ` + } @@ -212,11 +231,37 @@ function religionsEditorAddLines() {
${si(area) + unit}
${si(population)}
+ ${r.type === "Folk" ? + ` + culture + + + - + ` + : + ` + + + + ` + } `; } $body.innerHTML = lines; @@ -245,6 +290,8 @@ function religionsEditorAddLines() { $body.querySelectorAll("div > input.religionDeity").forEach(el => el.on("input", religionChangeDeity)); $body.querySelectorAll("div > span.icon-arrows-cw").forEach(el => el.on("click", regenerateDeity)); $body.querySelectorAll("div > div.religionPopulation").forEach(el => el.on("click", changePopulation)); + $body.querySelectorAll("div > select.religionExtent").forEach(el => el.on("change", religionChangeExtent)); + $body.querySelectorAll("div > input.religionExpan").forEach(el => el.on("change", religionChangeExpansionism)); $body.querySelectorAll("div > span.icon-trash-empty").forEach(el => el.on("click", religionRemovePrompt)); $body.querySelectorAll("div > span.icon-lock").forEach($el => $el.on("click", updateLockStatus)); $body.querySelectorAll("div > span.icon-lock-open").forEach($el => $el.on("click", updateLockStatus)); @@ -259,7 +306,14 @@ function religionsEditorAddLines() { function getTypeOptions(type) { let options = ""; - const types = ["Folk", "Organized", "Cult", "Heresy"]; + const types = ["Organized", "Cult", "Heresy"]; + types.forEach(t => (options += ``)); + return options; +} + +function getExtentOptions(type) { + let options = ""; + const types = ["global", "state", "culture"]; types.forEach(t => (options += ``)); return options; } @@ -434,6 +488,20 @@ function changePopulation() { } } +function religionChangeExtent() { + const religion = +this.parentNode.dataset.id; + this.parentNode.dataset.expansion = this.value; + pack.religions[religion].expansion = this.value; + recalculateReligions(); +} + +function religionChangeExpansionism() { + const religion = +this.parentNode.dataset.id; + this.parentNode.dataset.expansionism = this.value; + pack.religions[religion].expansionism = +this.value; + recalculateReligions(); +} + function religionRemovePrompt() { if (customization) return; @@ -507,6 +575,7 @@ function religionCenterDrag() { const cell = findCell(x, y); if (pack.cells.h[cell] < 20) return; // ignore dragging on water pack.religions[religionId].center = cell; + recalculateReligions(); }); } @@ -584,7 +653,7 @@ function enterReligionsManualAssignent() { if (!layerIsOn("toggleReligions")) toggleReligions(); customization = 7; relig.append("g").attr("id", "temp"); - document.querySelectorAll("#religionsBottom > button").forEach(el => (el.style.display = "none")); + document.querySelectorAll("#religionsBottom > *").forEach(el => (el.style.display = "none")); byId("religionsManuallyButtons").style.display = "inline-block"; debug.select("#religionCenters").style("display", "none"); @@ -686,7 +755,7 @@ function exitReligionsManualAssignment(close) { customization = 0; relig.select("#temp").remove(); removeCircle(); - document.querySelectorAll("#religionsBottom > button").forEach(el => (el.style.display = "inline-block")); + document.querySelectorAll("#religionsBottom > *").forEach(el => (el.style.display = "inline-block")); byId("religionsManuallyButtons").style.display = "none"; byId("religionsEditor") @@ -740,15 +809,15 @@ function addReligion() { function downloadReligionsCsv() { const unit = getAreaUnit("2"); - const headers = `Id,Name,Color,Type,Form,Supreme Deity,Area ${unit},Believers,Origins`; + const headers = `Id,Name,Color,Type,Form,Supreme Deity,Area ${unit},Believers,Origins,Potential,Expansionism`; const lines = Array.from($body.querySelectorAll(":scope > div")); const data = lines.map($line => { - const {id, name, color, type, form, deity, area, population} = $line.dataset; + const {id, name, color, type, form, deity, area, population, expansion, expansionism} = $line.dataset; const deityText = '"' + deity + '"'; const {origins} = pack.religions[+id]; const originList = (origins || []).filter(origin => origin).map(origin => pack.religions[origin].name); const originText = '"' + originList.join(", ") + '"'; - return [id, name, color, type, form, deityText, area, population, originText].join(","); + return [id, name, color, type, form, deityText, area, population, originText, expansion, expansionism].join(","); }); const csvData = [headers].concat(data).join("\n"); @@ -773,3 +842,13 @@ function updateLockStatus() { classList.toggle("icon-lock-open"); classList.toggle("icon-lock"); } + +function recalculateReligions(must) { + if (!must && !religionsAutoChange.checked) return; + + Religions.recalculate(); + + drawReligions(); + refreshReligionsEditor(); + drawReligionCenters(); +} diff --git a/modules/religions-generator.js b/modules/religions-generator.js index 1e85b11d..84d09f67 100644 --- a/modules/religions-generator.js +++ b/modules/religions-generator.js @@ -678,6 +678,7 @@ window.Religions = (function () { const cultureId = cells.culture[cellId]; religionIds[cellId] = cultureToReligionMap.get(cultureId) || 0; } + } return religionIds; } @@ -699,6 +700,32 @@ window.Religions = (function () { pack.cells.religion = newReligionIds; } + function checkCenters() { + const cells = pack.cells; + pack.religions.forEach(r => { + if (!r.i) return; + // move religion center if it's not within religion area after expansion + if (r.type==="Folk" || cells.religion[r.center] === r.i) return; // in area, or non-expanding + const firstCell = cells.i.find(i => cells.religion[i] === r.i); + if (firstCell) r.center = firstCell; // move center, othervise it's an extinct religion + }); + } + + function recalculate() { + const {religion, culture} = pack.cells; + // start with the culutres map, but also keep locked religions + for(const i of pack.cells.i){ + if( !pack.religions[religion[i]]?.lock ){ + religion[i] = culture[i]; + } + } + + expandReligions(); + expandHeresies(); + + checkCenters(); + } + const add = function (center) { const {cells, religions} = pack; const religionId = cells.religion[center]; @@ -749,10 +776,122 @@ window.Religions = (function () { cells.religion[center] = i; }; + const addFolk = function (center) { + const {cultures, religions, cells} = pack; + + const c = cultures.find(c => !c.removed && c.center === center); + const codes = religions.map(r => r.code); + const newFolk = createFolk(c, codes); + + if(c.i < religions.length){ + // move an existing organized religion to the end of the array + const rCargo = religions[c.i]; + if(!rCargo.removed && rCargo.type != "Folk") { + const newId = religions.length; + rCargo.i = newId; + + for(const i of cells.i) { + if(cells.religion[i] = c.i) { + cells.religion[i] = newId; + } + } + religions.forEach(r => { + if (r.i === 0) return; + for(let j = 0; j < r.origins.length; j++) { + if(r.origins[j] === c.i) { + r.origins[j] === newId; + return; + } + } + }); + + religions.push(rCargo); + } + + religions[c.i] = newFolk; + } + else religions.push(newFolk); + }; + function updateCultures() { - pack.religions = pack.religions.map((religion, index) => { - if (index === 0) return religion; - return {...religion, culture: pack.cells.culture[religion.center]}; + TIME && console.time("updateCulturesForReligions"); + const {religions, cultures, cells} = pack; + + const tReligions = []; + const spareCovenants = []; + const codes = religions.filter(r => !r.removed).map(r => r.code); + + tReligions.push(religions[0]); + for (let i = 1; i < cultures.length; i++) { + const faith = religions.find(r => r.i === i); + if (faith && !faith.removed) { + if (faith.type === "Folk") { + tReligions.push(faith); + continue; + } + else spareCovenants.push(faith); + } + const newFolk = createFolk(cultures[i], codes); + tReligions.push(newFolk); + codes.push(newFolk.code); + } + for (let i = cultures.length; i < religions.length; i++) { + const faith = religions.find(r => r.i === i); + if (faith) { + if (faith.type === "Folk" && !faith.lock) + tReligions.push({...faith, removed: true}); + else tReligions.push(faith); + } + else tReligions.push({ + i, + name: "filler index", + origins: [null], + removed: true + }); + } + + const updateMap = []; + for (let k = 0; k < spareCovenants.length; k++) { + const sc = spareCovenants[k]; + const newId = tReligions.length; + + for (const i of cells.i) { + if (cells.religion[i] = sc.i) { + cells.religion[i] = newId; + } + } + + updateMap.push({oldId: sc.i, newId}); + tReligions.forEach(r => { + if (r.i === 0) return; + for (let i = 0; i < r.origins.length; i++) { + if (r.origins[i] === sc.i) { + r.origins[i] === newId; + return; + } + } + }); + // update origins from other spareCovenants + for (let i = 0; i < sc.origins.length; i++) { + const changeRule = updateMap.find(u => u.oldId === sc.origins[i]) + if (changeRule) sc.origins[i] = changeRule.newId; + } + tReligions.push({...sc, i: newId}); + } + + pack.religions = tReligions; + + pack.religions.forEach(r => { + if (r.i === 0) return; + + if (r.origins?.length < 1) r.origins = [0]; + + if (r.type === "Folk" && cultures[r.i]) { + r.center = cultures[r.i].center; + } + else { + r.culture = cells.culture[r.center]; + } }); } diff --git a/modules/ui/editors.js b/modules/ui/editors.js index 23798861..def092fe 100644 --- a/modules/ui/editors.js +++ b/modules/ui/editors.js @@ -1188,6 +1188,6 @@ async function editCultures() { async function editReligions() { if (customization) return; - const Editor = await import("../dynamic/editors/religions-editor.js?v=1.88.07"); + const Editor = await import("../dynamic/editors/religions-editor.js?v=1.90.00"); Editor.open(); } diff --git a/versioning.js b/versioning.js index c901a46a..32386e54 100644 --- a/versioning.js +++ b/versioning.js @@ -28,6 +28,7 @@ const version = "1.89.08"; // generator version, update each time