groundHog v{process.env.REACT_APP_VERSION}
By Christopher Dollard (aka charredUtensil)
diff --git a/src/webui/components/about/styles.module.scss b/src/webui/components/about/styles.module.scss
new file mode 100644
index 0000000..ee5b228
--- /dev/null
+++ b/src/webui/components/about/styles.module.scss
@@ -0,0 +1,40 @@
+.popoverWrapper {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+
+ > div {
+ background: var(--palette-bg);
+ border: 1px solid var(--palette-settings-bg);
+ margin: 0 auto;
+ padding: 0 24px;
+ max-width: 500px;
+ max-height: calc(100% - 100px);
+ overflow-x: hidden;
+ overflow-y: scroll;
+ }
+
+ .about {
+ color: var(--palette-accent);
+
+ a {
+ color: var(--palette-fg);
+ }
+ }
+
+ .script {
+ transform: translateX(-250px);
+ width: 300px;
+
+ .src {
+ white-space: pre;
+ font-family: var(--font-mono);
+ font-size: 12px;
+ }
+ }
+}
diff --git a/src/webui/components/map_preview/index.tsx b/src/webui/components/map_preview/index.tsx
index 8ced21b..fe9f743 100644
--- a/src/webui/components/map_preview/index.tsx
+++ b/src/webui/components/map_preview/index.tsx
@@ -1,4 +1,4 @@
-import React, { CSSProperties, createRef } from "react";
+import React, { CSSProperties, useReducer, useState } from "react";
import { Cavern } from "../../../core/models/cavern";
import BaseplatePreview from "./baseplate";
import PathPreview from "./path";
@@ -11,6 +11,7 @@ import styles from "./style.module.scss";
import HeightPreview from "./height";
import Stats from "./stats";
import PlansPreview from "./plan";
+import ScriptPreview, { ScriptOverlay } from "./script_preview";
export type MapOverlay =
| "about"
@@ -24,30 +25,21 @@ export type MapOverlay =
| "ore"
| "overview"
| "oxygen"
+ | "script"
| "tiles"
| null;
-// function getTransform(cavern: Cavern, mapOverlay: MapOverlay) {
-// if (mapOverlay !== "overview") {
-// return undefined;
-// }
-// if (!cavern.cameraPosition) {
-// return `scale(2) rotate3d(1, 0, 0, 60deg) rotate(-30deg)`
-// }
-// const { x, y, yaw, pitch } = cavern.cameraPosition;
-// return `scale(6) rotate3d(1, 0, 0, ${pitch}rad) rotate(${Math.PI / -2 - yaw}rad) translate(${-x * 6}px, ${-y * 6}px)`;
-// }
function getTransform(cavern: Cavern, mapOverlay: MapOverlay) {
if (mapOverlay !== "overview" || !cavern.cameraPosition) {
return {};
}
const { x, y, yaw, pitch } = cavern.cameraPosition;
return {
- '--pvw-scale': 6,
- '--pvw-pitch': `${pitch}rad`,
- '--pvw-yaw': `${Math.PI - (yaw + Math.PI * 1.5) % (Math.PI * 2)}rad`,
- '--pvw-tr-x': -x * 6,
- '--pvw-tr-y': -y * 6,
+ "--pvw-scale": 6,
+ "--pvw-pitch": `${pitch}rad`,
+ "--pvw-yaw": `${Math.PI - ((yaw + Math.PI * 1.5) % (Math.PI * 2))}rad`,
+ "--pvw-tr-x": -x * 6,
+ "--pvw-tr-y": -y * 6,
} as CSSProperties;
}
@@ -64,99 +56,139 @@ export default function CavernPreview({
showOutlines: boolean;
showPearls: boolean;
}) {
- const holder = createRef();
+ const [scriptLineHovered, setScriptLineHovered] = useState(-1);
+ const [scriptLineOffsets, setScriptLineOffsets] = useReducer(
+ (was: number[], now: number[]) => {
+ if (was.length !== now.length) {
+ return now;
+ }
+ for (let i = 0; i < was.length; i++) {
+ if (was[i] !== now[i]) {
+ return now;
+ }
+ }
+ return was;
+ },
+ [],
+ );
+
+ switch (mapOverlay) {
+ case "about":
+ case "lore":
+ return null;
+ default:
+ }
+
const height = cavern.context.targetSize * 2 * 6;
const width = Math.max(height, cavern.context.targetSize * 6 + 600);
return (
-
diff --git a/src/webui/components/map_preview/plan.tsx b/src/webui/components/map_preview/plan.tsx
index ba9e374..1e76b21 100644
--- a/src/webui/components/map_preview/plan.tsx
+++ b/src/webui/components/map_preview/plan.tsx
@@ -117,7 +117,13 @@ function hall(plan: Partial) {
);
}
-export default function PlansPreview({ cavern, mapOverlay }: { cavern: Cavern, mapOverlay: MapOverlay }) {
+export default function PlansPreview({
+ cavern,
+ mapOverlay,
+}: {
+ cavern: Cavern;
+ mapOverlay: MapOverlay;
+}) {
if (!cavern.plans) {
return null;
}
@@ -152,15 +158,21 @@ export default function PlansPreview({ cavern, mapOverlay }: { cavern: Cavern, m
sign: -1 | 1,
className: string,
): ReactNode {
- if (mapOverlay === 'overview') {
- return plans.map(plan => {
+ if (mapOverlay === "script") {
+ return null;
+ }
+ if (mapOverlay === "overview") {
+ return plans.map((plan) => {
const bps = plan.path.baseplates;
if (bps.length <= 1) {
const [x, y] = bps[0].center;
return (
-
+
- {'architect' in plan && plan.architect.name} {plan.id}
+ {"architect" in plan && plan.architect.name} {plan.id}
);
@@ -172,15 +184,14 @@ export default function PlansPreview({ cavern, mapOverlay }: { cavern: Cavern, m
})
.join(" ");
return (
-
-
+
+
- {'architect' in plan && plan.architect.name} {plan.id}
+ {"architect" in plan && plan.architect.name} {plan.id}
diff --git a/src/webui/components/map_preview/script_preview/index.tsx b/src/webui/components/map_preview/script_preview/index.tsx
new file mode 100644
index 0000000..2511655
--- /dev/null
+++ b/src/webui/components/map_preview/script_preview/index.tsx
@@ -0,0 +1,192 @@
+import React, {
+ Fragment,
+ createRef,
+ useLayoutEffect,
+ useMemo,
+} from "react";
+import { Cavern } from "../../../../core/models/cavern";
+import styles from "./styles.module.scss";
+import { Point } from "../../../../core/common/geometry";
+import { filterTruthy } from "../../../../core/common/utils";
+
+type Statement = {
+ kind: string;
+ code: string;
+ pos?: Point;
+};
+
+const SCALE = 6;
+
+function parse(script: string): Statement[] {
+ return script.split("\n").map((line) => {
+ if (line.startsWith("#")) {
+ return { kind: "misc", code: line };
+ }
+ if (!line) {
+ return { kind: "misc", code: "\u00A0" };
+ }
+ const m = line.match(/(?(^|\())[a-z]+:(?\d+),(?\d+)/);
+ if (m) {
+ const kind = m.groups!.prefix === "(" ? "condition" : "event";
+ return {
+ kind: kind,
+ code: line,
+ pos: [parseInt(m.groups!.x, 10), parseInt(m.groups!.y)],
+ };
+ }
+ return { kind: "misc", code: line };
+ });
+}
+
+function getLineOffsets(container: HTMLDivElement) {
+ const result = [];
+ const lines = Array.from(
+ container.getElementsByClassName(styles.line),
+ ) as HTMLElement[];
+ let i = 0;
+ for (; i < lines.length; i++) {
+ if (lines[i].offsetTop + lines[i].clientHeight >= container.scrollTop) {
+ break;
+ }
+ }
+ for (; i < lines.length; i++) {
+ if (lines[i].offsetTop >= container.scrollTop + container.clientHeight) {
+ break;
+ }
+ result[i] =
+ lines[i].offsetTop +
+ lines[i].clientHeight / 2 -
+ container.clientHeight / 2 -
+ container.scrollTop;
+ }
+ return result;
+}
+
+export default function ScriptPreview({
+ cavern,
+ setScriptLineOffsets,
+ scriptLineHovered,
+ setScriptLineHovered,
+}: {
+ cavern: Cavern | undefined;
+ setScriptLineOffsets: (v: number[]) => void;
+ scriptLineHovered: number;
+ setScriptLineHovered: (v: number) => void;
+}) {
+ const ref = createRef();
+ useLayoutEffect(() => {
+ const container = ref.current;
+ if (!container) {
+ return;
+ }
+ setScriptLineOffsets(getLineOffsets(container));
+ }, [ref, setScriptLineOffsets]);
+ const statements = useMemo(
+ () => (cavern?.script ? parse(cavern.script) : undefined),
+ [cavern],
+ );
+ return (
+ setScriptLineOffsets(getLineOffsets(ref.current!))}
+ >
+
Script
+
+ {statements?.map(({ code, pos, kind }, i) => {
+ const className = filterTruthy([
+ styles.line,
+ scriptLineHovered === i && styles.hovered,
+ styles[kind],
+ ]).join(" ");
+ return (
+
setScriptLineHovered(i) : undefined}
+ >
+ {code}
+
+ );
+ })}
+
+
+ );
+}
+
+export function ScriptOverlay({
+ cavern,
+ scriptLineOffsets,
+ scriptLineHovered,
+}: {
+ cavern: Cavern | undefined;
+ scriptLineOffsets: number[];
+ scriptLineHovered: number;
+}) {
+ const statements = useMemo(
+ () => (cavern?.script ? parse(cavern.script) : undefined),
+ [cavern],
+ );
+ if (!cavern?.script) {
+ return null;
+ }
+ const ox = cavern.left!;
+ const oy = cavern.top!;
+ return (
+ <>
+
+ {statements!.map(({ kind, pos }, i) => {
+ if (!pos || scriptLineOffsets[i] === undefined) {
+ return null;
+ }
+ const active = true;
+ const className = filterTruthy([
+ styles.tile,
+ active ? styles.active : styles.inactive,
+ scriptLineHovered === i && styles.hovered,
+ styles[kind],
+ ]).join(" ");
+ return (
+
+ );
+ })}
+
+ {parse(cavern.script).map(({ kind, pos }, i) => {
+ if (
+ !pos ||
+ scriptLineOffsets[i] === undefined ||
+ scriptLineHovered !== i
+ ) {
+ return null;
+ }
+ const className = filterTruthy([
+ styles.arrow,
+ scriptLineHovered === i && styles.hovered,
+ styles[kind],
+ ]).join(" ");
+ const lx = -9999;
+ const ly = scriptLineOffsets[i];
+ const px = (pos[0] + ox + 0.5) * SCALE;
+ const py = (pos[1] + oy + 0.5) * SCALE;
+ const bx = px - Math.abs(py - ly) * 0.3;
+ const d = filterTruthy([
+ `M ${px} ${py}`,
+ `L ${bx} ${ly}`,
+ `L ${lx} ${ly}`,
+ ]).join("");
+ return (
+
+
+
+
+ );
+ })}
+ >
+ );
+}
diff --git a/src/webui/components/map_preview/script_preview/styles.module.scss b/src/webui/components/map_preview/script_preview/styles.module.scss
new file mode 100644
index 0000000..48d185c
--- /dev/null
+++ b/src/webui/components/map_preview/script_preview/styles.module.scss
@@ -0,0 +1,55 @@
+.script {
+ position: relative;
+ background: var(--palette-bg);
+ border-right: 1px solid var(--palette-settings-bg);
+ width: 450px;
+ overflow-x: hidden;
+ overflow-y: scroll;
+ z-index: 1;
+
+ > h2 {
+ padding: 0 12px;
+ }
+
+ .src {
+ font-family: var(--font-mono);
+ font-size: 12px;
+ word-wrap: break-word;
+
+ .line {
+ color: var(--color-codehlt);
+ padding: 0 12px;
+
+ &.hovered {
+ color: black;
+ background: var(--color-codehlt);
+ }
+ }
+ }
+}
+
+.tiles {
+ .active.tile {
+ fill: var(--color-codehlt);
+ }
+
+ .inactive.tile {
+ fill: transparent;
+ }
+}
+
+.arrow {
+ fill: none;
+ stroke: var(--color-codehlt);
+ stroke-width: 2px;
+}
+
+.misc {
+ --color-codehlt: var(--palette-fg);
+}
+.condition {
+ --color-codehlt: yellow;
+}
+.event {
+ --color-codehlt: cyan;
+}
diff --git a/src/webui/components/map_preview/stats.tsx b/src/webui/components/map_preview/stats.tsx
index bfd25a4..f02c633 100644
--- a/src/webui/components/map_preview/stats.tsx
+++ b/src/webui/components/map_preview/stats.tsx
@@ -39,128 +39,121 @@ export default function Stats({
cavern: Cavern;
mapOverlay: MapOverlay;
}) {
- return (
-
- {(() => {
- switch (mapOverlay) {
- case "overview":
- return (
- cavern.briefing?.intro && (
-
- Briefing: {cavern.briefing.intro.replace(/\n/g, "\u00B6")}
-
- )
- );
- case "tiles":
- return (
-
- - Playable area: {cavern.tiles?.size ?? 0}
- -
- Walls:{" "}
- {cavern.tiles?.reduce((r, t) => (t.isWall ? r + 1 : r), 0)}
-
-
- );
- case "entities": {
- return (
-
- - Miners: {cavern.miners?.length ?? 0}
- -
- Buildings:
-
- -
- Vehicles:
-
- -
- Creatures:
-
-
- );
- }
- case "crystals":
- return (
-
- - Total EC: {getTotalCrystals(cavern)}
- {cavern.objectives?.crystals ? (
- - Goal: {cavern.objectives?.crystals}
- ) : null}
-
- );
- case "ore":
- return (
-
- - Total Ore: {getTotalOre(cavern)}
- {cavern.objectives?.ore ? (
- - Goal: {cavern.objectives?.ore}
- ) : null}
-
- );
- case "landslides": {
- if (!cavern.landslides?.size) {
- return null;
- }
- const count = cavern.landslides.size;
- const avgCooldown =
- cavern.landslides.reduce((r, ls) => r + ls.cooldown, 0) / count;
- return (
-
- - Landslides: {count}
- {avgCooldown && (
- - Avg Cooldown: {avgCooldown.toFixed(2)} seconds
- )}
-
- );
- }
- case "erosion": {
- const count = cavern.erosion?.size ?? 0;
- const avgCooldown = cavern.erosion
- ? cavern.erosion.reduce((r, ls) => r + ls.cooldown, 0) / count
- : null;
- return (
-
- -
- Water:{" "}
- {cavern.tiles?.reduce(
- (r, t) => (t === Tile.WATER ? r + 1 : r),
- 0,
- )}
-
- -
- Lava:{" "}
- {cavern.tiles?.reduce(
- (r, t) => (t === Tile.LAVA ? r + 1 : r),
- 0,
- )}
-
- - Erosion: {count}
- {avgCooldown && (
- - Avg Cooldown: {avgCooldown.toFixed(2)} seconds
- )}
-
- );
- }
- case "height": {
- if (!cavern.height) {
- return null;
- }
- return (
-
- -
- min:{" "}
- {cavern.height.reduce((r, h) => (h < r ? h : r), 0).toFixed()}
-
- -
- max:{" "}
- {cavern.height.reduce((r, h) => (h > r ? h : r), 0).toFixed()}
-
-
- );
- }
- case "oxygen": {
- return
Oxygen: {cavern.oxygen?.join("/") ?? "Infinity"}
;
- }
+ const content = (() => {
+ switch (mapOverlay) {
+ case "overview":
+ return (
+ cavern.briefing?.intro && (
+
Briefing: {cavern.briefing.intro.replace(/\n/g, "\u00B6")}
+ )
+ );
+ case "tiles":
+ return (
+
+ - Playable area: {cavern.tiles?.size ?? 0}
+ -
+ Walls: {cavern.tiles?.reduce((r, t) => (t.isWall ? r + 1 : r), 0)}
+
+
+ );
+ case "entities": {
+ return (
+
+ - Miners: {cavern.miners?.length ?? 0}
+ -
+ Buildings:
+
+ -
+ Vehicles:
+
+ -
+ Creatures:
+
+
+ );
+ }
+ case "crystals":
+ return (
+
+ - Total EC: {getTotalCrystals(cavern)}
+ {cavern.objectives?.crystals ? (
+ - Goal: {cavern.objectives?.crystals}
+ ) : null}
+
+ );
+ case "ore":
+ return (
+
+ - Total Ore: {getTotalOre(cavern)}
+ {cavern.objectives?.ore ? (
+ - Goal: {cavern.objectives?.ore}
+ ) : null}
+
+ );
+ case "landslides": {
+ if (!cavern.landslides?.size) {
+ return null;
}
- })()}
-
- );
+ const count = cavern.landslides.size;
+ const avgCooldown =
+ cavern.landslides.reduce((r, ls) => r + ls.cooldown, 0) / count;
+ return (
+
+ - Landslides: {count}
+ {avgCooldown && (
+ - Avg Cooldown: {avgCooldown.toFixed(2)} seconds
+ )}
+
+ );
+ }
+ case "erosion": {
+ const count = cavern.erosion?.size ?? 0;
+ const avgCooldown = cavern.erosion
+ ? cavern.erosion.reduce((r, ls) => r + ls.cooldown, 0) / count
+ : null;
+ return (
+
+ -
+ Water:{" "}
+ {cavern.tiles?.reduce(
+ (r, t) => (t === Tile.WATER ? r + 1 : r),
+ 0,
+ )}
+
+ -
+ Lava:{" "}
+ {cavern.tiles?.reduce((r, t) => (t === Tile.LAVA ? r + 1 : r), 0)}
+
+ - Erosion: {count}
+ {avgCooldown && (
+ - Avg Cooldown: {avgCooldown.toFixed(2)} seconds
+ )}
+
+ );
+ }
+ case "height": {
+ if (!cavern.height) {
+ return null;
+ }
+ return (
+
+ -
+ min:{" "}
+ {cavern.height.reduce((r, h) => (h < r ? h : r), 0).toFixed()}
+
+ -
+ max:{" "}
+ {cavern.height.reduce((r, h) => (h > r ? h : r), 0).toFixed()}
+
+
+ );
+ }
+ case "oxygen": {
+ return Oxygen: {cavern.oxygen?.join("/") ?? "Infinity"}
;
+ }
+ default:
+ return null;
+ }
+ })();
+ return content && {content}
;
}
diff --git a/src/webui/components/map_preview/style.module.scss b/src/webui/components/map_preview/style.module.scss
index c4c0d1f..41f1ddd 100644
--- a/src/webui/components/map_preview/style.module.scss
+++ b/src/webui/components/map_preview/style.module.scss
@@ -30,6 +30,8 @@
width: 100%;
height: 100%;
+ display: flex;
+
--pvw-bpak: #222222;
--pvw-bpck: #2d004b;
--pvw-bphk: #166921;
@@ -74,188 +76,194 @@
--pvw-oxex: #555533;
--pvw-oxhc: var(--pvw-tile42);
- .map {
- position: absolute;
- transition: transform 1s linear;
- transform:
- rotate3d(1, 0, 0, var(--pvw-pitch))
- rotate(var(--pvw-yaw))
- matrix(
- var(--pvw-scale),
- 0,
- 0,
- var(--pvw-scale),
- calc(var(--pvw-tr-x) * var(--pvw-scale)),
- calc(var(--pvw-tr-y) * var(--pvw-scale))
- );
-
- .baseplate {
- font-family: var(--font-tiny);
- font-size: 8px;
-
- .fg {
- fill: white;
- }
+ .mapWrapper {
+ position: relative;
+ width: 100%;
- &.ambiguousKind .bg {
- fill: var(--pvw-bpak);
- }
+ .map {
+ position: absolute;
+ transition: transform 500ms linear;
+ transform: rotate3d(1, 0, 0, var(--pvw-pitch)) rotate(var(--pvw-yaw))
+ matrix(
+ var(--pvw-scale),
+ 0,
+ 0,
+ var(--pvw-scale),
+ calc(var(--pvw-tr-x) * var(--pvw-scale)),
+ calc(var(--pvw-tr-y) * var(--pvw-scale))
+ );
- &.caveKind .bg {
- fill: var(--pvw-bpck);
- }
+ .baseplate {
+ font-family: var(--font-tiny);
+ font-size: 8px;
- &.hallKind .bg {
- fill: var(--pvw-bphk);
- }
- }
+ .fg {
+ fill: white;
+ }
- .path {
- stroke-linecap: round;
- stroke-dasharray: 2, 3;
+ &.ambiguousKind .bg {
+ fill: var(--pvw-bpak);
+ }
- &.ambiguousKind {
- --fg-color: white;
- --fg-opacity: 0.3;
- }
+ &.caveKind .bg {
+ fill: var(--pvw-bpck);
+ }
- &.spanningKind {
- --fg-color: var(--pvw-pathspan);
+ &.hallKind .bg {
+ fill: var(--pvw-bphk);
+ }
}
- &.auxiliaryKind {
- --fg-color: var(--pvw-pathaux);
- }
+ .path {
+ stroke-linecap: round;
+ stroke-dasharray: 2, 3;
- & > path {
- stroke: var(--fg-color);
- stroke-opacity: var(--fg-opacity);
- stroke-width: 2px;
- }
+ &.ambiguousKind {
+ --fg-color: white;
+ --fg-opacity: 0.3;
+ }
- & > text {
- fill: var(--fg-color);
- opacity: var(--fg-opacity);
- font-family: var(--font-tiny);
- font-size: 12px;
- }
- }
+ &.spanningKind {
+ --fg-color: var(--pvw-pathspan);
+ }
- .plan {
- --color-bg: #444444;
- --color-fg: white;
- &.caveKind .bg {
- stroke-width: 2px;
- fill: none;
- }
- &.hallKind {
- .bg {
- stroke-linecap: round;
- opacity: 0.4;
+ &.auxiliaryKind {
+ --fg-color: var(--pvw-pathaux);
}
- &.spanningPathKind {
- --color-fg: var(--pvw-pathspan);
+
+ & > path {
+ stroke: var(--fg-color);
+ stroke-opacity: var(--fg-opacity);
+ stroke-width: 2px;
}
- &.auxiliaryPathKind {
- --color-fg: var(--pvw-pathaux);
+
+ & > text {
+ fill: var(--fg-color);
+ opacity: var(--fg-opacity);
+ font-family: var(--font-tiny);
+ font-size: 12px;
}
}
- &.fluid6 {
- --color-bg: var(--pvw-tile6);
- }
- &.fluid11 {
- --color-bg: var(--pvw-tile11);
- }
- &.left .label {
- text-anchor: end;
- }
- &.inline .label {
- text-anchor: middle;
- font-size: 6px;
- }
- .label {
- fill: var(--color-fg);
- font-size: 12px;
- }
- .pointer {
- fill: none;
- stroke-width: 1px;
- stroke: var(--color-fg);
- }
- .bg {
- stroke: var(--color-bg);
- }
- }
- .pearl {
- &.innerPearl {
- stroke-width: 1px;
- &.caveKind {
- --color0: #40ffff;
- --color1: #40dddd;
- --color2: #40bbbb;
- --color3: #409999;
+ .plan {
+ --color-bg: #444444;
+ --color-fg: white;
+ &.caveKind .bg {
+ stroke-width: 2px;
+ fill: none;
}
&.hallKind {
- --color0: #ffff20;
- --color1: #dddd20;
- --color2: #bbbb20;
- --color3: #999920;
+ .bg {
+ stroke-linecap: round;
+ opacity: 0.4;
+ }
+ &.spanningPathKind {
+ --color-fg: var(--pvw-pathspan);
+ }
+ &.auxiliaryPathKind {
+ --color-fg: var(--pvw-pathaux);
+ }
}
- }
- &.outerPearl {
- stroke-width: 0.5px;
- --color0: #999999;
- --color1: #888888;
- --color2: #777777;
- --color3: #666666;
- }
- .layer {
- &.layer0 {
- stroke: var(--color0);
+ &.fluid6 {
+ --color-bg: var(--pvw-tile6);
}
- &.layer1 {
- stroke: var(--color1);
+ &.fluid11 {
+ --color-bg: var(--pvw-tile11);
}
- &.layer2 {
- stroke: var(--color2);
+ &.left .label {
+ text-anchor: end;
}
- &.layer3 {
- stroke: var(--color3);
+ &.inline .label {
+ text-anchor: middle;
+ font-size: 6px;
+ }
+ .label {
+ fill: var(--color-fg);
+ font-size: 12px;
+ }
+ .pointer {
+ fill: none;
+ stroke-width: 1px;
+ stroke: var(--color-fg);
+ }
+ .bg {
+ stroke: var(--color-bg);
}
}
- }
-
- .tiles {
- shape-rendering: crispEdges;
- }
- .height {
- shape-rendering: crispEdges;
- }
+ .pearl {
+ &.innerPearl {
+ stroke-width: 1px;
+ &.caveKind {
+ --color0: #40ffff;
+ --color1: #40dddd;
+ --color2: #40bbbb;
+ --color3: #409999;
+ }
+ &.hallKind {
+ --color0: #ffff20;
+ --color1: #dddd20;
+ --color2: #bbbb20;
+ --color3: #999920;
+ }
+ }
+ &.outerPearl {
+ stroke-width: 0.5px;
+ --color0: #999999;
+ --color1: #888888;
+ --color2: #777777;
+ --color3: #666666;
+ }
+ .layer {
+ &.layer0 {
+ stroke: var(--color0);
+ }
+ &.layer1 {
+ stroke: var(--color1);
+ }
+ &.layer2 {
+ stroke: var(--color2);
+ }
+ &.layer3 {
+ stroke: var(--color3);
+ }
+ }
+ }
- .entity {
- --color-fg: var(--pvw-entfriend);
- &.enemy {
- --color-fg: var(--pvw-entenemy);
+ .tiles {
+ shape-rendering: crispEdges;
+ .tile {
+ transition: fill 500ms ease-out;
+ }
}
- .marker {
- fill: var(--color-fg);
- stroke: black;
- stroke-width: 0.5px;
+
+ .height {
+ shape-rendering: crispEdges;
}
- .label {
- fill: black;
- font-family: "Outfit";
- font-size: 2px;
- text-anchor: middle;
- pointer-events: none;
+
+ .entity {
+ --color-fg: var(--pvw-entfriend);
+ &.enemy {
+ --color-fg: var(--pvw-entenemy);
+ }
+ .marker {
+ fill: var(--color-fg);
+ stroke: black;
+ stroke-width: 0.5px;
+ }
+ .label {
+ fill: black;
+ font-family: "Outfit";
+ font-size: 2px;
+ text-anchor: middle;
+ pointer-events: none;
+ }
}
- }
- .openCaveFlag {
- stroke: red;
- fill: white;
+ .openCaveFlag {
+ stroke: red;
+ fill: white;
+ }
}
}
diff --git a/src/webui/components/map_preview/tiles.tsx b/src/webui/components/map_preview/tiles.tsx
index 0ff9c26..77b9387 100644
--- a/src/webui/components/map_preview/tiles.tsx
+++ b/src/webui/components/map_preview/tiles.tsx
@@ -104,6 +104,8 @@ function getFill(
}
return t.isWall ? tk(t) : "oxex";
}
+ case "script":
+ return dk(t);
}
return null;
}
@@ -151,11 +153,7 @@ function getTitle(
case "overview":
case "tiles":
return t.name;
- case "about":
- case "entities":
- case "height":
- case "lore":
- case null:
+ default:
return null;
}
}
@@ -171,10 +169,7 @@ export default function TilesPreview({
return null;
}
return (
-
+
{cavern.tiles.map((t, x, y) => {
const fill = getFill(cavern, mapOverlay, t, x, y);
if (!fill) {
diff --git a/tsconfig.json b/tsconfig.json
index 6597d5c..3873b6f 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,6 +1,6 @@
{
"compilerOptions": {
- "target": "es2016",
+ "target": "es2018",
"jsx": "react",
"module": "commonjs",
"esModuleInterop": true,