Refine Archive World navigation and gate progression
All checks were successful
Build Org Website / build (push) Successful in 38s

This commit is contained in:
gitea-actions
2026-07-30 10:02:58 +01:00
parent c06af38d80
commit 2f125f32ae
10 changed files with 301 additions and 80 deletions

View File

@@ -18,6 +18,30 @@
return { x: (x / length) * speed, y: (y / length) * speed };
}
function moveToward(value, target, maximumDelta) {
if (Math.abs(target - value) <= maximumDelta) return target;
return value + Math.sign(target - value) * maximumDelta;
}
function approachVelocity(currentX, currentY, inputX, inputY, movement, deltaMs, hasBoots) {
const config = movement || {};
const speed = Math.max(1, Number(config.speed) || 160);
const moving = Boolean(Number(inputX) || Number(inputY));
const target = moving ? normalizedVector(inputX, inputY, speed) : { x: 0, y: 0 };
const rate = moving
? (hasBoots ? Number(config.bootAcceleration) || 1700 : Number(config.acceleration) || 1300)
: Number(config.deceleration) || 1900;
const step = Math.max(0, Math.min(50, Number(deltaMs) || 0)) / 1000 * rate;
let x = moveToward(Number(currentX) || 0, target.x, step);
let y = moveToward(Number(currentY) || 0, target.y, step);
const length = Math.hypot(x, y);
if (length > speed) {
x = x / length * speed;
y = y / length * speed;
}
return { x, y };
}
function discover(state, landmarkId) {
const next = copy(state);
if (!next || !Data.LANDMARK_IDS.includes(landmarkId)) return next;
@@ -164,11 +188,22 @@
return !area.collisions.some((item) => pointInRect(x, y, item, 10));
}
function isCombatSafe(areaId, x, y) {
const area = Data.AREAS[areaId];
return Boolean(area && (area.safeZones || []).some((item) => pointInRect(x, y, item, 0)));
}
function nearestSafeSpawn(areaId, x, y) {
const area = Data.AREAS[areaId] || Data.AREAS.town;
const points = Object.entries(area.safeSpawns || { entrance: area.spawn });
const safeCurrent = isSafe(areaId, x, y);
if (safeCurrent) return { area: areaId, spawn: "saved", x, y };
return nearestNamedSafeSpawn(areaId, x, y);
}
function nearestNamedSafeSpawn(areaId, x, y) {
const area = Data.AREAS[areaId] || Data.AREAS.town;
const points = Object.entries(area.safeSpawns || { entrance: area.spawn });
const best = points.sort((a, b) =>
Math.hypot(a[1].x - x, a[1].y - y) - Math.hypot(b[1].x - x, b[1].y - y))[0];
return { area: areaId, spawn: best[0], x: best[1].x, y: best[1].y };
@@ -186,7 +221,8 @@
}
return Object.freeze({
normalizedVector, discover, startQuest, progressQuest, completeQuest, updateStory, addItem, itemQuantity,
consumeItem, grantXp, takeDamage, respawn, recordBoss, isSafe, nearestSafeSpawn, currentObjective
normalizedVector, approachVelocity, discover, startQuest, progressQuest, completeQuest, updateStory, addItem, itemQuantity,
consumeItem, grantXp, takeDamage, respawn, recordBoss, isSafe, isCombatSafe,
nearestSafeSpawn, nearestNamedSafeSpawn, currentObjective
});
}));