Private
Public Access
1
0

feat(gameplay): Adding % bonus for planet type

This commit is contained in:
gauvainboiche
2026-03-30 15:43:43 +02:00
parent c0f66d8cc0
commit 3b229755f8
10 changed files with 548 additions and 81 deletions

View File

@@ -37,6 +37,31 @@ export async function initGameSchema() {
PRIMARY KEY (world_seed, team)
);
`);
await pool.query(`
CREATE TABLE IF NOT EXISTS team_element_bonus (
world_seed TEXT NOT NULL,
team TEXT NOT NULL CHECK (team IN ('blue', 'red')),
bonus DOUBLE PRECISION NOT NULL DEFAULT 0,
PRIMARY KEY (world_seed, team)
);
`);
await pool.query(`
CREATE TABLE IF NOT EXISTS db_metadata (
id SERIAL PRIMARY KEY,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
INSERT INTO db_metadata (created_at)
SELECT NOW() WHERE NOT EXISTS (SELECT 1 FROM db_metadata);
`);
await pool.query(`
CREATE TABLE IF NOT EXISTS victory_points (
id SERIAL PRIMARY KEY,
awarded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
world_seed TEXT NOT NULL,
team TEXT NOT NULL CHECK (team IN ('blue', 'red'))
);
CREATE INDEX IF NOT EXISTS idx_vp_team ON victory_points (team);
`);
await pool.query(`
ALTER TABLE grid_cells ADD COLUMN IF NOT EXISTS discovered_by TEXT;
UPDATE grid_cells SET discovered_by = 'blue' WHERE discovered_by IS NULL;
@@ -65,9 +90,30 @@ export async function ensureSeedEpoch() {
return worldSeed;
}
if (seedSlot !== lastSeedSlot) {
// Award a victory point to the team with the highest econ score before wiping
try {
const expiredSeed = `swg-${lastSeedSlot}`;
const econRows = await pool.query(
`SELECT team, score FROM team_econ_scores WHERE world_seed = $1`,
[expiredSeed]
);
const scores = { blue: 0, red: 0 };
for (const row of econRows.rows) scores[row.team] = Number(row.score);
if (scores.blue > 0 || scores.red > 0) {
const winner = scores.blue >= scores.red ? "blue" : "red";
await pool.query(
`INSERT INTO victory_points (world_seed, team) VALUES ($1, $2)`,
[expiredSeed, winner]
);
console.log(`[world] VP awarded to ${winner} for seed ${expiredSeed} (blue=${scores.blue.toFixed(3)}, red=${scores.red.toFixed(3)})`);
}
} catch (e) {
console.error("[world] VP award error:", e);
}
await pool.query("TRUNCATE grid_cells RESTART IDENTITY");
await pool.query("DELETE FROM team_cooldowns WHERE world_seed != $1", [worldSeed]);
await pool.query("DELETE FROM team_econ_scores WHERE world_seed != $1", [worldSeed]);
await pool.query("DELETE FROM team_element_bonus WHERE world_seed != $1", [worldSeed]);
console.log(`[world] Slot ${lastSeedSlot}${seedSlot}; grid wiped, old cooldowns cleared.`);
lastSeedSlot = seedSlot;
}
@@ -147,6 +193,46 @@ export async function addEconScore(worldSeed, team, delta) {
);
}
export async function getElementBonus(worldSeed) {
const { rows } = await pool.query(
`SELECT team, bonus FROM team_element_bonus WHERE world_seed = $1`,
[worldSeed]
);
const result = { blue: 0, red: 0 };
for (const row of rows) result[row.team] = Number(row.bonus);
return result;
}
export async function setElementBonus(worldSeed, team, bonus) {
await pool.query(
`INSERT INTO team_element_bonus (world_seed, team, bonus)
VALUES ($1, $2, $3)
ON CONFLICT (world_seed, team) DO UPDATE
SET bonus = EXCLUDED.bonus`,
[worldSeed, team, bonus]
);
}
// ── DB metadata ───────────────────────────────────────────────────────────────
export async function getDbCreatedAt() {
const { rows } = await pool.query(
`SELECT created_at FROM db_metadata ORDER BY id ASC LIMIT 1`
);
return rows[0]?.created_at ?? null;
}
// ── Victory points ────────────────────────────────────────────────────────────
export async function getVictoryPoints() {
const { rows } = await pool.query(
`SELECT team, COUNT(*) AS cnt FROM victory_points GROUP BY team`
);
const result = { blue: 0, red: 0 };
for (const row of rows) result[row.team] = Number(row.cnt);
return result;
}
// ── Scores ────────────────────────────────────────────────────────────────────
export async function getScores(worldSeed) {
@@ -157,4 +243,4 @@ export async function getScores(worldSeed) {
[worldSeed]
);
return rows;
}
}