mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-24 13:01:24 +01:00
merge completed... now to fix all the bugs...
This commit is contained in:
commit
87c4d80fbc
3472 changed files with 466748 additions and 6517 deletions
|
|
@ -1,15 +1,15 @@
|
|||
// module to control the Tools options (click to edit, to re-geenerate, tp add)
|
||||
'use strict';
|
||||
// module to control the Tools options (click to edit, to re-geenerate, tp add)
|
||||
|
||||
toolsContent.addEventListener('click', function (event) {
|
||||
if (customization) {
|
||||
tip('Please exit the customization mode first', false, 'warning');
|
||||
return;
|
||||
}
|
||||
if (event.target.tagName !== 'BUTTON') return;
|
||||
if (!['BUTTON', 'I'].includes(event.target.tagName)) return;
|
||||
const button = event.target.id;
|
||||
|
||||
// Click to open Editor buttons
|
||||
// click on open Editor buttons
|
||||
if (button === 'editHeightmapButton') editHeightmap();
|
||||
else if (button === 'editBiomesButton') editBiomes();
|
||||
else if (button === 'editStatesButton') editStates();
|
||||
|
|
@ -17,7 +17,6 @@ toolsContent.addEventListener('click', function (event) {
|
|||
else if (button === 'editDiplomacyButton') editDiplomacy();
|
||||
else if (button === 'editCulturesButton') editCultures();
|
||||
else if (button === 'editReligions') editReligions();
|
||||
else if (button === 'editResources') editResources();
|
||||
else if (button === 'editEmblemButton') openEmblemEditor();
|
||||
else if (button === 'editNamesBaseButton') editNamesbase();
|
||||
else if (button === 'editUnitsButton') editUnits();
|
||||
|
|
@ -26,9 +25,10 @@ toolsContent.addEventListener('click', function (event) {
|
|||
else if (button === 'overviewBurgsButton') overviewBurgs();
|
||||
else if (button === 'overviewRiversButton') overviewRivers();
|
||||
else if (button === 'overviewMilitaryButton') overviewMilitary();
|
||||
else if (button === 'overviewMarkersButton') overviewMarkers();
|
||||
else if (button === 'overviewCellsButton') viewCellDetails();
|
||||
|
||||
// Click to Regenerate buttons
|
||||
// click on Regenerate buttons
|
||||
if (event.target.parentNode.id === 'regenerateFeature') {
|
||||
if (sessionStorage.getItem('regenerateFeatureDontAsk')) {
|
||||
processFeatureRegeneration(event, button);
|
||||
|
|
@ -61,7 +61,10 @@ toolsContent.addEventListener('click', function (event) {
|
|||
});
|
||||
}
|
||||
|
||||
// Click to Add buttons
|
||||
// click on Configure regenerate buttons
|
||||
if (button === 'configRegenerateMarkers') configMarkersGeneration();
|
||||
|
||||
// click on Add buttons
|
||||
if (button === 'addLabel') toggleAddLabel();
|
||||
else if (button === 'addBurgTool') toggleAddBurg();
|
||||
else if (button === 'addRiver') toggleAddRiver();
|
||||
|
|
@ -84,13 +87,12 @@ function processFeatureRegeneration(event, button) {
|
|||
else if (button === 'regenerateStates') regenerateStates();
|
||||
else if (button === 'regenerateProvinces') regenerateProvinces();
|
||||
else if (button === 'regenerateBurgs') regenerateBurgs();
|
||||
else if (button === 'regenerateResources') regenerateResources();
|
||||
else if (button === 'regenerateEmblems') regenerateEmblems();
|
||||
else if (button === 'regenerateReligions') regenerateReligions();
|
||||
else if (button === 'regenerateCultures') regenerateCultures();
|
||||
else if (button === 'regenerateMilitary') regenerateMilitary();
|
||||
else if (button === 'regenerateIce') regenerateIce();
|
||||
else if (button === 'regenerateMarkers') regenerateMarkers(event);
|
||||
else if (button === 'regenerateMarkers') regenerateMarkers();
|
||||
else if (button === 'regenerateZones') regenerateZones(event);
|
||||
}
|
||||
|
||||
|
|
@ -119,6 +121,7 @@ function regenerateRivers() {
|
|||
Lakes.defineGroup();
|
||||
Rivers.specify();
|
||||
if (!layerIsOn('toggleRivers')) toggleRivers();
|
||||
else drawRivers();
|
||||
}
|
||||
|
||||
function recalculatePopulation() {
|
||||
|
|
@ -137,21 +140,11 @@ function recalculatePopulation() {
|
|||
function regenerateStates() {
|
||||
const localSeed = Math.floor(Math.random() * 1e9); // new random seed
|
||||
Math.random = aleaPRNG(localSeed);
|
||||
const burgs = pack.burgs.filter((b) => b.i && !b.removed);
|
||||
if (!burgs.length) {
|
||||
tip('No burgs to generate states. Please create burgs first', false, 'error');
|
||||
return;
|
||||
}
|
||||
if (burgs.length < +regionsInput.value) {
|
||||
tip(`Not enough burgs to generate ${regionsInput.value} states. Will generate only ${burgs.length} states`, false, 'warn');
|
||||
}
|
||||
|
||||
// burg local ids sorted by a bit randomized population:
|
||||
const sorted = burgs
|
||||
.map((b, i) => [i, b.population * Math.random()])
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.map((b) => b[0]);
|
||||
const capitalsTree = d3.quadtree();
|
||||
const statesCount = +regionsInput.value;
|
||||
const burgs = pack.burgs.filter((b) => b.i && !b.removed);
|
||||
if (!burgs.length) return tip('There are no any burgs to generate states. Please create burgs first', false, 'error');
|
||||
if (burgs.length < statesCount) tip(`Not enough burgs to generate ${statesCount} states. Will generate only ${burgs.length} states`, false, 'warn');
|
||||
|
||||
// turn all old capitals into towns
|
||||
burgs
|
||||
|
|
@ -168,8 +161,7 @@ function regenerateStates() {
|
|||
|
||||
unfog();
|
||||
|
||||
// if desired states number is 0
|
||||
if (regionsInput.value == 0) {
|
||||
if (!statesCount) {
|
||||
tip(`Cannot generate zero states. Please check the <i>States Number</i> option`, false, 'warn');
|
||||
pack.states = pack.states.slice(0, 1); // remove all except of neutrals
|
||||
pack.states[0].diplomacy = []; // clear diplomacy
|
||||
|
|
@ -185,26 +177,34 @@ function regenerateStates() {
|
|||
return;
|
||||
}
|
||||
|
||||
const neutral = pack.states[0].name;
|
||||
const count = Math.min(+regionsInput.value, burgs.length);
|
||||
// burg local ids sorted by a bit randomized population:
|
||||
const sortedBurgs = burgs
|
||||
.map((b, i) => [b, b.population * Math.random()])
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.map((b) => b[0]);
|
||||
const capitalsTree = d3.quadtree();
|
||||
|
||||
const neutral = pack.states[0].name; // neutrals name
|
||||
const count = Math.min(statesCount, burgs.length) + 1; // +1 for neutral
|
||||
let spacing = (graphWidth + graphHeight) / 2 / count; // min distance between capitals
|
||||
|
||||
pack.states = d3.range(count).map((i) => {
|
||||
if (!i) return {i, name: neutral};
|
||||
|
||||
let capital = null,
|
||||
x = 0,
|
||||
y = 0;
|
||||
for (const i of sorted) {
|
||||
capital = burgs[i];
|
||||
(x = capital.x), (y = capital.y);
|
||||
if (capitalsTree.find(x, y, spacing) === undefined) break;
|
||||
let capital = null;
|
||||
for (const burg of sortedBurgs) {
|
||||
const {x, y} = burg;
|
||||
if (capitalsTree.find(x, y, spacing) === undefined) {
|
||||
burg.capital = 1;
|
||||
capital = burg;
|
||||
capitalsTree.add([x, y]);
|
||||
moveBurgToGroup(burg.i, 'cities');
|
||||
break;
|
||||
}
|
||||
|
||||
spacing = Math.max(spacing - 1, 1);
|
||||
}
|
||||
|
||||
capitalsTree.add([x, y]);
|
||||
capital.capital = 1;
|
||||
moveBurgToGroup(capital.i, 'cities');
|
||||
|
||||
const culture = capital.culture;
|
||||
const basename = capital.name.length < 9 && capital.cell % 5 === 0 ? capital.name : Names.getCulture(culture, 3, 6, '', 0);
|
||||
const name = Names.getState(basename, culture);
|
||||
|
|
@ -337,13 +337,6 @@ function regenerateBurgs() {
|
|||
if (document.getElementById('statesEditorRefresh').offsetParent) statesEditorRefresh.click();
|
||||
}
|
||||
|
||||
function regenerateResources() {
|
||||
Resources.generate();
|
||||
goods.selectAll('*').remove();
|
||||
if (layerIsOn('toggleResources')) drawResources();
|
||||
refreshAllEditors();
|
||||
}
|
||||
|
||||
function regenerateEmblems() {
|
||||
// remove old emblems
|
||||
document.querySelectorAll('[id^=stateCOA]').forEach((el) => el.remove());
|
||||
|
|
@ -424,23 +417,11 @@ function regenerateIce() {
|
|||
drawIce();
|
||||
}
|
||||
|
||||
function regenerateMarkers(event) {
|
||||
if (isCtrlClick(event)) prompt('Please provide markers number multiplier', {default: 1, step: 0.01, min: 0, max: 100}, (v) => addNumberOfMarkers(v));
|
||||
else addNumberOfMarkers(gauss(1, 0.5, 0.3, 5, 2));
|
||||
|
||||
function addNumberOfMarkers(number) {
|
||||
// remove existing markers and assigned notes
|
||||
markers
|
||||
.selectAll('use')
|
||||
.each(function () {
|
||||
const index = notes.findIndex((n) => n.id === this.id);
|
||||
if (index != -1) notes.splice(index, 1);
|
||||
})
|
||||
.remove();
|
||||
|
||||
addMarkers(number);
|
||||
if (!layerIsOn('toggleMarkers')) toggleMarkers();
|
||||
}
|
||||
function regenerateMarkers() {
|
||||
Markers.regenerate();
|
||||
turnButtonOn('toggleMarkers');
|
||||
drawMarkers();
|
||||
if (document.getElementById('markersOverviewRefresh').offsetParent) markersOverviewRefresh.click();
|
||||
}
|
||||
|
||||
function regenerateZones(event) {
|
||||
|
|
@ -485,7 +466,10 @@ function addLabelOnClick() {
|
|||
const name = Names.getCulture(culture);
|
||||
const id = getNextId('label');
|
||||
|
||||
let group = labels.select('#addedLabels');
|
||||
// use most recently selected label group
|
||||
let selected = labelGroupSelect.value;
|
||||
const symbol = selected ? '#' + selected : '#addedLabels';
|
||||
let group = labels.select(symbol);
|
||||
if (!group.size())
|
||||
group = labels
|
||||
.append('g')
|
||||
|
|
@ -495,7 +479,6 @@ function addLabelOnClick() {
|
|||
.attr('stroke', '#3a3a3a')
|
||||
.attr('stroke-width', 0)
|
||||
.attr('font-family', 'Almendra SC')
|
||||
.attr('data-font', 'Almendra+SC')
|
||||
.attr('font-size', 18)
|
||||
.attr('data-size', 18)
|
||||
.attr('filter', null);
|
||||
|
|
@ -697,7 +680,7 @@ function addRouteOnClick() {
|
|||
}
|
||||
|
||||
function toggleAddMarker() {
|
||||
const pressed = document.getElementById('addMarker').classList.contains('pressed');
|
||||
const pressed = document.getElementById('addMarker')?.classList.contains('pressed');
|
||||
if (pressed) {
|
||||
unpressClickToAddButton();
|
||||
return;
|
||||
|
|
@ -705,45 +688,115 @@ function toggleAddMarker() {
|
|||
|
||||
addFeature.querySelectorAll('button.pressed').forEach((b) => b.classList.remove('pressed'));
|
||||
addMarker.classList.add('pressed');
|
||||
closeDialogs('.stable');
|
||||
markersAddFromOverview.classList.add('pressed');
|
||||
|
||||
viewbox.style('cursor', 'crosshair').on('click', addMarkerOnClick);
|
||||
tip('Click on map to add a marker. Hold Shift to add multiple', true);
|
||||
if (!layerIsOn('toggleMarkers')) toggleMarkers();
|
||||
}
|
||||
|
||||
function addMarkerOnClick() {
|
||||
const {markers} = pack;
|
||||
const point = d3.mouse(this);
|
||||
const x = rn(point[0], 2),
|
||||
y = rn(point[1], 2);
|
||||
const id = getNextId('markerElement');
|
||||
const x = rn(point[0], 2);
|
||||
const y = rn(point[1], 2);
|
||||
const i = last(markers).i + 1;
|
||||
|
||||
const selected = markerSelectGroup.value;
|
||||
const valid =
|
||||
selected &&
|
||||
d3
|
||||
.select('#defs-markers')
|
||||
.select('#' + selected)
|
||||
.size();
|
||||
const symbol = valid ? '#' + selected : '#marker0';
|
||||
const added = markers.select("[data-id='" + symbol + "']").size();
|
||||
let desired = valid && added ? markers.select("[data-id='" + symbol + "']").attr('data-size') : 1;
|
||||
if (isNaN(desired)) desired = 1;
|
||||
const size = desired * 5 + 25 / scale;
|
||||
const isMarkerSelected = elSelected?.node()?.parentElement?.id === 'markers';
|
||||
const selectedMarker = isMarkerSelected ? markers.find((marker) => marker.i === +elSelected.attr('id').slice(6)) : null;
|
||||
const baseMarker = selectedMarker || {icon: '❓'};
|
||||
const marker = {...baseMarker, i, x, y};
|
||||
|
||||
markers
|
||||
.append('use')
|
||||
.attr('id', id)
|
||||
.attr('xlink:href', symbol)
|
||||
.attr('data-id', symbol)
|
||||
.attr('data-x', x)
|
||||
.attr('data-y', y)
|
||||
.attr('x', x - size / 2)
|
||||
.attr('y', y - size)
|
||||
.attr('data-size', desired)
|
||||
.attr('width', size)
|
||||
.attr('height', size);
|
||||
markers.push(marker);
|
||||
const markersElement = document.getElementById('markers');
|
||||
const rescale = +markersElement.getAttribute('rescale');
|
||||
markersElement.insertAdjacentHTML('beforeend', drawMarker(marker, rescale));
|
||||
|
||||
if (d3.event.shiftKey === false) unpressClickToAddButton();
|
||||
if (d3.event.shiftKey === false) {
|
||||
document.getElementById('markerAdd').classList.remove('pressed');
|
||||
document.getElementById('markersAddFromOverview').classList.remove('pressed');
|
||||
unpressClickToAddButton();
|
||||
}
|
||||
}
|
||||
|
||||
function configMarkersGeneration() {
|
||||
drawConfigTable();
|
||||
|
||||
function drawConfigTable() {
|
||||
const {markers} = pack;
|
||||
const config = Markers.getConfig();
|
||||
const headers = `<thead style='font-weight:bold'><tr>
|
||||
<td data-tip="Marker type name">Type</td>
|
||||
<td data-tip="Marker icon">Icon</td>
|
||||
<td data-tip="Marker number multiplier">Multiplier</td>
|
||||
<td data-tip="Number of markers of that type on the current map">Number</td>
|
||||
</tr></thead>`;
|
||||
const lines = config.map(({type, icon, multiplier}, index) => {
|
||||
const inputId = `markerIconInput${index}`;
|
||||
return `<tr>
|
||||
<td><input value="${type}" /></td>
|
||||
<td>
|
||||
<input id="${inputId}" style="width: 5em" value="${icon}" />
|
||||
<i class="icon-edit pointer" style="position: absolute; margin:.4em 0 0 -1.4em; font-size:.85em"></i>
|
||||
</td>
|
||||
<td><input type="number" min="0" max="100" step="0.1" value="${multiplier}" /></td>
|
||||
<td style="text-align:center">${markers.filter((marker) => marker.type === type).length}</td>
|
||||
</tr>`;
|
||||
});
|
||||
const table = `<table class="table">${headers}<tbody>${lines.join('')}</tbody></table>`;
|
||||
alertMessage.innerHTML = table;
|
||||
|
||||
alertMessage.querySelectorAll('i').forEach((selectIconButton) => {
|
||||
selectIconButton.addEventListener('click', function () {
|
||||
const input = this.previousElementSibling;
|
||||
selectIcon(input.value, (icon) => (input.value = icon));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const applyChanges = () => {
|
||||
const rows = alertMessage.querySelectorAll('tbody > tr');
|
||||
const rowsData = Array.from(rows).map((row) => {
|
||||
const inputs = row.querySelectorAll('input');
|
||||
return {
|
||||
type: inputs[0].value,
|
||||
icon: inputs[1].value,
|
||||
multiplier: parseFloat(inputs[2].value)
|
||||
};
|
||||
});
|
||||
|
||||
const config = Markers.getConfig();
|
||||
const newConfig = config.map((markerType, index) => {
|
||||
const {type, icon, multiplier} = rowsData[index];
|
||||
return {...markerType, type, icon, multiplier};
|
||||
});
|
||||
|
||||
Markers.setConfig(newConfig);
|
||||
};
|
||||
|
||||
$('#alert').dialog({
|
||||
resizable: false,
|
||||
title: 'Markers generation settings',
|
||||
position: {my: 'left top', at: 'left+10 top+10', of: 'svg', collision: 'fit'},
|
||||
buttons: {
|
||||
Regenerate: () => {
|
||||
applyChanges();
|
||||
regenerateMarkers();
|
||||
drawConfigTable();
|
||||
},
|
||||
Close: function () {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
},
|
||||
open: function () {
|
||||
const buttons = $(this).dialog('widget').find('.ui-dialog-buttonset > button');
|
||||
buttons[0].addEventListener('mousemove', () => tip('Apply changes and regenerate markers'));
|
||||
buttons[1].addEventListener('mousemove', () => tip('Close the window'));
|
||||
},
|
||||
close: function () {
|
||||
$(this).dialog('destroy');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function viewCellDetails() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue