mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-22 20:11:24 +01:00
Merge branch 'zone-types' into zoneFilter
This commit is contained in:
commit
be5fd52545
50 changed files with 5605 additions and 1374 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,2 +1,4 @@
|
|||
.bat
|
||||
.vscode
|
||||
.idea
|
||||
.idea/Fantasy-Map-Generator.iml
|
||||
|
|
|
|||
74
components/fill-box.js
Normal file
74
components/fill-box.js
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
// fill-box cannot use Shadow DOM as it needs access to svg hatches
|
||||
// append stylesheet
|
||||
{
|
||||
const style = `
|
||||
fill-box:not([disabled]) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
fill-box > svg {
|
||||
vertical-align: middle;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
fill-box > svg > rect {
|
||||
stroke: #666666;
|
||||
stroke-width: 2;
|
||||
}`;
|
||||
|
||||
const styleElement = document.createElement("style");
|
||||
styleElement.setAttribute("type", "text/css");
|
||||
styleElement.innerHTML = style;
|
||||
document.head.appendChild(styleElement);
|
||||
}
|
||||
|
||||
{
|
||||
const template = document.createElement("template");
|
||||
template.innerHTML = `
|
||||
<svg>
|
||||
<rect x="0" y="0" width="100%" height="100%">
|
||||
</svg>
|
||||
`;
|
||||
|
||||
class FillBox extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.appendChild(template.content.cloneNode(true));
|
||||
this.querySelector("rect")?.setAttribute("fill", this.fill);
|
||||
this.querySelector("svg")?.setAttribute("width", this.size);
|
||||
this.querySelector("svg")?.setAttribute("height", this.size);
|
||||
}
|
||||
|
||||
static showTip() {
|
||||
tip(this.tip);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.addEventListener("mousemove", this.constructor.showTip);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.removeEventListener("mousemove", this.constructor.showTip);
|
||||
}
|
||||
|
||||
get fill() {
|
||||
return this.getAttribute("fill") || "#333";
|
||||
}
|
||||
|
||||
set fill(newFill) {
|
||||
this.setAttribute("fill", newFill);
|
||||
this.querySelector("rect")?.setAttribute("fill", newFill);
|
||||
}
|
||||
|
||||
get size() {
|
||||
return this.getAttribute("size") || "1em";
|
||||
}
|
||||
|
||||
get tip() {
|
||||
return this.dataset.tip || "Fill style. Click to change";
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("fill-box", FillBox);
|
||||
}
|
||||
94
index.css
94
index.css
|
|
@ -29,9 +29,13 @@ input:read-only {
|
|||
cursor: default;
|
||||
}
|
||||
|
||||
input[type="radio"] {
|
||||
vertical-align: bottom;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
textarea {
|
||||
padding: 2px;
|
||||
text-indent: 1px;
|
||||
padding: 3px;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
|
@ -834,75 +838,79 @@ fieldset {
|
|||
}
|
||||
|
||||
.matrix-table {
|
||||
width: 100%;
|
||||
font-size: smaller;
|
||||
text-align: center;
|
||||
border-collapse: collapse;
|
||||
max-height: 80vh;
|
||||
max-width: 85vw;
|
||||
scrollbar-width: thin;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
table.matrix-table th,
|
||||
table.matrix-table td {
|
||||
.matrix-table > table {
|
||||
text-align: center;
|
||||
border-collapse: collapse;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.matrix-table > table th,
|
||||
.matrix-table > table td {
|
||||
border: 1px solid var(--dark-solid);
|
||||
height: 2em;
|
||||
padding: 0.2em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
table.matrix-table th {
|
||||
.matrix-table > table th {
|
||||
background-color: #302a2a;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
table.matrix-table tr:hover th {
|
||||
background: #3e3636;
|
||||
}
|
||||
|
||||
table.matrix-table td:hover {
|
||||
.matrix-table > table td:hover {
|
||||
outline: 2px solid var(--dark-solid);
|
||||
outline-offset: -1px;
|
||||
z-index: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
table.matrix-table td.Ally {
|
||||
.matrix-table > table td.Ally {
|
||||
background-color: #73ec73;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
table.matrix-table td.Friendly {
|
||||
.matrix-table > table td.Friendly {
|
||||
background-color: #d4f8aa;
|
||||
}
|
||||
|
||||
table.matrix-table td.Neutral {
|
||||
.matrix-table > table td.Neutral {
|
||||
background-color: #d8d9d3;
|
||||
}
|
||||
|
||||
table.matrix-table td.Suspicion {
|
||||
.matrix-table > table td.Suspicion {
|
||||
background-color: #eeafaa;
|
||||
}
|
||||
|
||||
table.matrix-table td.Enemy {
|
||||
.matrix-table > table td.Enemy {
|
||||
background-color: #ffa39c;
|
||||
color: #af0d23;
|
||||
}
|
||||
|
||||
table.matrix-table td.Unknown {
|
||||
.matrix-table > table td.Unknown {
|
||||
background-color: #c1bfbf;
|
||||
}
|
||||
|
||||
table.matrix-table td.Rival {
|
||||
.matrix-table > table td.Rival {
|
||||
background-color: #bd845c;
|
||||
}
|
||||
|
||||
table.matrix-table td.Vassal {
|
||||
.matrix-table > table td.Vassal {
|
||||
background-color: #87cefa;
|
||||
}
|
||||
|
||||
table.matrix-table td.Suzerain {
|
||||
.matrix-table > table td.Suzerain {
|
||||
background-color: #8f8fe1;
|
||||
}
|
||||
|
||||
table.matrix-table td.x {
|
||||
.matrix-table > table td.x {
|
||||
background-color: #d4ca94;
|
||||
cursor: initial;
|
||||
}
|
||||
|
||||
#sizeOutput {
|
||||
|
|
@ -1310,19 +1318,23 @@ div.slider .ui-slider-handle {
|
|||
}
|
||||
|
||||
#alertMessage::-webkit-scrollbar,
|
||||
.table::-webkit-scrollbar {
|
||||
.table::-webkit-scrollbar,
|
||||
.matrix-table::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#alertMessage::-webkit-scrollbar-thumb,
|
||||
.table::-webkit-scrollbar-thumb {
|
||||
.table::-webkit-scrollbar-thumb,
|
||||
.matrix-table::-webkit-scrollbar-thumb {
|
||||
background-color: #aaa;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
#alertMessage::-webkit-scrollbar-thumb:hover,
|
||||
.table::-webkit-scrollbar-thumb:hover {
|
||||
.table::-webkit-scrollbar-thumb:hover,
|
||||
.matrix-table::-webkit-scrollbar-thumb:hover {
|
||||
background: #666;
|
||||
}
|
||||
|
||||
|
|
@ -1504,15 +1516,14 @@ div.states > .riverType {
|
|||
width: 5em;
|
||||
}
|
||||
|
||||
div.states > .coaIcon {
|
||||
.coaIcon {
|
||||
stroke-width: 3;
|
||||
width: 1.4em;
|
||||
height: 1.4em;
|
||||
margin: -0.3em 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.states > .coaIcon > use {
|
||||
.coaIcon > use {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
|
@ -1520,6 +1531,11 @@ div.states > .coaIcon > use {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.changeRelations > * {
|
||||
pointer-events: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#diplomacySelect {
|
||||
width: 5em;
|
||||
margin: 0.1em 0 0 -0.3em;
|
||||
|
|
@ -1657,11 +1673,6 @@ div.states > div.biomeArea {
|
|||
width: 5em;
|
||||
}
|
||||
|
||||
rect.fillRect {
|
||||
stroke: #666666;
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
#militaryHeader > div,
|
||||
#regimentsHeader > div {
|
||||
width: 5.2em;
|
||||
|
|
@ -2000,7 +2011,7 @@ div.textual fieldset {
|
|||
|
||||
div.textual span,
|
||||
.textual legend {
|
||||
font-size: 0.8em;
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
|
@ -2119,8 +2130,9 @@ svg.button {
|
|||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#info-line {
|
||||
.info-line {
|
||||
font-size: 0.9em;
|
||||
font-style: italic;
|
||||
color: gray;
|
||||
user-select: none;
|
||||
}
|
||||
|
|
@ -2264,10 +2276,10 @@ svg.button {
|
|||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
max-width: 22em;
|
||||
background-color: #fff;
|
||||
max-width: 23em;
|
||||
padding: 1.2em;
|
||||
border: solid 1px #000;
|
||||
background-color: var(--bg-dialogs);
|
||||
border: solid 1px var(--dark-solid);
|
||||
font-size: 1.2em;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
|
@ -2298,7 +2310,7 @@ svg.button {
|
|||
|
||||
.epgrid line {
|
||||
stroke: lightgrey;
|
||||
stroke-opacity: 0.7;
|
||||
stroke-opacity: 0.5;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
|
||||
|
|
|
|||
432
index.html
432
index.html
|
|
@ -19,7 +19,7 @@
|
|||
body {margin: 0; font-size: 10px; overflow: hidden;}
|
||||
#map {position: absolute;}
|
||||
#initial {fill: none; stroke: black; pointer-events: none;}
|
||||
#init-rose {animation: 20s infinite spin; opacity: .7; transform-origin: center;}
|
||||
#init-rose {opacity: .7; transform-origin: center; opacity: .7; animation: 20s infinite spin;}
|
||||
@keyframes spin {0% {transform: rotate(0deg);} 100% {transform: rotate(359deg);}}
|
||||
#loading {opacity:1; font-size: 11px; color:#fff5da; text-align:center; text-shadow:0px 1px 4px #4c3a35; width:80%; max-width:600px; position:fixed; top:50%; left:50%; transform:translate(-50%, -50%); pointer-events:none;}
|
||||
#loading-text {font-size: 1.8em; margin: 0.2em 0 0 1em;}
|
||||
|
|
@ -148,55 +148,6 @@
|
|||
</filter>
|
||||
</g>
|
||||
|
||||
<g id="hatching">
|
||||
<pattern id="hatch0" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch1" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch2" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch3" patternTransform="rotate(-45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch4" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="0" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch5" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="0" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch6" patternUnits="userSpaceOnUse" width="5" height="5">
|
||||
<circle cx="2.5" cy="2.5" r="1" style="fill: black"/>
|
||||
</pattern>
|
||||
<pattern id="hatch7" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="3" transform="rotate(-45 0 0)" style="stroke:black; stroke-width:1.5" />
|
||||
</pattern>
|
||||
<pattern id="hatch8" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="3" style="stroke:black; stroke-width:2.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch9" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="3" style="stroke:black; stroke-width:2.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch10" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="3" y2="0" style="stroke:black; stroke-width:2.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch11" patternTransform="rotate(-45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="3" style="stroke:black; stroke-width:2.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch12" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="1" x2="0" y2="3" style="stroke:black; stroke-width:1.5" />
|
||||
<line x1="1" y1="0" x2="3" y2="0" style="stroke:black; stroke-width:1.5" />
|
||||
</pattern>
|
||||
<pattern id="hatch13" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="3" style="stroke:black; stroke-width:1.5" />
|
||||
<line x1="0" y1="0" x2="3" y2="0" style="stroke:black; stroke-width:1.5" />
|
||||
</pattern>
|
||||
</g>
|
||||
|
||||
<g id="deftemp">
|
||||
<mask id="land"></mask>
|
||||
<mask id="water">
|
||||
|
|
@ -226,7 +177,7 @@
|
|||
<div id="loading">
|
||||
<div id="titleName"><t data-t="titleName">Azgaar's</t></div>
|
||||
<div id="title"><t data-t="title">Fantasy Map Generator</t></div>
|
||||
<div id="version"><t data-t="version">v. </t>1.71</div>
|
||||
<div id="version"><t data-t="version">v. </t>1.72</div>
|
||||
<p id="loading-text"><t data-t="loading">LOADING</t><span>.</span><span>.</span><span>.</span></p>
|
||||
</div>
|
||||
|
||||
|
|
@ -309,17 +260,9 @@
|
|||
|
||||
<div id="styleContent" class="tabcontent">
|
||||
<p data-tip="Select a style preset. State labels may required regeneration if font is changed" style="display: inline-block">Style preset:</p>
|
||||
<select data-tip="Select a style preset" id="stylePreset" onchange="changeStylePreset(this.value)" style="width:45%">
|
||||
<option value="styleDefault" data-system=1 selected>Default</option>
|
||||
<option value="styleAncient" data-system=1>Ancient</option>
|
||||
<option value="styleGloom" data-system=1>Gloom</option>
|
||||
<option value="styleClean" data-system=1>Clean</option>
|
||||
<option value="styleLight" data-system=1>Light</option>
|
||||
<option value="styleWatercolor" data-system=1>Watercolor</option>
|
||||
<option value="styleMonochrome" data-system=1>Monochrome</option>
|
||||
</select>
|
||||
<select data-tip="Select a style preset" id="stylePreset" onchange="requestStylePresetChange(this.value)" style="width:45%; text-transform: capitalize;"></select>
|
||||
<button id="addStyleButton" data-tip="Click to save current style as a new preset" class="icon-plus sideButton" style="display: inline-block" onclick="addStylePreset()"></button>
|
||||
<button id="removeStyleButton" data-tip="Click to remove current custom style preset" class="icon-minus sideButton" style="display: none" onclick="removeStylePreset()"></button>
|
||||
<button id="removeStyleButton" data-tip="Click to remove current custom style preset" class="icon-minus sideButton" style="display: none" onclick="requestRemoveStylePreset()"></button>
|
||||
|
||||
<p data-tip="Select an element to edit its style" style="display: inline-block;">Select element:</p>
|
||||
<select data-tip="Select an element to edit its style (list is ordered alphabetically)" id="styleElementSelect" style="width:42%">
|
||||
|
|
@ -947,7 +890,7 @@
|
|||
|
||||
<tr data-tip="Map seed number. Seed produces the same map only if canvas size and options are the same">
|
||||
<td>
|
||||
<i data-tip="Show seed history to apply a previous seed" id="optionsMapHistory" class="icon-history"></i>
|
||||
<i data-tip="Show seed history to apply a previous seed" id="optionsMapHistory" class="icon-hourglass-1"></i>
|
||||
</td>
|
||||
<td>Map seed</td>
|
||||
<td>
|
||||
|
|
@ -1062,7 +1005,7 @@
|
|||
<input id="regionsInput" data-stored="regions" type="range" min=0 max=99 value=13>
|
||||
</td>
|
||||
<td>
|
||||
<input id="regionsOutput" data-stored="regions" type="number" min=0 max=99 value=13>
|
||||
<input id="regionsOutput" data-stored="regions" type="number" min=0 max=999 value=13>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
|
@ -1446,9 +1389,21 @@
|
|||
</div>
|
||||
|
||||
<div id="aboutContent" class="tabcontent">
|
||||
<p><a href="https://github.com/Azgaar/Fantasy-Map-Generator" target="_blank">Fantasy Map Generator</a> is a free <a href="https://github.com/Azgaar/Fantasy-Map-Generator/blob/master/LICENSE" target="_blank">open source</a> tool which procedurally generates fantasy maps. You may use auto-generated maps as they are, edit them or even create a new map from scratch. Check out the <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Quick-Start-Tutorial" target="_blank">quick start tutorial</a>, <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Q&A" target="_blank">Q&A</a> and <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Hotkeys" target="_blank">hotkeys</a> for guidance.</p>
|
||||
<p>Join our <a href='https://discordapp.com/invite/X7E84HU' target='_blank'>Discord server</a> and <a href="https://www.reddit.com/r/FantasyMapGenerator/" target="_blank">Reddit community</a> to ask questions, get help and share maps.</p>
|
||||
<p>The project is under active development. Creator and main maintainer: Azgaar. To track the development progress see the <a href="https://trello.com/b/7x832DG4/fantasy-map-generator" target="_blank">devboard</a>. For older versions see the <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog" target="_blank">changelog</a>. Please report bugs <a href="https://github.com/Azgaar/Fantasy-Map-Generator/issues" target="_blank">here</a>. You can also contact me directly via <a href="mailto:azgaar.fmg@yandex.by" target="_blank">email</a>.</p>
|
||||
<p>
|
||||
<a href="https://github.com/Azgaar/Fantasy-Map-Generator" target="_blank">Fantasy Map Generator</a> is a free <a href="https://github.com/Azgaar/Fantasy-Map-Generator/blob/master/LICENSE" target="_blank">open source</a> tool which procedurally generates fantasy maps.
|
||||
You may use auto-generated maps as they are, edit them or even create a new map from scratch.
|
||||
Check out the <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Quick-Start-Tutorial" target="_blank">Quick start</a>, <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Q&A" target="_blank">Q&A</a>, <a href="https://youtube.com/playlist?list=PLtgiuDC8iVR2gIG8zMTRn7T_L0arl9h1C" target="_blank">Video tutorial</a>, and <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Hotkeys" target="_blank">hotkeys</a> for guidance.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Join our <a href='https://discordapp.com/invite/X7E84HU' target='_blank'>Discord server</a> and <a href="https://www.reddit.com/r/FantasyMapGenerator/" target="_blank">Reddit community</a> to ask questions, get help and share maps.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The project is under active development. Creator and main maintainer: Azgaar. To track the development progress see the <a href="https://trello.com/b/7x832DG4/fantasy-map-generator" target="_blank">devboard</a>.
|
||||
For older versions see the <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog" target="_blank">changelog</a>. Please report bugs <a href="https://github.com/Azgaar/Fantasy-Map-Generator/issues" target="_blank">here</a>. You can also contact me directly via <a href="mailto:azgaar.fmg@yandex.by" target="_blank">email</a>.
|
||||
</p>
|
||||
|
||||
<div style="background-color: #e85b46; padding: .4em; width: max-content; margin: .6em auto 0 auto; border: 1px solid #943838">
|
||||
<a href="https://www.patreon.com/azgaar" target="_blank" style="color: white; text-decoration: none; font-family: sans-serif">
|
||||
<div>
|
||||
|
|
@ -1461,7 +1416,10 @@
|
|||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<p>Special thanks to <a data-tip="Click to see list of supporters" onclick="showSupporters()">all supporters</a> on Patreon!</p>
|
||||
|
||||
<p>
|
||||
Special thanks to <a data-tip="Click to see list of supporters" onclick="showSupporters()">all supporters</a> on Patreon!
|
||||
</p>
|
||||
|
||||
<ul class="share-buttons">
|
||||
<li><a href="https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fazgaar.github.io%2FFantasy-Map-Generator%2F"e=" data-tip="Share on Facebook" target="_blank"><img alt="Share on Facebook" src="images/Facebook.png" /></a></li>
|
||||
|
|
@ -1784,7 +1742,7 @@
|
|||
<span data-tip="Set curve profile">Curve:
|
||||
<select id="epCurve">
|
||||
<option>Linear</option>
|
||||
<option selected>Basis spline</option>
|
||||
<option selected>Basis spline</option>
|
||||
<option>Bundle</option>
|
||||
<option>Cubic Catmull-Rom</option>
|
||||
<option>Monotone X</option>
|
||||
|
|
@ -1975,69 +1933,73 @@
|
|||
<div id="burgBody" style="padding-bottom: .3em">
|
||||
<div style="display: flex; align-items: center">
|
||||
<svg data-tip="Burg emblem. Click to edit" class="pointer" viewBox="0 0 200 200" width="13em" height="13em"><use id="burgEmblem"></use></svg>
|
||||
<div>
|
||||
<div id="burgProvinceAndState" style="font-style: italic; max-width: 16em"></div>
|
||||
<div style="display: grid; grid-auto-rows: minmax(1.6em, auto)">
|
||||
<div id="burgProvinceAndState" style="font-style: italic; max-width: 16em"></div>
|
||||
|
||||
<div>
|
||||
<div class="label">Name:</div>
|
||||
<input id="burgName" data-tip="Type to rename the burg" autocorrect="off" spellcheck="false" style="width: 8em">
|
||||
<span data-tip="Speak the name. You can change voice and language in options" class="speaker">🔊</span>
|
||||
<span id="burgNameReRandom" data-tip="Generate random name for the burg" class="icon-globe pointer"></span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="label">Name:</div>
|
||||
<input id="burgName" data-tip="Type to rename the burg" autocorrect="off" spellcheck="false" style="width: 8em">
|
||||
<span data-tip="Speak the name. You can change voice and language in options" class="speaker">🔊</span>
|
||||
<span id="burgNameReRandom" data-tip="Generate random name for the burg" class="icon-globe pointer"></span>
|
||||
</div>
|
||||
|
||||
<div data-tip="Select burg type. Type slightly affects emblem generation">
|
||||
<div class="label">Type:</div>
|
||||
<select id="burgType" style="width: 8em">
|
||||
<option value="Generic">Generic</option>
|
||||
<option value="River">River</option>
|
||||
<option value="Lake">Lake</option>
|
||||
<option value="Naval">Naval</option>
|
||||
<option value="Nomadic">Nomadic</option>
|
||||
<option value="Hunting">Hunting</option>
|
||||
<option value="Highland">Highland</option>
|
||||
</select>
|
||||
</div>
|
||||
<div data-tip="Select burg type. Type slightly affects emblem generation">
|
||||
<div class="label">Type:</div>
|
||||
<select id="burgType" style="width: 8em">
|
||||
<option value="Generic">Generic</option>
|
||||
<option value="River">River</option>
|
||||
<option value="Lake">Lake</option>
|
||||
<option value="Naval">Naval</option>
|
||||
<option value="Nomadic">Nomadic</option>
|
||||
<option value="Hunting">Hunting</option>
|
||||
<option value="Highland">Highland</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-tip="Select dominant culture">
|
||||
<div class="label">Culture:</div>
|
||||
<select id="burgCulture" style="width: 8em"></select>
|
||||
<span id="burgNameReCulture" data-tip="Generate culture-specific name for the burg" class="icon-book pointer"></span>
|
||||
</div>
|
||||
<div data-tip="Select dominant culture">
|
||||
<div class="label">Culture:</div>
|
||||
<select id="burgCulture" style="width: 8em"></select>
|
||||
<span id="burgNameReCulture" data-tip="Generate culture-specific name for the burg" class="icon-book pointer"></span>
|
||||
</div>
|
||||
|
||||
<div data-tip="Set burg population">
|
||||
<div class="label">Population:</div>
|
||||
<input id="burgPopulation" type="number" min=0 step=1 style="width: 8em">
|
||||
</div>
|
||||
<div data-tip="Set burg population">
|
||||
<div class="label">Population:</div>
|
||||
<input id="burgPopulation" type="number" min=0 step=1 style="width: 8em">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="label">Features:</div>
|
||||
<span id="burgCapital" data-tip="Shows whether the burg is a state capital. Click to toggle" data-feature="capital" class="burgFeature icon-star"></span>
|
||||
<span id="burgPort" data-tip="Shows whether the burg is a port. Click to toggle" data-feature="port" class="burgFeature icon-anchor"></span>
|
||||
<span id="burgCitadel" data-tip="Shows whether the burg has a citadel (castle). Click to toggle" data-feature="citadel" class="burgFeature icon-chess-rook" style="font-size: 1.1em"></span>
|
||||
<span id="burgWalls" data-tip="Shows whether the burg is walled. Click to toggle" data-feature="walls" class="burgFeature icon-fort-awesome"></span>
|
||||
<span id="burgPlaza" data-tip="Shows whether the burg is a trade center (has big marketplace). Click to toggle" data-feature="plaza" class="burgFeature icon-store" style="font-size: 1em"></span>
|
||||
<span id="burgTemple" data-tip="Shows whether the burg is a religious center. Click to toggle" data-feature="temple" class="burgFeature icon-chess-bishop" style="font-size: 1.1em; margin-left: 3px"></span>
|
||||
<span id="burgShanty" data-tip="Shows whether the burg has a shanty town. Click to toggle" data-feature="shanty" class="burgFeature icon-campground" style="font-size: 1em"></span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="label">Features:</div>
|
||||
<span id="burgCapital" data-tip="Shows whether the burg is a state capital. Click to toggle" data-feature="capital" class="burgFeature icon-star"></span>
|
||||
<span id="burgPort" data-tip="Shows whether the burg is a port. Click to toggle" data-feature="port" class="burgFeature icon-anchor"></span>
|
||||
<span id="burgCitadel" data-tip="Shows whether the burg has a citadel (castle). Click to toggle" data-feature="citadel" class="burgFeature icon-chess-rook" style="font-size: 1.1em"></span>
|
||||
<span id="burgWalls" data-tip="Shows whether the burg is walled. Click to toggle" data-feature="walls" class="burgFeature icon-fort-awesome"></span>
|
||||
<span id="burgPlaza" data-tip="Shows whether the burg is a trade center (has big marketplace). Click to toggle" data-feature="plaza" class="burgFeature icon-store" style="font-size: 1em"></span>
|
||||
<span id="burgTemple" data-tip="Shows whether the burg is a religious center. Click to toggle" data-feature="temple" class="burgFeature icon-chess-bishop" style="font-size: 1.1em; margin-left: 3px"></span>
|
||||
<span id="burgShanty" data-tip="Shows whether the burg has a shanty town. Click to toggle" data-feature="shanty" class="burgFeature icon-campground" style="font-size: 1em"></span>
|
||||
</div>
|
||||
|
||||
<div data-tip="Burg mean annual temperature and real-world city for comparison">
|
||||
<div class="label">Temperature:</div>
|
||||
<span id="burgTemperature"></span>, like in
|
||||
<span id="burgTemperatureLikeIn"></span>
|
||||
</div>
|
||||
<div data-tip="Burg mean annual temperature and real-world city for comparison">
|
||||
<div class="label">Temperature:</div>
|
||||
<span id="burgTemperature"></span>, like in
|
||||
<span id="burgTemperatureLikeIn"></span>
|
||||
<i id="burgTemperatureGraph" data-tip="Show temperature graph for the burg" class="icon-chart-area pointer"></i>
|
||||
</div>
|
||||
|
||||
<div data-tip="Burg height above mean sea level">
|
||||
<div class="label">Elevation:</div>
|
||||
<span id="burgElevation"></span> above sea level
|
||||
</div>
|
||||
<div data-tip="Burg height above mean sea level">
|
||||
<div class="label">Elevation:</div>
|
||||
<span id="burgElevation"></span> above sea level
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="mfcgPreviewSection" data-tip="Burg preview in the Medieval Fantasy City Generator. Default seed is a combination of map seed and burg id" style="display: flex; flex-direction: column">
|
||||
<div>
|
||||
See in <a id="mfcgLink" target="_blank">City Generator by Watabou</a>.
|
||||
Seed: <input id="mfcgBurgSeed" style="width: 10em" type="number" min=1 max="1e13" step="1" />
|
||||
<i id="regenerateMFCGBurgSeed" data-tip="Randomize Medieval Fantasy City Generator burg seed" class="icon-arrows-cw pointer" style="margin-left: .1em"></i>
|
||||
<div id="mfcgBurgSeedSection">
|
||||
Seed: <input id="mfcgBurgSeed" style="width: 10em" type="number" min=1 max="1e13" step="1" />
|
||||
<i id="regenerateMFCGBurgSeed" data-tip="Randomize Medieval Fantasy City Generator burg seed" class="icon-arrows-cw pointer" style="margin-left: .1em"></i>
|
||||
</div>
|
||||
<i id="addCustomMFCGBurgLink" data-tip="Provide custom link to the burg map" class="icon-pencil pointer" style="margin-left: .1em"></i>
|
||||
</div>
|
||||
<iframe id="mfcgPreview" sandbox="allow-scripts allow-same-origin"></iframe>
|
||||
</div>
|
||||
|
|
@ -2618,8 +2580,10 @@
|
|||
<option value="Sultanate">Sultanate</option>
|
||||
<option value="Tsardom">Tsardom</option>
|
||||
<option value="Ulus">Ulus</option>
|
||||
<option value="Viceroyalty">Viceroyalty</option>
|
||||
</optgroup>
|
||||
<optgroup label="Republic">
|
||||
<option value="Chancellery">Chancellery</option>
|
||||
<option value="City-state">City-state</option>
|
||||
<option value="Diarchy">Diarchy</option>
|
||||
<option value="Federation">Federation</option>
|
||||
|
|
@ -2657,8 +2621,10 @@
|
|||
<option value="Divine Kingdom">Divine Kingdom</option>
|
||||
<option value="Divine Empire">Divine Empire</option>
|
||||
<option value="Eparchy">Eparchy</option>
|
||||
<option value="Exarchate">Exarchate</option>
|
||||
<option value="Holy State">Holy State</option>
|
||||
<option value="Imamah">Imamah</option>
|
||||
<option value="Patriarchate">Patriarchate</option>
|
||||
<option value="Theocracy">Theocracy</option>
|
||||
</optgroup>
|
||||
<optgroup label="Anarchy">
|
||||
|
|
@ -2735,33 +2701,27 @@
|
|||
<div id="diplomacyEditor" class="dialog stable" style="display: none">
|
||||
<div id="diplomacyHeader" class="header">
|
||||
<div style="left:.2em" data-tip="Click to sort by state name" class="sortable alphabetically" data-sortby="name">State </div>
|
||||
<div style="left:13.4em" data-tip="Click to sort by diplomatical relations" class="sortable alphabetically" data-sortby="relations">Relations </div>
|
||||
<div style="left:14.4em" data-tip="Click to sort by diplomatical relations" class="sortable alphabetically" data-sortby="relations">Relations </div>
|
||||
</div>
|
||||
|
||||
<div id="diplomacyBodySection" class="table"></div>
|
||||
|
||||
<div id="diplomacySelect">
|
||||
<div data-tip="Ally means states formed a defensive pact and will protect each other in case of third party aggression">Ally</div>
|
||||
<div data-tip="State is friendly to anouther state when they share some common interests">Friendly</div>
|
||||
<div data-tip="Neutral means states relations are neither positive nor negative">Neutral</div>
|
||||
<div data-tip="Suspicion means state has a cautious distrust of another state">Suspicion</div>
|
||||
<div data-tip="Enemies are states at war with each other">Enemy</div>
|
||||
<div data-tip="Relations are unknown if states do not have enough information about each other">Unknown</div>
|
||||
<div data-tip="Rivalry is a state of competing for dominance in the region">Rival</div>
|
||||
<div data-tip="Vassal is a state having obligation to its suzerain">Vassal</div>
|
||||
<div data-tip="Suzerain is a state having some control over its vassals">Suzerain</div>
|
||||
</div>
|
||||
<div class="info-line">Click on state name to see relations.<br>Click on relations name to change it</div>
|
||||
|
||||
<div id="diplomacyBottom" style="margin-top: .1em">
|
||||
<button id="diplomacyEditorRefresh" data-tip="Refresh the Editor" class="icon-cw"></button>
|
||||
<button id="diplomacyEditStyle" data-tip="Edit states (including diplomacy view) style in Style Editor" class="icon-adjust"></button>
|
||||
<button id="diplomacyRegenerate" data-tip="Regenerate diplomatical relations" class="icon-retweet"></button>
|
||||
<button id="diplomacyReset" data-tip="Reset diplomatical relations of selected state to Neutral" class="icon-eraser"></button>
|
||||
<button id="diplomacyHistory" data-tip="Show relations history" class="icon-hourglass-1"></button>
|
||||
<button id="diplomacyMatrix" data-tip="Show relations matrix" class="icon-list-bullet"></button>
|
||||
<button id="diplomacyShowMatrix" data-tip="Show relations matrix" class="icon-list-bullet"></button>
|
||||
<button id="diplomacyExport" data-tip="Save state relations matrix as a text file (.csv)" class="icon-download"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="diplomacyMatrix" class="dialog" style="display: none">
|
||||
<div id="diplomacyMatrixBody" class="matrix-table"></div>
|
||||
</div>
|
||||
|
||||
<div id="provinceNameEditor" class="dialog" data-province="0" style="display: none">
|
||||
<div>
|
||||
<div data-tip="Province short name" class="label">Short name:</div>
|
||||
|
|
@ -2779,6 +2739,8 @@
|
|||
<option value="Autonomy">Autonomy</option>
|
||||
<option value="Barony">Barony</option>
|
||||
<option value="Canton">Canton</option>
|
||||
<option value="Captaincy">Captaincy</option>
|
||||
<option value="Chiefdom">Chiefdom</option>
|
||||
<option value="Clan">Clan</option>
|
||||
<option value="Colony">Colony</option>
|
||||
<option value="Council">Council</option>
|
||||
|
|
@ -2786,6 +2748,7 @@
|
|||
<option value="Deanery">Deanery</option>
|
||||
<option value="Department">Department</option>
|
||||
<option value="Dependency">Dependency</option>
|
||||
<option value="Diaconate">Diaconate</option>
|
||||
<option value="District">District</option>
|
||||
<option value="Earldom">Earldom</option>
|
||||
<option value="Governorate">Governorate</option>
|
||||
|
|
@ -2795,6 +2758,7 @@
|
|||
<option value="Landgrave">Landgrave</option>
|
||||
<option value="Mandate">Mandate</option>
|
||||
<option value="Margrave">Margrave</option>
|
||||
<option value="Municipality">Municipality</option>
|
||||
<option value="Occupation zone">Occupation zone</option>
|
||||
<option value="Parish">Parish</option>
|
||||
<option value="Prefecture">Prefecture</option>
|
||||
|
|
@ -2802,6 +2766,7 @@
|
|||
<option value="Region">Region</option>
|
||||
<option value="Republic">Republic</option>
|
||||
<option value="Reservation">Reservation</option>
|
||||
<option value="Seneschalty">Seneschalty</option>
|
||||
<option value="Shire">Shire</option>
|
||||
<option value="State">State</option>
|
||||
<option value="Territory">Territory</option>
|
||||
|
|
@ -2869,21 +2834,22 @@
|
|||
<div id="namesbaseBasesTop">
|
||||
<span>Select base: </span>
|
||||
<select id="namesbaseSelect" data-tip="Select base to edit" style="width: 12em" value="0"></select>
|
||||
<span style="margin-left: 2px">Names data: </span>
|
||||
</div>
|
||||
|
||||
<div id="namesbaseBody">
|
||||
<span>Names data:</span><br>
|
||||
<textarea id="namesbaseTextarea" data-base="0" rows=12 data-tip="Names data: a comma separated list of source names used for names generation" placeholder="Provide a names data: a comma separated list of source names" autocorrect="off" spellcheck="false"></textarea>
|
||||
<br>
|
||||
<div id="namesbaseBody" style="margin-block: 2px">
|
||||
<textarea id="namesbaseTextarea" data-base="0" rows=13 data-tip="Names data: a comma separated list of source names used for names generation" placeholder="Provide a names data: a comma separated list of source names" autocorrect="off" spellcheck="false"></textarea>
|
||||
|
||||
<div>
|
||||
<span>Name: </span>
|
||||
<input id="namesbaseName" data-tip="Type to change a base name" placeholder="Base name" autocorrect="off" spellcheck="false" style="width:12em"/>
|
||||
<span>Length: </span>
|
||||
<input id="namesbaseMin" data-tip="Recommended minimum name length" type="number" min=2 max=100>
|
||||
<input id="namesbaseMax" data-tip="Recommended maximum name length" type="number" min=2 value=10>
|
||||
<span>Double: </span>
|
||||
<span>Doubled: </span>
|
||||
<input id="namesbaseDouble" data-tip="Populate with letters that can used twice in a row (geminates)" autocorrect="off" spellcheck="false" style="width:10em">
|
||||
</div>
|
||||
|
||||
<fieldset>
|
||||
<legend>Generated examples: </legend>
|
||||
<div id="namesbaseExamples" data-tip="Examples. Click to re-generate"></div>
|
||||
|
|
@ -2892,12 +2858,12 @@
|
|||
|
||||
<div id="namesbaseBottom">
|
||||
<button id="namesbaseUpdateExamples" data-tip="Re-generate examples based on provided data" class="icon-arrows-cw"></button>
|
||||
<button id="namesbaseAnalize" data-tip="Analyze namesbase to get a validity and quality overview" class="icon-flask"></button>
|
||||
<button id="namesbaseAdd" data-tip="Add new namesbase" class="icon-plus"></button>
|
||||
<button id="namesbaseDefault" data-tip="Restore default namesbase" class="icon-cancel"></button>
|
||||
<button id="namesbaseDownload" data-tip="Download namesbase to PC" class="icon-download"></button>
|
||||
<button id="namesbaseUpload" data-tip="Upload a namesbase from PC" class="icon-upload"></button>
|
||||
<button id="namesbaseCA" data-tip="Find or share custom namesbase on Cartography Assets portal" class="icon-drafting-compass" onclick="openURL('https://cartographyassets.com/asset-category/specific-assets/azgaars-generator/namebases/')"></button>
|
||||
<button id="namesbaseCA" data-tip="Find or share custom namesbase on Cartography Assets portal" class="icon-drafting-compass"></button>
|
||||
<button id="namesbaseAnalyze" data-tip="Analyze namesbase to get a validity and quality overview" class="icon-flask"></button>
|
||||
<button id="namesbaseSpeak" data-tip="Speak the examples. You can change voice and language in options" class="icon-voice"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -3310,6 +3276,7 @@
|
|||
<button id="addNewBurg" data-tip="Add a new burg. Hold Shift to add multiple" class="icon-plus"></button>
|
||||
<button id="burgsExport" data-tip="Save burgs-related data as a text file (.csv)" class="icon-download"></button>
|
||||
<button id="burgNamesImport" data-tip="Rename burgs in bulk" class="icon-upload"></button>
|
||||
<button id="burgsLockAll" data-tip="Lock or unlock all burgs" class="icon-lock"></button>
|
||||
<button id="burgsRemoveAll" data-tip="Remove all unlocked burgs except for capitals. To remove a capital remove its state first" class="icon-trash"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -3609,7 +3576,19 @@
|
|||
</div>
|
||||
<p>GeoJSON format is used in GIS tools such as QGIS. Check out <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/GIS-data-export" target="_blank">wiki-page</a> for guidance.</p>
|
||||
<p>Generator uses pop-up window to download files. Please ensure your browser does not block popups.</p>
|
||||
<p>It's also possible to export map to <i>Foundry VTT</i>, see <a href="https://github.com/Ethck/azgaar-foundry" target="_blank">the module.</a></p>
|
||||
|
||||
<div style="margin: 1em 0 .3em; font-weight: bold">Export To JSON</div>
|
||||
<div>
|
||||
<button onclick="exportToJson('Full')" data-tip="Download full data as in JSON format">full</button>
|
||||
<button onclick="exportToJson('Minimal')" data-tip="Download minimal data as in JSON format">minimal</button>
|
||||
<button onclick="exportToJson('PackCells')" data-tip="Download map metadata and pack cells data as in JSON format">pack cells</button>
|
||||
<button onclick="exportToJson('GridCells')" data-tip="Download map metadata and grid cells data as in JSON format">grid cells</button>
|
||||
</div>
|
||||
<p>Export in JSON format can be used as an API replacement.</p>
|
||||
|
||||
<div>
|
||||
<p>It's also possible to export map to <i>Foundry VTT</i>, see <a href="https://github.com/Ethck/azgaar-foundry" target="_blank">the module.</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="saveMapData" style="display: none" class="dialog">
|
||||
|
|
@ -3662,8 +3641,7 @@
|
|||
<div data-tip="Image scale relative to image size (e.g. 5x)" style="margin-bottom: .3em">
|
||||
<div class="label">Scale:</div>
|
||||
<input id="tileScaleInput" data-stored="tileScale" type="range" min=1 max=4 value=1 style="width: 10em">
|
||||
<input id="tileScaleOutput" data-stored="tileScale" type="number" min=1 value=1
|
||||
>
|
||||
<input id="tileScaleOutput" data-stored="tileScale" type="number" min=1 value=1 >
|
||||
</div>
|
||||
<div data-tip="Calculated size of image if combined" style="margin-bottom: .3em">
|
||||
<div class="label">Total size:</div>
|
||||
|
|
@ -3679,7 +3657,7 @@
|
|||
<div id="prompt" style="display: none" class="dialog">
|
||||
<form id="promptForm">
|
||||
<div id="promptText"></div>
|
||||
<input id="promptInput" type="number" step=.01 placeholder="type value" autocomplete="off" required>
|
||||
<input id="promptInput" type="number" step=.01 placeholder="type value" autocomplete="off">
|
||||
<button type="submit">Confirm</button>
|
||||
<button type="button" id="promptCancel" formnovalidate>Cancel</button>
|
||||
</form>
|
||||
|
|
@ -4355,6 +4333,153 @@
|
|||
<path d="M 43.4,0 36.2,12.5 43.4,25 M 21.7,12.5 H 36.2 Z M 0,0 H 14.5 L 21.7,12.5 14.5,25 H 0"/>
|
||||
</pattern>
|
||||
</g>
|
||||
|
||||
<g id="defs-hatching">
|
||||
<pattern id="hatch0" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch1" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch2" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch3" patternTransform="rotate(-45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch4" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="0" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch5" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="0" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch6" patternUnits="userSpaceOnUse" width="5" height="5">
|
||||
<circle cx="2.5" cy="2.5" r="1" style="fill: black"/>
|
||||
</pattern>
|
||||
<pattern id="hatch7" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="3" transform="rotate(-45 0 0)" style="stroke:black; stroke-width:1.5" />
|
||||
</pattern>
|
||||
<pattern id="hatch8" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="3" style="stroke:black; stroke-width:2.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch9" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="3" style="stroke:black; stroke-width:2.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch10" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="3" y2="0" style="stroke:black; stroke-width:2.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch11" patternTransform="rotate(-45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="3" style="stroke:black; stroke-width:2.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch12" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="1" x2="0" y2="3" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="1" y1="0" x2="3" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch13" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="3" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="0" y1="0" x2="3" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch14" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="1" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch15" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="1" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch16" patternTransform="rotate(-45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="1" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch17" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="1" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="1" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch18" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="1" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="1" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch19" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="2" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch20" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="2" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch21" patternTransform="rotate(-45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="2" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch22" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="2" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="2" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch23" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="3" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="0" y1="0" x2="3" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch24" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="2" y1="0" x2="0" y2="4" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="2" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch25" patternTransform="rotate(-45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="2" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch26" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="2" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch27" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="2" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch28" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="2" y1="0" x2="0" y2="2" style="stroke:black; stroke-width:2"/>
|
||||
</pattern>
|
||||
<pattern id="hatch29" patternTransform="rotate(30 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="1" x2="0" y2="3" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="1" y1="0" x2="3" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch30" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="1" y1="0" x2="0" y2="3" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="1" y1="0" x2="3" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch31" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="1" y1="0" x2="0" y2="3" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="1" y1="0" x2="3" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch32" patternUnits="userSpaceOnUse" width="5" height="5">
|
||||
<circle cx="2.5" cy="2.5" r="0.5" style="fill: black"/>
|
||||
</pattern>
|
||||
<pattern id="hatch33" patternUnits="userSpaceOnUse" width="5" height="5">
|
||||
<circle cx="2.5" cy="2.5" r="1.5" style="fill: black"/>
|
||||
</pattern>
|
||||
<pattern id="hatch34" patternUnits="userSpaceOnUse" width="5" height="5">
|
||||
<circle cx="3" cy="3" r="1" style="fill: black"/>
|
||||
<circle cx="1" cy="1" r="1" style="fill: black"/>
|
||||
</pattern>
|
||||
<pattern id="hatch35" patternUnits="userSpaceOnUse" width="5" height="5">
|
||||
<circle cx="3" cy="3" r="1.5" style="fill: black"/>
|
||||
<circle cx="1" cy="1" r="1.5" style="fill: black"/>
|
||||
</pattern>
|
||||
<pattern id="hatch36" patternTransform="rotate(-45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="3" transform="rotate(-45 0 0)" style="stroke:black; stroke-width:1.5" />
|
||||
</pattern>
|
||||
<pattern id="hatch37" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="0" y2="3" transform="rotate(-45 0 0)" style="stroke:black; stroke-width:1.5" />
|
||||
</pattern>
|
||||
<pattern id="hatch38" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="4" y2="4" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="0" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch39" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="4" y2="4" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="0" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch40" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="3" y2="3" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="0" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
<pattern id="hatch41" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="4" height="4">
|
||||
<line x1="0" y1="0" x2="3" y2="3" style="stroke:black; stroke-width:1.5"/>
|
||||
<line x1="0" y1="0" x2="4" y2="0" style="stroke:black; stroke-width:1.5"/>
|
||||
</pattern>
|
||||
</g>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
|
|
@ -4395,18 +4520,20 @@
|
|||
<script src="modules/fonts.js"></script>
|
||||
<script src="modules/ui/layers.js"></script>
|
||||
<script src="modules/ui/measurers.js"></script>
|
||||
<script src="modules/ui/stylePresets.js"></script>
|
||||
<!-- <script src="libs/umami.js"></script> -->
|
||||
|
||||
<script defer src="https://unpkg.com/dropbox@10.8.0/dist/Dropbox-sdk.min.js"></script>
|
||||
<script defer src="modules/ui/general.js"></script>
|
||||
<script defer src="modules/ui/options.js"></script>
|
||||
<script defer src="modules/ui/style.js"></script>
|
||||
<script src="modules/ui/general.js"></script>
|
||||
<script src="modules/ui/options.js"></script>
|
||||
<script src="main.js"></script>
|
||||
|
||||
<script defer src="modules/load.js"></script>
|
||||
<script defer src="modules/cloud.js"></script>
|
||||
<script defer src="main.js"></script>
|
||||
<script defer src="modules/export-json.js"></script>
|
||||
<script defer src="modules/save.js"></script>
|
||||
<script defer src="modules/export.js"></script>
|
||||
<script defer src="modules/relief-icons.js"></script>
|
||||
<script defer src="modules/ui/style.js"></script>
|
||||
<script defer src="modules/ui/tools.js"></script>
|
||||
<script defer src="modules/ui/world-configurator.js"></script>
|
||||
<script defer src="modules/ui/editors.js"></script>
|
||||
|
|
@ -4417,6 +4544,7 @@
|
|||
<script defer src="modules/ui/cultures-editor.js"></script>
|
||||
<script defer src="modules/ui/namesbase-editor.js"></script>
|
||||
<script defer src="modules/ui/elevation-profile.js"></script>
|
||||
<script defer src="modules/ui/temperature-graph.js"></script>
|
||||
<script defer src="modules/ui/routes-editor.js"></script>
|
||||
<script defer src="modules/ui/ice-editor.js"></script>
|
||||
<script defer src="modules/ui/lakes-editor.js"></script>
|
||||
|
|
@ -4426,7 +4554,6 @@
|
|||
<script defer src="modules/ui/rivers-creator.js"></script>
|
||||
<script defer src="modules/ui/relief-editor.js"></script>
|
||||
<script defer src="modules/ui/religions-editor.js"></script>
|
||||
<script defer src="modules/ui/markers-editor.js"></script>
|
||||
<script defer src="modules/ui/burg-editor.js"></script>
|
||||
<script defer src="modules/ui/units-editor.js"></script>
|
||||
<script defer src="modules/ui/notes-editor.js"></script>
|
||||
|
|
@ -4439,13 +4566,18 @@
|
|||
<script defer src="modules/ui/markers-overview.js"></script>
|
||||
<script defer src="modules/ui/regiment-editor.js"></script>
|
||||
<script defer src="modules/ui/battle-screen.js"></script>
|
||||
<script defer src="modules/coa-renderer.js"></script>
|
||||
<script defer src="modules/ui/emblems-editor.js"></script>
|
||||
<script defer src="modules/ui/markers-editor.js"></script>
|
||||
<script defer src="modules/ui/3d.js"></script>
|
||||
<script defer src="modules/ui/hotkeys.js"></script>
|
||||
<script defer src="modules/coa-renderer.js"></script>
|
||||
<script defer src="libs/rgbquant.min.js"></script>
|
||||
<script defer src="libs/jquery.ui.touch-punch.min.js"></script>
|
||||
<script defer src="libs/pell.min.js"></script>
|
||||
<script defer src="libs/jszip.min.js"></script>
|
||||
<script defer src="https://unpkg.com/dropbox@10.8.0/dist/Dropbox-sdk.min.js"></script>
|
||||
|
||||
<!-- Web Components -->
|
||||
<script defer src="components/fill-box.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
92
main.js
92
main.js
|
|
@ -1,11 +1,11 @@
|
|||
// Azgaar (azgaar.fmg@yandex.com). Minsk, 2017-2021. MIT License
|
||||
// Azgaar (azgaar.fmg@yandex.com). Minsk, 2017-2022. MIT License
|
||||
// https://github.com/Azgaar/Fantasy-Map-Generator
|
||||
|
||||
"use strict";
|
||||
const version = "1.71"; // generator version
|
||||
const version = "1.73"; // generator version
|
||||
document.title += " v" + version;
|
||||
|
||||
// Switches to disable/enable logging features
|
||||
// switches to disable/enable logging features
|
||||
const PRODUCTION = location.hostname && location.hostname !== "localhost" && location.hostname !== "127.0.0.1";
|
||||
const DEBUG = localStorage.getItem("debug");
|
||||
const INFO = DEBUG || !PRODUCTION;
|
||||
|
|
@ -109,7 +109,7 @@ scaleBar.on("mousemove", () => tip("Click to open Units Editor")).on("click", ()
|
|||
legend.on("mousemove", () => tip("Drag to change the position. Click to hide the legend")).on("click", () => clearLegend());
|
||||
|
||||
// main data variables
|
||||
let grid = {}; // initial grapg based on jittered square grid and data
|
||||
let grid = {}; // initial graph based on jittered square grid and data
|
||||
let pack = {}; // packed graph and data
|
||||
let seed;
|
||||
let mapId;
|
||||
|
|
@ -161,7 +161,7 @@ let urbanDensity = +document.getElementById("urbanDensityInput").value;
|
|||
|
||||
applyStoredOptions();
|
||||
|
||||
// voronoi graph extention, cannot be changed arter generation
|
||||
// voronoi graph extension, cannot be changed after generation
|
||||
let graphWidth = +mapWidthInput.value;
|
||||
let graphHeight = +mapHeightInput.value;
|
||||
|
||||
|
|
@ -173,14 +173,37 @@ landmass.append("rect").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr
|
|||
oceanPattern.append("rect").attr("fill", "url(#oceanic)").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr("height", graphHeight);
|
||||
oceanLayers.append("rect").attr("id", "oceanBase").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr("height", graphHeight);
|
||||
|
||||
// remove loading screen
|
||||
d3.select("#loading").transition().duration(4000).style("opacity", 0).remove();
|
||||
d3.select("#initial").transition().duration(4000).attr("opacity", 0).remove();
|
||||
d3.select("#optionsContainer").transition().duration(3000).style("opacity", 1);
|
||||
d3.select("#tooltip").transition().duration(4000).style("opacity", 1);
|
||||
if (!location.hostname) {
|
||||
const wiki = "https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Run-FMG-locally";
|
||||
alertMessage.innerHTML = `Fantasy Map Generator cannot run serverless.
|
||||
Follow the <a href="${wiki}" target="_blank">instructions</a> on how you can easily run a local web-server`;
|
||||
|
||||
$("#alert").dialog({
|
||||
resizable: false,
|
||||
title: "Loading error",
|
||||
width: "28em",
|
||||
position: {my: "center center-4em", at: "center", of: "svg"},
|
||||
buttons: {
|
||||
OK: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
d3.select("#loading-text").transition().duration(1000).style("opacity", 0);
|
||||
d3.select("#init-rose").transition().duration(4000).style("opacity", 0);
|
||||
} else {
|
||||
checkLoadParameters();
|
||||
|
||||
// remove loading screen
|
||||
d3.select("#loading").transition().duration(4000).style("opacity", 0).remove();
|
||||
d3.select("#initial").transition().duration(4000).attr("opacity", 0).remove();
|
||||
d3.select("#optionsContainer").transition().duration(3000).style("opacity", 1);
|
||||
d3.select("#tooltip").transition().duration(4000).style("opacity", 1);
|
||||
}
|
||||
|
||||
// decide which map should be loaded or generated on page load
|
||||
void (function checkLoadParameters() {
|
||||
function checkLoadParameters() {
|
||||
const url = new URL(window.location.href);
|
||||
const params = url.searchParams;
|
||||
|
||||
|
|
@ -225,10 +248,10 @@ void (function checkLoadParameters() {
|
|||
|
||||
WARN && console.warn("Generate random map");
|
||||
generateMapOnLoad();
|
||||
})();
|
||||
}
|
||||
|
||||
function generateMapOnLoad() {
|
||||
applyStyleOnLoad(); // apply default or previously selected style
|
||||
async function generateMapOnLoad() {
|
||||
await applyStyleOnLoad(); // apply previously selected default or custom style
|
||||
generate(); // generate map
|
||||
focusOn(); // based on searchParams focus on point, cell or burg from MFCG
|
||||
applyPreset(); // apply saved layers preset
|
||||
|
|
@ -412,20 +435,18 @@ function showWelcomeMessage() {
|
|||
|
||||
alertMessage.innerHTML = `The Fantasy Map Generator is updated up to version <b>${version}</b>.
|
||||
This version is compatible with ${changelog}, loaded <i>.map</i> files will be auto-updated.
|
||||
<ul>Main changes:
|
||||
<li>Ability to limit military units by biome, state, culture and religion</li>
|
||||
<li>New marker types</li>
|
||||
<li>New markers editor</li>
|
||||
<li>Markers overview screen</li>
|
||||
<li>Markers regeneration menu</li>
|
||||
<li>Burg editor update</li>
|
||||
<li>Editable theme color</li>
|
||||
<li>Add font dialog</li>
|
||||
<li>Save to Dropbox</li>
|
||||
<ul><b>Latest changes:</b>
|
||||
<li>Color picker: new hatchings</li>
|
||||
<li>New style presets: Cyberpunk and Atlas</li>
|
||||
<li>Burg temperature graph</li>
|
||||
<li>4 new textures</li>
|
||||
<li>Province capture logic rework</li>
|
||||
<li>Button to release all provinces</li>
|
||||
<li>Limit military units by biome, state, culture and religion</li>
|
||||
</ul>
|
||||
|
||||
<p>Join our ${discord} and ${reddit} to ask questions, share maps, discuss the Generator and Worlbuilding, report bugs and propose new features.</p>
|
||||
<span>Thanks for all supporters on <a href="https://www.patreon.com/azgaar" target="_blank">Patreon</a>!</i></span>`;
|
||||
<span><i>Thanks for all supporters on ${patreon}!</i></span>`;
|
||||
|
||||
$("#alert").dialog({
|
||||
resizable: false,
|
||||
|
|
@ -493,7 +514,7 @@ function invokeActiveZooming() {
|
|||
coastline.select("#sea_island").attr("filter", filter);
|
||||
}
|
||||
|
||||
// rescale lables on zoom
|
||||
// rescale labels on zoom
|
||||
if (labels.style("display") !== "none") {
|
||||
labels.selectAll("g").each(function () {
|
||||
if (this.id === "burgLabels") return;
|
||||
|
|
@ -668,7 +689,7 @@ function generate() {
|
|||
const parsedError = parseError(error);
|
||||
clearMainTip();
|
||||
|
||||
alertMessage.innerHTML = `An error is occured on map generation. Please retry.
|
||||
alertMessage.innerHTML = `An error has occurred on map generation. Please retry.
|
||||
<br>If error is critical, clear the stored data and try again.
|
||||
<p id="errorBox">${parsedError}</p>`;
|
||||
$("#alert").dialog({
|
||||
|
|
@ -980,7 +1001,10 @@ function generatePrecipitation() {
|
|||
prec.selectAll("*").remove();
|
||||
const {cells, cellsX, cellsY} = grid;
|
||||
cells.prec = new Uint8Array(cells.i.length); // precipitation array
|
||||
const modifier = precInput.value / 100; // user's input
|
||||
|
||||
const cellsNumberModifier = (pointsInput.dataset.cells / 10000) ** 0.25;
|
||||
const precInputModifier = precInput.value / 100;
|
||||
const modifier = cellsNumberModifier * precInputModifier;
|
||||
|
||||
const westerly = [];
|
||||
const easterly = [];
|
||||
|
|
@ -996,14 +1020,14 @@ function generatePrecipitation() {
|
|||
// x2 = 60-70 latitude: wet summer (rising zone), dry winter (sinking zone)
|
||||
// x1 = 70-85 latitude: dry all year (sinking zone)
|
||||
// x0.5 = 85-90 latitude: dry all year (sinking zone)
|
||||
const lalitudeModifier = [4, 2, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3, 2, 2, 1, 1, 1, 0.5];
|
||||
const latitudeModifier = [4, 2, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3, 2, 2, 1, 1, 1, 0.5];
|
||||
const MAX_PASSABLE_ELEVATION = 85;
|
||||
|
||||
// define wind directions based on cells latitude and prevailing winds there
|
||||
d3.range(0, cells.i.length, cellsX).forEach(function (c, i) {
|
||||
const lat = mapCoordinates.latN - (i / cellsY) * mapCoordinates.latT;
|
||||
const latBand = ((Math.abs(lat) - 1) / 5) | 0;
|
||||
const latMod = lalitudeModifier[latBand];
|
||||
const latMod = latitudeModifier[latBand];
|
||||
const windTier = (Math.abs(lat - 89) / 30) | 0; // 30d tiers from 0 to 5 from N to S
|
||||
const {isWest, isEast, isNorth, isSouth} = getWindDirections(windTier);
|
||||
|
||||
|
|
@ -1020,14 +1044,14 @@ function generatePrecipitation() {
|
|||
const vertT = southerly + northerly;
|
||||
if (northerly) {
|
||||
const bandN = ((Math.abs(mapCoordinates.latN) - 1) / 5) | 0;
|
||||
const latModN = mapCoordinates.latT > 60 ? d3.mean(lalitudeModifier) : lalitudeModifier[bandN];
|
||||
const latModN = mapCoordinates.latT > 60 ? d3.mean(latitudeModifier) : latitudeModifier[bandN];
|
||||
const maxPrecN = (northerly / vertT) * 60 * modifier * latModN;
|
||||
passWind(d3.range(0, cellsX, 1), maxPrecN, cellsX, cellsY);
|
||||
}
|
||||
|
||||
if (southerly) {
|
||||
const bandS = ((Math.abs(mapCoordinates.latS) - 1) / 5) | 0;
|
||||
const latModS = mapCoordinates.latT > 60 ? d3.mean(lalitudeModifier) : lalitudeModifier[bandS];
|
||||
const latModS = mapCoordinates.latT > 60 ? d3.mean(latitudeModifier) : latitudeModifier[bandS];
|
||||
const maxPrecS = (southerly / vertT) * 60 * modifier * latModS;
|
||||
passWind(d3.range(cells.i.length - cellsX, cells.i.length, 1), maxPrecS, -cellsX, cellsY);
|
||||
}
|
||||
|
|
@ -1181,7 +1205,7 @@ function reGraph() {
|
|||
TIME && console.timeEnd("reGraph");
|
||||
}
|
||||
|
||||
// Detect and draw the coasline
|
||||
// Detect and draw the coastline
|
||||
function drawCoastline() {
|
||||
TIME && console.time("drawCoastline");
|
||||
reMarkFeatures();
|
||||
|
|
@ -1190,7 +1214,7 @@ function drawCoastline() {
|
|||
vertices = pack.vertices,
|
||||
n = cells.i.length,
|
||||
features = pack.features;
|
||||
const used = new Uint8Array(features.length); // store conneted features
|
||||
const used = new Uint8Array(features.length); // store connected features
|
||||
const largestLand = d3.scan(
|
||||
features.map(f => (f.land ? f.cells : 0)),
|
||||
(a, b) => b - a
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ window.BurgsAndStates = (function () {
|
|||
|
||||
function placeCapitals() {
|
||||
TIME && console.time("placeCapitals");
|
||||
let count = +regionsInput.value;
|
||||
let count = +regionsOutput.value;
|
||||
let burgs = [0];
|
||||
|
||||
const rand = () => 0.5 + Math.random() * 0.5;
|
||||
|
|
@ -240,7 +240,7 @@ window.BurgsAndStates = (function () {
|
|||
b.citadel = b.capital || (pop > 50 && P(0.75)) || P(0.5) ? 1 : 0;
|
||||
b.plaza = pop > 50 || (pop > 30 && P(0.75)) || (pop > 10 && P(0.5)) || P(0.25) ? 1 : 0;
|
||||
b.walls = b.capital || pop > 30 || (pop > 20 && P(0.75)) || (pop > 10 && P(0.5)) || P(0.2) ? 1 : 0;
|
||||
b.shanty = pop > 30 || (pop > 20 && P(0.75)) || (b.walls && P(0.75)) ? 1 : 0;
|
||||
b.shanty = pop > 60 || (pop > 40 && P(0.75)) || (pop > 20 && b.walls && P(0.4)) ? 1 : 0;
|
||||
const religion = cells.religion[b.cell];
|
||||
const theocracy = pack.states[b.state].form === "Theocracy";
|
||||
b.temple = (religion && theocracy) || pop > 50 || (pop > 35 && P(0.75)) || (pop > 20 && P(0.5)) ? 1 : 0;
|
||||
|
|
@ -726,7 +726,7 @@ window.BurgsAndStates = (function () {
|
|||
TIME && console.time("assignColors");
|
||||
const colors = ["#66c2a5", "#fc8d62", "#8da0cb", "#e78ac3", "#a6d854", "#ffd92f"]; // d3.schemeSet2;
|
||||
|
||||
// assin basic color using greedy coloring algorithm
|
||||
// assign basic color using greedy coloring algorithm
|
||||
pack.states.forEach(s => {
|
||||
if (!s.i || s.removed) return;
|
||||
const neibs = s.neighbors;
|
||||
|
|
@ -962,12 +962,12 @@ window.BurgsAndStates = (function () {
|
|||
const republic = {
|
||||
Republic: 75,
|
||||
Federation: 4,
|
||||
Oligarchy: 2,
|
||||
"Trade Company": 4,
|
||||
"Most Serene Republic": 2,
|
||||
Oligarchy: 2,
|
||||
Tetrarchy: 1,
|
||||
Triumvirate: 1,
|
||||
Diarchy: 1,
|
||||
"Trade Company": 4,
|
||||
Junta: 1
|
||||
}; // weighted random
|
||||
const union = {Union: 3, League: 4, Confederation: 1, "United Kingdom": 1, "United Republic": 1, "United Provinces": 2, Commonwealth: 1, Heptarchy: 1}; // weighted random
|
||||
|
|
@ -997,7 +997,7 @@ window.BurgsAndStates = (function () {
|
|||
const form = monarchy[tier];
|
||||
// Default name depends on exponent tier, some culture bases have special names for tiers
|
||||
if (s.diplomacy) {
|
||||
if (form === "Duchy" && s.neighbors.length > 1 && rand(6) < s.neighbors.length && s.diplomacy.includes("Vassal")) return "Marches"; // some vassal dutchies on borderland
|
||||
if (form === "Duchy" && s.neighbors.length > 1 && rand(6) < s.neighbors.length && s.diplomacy.includes("Vassal")) return "Marches"; // some vassal duchies on borderland
|
||||
if (base === 1 && P(0.3) && s.diplomacy.includes("Vassal")) return "Dominion"; // English vassals
|
||||
if (P(0.3) && s.diplomacy.includes("Vassal")) return "Protectorate"; // some vassals
|
||||
}
|
||||
|
|
@ -1037,7 +1037,12 @@ window.BurgsAndStates = (function () {
|
|||
if (tier < 2 && P(0.5)) return "Diocese";
|
||||
if (tier < 2 && P(0.5)) return "Bishopric";
|
||||
}
|
||||
if (tier < 2 && P(0.9) && [7, 5].includes(base)) return "Eparchy"; // Greek, Ruthenian
|
||||
if (P(0.9) && [7, 5].includes(base)) {
|
||||
// Greek, Ruthenian
|
||||
if (tier < 2) return "Eparchy";
|
||||
if (tier === 2) return "Exarchate";
|
||||
if (tier > 2) return "Patriarchate";
|
||||
}
|
||||
if (P(0.9) && [21, 16].includes(base)) return "Imamah"; // Nigerian, Turkish
|
||||
if (tier > 2 && P(0.8) && [18, 17, 28].includes(base)) return "Caliphate"; // Arabic, Berber, Swahili
|
||||
return rw(theocracy);
|
||||
|
|
@ -1093,7 +1098,7 @@ window.BurgsAndStates = (function () {
|
|||
const max = percentage == 100 ? 1000 : gauss(20, 5, 5, 100) * percentage ** 0.5; // max growth
|
||||
|
||||
const forms = {
|
||||
Monarchy: {County: 11, Earldom: 3, Shire: 1, Landgrave: 1, Margrave: 1, Barony: 1},
|
||||
Monarchy: {County: 22, Earldom: 6, Shire: 2, Landgrave: 2, Margrave: 2, Barony: 2, Captaincy: 1, Seneschalty: 1},
|
||||
Republic: {Province: 6, Department: 2, Governorate: 2, District: 1, Canton: 1, Prefecture: 1},
|
||||
Theocracy: {Parish: 3, Deanery: 1},
|
||||
Union: {Province: 1, State: 1, Canton: 1, Republic: 1, County: 1, Council: 1},
|
||||
|
|
|
|||
|
|
@ -976,7 +976,7 @@ window.COA = (function () {
|
|||
|
||||
if (emblemShape.value === "state" && state && pack.states[state].coa) return pack.states[state].coa.shield;
|
||||
if (pack.cultures[culture].shield) return pack.cultures[culture].shield;
|
||||
console.error("Shield shape is not defined on culture level", pack.cultures[culture]);
|
||||
ERROR && console.error("Shield shape is not defined on culture level", pack.cultures[culture]);
|
||||
return "heater";
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1938,7 +1938,9 @@ window.COArenderer = (function () {
|
|||
g.setAttribute("id", charge + "_" + id);
|
||||
return g.outerHTML;
|
||||
})
|
||||
.catch(err => console.error(err));
|
||||
.catch(err => {
|
||||
ERROR && console.error(err);
|
||||
});
|
||||
return fetched;
|
||||
}
|
||||
|
||||
|
|
|
|||
209
modules/export-json.js
Normal file
209
modules/export-json.js
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
function exportToJson(type) {
|
||||
if (customization) return tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error");
|
||||
closeDialogs("#alert");
|
||||
|
||||
const typeMap = {
|
||||
Full: getFullDataJson,
|
||||
Minimal: getMinimalDataJson,
|
||||
PackCells: getPackCellsDataJson,
|
||||
GridCells: getGridCellsDataJson,
|
||||
};
|
||||
|
||||
const mapData = typeMap[type]();
|
||||
const blob = new Blob([mapData], {type: "application/json"});
|
||||
const URL = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.download = getFileName(type) + ".json";
|
||||
link.href = URL;
|
||||
link.click();
|
||||
tip(`${link.download} is saved. Open "Downloads" screen (CTRL + J) to check`, true, "success", 7000);
|
||||
window.URL.revokeObjectURL(URL);
|
||||
}
|
||||
|
||||
function getMapInfo() {
|
||||
const info = {
|
||||
version,
|
||||
description: "Azgaar's Fantasy Map Generator output: azgaar.github.io/Fantasy-map-generator",
|
||||
exportedAt: new Date().toISOString(),
|
||||
mapName: mapName.value,
|
||||
seed,
|
||||
mapId
|
||||
};
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
function getSettings() {
|
||||
const settings = {
|
||||
distanceUnit: distanceUnitInput.value,
|
||||
distanceScale: distanceScaleInput.value,
|
||||
areaUnit: areaUnit.value,
|
||||
heightUnit: heightUnit.value,
|
||||
heightExponent: heightExponentInput.value,
|
||||
temperatureScale: temperatureScale.value,
|
||||
barSize: barSizeInput.value,
|
||||
barLabel: barLabel.value,
|
||||
barBackOpacity: barBackOpacity.value,
|
||||
barBackColor: barBackColor.value,
|
||||
barPosX: barPosX.value,
|
||||
barPosY: barPosY.value,
|
||||
populationRate: populationRate,
|
||||
urbanization: urbanization,
|
||||
mapSize: mapSizeOutput.value,
|
||||
latitudeO: latitudeOutput.value,
|
||||
temperatureEquator: temperatureEquatorOutput.value,
|
||||
temperaturePole: temperaturePoleOutput.value,
|
||||
prec: precOutput.value,
|
||||
options: options,
|
||||
mapName: mapName.value,
|
||||
hideLabels: hideLabels.checked,
|
||||
stylePreset: stylePreset.value,
|
||||
rescaleLabels: rescaleLabels.checked,
|
||||
urbanDensity: urbanDensity
|
||||
};
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
function getPackCellsData() {
|
||||
const cellConverted = {
|
||||
i: Array.from(pack.cells.i),
|
||||
v: pack.cells.v,
|
||||
c: pack.cells.c,
|
||||
p: pack.cells.p,
|
||||
g: Array.from(pack.cells.g),
|
||||
h: Array.from(pack.cells.h),
|
||||
area: Array.from(pack.cells.area),
|
||||
f: Array.from(pack.cells.f),
|
||||
t: Array.from(pack.cells.t),
|
||||
haven: Array.from(pack.cells.haven),
|
||||
harbor: Array.from(pack.cells.harbor),
|
||||
fl: Array.from(pack.cells.fl),
|
||||
r: Array.from(pack.cells.r),
|
||||
conf: Array.from(pack.cells.conf),
|
||||
biome: Array.from(pack.cells.biome),
|
||||
s: Array.from(pack.cells.s),
|
||||
pop: Array.from(pack.cells.pop),
|
||||
culture: Array.from(pack.cells.culture),
|
||||
burg: Array.from(pack.cells.burg),
|
||||
road: Array.from(pack.cells.road),
|
||||
crossroad: Array.from(pack.cells.crossroad),
|
||||
state: Array.from(pack.cells.state),
|
||||
religion: Array.from(pack.cells.religion),
|
||||
province: Array.from(pack.cells.province)
|
||||
};
|
||||
const cellObjArr = [];
|
||||
{
|
||||
cellConverted.i.forEach(value => {
|
||||
const cellobj = {
|
||||
i: value,
|
||||
v: cellConverted.v[value],
|
||||
c: cellConverted.c[value],
|
||||
p: cellConverted.p[value],
|
||||
g: cellConverted.g[value],
|
||||
h: cellConverted.h[value],
|
||||
area: cellConverted.area[value],
|
||||
f: cellConverted.f[value],
|
||||
t: cellConverted.t[value],
|
||||
haven: cellConverted.haven[value],
|
||||
harbor: cellConverted.harbor[value],
|
||||
fl: cellConverted.fl[value],
|
||||
r: cellConverted.r[value],
|
||||
conf: cellConverted.conf[value],
|
||||
biome: cellConverted.biome[value],
|
||||
s: cellConverted.s[value],
|
||||
pop: cellConverted.pop[value],
|
||||
culture: cellConverted.culture[value],
|
||||
burg: cellConverted.burg[value],
|
||||
road: cellConverted.road[value],
|
||||
crossroad: cellConverted.crossroad[value],
|
||||
state: cellConverted.state[value],
|
||||
religion: cellConverted.religion[value],
|
||||
province: cellConverted.province[value]
|
||||
};
|
||||
cellObjArr.push(cellobj);
|
||||
});
|
||||
}
|
||||
|
||||
const cellsData = {
|
||||
cells: cellObjArr,
|
||||
features: pack.features,
|
||||
cultures: pack.cultures,
|
||||
burgs: pack.burgs,
|
||||
states: pack.states,
|
||||
provinces: pack.provinces,
|
||||
religions: pack.religions,
|
||||
rivers: pack.rivers,
|
||||
markers: pack.markers
|
||||
};
|
||||
|
||||
return cellsData;
|
||||
}
|
||||
|
||||
//data only containing graphical appearance
|
||||
function getGridCellsData(){
|
||||
const gridData = {
|
||||
spacing: grid.spacing,
|
||||
cellsY: grid.cellsY,
|
||||
cellsX: grid.cellsX,
|
||||
points: grid.points,
|
||||
boundary: grid.boundary
|
||||
}
|
||||
return gridData
|
||||
}
|
||||
|
||||
function getFullDataJson() {
|
||||
TIME && console.time("getFullDataJson");
|
||||
|
||||
const info = getMapInfo();
|
||||
const settings = getSettings();
|
||||
const cells = getPackCellsData();
|
||||
const exportData = {info, settings, coords: mapCoordinates, cells, biomes: biomesData, notes, nameBases};
|
||||
|
||||
TIME && console.timeEnd("getFullDataJson");
|
||||
return JSON.stringify(exportData);
|
||||
}
|
||||
|
||||
// data excluding cells
|
||||
function getMinimalDataJson() {
|
||||
TIME && console.time("getMinimalDataJson");
|
||||
|
||||
const info = getMapInfo();
|
||||
const settings = getSettings();
|
||||
const packData = {
|
||||
features: pack.features,
|
||||
cultures: pack.cultures,
|
||||
burgs: pack.burgs,
|
||||
states: pack.states,
|
||||
provinces: pack.provinces,
|
||||
religions: pack.religions,
|
||||
rivers: pack.rivers,
|
||||
markers: pack.markers
|
||||
};
|
||||
const exportData = {info, settings, coords: mapCoordinates, pack: packData, biomes: biomesData, notes, nameBases};
|
||||
|
||||
TIME && console.timeEnd("getMinimalDataJson");
|
||||
return JSON.stringify(exportData);
|
||||
}
|
||||
|
||||
function getPackCellsDataJson() {
|
||||
TIME && console.time("getCellsDataJson");
|
||||
|
||||
const info = getMapInfo();
|
||||
const cells = getPackCellsData();
|
||||
const exportData = {info, cells};
|
||||
|
||||
TIME && console.timeEnd("getCellsDataJson");
|
||||
return JSON.stringify(exportData);
|
||||
}
|
||||
|
||||
function getGridCellsDataJson() {
|
||||
TIME && console.time("getGridCellsDataJson");
|
||||
|
||||
const info = getMapInfo();
|
||||
const gridCells = getGridCellsData()
|
||||
const exportData = {info,gridCells};
|
||||
|
||||
TIME && console.log("getGridCellsDataJson");
|
||||
return JSON.stringify(exportData);
|
||||
}
|
||||
|
|
@ -262,19 +262,19 @@ async function getMapURL(type, options = {}) {
|
|||
if (pattern) cloneDefs.appendChild(pattern.cloneNode(true));
|
||||
}
|
||||
|
||||
if (!cloneEl.getElementById("hatching").children.length) cloneEl.getElementById("hatching")?.remove(); // remove unused hatching group
|
||||
if (!cloneEl.getElementById("fogging-cont")) cloneEl.getElementById("fog")?.remove(); // remove unused fog
|
||||
if (!cloneEl.getElementById("regions")) cloneEl.getElementById("statePaths")?.remove(); // removed unused statePaths
|
||||
if (!cloneEl.getElementById("labels")) cloneEl.getElementById("textPaths")?.remove(); // removed unused textPaths
|
||||
|
||||
// add armies style
|
||||
if (cloneEl.getElementById("armies"))
|
||||
if (cloneEl.getElementById("armies")) {
|
||||
cloneEl.insertAdjacentHTML(
|
||||
"afterbegin",
|
||||
"<style>#armies text {stroke: none; fill: #fff; text-shadow: 0 0 4px #000; dominant-baseline: central; text-anchor: middle; font-family: Helvetica; fill-opacity: 1;}#armies text.regimentIcon {font-size: .8em;}</style>"
|
||||
);
|
||||
}
|
||||
|
||||
// add xlink: for href to support svg1.1
|
||||
// add xlink: for href to support svg 1.1
|
||||
if (type === "svg") {
|
||||
cloneEl.querySelectorAll("[href]").forEach(el => {
|
||||
const href = el.getAttribute("href");
|
||||
|
|
@ -283,6 +283,16 @@ async function getMapURL(type, options = {}) {
|
|||
});
|
||||
}
|
||||
|
||||
// add hatchings
|
||||
const hatchingUsers = cloneEl.querySelectorAll(`[fill^='url(#hatch']`);
|
||||
const hatchingFills = unique(Array.from(hatchingUsers).map(el => el.getAttribute("fill")));
|
||||
const hatchingIds = hatchingFills.map(fill => fill.slice(5, -1));
|
||||
for (const hatchingId of hatchingIds) {
|
||||
const hatching = svgDefs.getElementById(hatchingId);
|
||||
if (hatching) cloneDefs.appendChild(hatching.cloneNode(true));
|
||||
}
|
||||
|
||||
// load fonts
|
||||
const usedFonts = getUsedFonts(cloneEl);
|
||||
const fontsToLoad = usedFonts.filter(font => font.src);
|
||||
if (fontsToLoad.length) {
|
||||
|
|
@ -405,8 +415,8 @@ function saveGeoJSON_Cells() {
|
|||
json.features.push(feature);
|
||||
});
|
||||
|
||||
const name = getFileName("Cells") + ".geojson";
|
||||
downloadFile(JSON.stringify(json), name, "application/json");
|
||||
const fileName = getFileName("Cells") + ".geojson";
|
||||
downloadFile(JSON.stringify(json), fileName, "application/json");
|
||||
}
|
||||
|
||||
function saveGeoJSON_Routes() {
|
||||
|
|
@ -421,30 +431,25 @@ function saveGeoJSON_Routes() {
|
|||
json.features.push(feature);
|
||||
});
|
||||
|
||||
const name = getFileName("Routes") + ".geojson";
|
||||
downloadFile(JSON.stringify(json), name, "application/json");
|
||||
const fileName = getFileName("Routes") + ".geojson";
|
||||
downloadFile(JSON.stringify(json), fileName, "application/json");
|
||||
}
|
||||
|
||||
function saveGeoJSON_Rivers() {
|
||||
const json = {type: "FeatureCollection", features: []};
|
||||
|
||||
rivers.selectAll("path").each(function () {
|
||||
const coordinates = getRiverPoints(this);
|
||||
const id = this.id;
|
||||
const width = +this.dataset.increment;
|
||||
const increment = +this.dataset.increment;
|
||||
const river = pack.rivers.find(r => r.i === +id.slice(5));
|
||||
const name = river ? river.name : "";
|
||||
const type = river ? river.type : "";
|
||||
const i = river ? river.i : "";
|
||||
const basin = river ? river.basin : "";
|
||||
const river = pack.rivers.find(r => r.i === +this.id.slice(5));
|
||||
if (!river) return;
|
||||
|
||||
const feature = {type: "Feature", geometry: {type: "LineString", coordinates}, properties: {id, i, basin, name, type, width, increment}};
|
||||
const coordinates = getRiverPoints(this);
|
||||
const properties = {...river, id: this.id};
|
||||
const feature = {type: "Feature", geometry: {type: "LineString", coordinates}, properties};
|
||||
json.features.push(feature);
|
||||
});
|
||||
|
||||
const name = getFileName("Rivers") + ".geojson";
|
||||
downloadFile(JSON.stringify(json), name, "application/json");
|
||||
const fileName = getFileName("Rivers") + ".geojson";
|
||||
downloadFile(JSON.stringify(json), fileName, "application/json");
|
||||
}
|
||||
|
||||
function saveGeoJSON_Markers() {
|
||||
|
|
|
|||
|
|
@ -14,12 +14,14 @@ const fonts = [
|
|||
{
|
||||
family: "Almendra SC",
|
||||
src: "url(https://fonts.gstatic.com/s/almendrasc/v13/Iure6Yx284eebowr7hbyTaZOrLQ.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
unicodeRange:
|
||||
"U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Amatic SC",
|
||||
src: "url(https://fonts.gstatic.com/s/amaticsc/v11/TUZ3zwprpvBS1izr_vOMscGKfrUC.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
unicodeRange:
|
||||
"U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Architects Daughter",
|
||||
|
|
@ -34,7 +36,8 @@ const fonts = [
|
|||
{
|
||||
family: "Caesar Dressing",
|
||||
src: "url(https://fonts.gstatic.com/s/caesardressing/v6/yYLx0hLa3vawqtwdswbotmK4vrRHdrz7.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
unicodeRange:
|
||||
"U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Cinzel",
|
||||
|
|
@ -49,7 +52,8 @@ const fonts = [
|
|||
{
|
||||
family: "Fredericka the Great",
|
||||
src: "url(https://fonts.gstatic.com/s/frederickathegreat/v6/9Bt33CxNwt7aOctW2xjbCstzwVKsIBVV--Sjxbc.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
unicodeRange:
|
||||
"U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Gloria Hallelujah",
|
||||
|
|
@ -74,12 +78,14 @@ const fonts = [
|
|||
{
|
||||
family: "MedievalSharp",
|
||||
src: "url(https://fonts.gstatic.com/s/medievalsharp/v9/EvOJzAlL3oU5AQl2mP5KdgptMqhwMg.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
unicodeRange:
|
||||
"U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Metamorphous",
|
||||
src: "url(https://fonts.gstatic.com/s/metamorphous/v7/Wnz8HA03aAXcC39ZEX5y133EOyqs.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
unicodeRange:
|
||||
"U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Montez",
|
||||
|
|
@ -89,7 +95,8 @@ const fonts = [
|
|||
{
|
||||
family: "Nova Script",
|
||||
src: "url(https://fonts.gstatic.com/s/novascript/v10/7Au7p_IpkSWSTWaFWkumvlQKGFw.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
unicodeRange:
|
||||
"U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Orbitron",
|
||||
|
|
@ -109,12 +116,14 @@ const fonts = [
|
|||
{
|
||||
family: "Uncial Antiqua",
|
||||
src: "url(https://fonts.gstatic.com/s/uncialantiqua/v5/N0bM2S5WOex4OUbESzoESK-i-MfWQZQ.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
unicodeRange:
|
||||
"U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Underdog",
|
||||
src: "url(https://fonts.gstatic.com/s/underdog/v6/CHygV-jCElj7diMroWSlWV8.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
unicodeRange:
|
||||
"U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Yellowtail",
|
||||
|
|
@ -243,7 +252,7 @@ async function addGoogleFont(family) {
|
|||
})
|
||||
.catch(err => {
|
||||
tip(`Failed to load Google font ${family}`, true, "error", 4000);
|
||||
console.error(err);
|
||||
ERROR && console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
132
modules/load.js
132
modules/load.js
|
|
@ -145,7 +145,7 @@ function parseLoadedResult(result) {
|
|||
const mapVersion = parseFloat(mapData[0].split("|")[0] || mapData[0]);
|
||||
return [mapData, mapVersion];
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
ERROR && console.error(error);
|
||||
return [null, null];
|
||||
}
|
||||
}
|
||||
|
|
@ -190,7 +190,6 @@ function parseLoadedData(data) {
|
|||
if (customizationMenu.offsetParent) styleTab.click();
|
||||
|
||||
const reliefIcons = document.getElementById("defs-relief").innerHTML; // save relief icons
|
||||
const hatching = document.getElementById("hatching").cloneNode(true); // save hatching
|
||||
|
||||
void (function parseParameters() {
|
||||
const params = data[0].split("|");
|
||||
|
|
@ -426,16 +425,16 @@ function parseLoadedData(data) {
|
|||
void (function resolveVersionConflicts() {
|
||||
const version = parseFloat(data[0].split("|")[0]);
|
||||
if (version < 0.9) {
|
||||
// 0.9 has additional relief icons to be included into older maps
|
||||
// v0.9 has additional relief icons to be included into older maps
|
||||
document.getElementById("defs-relief").innerHTML = reliefIcons;
|
||||
}
|
||||
|
||||
if (version < 1) {
|
||||
// 1.0 adds a new religions layer
|
||||
// v1.0 adds a new religions layer
|
||||
relig = viewbox.insert("g", "#terrain").attr("id", "relig");
|
||||
Religions.generate();
|
||||
|
||||
// 1.0 adds a legend box
|
||||
// v1.0 adds a legend box
|
||||
legend = svg.append("g").attr("id", "legend");
|
||||
legend
|
||||
.attr("font-family", "Almendra SC")
|
||||
|
|
@ -448,7 +447,7 @@ function parseLoadedData(data) {
|
|||
.attr("stroke-dasharray", "0 4 10 4")
|
||||
.attr("stroke-linecap", "round");
|
||||
|
||||
// 1.0 separated drawBorders fron drawStates()
|
||||
// v1.0 separated drawBorders fron drawStates()
|
||||
stateBorders = borders.append("g").attr("id", "stateBorders");
|
||||
provinceBorders = borders.append("g").attr("id", "provinceBorders");
|
||||
borders
|
||||
|
|
@ -461,7 +460,7 @@ function parseLoadedData(data) {
|
|||
stateBorders.attr("opacity", 0.8).attr("stroke", "#56566d").attr("stroke-width", 1).attr("stroke-dasharray", "2").attr("stroke-linecap", "butt");
|
||||
provinceBorders.attr("opacity", 0.8).attr("stroke", "#56566d").attr("stroke-width", 0.5).attr("stroke-dasharray", "1").attr("stroke-linecap", "butt");
|
||||
|
||||
// 1.0 adds state relations, provinces, forms and full names
|
||||
// v1.0 adds state relations, provinces, forms and full names
|
||||
provs = viewbox.insert("g", "#borders").attr("id", "provs").attr("opacity", 0.6);
|
||||
BurgsAndStates.collectStatistics();
|
||||
BurgsAndStates.generateCampaigns();
|
||||
|
|
@ -473,10 +472,7 @@ function parseLoadedData(data) {
|
|||
if (!layerIsOn("toggleBorders")) $("#borders").fadeOut();
|
||||
if (!layerIsOn("toggleStates")) regions.attr("display", "none").selectAll("path").remove();
|
||||
|
||||
// 1.0 adds hatching
|
||||
document.getElementsByTagName("defs")[0].appendChild(hatching);
|
||||
|
||||
// 1.0 adds zones layer
|
||||
// v1.0 adds zones layer
|
||||
zones = viewbox.insert("g", "#borders").attr("id", "zones").attr("display", "none");
|
||||
zones.attr("opacity", 0.6).attr("stroke", null).attr("stroke-width", 0).attr("stroke-dasharray", null).attr("stroke-linecap", "butt");
|
||||
addZones();
|
||||
|
|
@ -485,35 +481,35 @@ function parseLoadedData(data) {
|
|||
turnButtonOn("toggleMarkers");
|
||||
}
|
||||
|
||||
// 1.0 add fogging layer (state focus)
|
||||
// v1.0 add fogging layer (state focus)
|
||||
fogging = viewbox.insert("g", "#ruler").attr("id", "fogging-cont").attr("mask", "url(#fog)").append("g").attr("id", "fogging").style("display", "none");
|
||||
fogging.append("rect").attr("x", 0).attr("y", 0).attr("width", "100%").attr("height", "100%");
|
||||
defs.append("mask").attr("id", "fog").append("rect").attr("x", 0).attr("y", 0).attr("width", "100%").attr("height", "100%").attr("fill", "white");
|
||||
|
||||
// 1.0 changes states opacity bask to regions level
|
||||
// v1.0 changes states opacity bask to regions level
|
||||
if (statesBody.attr("opacity")) {
|
||||
regions.attr("opacity", statesBody.attr("opacity"));
|
||||
statesBody.attr("opacity", null);
|
||||
}
|
||||
|
||||
// 1.0 changed labels to multi-lined
|
||||
// v1.0 changed labels to multi-lined
|
||||
labels.selectAll("textPath").each(function () {
|
||||
const text = this.textContent;
|
||||
const shift = this.getComputedTextLength() / -1.5;
|
||||
this.innerHTML = `<tspan x="${shift}">${text}</tspan>`;
|
||||
});
|
||||
|
||||
// 1.0 added new biome - Wetland
|
||||
// v1.0 added new biome - Wetland
|
||||
biomesData.name.push("Wetland");
|
||||
biomesData.color.push("#0b9131");
|
||||
biomesData.habitability.push(12);
|
||||
}
|
||||
|
||||
if (version < 1.1) {
|
||||
// v 1.0 initial code had a bug with religion layer id
|
||||
// v1.0 initial code had a bug with religion layer id
|
||||
if (!relig.size()) relig = viewbox.insert("g", "#terrain").attr("id", "relig");
|
||||
|
||||
// v 1.0 initially has Sympathy status then relaced with Friendly
|
||||
// v1.0 initially has Sympathy status then relaced with Friendly
|
||||
for (const s of pack.states) {
|
||||
if (!s.diplomacy) continue;
|
||||
s.diplomacy = s.diplomacy.map(r => (r === "Sympathy" ? "Friendly" : r));
|
||||
|
|
@ -522,7 +518,7 @@ function parseLoadedData(data) {
|
|||
// labels should be toggled via style attribute, so remove display attribute
|
||||
labels.attr("display", null);
|
||||
|
||||
// v 1.0 added religions heirarchy tree
|
||||
// v1.0 added religions heirarchy tree
|
||||
if (pack.religions[1] && !pack.religions[1].code) {
|
||||
pack.religions
|
||||
.filter(r => r.i)
|
||||
|
|
@ -542,7 +538,7 @@ function parseLoadedData(data) {
|
|||
lakes.select("#salt").attr("opacity", 0.5).attr("fill", "#409b8a").attr("stroke", "#388985").attr("stroke-width", 0.7).attr("filter", null);
|
||||
}
|
||||
|
||||
// v 1.1 added new lake and coast groups
|
||||
// v1.1 added new lake and coast groups
|
||||
if (!document.getElementById("sinkhole")) {
|
||||
lakes.append("g").attr("id", "sinkhole");
|
||||
lakes.append("g").attr("id", "frozen");
|
||||
|
|
@ -557,7 +553,7 @@ function parseLoadedData(data) {
|
|||
coastline.select("#lake_island").attr("opacity", 1).attr("stroke", "#7c8eaf").attr("stroke-width", 0.35).attr("filter", null);
|
||||
}
|
||||
|
||||
// v 1.1 features stores more data
|
||||
// v1.1 features stores more data
|
||||
defs.select("#land").selectAll("path").remove();
|
||||
defs.select("#water").selectAll("path").remove();
|
||||
coastline.selectAll("path").remove();
|
||||
|
|
@ -566,13 +562,13 @@ function parseLoadedData(data) {
|
|||
}
|
||||
|
||||
if (version < 1.11) {
|
||||
// v 1.11 added new attributes
|
||||
// v1.11 added new attributes
|
||||
terrs.attr("scheme", "bright").attr("terracing", 0).attr("skip", 5).attr("relax", 0).attr("curve", 0);
|
||||
svg.select("#oceanic > *").attr("id", "oceanicPattern");
|
||||
oceanLayers.attr("layers", "-6,-3,-1");
|
||||
gridOverlay.attr("type", "pointyHex").attr("size", 10);
|
||||
|
||||
// v 1.11 added cultures heirarchy tree
|
||||
// v1.11 added cultures heirarchy tree
|
||||
if (pack.cultures[1] && !pack.cultures[1].code) {
|
||||
pack.cultures
|
||||
.filter(c => c.i)
|
||||
|
|
@ -582,17 +578,17 @@ function parseLoadedData(data) {
|
|||
});
|
||||
}
|
||||
|
||||
// v 1.11 had an issue with fogging being displayed on load
|
||||
// v1.11 had an issue with fogging being displayed on load
|
||||
unfog();
|
||||
|
||||
// v 1.2 added new terrain attributes
|
||||
// v1.2 added new terrain attributes
|
||||
if (!terrain.attr("set")) terrain.attr("set", "simple");
|
||||
if (!terrain.attr("size")) terrain.attr("size", 1);
|
||||
if (!terrain.attr("density")) terrain.attr("density", 0.4);
|
||||
}
|
||||
|
||||
if (version < 1.21) {
|
||||
// v 1.11 replaced "display" attribute by "display" style
|
||||
// v1.11 replaced "display" attribute by "display" style
|
||||
viewbox.selectAll("g").each(function () {
|
||||
if (this.hasAttribute("display")) {
|
||||
this.removeAttribute("display");
|
||||
|
|
@ -600,7 +596,7 @@ function parseLoadedData(data) {
|
|||
}
|
||||
});
|
||||
|
||||
// v 1.21 added rivers data to pack
|
||||
// v1.21 added rivers data to pack
|
||||
pack.rivers = []; // rivers data
|
||||
rivers.selectAll("path").each(function () {
|
||||
const i = +this.id.slice(5);
|
||||
|
|
@ -616,12 +612,12 @@ function parseLoadedData(data) {
|
|||
}
|
||||
|
||||
if (version < 1.22) {
|
||||
// v 1.22 changed state neighbors from Set object to array
|
||||
// v1.22 changed state neighbors from Set object to array
|
||||
BurgsAndStates.collectStatistics();
|
||||
}
|
||||
|
||||
if (version < 1.3) {
|
||||
// v 1.3 added global options object
|
||||
// v1.3 added global options object
|
||||
const winds = options.slice(); // previostly wind was saved in settings[19]
|
||||
const year = rand(100, 2000);
|
||||
const era = Names.getBaseShort(P(0.7) ? 1 : rand(nameBases.length)) + " Era";
|
||||
|
|
@ -629,10 +625,10 @@ function parseLoadedData(data) {
|
|||
const military = Military.getDefaultOptions();
|
||||
options = {winds, year, era, eraShort, military};
|
||||
|
||||
// v 1.3 added campaings data for all states
|
||||
// v1.3 added campaings data for all states
|
||||
BurgsAndStates.generateCampaigns();
|
||||
|
||||
// v 1.3 added militry layer
|
||||
// v1.3 added militry layer
|
||||
armies = viewbox.insert("g", "#icons").attr("id", "armies");
|
||||
armies.attr("opacity", 1).attr("fill-opacity", 1).attr("font-size", 6).attr("box-size", 3).attr("stroke", "#000").attr("stroke-width", 0.3);
|
||||
turnButtonOn("toggleMilitary");
|
||||
|
|
@ -640,18 +636,18 @@ function parseLoadedData(data) {
|
|||
}
|
||||
|
||||
if (version < 1.4) {
|
||||
// v 1.35 added dry lakes
|
||||
// v1.35 added dry lakes
|
||||
if (!lakes.select("#dry").size()) {
|
||||
lakes.append("g").attr("id", "dry");
|
||||
lakes.select("#dry").attr("opacity", 1).attr("fill", "#c9bfa7").attr("stroke", "#8e816f").attr("stroke-width", 0.7).attr("filter", null);
|
||||
}
|
||||
|
||||
// v 1.4 added ice layer
|
||||
// v1.4 added ice layer
|
||||
ice = viewbox.insert("g", "#coastline").attr("id", "ice").style("display", "none");
|
||||
ice.attr("opacity", null).attr("fill", "#e8f0f6").attr("stroke", "#e8f0f6").attr("stroke-width", 1).attr("filter", "url(#dropShadow05)");
|
||||
drawIce();
|
||||
|
||||
// v 1.4 added icon and power attributes for units
|
||||
// v1.4 added icon and power attributes for units
|
||||
for (const unit of options.military) {
|
||||
if (!unit.icon) unit.icon = getUnitIcon(unit.type);
|
||||
if (!unit.power) unit.power = unit.crew;
|
||||
|
|
@ -668,7 +664,7 @@ function parseLoadedData(data) {
|
|||
else return "⚔️";
|
||||
}
|
||||
|
||||
// 1.4 added state reference for regiments
|
||||
// v1.4 added state reference for regiments
|
||||
pack.states.filter(s => s.military).forEach(s => s.military.forEach(r => (r.state = s.i)));
|
||||
}
|
||||
|
||||
|
|
@ -679,19 +675,19 @@ function parseLoadedData(data) {
|
|||
localStorage.removeItem("styleAncient");
|
||||
localStorage.removeItem("styleMonochrome");
|
||||
|
||||
// v 1.5 cultures has shield attribute
|
||||
// v1.5 cultures has shield attribute
|
||||
pack.cultures.forEach(culture => {
|
||||
if (culture.removed) return;
|
||||
culture.shield = Cultures.getRandomShield();
|
||||
});
|
||||
|
||||
// v 1.5 added burg type value
|
||||
// v1.5 added burg type value
|
||||
pack.burgs.forEach(burg => {
|
||||
if (!burg.i || burg.removed) return;
|
||||
burg.type = BurgsAndStates.getType(burg.cell, burg.port);
|
||||
});
|
||||
|
||||
// v 1.5 added emblems
|
||||
// v1.5 added emblems
|
||||
defs.append("g").attr("id", "defs-emblems");
|
||||
emblems = viewbox.insert("g", "#population").attr("id", "emblems").style("display", "none");
|
||||
emblems.append("g").attr("id", "burgEmblems");
|
||||
|
|
@ -700,7 +696,7 @@ function parseLoadedData(data) {
|
|||
regenerateEmblems();
|
||||
toggleEmblems();
|
||||
|
||||
// v 1.5 changed releif icons data
|
||||
// v1.5 changed releif icons data
|
||||
terrain.selectAll("use").each(function () {
|
||||
const type = this.getAttribute("data-type") || this.getAttribute("xlink:href");
|
||||
this.removeAttribute("xlink:href");
|
||||
|
|
@ -711,7 +707,7 @@ function parseLoadedData(data) {
|
|||
}
|
||||
|
||||
if (version < 1.6) {
|
||||
// v 1.6 changed rivers data
|
||||
// v1.6 changed rivers data
|
||||
for (const river of pack.rivers) {
|
||||
const el = document.getElementById("river" + river.i);
|
||||
if (el) {
|
||||
|
|
@ -726,7 +722,7 @@ function parseLoadedData(data) {
|
|||
}
|
||||
}
|
||||
|
||||
// v 1.6 changed lakes data
|
||||
// v1.6 changed lakes data
|
||||
for (const f of pack.features) {
|
||||
if (f.type !== "lake") continue;
|
||||
if (f.evaporation) continue;
|
||||
|
|
@ -743,7 +739,7 @@ function parseLoadedData(data) {
|
|||
}
|
||||
|
||||
if (version < 1.61) {
|
||||
// v 1.61 changed rulers data
|
||||
// v1.61 changed rulers data
|
||||
ruler.style("display", null);
|
||||
rulers = new Rulers();
|
||||
|
||||
|
|
@ -797,12 +793,12 @@ function parseLoadedData(data) {
|
|||
}
|
||||
|
||||
if (version < 1.62) {
|
||||
// v 1.62 changed grid data
|
||||
// v1.62 changed grid data
|
||||
gridOverlay.attr("size", null);
|
||||
}
|
||||
|
||||
if (version < 1.63) {
|
||||
// v.1.63 changed ocean pattern opacity element
|
||||
// v1.63 changed ocean pattern opacity element
|
||||
const oceanPattern = document.getElementById("oceanPattern");
|
||||
if (oceanPattern) oceanPattern.removeAttribute("opacity");
|
||||
const oceanicPattern = document.getElementById("oceanicPattern");
|
||||
|
|
@ -816,7 +812,7 @@ function parseLoadedData(data) {
|
|||
}
|
||||
|
||||
if (version < 1.64) {
|
||||
// v.1.64 change states style
|
||||
// v1.64 change states style
|
||||
const opacity = regions.attr("opacity");
|
||||
const filter = regions.attr("filter");
|
||||
statesBody.attr("opacity", opacity).attr("filter", filter);
|
||||
|
|
@ -825,9 +821,10 @@ function parseLoadedData(data) {
|
|||
}
|
||||
|
||||
if (version < 1.65) {
|
||||
// v 1.65 changed rivers data
|
||||
// v1.65 changed rivers data
|
||||
d3.select("#rivers").attr("style", null); // remove style to unhide layer
|
||||
const {cells, rivers} = pack;
|
||||
const defaultWidthFactor = rn(1 / (pointsInput.dataset.cells / 10000) ** 0.25, 2);
|
||||
|
||||
for (const river of rivers) {
|
||||
const node = document.getElementById("river" + river.i);
|
||||
|
|
@ -856,7 +853,7 @@ function parseLoadedData(data) {
|
|||
river.points = riverPoints;
|
||||
}
|
||||
|
||||
river.widthFactor = 1;
|
||||
river.widthFactor = defaultWidthFactor;
|
||||
|
||||
cells.i.forEach(i => {
|
||||
const riverInWater = cells.r[i] && cells.h[i] < 20;
|
||||
|
|
@ -872,7 +869,7 @@ function parseLoadedData(data) {
|
|||
}
|
||||
|
||||
if (version < 1.7) {
|
||||
// v 1.7 changed markers data
|
||||
// v1.7 changed markers data
|
||||
const defs = document.getElementById("defs-markers");
|
||||
const markersGroup = document.getElementById("markers");
|
||||
|
||||
|
|
@ -928,6 +925,22 @@ function parseLoadedData(data) {
|
|||
if (layerIsOn("markers")) drawMarkers();
|
||||
}
|
||||
}
|
||||
|
||||
if (version < 1.72) {
|
||||
// v1.72 renamed custom style presets
|
||||
const storedStyles = Object.keys(localStorage).filter(key => key.startsWith("style"));
|
||||
storedStyles.forEach(styleName => {
|
||||
const style = localStorage.getItem(styleName);
|
||||
const newStyleName = styleName.replace(/^style/, customPresetPrefix);
|
||||
localStorage.setItem(newStyleName, style);
|
||||
localStorage.removeItem(styleName);
|
||||
});
|
||||
}
|
||||
|
||||
if (version < 1.73) {
|
||||
// v1.73 moved the hatching patterns out of the user's SVG
|
||||
document.getElementById("hatching")?.remove();
|
||||
}
|
||||
})();
|
||||
|
||||
void (function checkDataIntegrity() {
|
||||
|
|
@ -1013,6 +1026,31 @@ function parseLoadedData(data) {
|
|||
ERROR && console.error("Data Integrity Check. Province", p.i, "is linked to removed state", p.state);
|
||||
p.removed = true; // remove incorrect province
|
||||
});
|
||||
|
||||
{
|
||||
const markerIds = [];
|
||||
let nextId = last(pack.markers)?.i + 1 || 0;
|
||||
|
||||
pack.markers.forEach(marker => {
|
||||
if (markerIds[marker.i]) {
|
||||
ERROR && console.error("Data Integrity Check. Marker", marker.i, "has non-unique id. Changing to", nextId);
|
||||
|
||||
const domElements = document.querySelectorAll("#marker" + marker.i);
|
||||
if (domElements[1]) domElements[1].id = "marker" + nextId; // rename 2nd dom element
|
||||
|
||||
const noteElements = notes.filter(note => note.id === "marker" + marker.i);
|
||||
if (noteElements[1]) noteElements[1].id = "marker" + nextId; // rename 2nd note
|
||||
|
||||
marker.i = nextId;
|
||||
nextId += 1;
|
||||
} else {
|
||||
markerIds[marker.i] = true;
|
||||
}
|
||||
});
|
||||
|
||||
// sort markers by index
|
||||
pack.markers.sort((a, b) => a.i - b.i);
|
||||
}
|
||||
})();
|
||||
|
||||
changeMapSize();
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ window.Markers = (function () {
|
|||
}
|
||||
|
||||
function addMarker({cell, type, icon, dx, dy, px}) {
|
||||
const i = pack.markers.length;
|
||||
const i = last(pack.markers)?.i + 1 || 0;
|
||||
const [x, y] = getMarkerCoordinates(cell);
|
||||
const marker = {i, icon, type, x, y, cell};
|
||||
if (dx) marker.dx = dx;
|
||||
|
|
|
|||
|
|
@ -30,63 +30,59 @@ window.Religions = (function () {
|
|||
const base = {
|
||||
number: ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve"],
|
||||
being: [
|
||||
"God",
|
||||
"Goddess",
|
||||
"Lord",
|
||||
"Lady",
|
||||
"Deity",
|
||||
"Creator",
|
||||
"Maker",
|
||||
"Overlord",
|
||||
"Ruler",
|
||||
"Chief",
|
||||
"Master",
|
||||
"Spirit",
|
||||
"Ancestor",
|
||||
"Ancient",
|
||||
"Brother",
|
||||
"Chief",
|
||||
"Council",
|
||||
"Creator",
|
||||
"Deity",
|
||||
"Elder",
|
||||
"Father",
|
||||
"Forebear",
|
||||
"Forefather",
|
||||
"Mother",
|
||||
"Brother",
|
||||
"Sister",
|
||||
"Elder",
|
||||
"Numen",
|
||||
"Ancient",
|
||||
"Virgin",
|
||||
"Giver",
|
||||
"Council",
|
||||
"God",
|
||||
"Goddess",
|
||||
"Guardian",
|
||||
"Reaper"
|
||||
"Lady",
|
||||
"Lord",
|
||||
"Maker",
|
||||
"Master",
|
||||
"Mother",
|
||||
"Numen",
|
||||
"Overlord",
|
||||
"Reaper",
|
||||
"Ruler",
|
||||
"Sister",
|
||||
"Spirit",
|
||||
"Virgin"
|
||||
],
|
||||
animal: [
|
||||
"Dragon",
|
||||
"Wyvern",
|
||||
"Phoenix",
|
||||
"Unicorn",
|
||||
"Sphinx",
|
||||
"Centaur",
|
||||
"Pegasus",
|
||||
"Kraken",
|
||||
"Basilisk",
|
||||
"Chimera",
|
||||
"Cyclope",
|
||||
"Antelope",
|
||||
"Ape",
|
||||
"Badger",
|
||||
"Basilisk",
|
||||
"Bear",
|
||||
"Beaver",
|
||||
"Bison",
|
||||
"Boar",
|
||||
"Buffalo",
|
||||
"Camel",
|
||||
"Cat",
|
||||
"Centaur",
|
||||
"Chimera",
|
||||
"Cobra",
|
||||
"Crane",
|
||||
"Crocodile",
|
||||
"Crow",
|
||||
"Cyclope",
|
||||
"Deer",
|
||||
"Dog",
|
||||
"Dragon",
|
||||
"Eagle",
|
||||
"Elk",
|
||||
"Falcon",
|
||||
"Fox",
|
||||
"Goat",
|
||||
"Goose",
|
||||
|
|
@ -94,10 +90,12 @@ window.Religions = (function () {
|
|||
"Hawk",
|
||||
"Heron",
|
||||
"Horse",
|
||||
"Hound",
|
||||
"Hyena",
|
||||
"Ibis",
|
||||
"Jackal",
|
||||
"Jaguar",
|
||||
"Kraken",
|
||||
"Lark",
|
||||
"Leopard",
|
||||
"Lion",
|
||||
|
|
@ -107,177 +105,179 @@ window.Religions = (function () {
|
|||
"Mule",
|
||||
"Narwhal",
|
||||
"Owl",
|
||||
"Ox",
|
||||
"Panther",
|
||||
"Pegasus",
|
||||
"Phoenix",
|
||||
"Rat",
|
||||
"Raven",
|
||||
"Rook",
|
||||
"Scorpion",
|
||||
"Serpent",
|
||||
"Shark",
|
||||
"Sheep",
|
||||
"Snake",
|
||||
"Sphinx",
|
||||
"Spider",
|
||||
"Swan",
|
||||
"Tiger",
|
||||
"Turtle",
|
||||
"Unicorn",
|
||||
"Viper",
|
||||
"Vulture",
|
||||
"Walrus",
|
||||
"Wolf",
|
||||
"Wolverine",
|
||||
"Worm",
|
||||
"Camel",
|
||||
"Falcon",
|
||||
"Hound",
|
||||
"Ox",
|
||||
"Serpent"
|
||||
"Wyvern"
|
||||
],
|
||||
adjective: [
|
||||
"New",
|
||||
"Good",
|
||||
"High",
|
||||
"Old",
|
||||
"Great",
|
||||
"Big",
|
||||
"Young",
|
||||
"Major",
|
||||
"Strong",
|
||||
"Happy",
|
||||
"Last",
|
||||
"Main",
|
||||
"Huge",
|
||||
"Far",
|
||||
"Beautiful",
|
||||
"Wild",
|
||||
"Fair",
|
||||
"Prime",
|
||||
"Crazy",
|
||||
"Ancient",
|
||||
"Proud",
|
||||
"Secret",
|
||||
"Lucky",
|
||||
"Sad",
|
||||
"Silent",
|
||||
"Latter",
|
||||
"Severe",
|
||||
"Fat",
|
||||
"Holy",
|
||||
"Pure",
|
||||
"Aggressive",
|
||||
"Honest",
|
||||
"Giant",
|
||||
"Mad",
|
||||
"Pregnant",
|
||||
"Distant",
|
||||
"Lost",
|
||||
"Broken",
|
||||
"Almighty",
|
||||
"Ancient",
|
||||
"Beautiful",
|
||||
"Benevolent",
|
||||
"Big",
|
||||
"Blind",
|
||||
"Friendly",
|
||||
"Unknown",
|
||||
"Sleeping",
|
||||
"Slumbering",
|
||||
"Loud",
|
||||
"Hungry",
|
||||
"Wise",
|
||||
"Worried",
|
||||
"Sacred",
|
||||
"Magical",
|
||||
"Superior",
|
||||
"Patient",
|
||||
"Blond",
|
||||
"Bloody",
|
||||
"Brave",
|
||||
"Broken",
|
||||
"Brutal",
|
||||
"Burning",
|
||||
"Calm",
|
||||
"Cheerful",
|
||||
"Crazy",
|
||||
"Cruel",
|
||||
"Dead",
|
||||
"Deadly",
|
||||
"Peaceful",
|
||||
"Grateful",
|
||||
"Frozen",
|
||||
"Evil",
|
||||
"Scary",
|
||||
"Burning",
|
||||
"Divine",
|
||||
"Bloody",
|
||||
"Dying",
|
||||
"Waking",
|
||||
"Brutal",
|
||||
"Unhappy",
|
||||
"Calm",
|
||||
"Cruel",
|
||||
"Favorable",
|
||||
"Blond",
|
||||
"Explicit",
|
||||
"Disturbing",
|
||||
"Devastating",
|
||||
"Brave",
|
||||
"Sunny",
|
||||
"Troubled",
|
||||
"Flying",
|
||||
"Sustainable",
|
||||
"Marine",
|
||||
"Fatal",
|
||||
"Inherent",
|
||||
"Selected",
|
||||
"Naval",
|
||||
"Cheerful",
|
||||
"Almighty",
|
||||
"Benevolent",
|
||||
"Distant",
|
||||
"Disturbing",
|
||||
"Divine",
|
||||
"Dying",
|
||||
"Eternal",
|
||||
"Evil",
|
||||
"Explicit",
|
||||
"Fair",
|
||||
"Far",
|
||||
"Fat",
|
||||
"Fatal",
|
||||
"Favorable",
|
||||
"Flying",
|
||||
"Friendly",
|
||||
"Frozen",
|
||||
"Giant",
|
||||
"Good",
|
||||
"Grateful",
|
||||
"Great",
|
||||
"Happy",
|
||||
"High",
|
||||
"Holy",
|
||||
"Honest",
|
||||
"Huge",
|
||||
"Hungry",
|
||||
"Immutable",
|
||||
"Infallible"
|
||||
"Infallible",
|
||||
"Inherent",
|
||||
"Last",
|
||||
"Latter",
|
||||
"Lost",
|
||||
"Loud",
|
||||
"Lucky",
|
||||
"Mad",
|
||||
"Magical",
|
||||
"Main",
|
||||
"Major",
|
||||
"Marine",
|
||||
"Naval",
|
||||
"New",
|
||||
"Old",
|
||||
"Patient",
|
||||
"Peaceful",
|
||||
"Pregnant",
|
||||
"Prime",
|
||||
"Proud",
|
||||
"Pure",
|
||||
"Sacred",
|
||||
"Sad",
|
||||
"Scary",
|
||||
"Secret",
|
||||
"Selected",
|
||||
"Severe",
|
||||
"Silent",
|
||||
"Sleeping",
|
||||
"Slumbering",
|
||||
"Strong",
|
||||
"Sunny",
|
||||
"Superior",
|
||||
"Sustainable",
|
||||
"Troubled",
|
||||
"Unhappy",
|
||||
"Unknown",
|
||||
"Waking",
|
||||
"Wild",
|
||||
"Wise",
|
||||
"Worried",
|
||||
"Young"
|
||||
],
|
||||
genitive: [
|
||||
"Day",
|
||||
"Life",
|
||||
"Death",
|
||||
"Night",
|
||||
"Home",
|
||||
"Fog",
|
||||
"Snow",
|
||||
"Winter",
|
||||
"Summer",
|
||||
"Cold",
|
||||
"Springs",
|
||||
"Gates",
|
||||
"Nature",
|
||||
"Thunder",
|
||||
"Lightning",
|
||||
"War",
|
||||
"Ice",
|
||||
"Frost",
|
||||
"Fire",
|
||||
"Day",
|
||||
"Death",
|
||||
"Doom",
|
||||
"Fate",
|
||||
"Pain",
|
||||
"Fire",
|
||||
"Fog",
|
||||
"Frost",
|
||||
"Gates",
|
||||
"Heaven",
|
||||
"Home",
|
||||
"Ice",
|
||||
"Justice",
|
||||
"Life",
|
||||
"Light",
|
||||
"Lightning",
|
||||
"Love",
|
||||
"Nature",
|
||||
"Night",
|
||||
"Pain",
|
||||
"Snow",
|
||||
"Springs",
|
||||
"Summer",
|
||||
"Thunder",
|
||||
"Time",
|
||||
"Victory"
|
||||
"Victory",
|
||||
"War",
|
||||
"Winter"
|
||||
],
|
||||
theGenitive: [
|
||||
"World",
|
||||
"Word",
|
||||
"South",
|
||||
"West",
|
||||
"North",
|
||||
"East",
|
||||
"Sun",
|
||||
"Moon",
|
||||
"Peak",
|
||||
"Fall",
|
||||
"Dawn",
|
||||
"Eclipse",
|
||||
"Abyss",
|
||||
"Blood",
|
||||
"Tree",
|
||||
"Dawn",
|
||||
"Earth",
|
||||
"East",
|
||||
"Eclipse",
|
||||
"Fall",
|
||||
"Harvest",
|
||||
"Moon",
|
||||
"North",
|
||||
"Peak",
|
||||
"Rainbow",
|
||||
"Sea",
|
||||
"Sky",
|
||||
"South",
|
||||
"Stars",
|
||||
"Storm",
|
||||
"Sun",
|
||||
"Tree",
|
||||
"Underworld",
|
||||
"Wild"
|
||||
"West",
|
||||
"Wild",
|
||||
"Word",
|
||||
"World"
|
||||
],
|
||||
color: ["Dark", "Light", "Bright", "Golden", "White", "Black", "Red", "Pink", "Purple", "Blue", "Green", "Yellow", "Amber", "Orange", "Brown", "Grey"]
|
||||
color: ["Amber", "Black", "Blue", "Bright", "Brown", "Dark", "Golden", "Green", "Grey", "Light", "Orange", "Pink", "Purple", "Red", "White", "Yellow"]
|
||||
};
|
||||
|
||||
const forms = {
|
||||
|
|
@ -308,10 +308,10 @@ window.Religions = (function () {
|
|||
Monotheism: {Religion: 1, Church: 1},
|
||||
"Non-theism": {Beliefs: 3, Spirits: 1},
|
||||
|
||||
Cult: {Cult: 4, Sect: 4, Worship: 1, Orden: 1, Coterie: 1, Arcanum: 1},
|
||||
"Dark Cult": {Cult: 2, Sect: 2, Occultism: 1, Idols: 1, Coven: 1, Circle: 1, Blasphemy: 1},
|
||||
Cult: {Cult: 4, Sect: 4, Arcanum: 1, Coterie: 1, Order: 1, Worship: 1},
|
||||
"Dark Cult": {Cult: 2, Sect: 2, Blasphemy: 1, Circle: 1, Coven: 1, Idols: 1, Occultism: 1},
|
||||
|
||||
Heresy: {Heresy: 3, Sect: 2, Schism: 1, Dissenters: 1, Circle: 1, Brotherhood: 1, Society: 1, Iconoclasm: 1, Dissent: 1, Apostates: 1}
|
||||
Heresy: {Heresy: 3, Sect: 2, Apostates: 1, Brotherhood: 1, Circle: 1, Dissent: 1, Dissenters: 1, Iconoclasm: 1, Schism: 1, Society: 1}
|
||||
};
|
||||
|
||||
const generate = function () {
|
||||
|
|
|
|||
|
|
@ -23,22 +23,27 @@ window.Rivers = (function () {
|
|||
resolveDepressions(h);
|
||||
drainWater();
|
||||
defineRivers();
|
||||
|
||||
calculateConfluenceFlux();
|
||||
Lakes.cleanupLakeData();
|
||||
|
||||
if (allowErosion) cells.h = Uint8Array.from(h); // apply changed heights as basic one
|
||||
if (allowErosion) {
|
||||
cells.h = Uint8Array.from(h); // apply gradient
|
||||
downcutRivers(); // downcut river beds
|
||||
}
|
||||
|
||||
TIME && console.timeEnd("generateRivers");
|
||||
|
||||
function drainWater() {
|
||||
const MIN_FLUX_TO_FORM_RIVER = 30;
|
||||
const cellsNumberModifier = (pointsInput.dataset.cells / 10000) ** 0.25;
|
||||
|
||||
const prec = grid.cells.prec;
|
||||
const area = pack.cells.area;
|
||||
const land = cells.i.filter(i => h[i] >= 20).sort((a, b) => h[b] - h[a]);
|
||||
const lakeOutCells = Lakes.setClimateData(h);
|
||||
|
||||
land.forEach(function (i) {
|
||||
cells.fl[i] += (prec[cells.g[i]] * area[i]) / 100; // add flux from precipitation
|
||||
cells.fl[i] += prec[cells.g[i]] / cellsNumberModifier; // add flux from precipitation
|
||||
|
||||
// create lake outlet if lake is not in deep depression and flux > evaporation
|
||||
const lakes = lakeOutCells[i] ? features.filter(feature => i === feature.outCell && feature.flux > feature.evaporation) : [];
|
||||
|
|
@ -90,6 +95,15 @@ window.Rivers = (function () {
|
|||
// cells is depressed
|
||||
if (h[i] <= h[min]) return;
|
||||
|
||||
// debug
|
||||
// .append("line")
|
||||
// .attr("x1", pack.cells.p[i][0])
|
||||
// .attr("y1", pack.cells.p[i][1])
|
||||
// .attr("x2", pack.cells.p[min][0])
|
||||
// .attr("y2", pack.cells.p[min][1])
|
||||
// .attr("stroke", "#333")
|
||||
// .attr("stroke-width", 0.2);
|
||||
|
||||
if (cells.fl[i] < MIN_FLUX_TO_FORM_RIVER) {
|
||||
// flux is too small to operate as a river
|
||||
if (h[min] >= 20) cells.fl[min] += cells.fl[i];
|
||||
|
|
@ -149,6 +163,9 @@ window.Rivers = (function () {
|
|||
cells.conf = new Uint16Array(cells.i.length);
|
||||
pack.rivers = [];
|
||||
|
||||
const defaultWidthFactor = rn(1 / (pointsInput.dataset.cells / 10000) ** 0.25, 2);
|
||||
const mainStemWidthFactor = defaultWidthFactor * 1.2;
|
||||
|
||||
for (const key in riversData) {
|
||||
const riverCells = riversData[key];
|
||||
if (riverCells.length < 3) continue; // exclude tiny rivers
|
||||
|
|
@ -166,7 +183,7 @@ window.Rivers = (function () {
|
|||
const mouth = riverCells[riverCells.length - 2];
|
||||
const parent = riverParents[key] || 0;
|
||||
|
||||
const widthFactor = !parent || parent === riverId ? 1.2 : 1;
|
||||
const widthFactor = !parent || parent === riverId ? mainStemWidthFactor : defaultWidthFactor;
|
||||
const meanderedPoints = addMeandering(riverCells);
|
||||
const discharge = cells.fl[mouth]; // m3 in second
|
||||
const length = getApproximateLength(meanderedPoints);
|
||||
|
|
@ -176,6 +193,22 @@ window.Rivers = (function () {
|
|||
}
|
||||
}
|
||||
|
||||
function downcutRivers() {
|
||||
const MAX_DOWNCUT = 5;
|
||||
|
||||
for (const i of pack.cells.i) {
|
||||
if (cells.h[i] < 35) continue; // don't donwcut lowlands
|
||||
if (!cells.fl[i]) continue;
|
||||
|
||||
const higherCells = cells.c[i].filter(c => cells.h[c] > cells.h[i]);
|
||||
const higherFlux = higherCells.reduce((acc, c) => acc + cells.fl[c], 0) / higherCells.length;
|
||||
if (!higherFlux) continue;
|
||||
|
||||
const downcut = Math.floor(cells.fl[i] / higherFlux);
|
||||
if (downcut) cells.h[i] -= Math.min(downcut, MAX_DOWNCUT);
|
||||
}
|
||||
}
|
||||
|
||||
function calculateConfluenceFlux() {
|
||||
for (const i of cells.i) {
|
||||
if (!cells.conf[i]) continue;
|
||||
|
|
@ -344,14 +377,14 @@ window.Rivers = (function () {
|
|||
const LENGTH_PROGRESSION = [1, 1, 2, 3, 5, 8, 13, 21, 34].map(n => n / LENGTH_FACTOR);
|
||||
const MAX_PROGRESSION = last(LENGTH_PROGRESSION);
|
||||
|
||||
const getOffset = (flux, pointNumber, widthFactor = 1, startingWidth = 0) => {
|
||||
const getOffset = (flux, pointNumber, widthFactor, startingWidth = 0) => {
|
||||
const fluxWidth = Math.min(flux ** 0.9 / FLUX_FACTOR, MAX_FLUX_WIDTH);
|
||||
const lengthWidth = pointNumber * STEP_WIDTH + (LENGTH_PROGRESSION[pointNumber] || MAX_PROGRESSION);
|
||||
return widthFactor * (lengthWidth + fluxWidth) + startingWidth;
|
||||
};
|
||||
|
||||
// build polygon from a list of points and calculated offset (width)
|
||||
const getRiverPath = function (points, widthFactor = 1, startingWidth = 0) {
|
||||
const getRiverPath = function (points, widthFactor, startingWidth = 0) {
|
||||
const riverPointsLeft = [];
|
||||
const riverPointsRight = [];
|
||||
|
||||
|
|
@ -444,5 +477,20 @@ window.Rivers = (function () {
|
|||
return getBasin(parent);
|
||||
};
|
||||
|
||||
return {generate, alterHeights, resolveDepressions, addMeandering, getRiverPath, specify, getName, getType, getBasin, getWidth, getOffset, getApproximateLength, getRiverPoints, remove};
|
||||
return {
|
||||
generate,
|
||||
alterHeights,
|
||||
resolveDepressions,
|
||||
addMeandering,
|
||||
getRiverPath,
|
||||
specify,
|
||||
getName,
|
||||
getType,
|
||||
getBasin,
|
||||
getWidth,
|
||||
getOffset,
|
||||
getApproximateLength,
|
||||
getRiverPoints,
|
||||
remove
|
||||
};
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ async function saveToDropbox() {
|
|||
await Cloud.providers.dropbox.save(filename, mapData);
|
||||
tip("Map is saved to your Dropbox", true, "success", 8000);
|
||||
} catch (msg) {
|
||||
console.error(msg);
|
||||
ERROR && console.error(msg);
|
||||
tip("Cannot save .map to your Dropbox", true, "error", 8000);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,8 +141,8 @@ class Battle {
|
|||
const state = pack.states[regiment.state];
|
||||
const distance = (Math.hypot(this.y - regiment.by, this.x - regiment.bx) * distanceScaleInput.value) | 0; // distance between regiment and its base
|
||||
const color = state.color[0] === "#" ? state.color : "#999";
|
||||
const icon = `<svg width="1.4em" height="1.4em" style="margin-bottom: -.6em">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="${color}" class="fillRect"></rect>
|
||||
const icon = `<svg width="1.4em" height="1.4em" style="margin-bottom: -.6em; stroke: #333">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="${color}"></rect>
|
||||
<text x="0" y="1.04em" style="">${regiment.icon}</text></svg>`;
|
||||
const body = `<tbody id="battle${state.i}-${regiment.i}">`;
|
||||
|
||||
|
|
@ -183,7 +183,7 @@ class Battle {
|
|||
dist = added ? "0 " + distanceUnitInput.value : distance(r);
|
||||
return `<div ${added ? "class='inactive'" : ""} data-s=${s.i} data-i=${r.i} data-state=${s.name} data-regiment=${r.name}
|
||||
data-total=${r.a} data-distance=${dist} data-tip="Click to select regiment">
|
||||
<svg width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${s.color}" class="fillRect"></svg>
|
||||
<svg width=".9em" height=".9em" style="margin-bottom:-1px; stroke: #333"><rect x="0" y="0" width="100%" height="100%" fill="${s.color}" ></svg>
|
||||
<div style="width:6em">${s.name.slice(0, 11)}</div>
|
||||
<div style="width:1.2em">${r.icon}</div>
|
||||
<div style="width:13em">${r.name.slice(0, 24)}</div>
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@ function editBiomes() {
|
|||
document.getElementById("biomesExport").addEventListener("click", downloadBiomesData);
|
||||
|
||||
body.addEventListener("click", function (ev) {
|
||||
const el = ev.target,
|
||||
cl = el.classList;
|
||||
if (cl.contains("fillRect")) biomeChangeColor(el);
|
||||
const el = ev.target;
|
||||
const cl = el.classList;
|
||||
if (el.tagName === "FILL-BOX") 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);
|
||||
|
|
@ -94,9 +94,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="fillRect pointer"></svg>
|
||||
<fill-box fill="${b.color[i]}"></fill-box>
|
||||
<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=${
|
||||
|
|
@ -158,15 +156,15 @@ function editBiomes() {
|
|||
|
||||
function biomeChangeColor(el) {
|
||||
const currentFill = el.getAttribute("fill");
|
||||
const biome = +el.parentNode.parentNode.dataset.id;
|
||||
const biome = +el.parentNode.dataset.id;
|
||||
|
||||
const callback = function (fill) {
|
||||
el.setAttribute("fill", fill);
|
||||
biomesData.color[biome] = fill;
|
||||
const callback = newFill => {
|
||||
el.fill = newFill;
|
||||
biomesData.color[biome] = newFill;
|
||||
biomes
|
||||
.select("#biome" + biome)
|
||||
.attr("fill", fill)
|
||||
.attr("stroke", fill);
|
||||
.attr("fill", newFill)
|
||||
.attr("stroke", newFill);
|
||||
};
|
||||
|
||||
openPicker(currentFill, callback);
|
||||
|
|
@ -270,7 +268,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="fillRect pointer"></svg>
|
||||
<fill-box fill="${b.color[i]}"></fill-box>
|
||||
<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]}>
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ function editBurg(id) {
|
|||
burgBody.querySelectorAll(".burgFeature").forEach(el => el.addEventListener("click", toggleFeature));
|
||||
document.getElementById("mfcgBurgSeed").addEventListener("change", changeSeed);
|
||||
document.getElementById("regenerateMFCGBurgSeed").addEventListener("click", randomizeSeed);
|
||||
document.getElementById("addCustomMFCGBurgLink").addEventListener("click", addCustomMfcgLink);
|
||||
|
||||
document.getElementById("burgStyleShow").addEventListener("click", showStyleSection);
|
||||
document.getElementById("burgStyleHide").addEventListener("click", hideStyleSection);
|
||||
|
|
@ -51,6 +52,7 @@ function editBurg(id) {
|
|||
document.getElementById("burglLegend").addEventListener("click", editBurgLegend);
|
||||
document.getElementById("burgLock").addEventListener("click", toggleBurgLockButton);
|
||||
document.getElementById("burgRemove").addEventListener("click", removeSelectedBurg);
|
||||
document.getElementById("burgTemperatureGraph").addEventListener("click", showTemperatureGraph);
|
||||
|
||||
function updateBurgValues() {
|
||||
const id = +elSelected.attr("data-id");
|
||||
|
|
@ -112,7 +114,13 @@ function editBurg(id) {
|
|||
if (options.showMFCGMap) {
|
||||
document.getElementById("mfcgPreviewSection").style.display = "block";
|
||||
updateMFCGFrame(b);
|
||||
document.getElementById("mfcgBurgSeed").value = getBurgSeed(b);
|
||||
|
||||
if (b.link) {
|
||||
document.getElementById("mfcgBurgSeedSection").style.display = "none";
|
||||
} else {
|
||||
document.getElementById("mfcgBurgSeedSection").style.display = "inline-block";
|
||||
document.getElementById("mfcgBurgSeed").value = getBurgSeed(b);
|
||||
}
|
||||
} else {
|
||||
document.getElementById("mfcgPreviewSection").style.display = "none";
|
||||
}
|
||||
|
|
@ -347,22 +355,25 @@ function editBurg(id) {
|
|||
|
||||
function toggleFeature() {
|
||||
const id = +elSelected.attr("data-id");
|
||||
const b = pack.burgs[id];
|
||||
const burg = pack.burgs[id];
|
||||
const feature = this.dataset.feature;
|
||||
const turnOn = this.classList.contains("inactive");
|
||||
if (feature === "port") togglePort(id);
|
||||
else if (feature === "capital") toggleCapital(id);
|
||||
else b[feature] = +turnOn;
|
||||
if (b[feature]) this.classList.remove("inactive");
|
||||
else if (!b[feature]) this.classList.add("inactive");
|
||||
else burg[feature] = +turnOn;
|
||||
if (burg[feature]) this.classList.remove("inactive");
|
||||
else if (!burg[feature]) this.classList.add("inactive");
|
||||
|
||||
if (b.port) document.getElementById("burgEditAnchorStyle").style.display = "inline-block";
|
||||
if (burg.port) document.getElementById("burgEditAnchorStyle").style.display = "inline-block";
|
||||
else document.getElementById("burgEditAnchorStyle").style.display = "none";
|
||||
updateMFCGFrame(burg);
|
||||
}
|
||||
|
||||
function toggleBurgLockButton() {
|
||||
const id = +elSelected.attr("data-id");
|
||||
toggleBurgLock(id);
|
||||
const burg = pack.burgs[id];
|
||||
burg.lock = !burg.lock;
|
||||
|
||||
updateBurgLockIcon();
|
||||
}
|
||||
|
||||
|
|
@ -426,6 +437,17 @@ function editBurg(id) {
|
|||
document.getElementById("mfcgBurgSeed").value = burgSeed;
|
||||
}
|
||||
|
||||
function addCustomMfcgLink() {
|
||||
const id = +elSelected.attr("data-id");
|
||||
const burg = pack.burgs[id];
|
||||
const message = "Enter custom link to the burg map. It can be a link to Medieval Fantasy City Generator or other tool. Keep empty to use MFCG seed";
|
||||
prompt(message, {default: burg.link || "", required: false}, link => {
|
||||
if (link) burg.link = link;
|
||||
else delete burg.link;
|
||||
updateMFCGFrame(burg);
|
||||
});
|
||||
}
|
||||
|
||||
function openEmblemEdit() {
|
||||
const id = +elSelected.attr("data-id"),
|
||||
burg = pack.burgs[id];
|
||||
|
|
@ -522,6 +544,11 @@ function editBurg(id) {
|
|||
editNotes("burg" + id, name);
|
||||
}
|
||||
|
||||
function showTemperatureGraph() {
|
||||
const id = elSelected.attr("data-id");
|
||||
showBurgTemperatureGraph(id);
|
||||
}
|
||||
|
||||
function removeSelectedBurg() {
|
||||
const id = +elSelected.attr("data-id");
|
||||
if (pack.burgs[id].capital) {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ function overviewBurgs() {
|
|||
|
||||
const body = document.getElementById("burgsBody");
|
||||
updateFilter();
|
||||
updateLockAllIcon();
|
||||
burgsOverviewAddLines();
|
||||
$("#burgsOverview").dialog();
|
||||
|
||||
|
|
@ -33,6 +34,7 @@ function overviewBurgs() {
|
|||
document.getElementById("burgsListToLoad").addEventListener("change", function () {
|
||||
uploadFile(this, importBurgNames);
|
||||
});
|
||||
document.getElementById("burgsLockAll").addEventListener("click", toggleLockAll);
|
||||
document.getElementById("burgsRemoveAll").addEventListener("click", triggerAllBurgsRemove);
|
||||
document.getElementById("burgsInvertLock").addEventListener("click", invertLock);
|
||||
|
||||
|
|
@ -87,7 +89,7 @@ function overviewBurgs() {
|
|||
<input data-tip="Burg name. Click and type to change" class="burgName" value="${b.name}" autocorrect="off" spellcheck="false">
|
||||
<input data-tip="Burg province" class="burgState" value="${province}" disabled>
|
||||
<input data-tip="Burg state" class="burgState" value="${state}" disabled>
|
||||
<select data-tip="Dominant culture. Click to change burg culture (to change cell cultrure use Cultures Editor)" class="stateCulture">${getCultureOptions(
|
||||
<select data-tip="Dominant culture. Click to change burg culture (to change cell culture use Cultures Editor)" class="stateCulture">${getCultureOptions(
|
||||
b.culture
|
||||
)}</select>
|
||||
<span data-tip="Burg population" class="icon-male"></span>
|
||||
|
|
@ -195,8 +197,11 @@ function overviewBurgs() {
|
|||
}
|
||||
|
||||
function toggleBurgLockStatus() {
|
||||
const burg = +this.parentNode.dataset.id;
|
||||
toggleBurgLock(burg);
|
||||
const burgId = +this.parentNode.dataset.id;
|
||||
|
||||
const burg = pack.burgs[burgId];
|
||||
burg.lock = !burg.lock;
|
||||
|
||||
if (this.classList.contains("icon-lock")) {
|
||||
this.classList.remove("icon-lock");
|
||||
this.classList.add("icon-lock-open");
|
||||
|
|
@ -478,9 +483,9 @@ function overviewBurgs() {
|
|||
}
|
||||
|
||||
function renameBurgsInBulk() {
|
||||
const message = `Download burgs list as a text file, make changes and re-upload the file.
|
||||
alertMessage.innerHTML = `Download burgs list as a text file, make changes and re-upload the file.
|
||||
Make sure the file is a plain text document with each name on its own line (the dilimiter is CRLF).
|
||||
If you do not want to change the name, just leave it as is`;
|
||||
alertMessage.innerHTML = message;
|
||||
|
||||
$("#alert").dialog({
|
||||
title: "Burgs bulk renaming",
|
||||
|
|
@ -562,4 +567,21 @@ function overviewBurgs() {
|
|||
pack.burgs = pack.burgs.map(burg => ({...burg, lock: !burg.lock}));
|
||||
burgsOverviewAddLines();
|
||||
}
|
||||
|
||||
function toggleLockAll() {
|
||||
const activeBurgs = pack.burgs.filter(b => b.i && !b.removed);
|
||||
const allLocked = activeBurgs.every(burg => burg.lock);
|
||||
|
||||
pack.burgs.forEach(burg => {
|
||||
burg.lock = !allLocked;
|
||||
});
|
||||
|
||||
burgsOverviewAddLines();
|
||||
document.getElementById("burgsLockAll").className = allLocked ? "icon-lock" : "icon-lock-open";
|
||||
}
|
||||
|
||||
function updateLockAllIcon() {
|
||||
const allLocked = pack.burgs.every(({lock, i, removed}) => lock || !i || removed);
|
||||
document.getElementById("burgsLockAll").className = allLocked ? "icon-lock-open" : "icon-lock";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,9 +108,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} data-emblems="${c.shield}">
|
||||
<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>
|
||||
<fill-box fill="${c.color}"></fill-box>
|
||||
<input data-tip="Culture name. Click and type to change" class="cultureName" value="${c.name}" autocorrect="off" spellcheck="false">
|
||||
<span data-tip="Regenerate culture name" class="icon-cw hiddenIcon" style="visibility: hidden"></span>
|
||||
<span data-tip="Cells count" class="icon-check-empty hide"></span>
|
||||
|
|
@ -148,7 +146,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.fillRect").forEach(el => el.addEventListener("click", cultureChangeColor));
|
||||
body.querySelectorAll("fill-box").forEach(el => el.addEventListener("click", cultureChangeColor));
|
||||
body.querySelectorAll("div > input.cultureName").forEach(el => el.addEventListener("input", cultureChangeName));
|
||||
body.querySelectorAll("div > span.icon-cw").forEach(el => el.addEventListener("click", cultureRegenerateName));
|
||||
body.querySelectorAll("div > input.statePower").forEach(el => el.addEventListener("input", cultureChangeExpansionism));
|
||||
|
|
@ -248,16 +246,16 @@ function editCultures() {
|
|||
function cultureChangeColor() {
|
||||
const el = this;
|
||||
const currentFill = el.getAttribute("fill");
|
||||
const culture = +el.parentNode.parentNode.dataset.id;
|
||||
const culture = +el.parentNode.dataset.id;
|
||||
|
||||
const callback = function (fill) {
|
||||
el.setAttribute("fill", fill);
|
||||
pack.cultures[culture].color = fill;
|
||||
const callback = newFill => {
|
||||
el.fill = newFill;
|
||||
pack.cultures[culture].color = newFill;
|
||||
cults
|
||||
.select("#culture" + culture)
|
||||
.attr("fill", fill)
|
||||
.attr("stroke", fill);
|
||||
debug.select("#cultureCenter" + culture).attr("fill", fill);
|
||||
.attr("fill", newFill)
|
||||
.attr("stroke", newFill);
|
||||
debug.select("#cultureCenter" + culture).attr("fill", newFill);
|
||||
};
|
||||
|
||||
openPicker(currentFill, callback);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
"use strict";
|
||||
function editDiplomacy() {
|
||||
if (customization) return;
|
||||
if (pack.states.filter(s => s.i && !s.removed).length < 2) {
|
||||
tip("There should be at least 2 states to edit the diplomacy", false, "error");
|
||||
return;
|
||||
}
|
||||
if (pack.states.filter(s => s.i && !s.removed).length < 2) return tip("There should be at least 2 states to edit the diplomacy", false, "error");
|
||||
|
||||
const body = document.getElementById("diplomacyBodySection");
|
||||
|
||||
closeDialogs("#diplomacyEditor, .stable");
|
||||
if (!layerIsOn("toggleStates")) toggleStates();
|
||||
|
|
@ -14,21 +13,29 @@ function editDiplomacy() {
|
|||
if (layerIsOn("toggleBiomes")) toggleBiomes();
|
||||
if (layerIsOn("toggleReligions")) toggleReligions();
|
||||
|
||||
const body = document.getElementById("diplomacyBodySection");
|
||||
const statuses = ["Ally", "Friendly", "Neutral", "Suspicion", "Enemy", "Unknown", "Rival", "Vassal", "Suzerain"];
|
||||
const description = [" is an ally of ", " is friendly to ", " is neutral to ", " is suspicious of ",
|
||||
" is at war with ", " does not know about ", " is a rival of ", " is a vassal of ", " is suzerain to "];
|
||||
const colors = ["#00b300", "#d4f8aa", "#edeee8", "#eeafaa", "#e64b40", "#a9a9a9", "#ad5a1f", "#87CEFA", "#00008B"];
|
||||
refreshDiplomacyEditor();
|
||||
const relations = {
|
||||
Ally: {inText: "is an ally of", color: "#00b300", tip: "Allies formed a defensive pact and protect each other in case of third party aggression"},
|
||||
Friendly: {inText: "is friendly to", color: "#d4f8aa", tip: "State is friendly to anouther state when they share some common interests"},
|
||||
Neutral: {inText: "is neutral to", color: "#edeee8", tip: "Neutral means states relations are neither positive nor negative"},
|
||||
Suspicion: {inText: "is suspicious of", color: "#eeafaa", tip: "Suspicion means state has a cautious distrust of another state"},
|
||||
Enemy: {inText: "is at war with", color: "#e64b40", tip: "Enemies are states at war with each other"},
|
||||
Unknown: {inText: "does not know about", color: "#a9a9a9", tip: "Relations are unknown if states do not have enough information about each other"},
|
||||
Rival: {inText: "is a rival of", color: "#ad5a1f", tip: "Rivalry is a state of competing for dominance in the region"},
|
||||
Vassal: {inText: "is a vassal of", color: "#87CEFA", tip: "Vassal is a state having obligation to its suzerain"},
|
||||
Suzerain: {inText: "is suzerain to", color: "#00008B", tip: "Suzerain is a state having some control over its vassals"}
|
||||
};
|
||||
|
||||
tip("Click on a state to see its diplomatic relations", false, "warning");
|
||||
refreshDiplomacyEditor();
|
||||
viewbox.style("cursor", "crosshair").on("click", selectStateOnMapClick);
|
||||
|
||||
if (modules.editDiplomacy) return;
|
||||
modules.editDiplomacy = true;
|
||||
|
||||
$("#diplomacyEditor").dialog({
|
||||
title: "Diplomacy Editor", resizable: false, width: fitContent(), close: closeDiplomacyEditor,
|
||||
title: "Diplomacy Editor",
|
||||
resizable: false,
|
||||
width: fitContent(),
|
||||
close: closeDiplomacyEditor,
|
||||
position: {my: "right top", at: "right-10 top+10", of: "svg", collision: "fit"}
|
||||
});
|
||||
|
||||
|
|
@ -36,10 +43,30 @@ function editDiplomacy() {
|
|||
document.getElementById("diplomacyEditorRefresh").addEventListener("click", refreshDiplomacyEditor);
|
||||
document.getElementById("diplomacyEditStyle").addEventListener("click", () => editStyle("regions"));
|
||||
document.getElementById("diplomacyRegenerate").addEventListener("click", regenerateRelations);
|
||||
document.getElementById("diplomacyMatrix").addEventListener("click", showRelationsMatrix);
|
||||
document.getElementById("diplomacyReset").addEventListener("click", resetRelations);
|
||||
document.getElementById("diplomacyShowMatrix").addEventListener("click", showRelationsMatrix);
|
||||
document.getElementById("diplomacyHistory").addEventListener("click", showRelationsHistory);
|
||||
document.getElementById("diplomacyExport").addEventListener("click", downloadDiplomacyData);
|
||||
document.getElementById("diplomacySelect").addEventListener("mouseup", diplomacyChangeRelations);
|
||||
|
||||
body.addEventListener("click", function (ev) {
|
||||
const el = ev.target;
|
||||
if (el.parentElement.classList.contains("Self")) return;
|
||||
|
||||
if (el.classList.contains("changeRelations")) {
|
||||
const line = el.parentElement;
|
||||
const subjectId = +line.dataset.id;
|
||||
const objectId = +body.querySelector("div.Self").dataset.id;
|
||||
const currentRelation = line.dataset.relations;
|
||||
|
||||
selectRelation(subjectId, objectId, currentRelation);
|
||||
return;
|
||||
}
|
||||
|
||||
// select state of clicked line
|
||||
body.querySelector("div.Self").classList.remove("Self");
|
||||
el.parentElement.classList.add("Self");
|
||||
refreshDiplomacyEditor();
|
||||
});
|
||||
|
||||
function refreshDiplomacyEditor() {
|
||||
diplomacyEditorAddLines();
|
||||
|
|
@ -50,33 +77,34 @@ function editDiplomacy() {
|
|||
function diplomacyEditorAddLines() {
|
||||
const states = pack.states;
|
||||
const selectedLine = body.querySelector("div.Self");
|
||||
const sel = selectedLine ? +selectedLine.dataset.id : states.find(s => s.i && !s.removed).i;
|
||||
const selName = states[sel].fullName;
|
||||
diplomacySelect.style.display = "none";
|
||||
const selectedId = selectedLine ? +selectedLine.dataset.id : states.find(s => s.i && !s.removed).i;
|
||||
const selectedName = states[selectedId].name;
|
||||
|
||||
COArenderer.trigger("stateCOA"+sel, states[sel].coa);
|
||||
let lines = `<div class="states Self" data-id=${sel} data-tip="List below shows relations to ${selName}">
|
||||
<div style="width: max-content">${selName}</div>
|
||||
<svg class="coaIcon" viewBox="0 0 200 200"><use href="#stateCOA${sel}"></use></svg>
|
||||
COArenderer.trigger("stateCOA" + selectedId, states[selectedId].coa);
|
||||
let lines = `<div class="states Self" data-id=${selectedId} data-tip="List below shows relations to ${selectedName}">
|
||||
<div style="width: max-content">${states[selectedId].fullName}</div>
|
||||
<svg class="coaIcon" viewBox="0 0 200 200"><use href="#stateCOA${selectedId}"></use></svg>
|
||||
</div>`;
|
||||
|
||||
for (const s of states) {
|
||||
if (!s.i || s.removed || s.i === sel) continue;
|
||||
const relation = s.diplomacy[sel];
|
||||
const index = statuses.indexOf(relation);
|
||||
const color = colors[index];
|
||||
const tip = s.fullName + description[index] + selName;
|
||||
const tipSelect = `${tip}. Click to see relations to ${s.name}`;
|
||||
const tipChange = `${tip}. Click to change relations to ${selName}`;
|
||||
COArenderer.trigger("stateCOA"+s.i, s.coa);
|
||||
for (const state of states) {
|
||||
if (!state.i || state.removed || state.i === selectedId) continue;
|
||||
const relation = state.diplomacy[selectedId];
|
||||
const {color, inText} = relations[relation];
|
||||
|
||||
lines += `<div class="states" data-id=${s.i} data-name="${s.fullName}" data-relations="${relation}">
|
||||
<svg data-tip="${tipSelect}" class="coaIcon" viewBox="0 0 200 200"><use href="#stateCOA${s.i}"></use></svg>
|
||||
<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="fillRect pointer" style="pointer-events: none"></rect>
|
||||
</svg>
|
||||
<input data-tip="${tipChange}" class="changeRelations diplomacyRelations" value="${relation}" readonly/>
|
||||
const tip = `${state.name} ${inText} ${selectedName}`;
|
||||
const tipSelect = `${tip}. Click to see relations to ${state.name}`;
|
||||
const tipChange = `Click to change relations. ${tip}`;
|
||||
|
||||
const name = state.fullName.length < 23 ? state.fullName : state.name;
|
||||
COArenderer.trigger("stateCOA" + state.i, state.coa);
|
||||
|
||||
lines += `<div class="states" data-id=${state.i} data-name="${name}" data-relations="${relation}">
|
||||
<svg data-tip="${tipSelect}" class="coaIcon" viewBox="0 0 200 200"><use href="#stateCOA${state.i}"></use></svg>
|
||||
<div data-tip="${tipSelect}" style="width: 12em">${name}</div>
|
||||
<div data-tip="${tipChange}" class="changeRelations" style="width: 6em">
|
||||
<fill-box fill="${color}" size=".9em"></fill-box>
|
||||
${relation}
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
body.innerHTML = lines;
|
||||
|
|
@ -84,8 +112,6 @@ function editDiplomacy() {
|
|||
// 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)));
|
||||
body.querySelectorAll("div.states").forEach(el => el.addEventListener("click", selectStateOnLineClick));
|
||||
body.querySelectorAll(".changeRelations").forEach(el => el.addEventListener("click", toggleDiplomacySelect));
|
||||
|
||||
applySorting(diplomacyHeader);
|
||||
$("#diplomacyEditor").dialog();
|
||||
|
|
@ -95,19 +121,31 @@ function editDiplomacy() {
|
|||
if (!layerIsOn("toggleStates")) return;
|
||||
const state = +event.target.dataset.id;
|
||||
if (customization || !state) return;
|
||||
const d = regions.select("#state"+state).attr("d");
|
||||
const d = regions.select("#state" + state).attr("d");
|
||||
|
||||
const path = debug.append("path").attr("class", "highlight").attr("d", d)
|
||||
.attr("fill", "none").attr("stroke", "red").attr("stroke-width", 1).attr("opacity", 1)
|
||||
const path = debug
|
||||
.append("path")
|
||||
.attr("class", "highlight")
|
||||
.attr("d", d)
|
||||
.attr("fill", "none")
|
||||
.attr("stroke", "red")
|
||||
.attr("stroke-width", 1)
|
||||
.attr("opacity", 1)
|
||||
.attr("filter", "url(#blur1)");
|
||||
|
||||
const l = path.node().getTotalLength(), dur = (l + 5000) / 2;
|
||||
const l = path.node().getTotalLength(),
|
||||
dur = (l + 5000) / 2;
|
||||
const i = d3.interpolateString("0," + l, l + "," + l);
|
||||
path.transition().duration(dur).attrTween("stroke-dasharray", function() {return t => i(t)});
|
||||
path
|
||||
.transition()
|
||||
.duration(dur)
|
||||
.attrTween("stroke-dasharray", function () {
|
||||
return t => i(t);
|
||||
});
|
||||
}
|
||||
|
||||
function stateHighlightOff(event) {
|
||||
debug.selectAll(".highlight").each(function() {
|
||||
debug.selectAll(".highlight").each(function () {
|
||||
d3.select(this).transition().duration(1000).attr("opacity", 0).remove();
|
||||
});
|
||||
}
|
||||
|
|
@ -118,22 +156,17 @@ function editDiplomacy() {
|
|||
if (!sel) return;
|
||||
if (!layerIsOn("toggleStates")) toggleStates();
|
||||
|
||||
statesBody.selectAll("path").each(function() {
|
||||
statesBody.selectAll("path").each(function () {
|
||||
if (this.id.slice(0, 9) === "state-gap") return; // exclude state gap element
|
||||
const id = +this.id.slice(5); // state id
|
||||
const index = statuses.indexOf(pack.states[id].diplomacy[sel]); // status index
|
||||
const clr = index !== -1 ? colors[index] : "#4682b4"; // Self (bluish)
|
||||
this.setAttribute("fill", clr);
|
||||
statesBody.select("#state-gap"+id).attr("stroke", clr);
|
||||
statesHalo.select("#state-border"+id).attr("stroke", d3.color(clr).darker().hex());
|
||||
});
|
||||
}
|
||||
|
||||
function selectStateOnLineClick() {
|
||||
if (this.classList.contains("Self")) return;
|
||||
body.querySelector("div.Self").classList.remove("Self");
|
||||
this.classList.add("Self");
|
||||
refreshDiplomacyEditor();
|
||||
const relation = pack.states[id].diplomacy[sel];
|
||||
const color = relations[relation]?.color || "#4682b4";
|
||||
|
||||
this.setAttribute("fill", color);
|
||||
statesBody.select("#state-gap" + id).attr("stroke", color);
|
||||
statesHalo.select("#state-border" + id).attr("stroke", d3.color(color).darker().hex());
|
||||
});
|
||||
}
|
||||
|
||||
function selectStateOnMapClick() {
|
||||
|
|
@ -145,42 +178,61 @@ function editDiplomacy() {
|
|||
if (+selectedLine.dataset.id === state) return;
|
||||
|
||||
selectedLine.classList.remove("Self");
|
||||
body.querySelector("div[data-id='"+state+"']").classList.add("Self");
|
||||
body.querySelector("div[data-id='" + state + "']").classList.add("Self");
|
||||
refreshDiplomacyEditor();
|
||||
}
|
||||
|
||||
function toggleDiplomacySelect(event) {
|
||||
event.stopPropagation();
|
||||
const select = document.getElementById("diplomacySelect");
|
||||
const show = select.style.display === "none";
|
||||
if (!show) {select.style.display = "none"; return;}
|
||||
select.style.display = "block";
|
||||
const input = event.target.closest("div").querySelector("input");
|
||||
select.style.left = input.getBoundingClientRect().left + "px";
|
||||
select.style.top = input.getBoundingClientRect().bottom + "px";
|
||||
body.dataset.state = event.target.closest("div.states").dataset.id;
|
||||
function selectRelation(subjectId, objectId, currentRelation) {
|
||||
const states = pack.states;
|
||||
|
||||
const subject = states[subjectId];
|
||||
const header = `<div style="margin-bottom: 0.3em"><svg class="coaIcon" viewBox="0 0 200 200"><use href="#stateCOA${subject.i}"></use></svg> <b>${subject.fullName}</b></div>`;
|
||||
|
||||
const options = Object.entries(relations)
|
||||
.map(
|
||||
([relation, {color, inText, tip}]) =>
|
||||
`<div style="margin-block: 0.2em" data-tip="${tip}"><label class="pointer">
|
||||
<input type="radio" name="relationSelect" value="${relation}" ${currentRelation === relation && "checked"} >
|
||||
<fill-box fill="${color}" size=".8em"></fill-box>
|
||||
${inText}
|
||||
</label></div>`
|
||||
)
|
||||
.join("");
|
||||
|
||||
const object = states[objectId];
|
||||
const footer = `<div style="margin-top: 0.7em"><svg class="coaIcon" viewBox="0 0 200 200"><use href="#stateCOA${object.i}"></use></svg> <b>${object.fullName}</b></div>`;
|
||||
|
||||
alertMessage.innerHTML = `<div style="overflow: hidden">${header} ${options} ${footer}</div>`;
|
||||
|
||||
$("#alert").dialog({
|
||||
width: fitContent(),
|
||||
title: `Change relations`,
|
||||
buttons: {
|
||||
Apply: function () {
|
||||
const newRelation = document.querySelector('input[name="relationSelect"]:checked')?.value;
|
||||
changeRelation(subjectId, objectId, currentRelation, newRelation);
|
||||
$(this).dialog("close");
|
||||
},
|
||||
Cancel: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function diplomacyChangeRelations(event) {
|
||||
event.stopPropagation();
|
||||
diplomacySelect.style.display = "none";
|
||||
const subject = +body.dataset.state;
|
||||
const rel = event.target.innerHTML;
|
||||
function changeRelation(subjectId, objectId, oldRelation, newRelation) {
|
||||
if (newRelation === oldRelation) return;
|
||||
const states = pack.states;
|
||||
const chronicle = states[0].diplomacy;
|
||||
|
||||
const states = pack.states, chronicle = states[0].diplomacy;
|
||||
const selectedLine = body.querySelector("div.Self");
|
||||
const object = selectedLine ? +selectedLine.dataset.id : states.find(s => s.i && !s.removed).i;
|
||||
if (!object) return;
|
||||
const objectName = states[object].name; // object of relations change
|
||||
const subjectName = states[subject].name; // subject of relations change - actor
|
||||
const subjectName = states[subjectId].name;
|
||||
const objectName = states[objectId].name;
|
||||
|
||||
const oldRel = states[subject].diplomacy[object];
|
||||
if (rel === oldRel) return;
|
||||
states[subject].diplomacy[object] = rel;
|
||||
states[object].diplomacy[subject] = rel === "Vassal" ? "Suzerain" : rel === "Suzerain" ? "Vassal" : rel;
|
||||
states[subjectId].diplomacy[objectId] = newRelation;
|
||||
states[objectId].diplomacy[subjectId] = newRelation === "Vassal" ? "Suzerain" : newRelation === "Suzerain" ? "Vassal" : newRelation;
|
||||
|
||||
// update relation history
|
||||
const change = () => [`Relations change`, `${subjectName}-${getAdjective(objectName)} relations changed to ${rel.toLowerCase()}`];
|
||||
const change = () => [`Relations change`, `${subjectName}-${getAdjective(objectName)} relations changed to ${newRelation.toLowerCase()}`];
|
||||
const ally = () => [`Defence pact`, `${subjectName} entered into defensive pact with ${objectName}`];
|
||||
const vassal = () => [`Vassalization`, `${subjectName} became a vassal of ${objectName}`];
|
||||
const suzerain = () => [`Vassalization`, `${subjectName} vassalized ${objectName}`];
|
||||
|
|
@ -189,24 +241,33 @@ function editDiplomacy() {
|
|||
const war = () => [`War declaration`, `${subjectName} declared a war on its enemy ${objectName}`];
|
||||
const peace = () => {
|
||||
const treaty = `${subjectName} and ${objectName} agreed to cease fire and signed a peace treaty`;
|
||||
const changed = rel === "Ally" ? ally()
|
||||
: rel === "Vassal" ? vassal()
|
||||
: rel === "Suzerain" ? suzerain()
|
||||
: rel === "Unknown" ? unknown()
|
||||
: change();
|
||||
const changed =
|
||||
newRelation === "Ally"
|
||||
? ally()
|
||||
: newRelation === "Vassal"
|
||||
? vassal()
|
||||
: newRelation === "Suzerain"
|
||||
? suzerain()
|
||||
: newRelation === "Unknown"
|
||||
? unknown()
|
||||
: change();
|
||||
return [`War termination`, treaty, changed[1]];
|
||||
}
|
||||
};
|
||||
|
||||
if (oldRel === "Enemy") chronicle.push(peace()); else
|
||||
if (rel === "Enemy") chronicle.push(war()); else
|
||||
if (rel === "Vassal") chronicle.push(vassal()); else
|
||||
if (rel === "Suzerain") chronicle.push(suzerain()); else
|
||||
if (rel === "Ally") chronicle.push(ally()); else
|
||||
if (rel === "Unknown") chronicle.push(unknown()); else
|
||||
if (rel === "Rival") chronicle.push(rival()); else
|
||||
chronicle.push(change());
|
||||
if (oldRelation === "Enemy") chronicle.push(peace());
|
||||
else if (newRelation === "Enemy") chronicle.push(war());
|
||||
else if (newRelation === "Vassal") chronicle.push(vassal());
|
||||
else if (newRelation === "Suzerain") chronicle.push(suzerain());
|
||||
else if (newRelation === "Ally") chronicle.push(ally());
|
||||
else if (newRelation === "Unknown") chronicle.push(unknown());
|
||||
else if (newRelation === "Rival") chronicle.push(rival());
|
||||
else chronicle.push(change());
|
||||
|
||||
refreshDiplomacyEditor();
|
||||
if (diplomacyMatrix.offsetParent) {
|
||||
document.getElementById("diplomacyMatrixBody").innerHTML = "";
|
||||
showRelationsMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
function regenerateRelations() {
|
||||
|
|
@ -214,28 +275,52 @@ function editDiplomacy() {
|
|||
refreshDiplomacyEditor();
|
||||
}
|
||||
|
||||
function resetRelations() {
|
||||
const selectedId = +body.querySelector("div.Self")?.dataset?.id;
|
||||
if (!selectedId) return;
|
||||
const states = pack.states;
|
||||
|
||||
states[selectedId].diplomacy.forEach((relations, index) => {
|
||||
if (relations !== "x") {
|
||||
states[selectedId].diplomacy[index] = "Neutral";
|
||||
states[index].diplomacy[selectedId] = "Neutral";
|
||||
}
|
||||
});
|
||||
|
||||
refreshDiplomacyEditor();
|
||||
}
|
||||
|
||||
function showRelationsHistory() {
|
||||
const chronicle = pack.states[0].diplomacy;
|
||||
if (!chronicle.length) {tip("Relations history is blank", false, "error"); return;}
|
||||
if (!chronicle.length) return tip("Relations history is blank", false, "error");
|
||||
|
||||
let message = `<div autocorrect="off" spellcheck="false">`;
|
||||
chronicle.forEach((e, d) => {
|
||||
chronicle.forEach((entry, d) => {
|
||||
message += `<div>`;
|
||||
e.forEach((l, i) => message += `<div contenteditable="true" data-id="${d}-${i}"${i ? "" : " style='font-weight:bold'"}>${l}</div>`);
|
||||
entry.forEach((l, i) => {
|
||||
message += `<div contenteditable="true" data-id="${d}-${i}"${i ? "" : " style='font-weight:bold'"}>${l}</div>`;
|
||||
});
|
||||
message += `‍</div>`;
|
||||
});
|
||||
alertMessage.innerHTML = message + `</div><i id="info-line">Type to edit. Press Enter to add a new line, empty the element to remove it</i>`;
|
||||
alertMessage.innerHTML = message + `</div><div class="info-line">Type to edit. Press Enter to add a new line, empty the element to remove it</div>`;
|
||||
alertMessage.querySelectorAll("div[contenteditable='true']").forEach(el => el.addEventListener("input", changeReliationsHistory));
|
||||
|
||||
$("#alert").dialog({title: "Relations history", position: {my: "center", at: "center", of: "svg"},
|
||||
$("#alert").dialog({
|
||||
title: "Relations history",
|
||||
position: {my: "center", at: "center", of: "svg"},
|
||||
buttons: {
|
||||
Save: function() {
|
||||
Save: function () {
|
||||
const data = this.querySelector("div").innerText.split("\n").join("\r\n");
|
||||
const name = getFileName("Relations history") + ".txt";
|
||||
downloadFile(data, name);
|
||||
},
|
||||
Clear: function() {pack.states[0].diplomacy = []; $(this).dialog("close");},
|
||||
Close: function() {$(this).dialog("close");}
|
||||
Clear: function () {
|
||||
pack.states[0].diplomacy = [];
|
||||
$(this).dialog("close");
|
||||
},
|
||||
Close: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -251,22 +336,48 @@ function editDiplomacy() {
|
|||
|
||||
function showRelationsMatrix() {
|
||||
const states = pack.states.filter(s => s.i && !s.removed);
|
||||
const valid = states.map(s => s.i);
|
||||
const valid = states.map(state => state.i);
|
||||
const diplomacyMatrixBody = document.getElementById("diplomacyMatrixBody");
|
||||
|
||||
let message = `<table class="matrix-table"><tr><th data-tip='‍'></th>`;
|
||||
message += states.map(s => `<th data-tip='See relations to ${s.fullName}'>${s.name}</th>`).join("") + `</tr>`; // headers
|
||||
states.forEach(s => {
|
||||
message += `<tr><th data-tip='See relations of ${s.fullName}'>${s.name}</th>` + s.diplomacy
|
||||
.filter((v, i) => valid.includes(i)).map((r, i) => {
|
||||
const desc = description[statuses.indexOf(r)];
|
||||
const tip = desc ? s.fullName + desc + pack.states[valid[i]].fullName : '‍';
|
||||
return `<td data-tip='${tip}' class='${r}'>${r}</td>`
|
||||
}).join("") + "</tr>";
|
||||
let table = `<table><thead><tr><th data-tip='‍'></th>`;
|
||||
table += states.map(state => `<th data-tip='Relations to ${state.fullName}'>${state.name}</th>`).join("") + `</tr>`;
|
||||
table += `<tbody>`;
|
||||
|
||||
states.forEach(state => {
|
||||
table +=
|
||||
`<tr data-id=${state.i}><th data-tip='Relations of ${state.fullName}'>${state.name}</th>` +
|
||||
state.diplomacy
|
||||
.filter((v, i) => valid.includes(i))
|
||||
.map((relation, index) => {
|
||||
const relationObj = relations[relation];
|
||||
if (!relationObj) return `<td class='${relation}'>${relation}</td>`;
|
||||
|
||||
const objectState = pack.states[valid[index]];
|
||||
const tip = `${state.fullName} ${relationObj.inText} ${objectState.fullName}`;
|
||||
return `<td data-id=${objectState.i} data-tip='${tip}' class='${relation}'>${relation}</td>`;
|
||||
})
|
||||
.join("") +
|
||||
"</tr>";
|
||||
});
|
||||
message += `</table>`;
|
||||
alertMessage.innerHTML = message;
|
||||
|
||||
$("#alert").dialog({title: "Relations matrix", width: fitContent(), position: {my: "center", at: "center", of: "svg"}, buttons: {}});
|
||||
table += `</tbody></table>`;
|
||||
diplomacyMatrixBody.innerHTML = table;
|
||||
|
||||
const tableEl = diplomacyMatrixBody.querySelector("table");
|
||||
tableEl.addEventListener("click", function (event) {
|
||||
const el = event.target;
|
||||
if (el.tagName !== "TD") return;
|
||||
|
||||
const currentRelation = el.innerText;
|
||||
if (!relations[currentRelation]) return;
|
||||
|
||||
const subjectId = +el.closest("tr")?.dataset?.id;
|
||||
const objectId = +el?.dataset?.id;
|
||||
|
||||
selectRelation(subjectId, objectId, currentRelation);
|
||||
});
|
||||
|
||||
$("#diplomacyMatrix").dialog({title: "Relations matrix", position: {my: "center", at: "center", of: "svg"}, buttons: {}});
|
||||
}
|
||||
|
||||
function downloadDiplomacyData() {
|
||||
|
|
@ -288,7 +399,8 @@ function editDiplomacy() {
|
|||
clearMainTip();
|
||||
const selected = body.querySelector("div.Self");
|
||||
if (selected) selected.classList.remove("Self");
|
||||
if (layerIsOn("toggleStates")) drawStates(); else toggleStates();
|
||||
if (layerIsOn("toggleStates")) drawStates();
|
||||
else toggleStates();
|
||||
debug.selectAll(".highlight").remove();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,41 +265,48 @@ function getBurgSeed(burg) {
|
|||
}
|
||||
|
||||
function getMFCGlink(burg) {
|
||||
if (burg.link) return burg.link;
|
||||
|
||||
const {cells} = pack;
|
||||
const {name, population, cell} = burg;
|
||||
const burgSeed = getBurgSeed(burg);
|
||||
const sizeRaw = 2.13 * Math.pow((population * populationRate) / urbanDensity, 0.385);
|
||||
const {i, name, population: burgPopulation, cell} = burg;
|
||||
const seed = getBurgSeed(burg);
|
||||
|
||||
const sizeRaw = 2.13 * Math.pow((burgPopulation * populationRate) / urbanDensity, 0.385);
|
||||
const size = minmax(Math.ceil(sizeRaw), 6, 100);
|
||||
const people = rn(population * populationRate * urbanization);
|
||||
const population = rn(burgPopulation * populationRate * urbanization);
|
||||
|
||||
const river = cells.r[cell] ? 1 : 0;
|
||||
const coast = Number(burg.port > 0);
|
||||
const sea = coast && cells.haven[cell] ? getSeaDirections(cell) : null;
|
||||
|
||||
const biome = cells.biome[cell];
|
||||
const arableBiomes = river ? [1, 2, 3, 4, 5, 6, 7, 8] : [5, 6, 7, 8];
|
||||
const farms = +arableBiomes.includes(biome);
|
||||
|
||||
const citadel = +burg.citadel;
|
||||
const urban_castle = +(citadel && each(2)(i));
|
||||
|
||||
const hub = +cells.road[cell] > 50;
|
||||
const river = cells.r[cell] ? 1 : 0;
|
||||
|
||||
const coast = +burg.port;
|
||||
const citadel = +burg.citadel;
|
||||
const walls = +burg.walls;
|
||||
const plaza = +burg.plaza;
|
||||
const temple = +burg.temple;
|
||||
const shanty = +burg.shanty;
|
||||
const shantytown = +burg.shanty;
|
||||
|
||||
const sea = coast && cells.haven[cell] ? getSeaDirections(cell) : "";
|
||||
function getSeaDirections(i) {
|
||||
const p1 = cells.p[i];
|
||||
const p2 = cells.p[cells.haven[i]];
|
||||
let deg = (Math.atan2(p2[1] - p1[1], p2[0] - p1[0]) * 180) / Math.PI - 90;
|
||||
if (deg < 0) deg += 360;
|
||||
const norm = rn(normalize(deg, 0, 360) * 2, 2); // 0 = south, 0.5 = west, 1 = north, 1.5 = east
|
||||
return "&sea=" + norm;
|
||||
return rn(normalize(deg, 0, 360) * 2, 2); // 0 = south, 0.5 = west, 1 = north, 1.5 = east
|
||||
}
|
||||
|
||||
const baseURL = "https://watabou.github.io/city-generator/?random=0&continuous=0";
|
||||
const url = `${baseURL}&name=${name}&population=${people}&size=${size}&seed=${burgSeed}&hub=${hub}&river=${river}&coast=${coast}&citadel=${citadel}&plaza=${plaza}&temple=${temple}&walls=${walls}&shantytown=${shanty}${sea}`;
|
||||
return url;
|
||||
}
|
||||
const parameters = {name, population, size, seed, river, coast, farms, citadel, urban_castle, hub, plaza, temple, walls, shantytown, gates: -1};
|
||||
const url = new URL("https://watabou.github.io/city-generator");
|
||||
url.search = new URLSearchParams(parameters);
|
||||
if (sea) url.searchParams.append("sea", sea);
|
||||
|
||||
function toggleBurgLock(burg) {
|
||||
const b = pack.burgs[burg];
|
||||
b.lock = b.lock ? 0 : 1;
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
// draw legend box
|
||||
|
|
@ -418,10 +425,10 @@ function clearLegend() {
|
|||
function createPicker() {
|
||||
const pos = () => tip("Drag to change the picker position");
|
||||
const cl = () => tip("Click to close the picker");
|
||||
const closePicker = () => contaiter.style("display", "none");
|
||||
const closePicker = () => container.style("display", "none");
|
||||
|
||||
const contaiter = d3.select("body").append("svg").attr("id", "pickerContainer").attr("width", "100%").attr("height", "100%");
|
||||
contaiter
|
||||
const container = d3.select("body").append("svg").attr("id", "pickerContainer").attr("width", "100%").attr("height", "100%");
|
||||
container
|
||||
.append("rect")
|
||||
.attr("x", 0)
|
||||
.attr("y", 0)
|
||||
|
|
@ -430,7 +437,7 @@ function createPicker() {
|
|||
.attr("opacity", 0.2)
|
||||
.on("mousemove", cl)
|
||||
.on("click", closePicker);
|
||||
const picker = contaiter
|
||||
const picker = container
|
||||
.append("g")
|
||||
.attr("id", "picker")
|
||||
.call(
|
||||
|
|
@ -487,7 +494,7 @@ function createPicker() {
|
|||
|
||||
const colors = picker.append("g").attr("id", "pickerColors").attr("stroke", "#333333");
|
||||
const hatches = picker.append("g").attr("id", "pickerHatches").attr("stroke", "#333333");
|
||||
const hatching = d3.selectAll("g#hatching > pattern");
|
||||
const hatching = d3.selectAll("g#defs-hatching > pattern");
|
||||
const number = hatching.size();
|
||||
|
||||
const clr = d3.range(number).map(i => d3.hsl((i / number) * 360, 0.7, 0.7).hex());
|
||||
|
|
@ -497,8 +504,8 @@ function createPicker() {
|
|||
.attr("id", "picker_" + d)
|
||||
.attr("fill", d)
|
||||
.attr("class", i ? "" : "selected")
|
||||
.attr("x", i * 22 + 4)
|
||||
.attr("y", 40)
|
||||
.attr("x", (i % 14) * 22 + 4)
|
||||
.attr("y", 40 + Math.floor(i / 14)*20)
|
||||
.attr("width", 16)
|
||||
.attr("height", 16);
|
||||
});
|
||||
|
|
@ -508,20 +515,20 @@ function createPicker() {
|
|||
.append("rect")
|
||||
.attr("id", "picker_" + this.id)
|
||||
.attr("fill", "url(#" + this.id + ")")
|
||||
.attr("x", i * 22 + 4)
|
||||
.attr("y", 61)
|
||||
.attr("x", (i % 14) * 22 + 4)
|
||||
.attr("y", Math.floor(i / 14)*20 + 20 + (number * 2))
|
||||
.attr("width", 16)
|
||||
.attr("height", 16);
|
||||
.attr("height", 16)
|
||||
});
|
||||
|
||||
colors
|
||||
.selectAll("rect")
|
||||
.on("click", pickerFillClicked)
|
||||
.on("mousemove", () => tip("Click to fill with the color"));
|
||||
.on("mouseover", () => tip("Click to fill with the color"));
|
||||
hatches
|
||||
.selectAll("rect")
|
||||
.on("click", pickerFillClicked)
|
||||
.on("mousemove", () => tip("Click to fill with the hatching"));
|
||||
.on("mouseover", function() { tip("Click to fill with the hatching " + this.id) });
|
||||
|
||||
// append box
|
||||
const bbox = picker.node().getBBox();
|
||||
|
|
@ -537,10 +544,10 @@ function createPicker() {
|
|||
.attr("fill", "#ffffff")
|
||||
.attr("stroke", "#5d4651")
|
||||
.on("mousemove", pos);
|
||||
picker.insert("text", ":first-child").attr("x", 291).attr("y", -10).attr("id", "pickerCloseText").text("✕");
|
||||
picker.insert("text", ":first-child").attr("x", width-20).attr("y", -10).attr("id", "pickerCloseText").text("✕");
|
||||
picker
|
||||
.insert("rect", ":first-child")
|
||||
.attr("x", 288)
|
||||
.attr("x", width-23)
|
||||
.attr("y", -21)
|
||||
.attr("id", "pickerCloseRect")
|
||||
.attr("width", 14)
|
||||
|
|
|
|||
|
|
@ -460,32 +460,31 @@ function showInfo() {
|
|||
const Discord = link("https://discordapp.com/invite/X7E84HU", "Discord");
|
||||
const Reddit = link("https://www.reddit.com/r/FantasyMapGenerator", "Reddit");
|
||||
const Patreon = link("https://www.patreon.com/azgaar", "Patreon");
|
||||
const Trello = link("https://trello.com/b/7x832DG4/fantasy-map-generator", "Trello");
|
||||
const Armoria = link("https://azgaar.github.io/Armoria", "Armoria");
|
||||
|
||||
const QuickStart = link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Quick-Start-Tutorial", "Quick start tutorial");
|
||||
const QAA = link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Q&A", "Q&A page");
|
||||
const VideoTutorial = link("https://youtube.com/playlist?list=PLtgiuDC8iVR2gIG8zMTRn7T_L0arl9h1C", "Video tutorial");
|
||||
|
||||
alertMessage.innerHTML = `
|
||||
<b>Fantasy Map Generator</b> (FMG) is an open-source application, it means the code is published an anyone can use it.
|
||||
In case of FMG is also means that you own all created maps and can use them as you wish, you can even sell them.
|
||||
<b>Fantasy Map Generator</b> (FMG) is a free open-source application.
|
||||
It means that you own all created maps and can use them as you wish.
|
||||
|
||||
<p>The development is supported by community, you can donate on ${Patreon}.
|
||||
<p>The development is community-backed, you can donate on ${Patreon}.
|
||||
You can also help creating overviews, tutorials and spreding the word about the Generator.</p>
|
||||
|
||||
<p>The best way to get help is to contact the community on ${Discord} and ${Reddit}.
|
||||
Before asking questions, please check out the ${QuickStart} and the ${QAA}.</p>
|
||||
Before asking questions, please check out the ${QuickStart}, the ${QAA}, and ${VideoTutorial}.</p>
|
||||
|
||||
<p>Track the development process on ${Trello}.</p>
|
||||
<p>Check out our another project: ${Armoria} — heraldry generator and editor.</p>
|
||||
|
||||
<p>Check out our new project: ${Armoria}, heraldry generator and editor.</p>
|
||||
|
||||
<b>Links:</b>
|
||||
<ul style="columns:2">
|
||||
<li>${link("https://github.com/Azgaar/Fantasy-Map-Generator", "GitHub repository")}</li>
|
||||
<li>${link("https://github.com/Azgaar/Fantasy-Map-Generator/blob/master/LICENSE", "License")}</li>
|
||||
<li>${link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog", "Changelog")}</li>
|
||||
<li>${link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Hotkeys", "Hotkeys")}</li>
|
||||
<li>${link("https://trello.com/b/7x832DG4/fantasy-map-generator", "Devboard")}</li>
|
||||
<li><a href="mailto:azgaar.fmg@yandex.by" target="_blank">Contact Azgaar</a></li>
|
||||
</ul>`;
|
||||
|
||||
$("#alert").dialog({
|
||||
|
|
|
|||
|
|
@ -470,23 +470,26 @@ function togglePrec(event) {
|
|||
|
||||
function drawPrec() {
|
||||
prec.selectAll("circle").remove();
|
||||
const cells = grid.cells,
|
||||
p = grid.points;
|
||||
const {cells, points} = grid;
|
||||
|
||||
prec.style("display", "block");
|
||||
const show = d3.transition().duration(800).ease(d3.easeSinIn);
|
||||
prec.selectAll("text").attr("opacity", 0).transition(show).attr("opacity", 1);
|
||||
|
||||
const cellsNumberModifier = (pointsInput.dataset.cells / 10000) ** 0.25;
|
||||
const data = cells.i.filter(i => cells.h[i] >= 20 && cells.prec[i]);
|
||||
const getRadius = prec => rn(Math.sqrt(prec / 4) / cellsNumberModifier, 2);
|
||||
|
||||
prec
|
||||
.selectAll("circle")
|
||||
.data(data)
|
||||
.enter()
|
||||
.append("circle")
|
||||
.attr("cx", d => p[d][0])
|
||||
.attr("cy", d => p[d][1])
|
||||
.attr("cx", d => points[d][0])
|
||||
.attr("cy", d => points[d][1])
|
||||
.attr("r", 0)
|
||||
.transition(show)
|
||||
.attr("r", d => rn(Math.max(Math.sqrt(cells.prec[d] * 0.5), 0.8), 2));
|
||||
.attr("r", d => getRadius(cells.prec[d]));
|
||||
}
|
||||
|
||||
function togglePopulation(event) {
|
||||
|
|
|
|||
|
|
@ -75,12 +75,9 @@ function overviewMilitary() {
|
|||
const sortData = options.military.map(u => `data-${u.name}="${getForces(u)}"`).join(" ");
|
||||
const lineData = options.military.map(u => `<div data-type="${u.name}" data-tip="State ${u.name} units number">${getForces(u)}</div>`).join(" ");
|
||||
|
||||
lines += `<div class="states" data-id=${s.i} data-state="${
|
||||
s.name
|
||||
}" ${sortData} data-total="${total}" data-population="${population}" data-rate="${rate}" data-alert="${s.alert}">
|
||||
<svg data-tip="${s.fullName}" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${
|
||||
s.color
|
||||
}" class="fillRect"></svg>
|
||||
lines += `<div class="states" data-id=${s.i} data-state="${s.name}" ${sortData} data-total="${total}"
|
||||
data-population="${population}" data-rate="${rate}" data-alert="${s.alert}">
|
||||
<fill-box data-tip="${s.fullName}" fill="${s.color}" disabled></fill-box>
|
||||
<input data-tip="${s.fullName}" style="width:6em" value="${s.name}" readonly>
|
||||
${lineData}
|
||||
<div data-type="total" data-tip="Total state military personnel (considering crew)" style="font-weight: bold">${si(total)}</div>
|
||||
|
|
|
|||
|
|
@ -17,18 +17,24 @@ function editNamesbase() {
|
|||
document.getElementById("namesbaseMax").addEventListener("input", updateBaseMax);
|
||||
document.getElementById("namesbaseDouble").addEventListener("input", updateBaseDublication);
|
||||
document.getElementById("namesbaseAdd").addEventListener("click", namesbaseAdd);
|
||||
document.getElementById("namesbaseAnalize").addEventListener("click", analizeNamesbase);
|
||||
document.getElementById("namesbaseAnalyze").addEventListener("click", analyzeNamesbase);
|
||||
document.getElementById("namesbaseDefault").addEventListener("click", namesbaseRestoreDefault);
|
||||
document.getElementById("namesbaseDownload").addEventListener("click", namesbaseDownload);
|
||||
document.getElementById("namesbaseUpload").addEventListener("click", () => namesbaseToLoad.click());
|
||||
document.getElementById("namesbaseToLoad").addEventListener("change", function() {uploadFile(this, namesbaseUpload)});
|
||||
document.getElementById("namesbaseUpload").addEventListener("click", () => document.getElementById("namesbaseToLoad").click());
|
||||
document.getElementById("namesbaseToLoad").addEventListener("change", function () {
|
||||
uploadFile(this, namesbaseUpload);
|
||||
});
|
||||
document.getElementById("namesbaseCA").addEventListener("click", () => {
|
||||
openURL("https://cartographyassets.com/asset-category/specific-assets/azgaars-generator/namebases/");
|
||||
});
|
||||
document.getElementById("namesbaseSpeak").addEventListener("click", () => speak(namesbaseExamples.textContent));
|
||||
|
||||
createBasesList();
|
||||
updateInputs();
|
||||
|
||||
$("#namesbaseEditor").dialog({
|
||||
title: "Namesbase Editor", width: "42.5em",
|
||||
title: "Namesbase Editor",
|
||||
width: "auto",
|
||||
position: {my: "center", at: "center", of: "svg"}
|
||||
});
|
||||
|
||||
|
|
@ -40,7 +46,10 @@ function editNamesbase() {
|
|||
|
||||
function updateInputs() {
|
||||
const base = +document.getElementById("namesbaseSelect").value;
|
||||
if (!nameBases[base]) {tip(`Namesbase ${base} is not defined`, false, "error"); return;}
|
||||
if (!nameBases[base]) {
|
||||
tip(`Namesbase ${base} is not defined`, false, "error");
|
||||
return;
|
||||
}
|
||||
document.getElementById("namesbaseTextarea").value = nameBases[base].b;
|
||||
document.getElementById("namesbaseName").value = nameBases[base].name;
|
||||
document.getElementById("namesbaseMin").value = nameBases[base].min;
|
||||
|
|
@ -52,7 +61,7 @@ function editNamesbase() {
|
|||
function updateExamples() {
|
||||
const base = +document.getElementById("namesbaseSelect").value;
|
||||
let examples = "";
|
||||
for (let i=0; i < 10; i++) {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const example = Names.getBase(base);
|
||||
if (example === undefined) {
|
||||
examples = "Cannot generate examples. Please verify the data";
|
||||
|
|
@ -84,13 +93,19 @@ function editNamesbase() {
|
|||
|
||||
function updateBaseMin() {
|
||||
const base = +document.getElementById("namesbaseSelect").value;
|
||||
if (+this.value > nameBases[base].max) {tip("Minimal length cannot be greater than maximal", false, "error"); return;}
|
||||
if (+this.value > nameBases[base].max) {
|
||||
tip("Minimal length cannot be greater than maximal", false, "error");
|
||||
return;
|
||||
}
|
||||
nameBases[base].min = +this.value;
|
||||
}
|
||||
|
||||
function updateBaseMax() {
|
||||
const base = +document.getElementById("namesbaseSelect").value;
|
||||
if (+this.value < nameBases[base].min) {tip("Maximal length should be greater than minimal", false, "error"); return;}
|
||||
if (+this.value < nameBases[base].min) {
|
||||
tip("Maximal length should be greater than minimal", false, "error");
|
||||
return;
|
||||
}
|
||||
nameBases[base].max = +this.value;
|
||||
}
|
||||
|
||||
|
|
@ -99,59 +114,70 @@ function editNamesbase() {
|
|||
nameBases[base].d = this.value;
|
||||
}
|
||||
|
||||
function analizeNamesbase() {
|
||||
const string = document.getElementById("namesbaseTextarea").value;
|
||||
if (!string) {tip("Names data field should not be empty", false, "error"); return;}
|
||||
const base = string.toLowerCase();
|
||||
const array = base.split(",");
|
||||
const l = array.length;
|
||||
if (!l) {tip("Names data should not be empty", false, "error"); return;}
|
||||
function analyzeNamesbase() {
|
||||
const namesSourceString = document.getElementById("namesbaseTextarea").value;
|
||||
const namesArray = namesSourceString.toLowerCase().split(",");
|
||||
const length = namesArray.length;
|
||||
if (!namesSourceString || !length) return tip("Names data should not be empty", false, "error");
|
||||
|
||||
const wordsLength = array.map(n => n.length);
|
||||
const multi = rn(d3.mean(array.map(n => (n.match(/ /i)||[]).length)) * 100, 2);
|
||||
const geminate = array.map(name => name.match(/[^\w\s]|(.)(?=\1)/g)||[]).flat();
|
||||
const doubled = ([...new Set(geminate)].filter(l => geminate.filter(d => d === l).length > 3)||["none"]).join("");
|
||||
const chain = Names.calculateChain(string);
|
||||
const depth = rn(d3.mean(Object.keys(chain).map(key => chain[key].filter(c => c !== " ").length)));
|
||||
const nonLatin = (string.match(/[^\u0000-\u007f]/g)||["none"]).join("");
|
||||
const chain = Names.calculateChain(namesSourceString);
|
||||
const variety = rn(d3.mean(Object.values(chain).map(keyValue => keyValue.length)));
|
||||
|
||||
const lengthStat =
|
||||
l < 30 ? "<span style='color:red'>[not enough]</span>" :
|
||||
l < 150 ? "<span style='color:darkred'>[low]</span>" :
|
||||
l < 150 ? "<span style='color:orange'>[low]</span>" :
|
||||
l < 400 ? "<span style='color:green'>[good]</span>" :
|
||||
l < 600 ? "<span style='color:orange'>[overmuch]</span>" :
|
||||
"<span style='color:darkred'>[overmuch]</span>";
|
||||
const wordsLength = namesArray.map(n => n.length);
|
||||
|
||||
const rangeStat =
|
||||
l < 10 ? "<span style='color:red'>[low]</span>" :
|
||||
l < 15 ? "<span style='color:darkred'>[low]</span>" :
|
||||
l < 20 ? "<span style='color:orange'>[low]</span>" :
|
||||
"<span style='color:green'>[good]</span>";
|
||||
const nonLatin = namesSourceString.match(/[^\u0000-\u007f]/g);
|
||||
const nonBasicLatinChars = nonLatin
|
||||
? unique(
|
||||
namesSourceString
|
||||
.match(/[^\u0000-\u007f]/g)
|
||||
.join("")
|
||||
.toLowerCase()
|
||||
).join("")
|
||||
: "none";
|
||||
|
||||
const depthStat =
|
||||
l < 15 ? "<span style='color:red'>[low]</span>" :
|
||||
l < 20 ? "<span style='color:darkred'>[low]</span>" :
|
||||
l < 25 ? "<span style='color:orange'>[low]</span>" :
|
||||
"<span style='color:green'>[good]</span>";
|
||||
const geminate = namesArray.map(name => name.match(/[^\w\s]|(.)(?=\1)/g) || []).flat();
|
||||
const doubled = unique(geminate).filter(char => geminate.filter(doudledChar => doudledChar === char).length > 3) || ["none"];
|
||||
|
||||
const duplicates = unique(namesArray.filter((e, i, a) => a.indexOf(e) !== i)).join(", ") || "none";
|
||||
const multiwordRate = d3.mean(namesArray.map(n => +n.includes(" ")));
|
||||
|
||||
const getLengthQuality = () => {
|
||||
if (length < 30) return "<span data-tip='Namesbase contains < 30 names - not enough to generate reasonable data' style='color:red'>[not enough]</span>";
|
||||
if (length < 100) return "<span data-tip='Namesbase contains < 100 names - not enough to generate good names' style='color:darkred'>[low]</span>";
|
||||
if (length <= 400) return "<span data-tip='Namesbase contains a reasonable number of samples' style='color:green'>[good]</span>";
|
||||
return "<span data-tip='Namesbase contains > 400 names. That is too much, try to reduce it to ~300 names' style='color:darkred'>[overmuch]</span>";
|
||||
};
|
||||
|
||||
const getVarietyLevel = () => {
|
||||
if (variety < 15) return "<span data-tip='Namesbase average variety < 15 - generated names will be too repetitive' style='color:red'>[low]</span>";
|
||||
if (variety < 30) return "<span data-tip='Namesbase average variety < 30 - names can be too repetitive' style='color:orange'>[mean]</span>";
|
||||
return "<span data-tip='Namesbase variety is good' style='color:green'>[good]</span>";
|
||||
};
|
||||
|
||||
alertMessage.innerHTML = `<div style="line-height: 1.6em; max-width: 20em">
|
||||
<div>Namesbase length: ${l} ${lengthStat}</div>
|
||||
<div>Namesbase range: ${Object.keys(chain).length-1} ${rangeStat}</div>
|
||||
<div>Namesbase depth: ${depth} ${depthStat}</div>
|
||||
<div>Non-basic chars: ${nonLatin}</div>
|
||||
<div data-tip="Number of names provided">Namesbase length: ${length} ${getLengthQuality()}</div>
|
||||
<div data-tip="Average number of generation variants for each key in the chain">Namesbase variety: ${variety} ${getVarietyLevel()}</div>
|
||||
<hr>
|
||||
<div>Min name length: ${d3.min(wordsLength)}</div>
|
||||
<div>Max name length: ${d3.max(wordsLength)}</div>
|
||||
<div>Mean name length: ${rn(d3.mean(wordsLength), 1)}</div>
|
||||
<div>Median name length: ${d3.median(wordsLength)}</div>
|
||||
<div>Doubled chars: ${doubled}</div>
|
||||
<div>Multi-word names: ${multi}%</div>
|
||||
<div data-tip="The shortest name length">Min name length: ${d3.min(wordsLength)}</div>
|
||||
<div data-tip="The longest name length">Max name length: ${d3.max(wordsLength)}</div>
|
||||
<div data-tip="Average name length">Mean name length: ${rn(d3.mean(wordsLength), 1)}</div>
|
||||
<div data-tip="Common name length">Median name length: ${d3.median(wordsLength)}</div>
|
||||
<hr>
|
||||
<div data-tip="Characters outside of Basic Latin have bad font support">Non-basic chars: ${nonBasicLatinChars}</div>
|
||||
<div data-tip="Characters that are frequently (more than 3 times) doubled">Doubled chars: ${doubled.join("")}</div>
|
||||
<div data-tip="Names used more than one time">Duplicates: ${duplicates}</div>
|
||||
<div data-tip="Percentage of names containing space character">Multi-word names: ${rn(multiwordRate * 100, 2)}%</div>
|
||||
</div>`;
|
||||
|
||||
$("#alert").dialog({
|
||||
resizable: false, title: "Data Analysis",
|
||||
resizable: false,
|
||||
title: "Data Analysis",
|
||||
position: {my: "left top-30", at: "right+10 top", of: "#namesbaseEditor"},
|
||||
buttons: {OK: function() {$(this).dialog("close");}}
|
||||
buttons: {
|
||||
OK: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -171,35 +197,42 @@ function editNamesbase() {
|
|||
|
||||
function namesbaseRestoreDefault() {
|
||||
alertMessage.innerHTML = `Are you sure you want to restore default namesbase?`;
|
||||
$("#alert").dialog({resizable: false, title: "Restore default data",
|
||||
$("#alert").dialog({
|
||||
resizable: false,
|
||||
title: "Restore default data",
|
||||
buttons: {
|
||||
Restore: function() {
|
||||
Restore: function () {
|
||||
$(this).dialog("close");
|
||||
Names.clearChains();
|
||||
nameBases = Names.getNameBases();
|
||||
createBasesList();
|
||||
updateInputs();
|
||||
},
|
||||
Cancel: function() {$(this).dialog("close");}
|
||||
Cancel: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function namesbaseDownload() {
|
||||
const data = nameBases.map((b,i) => `${b.name}|${b.min}|${b.max}|${b.d}|${b.m}|${b.b}`).join("\r\n");
|
||||
const data = nameBases.map((b, i) => `${b.name}|${b.min}|${b.max}|${b.d}|${b.m}|${b.b}`).join("\r\n");
|
||||
const name = getFileName("Namesbase") + ".txt";
|
||||
downloadFile(data, name);
|
||||
}
|
||||
|
||||
function namesbaseUpload(dataLoaded) {
|
||||
const data = dataLoaded.split("\r\n");
|
||||
if (!data || !data[0]) {tip("Cannot load a namesbase. Please check the data format", false, "error"); return;}
|
||||
if (!data || !data[0]) {
|
||||
tip("Cannot load a namesbase. Please check the data format", false, "error");
|
||||
return;
|
||||
}
|
||||
|
||||
Names.clearChains();
|
||||
nameBases = [];
|
||||
data.forEach(d => {
|
||||
const e = d.split("|");
|
||||
nameBases.push({name:e[0], min:e[1], max:e[2], d:e[3], m:e[4], b:e[5]});
|
||||
nameBases.push({name: e[0], min: e[1], max: e[2], d: e[3], m: e[4], b: e[5]});
|
||||
});
|
||||
|
||||
createBasesList();
|
||||
|
|
|
|||
|
|
@ -102,7 +102,9 @@ function showSupporters() {
|
|||
Dominick Ormsby,Linn Browning,Václav Švec,Alan Buehne,George J.Lekkas,Alexandre Boivin,Tommy Mayfield,Skylar Mangum-Turner,Karen Blythe,Stefan Gugerel,
|
||||
Mike Conley,Xavier privé,Hope You're Well,Mark Sprietsma,Robert Landry,Nick Mowry,steve hall,Markell,Josh Wren,Neutrix,BLRageQuit,Rocky,
|
||||
Dario Spadavecchia,Bas Kroot,John Patrick Callahan Jr,Alexandra Vesey,D,Exp1nt,james,Braxton Istace,w,Rurikid,AntiBlock,Redsauz,BigE0021,
|
||||
Jonathan Williams,ojacid .,Brian Wilson,A Patreon of the Ahts,Shubham Jakhotiya,www15o,Jan Bundesmann,Angelique Badger`;
|
||||
Jonathan Williams,ojacid .,Brian Wilson,A Patreon of the Ahts,Shubham Jakhotiya,www15o,Jan Bundesmann,Angelique Badger,Joshua Xiong,Moist mongol,
|
||||
Frank Fewkes,jason baldrick,Game Master Pro,Andrew Kircher,Preston Mitchell,Chris Kohut,Emarandzeb,Trentin Bergeron,Damon Gallaty,Pleaseworkforonce,
|
||||
Jordan,William Markus,Sidr Dim`;
|
||||
|
||||
const array = supporters
|
||||
.replace(/(?:\r\n|\r|\n)/g, "")
|
||||
|
|
@ -287,18 +289,16 @@ function generateMapWithSeed(source) {
|
|||
}
|
||||
|
||||
function showSeedHistoryDialog() {
|
||||
const alert = mapHistory
|
||||
.map(function (h, i) {
|
||||
const created = new Date(h.created).toLocaleTimeString();
|
||||
const button = `<i data-tip"Click to generate a map with this seed" onclick="restoreSeed(${i})" class="icon-history optionsSeedRestore"></i>`;
|
||||
return `<div>${i + 1}. Seed: ${h.seed} ${button}. Size: ${h.width}x${h.height}. Template: ${h.template}. Created: ${created}</div>`;
|
||||
})
|
||||
.join("");
|
||||
alertMessage.innerHTML = alert;
|
||||
const lines = mapHistory.map((h, i) => {
|
||||
const created = new Date(h.created).toLocaleTimeString();
|
||||
const button = `<i data-tip="Click to generate a map with this seed" onclick="restoreSeed(${i})" class="icon-history optionsSeedRestore"></i>`;
|
||||
return `<li>Seed: ${h.seed} ${button}. Size: ${h.width}x${h.height}. Template: ${h.template}. Created: ${created}</li>`;
|
||||
});
|
||||
alertMessage.innerHTML = `<ol style="margin: 0; padding-left: 1.5em">${lines.join("")}</ol>`;
|
||||
|
||||
$("#alert").dialog({
|
||||
resizable: false,
|
||||
title: "Seed history",
|
||||
width: fitContent(),
|
||||
position: {my: "center", at: "center", of: "svg"}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ function editProvinces() {
|
|||
cl = el.classList,
|
||||
line = el.parentNode,
|
||||
p = +line.dataset.id;
|
||||
if (cl.contains("fillRect")) changeFill(el);
|
||||
|
||||
if (el.tagName === "FILL-BOX") changeFill(el);
|
||||
else if (cl.contains("name")) editProvinceName(p);
|
||||
else if (cl.contains("coaIcon")) editEmblem("province", "provinceCOA" + p, pack.provinces[p]);
|
||||
else if (cl.contains("icon-star-empty")) capitalZoomIn(p);
|
||||
|
|
@ -133,11 +134,9 @@ function editProvinces() {
|
|||
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="fillRect pointer"></svg>
|
||||
<fill-box fill="${p.color}"></fill-box>
|
||||
<input data-tip="Province name. Click to change" class="name pointer" value="${p.name}" readonly>
|
||||
<svg data-tip="Click to show and edit province emblem" class="coaIcon hide" viewBox="0 0 200 200"><use href="#provinceCOA${p.i}"></use></svg>
|
||||
<svg data-tip="Click to show and edit province emblem" class="coaIcon pointer hide" viewBox="0 0 200 200"><use href="#provinceCOA${p.i}"></use></svg>
|
||||
<input data-tip="Province form name. Click to change" class="name pointer hide" value="${p.formName}" readonly>
|
||||
<span data-tip="Province capital. Click to zoom into view" class="icon-star-empty pointer hide ${p.burg ? "" : "placeholder"}"></span>
|
||||
<select data-tip="Province capital. Click to select from burgs within the state. No capital means the province is governed from the state capital" class="cultureBase hide ${
|
||||
|
|
@ -215,14 +214,14 @@ function editProvinces() {
|
|||
|
||||
function changeFill(el) {
|
||||
const currentFill = el.getAttribute("fill");
|
||||
const p = +el.parentNode.parentNode.dataset.id;
|
||||
const p = +el.parentNode.dataset.id;
|
||||
|
||||
const callback = function (fill) {
|
||||
el.setAttribute("fill", fill);
|
||||
pack.provinces[p].color = fill;
|
||||
const callback = newFill => {
|
||||
el.fill = newFill;
|
||||
pack.provinces[p].color = newFill;
|
||||
const g = provs.select("#provincesBody");
|
||||
g.select("#province" + p).attr("fill", fill);
|
||||
g.select("#province-gap" + p).attr("stroke", fill);
|
||||
g.select("#province" + p).attr("fill", newFill);
|
||||
g.select("#province-gap" + p).attr("stroke", newFill);
|
||||
};
|
||||
|
||||
openPicker(currentFill, callback);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@ function overviewRegiments(state) {
|
|||
updateHeaders();
|
||||
|
||||
$("#regimentsOverview").dialog({
|
||||
title: "Regiments Overview", resizable: false, width: fitContent(),
|
||||
title: "Regiments Overview",
|
||||
resizable: false,
|
||||
width: fitContent(),
|
||||
position: {my: "right top", at: "right-10 top+10", of: "svg", collision: "fit"}
|
||||
});
|
||||
|
||||
|
|
@ -31,11 +33,13 @@ function overviewRegiments(state) {
|
|||
header.querySelectorAll(".removable").forEach(el => el.remove());
|
||||
const insert = html => document.getElementById("regimentsTotal").insertAdjacentHTML("beforebegin", html);
|
||||
for (const u of options.military) {
|
||||
const label = capitalize(u.name.replace(/_/g, ' '));
|
||||
const label = capitalize(u.name.replace(/_/g, " "));
|
||||
insert(`<div data-tip="Regiment ${u.name} units number. Click to sort" class="sortable removable" data-sortby="${u.name}">${label} </div>`);
|
||||
}
|
||||
header.querySelectorAll(".removable").forEach(function(e) {
|
||||
e.addEventListener("click", function() {sortLines(this);});
|
||||
header.querySelectorAll(".removable").forEach(function (e) {
|
||||
e.addEventListener("click", function () {
|
||||
sortLines(this);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -51,11 +55,13 @@ function overviewRegiments(state) {
|
|||
if (state !== -1 && s.i !== state) continue; // specific state is selected
|
||||
|
||||
for (const r of s.military) {
|
||||
const sortData = options.military.map(u => `data-${u.name}=${r.u[u.name]||0}`).join(" ");
|
||||
const lineData = options.military.map(u => `<div data-type="${u.name}" data-tip="${capitalize(u.name)} units number">${r.u[u.name]||0}</div>`).join(" ");
|
||||
const sortData = options.military.map(u => `data-${u.name}=${r.u[u.name] || 0}`).join(" ");
|
||||
const lineData = options.military
|
||||
.map(u => `<div data-type="${u.name}" data-tip="${capitalize(u.name)} units number">${r.u[u.name] || 0}</div>`)
|
||||
.join(" ");
|
||||
|
||||
lines += `<div class="states" data-id=${r.i} data-s="${s.i}" data-state="${s.name}" data-name="${r.name}" ${sortData} data-total="${r.a}">
|
||||
<svg data-tip="${s.fullName}" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${s.color}" class="fillRect"></svg>
|
||||
<fill-box data-tip="${s.fullName}" fill="${s.color}" disabled></fill-box>
|
||||
<input data-tip="${s.fullName}" style="width:6em" value="${s.name}" readonly>
|
||||
<span data-tip="Regiment's emblem" style="width:1em">${r.icon}</span>
|
||||
<input data-tip="Regiment's name" style="width:13em" value="${r.name}" readonly>
|
||||
|
|
@ -70,12 +76,15 @@ function overviewRegiments(state) {
|
|||
|
||||
lines += `<div id="regimentsTotalLine" class="totalLine" data-tip="Total of all displayed regiments">
|
||||
<div style="width: 21em; margin-left: 1em">Regiments: ${regiments.length}</div>
|
||||
${options.military.map(u => `<div style="width:5em">${si(d3.sum(regiments.map(r => r.u[u.name]||0)))}</div>`).join(" ")}
|
||||
${options.military.map(u => `<div style="width:5em">${si(d3.sum(regiments.map(r => r.u[u.name] || 0)))}</div>`).join(" ")}
|
||||
<div style="width:5em">${si(d3.sum(regiments.map(r => r.a)))}</div>
|
||||
</div>`;
|
||||
|
||||
body.insertAdjacentHTML("beforeend", lines);
|
||||
if (body.dataset.type === "percentage") {body.dataset.type = "absolute"; togglePercentageMode();}
|
||||
if (body.dataset.type === "percentage") {
|
||||
body.dataset.type = "absolute";
|
||||
togglePercentageMode();
|
||||
}
|
||||
applySorting(regimentsHeader);
|
||||
|
||||
// add listeners
|
||||
|
|
@ -87,7 +96,7 @@ function overviewRegiments(state) {
|
|||
const filter = document.getElementById("regimentsFilter");
|
||||
filter.options.length = 0; // remove all options
|
||||
filter.options.add(new Option(`all`, -1, false, state === -1));
|
||||
const statesSorted = pack.states.filter(s => s.i && !s.removed).sort((a, b) => (a.name > b.name) ? 1 : -1);
|
||||
const statesSorted = pack.states.filter(s => s.i && !s.removed).sort((a, b) => (a.name > b.name ? 1 : -1));
|
||||
statesSorted.forEach(s => filter.options.add(new Option(s.name, s.i, false, s.i == state)));
|
||||
}
|
||||
|
||||
|
|
@ -108,19 +117,20 @@ function overviewRegiments(state) {
|
|||
if (body.dataset.type === "absolute") {
|
||||
body.dataset.type = "percentage";
|
||||
const lines = body.querySelectorAll(":scope > div:not(.totalLine)");
|
||||
const array = Array.from(lines), cache = [];
|
||||
const array = Array.from(lines),
|
||||
cache = [];
|
||||
|
||||
const total = function(type) {
|
||||
const total = function (type) {
|
||||
if (cache[type]) cache[type];
|
||||
cache[type] = d3.sum(array.map(el => +el.dataset[type]));
|
||||
return cache[type];
|
||||
}
|
||||
};
|
||||
|
||||
lines.forEach(function(el) {
|
||||
el.querySelectorAll("div").forEach(function(div) {
|
||||
lines.forEach(function (el) {
|
||||
el.querySelectorAll("div").forEach(function (div) {
|
||||
const type = div.dataset.type;
|
||||
if (type === "rate") return;
|
||||
div.textContent = total(type) ? rn(+el.dataset[type] / total(type) * 100) + "%" : "0%";
|
||||
div.textContent = total(type) ? rn((+el.dataset[type] / total(type)) * 100) + "%" : "0%";
|
||||
});
|
||||
});
|
||||
} else {
|
||||
|
|
@ -145,15 +155,19 @@ function overviewRegiments(state) {
|
|||
|
||||
function addRegimentOnClick() {
|
||||
const state = +regimentsFilter.value;
|
||||
if (state === -1) {tip("Please select state from the list", false, "error"); return;}
|
||||
if (state === -1) {
|
||||
tip("Please select state from the list", false, "error");
|
||||
return;
|
||||
}
|
||||
|
||||
const point = d3.mouse(this);
|
||||
const cell = findCell(point[0], point[1]);
|
||||
const x = pack.cells.p[cell][0], y = pack.cells.p[cell][1];
|
||||
const x = pack.cells.p[cell][0],
|
||||
y = pack.cells.p[cell][1];
|
||||
const military = pack.states[state].military;
|
||||
const i = military.length ? last(military).i + 1 : 0;
|
||||
const n = +(pack.cells.h[cell] < 20); // naval or land
|
||||
const reg = {a:0, cell, i, n, u:{}, x, y, bx:x, by:y, state, icon:"🛡️"};
|
||||
const reg = {a: 0, cell, i, n, u: {}, x, y, bx: x, by: y, state, icon: "🛡️"};
|
||||
reg.name = Military.getName(reg, military);
|
||||
military.push(reg);
|
||||
Military.generateNote(reg, pack.states[state]); // add legend
|
||||
|
|
@ -163,9 +177,9 @@ function overviewRegiments(state) {
|
|||
|
||||
function downloadRegimentsData() {
|
||||
const units = options.military.map(u => u.name);
|
||||
let data = "State,Id,Name,"+units.map(u => capitalize(u)).join(",")+",Total\n"; // headers
|
||||
let data = "State,Id,Name," + units.map(u => capitalize(u)).join(",") + ",Total\n"; // headers
|
||||
|
||||
body.querySelectorAll(":scope > div:not(.totalLine)").forEach(function(el) {
|
||||
body.querySelectorAll(":scope > div:not(.totalLine)").forEach(function (el) {
|
||||
data += el.dataset.state + ",";
|
||||
data += el.dataset.id + ",";
|
||||
data += el.dataset.name + ",";
|
||||
|
|
@ -176,5 +190,4 @@ function overviewRegiments(state) {
|
|||
const name = getFileName("Regiments") + ".csv";
|
||||
downloadFile(data, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -79,7 +79,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="fillRect pointer"></svg>
|
||||
<fill-box fill="${r.color}"></fill-box>
|
||||
<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">
|
||||
|
|
@ -93,7 +93,9 @@ function editReligions() {
|
|||
</div>`;
|
||||
} else {
|
||||
// No religion (neutral) line
|
||||
lines += `<div class="states" data-id=${r.i} data-name="${r.name}" data-color="" data-area=${area} data-population=${population} data-type="" data-form="" data-deity="" data-expansionism="">
|
||||
lines += `<div class="states" data-id=${r.i} data-name="${
|
||||
r.name
|
||||
}" data-color="" data-area=${area} data-population=${population} data-type="" data-form="" data-deity="" data-expansionism="">
|
||||
<svg width="9" height="9" class="placeholder"></svg>
|
||||
<input data-tip="Religion name. Click and type to change" class="religionName italic" value="${r.name}" autocorrect="off" spellcheck="false">
|
||||
<select data-tip="Religion type" class="religionType placeholder">${getTypeOptions(r.type)}</select>
|
||||
|
|
@ -124,7 +126,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.fillRect").forEach(el => el.addEventListener("click", religionChangeColor));
|
||||
body.querySelectorAll("fill-box").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));
|
||||
|
|
@ -215,13 +217,13 @@ function editReligions() {
|
|||
function religionChangeColor() {
|
||||
const el = this;
|
||||
const currentFill = el.getAttribute("fill");
|
||||
const religion = +el.parentNode.parentNode.dataset.id;
|
||||
const religion = +el.parentNode.dataset.id;
|
||||
|
||||
const callback = function (fill) {
|
||||
el.setAttribute("fill", fill);
|
||||
pack.religions[religion].color = fill;
|
||||
relig.select("#religion" + religion).attr("fill", fill);
|
||||
debug.select("#religionsCenter" + religion).attr("fill", fill);
|
||||
const callback = newFill => {
|
||||
el.fill = newFill;
|
||||
pack.religions[religion].color = newFill;
|
||||
relig.select("#religion" + religion).attr("fill", newFill);
|
||||
debug.select("#religionsCenter" + religion).attr("fill", newFill);
|
||||
};
|
||||
|
||||
openPicker(currentFill, callback);
|
||||
|
|
@ -459,7 +461,13 @@ function editReligions() {
|
|||
|
||||
// prepare svg
|
||||
alertMessage.innerHTML = "<div id='religionInfo' class='chartInfo'>‍</div>";
|
||||
const svg = d3.select("#alertMessage").insert("svg", "#religionInfo").attr("id", "hierarchy").attr("width", width).attr("height", height).style("text-anchor", "middle");
|
||||
const svg = d3
|
||||
.select("#alertMessage")
|
||||
.insert("svg", "#religionInfo")
|
||||
.attr("id", "hierarchy")
|
||||
.attr("width", width)
|
||||
.attr("height", height)
|
||||
.style("text-anchor", "middle");
|
||||
const graph = svg.append("g").attr("transform", `translate(10, -45)`);
|
||||
const links = graph.append("g").attr("fill", "none").attr("stroke", "#aaaaaa");
|
||||
const nodes = graph.append("g");
|
||||
|
|
@ -473,7 +481,24 @@ function editReligions() {
|
|||
.enter()
|
||||
.append("path")
|
||||
.attr("d", d => {
|
||||
return "M" + d.source.x + "," + d.source.y + "C" + d.source.x + "," + (d.source.y * 3 + d.target.y) / 4 + " " + d.target.x + "," + (d.source.y * 2 + d.target.y) / 3 + " " + d.target.x + "," + d.target.y;
|
||||
return (
|
||||
"M" +
|
||||
d.source.x +
|
||||
"," +
|
||||
d.source.y +
|
||||
"C" +
|
||||
d.source.x +
|
||||
"," +
|
||||
(d.source.y * 3 + d.target.y) / 4 +
|
||||
" " +
|
||||
d.target.x +
|
||||
"," +
|
||||
(d.source.y * 2 + d.target.y) / 3 +
|
||||
" " +
|
||||
d.target.x +
|
||||
"," +
|
||||
d.target.y
|
||||
);
|
||||
});
|
||||
|
||||
const node = nodes
|
||||
|
|
@ -578,7 +603,11 @@ function editReligions() {
|
|||
$("#religionsEditor").dialog({position: {my: "right top", at: "right-10 top+10", of: "svg"}});
|
||||
|
||||
tip("Click on religion to select, drag the circle to change religion", true);
|
||||
viewbox.style("cursor", "crosshair").on("click", selectReligionOnMapClick).call(d3.drag().on("start", dragReligionBrush)).on("touchmove mousemove", moveReligionBrush);
|
||||
viewbox
|
||||
.style("cursor", "crosshair")
|
||||
.on("click", selectReligionOnMapClick)
|
||||
.call(d3.drag().on("start", dragReligionBrush))
|
||||
.on("touchmove mousemove", moveReligionBrush);
|
||||
|
||||
body.querySelector("div").classList.add("selected");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,8 @@ function createRiver() {
|
|||
const source = riverCells[0];
|
||||
const mouth = parent === riverId ? last(riverCells) : riverCells[riverCells.length - 2];
|
||||
const sourceWidth = 0.05;
|
||||
const widthFactor = 1.2;
|
||||
const defaultWidthFactor = rn(1 / (pointsInput.dataset.cells / 10000) ** 0.25, 2);
|
||||
const widthFactor = 1.2 * defaultWidthFactor;
|
||||
|
||||
const meanderedPoints = addMeandering(riverCells);
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ function editStates() {
|
|||
cl = el.classList,
|
||||
line = el.parentNode,
|
||||
state = +line.dataset.id;
|
||||
if (cl.contains("fillRect")) stateChangeFill(el);
|
||||
if (el.tagName === "FILL-BOX") stateChangeFill(el);
|
||||
else if (cl.contains("name")) editStateName(state);
|
||||
else if (cl.contains("coaIcon")) editEmblem("state", "stateCOA" + state, pack.states[state]);
|
||||
else if (cl.contains("icon-star-empty")) stateCapitalZoomIn(state);
|
||||
|
|
@ -102,7 +102,7 @@ function editStates() {
|
|||
// Neutral line
|
||||
lines += `<div class="states" data-id=${s.i} data-name="${s.name}" data-cells=${s.cells} data-area=${area}
|
||||
data-population=${population} data-burgs=${s.burgs} data-color="" data-form="" data-capital="" data-culture="" data-type="" data-expansionism="">
|
||||
<svg width="9" height="9" class="placeholder"></svg>
|
||||
<svg width="1em" height="1em" class="placeholder"></svg>
|
||||
<input data-tip="Neutral lands name. Click to change" class="stateName name pointer italic" value="${s.name}" readonly>
|
||||
<svg class="coaIcon placeholder hide"></svg>
|
||||
<input class="stateForm placeholder" value="none">
|
||||
|
|
@ -126,17 +126,12 @@ function editStates() {
|
|||
|
||||
const capital = pack.burgs[s.capital].name;
|
||||
COArenderer.trigger("stateCOA" + s.i, s.coa);
|
||||
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="fillRect pointer"></svg>
|
||||
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}>
|
||||
<fill-box fill="${s.color}"></fill-box>
|
||||
<input data-tip="State name. Click to change" class="stateName name pointer" value="${s.name}" readonly>
|
||||
<svg data-tip="Click to show and edit state emblem" class="coaIcon hide" viewBox="0 0 200 200"><use href="#stateCOA${s.i}"></use></svg>
|
||||
<svg data-tip="Click to show and edit state emblem" class="coaIcon pointer hide" viewBox="0 0 200 200"><use href="#stateCOA${s.i}"></use></svg>
|
||||
<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"/>
|
||||
|
|
@ -149,9 +144,8 @@ function editStates() {
|
|||
<div data-tip="${populationTip}" class="culturePopulation hide">${si(population)}</div>
|
||||
<select data-tip="State type. Defines growth model. Click to change" class="cultureType ${hidden} show hide">${getTypeOptions(s.type)}</select>
|
||||
<span data-tip="State expansionism" class="icon-resize-full ${hidden} show hide"></span>
|
||||
<input data-tip="Expansionism (defines competitive size). Change to re-calculate states based on new value" class="statePower ${hidden} show hide" type="number" min=0 max=99 step=.1 value=${
|
||||
s.expansionism
|
||||
}>
|
||||
<input data-tip="Expansionism (defines competitive size). Change to re-calculate states based on new value"
|
||||
class="statePower ${hidden} show hide" type="number" min=0 max=99 step=.1 value=${s.expansionism}>
|
||||
<span data-tip="Cells count" class="icon-check-empty ${hidden} show hide"></span>
|
||||
<div data-tip="Cells count" class="stateCells ${hidden} show hide">${s.cells}</div>
|
||||
<span data-tip="Toggle state focus" class="icon-pin ${focused ? "" : " inactive"} hide"></span>
|
||||
|
|
@ -237,18 +231,18 @@ function editStates() {
|
|||
|
||||
function stateChangeFill(el) {
|
||||
const currentFill = el.getAttribute("fill");
|
||||
const state = +el.parentNode.parentNode.dataset.id;
|
||||
const state = +el.parentNode.dataset.id;
|
||||
|
||||
const callback = function (fill) {
|
||||
el.setAttribute("fill", fill);
|
||||
pack.states[state].color = fill;
|
||||
statesBody.select("#state" + state).attr("fill", fill);
|
||||
statesBody.select("#state-gap" + state).attr("stroke", fill);
|
||||
const halo = d3.color(fill) ? d3.color(fill).darker().hex() : "#666666";
|
||||
const callback = function (newFill) {
|
||||
el.fill = newFill;
|
||||
pack.states[state].color = newFill;
|
||||
statesBody.select("#state" + state).attr("fill", newFill);
|
||||
statesBody.select("#state-gap" + state).attr("stroke", newFill);
|
||||
const halo = d3.color(newFill) ? d3.color(newFill).darker().hex() : "#666666";
|
||||
statesHalo.select("#state-border" + state).attr("stroke", halo);
|
||||
|
||||
// recolor regiments
|
||||
const solidColor = fill[0] === "#" ? fill : "#999";
|
||||
const solidColor = newFill[0] === "#" ? newFill : "#999";
|
||||
const darkerColor = d3.color(solidColor).darker().hex();
|
||||
armies.select("#army" + state).attr("fill", solidColor);
|
||||
armies
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
311
modules/ui/stylePresets.js
Normal file
311
modules/ui/stylePresets.js
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
// UI module to control the style presets
|
||||
"use strict";
|
||||
|
||||
const systemPresets = ["default", "ancient", "gloom", "light", "watercolor", "clean", "atlas", "cyberpunk", "monochrome"];
|
||||
const customPresetPrefix = "fmgStyle_";
|
||||
|
||||
// add style presets to list
|
||||
{
|
||||
const systemOptions = systemPresets.map(styleName => `<option value="${styleName}">${styleName}</option>`);
|
||||
const storedStyles = Object.keys(localStorage).filter(key => key.startsWith(customPresetPrefix));
|
||||
const customOptions = storedStyles.map(styleName => `<option value="${styleName}">${styleName.replace(customPresetPrefix, "")} [custom]</option>`);
|
||||
const options = systemOptions.join("") + customOptions.join("");
|
||||
document.getElementById("stylePreset").innerHTML = options;
|
||||
}
|
||||
|
||||
async function applyStyleOnLoad() {
|
||||
const desiredPreset = localStorage.getItem("presetStyle") || "default";
|
||||
const styleData = await getStylePreset(desiredPreset);
|
||||
const [appliedPreset, style] = styleData;
|
||||
|
||||
applyStyle(style);
|
||||
updateMapFilter();
|
||||
stylePreset.value = stylePreset.dataset.old = appliedPreset;
|
||||
setPresetRemoveButtonVisibiliy();
|
||||
}
|
||||
|
||||
async function getStylePreset(desiredPreset) {
|
||||
let presetToLoad = desiredPreset;
|
||||
|
||||
const isCustom = !systemPresets.includes(desiredPreset);
|
||||
if (isCustom) {
|
||||
const storedStyleJSON = localStorage.getItem(desiredPreset);
|
||||
if (!storedStyleJSON) {
|
||||
ERROR && console.error(`Custom style ${desiredPreset} in not found in localStorage. Applying default style`);
|
||||
presetToLoad = "default";
|
||||
} else {
|
||||
const isValid = JSON.isValid(storedStyleJSON);
|
||||
if (isValid) return [desiredPreset, JSON.parse(storedStyleJSON)];
|
||||
|
||||
ERROR && console.error(`Custom style ${desiredPreset} stored in localStorage is not valid. Applying default style`);
|
||||
presetToLoad = "default";
|
||||
}
|
||||
}
|
||||
|
||||
const style = await fetchSystemPreset(presetToLoad);
|
||||
return [presetToLoad, style];
|
||||
}
|
||||
|
||||
async function fetchSystemPreset(preset) {
|
||||
const style = await fetch(`./styles/${preset}.json`)
|
||||
.then(res => res.json())
|
||||
.catch(err => {
|
||||
ERROR && console.error("Error on loading style preset", preset, err);
|
||||
return null;
|
||||
});
|
||||
|
||||
if (!style) throw new Error("Cannot fetch style preset", preset);
|
||||
return style;
|
||||
}
|
||||
|
||||
function applyStyle(style) {
|
||||
for (const selector in style) {
|
||||
const el = document.querySelector(selector);
|
||||
if (!el) continue;
|
||||
for (const attribute in style[selector]) {
|
||||
const value = style[selector][attribute];
|
||||
|
||||
if (value === "null" || value === null) {
|
||||
el.removeAttribute(attribute);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (attribute === "text-shadow") {
|
||||
el.style[attribute] = value;
|
||||
} else {
|
||||
el.setAttribute(attribute, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function requestStylePresetChange(preset) {
|
||||
const isConfirmed = sessionStorage.getItem("styleChangeConfirmed");
|
||||
if (isConfirmed) {
|
||||
changeStyle(preset);
|
||||
return;
|
||||
}
|
||||
|
||||
confirmationDialog({
|
||||
title: "Change style preset",
|
||||
message: "Are you sure you want to change the style preset? All unsaved style changes will be lost",
|
||||
confirm: "Change",
|
||||
onConfirm: () => {
|
||||
sessionStorage.setItem("styleChangeConfirmed", true);
|
||||
changeStyle(preset);
|
||||
},
|
||||
onCancel: () => {
|
||||
stylePreset.value = stylePreset.dataset.old;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function changeStyle(desiredPreset) {
|
||||
const styleData = await getStylePreset(desiredPreset);
|
||||
const [appliedPreset, style] = styleData;
|
||||
localStorage.setItem("presetStyle", appliedPreset);
|
||||
applyStyleWithUiRefresh(style);
|
||||
}
|
||||
|
||||
function applyStyleWithUiRefresh(style) {
|
||||
applyStyle(style);
|
||||
updateElements();
|
||||
selectStyleElement(); // re-select element to trigger values update
|
||||
updateMapFilter();
|
||||
stylePreset.dataset.old = stylePreset.value;
|
||||
|
||||
invokeActiveZooming();
|
||||
setPresetRemoveButtonVisibiliy();
|
||||
}
|
||||
|
||||
function addStylePreset() {
|
||||
$("#styleSaver").dialog({title: "Style Saver", width: "26em", position: {my: "center", at: "center", of: "svg"}});
|
||||
|
||||
const styleName = stylePreset.value.replace(customPresetPrefix, "");
|
||||
document.getElementById("styleSaverName").value = styleName;
|
||||
styleSaverJSON.value = JSON.stringify(collectStyleData(), null, 2);
|
||||
checkName();
|
||||
|
||||
if (modules.saveStyle) return;
|
||||
modules.saveStyle = true;
|
||||
|
||||
// add listeners
|
||||
document.getElementById("styleSaverName").addEventListener("input", checkName);
|
||||
document.getElementById("styleSaverSave").addEventListener("click", saveStyle);
|
||||
document.getElementById("styleSaverDownload").addEventListener("click", styleDownload);
|
||||
document.getElementById("styleSaverLoad").addEventListener("click", () => styleToLoad.click());
|
||||
document.getElementById("styleToLoad").addEventListener("change", loadStyleFile);
|
||||
|
||||
function collectStyleData() {
|
||||
const style = {};
|
||||
const attributes = {
|
||||
"#map": ["background-color", "filter", "data-filter"],
|
||||
"#armies": ["font-size", "box-size", "stroke", "stroke-width", "fill-opacity", "filter"],
|
||||
"#biomes": ["opacity", "filter", "mask"],
|
||||
"#stateBorders": ["opacity", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter"],
|
||||
"#provinceBorders": ["opacity", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter"],
|
||||
"#cells": ["opacity", "stroke", "stroke-width", "filter", "mask"],
|
||||
"#gridOverlay": ["opacity", "scale", "dx", "dy", "type", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "transform", "filter", "mask"],
|
||||
"#coordinates": ["opacity", "data-size", "font-size", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter", "mask"],
|
||||
"#compass": ["opacity", "transform", "filter", "mask", "shape-rendering"],
|
||||
"#rose": ["transform"],
|
||||
"#relig": ["opacity", "stroke", "stroke-width", "filter"],
|
||||
"#cults": ["opacity", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter"],
|
||||
"#landmass": ["opacity", "fill", "filter"],
|
||||
"#markers": ["opacity", "rescale", "filter"],
|
||||
"#prec": ["opacity", "stroke", "stroke-width", "fill", "filter"],
|
||||
"#population": ["opacity", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter"],
|
||||
"#rural": ["stroke"],
|
||||
"#urban": ["stroke"],
|
||||
"#freshwater": ["opacity", "fill", "stroke", "stroke-width", "filter"],
|
||||
"#salt": ["opacity", "fill", "stroke", "stroke-width", "filter"],
|
||||
"#sinkhole": ["opacity", "fill", "stroke", "stroke-width", "filter"],
|
||||
"#frozen": ["opacity", "fill", "stroke", "stroke-width", "filter"],
|
||||
"#lava": ["opacity", "fill", "stroke", "stroke-width", "filter"],
|
||||
"#dry": ["opacity", "fill", "stroke", "stroke-width", "filter"],
|
||||
"#sea_island": ["opacity", "stroke", "stroke-width", "filter", "auto-filter"],
|
||||
"#lake_island": ["opacity", "stroke", "stroke-width", "filter"],
|
||||
"#terrain": ["opacity", "set", "size", "density", "filter", "mask"],
|
||||
"#rivers": ["opacity", "filter", "fill"],
|
||||
"#ruler": ["opacity", "filter"],
|
||||
"#roads": ["opacity", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter", "mask"],
|
||||
"#trails": ["opacity", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter", "mask"],
|
||||
"#searoutes": ["opacity", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter", "mask"],
|
||||
"#statesBody": ["opacity", "filter"],
|
||||
"#statesHalo": ["opacity", "data-width", "stroke-width", "filter"],
|
||||
"#provs": ["opacity", "fill", "font-size", "font-family", "filter"],
|
||||
"#temperature": ["opacity", "font-size", "fill", "fill-opacity", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter"],
|
||||
"#ice": ["opacity", "fill", "stroke", "stroke-width", "filter"],
|
||||
"#emblems": ["opacity", "stroke-width", "filter"],
|
||||
"#texture": ["opacity", "filter", "mask"],
|
||||
"#textureImage": ["x", "y"],
|
||||
"#zones": ["opacity", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter", "mask"],
|
||||
"#oceanLayers": ["filter", "layers"],
|
||||
"#oceanBase": ["fill"],
|
||||
"#oceanicPattern": ["href", "opacity"],
|
||||
"#terrs": ["opacity", "scheme", "terracing", "skip", "relax", "curve", "filter", "mask"],
|
||||
"#legend": ["data-size", "font-size", "font-family", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "data-x", "data-y", "data-columns"],
|
||||
"#legendBox": ["fill", "fill-opacity"],
|
||||
"#burgLabels > #cities": ["opacity", "fill", "text-shadow", "data-size", "font-size", "font-family"],
|
||||
"#burgIcons > #cities": ["opacity", "fill", "fill-opacity", "size", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap"],
|
||||
"#anchors > #cities": ["opacity", "fill", "size", "stroke", "stroke-width"],
|
||||
"#burgLabels > #towns": ["opacity", "fill", "text-shadow", "data-size", "font-size", "font-family"],
|
||||
"#burgIcons > #towns": ["opacity", "fill", "fill-opacity", "size", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap"],
|
||||
"#anchors > #towns": ["opacity", "fill", "size", "stroke", "stroke-width"],
|
||||
"#labels > #states": ["opacity", "fill", "stroke", "stroke-width", "text-shadow", "data-size", "font-size", "font-family", "filter"],
|
||||
"#labels > #addedLabels": ["opacity", "fill", "stroke", "stroke-width", "text-shadow", "data-size", "font-size", "font-family", "filter"],
|
||||
"#fogging": ["opacity", "fill", "filter"]
|
||||
};
|
||||
|
||||
for (const selector in attributes) {
|
||||
const el = document.querySelector(selector);
|
||||
if (!el) continue;
|
||||
|
||||
style[selector] = {};
|
||||
for (const attr of attributes[selector]) {
|
||||
let value = el.style[attr] || el.getAttribute(attr);
|
||||
if (attr === "font-size" && el.hasAttribute("data-size")) value = el.getAttribute("data-size");
|
||||
style[selector][attr] = parseValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
function parseValue(value) {
|
||||
if (value === "null" || value === null) return null;
|
||||
if (value === "") return "";
|
||||
if (!isNaN(+value)) return +value;
|
||||
return value;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
function checkName() {
|
||||
const styleName = customPresetPrefix + styleSaverName.value;
|
||||
|
||||
const isSystem = systemPresets.includes(styleName) || systemPresets.includes(styleSaverName.value);
|
||||
if (isSystem) return (styleSaverTip.innerHTML = "default");
|
||||
|
||||
const isExisting = Array.from(stylePreset.options).some(option => option.value == styleName);
|
||||
if (isExisting) return (styleSaverTip.innerHTML = "existing");
|
||||
|
||||
styleSaverTip.innerHTML = "new";
|
||||
}
|
||||
|
||||
function saveStyle() {
|
||||
const styleJSON = styleSaverJSON.value;
|
||||
const desiredName = styleSaverName.value;
|
||||
|
||||
if (!styleJSON) return tip("Please provide a style JSON", false, "error");
|
||||
if (!JSON.isValid(styleJSON)) return tip("JSON string is not valid, please check the format", false, "error");
|
||||
if (!desiredName) return tip("Please provide a preset name", false, "error");
|
||||
if (styleSaverTip.innerHTML === "default") return tip("You cannot overwrite default preset, please change the name", false, "error");
|
||||
|
||||
const presetName = customPresetPrefix + desiredName;
|
||||
applyOption(stylePreset, presetName, desiredName + " [custom]");
|
||||
localStorage.setItem("presetStyle", presetName);
|
||||
localStorage.setItem(presetName, styleJSON);
|
||||
|
||||
applyStyleWithUiRefresh(JSON.parse(styleJSON));
|
||||
tip("Style preset is saved and applied", false, "success", 4000);
|
||||
$("#styleSaver").dialog("close");
|
||||
}
|
||||
|
||||
function styleDownload() {
|
||||
const styleJSON = styleSaverJSON.value;
|
||||
const styleName = styleSaverName.value;
|
||||
|
||||
if (!styleJSON) return tip("Please provide a style JSON", false, "error");
|
||||
if (!JSON.isValid(styleJSON)) return tip("JSON string is not valid, please check the format", false, "error");
|
||||
if (!styleName) return tip("Please provide a preset name", false, "error");
|
||||
|
||||
downloadFile(styleJSON, styleName + ".json", "application/json");
|
||||
}
|
||||
|
||||
function loadStyleFile() {
|
||||
const fileName = this.files[0]?.name.replace(/\.[^.]*$/, "");
|
||||
uploadFile(this, styleUpload);
|
||||
|
||||
function styleUpload(dataLoaded) {
|
||||
if (!dataLoaded) return tip("Cannot load the file. Please check the data format", false, "error");
|
||||
const isValid = JSON.isValid(dataLoaded);
|
||||
if (!isValid) return tip("Loaded data is not a valid JSON, please check the format", false, "error");
|
||||
|
||||
styleSaverJSON.value = JSON.stringify(JSON.parse(dataLoaded), null, 2);
|
||||
styleSaverName.value = fileName;
|
||||
checkName();
|
||||
tip("Style preset is uploaded", false, "success", 4000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function requestRemoveStylePreset() {
|
||||
const isDefault = systemPresets.includes(stylePreset.value);
|
||||
if (isDefault) return tip("Cannot remove system preset", false, "error");
|
||||
|
||||
confirmationDialog({
|
||||
title: "Remove style preset",
|
||||
message: "Are you sure you want to remove the style preset? This action cannot be undone.",
|
||||
confirm: "Remove",
|
||||
onConfirm: removeStylePreset
|
||||
});
|
||||
}
|
||||
|
||||
function removeStylePreset() {
|
||||
localStorage.removeItem("presetStyle");
|
||||
localStorage.removeItem(stylePreset.value);
|
||||
stylePreset.selectedOptions[0].remove();
|
||||
|
||||
changeStyle("default");
|
||||
}
|
||||
|
||||
function updateMapFilter() {
|
||||
const filter = svg.attr("data-filter");
|
||||
mapFilters.querySelectorAll(".pressed").forEach(button => button.classList.remove("pressed"));
|
||||
if (!filter) return;
|
||||
mapFilters.querySelector("#" + filter).classList.add("pressed");
|
||||
}
|
||||
|
||||
function setPresetRemoveButtonVisibiliy() {
|
||||
const isDefault = systemPresets.includes(stylePreset.value);
|
||||
removeStyleButton.style.display = isDefault ? "none" : "inline-block";
|
||||
}
|
||||
161
modules/ui/temperature-graph.js
Normal file
161
modules/ui/temperature-graph.js
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
"use strict";
|
||||
|
||||
function showBurgTemperatureGraph(id) {
|
||||
const b = pack.burgs[id];
|
||||
const lat = mapCoordinates.latN - (b.y / graphHeight) * mapCoordinates.latT;
|
||||
const burgTemp = grid.cells.temp[pack.cells.g[b.cell]];
|
||||
const prec = grid.cells.prec[pack.cells.g[b.cell]];
|
||||
|
||||
// prettier-ignore
|
||||
const weights = [
|
||||
[
|
||||
[10.782752257744338, 2.7100404240962126], [-2.8226802110591462, 51.62920138583541], [-6.6250956268643835, 4.427939197315455], [-59.64690518541339, 41.89084162654791], [-1.3302059550553835, -3.6964487738450913],
|
||||
[-2.5844898544535497, 0.09879268612455298], [-5.58528252533573, -0.23426224364501905], [26.94531337690372, 20.898158905988907], [3.816397481634785, -0.19045424064580757], [-4.835697931609101, -10.748232783636434]
|
||||
],
|
||||
[
|
||||
[-2.478952081870123, 0.6405800134306895, -7.136785640930911, -0.2186529024764509, 3.6568435212735424, 31.446026153530838, -19.91005187482281, 0.2543395274783306, -7.036924569659988, -0.7721371621651565],
|
||||
[-197.10583739743538, 6.889921141533474, 0.5058941504631129, 7.7667203434606416, -53.74180550086929, -15.717331715167001, -61.32068414155791, -2.259728220978728, 35.84049189540032, 94.6157364730977],
|
||||
[-5.312011591880851, -0.09923148954215096, -1.7132477487917586, -22.55559652066422, 0.4806107280554336, -26.5583974109492, 2.0558257347014863, 25.815645234787432, -18.569029876991156, -2.6792003366730035],
|
||||
[20.706518520569514, 18.344297403881875, 99.52244671131733, -58.53124969563653, -60.74384321042212, -80.57540534651835, 7.884792406540866, -144.33871131678563, 80.134199744324, 20.50745285622448],
|
||||
[-52.88299538575159, -15.782505343805528, 16.63316001054924, 88.09475330556671, -17.619552086641818, -19.943999528182427, -120.46286026828177, 19.354752020806302, 43.49422099308949, 28.733924806541363],
|
||||
[-2.4621368711159897, -1.2074759925679757, -1.5133898639835084, 2.173715352424188, -5.988707597991683, 3.0234147182203843, 3.3284199340000797, -1.8805161326360575, 5.151910934121654, -1.2540553911612116]
|
||||
],
|
||||
[
|
||||
[-0.3357437479474717, 0.01430651794222215, -0.7927524256670906, 0.2121636229648523, 1.0587803023358318, -3.759288325505095],
|
||||
[-1.1988028704442968, 1.3768997508052783, -3.8480086358278816, 0.5289387340947143, 0.5769459339961177, -1.2528318145750772],
|
||||
[1.0074966649240946, 1.155301164699459, -2.974254371052421, 0.47408176553219467, 0.5939042688615264, -0.7631976947131744]
|
||||
]
|
||||
];
|
||||
// From (-∞, ∞) to ~[-1, 1]
|
||||
const In1 = [(Math.abs(lat) - 26.950680212887473) / 48.378128506956, (prec - 12.229929140832644) / 29.94402033696607];
|
||||
|
||||
let lastIn = In1;
|
||||
let lstOut = [];
|
||||
|
||||
for (let levelN = 0; levelN < weights.length; levelN++) {
|
||||
const layerN = weights[levelN];
|
||||
for (let i = 0; i < layerN.length; i++) {
|
||||
lstOut[i] = 0;
|
||||
for (let j = 0; j < layerN[i].length; j++) {
|
||||
lstOut[i] = lstOut[i] + lastIn[j] * layerN[i][j];
|
||||
}
|
||||
// sigmoid
|
||||
lstOut[i] = 1 / (1 + Math.exp(-lstOut[i]));
|
||||
}
|
||||
lastIn = lstOut.slice(0);
|
||||
}
|
||||
|
||||
// Standard deviation for average temperature for the year from [0, 1] to [min, max]
|
||||
const yearSig = lstOut[0] * 62.9466411977018 + 0.28613807855649165;
|
||||
// Standard deviation for the difference between the minimum and maximum temperatures for the year
|
||||
const yearDelTmpSig = lstOut[1] * 13.541688670361175 + 0.1414213562373084 > yearSig ? yearSig : lstOut[1] * 13.541688670361175 + 0.1414213562373084;
|
||||
// Expected value for the difference between the minimum and maximum temperatures for the year
|
||||
const yearDelTmpMu = lstOut[2] * 15.266666666666667 + 0.6416666666666663;
|
||||
|
||||
// Temperature change shape
|
||||
const delT = yearDelTmpMu / 2 + (0.5 * yearDelTmpSig) / 2;
|
||||
const minT = burgTemp - Math.max(yearSig + delT, 15);
|
||||
const maxT = burgTemp + (burgTemp - minT);
|
||||
|
||||
const chartWidth = Math.max(window.innerWidth / 2, 580);
|
||||
const chartHeight = 300;
|
||||
|
||||
// drawing starting point from top-left (y = 0) of SVG
|
||||
const xOffset = 60;
|
||||
const yOffset = 10;
|
||||
|
||||
const year = new Date().getFullYear(); // use current year
|
||||
const startDate = new Date(year, 0, 1);
|
||||
const endDate = new Date(year, 11, 31);
|
||||
const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
const xscale = d3.scaleTime().domain([startDate, endDate]).range([0, chartWidth]);
|
||||
const yscale = d3.scaleLinear().domain([minT, maxT]).range([chartHeight, 0]);
|
||||
|
||||
const tempMean = [];
|
||||
const tempMin = [];
|
||||
const tempMax = [];
|
||||
|
||||
months.forEach((month, index) => {
|
||||
const rate = index / 11;
|
||||
let formTmp = Math.cos(rate * 2 * Math.PI) / 2;
|
||||
if (lat > 0) formTmp = -formTmp;
|
||||
|
||||
const x = rate * chartWidth + xOffset;
|
||||
const tempAverage = formTmp * yearSig + burgTemp;
|
||||
const tempDelta = yearDelTmpMu / 2 + (formTmp * yearDelTmpSig) / 2;
|
||||
|
||||
tempMean.push([x, yscale(tempAverage) + yOffset]);
|
||||
tempMin.push([x, yscale(tempAverage - tempDelta) + yOffset]);
|
||||
tempMax.push([x, yscale(tempAverage + tempDelta) + yOffset]);
|
||||
});
|
||||
|
||||
drawGraph();
|
||||
$("#alert").dialog({title: "Annual temperature in " + b.name, width: "auto", position: {my: "center", at: "center", of: "svg"}});
|
||||
|
||||
function drawGraph() {
|
||||
alertMessage.innerHTML = "";
|
||||
const getCurve = data => round(d3.line().curve(d3.curveBasis)(data), 2);
|
||||
|
||||
const legendSize = 60;
|
||||
const chart = d3
|
||||
.select("#alertMessage")
|
||||
.append("svg")
|
||||
.attr("width", chartWidth + 120)
|
||||
.attr("height", chartHeight + yOffset + legendSize);
|
||||
|
||||
const legend = chart.append("g");
|
||||
const legendY = chartHeight + yOffset + legendSize * 0.8;
|
||||
const legendX = n => (chartWidth * n) / 4;
|
||||
const legendTextX = n => legendX(n) + 10;
|
||||
legend.append("circle").attr("cx", legendX(1)).attr("cy", legendY).attr("r", 4).style("fill", "red");
|
||||
legend.append("text").attr("x", legendTextX(1)).attr("y", legendY).attr("alignment-baseline", "central").text("Day temperature");
|
||||
legend.append("circle").attr("cx", legendX(2)).attr("cy", legendY).attr("r", 4).style("fill", "orange");
|
||||
legend.append("text").attr("x", legendTextX(2)).attr("y", legendY).attr("alignment-baseline", "central").text("Mean temperature");
|
||||
legend.append("circle").attr("cx", legendX(3)).attr("cy", legendY).attr("r", 4).style("fill", "blue");
|
||||
legend.append("text").attr("x", legendTextX(3)).attr("y", legendY).attr("alignment-baseline", "central").text("Night temperature");
|
||||
|
||||
const xGrid = d3.axisBottom(xscale).ticks().tickSize(-chartHeight);
|
||||
const yGrid = d3.axisLeft(yscale).ticks(5).tickSize(-chartWidth);
|
||||
|
||||
const grid = chart.append("g").attr("class", "epgrid").attr("stroke-dasharray", "4 1");
|
||||
grid.append("g").attr("transform", `translate(${xOffset}, ${chartHeight + yOffset})`).call(xGrid); // prettier-ignore
|
||||
grid.append("g").attr("transform", `translate(${xOffset}, ${yOffset})`).call(yGrid);
|
||||
grid.selectAll("text").remove();
|
||||
|
||||
// add zero degree line
|
||||
if (minT < 0 && maxT > 0) {
|
||||
grid
|
||||
.append("line")
|
||||
.attr("x1", xOffset)
|
||||
.attr("y1", yscale(0) + yOffset)
|
||||
.attr("x2", chartWidth + xOffset)
|
||||
.attr("y2", yscale(0) + yOffset)
|
||||
.attr("stroke", "gray");
|
||||
}
|
||||
|
||||
const xAxis = d3.axisBottom(xscale).ticks().tickFormat(d3.timeFormat("%B"));
|
||||
const yAxis = d3.axisLeft(yscale).ticks(5).tickFormat(convertTemperature);
|
||||
|
||||
const axis = chart.append("g");
|
||||
axis
|
||||
.append("g")
|
||||
.attr("transform", `translate(${xOffset}, ${chartHeight + yOffset})`)
|
||||
.call(xAxis);
|
||||
axis.append("g").attr("transform", `translate(${xOffset}, ${yOffset})`).call(yAxis);
|
||||
axis.select("path.domain").attr("d", `M0.5,0.5 H${chartWidth + 0.5}`);
|
||||
|
||||
const curves = chart.append("g").attr("fill", "none").style("stroke-width", 2.5);
|
||||
curves.append("path").attr("d", getCurve(tempMean)).attr("data-type", "daily").attr("stroke", "orange").on("mousemove", printVal);
|
||||
curves.append("path").attr("d", getCurve(tempMin)).attr("data-type", "night").attr("stroke", "blue").on("mousemove", printVal);
|
||||
curves.append("path").attr("d", getCurve(tempMax)).attr("data-type", "day").attr("stroke", "red").on("mousemove", printVal);
|
||||
|
||||
function printVal() {
|
||||
const [x, y] = d3.mouse(this);
|
||||
const type = this.getAttribute("data-type");
|
||||
const temp = convertTemperature(yscale.invert(y - yOffset));
|
||||
const month = months[rn(((x - xOffset) / chartWidth) * 12)] || months[0];
|
||||
tip(`Average ${type} temperature in ${month}: ${temp}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -143,7 +143,7 @@ function regenerateStates() {
|
|||
const localSeed = Math.floor(Math.random() * 1e9); // new random seed
|
||||
Math.random = aleaPRNG(localSeed);
|
||||
|
||||
const statesCount = +regionsInput.value;
|
||||
const statesCount = +regionsOutput.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");
|
||||
|
|
@ -624,7 +624,9 @@ function addRiverOnClick() {
|
|||
|
||||
const source = riverCells[0];
|
||||
const mouth = riverCells[riverCells.length - 2];
|
||||
const widthFactor = river?.widthFactor || (!parent || parent === riverId ? 1.2 : 1);
|
||||
|
||||
const defaultWidthFactor = rn(1 / (pointsInput.dataset.cells / 10000) ** 0.25, 2);
|
||||
const widthFactor = river?.widthFactor || (!parent || parent === riverId ? defaultWidthFactor * 1.2 : defaultWidthFactor);
|
||||
const meanderedPoints = addMeandering(riverCells);
|
||||
|
||||
const discharge = cells.fl[mouth]; // m3 in second
|
||||
|
|
|
|||
|
|
@ -37,26 +37,12 @@ function editZones() {
|
|||
const el = ev.target,
|
||||
cl = el.classList,
|
||||
zone = el.parentNode.dataset.id;
|
||||
if (cl.contains("culturePopulation")) {
|
||||
changePopulation(zone);
|
||||
return;
|
||||
}
|
||||
if (cl.contains("icon-trash-empty")) {
|
||||
zoneRemove(zone);
|
||||
return;
|
||||
}
|
||||
if (cl.contains("icon-eye")) {
|
||||
toggleVisibility(el);
|
||||
return;
|
||||
}
|
||||
if (cl.contains("icon-pin")) {
|
||||
toggleFog(zone, cl);
|
||||
return;
|
||||
}
|
||||
if (cl.contains("fillRect")) {
|
||||
changeFill(el);
|
||||
return;
|
||||
}
|
||||
if (el.tagName === "FILL-BOX") changeFill(el);
|
||||
else if (cl.contains("culturePopulation")) changePopulation(zone);
|
||||
else if (cl.contains("icon-trash-empty")) zoneRemove(zone);
|
||||
else if (cl.contains("icon-eye")) toggleVisibility(el);
|
||||
else if (cl.contains("icon-pin")) toggleFog(zone, cl);
|
||||
|
||||
if (customization) selectZone(el);
|
||||
});
|
||||
|
||||
|
|
@ -131,8 +117,9 @@ function editZones() {
|
|||
const inactive = this.style.display === "none";
|
||||
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="fillRect pointer"></svg>
|
||||
lines += `<div class="states" data-id="${this.id}" data-fill="${fill}" data-description="${description}"
|
||||
data-cells=${c.length} data-area=${area} data-population=${population}>
|
||||
<fill-box fill="${fill}"></fill-box>
|
||||
<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>
|
||||
|
|
@ -337,9 +324,9 @@ function editZones() {
|
|||
|
||||
function changeFill(el) {
|
||||
const fill = el.getAttribute("fill");
|
||||
const callback = function (fill) {
|
||||
el.setAttribute("fill", fill);
|
||||
document.getElementById(el.parentNode.parentNode.dataset.id).setAttribute("fill", fill);
|
||||
const callback = newFill => {
|
||||
el.fill = newFill;
|
||||
document.getElementById(el.parentNode.dataset.id).setAttribute("fill", newFill);
|
||||
};
|
||||
|
||||
openPicker(fill, callback);
|
||||
|
|
@ -411,12 +398,12 @@ function editZones() {
|
|||
function addZonesLayer() {
|
||||
const id = getNextId("zone");
|
||||
const description = "Unknown zone";
|
||||
const fill = "url(#hatch" + (id.slice(4) % 14) + ")";
|
||||
zones.append("g").attr("id", id).attr("data-description", description).attr("data-cells", "").attr("fill", fill).attr("data-type", zoneTypes[0]);
|
||||
const fill = "url(#hatch" + (id.slice(4) % 42) + ")";
|
||||
zones.append("g").attr("id", id).attr("data-description", description).attr("data-cells", "").attr("fill", fill);
|
||||
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="fillRect pointer"></svg>
|
||||
<fill-box fill="${fill}"></fill-box>
|
||||
<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>
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
start chrome.exe http://localhost:8000/
|
||||
@echo off
|
||||
php -S localhost:8000
|
||||
389
styles/ancient.json
Normal file
389
styles/ancient.json
Normal file
|
|
@ -0,0 +1,389 @@
|
|||
{
|
||||
"#map": {
|
||||
"background-color": "#000000",
|
||||
"filter": null,
|
||||
"data-filter": null
|
||||
},
|
||||
"#armies": {
|
||||
"font-size": 8,
|
||||
"box-size": 4,
|
||||
"stroke": "#000",
|
||||
"stroke-width": 0.2,
|
||||
"fill-opacity": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#biomes": {
|
||||
"opacity": null,
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#stateBorders": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#56566d",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 2,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#provinceBorders": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#56566d",
|
||||
"stroke-width": 0.2,
|
||||
"stroke-dasharray": 1,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#cells": {
|
||||
"opacity": null,
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 0.1,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#gridOverlay": {
|
||||
"opacity": 0.8,
|
||||
"scale": 1,
|
||||
"dx": 0,
|
||||
"dy": 0,
|
||||
"type": "pointyHex",
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#coordinates": {
|
||||
"opacity": 1,
|
||||
"data-size": 12,
|
||||
"font-size": 12,
|
||||
"stroke": "#d4d4d4",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 5,
|
||||
"stroke-linecap": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#compass": {
|
||||
"opacity": 0.5,
|
||||
"transform": null,
|
||||
"filter": "url(#filter-sepia)",
|
||||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": "translate(80 80) scale(.25)"
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.7,
|
||||
"stroke": "#404040",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#cults": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#777777",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#landmass": {
|
||||
"opacity": 1,
|
||||
"fill": "#e3dfce",
|
||||
"filter": null
|
||||
},
|
||||
"#markers": {
|
||||
"opacity": null,
|
||||
"rescale": 1,
|
||||
"filter": ""
|
||||
},
|
||||
"#prec": {
|
||||
"opacity": null,
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0.1,
|
||||
"fill": "#003dff",
|
||||
"filter": null
|
||||
},
|
||||
"#population": {
|
||||
"opacity": null,
|
||||
"stroke-width": 1.6,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#rural": {
|
||||
"stroke": "#0000ff"
|
||||
},
|
||||
"#urban": {
|
||||
"stroke": "#ff0000"
|
||||
},
|
||||
"#freshwater": {
|
||||
"opacity": 0.6,
|
||||
"fill": "#c8d6e0",
|
||||
"stroke": "#968d6e",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#salt": {
|
||||
"opacity": 0.5,
|
||||
"fill": "#339482",
|
||||
"stroke": "#836a34",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sinkhole": {
|
||||
"opacity": 1,
|
||||
"fill": "#c3d6df",
|
||||
"stroke": "#b29062",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#frozen": {
|
||||
"opacity": 0.95,
|
||||
"fill": "#cdd4e7",
|
||||
"stroke": "#cfe0eb",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#lava": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#a04e18",
|
||||
"stroke": "#835520",
|
||||
"stroke-width": 2,
|
||||
"filter": "url(#paper)"
|
||||
},
|
||||
"#dry": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#c6b795",
|
||||
"stroke": "#8e816f",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sea_island": {
|
||||
"opacity": 0.5,
|
||||
"stroke": "#1f3846",
|
||||
"stroke-width": 0.7,
|
||||
"filter": "url(#dropShadow)",
|
||||
"auto-filter": 1
|
||||
},
|
||||
"#lake_island": {
|
||||
"opacity": 1,
|
||||
"stroke": "#7c8eaf",
|
||||
"stroke-width": 0.35,
|
||||
"filter": null
|
||||
},
|
||||
"#terrain": {
|
||||
"opacity": 1,
|
||||
"set": "simple",
|
||||
"size": 1,
|
||||
"density": 0.4,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#rivers": {
|
||||
"opacity": null,
|
||||
"filter": "",
|
||||
"fill": "#a69b7d"
|
||||
},
|
||||
"#ruler": {
|
||||
"opacity": null,
|
||||
"filter": null
|
||||
},
|
||||
"#roads": {
|
||||
"opacity": 0.7,
|
||||
"stroke": "#8d502a",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 3,
|
||||
"stroke-linecap": "inherit",
|
||||
"filter": "",
|
||||
"mask": null
|
||||
},
|
||||
"#trails": {
|
||||
"opacity": 0.7,
|
||||
"stroke": "#924217",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": "1 2",
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#searoutes": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#b16925",
|
||||
"stroke-width": 0.8,
|
||||
"stroke-dasharray": "1 2",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#statesBody": {
|
||||
"opacity": 0.2,
|
||||
"filter": "url(#filter-sepia)"
|
||||
},
|
||||
"#statesHalo": {
|
||||
"opacity": 0.4,
|
||||
"data-width": 10,
|
||||
"stroke-width": 10,
|
||||
"filter": "blur(6px)"
|
||||
},
|
||||
"#provs": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#000000",
|
||||
"font-size": 10,
|
||||
"font-family": "Georgia",
|
||||
"filter": null
|
||||
},
|
||||
"#temperature": {
|
||||
"opacity": null,
|
||||
"font-size": "8px",
|
||||
"fill": "#000000",
|
||||
"fill-opacity": 0.3,
|
||||
"stroke": null,
|
||||
"stroke-width": 1.8,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#ice": {
|
||||
"opacity": 0.35,
|
||||
"fill": "#e8f0f6",
|
||||
"stroke": "#e8f0f6",
|
||||
"stroke-width": 3,
|
||||
"filter": "url(#dropShadow05)"
|
||||
},
|
||||
"#emblems": {
|
||||
"opacity": 0.8,
|
||||
"stroke-width": 0.8,
|
||||
"filter": "url(#dropShadow05)"
|
||||
},
|
||||
"#texture": {
|
||||
"opacity": 0.6,
|
||||
"filter": "",
|
||||
"mask": ""
|
||||
},
|
||||
"#textureImage": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"#zones": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#333333",
|
||||
"stroke-width": 0,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#oceanLayers": {
|
||||
"filter": "",
|
||||
"layers": "-6,-4,-2"
|
||||
},
|
||||
"#oceanBase": {
|
||||
"fill": "#c99f64"
|
||||
},
|
||||
"#oceanicPattern": {
|
||||
"href": "./images/kiwiroo.png",
|
||||
"opacity": 0.4
|
||||
},
|
||||
"#terrs": {
|
||||
"opacity": null,
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 2,
|
||||
"relax": 1,
|
||||
"curve": 0,
|
||||
"filter": "url(#blur3)",
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
"data-size": 13,
|
||||
"font-size": 13,
|
||||
"font-family": "Almendra SC",
|
||||
"stroke": "#812929",
|
||||
"stroke-width": 2.5,
|
||||
"stroke-dasharray": "0 4 10 4",
|
||||
"stroke-linecap": "round",
|
||||
"data-x": 99,
|
||||
"data-y": 93,
|
||||
"data-columns": 8
|
||||
},
|
||||
"#burgLabels > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 12,
|
||||
"font-size": 12,
|
||||
"font-family": "Great Vibes"
|
||||
},
|
||||
"#burgIcons > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#fdfab9",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 1,
|
||||
"stroke": "#6f4e1f",
|
||||
"stroke-width": 0.3,
|
||||
"stroke-dasharray": ".3 .4",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 2,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1.2
|
||||
},
|
||||
"#burgLabels > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 5,
|
||||
"font-size": 5,
|
||||
"font-family": "Great Vibes"
|
||||
},
|
||||
"#burgIcons > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#fef4d8",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 0.5,
|
||||
"stroke": "#72472c",
|
||||
"stroke-width": 0.12,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 1,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1.2
|
||||
},
|
||||
"#labels > #states": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"stroke": "#3a3a3a",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 22,
|
||||
"font-size": 22,
|
||||
"font-family": "Great Vibes",
|
||||
"filter": "url(#filter-sepia)"
|
||||
},
|
||||
"#labels > #addedLabels": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"stroke": "#3a3a3a",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 18,
|
||||
"font-size": 18,
|
||||
"font-family": "Times New Roman",
|
||||
"filter": "url(#filter-sepia)"
|
||||
},
|
||||
"#fogging": {
|
||||
"opacity": 0.98,
|
||||
"fill": "#30426f",
|
||||
"filter": null
|
||||
}
|
||||
}
|
||||
385
styles/atlas.json
Normal file
385
styles/atlas.json
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
{
|
||||
"#map": {
|
||||
"background-color": "#000000",
|
||||
"filter": null,
|
||||
"data-filter": null
|
||||
},
|
||||
"#armies": {
|
||||
"font-size": 6,
|
||||
"box-size": 3,
|
||||
"stroke": "#000",
|
||||
"stroke-width": 0.3,
|
||||
"fill-opacity": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#biomes": {
|
||||
"opacity": null,
|
||||
"filter": null,
|
||||
"mask": "u rl(#land)"
|
||||
},
|
||||
"#stateBorders": {
|
||||
"opacity": 1,
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 1.01,
|
||||
"stroke-dasharray": 0,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#provinceBorders": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0.69,
|
||||
"stroke-dasharray": 0,
|
||||
"stroke-linecap": "round",
|
||||
"filter": null
|
||||
},
|
||||
"#cells": {
|
||||
"opacity": null,
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 0.1,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#gridOverlay": {
|
||||
"opacity": 1,
|
||||
"scale": 7.99,
|
||||
"dx": -2,
|
||||
"dy": 3,
|
||||
"type": "square",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0.05,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#coordinates": {
|
||||
"opacity": 1,
|
||||
"data-size": 12,
|
||||
"font-size": 12,
|
||||
"stroke": "#d4d4d4",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 5,
|
||||
"stroke-linecap": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#compass": {
|
||||
"opacity": 0.8,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": "u rl(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": "translate(80 80) scale(.25)"
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.7,
|
||||
"stroke": "#777777",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#cults": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#777777",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#landmass": {
|
||||
"opacity": 1,
|
||||
"fill": "#eef6fb",
|
||||
"filter": null
|
||||
},
|
||||
"#markers": {
|
||||
"opacity": null,
|
||||
"rescale": 1,
|
||||
"filter": "u rl(#dropShadow01)"
|
||||
},
|
||||
"#prec": {
|
||||
"opacity": null,
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0.1,
|
||||
"fill": "#003dff",
|
||||
"filter": null
|
||||
},
|
||||
"#population": {
|
||||
"opacity": null,
|
||||
"stroke-width": 1.6,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#rural": {
|
||||
"stroke": "#0000ff"
|
||||
},
|
||||
"#urban": {
|
||||
"stroke": "#ff0000"
|
||||
},
|
||||
"#freshwater": {
|
||||
"opacity": 1,
|
||||
"fill": "#cae3f7",
|
||||
"stroke": "#0089ca",
|
||||
"stroke-width": 1.01,
|
||||
"filter": null
|
||||
},
|
||||
"#salt": {
|
||||
"opacity": 1,
|
||||
"fill": "#cae3f7",
|
||||
"stroke": "#0089ca",
|
||||
"stroke-width": 1.01,
|
||||
"filter": null
|
||||
},
|
||||
"#sinkhole": {
|
||||
"opacity": 1,
|
||||
"fill": "#cae3f7",
|
||||
"stroke": "#0089ca",
|
||||
"stroke-width": 1.01,
|
||||
"filter": null
|
||||
},
|
||||
"#frozen": {
|
||||
"opacity": 0.95,
|
||||
"fill": "#cdd4e7",
|
||||
"stroke": "#cfe0eb",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#lava": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#90270d",
|
||||
"stroke": "#f93e0c",
|
||||
"stroke-width": 2,
|
||||
"filter": "u rl(#crumpled)"
|
||||
},
|
||||
"#dry": {
|
||||
"opacity": 1,
|
||||
"fill": "#c9bfa7",
|
||||
"stroke": "#8e816f",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sea_island": {
|
||||
"opacity": 1,
|
||||
"stroke": "#028ac9",
|
||||
"stroke-width": 1.01,
|
||||
"filter": "",
|
||||
"auto-filter": 0
|
||||
},
|
||||
"#lake_island": {
|
||||
"opacity": 1,
|
||||
"stroke": "#7c8eaf",
|
||||
"stroke-width": 0.35,
|
||||
"filter": null
|
||||
},
|
||||
"#terrain": {
|
||||
"opacity": null,
|
||||
"set": "simple",
|
||||
"size": 1,
|
||||
"density": 0.4,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#rivers": {
|
||||
"opacity": null,
|
||||
"filter": null,
|
||||
"fill": "#0089ca"
|
||||
},
|
||||
"#ruler": {
|
||||
"opacity": null,
|
||||
"filter": null
|
||||
},
|
||||
"#roads": {
|
||||
"opacity": 1,
|
||||
"stroke": "#ff2c2c",
|
||||
"stroke-width": 1.05,
|
||||
"stroke-dasharray": 0,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#trails": {
|
||||
"opacity": 1,
|
||||
"stroke": "#9f5122",
|
||||
"stroke-width": 0.43,
|
||||
"stroke-dasharray": 0,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#searoutes": {
|
||||
"opacity": 1,
|
||||
"stroke": "#0089ca",
|
||||
"stroke-width": 0.45,
|
||||
"stroke-dasharray": "1 2",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#statesBody": {
|
||||
"opacity": 0.49,
|
||||
"filter": null
|
||||
},
|
||||
"#statesHalo": {
|
||||
"opacity": 0.4,
|
||||
"data-width": 10,
|
||||
"stroke-width": 10,
|
||||
"filter": "blur(5px)"
|
||||
},
|
||||
"#provs": {
|
||||
"opacity": 1,
|
||||
"fill": "#000000",
|
||||
"font-size": 10,
|
||||
"font-family": "Times New Roman",
|
||||
"filter": null
|
||||
},
|
||||
"#temperature": {
|
||||
"opacity": null,
|
||||
"font-size": "14px",
|
||||
"fill": "#000000",
|
||||
"fill-opacity": 0.3,
|
||||
"stroke": null,
|
||||
"stroke-width": 1.8,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": ""
|
||||
},
|
||||
"#ice": {
|
||||
"opacity": 0.9,
|
||||
"fill": "#e8f0f6",
|
||||
"stroke": "#e8f0f6",
|
||||
"stroke-width": 1,
|
||||
"filter": "u rl(#dropShadow05)"
|
||||
},
|
||||
"#emblems": {
|
||||
"opacity": 0.9,
|
||||
"stroke-width": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#texture": {
|
||||
"opacity": null,
|
||||
"filter": null,
|
||||
"mask": "u rl(#land)"
|
||||
},
|
||||
"#zones": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#333333",
|
||||
"stroke-width": 0,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#oceanLayers": {
|
||||
"filter": "",
|
||||
"layers": "none"
|
||||
},
|
||||
"#oceanBase": {
|
||||
"fill": "#b4d2f3"
|
||||
},
|
||||
"#oceanicPattern": {
|
||||
"href": "",
|
||||
"opacity": 1
|
||||
},
|
||||
"#terrs": {
|
||||
"opacity": null,
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 0,
|
||||
"relax": 0,
|
||||
"curve": 0,
|
||||
"filter": null,
|
||||
"mask": "u rl(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
"data-size": 13,
|
||||
"font-size": 13,
|
||||
"font-family": "Almendra SC",
|
||||
"stroke": "#812929",
|
||||
"stroke-width": 2.5,
|
||||
"stroke-dasharray": "0 4 10 4",
|
||||
"stroke-linecap": "round",
|
||||
"data-x": 99,
|
||||
"data-y": 93,
|
||||
"data-columns": 8
|
||||
},
|
||||
"#burgLabels > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#000000",
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 4,
|
||||
"font-size": 4,
|
||||
"font-family": "Questrial"
|
||||
},
|
||||
"#burgIcons > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#000000",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 1,
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0.24,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "round"
|
||||
},
|
||||
"#anchors > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 2,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1.2
|
||||
},
|
||||
"#burgLabels > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#000000",
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 3,
|
||||
"font-size": 3,
|
||||
"font-family": "Questrial"
|
||||
},
|
||||
"#burgIcons > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#000000",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 0.5,
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0.12,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "round"
|
||||
},
|
||||
"#anchors > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 1,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1.2
|
||||
},
|
||||
"#labels > #states": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#000000",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 16,
|
||||
"font-size": 16,
|
||||
"font-family": "Times New Roman",
|
||||
"filter": null
|
||||
},
|
||||
"#labels > #addedLabels": {
|
||||
"opacity": 1,
|
||||
"fill": "#000000",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 18,
|
||||
"font-size": 18,
|
||||
"font-family": "Questrial",
|
||||
"filter": null
|
||||
},
|
||||
"#fogging": {
|
||||
"opacity": 0.98,
|
||||
"fill": "#30426f",
|
||||
"filter": null
|
||||
}
|
||||
}
|
||||
388
styles/clean.json
Normal file
388
styles/clean.json
Normal file
|
|
@ -0,0 +1,388 @@
|
|||
{
|
||||
"#map": {
|
||||
"background-color": "#000000",
|
||||
"filter": null,
|
||||
"data-filter": null
|
||||
},
|
||||
"#armies": {
|
||||
"font-size": 6,
|
||||
"box-size": 3,
|
||||
"stroke": "#000",
|
||||
"stroke-width": 0,
|
||||
"opacity": 1,
|
||||
"fill-opacity": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#biomes": {
|
||||
"opacity": 0.5,
|
||||
"filter": "url(#blur7)",
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#stateBorders": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#414141",
|
||||
"stroke-width": 0.7,
|
||||
"stroke-dasharray": 0,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#provinceBorders": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#414141",
|
||||
"stroke-width": 0.45,
|
||||
"stroke-dasharray": 1,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#cells": {
|
||||
"opacity": null,
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 0.09,
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#gridOverlay": {
|
||||
"opacity": 0.8,
|
||||
"scale": 1,
|
||||
"dx": 0,
|
||||
"dy": "0",
|
||||
"type": "pointyHex",
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#coordinates": {
|
||||
"opacity": 1,
|
||||
"data-size": 12,
|
||||
"font-size": 12,
|
||||
"stroke": "#414141",
|
||||
"stroke-width": 0.45,
|
||||
"stroke-dasharray": 3,
|
||||
"stroke-linecap": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#compass": {
|
||||
"opacity": 0.8,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": null
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.7,
|
||||
"stroke": "#404040",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#cults": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#777777",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#landmass": {
|
||||
"opacity": 1,
|
||||
"fill": "#eeedeb",
|
||||
"filter": null
|
||||
},
|
||||
"#markers": {
|
||||
"opacity": null,
|
||||
"rescale": null,
|
||||
"filter": "url(#dropShadow01)"
|
||||
},
|
||||
"#prec": {
|
||||
"opacity": null,
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0,
|
||||
"fill": "#0080ff",
|
||||
"filter": null
|
||||
},
|
||||
"#population": {
|
||||
"opacity": null,
|
||||
"stroke-width": 2.58,
|
||||
"stroke-dasharray": 0,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": "url(#blur3)"
|
||||
},
|
||||
"#rural": {
|
||||
"stroke": "#ff0000"
|
||||
},
|
||||
"#urban": {
|
||||
"stroke": "#800000"
|
||||
},
|
||||
"#freshwater": {
|
||||
"opacity": 0.5,
|
||||
"fill": "#aadaff",
|
||||
"stroke": "#5f799d",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#salt": {
|
||||
"opacity": 0.5,
|
||||
"fill": "#409b8a",
|
||||
"stroke": "#388985",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sinkhole": {
|
||||
"opacity": 1,
|
||||
"fill": "#5bc9fd",
|
||||
"stroke": "#53a3b0",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#frozen": {
|
||||
"opacity": 0.95,
|
||||
"fill": "#cdd4e7",
|
||||
"stroke": "#cfe0eb",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#lava": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#90270d",
|
||||
"stroke": "#f93e0c",
|
||||
"stroke-width": 2,
|
||||
"filter": "url(#crumpled)"
|
||||
},
|
||||
"#dry": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#c9bfa7",
|
||||
"stroke": "#8e816f",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sea_island": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#595959",
|
||||
"stroke-width": 0.4,
|
||||
"filter": null,
|
||||
"auto-filter": 0
|
||||
},
|
||||
"#lake_island": {
|
||||
"opacity": 0,
|
||||
"stroke": "#7c8eaf",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#terrain": {
|
||||
"opacity": 1,
|
||||
"set": "simple",
|
||||
"size": 1,
|
||||
"density": 0.4,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#rivers": {
|
||||
"opacity": null,
|
||||
"filter": null,
|
||||
"fill": "#aadaff"
|
||||
},
|
||||
"#ruler": {
|
||||
"opacity": null,
|
||||
"filter": null
|
||||
},
|
||||
"#roads": {
|
||||
"opacity": 0.9,
|
||||
"stroke": "#f6d068",
|
||||
"stroke-width": 0.7,
|
||||
"stroke-dasharray": 0,
|
||||
"stroke-linecap": "inherit",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#trails": {
|
||||
"opacity": 1,
|
||||
"stroke": "#ffffff",
|
||||
"stroke-width": 0.25,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#searoutes": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#4f82c6",
|
||||
"stroke-width": 0.45,
|
||||
"stroke-dasharray": 2,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": "url(#water)"
|
||||
},
|
||||
"#statesBody": {
|
||||
"opacity": 0.3,
|
||||
"filter": null
|
||||
},
|
||||
"#statesHalo": {
|
||||
"opacity": 0.5,
|
||||
"data-width": 1,
|
||||
"stroke-width": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#provs": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#000000",
|
||||
"data-size": 10,
|
||||
"font-size": 10,
|
||||
"font-family": "Georgia",
|
||||
"filter": null
|
||||
},
|
||||
"#temperature": {
|
||||
"opacity": null,
|
||||
"font-size": "8px",
|
||||
"fill": "#000000",
|
||||
"fill-opacity": 0.3,
|
||||
"stroke": null,
|
||||
"stroke-width": 1.8,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#ice": {
|
||||
"opacity": 0.9,
|
||||
"fill": "#e8f0f6",
|
||||
"stroke": "#e8f0f6",
|
||||
"stroke-width": 1,
|
||||
"filter": "url(#dropShadow01)"
|
||||
},
|
||||
"#emblems": {
|
||||
"opacity": 1,
|
||||
"stroke-width": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#texture": {
|
||||
"opacity": null,
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#textureImage": {},
|
||||
"#zones": {
|
||||
"opacity": 0.7,
|
||||
"stroke": "#ff6262",
|
||||
"stroke-width": 0,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#oceanLayers": {
|
||||
"filter": null,
|
||||
"layers": "none"
|
||||
},
|
||||
"#oceanBase": {
|
||||
"fill": "#aadaff"
|
||||
},
|
||||
"#oceanicPattern": {
|
||||
"href": "",
|
||||
"opacity": 0.2
|
||||
},
|
||||
"#terrs": {
|
||||
"opacity": 0.5,
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 5,
|
||||
"relax": 0,
|
||||
"curve": 0,
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
"data-size": 12.74,
|
||||
"font-size": 12.74,
|
||||
"font-family": "Arial",
|
||||
"stroke": "#909090",
|
||||
"stroke-width": 1.13,
|
||||
"stroke-dasharray": 0,
|
||||
"stroke-linecap": "round",
|
||||
"data-x": 98.39,
|
||||
"data-y": 12.67,
|
||||
"data-columns": null
|
||||
},
|
||||
"#legendBox": {},
|
||||
"#burgLabels > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#414141",
|
||||
"text-shadow": "white 0 0 4px",
|
||||
"data-size": 7,
|
||||
"font-size": 7,
|
||||
"font-family": "Arial"
|
||||
},
|
||||
"#burgIcons > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 1,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 0.24,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 2,
|
||||
"stroke": "#303030",
|
||||
"stroke-width": 1.7
|
||||
},
|
||||
"#burgLabels > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#414141",
|
||||
"data-size": 3,
|
||||
"font-size": 3,
|
||||
"font-family": "Arial"
|
||||
},
|
||||
"#burgIcons > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 0.5,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 0.12,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 1,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1.06
|
||||
},
|
||||
"#labels > #states": {
|
||||
"opacity": 1,
|
||||
"fill": "#292929",
|
||||
"stroke": "#303030",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0 0 2px",
|
||||
"data-size": 10,
|
||||
"font-size": 10,
|
||||
"font-family": "Arial",
|
||||
"filter": null
|
||||
},
|
||||
"#labels > #addedLabels": {
|
||||
"opacity": 1,
|
||||
"fill": "#414141",
|
||||
"stroke": "#3a3a3a",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0 0 4px",
|
||||
"data-size": 18,
|
||||
"font-size": 18,
|
||||
"font-family": "Arial",
|
||||
"filter": null
|
||||
},
|
||||
"#fogging": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"filter": null
|
||||
}
|
||||
}
|
||||
385
styles/cyberpunk.json
Normal file
385
styles/cyberpunk.json
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
{
|
||||
"#map": {
|
||||
"background-color": "#000000",
|
||||
"filter": null,
|
||||
"data-filter": null
|
||||
},
|
||||
"#armies": {
|
||||
"font-size": 8,
|
||||
"box-size": 4,
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0.6,
|
||||
"fill-opacity": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#biomes": {
|
||||
"opacity": 0.7,
|
||||
"filter": "",
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#stateBorders": {
|
||||
"opacity": 1,
|
||||
"stroke": "#ffffff",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 3,
|
||||
"stroke-linecap": "round",
|
||||
"filter": ""
|
||||
},
|
||||
"#provinceBorders": {
|
||||
"opacity": 0.5,
|
||||
"stroke": "#ffffff",
|
||||
"stroke-width": 0.3,
|
||||
"stroke-dasharray": 1,
|
||||
"stroke-linecap": "round",
|
||||
"filter": ""
|
||||
},
|
||||
"#cells": {
|
||||
"opacity": null,
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 0.1,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#gridOverlay": {
|
||||
"opacity": 0.8,
|
||||
"scale": 1,
|
||||
"dx": 0,
|
||||
"dy": 0,
|
||||
"type": "pointyHex",
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#coordinates": {
|
||||
"opacity": 1,
|
||||
"data-size": 14,
|
||||
"font-size": 14,
|
||||
"stroke": "#4a4a4a",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 6,
|
||||
"stroke-linecap": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#compass": {
|
||||
"opacity": 0.9,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": "",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": null
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.5,
|
||||
"stroke": "#404040",
|
||||
"stroke-width": 2,
|
||||
"filter": "url(#splotch)"
|
||||
},
|
||||
"#cults": {
|
||||
"opacity": 0.35,
|
||||
"stroke": "#777777",
|
||||
"stroke-width": 2,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": "url(#splotch)"
|
||||
},
|
||||
"#landmass": {
|
||||
"opacity": 1,
|
||||
"fill": "#04011e",
|
||||
"filter": null
|
||||
},
|
||||
"#markers": {
|
||||
"opacity": 0.8,
|
||||
"rescale": 1,
|
||||
"filter": "url(#dropShadow05)"
|
||||
},
|
||||
"#prec": {
|
||||
"opacity": null,
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0.1,
|
||||
"fill": "#003dff",
|
||||
"filter": null
|
||||
},
|
||||
"#population": {
|
||||
"opacity": null,
|
||||
"stroke-width": 1.6,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "square",
|
||||
"filter": null
|
||||
},
|
||||
"#rural": {
|
||||
"stroke": "#5294ff"
|
||||
},
|
||||
"#urban": {
|
||||
"stroke": "#5cdeff"
|
||||
},
|
||||
"#freshwater": {
|
||||
"opacity": 0.9,
|
||||
"fill": "#381579",
|
||||
"stroke": "#47228c",
|
||||
"stroke-width": 3,
|
||||
"filter": null
|
||||
},
|
||||
"#salt": {
|
||||
"opacity": 0.5,
|
||||
"fill": "#409b8a",
|
||||
"stroke": "#388985",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sinkhole": {
|
||||
"opacity": 1,
|
||||
"fill": "#5bc9fd",
|
||||
"stroke": "#53a3b0",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#frozen": {
|
||||
"opacity": 0.95,
|
||||
"fill": "#cdd4e7",
|
||||
"stroke": "#cfe0eb",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#lava": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#90270d",
|
||||
"stroke": "#f93e0c",
|
||||
"stroke-width": 2,
|
||||
"filter": "url(#crumpled)"
|
||||
},
|
||||
"#dry": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#c9bfa7",
|
||||
"stroke": "#8e816f",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sea_island": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#1f3846",
|
||||
"stroke-width": 0.7,
|
||||
"filter": "url(#dropShadow)",
|
||||
"auto-filter": 1
|
||||
},
|
||||
"#lake_island": {
|
||||
"opacity": 1,
|
||||
"stroke": "#7c8eaf",
|
||||
"stroke-width": 0.35,
|
||||
"filter": null
|
||||
},
|
||||
"#terrain": {
|
||||
"opacity": 0.9,
|
||||
"set": "simple",
|
||||
"size": 1,
|
||||
"density": 0.4,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#rivers": {
|
||||
"opacity": null,
|
||||
"filter": null,
|
||||
"fill": "#6738bc"
|
||||
},
|
||||
"#ruler": {
|
||||
"opacity": null,
|
||||
"filter": null
|
||||
},
|
||||
"#roads": {
|
||||
"opacity": 1,
|
||||
"stroke": "#c44ac0",
|
||||
"stroke-width": 0.9,
|
||||
"stroke-dasharray": "2 3",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#trails": {
|
||||
"opacity": 1,
|
||||
"stroke": "#df2654",
|
||||
"stroke-width": 0.2,
|
||||
"stroke-dasharray": ".5 1",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#searoutes": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#a890c6",
|
||||
"stroke-width": 0.6,
|
||||
"stroke-dasharray": "1.2 2.4",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#statesBody": {
|
||||
"opacity": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#statesHalo": {
|
||||
"opacity": 1,
|
||||
"data-width": 13,
|
||||
"stroke-width": 13,
|
||||
"filter": "blur(8.25px)"
|
||||
},
|
||||
"#provs": {
|
||||
"opacity": 0.2,
|
||||
"fill": "#933e3e",
|
||||
"font-size": 8,
|
||||
"font-family": "Orbitron",
|
||||
"filter": ""
|
||||
},
|
||||
"#temperature": {
|
||||
"opacity": 0.8,
|
||||
"font-size": "22px",
|
||||
"fill": "#551282",
|
||||
"fill-opacity": 0.3,
|
||||
"stroke": null,
|
||||
"stroke-width": 3,
|
||||
"stroke-dasharray": 2,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#ice": {
|
||||
"opacity": 0.3,
|
||||
"fill": "#919191",
|
||||
"stroke": "#949494",
|
||||
"stroke-width": 0,
|
||||
"filter": "url(#dropShadow05)"
|
||||
},
|
||||
"#emblems": {
|
||||
"opacity": 0.75,
|
||||
"stroke-width": 0.5,
|
||||
"filter": ""
|
||||
},
|
||||
"#texture": {
|
||||
"opacity": 0.14,
|
||||
"filter": null,
|
||||
"mask": "url(#water)"
|
||||
},
|
||||
"#zones": {
|
||||
"opacity": 0.7,
|
||||
"stroke": "#ffffff",
|
||||
"stroke-width": 0.3,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "inherit",
|
||||
"filter": "url(#dropShadow05)",
|
||||
"mask": null
|
||||
},
|
||||
"#oceanLayers": {
|
||||
"filter": "",
|
||||
"layers": "-6,-3,-1"
|
||||
},
|
||||
"#oceanBase": {
|
||||
"fill": "#05001f"
|
||||
},
|
||||
"#oceanicPattern": {
|
||||
"href": "",
|
||||
"opacity": 0.15
|
||||
},
|
||||
"#terrs": {
|
||||
"opacity": 1,
|
||||
"scheme": "monochrome",
|
||||
"terracing": 6,
|
||||
"skip": 0,
|
||||
"relax": 2,
|
||||
"curve": 0,
|
||||
"filter": "",
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
"data-size": 13,
|
||||
"font-size": 13,
|
||||
"font-family": "Almendra SC",
|
||||
"stroke": "#812929",
|
||||
"stroke-width": 2.5,
|
||||
"stroke-dasharray": "0 4 10 4",
|
||||
"stroke-linecap": "round",
|
||||
"data-x": 99,
|
||||
"data-y": 93,
|
||||
"data-columns": 8
|
||||
},
|
||||
"#burgLabels > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 8,
|
||||
"font-size": 8,
|
||||
"font-family": "Orbitron"
|
||||
},
|
||||
"#burgIcons > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 2,
|
||||
"stroke": "#444444",
|
||||
"stroke-width": 0.25,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 4,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1
|
||||
},
|
||||
"#burgLabels > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 3,
|
||||
"font-size": 3,
|
||||
"font-family": "Orbitron"
|
||||
},
|
||||
"#burgIcons > #towns": {
|
||||
"opacity": 0.95,
|
||||
"fill": "#ffffff",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 0.8,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 0.2,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 1.6,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1
|
||||
},
|
||||
"#labels > #states": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 18,
|
||||
"font-size": 18,
|
||||
"font-family": "Orbitron",
|
||||
"filter": ""
|
||||
},
|
||||
"#labels > #addedLabels": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 18,
|
||||
"font-size": 18,
|
||||
"font-family": "Almendra SC",
|
||||
"filter": null
|
||||
},
|
||||
"#fogging": {
|
||||
"opacity": 0.98,
|
||||
"fill": "#1b1423",
|
||||
"filter": null
|
||||
}
|
||||
}
|
||||
385
styles/default.json
Normal file
385
styles/default.json
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
{
|
||||
"#map": {
|
||||
"background-color": "#000000",
|
||||
"filter": null,
|
||||
"data-filter": null
|
||||
},
|
||||
"#armies": {
|
||||
"font-size": 6,
|
||||
"box-size": 3,
|
||||
"stroke": "#000",
|
||||
"stroke-width": 0.3,
|
||||
"fill-opacity": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#biomes": {
|
||||
"opacity": null,
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#stateBorders": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#56566d",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 2,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#provinceBorders": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#56566d",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": "0 2",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null
|
||||
},
|
||||
"#cells": {
|
||||
"opacity": null,
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 0.1,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#gridOverlay": {
|
||||
"opacity": 0.8,
|
||||
"scale": 1,
|
||||
"dx": 0,
|
||||
"dy": 0,
|
||||
"type": "pointyHex",
|
||||
"stroke": "#777777",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#coordinates": {
|
||||
"opacity": 1,
|
||||
"data-size": 12,
|
||||
"font-size": 12,
|
||||
"stroke": "#d4d4d4",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 5,
|
||||
"stroke-linecap": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#compass": {
|
||||
"opacity": 0.8,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": null
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.7,
|
||||
"stroke": "#777777",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#cults": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#777777",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#landmass": {
|
||||
"opacity": 1,
|
||||
"fill": "#eef6fb",
|
||||
"filter": null
|
||||
},
|
||||
"#markers": {
|
||||
"opacity": null,
|
||||
"rescale": 1,
|
||||
"filter": "url(#dropShadow01)"
|
||||
},
|
||||
"#prec": {
|
||||
"opacity": null,
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0,
|
||||
"fill": "#003dff",
|
||||
"filter": null
|
||||
},
|
||||
"#population": {
|
||||
"opacity": null,
|
||||
"stroke-width": 1.6,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#rural": {
|
||||
"stroke": "#0000ff"
|
||||
},
|
||||
"#urban": {
|
||||
"stroke": "#ff0000"
|
||||
},
|
||||
"#freshwater": {
|
||||
"opacity": 0.5,
|
||||
"fill": "#a6c1fd",
|
||||
"stroke": "#5f799d",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#salt": {
|
||||
"opacity": 0.5,
|
||||
"fill": "#409b8a",
|
||||
"stroke": "#388985",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sinkhole": {
|
||||
"opacity": 1,
|
||||
"fill": "#5bc9fd",
|
||||
"stroke": "#53a3b0",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#frozen": {
|
||||
"opacity": 0.95,
|
||||
"fill": "#cdd4e7",
|
||||
"stroke": "#cfe0eb",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#lava": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#90270d",
|
||||
"stroke": "#f93e0c",
|
||||
"stroke-width": 2,
|
||||
"filter": "url(#crumpled)"
|
||||
},
|
||||
"#dry": {
|
||||
"opacity": 1,
|
||||
"fill": "#c9bfa7",
|
||||
"stroke": "#8e816f",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sea_island": {
|
||||
"opacity": 0.5,
|
||||
"stroke": "#1f3846",
|
||||
"stroke-width": 0.7,
|
||||
"filter": "url(#dropShadow)",
|
||||
"auto-filter": 1
|
||||
},
|
||||
"#lake_island": {
|
||||
"opacity": 1,
|
||||
"stroke": "#7c8eaf",
|
||||
"stroke-width": 0.35,
|
||||
"filter": null
|
||||
},
|
||||
"#terrain": {
|
||||
"opacity": null,
|
||||
"set": "simple",
|
||||
"size": 1,
|
||||
"density": 0.4,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#rivers": {
|
||||
"opacity": null,
|
||||
"filter": null,
|
||||
"fill": "#5d97bb"
|
||||
},
|
||||
"#ruler": {
|
||||
"opacity": null,
|
||||
"filter": null
|
||||
},
|
||||
"#roads": {
|
||||
"opacity": 0.9,
|
||||
"stroke": "#d06324",
|
||||
"stroke-width": 0.7,
|
||||
"stroke-dasharray": 2,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#trails": {
|
||||
"opacity": 0.9,
|
||||
"stroke": "#d06324",
|
||||
"stroke-width": 0.25,
|
||||
"stroke-dasharray": ".8 1.6",
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#searoutes": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#ffffff",
|
||||
"stroke-width": 0.45,
|
||||
"stroke-dasharray": "1 2",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#statesBody": {
|
||||
"opacity": 0.4,
|
||||
"filter": null
|
||||
},
|
||||
"#statesHalo": {
|
||||
"opacity": 0.4,
|
||||
"data-width": 10,
|
||||
"stroke-width": 10,
|
||||
"filter": "blur(5px)"
|
||||
},
|
||||
"#provs": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#000000",
|
||||
"font-size": 10,
|
||||
"font-family": "Georgia",
|
||||
"filter": null
|
||||
},
|
||||
"#temperature": {
|
||||
"opacity": null,
|
||||
"font-size": "8px",
|
||||
"fill": "#000000",
|
||||
"fill-opacity": 0.3,
|
||||
"stroke": null,
|
||||
"stroke-width": 1.8,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#ice": {
|
||||
"opacity": 0.9,
|
||||
"fill": "#e8f0f6",
|
||||
"stroke": "#e8f0f6",
|
||||
"stroke-width": 1,
|
||||
"filter": "url(#dropShadow05)"
|
||||
},
|
||||
"#emblems": {
|
||||
"opacity": 0.9,
|
||||
"stroke-width": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#texture": {
|
||||
"opacity": null,
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#zones": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#333333",
|
||||
"stroke-width": 0,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#oceanLayers": {
|
||||
"filter": null,
|
||||
"layers": "-6,-3,-1"
|
||||
},
|
||||
"#oceanBase": {
|
||||
"fill": "#466eab"
|
||||
},
|
||||
"#oceanicPattern": {
|
||||
"href": "./images/pattern1.png",
|
||||
"opacity": 0.2
|
||||
},
|
||||
"#terrs": {
|
||||
"opacity": null,
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 5,
|
||||
"relax": 0,
|
||||
"curve": 0,
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
"data-size": 13,
|
||||
"font-size": 13,
|
||||
"font-family": "Almendra SC",
|
||||
"stroke": "#812929",
|
||||
"stroke-width": 2.5,
|
||||
"stroke-dasharray": "0 4 10 4",
|
||||
"stroke-linecap": "round",
|
||||
"data-x": 99,
|
||||
"data-y": 93,
|
||||
"data-columns": 8
|
||||
},
|
||||
"#burgLabels > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 7,
|
||||
"font-size": 7,
|
||||
"font-family": "Almendra SC"
|
||||
},
|
||||
"#burgIcons > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 1,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 0.24,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 2,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1.2
|
||||
},
|
||||
"#burgLabels > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 4,
|
||||
"font-size": 4,
|
||||
"font-family": "Almendra SC"
|
||||
},
|
||||
"#burgIcons > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 0.5,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 0.12,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 1,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1.2
|
||||
},
|
||||
"#labels > #states": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"stroke": "#3a3a3a",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 22,
|
||||
"font-size": 22,
|
||||
"font-family": "Almendra SC",
|
||||
"filter": null
|
||||
},
|
||||
"#labels > #addedLabels": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"stroke": "#3a3a3a",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 18,
|
||||
"font-size": 18,
|
||||
"font-family": "Almendra SC",
|
||||
"filter": null
|
||||
},
|
||||
"#fogging": {
|
||||
"opacity": 0.98,
|
||||
"fill": "#30426f",
|
||||
"filter": null
|
||||
}
|
||||
}
|
||||
391
styles/gloom.json
Normal file
391
styles/gloom.json
Normal file
|
|
@ -0,0 +1,391 @@
|
|||
{
|
||||
"#map": {
|
||||
"background-color": "#000000",
|
||||
"filter": null,
|
||||
"data-filter": null
|
||||
},
|
||||
"#armies": {
|
||||
"font-size": 6,
|
||||
"box-size": 3,
|
||||
"stroke": "#000",
|
||||
"stroke-width": 0.3,
|
||||
"opacity": 1,
|
||||
"fill-opacity": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#biomes": {
|
||||
"opacity": null,
|
||||
"filter": "url(#blur5)",
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#stateBorders": {
|
||||
"opacity": 1,
|
||||
"stroke": "#56566d",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 2,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#provinceBorders": {
|
||||
"opacity": 1,
|
||||
"stroke": "#56566d",
|
||||
"stroke-width": 0.3,
|
||||
"stroke-dasharray": ".7 1",
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#cells": {
|
||||
"opacity": null,
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 0.1,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#gridOverlay": {
|
||||
"opacity": 0.8,
|
||||
"scale": 1,
|
||||
"dx": 0,
|
||||
"dy": "0",
|
||||
"type": "pointyHex",
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#coordinates": {
|
||||
"opacity": 1,
|
||||
"data-size": 14,
|
||||
"font-size": 14,
|
||||
"stroke": "#4a4a4a",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 6,
|
||||
"stroke-linecap": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#compass": {
|
||||
"opacity": 0.6,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": "translate(100 100) scale(0.3)"
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.7,
|
||||
"stroke": "#404040",
|
||||
"stroke-width": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#cults": {
|
||||
"opacity": 0.7,
|
||||
"stroke": "#777777",
|
||||
"stroke-width": 1.5,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#landmass": {
|
||||
"opacity": 1,
|
||||
"fill": "#e0e0e0",
|
||||
"filter": null
|
||||
},
|
||||
"#markers": {
|
||||
"opacity": 0.8,
|
||||
"rescale": 1,
|
||||
"filter": "url(#dropShadow05)"
|
||||
},
|
||||
"#prec": {
|
||||
"opacity": null,
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0.1,
|
||||
"fill": "#003dff",
|
||||
"filter": null
|
||||
},
|
||||
"#population": {
|
||||
"opacity": null,
|
||||
"stroke-width": 1.6,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#rural": {
|
||||
"stroke": "#0000aa"
|
||||
},
|
||||
"#urban": {
|
||||
"stroke": "#9d0000"
|
||||
},
|
||||
"#freshwater": {
|
||||
"opacity": 0.5,
|
||||
"fill": "#a6c1fd",
|
||||
"stroke": "#5f799d",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#salt": {
|
||||
"opacity": 0.5,
|
||||
"fill": "#409b8a",
|
||||
"stroke": "#388985",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sinkhole": {
|
||||
"opacity": 1,
|
||||
"fill": "#5bc9fd",
|
||||
"stroke": "#53a3b0",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#frozen": {
|
||||
"opacity": 0.95,
|
||||
"fill": "#cdd4e7",
|
||||
"stroke": "#cfe0eb",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#lava": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#90270d",
|
||||
"stroke": "#f93e0c",
|
||||
"stroke-width": 2,
|
||||
"filter": "url(#crumpled)"
|
||||
},
|
||||
"#dry": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#c9bfa7",
|
||||
"stroke": "#8e816f",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sea_island": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#1f3846",
|
||||
"stroke-width": 0.7,
|
||||
"filter": "url(#dropShadow)",
|
||||
"auto-filter": 1
|
||||
},
|
||||
"#lake_island": {
|
||||
"opacity": 1,
|
||||
"stroke": "#7c8eaf",
|
||||
"stroke-width": 0.35,
|
||||
"filter": null
|
||||
},
|
||||
"#terrain": {
|
||||
"opacity": 0.9,
|
||||
"set": "simple",
|
||||
"size": 1,
|
||||
"density": 0.4,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#rivers": {
|
||||
"opacity": null,
|
||||
"filter": null,
|
||||
"fill": "#779582"
|
||||
},
|
||||
"#ruler": {
|
||||
"opacity": null,
|
||||
"filter": null
|
||||
},
|
||||
"#roads": {
|
||||
"opacity": 1,
|
||||
"stroke": "#8b4418",
|
||||
"stroke-width": 0.9,
|
||||
"stroke-dasharray": "2 3",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#trails": {
|
||||
"opacity": 1,
|
||||
"stroke": "#844017",
|
||||
"stroke-width": 0.2,
|
||||
"stroke-dasharray": ".5 1",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#searoutes": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#5e1865",
|
||||
"stroke-width": 0.6,
|
||||
"stroke-dasharray": "1.2 2.4",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#statesBody": {
|
||||
"opacity": 0.4,
|
||||
"filter": null
|
||||
},
|
||||
"#statesHalo": {
|
||||
"opacity": 0.5,
|
||||
"data-width": 12,
|
||||
"stroke-width": 12,
|
||||
"filter": "blur(10px)"
|
||||
},
|
||||
"#provs": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#000000",
|
||||
"data-size": 10,
|
||||
"font-size": 10,
|
||||
"font-family": "Georgia",
|
||||
"filter": null
|
||||
},
|
||||
"#temperature": {
|
||||
"opacity": 1,
|
||||
"font-size": "11px",
|
||||
"fill": "#62001b",
|
||||
"fill-opacity": 0.3,
|
||||
"stroke": null,
|
||||
"stroke-width": 2,
|
||||
"stroke-dasharray": 2,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#ice": {
|
||||
"opacity": 0.9,
|
||||
"fill": "#e8f0f6",
|
||||
"stroke": "#e8f0f6",
|
||||
"stroke-width": 1,
|
||||
"filter": "url(#dropShadow05)"
|
||||
},
|
||||
"#emblems": {
|
||||
"opacity": 0.6,
|
||||
"stroke-width": 0.5,
|
||||
"filter": null
|
||||
},
|
||||
"#texture": {
|
||||
"opacity": null,
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#textureImage": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"#zones": {
|
||||
"opacity": 0.5,
|
||||
"stroke": "#333333",
|
||||
"stroke-width": 0,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": "url(#dropShadow01)",
|
||||
"mask": null
|
||||
},
|
||||
"#oceanLayers": {
|
||||
"filter": null,
|
||||
"layers": "-6,-4,-2"
|
||||
},
|
||||
"#oceanBase": {
|
||||
"fill": "#4e6964"
|
||||
},
|
||||
"#oceanicPattern": {
|
||||
"href": "./images/pattern3.png",
|
||||
"opacity": 0.2
|
||||
},
|
||||
"#terrs": {
|
||||
"opacity": 1,
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 0,
|
||||
"relax": 1,
|
||||
"curve": 1,
|
||||
"filter": "url(#filter-grayscale)",
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
"data-size": 13,
|
||||
"font-size": 13,
|
||||
"font-family": "Almendra SC",
|
||||
"stroke": "#812929",
|
||||
"stroke-width": 2.5,
|
||||
"stroke-dasharray": "0 4 10 4",
|
||||
"stroke-linecap": "round",
|
||||
"data-x": 99,
|
||||
"data-y": 93,
|
||||
"data-columns": 8
|
||||
},
|
||||
"#legendBox": {},
|
||||
"#burgLabels > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"text-shadow": "white 0 0 4px",
|
||||
"data-size": 7,
|
||||
"font-size": 7,
|
||||
"font-family": "Bitter"
|
||||
},
|
||||
"#burgIcons > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 2,
|
||||
"stroke": "#444444",
|
||||
"stroke-width": 0.25,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #cities": {
|
||||
"opacity": 0.8,
|
||||
"fill": "#ffffff",
|
||||
"size": 4,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1
|
||||
},
|
||||
"#burgLabels > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"data-size": 3,
|
||||
"font-size": 3,
|
||||
"font-family": "Bitter"
|
||||
},
|
||||
"#burgIcons > #towns": {
|
||||
"opacity": 0.95,
|
||||
"fill": "#ffffff",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 0.8,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 0.2,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 1.6,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1.2
|
||||
},
|
||||
"#labels > #states": {
|
||||
"opacity": 1,
|
||||
"fill": "#4e4e4e",
|
||||
"stroke": "#b5b5b5",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0 0 4px",
|
||||
"data-size": 22,
|
||||
"font-size": 22,
|
||||
"font-family": "Almendra SC",
|
||||
"filter": null
|
||||
},
|
||||
"#labels > #addedLabels": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"stroke": "#3a3a3a",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0 0 4px",
|
||||
"data-size": 18,
|
||||
"font-size": 18,
|
||||
"font-family": "Almendra SC",
|
||||
"filter": null
|
||||
},
|
||||
"#fogging": {
|
||||
"opacity": 0.98,
|
||||
"fill": "#1b1423",
|
||||
"filter": null
|
||||
}
|
||||
}
|
||||
385
styles/light.json
Normal file
385
styles/light.json
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
{
|
||||
"#map": {
|
||||
"background-color": "#000000",
|
||||
"filter": null,
|
||||
"data-filter": null
|
||||
},
|
||||
"#armies": {
|
||||
"font-size": 8,
|
||||
"box-size": 4,
|
||||
"stroke": "#000",
|
||||
"stroke-width": 0.02,
|
||||
"fill-opacity": 0.8,
|
||||
"filter": null
|
||||
},
|
||||
"#biomes": {
|
||||
"opacity": 0.5,
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#stateBorders": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#4c483e",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 2,
|
||||
"stroke-linecap": "square",
|
||||
"filter": null
|
||||
},
|
||||
"#provinceBorders": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#56566d",
|
||||
"stroke-width": 0.2,
|
||||
"stroke-dasharray": 1,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#cells": {
|
||||
"opacity": null,
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 0.1,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#gridOverlay": {
|
||||
"opacity": 0.5,
|
||||
"scale": 1,
|
||||
"dx": 0,
|
||||
"dy": 0,
|
||||
"type": "pointyHex",
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#coordinates": {
|
||||
"opacity": 0.7,
|
||||
"data-size": 15,
|
||||
"font-size": 15,
|
||||
"stroke": "#734d37",
|
||||
"stroke-width": 1.5,
|
||||
"stroke-dasharray": 5,
|
||||
"stroke-linecap": "square",
|
||||
"filter": null,
|
||||
"mask": ""
|
||||
},
|
||||
"#compass": {
|
||||
"opacity": 0.6,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": null
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.5,
|
||||
"stroke": null,
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#cults": {
|
||||
"opacity": 0.5,
|
||||
"stroke": "#777777",
|
||||
"stroke-width": 0,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#landmass": {
|
||||
"opacity": 1,
|
||||
"fill": "#f9f2ea",
|
||||
"filter": null
|
||||
},
|
||||
"#markers": {
|
||||
"opacity": null,
|
||||
"rescale": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#prec": {
|
||||
"opacity": null,
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0.1,
|
||||
"fill": "#2554ef",
|
||||
"filter": null
|
||||
},
|
||||
"#population": {
|
||||
"opacity": null,
|
||||
"stroke-width": 1.6,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#rural": {
|
||||
"stroke": "#0000ff"
|
||||
},
|
||||
"#urban": {
|
||||
"stroke": "#ff0000"
|
||||
},
|
||||
"#freshwater": {
|
||||
"opacity": 1,
|
||||
"fill": "#98cdc4",
|
||||
"stroke": "#719892",
|
||||
"stroke-width": 0.46,
|
||||
"filter": "url(#dropShadow05)"
|
||||
},
|
||||
"#salt": {
|
||||
"opacity": 0.5,
|
||||
"fill": "#409b8a",
|
||||
"stroke": "#388985",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sinkhole": {
|
||||
"opacity": 1,
|
||||
"fill": "#5bc9fd",
|
||||
"stroke": "#53a3b0",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#frozen": {
|
||||
"opacity": 0.95,
|
||||
"fill": "#cdd4e7",
|
||||
"stroke": "#cfe0eb",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#lava": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#90270d",
|
||||
"stroke": "#f93e0c",
|
||||
"stroke-width": 2,
|
||||
"filter": "url(#crumpled)"
|
||||
},
|
||||
"#dry": {
|
||||
"opacity": 1,
|
||||
"fill": "#c9bfa7",
|
||||
"stroke": "#8e816f",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sea_island": {
|
||||
"opacity": 1,
|
||||
"stroke": "#5e5e5e",
|
||||
"stroke-width": 0.4,
|
||||
"filter": "url(#dropShadow)",
|
||||
"auto-filter": 1
|
||||
},
|
||||
"#lake_island": {
|
||||
"opacity": 1,
|
||||
"stroke": "#7c8eaf",
|
||||
"stroke-width": 0.35,
|
||||
"filter": null
|
||||
},
|
||||
"#terrain": {
|
||||
"opacity": 0.6,
|
||||
"set": "colored",
|
||||
"size": 1,
|
||||
"density": 0.3,
|
||||
"filter": null,
|
||||
"mask": ""
|
||||
},
|
||||
"#rivers": {
|
||||
"opacity": null,
|
||||
"filter": null,
|
||||
"fill": "#6d94ba"
|
||||
},
|
||||
"#ruler": {
|
||||
"opacity": null,
|
||||
"filter": null
|
||||
},
|
||||
"#roads": {
|
||||
"opacity": 0.9,
|
||||
"stroke": "#3c1d0b",
|
||||
"stroke-width": 1.37,
|
||||
"stroke-dasharray": 2,
|
||||
"stroke-linecap": "inherit",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#trails": {
|
||||
"opacity": 0.9,
|
||||
"stroke": "#95481a",
|
||||
"stroke-width": 0.88,
|
||||
"stroke-dasharray": ".8 1.6",
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#searoutes": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#ffffff",
|
||||
"stroke-width": 0.45,
|
||||
"stroke-dasharray": "1 2",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#statesBody": {
|
||||
"opacity": 0.2,
|
||||
"filter": null
|
||||
},
|
||||
"#statesHalo": {
|
||||
"opacity": 0.3,
|
||||
"data-width": 25,
|
||||
"stroke-width": 25,
|
||||
"filter": "blur(5px)"
|
||||
},
|
||||
"#provs": {
|
||||
"opacity": 0.4,
|
||||
"fill": "#000000",
|
||||
"font-size": 5,
|
||||
"font-family": "IM Fell English",
|
||||
"filter": null
|
||||
},
|
||||
"#temperature": {
|
||||
"opacity": null,
|
||||
"font-size": "8px",
|
||||
"fill": "#000000",
|
||||
"fill-opacity": 0.3,
|
||||
"stroke": null,
|
||||
"stroke-width": 1.8,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#ice": {
|
||||
"opacity": 0.5,
|
||||
"fill": "#e8f0f6",
|
||||
"stroke": "#e8f0f6",
|
||||
"stroke-width": 1.5,
|
||||
"filter": "url(#dropShadow05)"
|
||||
},
|
||||
"#emblems": {
|
||||
"opacity": 0.9,
|
||||
"stroke-width": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#texture": {
|
||||
"opacity": 0.39,
|
||||
"filter": null,
|
||||
"mask": ""
|
||||
},
|
||||
"#zones": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#333333",
|
||||
"stroke-width": 0,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#oceanLayers": {
|
||||
"filter": "url(#dropShadow05)",
|
||||
"layers": "-6,-3,-1"
|
||||
},
|
||||
"#oceanBase": {
|
||||
"fill": "#8dc1c8"
|
||||
},
|
||||
"#oceanicPattern": {
|
||||
"href": "./images/pattern1.png",
|
||||
"opacity": 0.2
|
||||
},
|
||||
"#terrs": {
|
||||
"opacity": 0.4,
|
||||
"scheme": "light",
|
||||
"terracing": 10,
|
||||
"skip": 5,
|
||||
"relax": 0,
|
||||
"curve": 0,
|
||||
"filter": "url(#turbulence)",
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
"data-size": 13,
|
||||
"font-size": 13,
|
||||
"font-family": "Almendra SC",
|
||||
"stroke": "#812929",
|
||||
"stroke-width": 2.5,
|
||||
"stroke-dasharray": "0 4 10 4",
|
||||
"stroke-linecap": "round",
|
||||
"data-x": 54.73,
|
||||
"data-y": 62.98,
|
||||
"data-columns": 8
|
||||
},
|
||||
"#burgLabels > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#3a3a3a",
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 8,
|
||||
"font-size": 8,
|
||||
"font-family": "IM Fell English"
|
||||
},
|
||||
"#burgIcons > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 3,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 0.4,
|
||||
"stroke-dasharray": "0.5 0.25",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 5.5,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1.2
|
||||
},
|
||||
"#burgLabels > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 4,
|
||||
"font-size": 4,
|
||||
"font-family": "IM Fell English"
|
||||
},
|
||||
"#burgIcons > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 1.2,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 0.2,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 2.2,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1.2
|
||||
},
|
||||
"#labels > #states": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e3e",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0.3,
|
||||
"text-shadow": "white 0px 0px 6px",
|
||||
"data-size": 14,
|
||||
"font-size": 14,
|
||||
"font-family": "IM Fell English",
|
||||
"filter": null
|
||||
},
|
||||
"#labels > #addedLabels": {
|
||||
"opacity": 1,
|
||||
"fill": "#f24706",
|
||||
"stroke": "#701b05",
|
||||
"stroke-width": 0.1,
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 6,
|
||||
"font-size": 6,
|
||||
"font-family": "IM Fell English",
|
||||
"filter": null
|
||||
},
|
||||
"#fogging": {
|
||||
"opacity": 1,
|
||||
"fill": "#30426f",
|
||||
"filter": null
|
||||
}
|
||||
}
|
||||
381
styles/monochrome.json
Normal file
381
styles/monochrome.json
Normal file
|
|
@ -0,0 +1,381 @@
|
|||
{
|
||||
"#map": {
|
||||
"background-color": "#000000",
|
||||
"filter": "url(#filter-grayscale)",
|
||||
"data-filter": "grayscale"
|
||||
},
|
||||
"#armies": {
|
||||
"font-size": 6,
|
||||
"box-size": 3,
|
||||
"stroke": "#000",
|
||||
"stroke-width": 0.3,
|
||||
"opacity": 1,
|
||||
"fill-opacity": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#biomes": {
|
||||
"opacity": null,
|
||||
"filter": "url(#blur5)",
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#stateBorders": {
|
||||
"opacity": 1,
|
||||
"stroke": "#56566d",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 2,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#provinceBorders": {
|
||||
"opacity": 1,
|
||||
"stroke": "#56566d",
|
||||
"stroke-width": 0.4,
|
||||
"stroke-dasharray": 1,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#cells": {
|
||||
"opacity": null,
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 0.1,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#gridOverlay": {
|
||||
"opacity": 0.8,
|
||||
"scale": 1,
|
||||
"dx": 0,
|
||||
"dy": "0",
|
||||
"type": "pointyHex",
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#coordinates": {
|
||||
"opacity": 1,
|
||||
"data-size": 12,
|
||||
"font-size": 12,
|
||||
"stroke": "#d4d4d4",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 5,
|
||||
"stroke-linecap": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#compass": {
|
||||
"opacity": 0.8,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": null
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.7,
|
||||
"stroke": "#404040",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#cults": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#777777",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#landmass": {
|
||||
"opacity": 1,
|
||||
"fill": "#000000",
|
||||
"filter": null
|
||||
},
|
||||
"#markers": {
|
||||
"opacity": null,
|
||||
"rescale": 1,
|
||||
"filter": "url(#dropShadow01)"
|
||||
},
|
||||
"#prec": {
|
||||
"opacity": null,
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0.1,
|
||||
"fill": "#003dff",
|
||||
"filter": null
|
||||
},
|
||||
"#population": {
|
||||
"opacity": null,
|
||||
"stroke-width": 1.6,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#rural": {
|
||||
"stroke": "#0000ff"
|
||||
},
|
||||
"#urban": {
|
||||
"stroke": "#ff0000"
|
||||
},
|
||||
"#freshwater": {
|
||||
"opacity": 1,
|
||||
"fill": "#000000",
|
||||
"stroke": "#515151",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#salt": {
|
||||
"opacity": 1,
|
||||
"fill": "#000000",
|
||||
"stroke": "#484848",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#sinkhole": {
|
||||
"opacity": 1,
|
||||
"fill": "#000000",
|
||||
"stroke": "#5f5f5f",
|
||||
"stroke-width": 0.5,
|
||||
"filter": null
|
||||
},
|
||||
"#frozen": {
|
||||
"opacity": 1,
|
||||
"fill": "#000000",
|
||||
"stroke": "#6f6f6f",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#lava": {
|
||||
"opacity": 1,
|
||||
"fill": "#000000",
|
||||
"stroke": "#5d5d5d",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#sea_island": {
|
||||
"opacity": 1,
|
||||
"stroke": "#1f3846",
|
||||
"stroke-width": 0,
|
||||
"filter": null,
|
||||
"auto-filter": 0
|
||||
},
|
||||
"#lake_island": {
|
||||
"opacity": 0,
|
||||
"stroke": "#7c8eaf",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#terrain": {
|
||||
"opacity": null,
|
||||
"set": "simple",
|
||||
"size": 1,
|
||||
"density": 0.4,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#rivers": {
|
||||
"opacity": 0.2,
|
||||
"filter": "url(#blur1)",
|
||||
"fill": "#000000"
|
||||
},
|
||||
"#ruler": {
|
||||
"opacity": null,
|
||||
"filter": null
|
||||
},
|
||||
"#roads": {
|
||||
"opacity": 0.9,
|
||||
"stroke": "#d06324",
|
||||
"stroke-width": 0.7,
|
||||
"stroke-dasharray": 2,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#trails": {
|
||||
"opacity": 0.9,
|
||||
"stroke": "#d06324",
|
||||
"stroke-width": 0.25,
|
||||
"stroke-dasharray": ".8 1.6",
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#searoutes": {
|
||||
"opacity": 0.8,
|
||||
"stroke": "#ffffff",
|
||||
"stroke-width": 0.45,
|
||||
"stroke-dasharray": "1 2",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#statesBody": {
|
||||
"opacity": 0.4,
|
||||
"filter": null
|
||||
},
|
||||
"#statesHalo": {
|
||||
"opacity": 0.4,
|
||||
"data-width": 10,
|
||||
"stroke-width": 10,
|
||||
"filter": "blur(5px)"
|
||||
},
|
||||
"#provs": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#000000",
|
||||
"data-size": 10,
|
||||
"font-size": 10,
|
||||
"font-family": "Georgia",
|
||||
"filter": null
|
||||
},
|
||||
"#temperature": {
|
||||
"opacity": null,
|
||||
"font-size": "8px",
|
||||
"fill": "#000000",
|
||||
"fill-opacity": 0.3,
|
||||
"stroke": null,
|
||||
"stroke-width": 1.8,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#ice": {
|
||||
"opacity": 0.9,
|
||||
"fill": "#e8f0f6",
|
||||
"stroke": "#e8f0f6",
|
||||
"stroke-width": 1,
|
||||
"filter": "url(#dropShadow05)"
|
||||
},
|
||||
"#texture": {
|
||||
"opacity": 1,
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#emblems": {
|
||||
"opacity": 0.5,
|
||||
"stroke-width": 0.5,
|
||||
"filter": null
|
||||
},
|
||||
"#textureImage": {},
|
||||
"#zones": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#333333",
|
||||
"stroke-width": 0,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#oceanLayers": {
|
||||
"filter": null,
|
||||
"layers": "none"
|
||||
},
|
||||
"#oceanBase": {
|
||||
"fill": "#000000"
|
||||
},
|
||||
"#oceanicPattern": {
|
||||
"href": "",
|
||||
"opacity": 0.2
|
||||
},
|
||||
"#terrs": {
|
||||
"opacity": 1,
|
||||
"scheme": "monochrome",
|
||||
"terracing": 0,
|
||||
"skip": 5,
|
||||
"relax": 0,
|
||||
"curve": 0,
|
||||
"filter": "url(#blur3)",
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
"data-size": 13,
|
||||
"font-size": 13,
|
||||
"font-family": "Almendra SC",
|
||||
"stroke": "#812929",
|
||||
"stroke-width": 2.5,
|
||||
"stroke-dasharray": "0 4 10 4",
|
||||
"stroke-linecap": "round",
|
||||
"data-x": 99,
|
||||
"data-y": 93,
|
||||
"data-columns": 8
|
||||
},
|
||||
"#legendBox": {},
|
||||
"#burgLabels > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"text-shadow": "white 0 0 4px",
|
||||
"data-size": 7,
|
||||
"font-size": 7,
|
||||
"font-family": "Almendra SC"
|
||||
},
|
||||
"#burgIcons > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 1,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 0.24,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 2,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1.2
|
||||
},
|
||||
"#burgLabels > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"data-size": 4,
|
||||
"font-size": 4,
|
||||
"font-family": "Almendra SC"
|
||||
},
|
||||
"#burgIcons > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 0.5,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 0.12,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 1,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1.2
|
||||
},
|
||||
"#labels > #states": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"stroke": "#3a3a3a",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0 0 4px",
|
||||
"data-size": 22,
|
||||
"font-size": 22,
|
||||
"font-family": "Almendra SC",
|
||||
"filter": null
|
||||
},
|
||||
"#labels > #addedLabels": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"stroke": "#3a3a3a",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0 0 4px",
|
||||
"data-size": 18,
|
||||
"font-size": 18,
|
||||
"font-family": "Almendra SC",
|
||||
"filter": null
|
||||
},
|
||||
"#fogging": {
|
||||
"opacity": 0.98,
|
||||
"fill": "#30426f",
|
||||
"filter": null
|
||||
}
|
||||
}
|
||||
385
styles/watercolor.json
Normal file
385
styles/watercolor.json
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
{
|
||||
"#map": {
|
||||
"background-color": "#000000",
|
||||
"filter": null,
|
||||
"data-filter": null
|
||||
},
|
||||
"#armies": {
|
||||
"font-size": 8,
|
||||
"box-size": 4,
|
||||
"stroke": "#000",
|
||||
"stroke-width": 0.2,
|
||||
"fill-opacity": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#biomes": {
|
||||
"opacity": 0.6,
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#stateBorders": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#56566d",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 3,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#provinceBorders": {
|
||||
"opacity": 0.5,
|
||||
"stroke": "#56566d",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": "0 2",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null
|
||||
},
|
||||
"#cells": {
|
||||
"opacity": null,
|
||||
"stroke": "#808080",
|
||||
"stroke-width": 0.1,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#gridOverlay": {
|
||||
"opacity": 0.8,
|
||||
"scale": 1,
|
||||
"dx": 0,
|
||||
"dy": 0,
|
||||
"type": "pointyHex",
|
||||
"stroke": "#777777",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#coordinates": {
|
||||
"opacity": 1,
|
||||
"data-size": 12,
|
||||
"font-size": 12,
|
||||
"stroke": "#d4d4d4",
|
||||
"stroke-width": 1,
|
||||
"stroke-dasharray": 5,
|
||||
"stroke-linecap": null,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#compass": {
|
||||
"opacity": 0.8,
|
||||
"transform": null,
|
||||
"filter": null,
|
||||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": "translate(80 80) scale(.25)"
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.7,
|
||||
"stroke": "#777777",
|
||||
"stroke-width": 0,
|
||||
"filter": "url(#bluredSplotch)"
|
||||
},
|
||||
"#cults": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#777777",
|
||||
"stroke-width": 0.5,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": "url(#splotch)"
|
||||
},
|
||||
"#landmass": {
|
||||
"opacity": 1,
|
||||
"fill": "#eef6fb",
|
||||
"filter": null
|
||||
},
|
||||
"#markers": {
|
||||
"opacity": null,
|
||||
"rescale": 1,
|
||||
"filter": "url(#dropShadow01)"
|
||||
},
|
||||
"#prec": {
|
||||
"opacity": null,
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0.1,
|
||||
"fill": "#003dff",
|
||||
"filter": null
|
||||
},
|
||||
"#population": {
|
||||
"opacity": null,
|
||||
"stroke-width": 1.6,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null
|
||||
},
|
||||
"#rural": {
|
||||
"stroke": "#0000ff"
|
||||
},
|
||||
"#urban": {
|
||||
"stroke": "#ff0000"
|
||||
},
|
||||
"#freshwater": {
|
||||
"opacity": 0.5,
|
||||
"fill": "#a6c1fd",
|
||||
"stroke": "#5f799d",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#salt": {
|
||||
"opacity": 0.5,
|
||||
"fill": "#409b8a",
|
||||
"stroke": "#388985",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sinkhole": {
|
||||
"opacity": 1,
|
||||
"fill": "#5bc9fd",
|
||||
"stroke": "#53a3b0",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#frozen": {
|
||||
"opacity": 0.95,
|
||||
"fill": "#cdd4e7",
|
||||
"stroke": "#cfe0eb",
|
||||
"stroke-width": 0,
|
||||
"filter": null
|
||||
},
|
||||
"#lava": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#90270d",
|
||||
"stroke": "#f93e0c",
|
||||
"stroke-width": 2,
|
||||
"filter": "url(#crumpled)"
|
||||
},
|
||||
"#dry": {
|
||||
"opacity": 1,
|
||||
"fill": "#c9bfa7",
|
||||
"stroke": "#8e816f",
|
||||
"stroke-width": 0.7,
|
||||
"filter": null
|
||||
},
|
||||
"#sea_island": {
|
||||
"opacity": 0.5,
|
||||
"stroke": "#1f3846",
|
||||
"stroke-width": 0.7,
|
||||
"filter": "url(#dropShadow)",
|
||||
"auto-filter": 1
|
||||
},
|
||||
"#lake_island": {
|
||||
"opacity": 1,
|
||||
"stroke": "#7c8eaf",
|
||||
"stroke-width": 0.35,
|
||||
"filter": null
|
||||
},
|
||||
"#terrain": {
|
||||
"opacity": 1,
|
||||
"set": "gray",
|
||||
"size": 1,
|
||||
"density": 0.4,
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#rivers": {
|
||||
"opacity": null,
|
||||
"filter": null,
|
||||
"fill": "#2e89c2"
|
||||
},
|
||||
"#ruler": {
|
||||
"opacity": null,
|
||||
"filter": null
|
||||
},
|
||||
"#roads": {
|
||||
"opacity": 0.9,
|
||||
"stroke": "#969696",
|
||||
"stroke-width": 0.7,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#trails": {
|
||||
"opacity": 0.9,
|
||||
"stroke": "#969696",
|
||||
"stroke-width": 0.4,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#searoutes": {
|
||||
"opacity": 0.9,
|
||||
"stroke": "#969696",
|
||||
"stroke-width": 0.7,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "round",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#statesBody": {
|
||||
"opacity": 0.05,
|
||||
"filter": null
|
||||
},
|
||||
"#statesHalo": {
|
||||
"opacity": 0.4,
|
||||
"data-width": 8,
|
||||
"stroke-width": 8,
|
||||
"filter": "blur(2px)"
|
||||
},
|
||||
"#provs": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#000000",
|
||||
"font-size": 4,
|
||||
"font-family": "Comfortaa",
|
||||
"filter": null
|
||||
},
|
||||
"#temperature": {
|
||||
"opacity": null,
|
||||
"font-size": "8px",
|
||||
"fill": "#000000",
|
||||
"fill-opacity": 0.3,
|
||||
"stroke": null,
|
||||
"stroke-width": 1.8,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": null,
|
||||
"filter": null
|
||||
},
|
||||
"#ice": {
|
||||
"opacity": 0.7,
|
||||
"fill": "#dfe8ec",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0,
|
||||
"filter": "url(#dropShadow05)"
|
||||
},
|
||||
"#emblems": {
|
||||
"opacity": 0.95,
|
||||
"stroke-width": 1,
|
||||
"filter": null
|
||||
},
|
||||
"#texture": {
|
||||
"opacity": 0.2,
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#zones": {
|
||||
"opacity": 0.6,
|
||||
"stroke": "#333333",
|
||||
"stroke-width": 0,
|
||||
"stroke-dasharray": null,
|
||||
"stroke-linecap": "butt",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#oceanLayers": {
|
||||
"filter": null,
|
||||
"layers": "-6,-4,-2"
|
||||
},
|
||||
"#oceanBase": {
|
||||
"fill": "#2d788b"
|
||||
},
|
||||
"#oceanicPattern": {
|
||||
"href": "./images/kiwiroo.png",
|
||||
"opacity": 0.5
|
||||
},
|
||||
"#terrs": {
|
||||
"opacity": 0.5,
|
||||
"scheme": "light",
|
||||
"terracing": 0,
|
||||
"skip": 5,
|
||||
"relax": 1,
|
||||
"curve": 0,
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
"data-size": 13,
|
||||
"font-size": 13,
|
||||
"font-family": "Almendra SC",
|
||||
"stroke": "#812929",
|
||||
"stroke-width": 2.5,
|
||||
"stroke-dasharray": "0 4 10 4",
|
||||
"stroke-linecap": "round",
|
||||
"data-x": 99,
|
||||
"data-y": 93,
|
||||
"data-columns": 8
|
||||
},
|
||||
"#burgLabels > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#043449",
|
||||
"text-shadow": "white 0px 0px 2px",
|
||||
"data-size": 5,
|
||||
"font-size": 5,
|
||||
"font-family": "Comfortaa"
|
||||
},
|
||||
"#burgIcons > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 1,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 0.24,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #cities": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 2,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1.2
|
||||
},
|
||||
"#burgLabels > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 3,
|
||||
"font-size": 3,
|
||||
"font-family": "Comfortaa"
|
||||
},
|
||||
"#burgIcons > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"fill-opacity": 0.7,
|
||||
"size": 0.5,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 0.12,
|
||||
"stroke-dasharray": "",
|
||||
"stroke-linecap": "butt"
|
||||
},
|
||||
"#anchors > #towns": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"size": 1,
|
||||
"stroke": "#3e3e4b",
|
||||
"stroke-width": 1.2
|
||||
},
|
||||
"#labels > #states": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 0.15,
|
||||
"text-shadow": "black 1px 1px 2px",
|
||||
"data-size": 20,
|
||||
"font-size": 20,
|
||||
"font-family": "Gloria Hallelujah",
|
||||
"filter": null
|
||||
},
|
||||
"#labels > #addedLabels": {
|
||||
"opacity": 1,
|
||||
"fill": "#3e3e4b",
|
||||
"stroke": "#3a3a3a",
|
||||
"stroke-width": 0,
|
||||
"text-shadow": "white 0px 0px 4px",
|
||||
"data-size": 18,
|
||||
"font-size": 18,
|
||||
"font-family": "Comfortaa",
|
||||
"filter": null
|
||||
},
|
||||
"#fogging": {
|
||||
"opacity": 0.97,
|
||||
"fill": "#8398ce",
|
||||
"filter": null
|
||||
}
|
||||
}
|
||||
|
|
@ -154,18 +154,23 @@ void (function () {
|
|||
const prompt = document.getElementById("prompt");
|
||||
const form = prompt.querySelector("#promptForm");
|
||||
|
||||
window.prompt = function (promptText = "Please provide an input", options = {default: 1, step: 0.01, min: 0, max: 100}, callback) {
|
||||
if (options.default === undefined) {
|
||||
ERROR && console.error("Prompt: options object does not have default value defined");
|
||||
return;
|
||||
}
|
||||
const defaultText = "Please provide an input";
|
||||
const defaultOptions = {default: 1, step: 0.01, min: 0, max: 100, required: true};
|
||||
|
||||
window.prompt = function (promptText = defaultText, options = defaultOptions, callback) {
|
||||
if (options.default === undefined) return ERROR && console.error("Prompt: options object does not have default value defined");
|
||||
|
||||
const input = prompt.querySelector("#promptInput");
|
||||
prompt.querySelector("#promptText").innerHTML = promptText;
|
||||
|
||||
const type = typeof options.default === "number" ? "number" : "text";
|
||||
input.type = type;
|
||||
|
||||
if (options.step !== undefined) input.step = options.step;
|
||||
if (options.min !== undefined) input.min = options.min;
|
||||
if (options.max !== undefined) input.max = options.max;
|
||||
|
||||
input.required = options.required === false ? false : true;
|
||||
input.placeholder = "type a " + type;
|
||||
input.value = options.default;
|
||||
prompt.style.display = "block";
|
||||
|
|
@ -173,9 +178,9 @@ void (function () {
|
|||
form.addEventListener(
|
||||
"submit",
|
||||
event => {
|
||||
event.preventDefault();
|
||||
prompt.style.display = "none";
|
||||
const v = type === "number" ? +input.value : input.value;
|
||||
event.preventDefault();
|
||||
if (callback) callback(v);
|
||||
},
|
||||
{once: true}
|
||||
|
|
@ -183,7 +188,9 @@ void (function () {
|
|||
};
|
||||
|
||||
const cancel = prompt.querySelector("#promptCancel");
|
||||
cancel.addEventListener("click", () => (prompt.style.display = "none"));
|
||||
cancel.addEventListener("click", () => {
|
||||
prompt.style.display = "none";
|
||||
});
|
||||
})();
|
||||
|
||||
// indexedDB; ldb object
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
function convertTemperature(temp) {
|
||||
switch (temperatureScale.value) {
|
||||
case "°C":
|
||||
return temp + "°C";
|
||||
return rn(temp) + "°C";
|
||||
case "°F":
|
||||
return rn((temp * 9) / 5 + 32) + "°F";
|
||||
case "K":
|
||||
|
|
@ -21,7 +21,7 @@ function convertTemperature(temp) {
|
|||
case "°Rø":
|
||||
return rn((temp * 21) / 40 + 7.5) + "°Rø";
|
||||
default:
|
||||
return temp + "°C";
|
||||
return rn(temp) + "°C";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue