diff --git a/assets/adventures/false-alarm/cover.svg b/assets/adventures/false-alarm/cover.svg new file mode 100644 index 0000000..f46e51d --- /dev/null +++ b/assets/adventures/false-alarm/cover.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TOP SECRET // DELTA GREEN + FALSE ALARM + OPERATION FILE · EYES ONLY + + NORTHERN MAINE · FAA RADAR STATION + diff --git a/assets/adventures/false-alarm/handout-entity.svg b/assets/adventures/false-alarm/handout-entity.svg new file mode 100644 index 0000000..33a67ae --- /dev/null +++ b/assets/adventures/false-alarm/handout-entity.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IT DOES NOT FIT THE SPACE IT OCCUPIES + THE TEAR — DO NOT SHOW UNTIL CLIMAX + diff --git a/assets/adventures/false-alarm/handout-radar-log.svg b/assets/adventures/false-alarm/handout-radar-log.svg new file mode 100644 index 0000000..294eaf7 --- /dev/null +++ b/assets/adventures/false-alarm/handout-radar-log.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + 4080120 + + + + + + + + + + + + + + + UNRESOLVED CONTACT + no transponder · no motion vector + + + FAA ASR-11 // TERMINAL LOG — FINAL FRAMES + CLASSIFICATION: “GEOMETRIC SHADOW” · alt: N/A · hdg: N/A + SYSTEM FAULT 0xDEAD — CORRUPTED DATA LOOP — CRASH + diff --git a/assets/adventures/false-alarm/handout-waveform.svg b/assets/adventures/false-alarm/handout-waveform.svg new file mode 100644 index 0000000..8b69874 --- /dev/null +++ b/assets/adventures/false-alarm/handout-waveform.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + ▁▂ SUB-CARRIER — HUMAN VOICE (rev. filter) ▂▁ + “ . . . it is saying our names . . . ” + + + FINAL TRANSMISSION — AUDIO CAPTURE + rhythmic oscillating static · 00:00:06 loop · SAN 0/1D4 to listen closely + amplitude (dB) vs time · buried voiceprint isolated at 38 Hz + diff --git a/assets/adventures/false-alarm/map-compound.svg b/assets/adventures/false-alarm/map-compound.svg new file mode 100644 index 0000000..16fd600 --- /dev/null +++ b/assets/adventures/false-alarm/map-compound.svg @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FENCE — CUT OUTWARD + + + + GATE (OPEN) + + + + + + + S.O. CRUISER + door open · frozen · engine dead + + + + + + + + + + + STRIDES ~8 FT APART + + + + + + + + EQUIPMENT + BUILDING + DOOR + + + + + + + + + + + + + RADAR DOME + geodesic · catwalk within + + + + + + FAA RADAR STA. — EXTERIOR + OPERATION: FALSE ALARM + Northern Maine · heavy snow · 1 sq = 5 ft + + diff --git a/assets/adventures/false-alarm/map-radar-dome.svg b/assets/adventures/false-alarm/map-radar-dome.svg new file mode 100644 index 0000000..d5eefe0 --- /dev/null +++ b/assets/adventures/false-alarm/map-radar-dome.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + UPPER CATWALK (pitch black) + + + + + + + + + CENTRAL TRANSMITTER + Vance is rewiring this + + + + + + + ↓ LADDER (from server room) + + + + + + + MAIN TRANSFORMER + manual overload = lethal shock + + + + smell: ozone · scorched copper + + + + + RADAR DOME — CATWALK + INTERIOR · TOTAL DARKNESS + bring your own light · 1 sq = 5 ft + + diff --git a/assets/adventures/false-alarm/map-server-room.svg b/assets/adventures/false-alarm/map-server-room.svg new file mode 100644 index 0000000..832ab6f --- /dev/null +++ b/assets/adventures/false-alarm/map-server-room.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + DOOR TO EXTERIOR + + + + + + + + + + + + + SERVER RACKS + + + + + + + + MAIN CONSOLE + + + + + + + DR. ROSTOVA — FROZEN SOLID + + + + + + + + BACKUP GENERATOR + failing · hums unsteadily + + + + + + + LADDER ↑ DOME + + + + + + EQUIPMENT BLDG — INTERIOR + SERVER ROOM · ~40°F + emergency power only · 1 sq = 5 ft + + diff --git a/assets/adventures/false-alarm/token-entity.svg b/assets/adventures/false-alarm/token-entity.svg new file mode 100644 index 0000000..3ad8d1f --- /dev/null +++ b/assets/adventures/false-alarm/token-entity.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/adventures/false-alarm/token-rostova.svg b/assets/adventures/false-alarm/token-rostova.svg new file mode 100644 index 0000000..df95296 --- /dev/null +++ b/assets/adventures/false-alarm/token-rostova.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/adventures/false-alarm/token-vance.svg b/assets/adventures/false-alarm/token-vance.svg new file mode 100644 index 0000000..860c082 --- /dev/null +++ b/assets/adventures/false-alarm/token-vance.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/gen-false-alarm.mjs b/build/gen-false-alarm.mjs new file mode 100644 index 0000000..80d944c --- /dev/null +++ b/build/gen-false-alarm.mjs @@ -0,0 +1,245 @@ +// Build the "Operation FALSE ALARM" adventure compendium (packs/false-alarm). +// Produces a single Adventure document with inline folders, actors, items, +// journal entries and scenes, then compiles it with foundryvtt-cli. +import { compilePack } from "/Users/timevans/Git/VRPG/foundry/vanity/node_modules/@foundryvtt/foundryvtt-cli/index.mjs"; +import fs from "fs"; +import path from "path"; + +const REPO = "/Users/timevans/Git/deltagreen2"; +const OUT = "/private/tmp/claude-501/-Users-timevans-Library-Application-Support-FoundryVTT/0078d6e6-126b-4f13-b7f4-86feaf7bfbbc/scratchpad/fasrc"; +const PACK = `${REPO}/packs/false-alarm`; +const A = "systems/deltagreen2/assets/adventures/false-alarm"; +const STATS = { systemId: "deltagreen2", systemVersion: "2.0.0" }; + +// deterministic 16-char id +function id(seed) { + let h = 0x811c9dc5; + for (let i = 0; i < seed.length; i++) { h ^= seed.charCodeAt(i); h = Math.imul(h, 0x01000193) >>> 0; } + let s = "", x = h; const c = "abcdefghijklmnopqrstuvwxyz0123456789"; + for (let i = 0; i < 16; i++) { x = Math.imul(x ^ (x >>> 15), 0x2c1b3c6d) >>> 0; s += c[x % c.length]; } + return s; +} +const GREEN = "#556b2f"; + +// ---------------------------------------------------------------- folders +function folder(name, type) { + return { _id: id(`fa-folder-${type}-${name}`), name, type, folder: null, sort: 0, color: GREEN, description: "", flags: {}, _stats: STATS }; +} +const fActors = folder("Operation FALSE ALARM", "Actor"); +const fItems = folder("Operation FALSE ALARM", "Item"); +const fJournal = folder("Operation FALSE ALARM", "JournalEntry"); +const fScenes = folder("Operation FALSE ALARM", "Scene"); +const folders = [fActors, fItems, fJournal, fScenes]; + +// ---------------------------------------------------------------- items +function skillsAllZero() { return {}; } // rely on schema defaults +let itemSort = 0; +function gearItem(name, icon, expense, desc) { + return { + _id: id(`fa-item-${name}`), name, type: "gear", + img: `systems/deltagreen2/assets/icons/${icon}.svg`, + system: { description: `

