Sync screenshot-driven mobile shipyard fixes
This commit is contained in:
parent
844e226aca
commit
a6b7b541ec
@ -414,6 +414,10 @@ if (!isDesktopPointer.matches) {
|
|||||||
filter: grayscale(.7);
|
filter: grayscale(.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#mobile-controls.controller-active .mobile-control.ship-action[hidden] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
#mobile-controls.controller-active .mobile-control.ship-action.active,
|
#mobile-controls.controller-active .mobile-control.ship-action.active,
|
||||||
#mobile-controls.controller-active .mobile-control.ship-action:active {
|
#mobile-controls.controller-active .mobile-control.ship-action:active {
|
||||||
background: rgba(117, 78, 31, .9);
|
background: rgba(117, 78, 31, .9);
|
||||||
@ -799,17 +803,17 @@ if (!isDesktopPointer.matches) {
|
|||||||
|
|
||||||
const progression = state.progression || {};
|
const progression = state.progression || {};
|
||||||
if (buyButton) {
|
if (buyButton) {
|
||||||
|
buyButton.hidden = !progression.docked;
|
||||||
buyButton.disabled = !progression.docked;
|
buyButton.disabled = !progression.docked;
|
||||||
buyButton.textContent = progression.docked
|
buyButton.textContent = 'SHIPYARD';
|
||||||
? 'SHIPYARD'
|
|
||||||
: 'SHIPYARD\nPORT';
|
|
||||||
}
|
}
|
||||||
if (fitButton) {
|
if (fitButton) {
|
||||||
const module = progression.salvageModule;
|
const module = progression.salvageModule;
|
||||||
|
fitButton.hidden = !module;
|
||||||
fitButton.disabled = !module;
|
fitButton.disabled = !module;
|
||||||
fitButton.textContent = module
|
fitButton.textContent = module
|
||||||
? `FIT\n${module.name}`
|
? `FIT\n${module.name}`
|
||||||
: 'FIT\nEMPTY';
|
: 'FIT';
|
||||||
}
|
}
|
||||||
|
|
||||||
const statusText = String(state.status || '').trim();
|
const statusText = String(state.status || '').trim();
|
||||||
|
|||||||
@ -79,6 +79,7 @@ export const buyAndInstallModule = (progression, moduleId) => {
|
|||||||
|
|
||||||
export const marketForPort = (port) => {
|
export const marketForPort = (port) => {
|
||||||
const stock = purchasableModules().filter((module) => {
|
const stock = purchasableModules().filter((module) => {
|
||||||
|
if (module.slot === 'rudder') return true;
|
||||||
if (port?.type === 'industrial') return ['engine', 'hull', 'utility', 'cargo'].includes(module.slot);
|
if (port?.type === 'industrial') return ['engine', 'hull', 'utility', 'cargo'].includes(module.slot);
|
||||||
if (port?.type === 'military') return ['weapon', 'hull', 'navigation'].includes(module.slot);
|
if (port?.type === 'military') return ['weapon', 'hull', 'navigation'].includes(module.slot);
|
||||||
if (port?.type === 'fuel') return ['engine', 'navigation', 'cargo'].includes(module.slot);
|
if (port?.type === 'fuel') return ['engine', 'navigation', 'cargo'].includes(module.slot);
|
||||||
|
|||||||
@ -65,8 +65,7 @@ overlay.innerHTML = `
|
|||||||
`).join('')}
|
`).join('')}
|
||||||
</div>
|
</div>
|
||||||
<div class="shipyard-active-plate">
|
<div class="shipyard-active-plate">
|
||||||
<img src="${activeUrl}" alt="" draggable="false" />
|
<img src="${activeUrl}" alt="Sparrow active" draggable="false" />
|
||||||
<span data-shipyard="active">SPARROW ACTIVE</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -253,15 +252,10 @@ style.textContent = `
|
|||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.shipyard-active-plate img { display: block; width: 100%; }
|
.shipyard-active-plate img {
|
||||||
.shipyard-active-plate span {
|
display: block;
|
||||||
position: absolute;
|
width: 100%;
|
||||||
inset: 0;
|
height: auto;
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
color: #b9efc0;
|
|
||||||
font-size: clamp(9px, 1.15vw, 13px);
|
|
||||||
letter-spacing: .08em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.shipyard-footer {
|
.shipyard-footer {
|
||||||
@ -351,11 +345,21 @@ style.textContent = `
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (orientation: portrait) and (max-width: 760px) {
|
@media (orientation: portrait) and (max-width: 760px) {
|
||||||
|
.shipyard-shell {
|
||||||
|
min-height: calc(100dvh - 8px);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.shipyard-title { width: min(500px, 80vw); }
|
.shipyard-title { width: min(500px, 80vw); }
|
||||||
.shipyard-grid { grid-template-columns: 1fr; }
|
.shipyard-grid { grid-template-columns: 1fr; }
|
||||||
.shipyard-preview-wrap { display: none; }
|
.shipyard-preview-wrap { display: none; }
|
||||||
.shipyard-upgrade-wrap { width: min(96vw, 520px); margin: 0 auto; }
|
.shipyard-upgrade-wrap { width: min(96vw, 520px); margin: 0 auto; }
|
||||||
.shipyard-footer { margin-top: 48px; }
|
|
||||||
|
.shipyard-footer {
|
||||||
|
margin-top: auto;
|
||||||
|
padding: 58px 0 max(14px, env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import assert from 'node:assert/strict';
|
|||||||
import {
|
import {
|
||||||
bestAffordableMarketUpgrade,
|
bestAffordableMarketUpgrade,
|
||||||
buyAndInstallModule,
|
buyAndInstallModule,
|
||||||
|
marketForPort,
|
||||||
collectSalvage,
|
collectSalvage,
|
||||||
createStarterProgression,
|
createStarterProgression,
|
||||||
deriveShipStats,
|
deriveShipStats,
|
||||||
@ -58,6 +59,14 @@ test('market can select an affordable upgrade for a port', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('rudder is stocked at every port type so the shipyard card is actionable', () => {
|
||||||
|
const portTypes = ['industrial', 'military', 'fuel', 'trade'];
|
||||||
|
for (const type of portTypes) {
|
||||||
|
const stock = marketForPort({ type });
|
||||||
|
assert.ok(stock.some(({ id }) => id === 'reinforced-rudder'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('rudder tier matches shipyard art and improves handling', () => {
|
test('rudder tier matches shipyard art and improves handling', () => {
|
||||||
const starter = { ...createStarterProgression(), credits: 650 };
|
const starter = { ...createStarterProgression(), credits: 650 };
|
||||||
const result = buyAndInstallModule(starter, 'reinforced-rudder');
|
const result = buyAndInstallModule(starter, 'reinforced-rudder');
|
||||||
|
|||||||
@ -280,6 +280,8 @@ test('mobile controls expose native buy and salvage-fit actions', async () => {
|
|||||||
assert.match(game, /salvageModule: salvageModule \? \{/);
|
assert.match(game, /salvageModule: salvageModule \? \{/);
|
||||||
assert.match(hud, /root\.querySelector\('\.mobile-control\.buy'\)/);
|
assert.match(hud, /root\.querySelector\('\.mobile-control\.buy'\)/);
|
||||||
assert.match(hud, /root\.querySelector\('\.mobile-control\.fit'\)/);
|
assert.match(hud, /root\.querySelector\('\.mobile-control\.fit'\)/);
|
||||||
|
assert.match(hud, /buyButton\.hidden = !progression\.docked/);
|
||||||
|
assert.match(hud, /fitButton\.hidden = !module/);
|
||||||
assert.match(hud, /buyButton\.disabled = !progression\.docked/);
|
assert.match(hud, /buyButton\.disabled = !progression\.docked/);
|
||||||
assert.match(hud, /fitButton\.disabled = !module/);
|
assert.match(hud, /fitButton\.disabled = !module/);
|
||||||
});
|
});
|
||||||
@ -299,6 +301,8 @@ test('shipyard overlay uses supplied component art and explicit module purchases
|
|||||||
assert.match(shipyard, /shipyard-ui\/upgrades\.png\?url/);
|
assert.match(shipyard, /shipyard-ui\/upgrades\.png\?url/);
|
||||||
assert.match(shipyard, /airship:shipyard-open/);
|
assert.match(shipyard, /airship:shipyard-open/);
|
||||||
assert.match(shipyard, /dispatchAction\('purchase-module', \{ moduleId \}\)/);
|
assert.match(shipyard, /dispatchAction\('purchase-module', \{ moduleId \}\)/);
|
||||||
|
assert.doesNotMatch(shipyard, /data-shipyard="active"/);
|
||||||
|
assert.match(shipyard, /min-height: calc\(100dvh - 8px\)/);
|
||||||
assert.match(game, /marketForPort\(port\)/);
|
assert.match(game, /marketForPort\(port\)/);
|
||||||
assert.match(game, /airship:shipyard-state/);
|
assert.match(game, /airship:shipyard-state/);
|
||||||
assert.match(game, /this\.shipyardOpen = true/);
|
assert.match(game, /this\.shipyardOpen = true/);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user