Files
44r0n7 626879ed0c Add freshness bar, enhance overlays and renderers
- Add enemy freshness tracking (novelty bonus for repeated deploys)
- Add freshness bar to sidepanel enemy cards with penalty indicator
- Major overhaul of renderer-overlays.js (790+ lines for UI polish)
- Enhanced combat log, shop overlays, and inventory UI
- Improved weapon/upgrade display with partial ownership colors
- Added element icons and weakness/resistance indicators to cards
- Enhanced radial menu and tooltip system
- Add "stale/%" penalty text when freshness depleted
- Update play link to ffazeshift.net in index.html
2026-06-17 11:58:17 -04:00

64 lines
1.6 KiB
JavaScript

// ═══ utils.js ═══
// ============================================================
// UTILS — shared pure helpers
// ============================================================
function distSq(ax, ay, bx, by) {
const dx = ax - bx;
const dy = ay - by;
return dx * dx + dy * dy;
}
function normalizeAngle(angle) {
while (angle > Math.PI) angle -= Math.PI * 2;
while (angle < -Math.PI) angle += Math.PI * 2;
return angle;
}
function shortestAngleDelta(from, to) {
return normalizeAngle(to - from);
}
function stepTowardAngle(current, desired, maxStep) {
const delta = shortestAngleDelta(current, desired);
if (Math.abs(delta) <= maxStep) return normalizeAngle(desired);
return normalizeAngle(current + Math.sign(delta) * maxStep);
}
function compactLiveArray(items, isLive) {
let write = 0;
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (isLive(item)) items[write++] = item;
}
items.length = write;
}
function clamp(value, min, max) {
return Math.max(min, Math.min(max, value));
}
function cheapestEnemyCost() {
const tier = G?.difficultyTier ?? 0;
const prestige = G?.prestigeLevel ?? 0;
return ENEMY_DEFS
.filter(d => (d.minTier ?? 0) <= tier && (d.minPrestige ?? 0) <= prestige)
.reduce((min, d) => Math.min(min, d.cost), Infinity);
}
function countAliveEnemies() {
let count = 0;
for (const e of G.enemies) if (e.alive) count++;
return count;
}
function getEquippedWeapons() {
return G.weapons.slice(0, G.tower.weaponSlots).filter(Boolean);
}
function findWeaponInstance(instanceId) {
for (const w of G.weapons) if (w && w.instanceId === instanceId) return w;
return null;
}