${desc}

`, equipped: false, expense }, + folder: fItems._id, sort: (itemSort += 100), ownership: { default: 0 }, flags: {}, effects: [], _stats: STATS, + }; +} +function weaponItem(name, icon, sys, desc) { + return { + _id: id(`fa-item-${name}`), name, type: "weapon", + img: `systems/deltagreen2/assets/icons/${icon}.svg`, + system: { description: `

${desc}

`, skill: "firearms", range: "15M", damage: "1D10", armorPiercing: 0, lethality: 0, isLethal: false, killRadius: "", ammo: 0, ammoMax: 0, expense: "Standard", equipped: false, ...sys }, + folder: fItems._id, sort: (itemSort += 100), ownership: { default: 0 }, flags: {}, effects: [], _stats: STATS, + }; +} +const items = [ + weaponItem("Deputy Vance's Service Pistol", "glock", + { skill: "firearms", damage: "1D10", ammo: 12, ammoMax: 15, range: "15M" }, + "A .40 S&W duty pistol, found in the cruiser footwell. Three rounds are missing and there are no bullet holes in the car. Whatever he fired at, he fired at outside — or at nothing. Evidence."), + weaponItem("Heavy Pipe Wrench", "forcible-entry-tool", + { skill: "melee_weapons", damage: "1D10+2", range: "0M", ammo: 0, ammoMax: 0 }, + "A two-foot steel maintenance wrench. In the Changed Vance's grip it swings with impossible speed. Melee weapon."), + gearItem("Corrupted Data Drive", "software", "Standard", + "The radar facility's primary log drive. Its final frames recorded a “geometric shadow” hovering over the dish — not an aircraft. Must be wiped or destroyed as part of the cover-up (see the FAA cloud backup). Computer Science to read; SIGINT/Science to analyse the audio."), + gearItem("Dr. Rostova's Keycard & ID", "papers", "Trivial", + "FAA contractor credentials for Dr. Elena Rostova, sole on-site technician. Opens the equipment building and the console. Her emergency contact is a sister in Vermont — a loose end for the cover-up."), + gearItem("Thermite Charge", "anfo", "Unusual", + "Incendiary supplied for sanitation. Burns hot enough to reduce a frozen body — or a data drive — to slag. Needed to dispose of Dr. Rostova's remains without leaving forensic questions."), + gearItem("Cold-Weather Field Kit", "camping-gear", "Standard", + "Parkas, chemical heat packs, headlamps and rope. The dome interior is pitch black and the whole site is well below freezing; Agents without light and warmth accrue penalties over a long night."), +]; + +// ---------------------------------------------------------------- actors +function npcActor({ key, name, type, img, token, stats, health, skills, notes, shortDescription, san, weapons }) { + const _id = id(`fa-actor-${key}`); + const sys = { + statistics: Object.fromEntries(Object.entries(stats).map(([k, v]) => [k, { value: v }])), + health: { value: health, min: 0, max: health }, + wp: { value: stats.pow, min: 0, max: stats.pow }, + skills: Object.fromEntries(Object.entries(skills || {}).map(([k, v]) => [k, { proficiency: v }])), + notes, shortDescription, showUntrainedSkills: false, + }; + if (type === "npc") sys.sanity = { value: san ?? 0, currentBreakingPoint: 101 }; + else sys.sanity = { notes: "", failedLoss: san?.failed ?? "1D4", successLoss: san?.success ?? "1" }; + const embeddedItems = (weapons || []).map((w) => { + const wid = id(`fa-actor-${key}-wpn-${w.name}`); + return { _id: wid, _key: `!actors.items!${_id}.${wid}`, name: w.name, type: "weapon", + img: `systems/deltagreen2/assets/icons/${w.icon}.svg`, + system: { description: "", skill: w.skill, range: w.range || "0M", damage: w.damage, armorPiercing: w.ap || 0, lethality: w.lethality || 0, isLethal: !!w.lethality, killRadius: "", ammo: w.ammo || 0, ammoMax: w.ammoMax || 0, expense: "Standard", equipped: true } }; + }); + return { + _id, _key: `!actors!${_id}`, name, type, img, + system: sys, + prototypeToken: { name, texture: { src: token, anchorX: 0.5, anchorY: 0.5, fit: "contain", scaleX: 1, scaleY: 1 }, width: 1, height: 1, displayName: 20, disposition: type === "npc" ? 0 : -1, actorLink: false }, + items: embeddedItems, effects: [], folder: fActors._id, sort: 0, ownership: { default: 0 }, flags: {}, _stats: STATS, + }; +} + +const aRostova = npcActor({ + key: "rostova", name: "Dr. Elena Rostova", type: "npc", + img: `${A}/token-rostova.svg`, token: `${A}/token-rostova.svg`, + stats: { str: 10, con: 10, dex: 11, int: 15, pow: 12, cha: 11 }, health: 10, san: 0, + skills: { computer_science: 70, science: 0, sigint: 40, first_aid: 30, alertness: 40 }, + shortDescription: "FAA facility technician — deceased, flash-frozen.", + notes: "

Dr. Elena Rostova (deceased)

The facility's sole on-site technician, found slumped over the main console frozen solid despite the room reading roughly 40°F. Her eyes are wide; her lips are torn away from her teeth in a rictus. There is no external cause of death a coroner could accept.

What she knew: She logged the corrupted radar return and played back the final transmission before she died. The audio killed her — or something reached back down it. She is a clue, not a combatant.

Cover-up: her remains must be burned (Thermite Charge) and her FAA records and next-of-kin contact managed.

", +}); + +const aVance = npcActor({ + key: "vance", name: "Deputy Marcus Vance (Changed)", type: "unnatural", + img: `${A}/token-vance.svg`, token: `${A}/token-vance.svg`, + stats: { str: 17, con: 16, dex: 16, int: 6, pow: 15, cha: 3 }, health: 16, + san: { failed: "1D6", success: "1" }, + skills: { alertness: 60, athletics: 70, dodge: 50, melee_weapons: 65, unarmed_combat: 55 }, + shortDescription: "The blinded deputy — no longer entirely human.", + weapons: [{ name: "Pipe Wrench (frenzied)", icon: "forcible-entry-tool", skill: "melee_weapons", damage: "1D10+2", range: "0M" }], + notes: "

Deputy Marcus Vance — Changed

Six hours ago a small-town deputy. Now he is blind — he gouged out his own eyes — yet moves with terrifying, jerky speed, rewiring the central transmitter by feel to broadcast the static loop at maximum amplification. His jaw unhinges abnormally when he screams: he recites the radar's technical manual backward.

Combat

Sanity

Witnessing the Changed Vance costs 1/1D6 SAN. He can still be dropped by gunfire — he is flesh — but doing so does not stop the transmitter he has already wired.

", +}); + +const aTear = npcActor({ + key: "tear", name: "The Tear (Static Between Stations)", type: "unnatural", + img: `${A}/token-entity.svg`, token: `${A}/token-entity.svg`, + stats: { str: 20, con: 30, dex: 20, int: 20, pow: 25, cha: 1 }, health: 30, + san: { failed: "1D20", success: "1D6" }, + skills: { alertness: 90, dodge: 80 }, + shortDescription: "An extradimensional entity that mimics radio frequencies.", + notes: "

The Tear — the Static Between Stations

Not a creature so much as a place that should not touch this one: a shifting, non-Euclidean fractal silhouette that bleeds through the centre of the radar dish when the broadcast peaks. The air turns static-charged; hair stands on end; the temperature crashes.

Rules

The only resolution: cut the power

The tear cannot be fought, only closed by killing the broadcast:

When power dies the tear snaps back, and the vacuum implodes the dome.

", +}); +const actors = [aRostova, aVance, aTear]; + +// ---------------------------------------------------------------- journals +let jSort = 0; +function textPage(name, html, level = 1) { + return { _id: id(`fa-page-${name}`), name, type: "text", title: { show: true, level }, + text: { format: 1, content: html }, image: {}, video: { controls: true, volume: 0.5 }, src: null, + system: {}, sort: 0, ownership: { default: -1 }, flags: {}, _stats: STATS }; +} +function imagePage(name, src, caption) { + return { _id: id(`fa-page-img-${name}`), name, type: "image", title: { show: true, level: 1 }, + image: { caption: caption || "" }, text: { format: 1, content: "" }, src, system: {}, sort: 0, ownership: { default: -1 }, flags: {}, _stats: STATS }; +} +function journal(key, name, pages) { + return { _id: id(`fa-journal-${key}`), name, pages: pages.map((p, i) => ({ ...p, sort: (i + 1) * 100 })), + folder: fJournal._id, sort: (jSort += 100), ownership: { default: 0 }, flags: {}, _stats: STATS, + _key: undefined }; +} + +const journal_briefing = journal("01-briefing", "① BRIEFING — Operation FALSE ALARM", [ + imagePage("Operation File", `${A}/cover.svg`, "TOP SECRET // DELTA GREEN — EYES ONLY"), + textPage("Your Cover & Your Handler", + "

You are federal law-enforcement officers and specialists. Your Delta Green handler in A-Cell has pulled you off the books for the night. Cover story: a joint FAA / NWS team responding to a “severe weather generator failure” at a remote automated radar station.

You were briefed by phone. There was no paperwork. There will be none.

"), + textPage("The Hook", + "

Six hours ago, a standard FAA radar facility in the snowbound wilderness of northern Maine abruptly went offline — after transmitting a corrupted data loop. A local sheriff's deputy, Marcus Vance, drove out to investigate. He never checked back in.

"), + textPage("The Mission", + "
  1. Erase any unnatural data — the facility log and the FAA's remote cloud backups.
  2. Recover or terminate Deputy Vance.
  3. Secure the facility.
  4. Cover it up as a severe weather-generator failure.

Time, weather, and whatever is out there are all against you. Runtime: 3–4 hours.

"), +]); + +const journal_radar = journal("02-radar", "② HANDOUT — Radar Terminal Log", [ + imagePage("ASR-11 Final Frames", `${A}/handout-radar-log.svg`, "The last thing the dish saw before it crashed."), + textPage("What it shows", + "

Show players on a Computer Science success accessing the data log. The radar did not track a physical aircraft. It tracked a “geometric shadow” that hovered directly over the dish — no transponder, no altitude, no motion vector — and then the system crashed into a corrupted loop.

"), +]); + +const journal_audio = journal("03-audio", "③ HANDOUT — Final Transmission (Audio)", [ + imagePage("Static Capture", `${A}/handout-waveform.svg`, "Rhythmic, oscillating static — a six-second loop."), + textPage("Listening closely", + "

Playing back the audio from the final transmission (SIGINT or Science) reveals a rhythmic, oscillating static. Listening to it closely requires a Sanity check (0/1D4).

On a success, the listener notices a hidden, low-frequency human voice buried under the static — whispering the Agents' own names. (Handler: use the players' real character names. Whisper them.)

"), +]); + +const journal_tear = journal("04-tear", "④ HANDOUT — THE TEAR (climax only)", [ + imagePage("The Manifestation", `${A}/handout-entity.svg`, "DO NOT REVEAL until the broadcast peaks."), + textPage("Reveal notes", + "

Hold this image back until the radar dish activates and the entity bleeds through. The air is static-charged, everyone's hair stands on end, and a shifting, non-Euclidean fractal silhouette tears open at the centre of the dish. Presence costs 1D6/1D20 SAN. Bullets pass through and warp uselessly. See GM — NPCs & The Threat.

"), +]); + +const journal_gm_scenes = journal("05-gm-scenes", "⑤ GM — Scene Guide & Clues", [ + textPage("Scene 1 — The Arrival", + "

A fenced compound: one concrete equipment building and a massive geodesic radar dome over the pines. Heavy snow.

"), + textPage("Scene 2 — The Server Room", + "

The concrete building runs on a failing backup generator that hums unsteadily. Dr. Elena Rostova is dead at the console: frozen solid in a 40°F room, eyes wide, lips torn from her teeth.

"), + textPage("Scene 3 — The Radar Dome", + "

The upper catwalk inside the dome is pitch black, reeking of ozone and scorched copper. Deputy Vance is here — blind, self-mutilated, frantically rewiring the transmitter to broadcast the static loop at maximum amplification.

"), + textPage("The Climax — The Broadcast", + "

Whether Vance succeeds or the Agents trigger it during the fight, the dish activates, spins wildly, and projects a beam of invisible localised EM radiation. The Tear bleeds through (Handout ④).

It cannot be shot. To close it, cut the primary power — blow the backup generator outside, or manually overload the main transformer inside (lethal shock + 1D6/1D20 SAN). When power dies, the tear snaps back and the vacuum implodes the dome.

"), +]); + +const journal_gm_threat = journal("06-gm-threat", "⑥ GM — NPCs & The Threat", [ + textPage("Dr. Elena Rostova", aRostova.system.notes), + textPage("Deputy Marcus Vance (Changed)", aVance.system.notes), + textPage("The Tear", aTear.system.notes), +]); + +const journal_gm_after = journal("07-gm-after", "⑦ GM — Cover-Up & Aftermath", [ + textPage("Loose ends", + ""), + textPage("Sanity rewards", + "

Eliminating the threat grants +1D4 SAN, minus any losses from collateral damage or a failed cover-up. An Agent who overloaded the transformer by hand carries the worst of it — if they lived.

"), +]); + +const journalArr = [journal_briefing, journal_radar, journal_audio, journal_tear, journal_gm_scenes, journal_gm_threat, journal_gm_after] + .map((j) => { delete j._key; return j; }); + +// ---------------------------------------------------------------- scenes +function gridCfg() { return { type: 1, size: 100, style: "solidLines", thickness: 1, color: "#59ff87", alpha: 0.12, distance: 5, units: "ft" }; } +function sceneToken(actor, x, y, hidden = false) { + const tid = id(`fa-tok-${actor._id}-${x}-${y}`); + return { _id: tid, name: actor.name, actorId: actor._id, actorLink: false, + texture: { src: actor.prototypeToken.texture.src, anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1, fit: "contain" }, + x, y, width: 1, height: 1, hidden, disposition: actor.prototypeToken.disposition, displayName: 20, + sight: { enabled: false }, sort: 0, flags: {} }; +} +function scene(key, name, bg, w, h, tokens, notesFlag) { + return { + _id: id(`fa-scene-${key}`), name, active: false, navigation: true, navName: "", + width: w, height: h, padding: 0.25, background: { src: `${A}/${bg}` }, foreground: null, + grid: gridCfg(), initial: { x: Math.round(w / 2), y: Math.round(h / 2), scale: 0.5 }, + backgroundColor: "#050708", tokenVision: false, fogExploration: false, globalLight: true, darkness: 0, + tokens, walls: [], lights: [], sounds: [], templates: [], notes: [], drawings: [], tiles: [], + folder: fScenes._id, sort: 0, ownership: { default: 0 }, flags: {}, _stats: STATS, + }; +} +const scenes = [ + scene("1-arrival", "Scene 1 — The Arrival (Compound)", "map-compound.svg", 2600, 1800, []), + scene("2-server", "Scene 2 — The Server Room", "map-server-room.svg", 1800, 1400, [sceneToken(aRostova, 900, 780)]), + scene("3-dome", "Scene 3 — The Radar Dome", "map-radar-dome.svg", 2000, 2000, + [sceneToken(aVance, 1000, 1000), sceneToken(aTear, 1000, 1000, true)]), +]; + +// ---------------------------------------------------------------- adventure +const advId = id("fa-adventure-false-alarm"); +const adventure = { + _id: advId, _key: `!adventures!${advId}`, + name: "Operation FALSE ALARM", + img: `${A}/cover.svg`, + caption: "A tight 3–4 hour Delta Green shotgun scenario — a remote Maine radar station, and the static between stations.", + description: "

Operation FALSE ALARM

A remote automated FAA radar station in snowbound northern Maine has gone dark after transmitting a corrupted data loop, and the deputy who went to look never came back. An extradimensional entity is mimicking radio frequencies, drawing humans into the freezing dark.

Importing this adventure creates four Operation FALSE ALARM folders — Actors, Items, Journals and Scenes. Start players in the ① Briefing journal; run the three scenes in order; keep the GM journals (⑤⑥⑦) for yourself. Handout ④ (The Tear) is for the climax only.

3–4 hours · 4–6 Agents.

", + sort: 0, folder: null, + folders, actors, items, journal: journalArr, scenes, + cards: [], playlists: [], tables: [], macros: [], combats: [], + flags: {}, _stats: STATS, +}; + +// ---------------------------------------------------------------- compile +fs.rmSync(OUT, { recursive: true, force: true }); +fs.mkdirSync(OUT, { recursive: true }); +fs.writeFileSync(path.join(OUT, "operation-false-alarm.json"), JSON.stringify(adventure, null, 2)); +fs.rmSync(PACK, { recursive: true, force: true }); +await compilePack(OUT, PACK, { yaml: false }); +console.log(`Compiled adventure: ${actors.length} actors, ${items.length} items, ${journalArr.length} journals, ${scenes.length} scenes, ${folders.length} folders.`); diff --git a/packs/false-alarm/000004.log b/packs/false-alarm/000004.log new file mode 100644 index 0000000..e69de29 diff --git a/packs/false-alarm/000005.ldb b/packs/false-alarm/000005.ldb new file mode 100644 index 0000000..f270966 Binary files /dev/null and b/packs/false-alarm/000005.ldb differ diff --git a/packs/false-alarm/CURRENT b/packs/false-alarm/CURRENT new file mode 100644 index 0000000..1a84852 --- /dev/null +++ b/packs/false-alarm/CURRENT @@ -0,0 +1 @@ +MANIFEST-000002 diff --git a/packs/false-alarm/LOCK b/packs/false-alarm/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/packs/false-alarm/LOG b/packs/false-alarm/LOG new file mode 100644 index 0000000..939b2e4 --- /dev/null +++ b/packs/false-alarm/LOG @@ -0,0 +1,5 @@ +2026/07/15-23:34:13.141809 1715e7000 Delete type=3 #1 +2026/07/15-23:34:13.143714 171e7f000 Level-0 table #5: started +2026/07/15-23:34:13.144042 171e7f000 Level-0 table #5: 12085 bytes OK +2026/07/15-23:34:13.144148 171e7f000 Delete type=0 #3 +2026/07/15-23:34:13.144222 171e7f000 Manual compaction at level-0 from '!adventures!5zf355zpx5s1ux56' @ 72057594037927935 : 1 .. '!adventures!5zf355zpx5s1ux56' @ 0 : 0; will stop at (end) diff --git a/packs/false-alarm/MANIFEST-000002 b/packs/false-alarm/MANIFEST-000002 new file mode 100644 index 0000000..3195b93 Binary files /dev/null and b/packs/false-alarm/MANIFEST-000002 differ diff --git a/system.json b/system.json index f379ffc..b8c58d8 100644 --- a/system.json +++ b/system.json @@ -125,6 +125,18 @@ } ], "packs": [ + { + "name": "false-alarm", + "label": "Operation FALSE ALARM (Adventure)", + "system": "deltagreen2", + "path": "packs/false-alarm", + "type": "Adventure", + "flags": {}, + "ownership": { + "PLAYER": "LIMITED", + "ASSISTANT": "OWNER" + } + }, { "name": "firearms", "label": "Firearms",