Queue consumed on dispatch; engine chain hardened; queued planes unsellable (ISS-088)
CI / build + unit + e2e (pull_request) Failing after 12m59s
CI / build + unit + e2e (pull_request) Failing after 12m59s
This commit is contained in:
+35
-24
@@ -246,32 +246,43 @@ export async function deliverPackages(inst: GameDb, clockMs: number): Promise<nu
|
||||
let topUpFuel: number | null = null; // post-top-up fuel for the chained departure, when a top-up happened
|
||||
if (queue.length > 0 && newHealth > 0) {
|
||||
const nextDest = queue[0];
|
||||
const next = byIcao.get(nextDest); // unknown ICAO in the queue → cannot chain
|
||||
if (next) {
|
||||
// Wind-adjusted requirement for the NEXT leg — it departs from `to` (v0.36.0).
|
||||
const wNext = weatherFor(to.icao);
|
||||
const nextRequiredL = requiredFuelFor(
|
||||
type.burnPerKm * windBurnFactor(wNext.windKt, wNext.windDirDeg, initialBearingDeg(to.lat, to.lon, next.lat, next.lon)),
|
||||
type.emptyWeightKg,
|
||||
type.maxFuel,
|
||||
haversineKm(to.lat, to.lon, next.lat, next.lon),
|
||||
);
|
||||
if (nextRequiredL <= landedFuel) {
|
||||
queue.shift();
|
||||
chainedTo = nextDest;
|
||||
} else {
|
||||
// ISS-082: auto top-up — same target/price terms as flyPlane's dispatch refuel.
|
||||
const target = Math.min(type.maxFuel, Math.max(landedFuel, nextRequiredL * 1.5));
|
||||
const liters = Math.max(0, target - landedFuel);
|
||||
// Fresh account read (same pattern as the delivery awards above) so a top-up in this tick sees current cash.
|
||||
const fresh = (await inst.db.select().from(schema.account))[0];
|
||||
if (!fresh) throw new Error('account row missing');
|
||||
const cost = Math.round(liters * FUEL_PRICE_PER_L * (1 - repRate(fresh.reputation, FUEL_DISCOUNT_PER_REP, MAX_FUEL_DISCOUNT)) * 100) / 100;
|
||||
if (cost === 0 || fresh.cash >= cost) {
|
||||
// ponytail: defensive guard for legacy rows — a queued leg to the airport we just landed at is a
|
||||
// zero-distance no-op hop; drop it and ground instead of flying. Normal play can't produce this
|
||||
// since v0.46.0 (flyPlane consumes queue[0] on dispatch, every chain shifts its own leg).
|
||||
if (nextDest === to.icao) {
|
||||
queue.shift();
|
||||
} else {
|
||||
const next = byIcao.get(nextDest); // unknown ICAO in the queue → cannot chain
|
||||
if (next) {
|
||||
// Wind-adjusted requirement for the NEXT leg — it departs from `to` (v0.36.0).
|
||||
const wNext = weatherFor(to.icao);
|
||||
const nextRequiredL = requiredFuelFor(
|
||||
type.burnPerKm * windBurnFactor(wNext.windKt, wNext.windDirDeg, initialBearingDeg(to.lat, to.lon, next.lat, next.lon)),
|
||||
type.emptyWeightKg,
|
||||
type.maxFuel,
|
||||
haversineKm(to.lat, to.lon, next.lat, next.lon),
|
||||
);
|
||||
// v0.46.0 backstop: a leg that doesn't fit even a full tank is unflyable — ground with the queue
|
||||
// intact, mirroring flyPlane's 409 without throwing in the engine.
|
||||
if (nextRequiredL > type.maxFuel) {
|
||||
// no chain — the grounded update below keeps the queue for a later dispatch
|
||||
} else if (nextRequiredL <= landedFuel) {
|
||||
queue.shift();
|
||||
chainedTo = nextDest;
|
||||
topUpFuel = target;
|
||||
if (cost > 0) await inst.db.update(schema.account).set({ cash: Math.round((fresh.cash - cost) * 100) / 100 });
|
||||
} else {
|
||||
// ISS-082: auto top-up — same target/price terms as flyPlane's dispatch refuel.
|
||||
const target = Math.min(type.maxFuel, Math.max(landedFuel, nextRequiredL * 1.5));
|
||||
const liters = Math.max(0, target - landedFuel);
|
||||
// Fresh account read (same pattern as the delivery awards above) so a top-up in this tick sees current cash.
|
||||
const fresh = (await inst.db.select().from(schema.account))[0];
|
||||
if (!fresh) throw new Error('account row missing');
|
||||
const cost = Math.round(liters * FUEL_PRICE_PER_L * (1 - repRate(fresh.reputation, FUEL_DISCOUNT_PER_REP, MAX_FUEL_DISCOUNT)) * 100) / 100;
|
||||
if (cost === 0 || fresh.cash >= cost) {
|
||||
queue.shift();
|
||||
chainedTo = nextDest;
|
||||
topUpFuel = target;
|
||||
if (cost > 0) await inst.db.update(schema.account).set({ cash: Math.round((fresh.cash - cost) * 100) / 100 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user