2026-07-07 23:05:22 +02:00
|
|
|
import type { State } from './engine.ts';
|
|
|
|
|
|
|
|
|
|
export interface Upgrade {
|
|
|
|
|
id: string;
|
|
|
|
|
name: string;
|
|
|
|
|
desc: string;
|
|
|
|
|
cost: Partial<{ andakt: number; dread: number }>;
|
|
|
|
|
effect: (s: State) => void;
|
|
|
|
|
available: (s: State) => boolean;
|
|
|
|
|
once: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const UPGRADES: Upgrade[] = [
|
|
|
|
|
{
|
|
|
|
|
id: 'recruit_neighbor',
|
2026-07-07 23:13:54 +02:00
|
|
|
name: 'Rekrytera en troende',
|
2026-07-07 23:05:22 +02:00
|
|
|
desc: '+1 Troende. De undrade varför källarlamporna flimrade. Nu vet de.',
|
|
|
|
|
cost: { andakt: 20 },
|
2026-07-07 23:13:54 +02:00
|
|
|
effect: s => { s.troende += 1; s.andakt = Math.max(0, s.andakt - 20 * Math.max(1, s.troende - 2)); },
|
|
|
|
|
available: s => s.troende < 12,
|
2026-07-07 23:05:22 +02:00
|
|
|
once: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'first_meeting',
|
|
|
|
|
name: 'Källarmöte i Rosengård',
|
|
|
|
|
desc: 'Formalisera mötena. +1 andakt/s. Det luktar lite konstigt men ingen säger något.',
|
|
|
|
|
cost: { andakt: 30 },
|
|
|
|
|
effect: s => { s.andaktRate += 1; s.areas.rosengard = true; },
|
|
|
|
|
available: s => s.troende >= 2 && !s.upgrades.has('first_meeting'),
|
|
|
|
|
once: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'the_manuscript',
|
|
|
|
|
name: 'Översätt Skriften',
|
|
|
|
|
desc: 'Någon hittade ett dokument i en källarlokal vid Davidshallsgatan. Texten översätts bäst som "snälla sluta." Vi fortsätter.',
|
|
|
|
|
cost: { andakt: 80 },
|
|
|
|
|
effect: s => { s.dreadRate += 0.5; s.ritualUnlocked = true; },
|
|
|
|
|
available: s => s.troende >= 3 && s.upgrades.has('first_meeting') && !s.upgrades.has('the_manuscript'),
|
|
|
|
|
once: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'idol_under_bridge',
|
|
|
|
|
name: 'Idolen under bron',
|
|
|
|
|
desc: 'Vi placerade en idol under Øresundsbron vid nattens mörkaste timme. Danskarna la märke till det. De säger ingenting.',
|
|
|
|
|
cost: { andakt: 120, dread: 20 },
|
|
|
|
|
effect: s => { s.dreadRate += 1; s.andaktRate += 0.5; },
|
|
|
|
|
available: s => s.upgrades.has('the_manuscript') && !s.upgrades.has('idol_under_bridge'),
|
|
|
|
|
once: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'varnhem_circle',
|
|
|
|
|
name: 'Cirkeln på Värnhemstorget',
|
|
|
|
|
desc: 'Rita cirkeln. Använd krita. Det är viktigt att det är krita. Kommunen tvättar bort den varje morgon. Den är tillbaka varje kväll.',
|
|
|
|
|
cost: { andakt: 200, dread: 40 },
|
|
|
|
|
effect: s => { s.areas.varnhem = true; s.dreadRate += 1.5; s.kaosRate += 0.2; },
|
|
|
|
|
available: s => s.upgrades.has('idol_under_bridge') && s.dread >= 50 && !s.upgrades.has('varnhem_circle'),
|
|
|
|
|
once: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'torso_beacon',
|
|
|
|
|
name: 'Altaret vid Turning Torso',
|
|
|
|
|
desc: 'Byggnaden har alltid lyssnat. Nu ber vi den svara. Den gör det.',
|
|
|
|
|
cost: { andakt: 400, dread: 100 },
|
|
|
|
|
effect: s => { s.areas.torso = true; s.dreadRate += 3; s.ritualRate += 0.5; },
|
|
|
|
|
available: s => s.upgrades.has('varnhem_circle') && s.dread >= 100 && !s.upgrades.has('torso_beacon'),
|
|
|
|
|
once: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'grand_ritual_prep',
|
|
|
|
|
name: 'Förberedelser för Den Stora Ritualen',
|
|
|
|
|
desc: 'Allt har lett hit. Turning Torso pekar. Värnhemstorget väntar. Öresund drar sig tillbaka.',
|
|
|
|
|
cost: { andakt: 600, dread: 200 },
|
|
|
|
|
effect: s => { s.ritualRate += 2; s.kaosRate += 0.5; },
|
|
|
|
|
available: s => s.upgrades.has('torso_beacon') && s.ritual >= 50 && !s.upgrades.has('grand_ritual_prep'),
|
|
|
|
|
once: true,
|
|
|
|
|
},
|
|
|
|
|
];
|