diff --git a/res/ui/icons/waypoint.png b/res/ui/icons/waypoint.png
new file mode 100644
index 00000000..068d57cc
Binary files /dev/null and b/res/ui/icons/waypoint.png differ
diff --git a/src/css/ingame_hud/building_placer.scss b/src/css/ingame_hud/building_placer.scss
index bcfddc8a..0548390b 100644
--- a/src/css/ingame_hud/building_placer.scss
+++ b/src/css/ingame_hud/building_placer.scss
@@ -94,6 +94,7 @@
.keybinding {
position: relative;
}
+ font-weight: bold !important;
@include DarkThemeOverride {
color: rgba(#fff, 0.5);
diff --git a/src/css/ingame_hud/waypoints.scss b/src/css/ingame_hud/waypoints.scss
index d18b2188..70c3c23f 100644
--- a/src/css/ingame_hud/waypoints.scss
+++ b/src/css/ingame_hud/waypoints.scss
@@ -1,4 +1,4 @@
-#ingame_HUD_Waypoints {
+#ingame_HUD_Waypoints_Hint {
position: absolute;
@include S(right, 10px);
@include S(bottom, 100px);
@@ -25,3 +25,42 @@
}
}
}
+
+#ingame_HUD_Waypoints {
+ position: absolute;
+ @include S(right, 10px);
+ @include S(top, 60px);
+ display: flex;
+ flex-direction: column;
+
+ .waypoint {
+ @include SuperSmallText;
+ pointer-events: all;
+ cursor: pointer;
+ color: #000;
+ @include S(padding-left, 11px);
+ display: grid;
+ grid-template-columns: 1fr auto;
+ align-items: center;
+ background: uiResource("icons/waypoint.png") left 50% / #{D(8px)} no-repeat;
+ opacity: 0.5;
+ @include S(margin-bottom, 1px);
+ font-weight: bold;
+ &:hover {
+ opacity: 1;
+ }
+
+ .deleteButton {
+ @include S(width, 10px);
+ @include S(height, 10px);
+ @include S(margin-left, 4px);
+ background: uiResource("icons/close.png") center center / 60% no-repeat;
+ pointer-events: all;
+ cursor: pointer;
+
+ &:hover {
+ transform: scale(1.5);
+ }
+ }
+ }
+}
diff --git a/src/css/main.scss b/src/css/main.scss
index 1f71acb8..2c573318 100644
--- a/src/css/main.scss
+++ b/src/css/main.scss
@@ -57,6 +57,7 @@ ingame_Canvas,
ingame_VignetteOverlay,
// Ingame overlays
+ingame_HUD_Waypoints,
ingame_HUD_PlacementHints,
ingame_HUD_PlacerVariants,
@@ -71,7 +72,7 @@ ingame_HUD_EntityDebugger,
ingame_HUD_TutorialHints,
ingame_HUD_buildings_toolbar,
ingame_HUD_BlueprintPlacer,
-ingame_HUD_Waypoints,
+ingame_HUD_Waypoints_Hint,
ingame_HUD_Watermark,
// Overlays
diff --git a/src/js/changelog.js b/src/js/changelog.js
index 970cd1a1..86282cbc 100644
--- a/src/js/changelog.js
+++ b/src/js/changelog.js
@@ -4,6 +4,7 @@ export const CHANGELOG = [
date: "unreleased",
entries: [
"BLUEPRINTS! They are unlocked at level 12 and cost a special shape to build.",
+ "MAP MARKERS! Press 'M' to create a waypoint and be able to jump to it",
"Savegame levels are now shown in the main menu. For existing games, save them again to make the level show up.",
"Allow holding SHIFT to rotate counter clockwise",
"Added confirmation when deleting more than 500 buildings at a time",
@@ -13,6 +14,7 @@ export const CHANGELOG = [
"Allow placing extractors anywhere again, but they don't work at all if not placed on a resource",
"Show dialog explaining some keybindings after completing level 4",
"Fix keys being stuck when opening a dialog",
+ "Swapped shape order for painting upgrades",
"Allow changing all keybindings, including CTRL, ALT and SHIFT (by Dimava)",
"Fix cycling through keybindings selecting locked buildings as well (by Dimava)",
"There is now a github action, checking all pull requests with eslint. (by mrHedgehog)",
diff --git a/src/js/game/hud/base_hud_part.js b/src/js/game/hud/base_hud_part.js
index 032530fb..84b6d619 100644
--- a/src/js/game/hud/base_hud_part.js
+++ b/src/js/game/hud/base_hud_part.js
@@ -72,9 +72,16 @@ export class BaseHUDPart {
}
/**
- * Cleans up the hud element, if overridden make sure to call super.cleanups
+ * Cleans up the hud element, if overridden make sure to call super.cleanup
*/
cleanup() {
+ this.cleanupClickDetectors();
+ }
+
+ /**
+ * Cleans up all click detectors
+ */
+ cleanupClickDetectors() {
if (this.clickDetectors) {
for (let i = 0; i < this.clickDetectors.length; ++i) {
this.clickDetectors[i].cleanup();
diff --git a/src/js/game/hud/parts/waypoints.js b/src/js/game/hud/parts/waypoints.js
index 9fdf4adc..4371f827 100644
--- a/src/js/game/hud/parts/waypoints.js
+++ b/src/js/game/hud/parts/waypoints.js
@@ -1,27 +1,34 @@
-import { BaseHUDPart } from "../base_hud_part";
-import { makeDiv, arrayDelete, arrayDeleteValue, lerp } from "../../../core/utils";
-import { Vector } from "../../../core/vector";
+import { makeOffscreenBuffer } from "../../../core/buffer_utils";
+import { Math_max } from "../../../core/builtins";
+import { globalConfig, IS_DEMO } from "../../../core/config";
import { DrawParameters } from "../../../core/draw_parameters";
import { Loader } from "../../../core/loader";
-import { T } from "../../../translations";
-import { Rectangle } from "../../../core/rectangle";
-import { makeOffscreenBuffer } from "../../../core/buffer_utils";
-import { enumMouseButton } from "../../camera";
-import { STOP_PROPAGATION } from "../../../core/signal";
-import { KEYMAPPINGS } from "../../key_action_mapper";
-import { DynamicDomAttach } from "../dynamic_dom_attach";
-import { IS_DEMO, globalConfig } from "../../../core/config";
import { DialogWithForm } from "../../../core/modal_dialog_elements";
import { FormElementInput } from "../../../core/modal_dialog_forms";
-import { Math_max } from "../../../core/builtins";
+import { Rectangle } from "../../../core/rectangle";
+import { STOP_PROPAGATION } from "../../../core/signal";
+import { arrayDeleteValue, lerp, makeDiv, removeAllChildren } from "../../../core/utils";
+import { Vector } from "../../../core/vector";
+import { T } from "../../../translations";
+import { enumMouseButton } from "../../camera";
+import { KEYMAPPINGS } from "../../key_action_mapper";
+import { BaseHUDPart } from "../base_hud_part";
+import { DynamicDomAttach } from "../dynamic_dom_attach";
import { enumNotificationType } from "./notifications";
+/** @typedef {{
+ * label: string,
+ * center: { x: number, y: number },
+ * zoomLevel: number,
+ * deletable: boolean
+ * }} Waypoint */
+
export class HUDWaypoints extends BaseHUDPart {
createElements(parent) {
if (this.root.app.settings.getAllSettings().offerHints) {
- this.element = makeDiv(
+ this.hintElement = makeDiv(
parent,
- "ingame_HUD_Waypoints",
+ "ingame_HUD_Waypoints_Hint",
[],
`
${T.ingame.waypoints.waypoints}
@@ -36,6 +43,8 @@ export class HUDWaypoints extends BaseHUDPart {
}
this.waypointSprite = Loader.getSprite("sprites/misc/waypoint.png");
+
+ this.waypointsListElement = makeDiv(parent, "ingame_HUD_Waypoints", [], "Waypoints");
}
serialize() {
@@ -49,15 +58,48 @@ export class HUDWaypoints extends BaseHUDPart {
return "Invalid waypoints data";
}
this.waypoints = data.waypoints;
+ this.rerenderWaypointList();
+ }
+
+ rerenderWaypointList() {
+ removeAllChildren(this.waypointsListElement);
+ this.cleanupClickDetectors();
+
+ for (let i = 0; i < this.waypoints.length; ++i) {
+ const waypoint = this.waypoints[i];
+
+ const element = makeDiv(this.waypointsListElement, null, ["waypoint"]);
+ element.innerText = waypoint.label;
+
+ if (waypoint.deletable) {
+ const deleteButton = makeDiv(element, null, ["deleteButton"]);
+ this.trackClicks(deleteButton, () => this.deleteWaypoint(waypoint));
+ }
+
+ this.trackClicks(element, () => this.moveToWaypoint(waypoint), {
+ targetOnly: true,
+ });
+ }
+ }
+
+ /**
+ * @param {Waypoint} waypoint
+ */
+ moveToWaypoint(waypoint) {
+ this.root.camera.setDesiredCenter(new Vector(waypoint.center.x, waypoint.center.y));
+ this.root.camera.setDesiredZoom(waypoint.zoomLevel);
+ }
+
+ /**
+ * @param {Waypoint} waypoint
+ */
+ deleteWaypoint(waypoint) {
+ arrayDeleteValue(this.waypoints, waypoint);
+ this.rerenderWaypointList();
}
initialize() {
- /** @type {Array<{
- * label: string,
- * center: { x: number, y: number },
- * zoomLevel: number,
- * deletable: boolean
- * }>}
+ /** @type {Array}
*/
this.waypoints = [
{
@@ -74,7 +116,7 @@ export class HUDWaypoints extends BaseHUDPart {
})[1];
this.root.camera.downPreHandler.add(this.onMouseDown, this);
- this.domAttach = new DynamicDomAttach(this.root, this.element);
+ this.domAttach = new DynamicDomAttach(this.root, this.hintElement);
this.root.keyMapper.getBinding(KEYMAPPINGS.ingame.createMarker).add(this.requestCreateMarker, this);
@@ -82,7 +124,6 @@ export class HUDWaypoints extends BaseHUDPart {
}
/**
- *
* @param {Vector=} worldPos Override the world pos, otherwise it is the camera position
*/
requestCreateMarker(worldPos = null) {
@@ -116,10 +157,12 @@ export class HUDWaypoints extends BaseHUDPart {
zoomLevel: Math_max(this.root.camera.zoomLevel, globalConfig.mapChunkOverviewMinZoom + 0.05),
deletable: true,
});
+ this.waypoints.sort((a, b) => a.label.padStart(20, "0").localeCompare(b.label.padStart(20, "0")));
this.root.hud.signals.notification.dispatch(
T.ingame.waypoints.creationSuccessNotification,
enumNotificationType.success
);
+ this.rerenderWaypointList();
});
}
@@ -168,12 +211,11 @@ export class HUDWaypoints extends BaseHUDPart {
if (waypoint) {
if (button === enumMouseButton.left) {
this.root.soundProxy.playUiClick();
- this.root.camera.setDesiredCenter(new Vector(waypoint.center.x, waypoint.center.y));
- this.root.camera.setDesiredZoom(waypoint.zoomLevel);
+ this.moveToWaypoint(waypoint);
} else if (button === enumMouseButton.right) {
if (waypoint.deletable) {
this.root.soundProxy.playUiClick();
- arrayDeleteValue(this.waypoints, waypoint);
+ this.deleteWaypoint(waypoint);
} else {
this.root.soundProxy.playUiError();
}
@@ -183,9 +225,11 @@ export class HUDWaypoints extends BaseHUDPart {
} else {
// Allow right click to create a marker
if (button === enumMouseButton.right) {
- const worldPos = this.root.camera.screenToWorld(pos);
- this.requestCreateMarker(worldPos);
- return STOP_PROPAGATION;
+ if (this.root.camera.getIsMapOverlayActive()) {
+ const worldPos = this.root.camera.screenToWorld(pos);
+ this.requestCreateMarker(worldPos);
+ return STOP_PROPAGATION;
+ }
}
}
}
diff --git a/src/js/game/upgrades.js b/src/js/game/upgrades.js
index b766c149..500a2afe 100644
--- a/src/js/game/upgrades.js
+++ b/src/js/game/upgrades.js
@@ -98,12 +98,12 @@ export const UPGRADES = {
painting: {
tiers: [
{
- required: [{ shape: "WrWrWrWr", amount: 500 }],
- improvement: 1,
+ required: [{ shape: "RbRb----", amount: 1500 }],
+ improvement: 2,
},
{
- required: [{ shape: "RbRb----", amount: 4000 }],
- improvement: 2,
+ required: [{ shape: "WrWrWrWr", amount: 5000 }],
+ improvement: 1,
},
{
required: [{ shape: "RpRpRpRp:CwCwCwCw", amount: 30000 }],
diff --git a/src/js/platform/wrapper.js b/src/js/platform/wrapper.js
index 5754a8a2..9fee5b3a 100644
--- a/src/js/platform/wrapper.js
+++ b/src/js/platform/wrapper.js
@@ -66,7 +66,7 @@ export class PlatformWrapperInterface {
* @returns {number}
*/
getMinimumZoom() {
- return 0.1 * this.getScreenScale();
+ return 0.2 * this.getScreenScale();
}
/**
diff --git a/translations/base-en.yaml b/translations/base-en.yaml
index 91a90c2f..e293516f 100644
--- a/translations/base-en.yaml
+++ b/translations/base-en.yaml
@@ -61,8 +61,8 @@ demoBanners:
intro: >-
If you enjoy this game, please consider buying the full version!
advantages:
- - No advertisements
- Unlimited savegames
+ - Waypoints
- Dark mode & more
- >-
Allow me to further develop shapez.io ❤️