import { tryBuyEgg, tryBuyBaby, tryBuyAnimal } from "./zoo.js"; import { pickSaleTargetZoo } from "./conveyor.js"; import { sellAnimalToNpc, addMatureBabyToSale, addReceptionAnimalToSale } from "./trade.js"; import { playSound } from "./audio.js"; import { t, errorMessage } from "./texts-fr.js"; import { getApiBase, createSale } from "./api-client.js"; /** * @param {DragEvent} e * @param {{ state: import("./types.js").GameState, setState: () => void, setError: (s: string) => void }} setup * @returns {boolean} */ function handleTruckDropBaby(e, setup) { const babyOffer = e.dataTransfer.getData("application/x-builazoo-baby-offer"); if (!babyOffer) return false; const [animalId, priceStr] = babyOffer.split(":"); const price = Number(priceStr) || 80; const [ok, result] = tryBuyBaby(setup.state, animalId, price); if (!ok) setup.setError(String(t.buyFailed).replace("%s", errorMessage[result] ?? result)); else setup.setError(""); playSound(ok ? "buy" : "error"); setup.setState(); return true; } /** * @param {DragEvent} e * @param {{ state: import("./types.js").GameState, setState: () => void, setError: (s: string) => void }} setup * @returns {boolean} */ function handleTruckDropAnimal(e, setup) { const animalOffer = e.dataTransfer.getData("application/x-builazoo-animal-offer"); if (!animalOffer) return false; const [animalId, priceStr] = animalOffer.split(":"); const price = Number(priceStr) || 120; const [ok, result] = tryBuyAnimal(setup.state, animalId, price); if (!ok) setup.setError(String(t.buyFailed).replace("%s", errorMessage[result] ?? result)); else setup.setError(""); playSound(ok ? "buy" : "error"); setup.setState(); return true; } /** * @param {DragEvent} e * @param {{ state: import("./types.js").GameState, setState: () => void, setError: (s: string) => void }} setup * @returns {boolean} */ function handleTruckDropEgg(e, setup) { const eggType = e.dataTransfer.getData("application/x-builazoo-eggtype"); if (!eggType) return false; const toZooId = e.dataTransfer.getData("application/x-builazoo-offer-zooid") || "player"; const [ok, result] = tryBuyEgg(setup.state, eggType); if (!ok) { setup.setError(String(t.buyFailed).replace("%s", errorMessage[result] ?? result)); playSound("error"); } else { setup.setError(""); playSound("buy"); setup.state.eggPurchaseTruck = { eggType, fromZooId: "player", toZooId, startAt: Date.now() }; } setup.setState(); return true; } /** * @param {DragEvent} e * @param {{ state: import("./types.js").GameState, setState: () => void, setError: (s: string) => void }} setup * @returns {void} */ export function handleWorldMapTruckDrop(e, setup) { e.preventDefault(); const el = e.currentTarget; if (el && el instanceof HTMLElement) el.classList.remove("dragover"); if (handleTruckDropBaby(e, setup)) return; if (handleTruckDropAnimal(e, setup)) return; handleTruckDropEgg(e, setup); } /** * @param {DragEvent} e * @param {{ state: import("./types.js").GameState, setState: () => void, setError: (s: string) => void, lastActionWasDropRef: { current: boolean } }} setup * @returns {boolean} */ function applyNurseryDrop(e, setup) { const nurseryCellKey = e.dataTransfer.getData("application/x-builazoo-nursery-cell-key"); if (!nurseryCellKey) return false; const [ok, result] = addMatureBabyToSale(setup.state, nurseryCellKey); if (!ok) { setup.setError(String(t.errorPrefix).replace("%s", errorMessage[result] ?? result)); playSound("error"); } else { setup.setError(""); playSound("sell"); const listing = setup.state.saleListings[setup.state.saleListings.length - 1]; if (getApiBase() && listing) { createSale({ animalId: listing.animalId, isBaby: true, price: listing.price, endAt: new Date(listing.endAt * 1000).toISOString(), reproductionScoreAtSale: listing.reproductionScoreAtSale }).then(({ id }) => { listing.serverId = id; setup.setState(); }).catch(() => {}); } } setup.lastActionWasDropRef.current = true; setup.setState(); return true; } /** * @param {DragEvent} e * @param {{ state: import("./types.js").GameState, setState: () => void, setError: (s: string) => void, lastActionWasDropRef: { current: boolean } }} setup * @returns {boolean} */ function applyReceptionDrop(e, setup) { const receptionCellKey = e.dataTransfer.getData("application/x-builazoo-reception-cell-key"); if (!receptionCellKey) return false; const [ok, result] = addReceptionAnimalToSale(setup.state, receptionCellKey); if (!ok) { setup.setError(String(t.errorPrefix).replace("%s", errorMessage[result] ?? result)); playSound("error"); } else { setup.setError(""); playSound("sell"); const listing = setup.state.saleListings[setup.state.saleListings.length - 1]; if (getApiBase() && listing) { createSale({ animalId: listing.animalId, isBaby: false, price: listing.price, endAt: new Date(listing.endAt * 1000).toISOString(), reproductionScoreAtSale: listing.reproductionScoreAtSale }).then(({ id }) => { listing.serverId = id; setup.setState(); }).catch(() => {}); } } setup.lastActionWasDropRef.current = true; setup.setState(); return true; } /** * @param {DragEvent} e * @param {{ state: import("./types.js").GameState, setState: () => void, setError: (s: string) => void, lastActionWasDropRef: { current: boolean } }} setup * @returns {boolean} */ function applyGridCellSell(e, setup) { const raw = e.dataTransfer.getData("text/plain"); if (!raw || !/^\d+_\d+$/.test(raw)) return false; const [sx, sy] = raw.split("_").map(Number); const [ok, result] = sellAnimalToNpc(setup.state, sx, sy); if (!ok) { setup.setError(String(t.sellFailed).replace("%s", errorMessage[result] ?? result)); playSound("error"); } else { setup.setError(""); playSound("sell"); setup.state.truckSale = { toZooId: pickSaleTargetZoo(setup.state), startAt: Date.now() }; } setup.lastActionWasDropRef.current = true; setup.setState(); return true; } /** * @param {DragEvent} e * @param {{ state: import("./types.js").GameState, setState: () => void, setError: (s: string) => void, lastActionWasDropRef: { current: boolean }, sellZoneJustDroppedRef: { current: boolean } }} setup * @returns {void} */ export function handleSellZoneDrop(e, setup) { e.preventDefault(); const el = e.currentTarget; if (el && el instanceof HTMLElement) el.classList.remove("dragover"); setup.sellZoneJustDroppedRef.current = true; if (applyNurseryDrop(e, setup)) return; if (applyReceptionDrop(e, setup)) return; applyGridCellSell(e, setup); }