@dreadwood-types/types 0.1.266 → 0.1.267

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,491 @@
1
+ /**
2
+ * The Grove's centre in world tiles, written out here (not imported from rotwoodGrove.ts, which reads zones.ts, which reads the safe pockets,
3
+ * which read this file: a cycle). scripts/heartwood-hunt-test.mjs pins them equal to GROVE_CX and GROVE_CZ.
4
+ */
5
+ const GROVE_CX = 330;
6
+ const GROVE_CZ = 380;
7
+ const MINUTE = 60_000;
8
+ const HOUR = 60 * MINUTE;
9
+ // ---- the clock ----------------------------------------------------------------------------------------------------------
10
+ /** Time from one round's start to the next. */
11
+ export const HUNT_PERIOD_MS = 3 * HOUR;
12
+ /** Round n starts this long after the n-th period mark (Ringstone fights start at 0, 60 and 90 minutes; the Derby at :40 of even hours). */
13
+ export const HUNT_OFFSET_MS = 130 * MINUTE;
14
+ /** How long the heartwood stands. */
15
+ export const HUNT_ROUND_MS = 15 * MINUTE;
16
+ /** How long the result board stays up after the round. */
17
+ export const HUNT_RESULTS_MS = 5 * MINUTE;
18
+ /** The warning before the round starts, and the warning before it ends. */
19
+ export const HUNT_SOON_MS = 10 * MINUTE;
20
+ export const HUNT_LAST_MS = 2 * MINUTE;
21
+ export const HUNT_STAGES = ['idle', 'soon', 'open', 'last', 'results'];
22
+ export function isHuntStage(s) {
23
+ return typeof s === 'string' && HUNT_STAGES.includes(s);
24
+ }
25
+ export function huntStartOf(slot) {
26
+ return slot * HUNT_PERIOD_MS + HUNT_OFFSET_MS;
27
+ }
28
+ export function huntEndOf(slot) {
29
+ return huntStartOf(slot) + HUNT_ROUND_MS;
30
+ }
31
+ export function huntClockAt(now) {
32
+ const k = Math.floor((now - HUNT_OFFSET_MS) / HUNT_PERIOD_MS);
33
+ const elapsed = now - huntStartOf(k);
34
+ if (elapsed < HUNT_ROUND_MS) {
35
+ const msToEnd = HUNT_ROUND_MS - elapsed;
36
+ return { slot: k, stage: msToEnd <= HUNT_LAST_MS ? 'last' : 'open', msToStart: 0, msToEnd };
37
+ }
38
+ if (elapsed < HUNT_ROUND_MS + HUNT_RESULTS_MS)
39
+ return { slot: k, stage: 'results', msToStart: 0, msToEnd: 0 };
40
+ const next = k + 1;
41
+ const msToStart = huntStartOf(next) - now;
42
+ return { slot: next, stage: msToStart <= HUNT_SOON_MS ? 'soon' : 'idle', msToStart, msToEnd: huntEndOf(next) - now };
43
+ }
44
+ /** True while the tree stands and cuts and brood kills count. */
45
+ export function huntIsOpen(stage) {
46
+ return stage === 'open' || stage === 'last';
47
+ }
48
+ /** The next round to start strictly after `now` (for the login line): its slot and start. */
49
+ export function huntNextRound(now) {
50
+ const k = Math.floor((now - HUNT_OFFSET_MS) / HUNT_PERIOD_MS);
51
+ const slot = huntStartOf(k) > now ? k : k + 1;
52
+ return { slot, startsAt: huntStartOf(slot) };
53
+ }
54
+ /** The UTC day a time falls in (the daily paid-rounds cap resets at midnight UTC). */
55
+ export function huntDayOf(now) {
56
+ return Math.floor(now / (24 * HOUR));
57
+ }
58
+ function span(ms) {
59
+ const mins = Math.max(1, Math.round(ms / MINUTE));
60
+ if (mins < 60)
61
+ return `${mins} minute${mins === 1 ? '' : 's'}`;
62
+ const h = Math.floor(mins / 60);
63
+ const m = mins % 60;
64
+ return m === 0 ? `${h} hour${h === 1 ? '' : 's'}` : `${h} h ${m} min`;
65
+ }
66
+ // ---- the places ---------------------------------------------------------------------------------------------------------
67
+ /**
68
+ * Where the heartwood can rise (world tiles, inside the Grove's clearing, clear of every prop and of the Ent's path; the backend
69
+ * smoke pins each one standable with a standable ring round it). Five places, the tree never in the same one twice running.
70
+ */
71
+ export const HUNT_SPOTS = [
72
+ { id: 'west-lawn', x: GROVE_CX - 6, z: GROVE_CZ - 7, label: 'the clearing\'s north-west lawn' },
73
+ { id: 'east-lawn', x: GROVE_CX + 6, z: GROVE_CZ - 7, label: 'the clearing\'s north-east lawn' },
74
+ { id: 'west-hollow', x: GROVE_CX - 8, z: GROVE_CZ + 2, label: 'the western hollow, past the fallen logs' },
75
+ { id: 'east-hollow', x: GROVE_CX + 9, z: GROVE_CZ - 1, label: 'the eastern hollow, past the root arch' },
76
+ { id: 'north-glade', x: GROVE_CX + 1, z: GROVE_CZ - 9, label: 'the north glade, behind the Ent' },
77
+ ];
78
+ /** The place of a round. Consecutive rounds never share one (the step is 2 inside a block of five rounds and 3 across a block edge). */
79
+ export function huntSpotFor(slot) {
80
+ const n = HUNT_SPOTS.length;
81
+ const s = Math.floor(slot);
82
+ const idx = (((2 * s + Math.floor(s / n)) % n) + n) % n;
83
+ return HUNT_SPOTS[idx];
84
+ }
85
+ /** The tree: an ash (the ladder's level-30 wood) drawn large; the server places it while a round is on and takes it away after. */
86
+ export const HUNT_TREE_ID = 'hh-tree';
87
+ export const HUNT_TREE_STYLE = 'ash';
88
+ export const HUNT_TREE_SCALE = 1.8;
89
+ // ---- the cutting --------------------------------------------------------------------------------------------------------
90
+ /** Woodwork needed to take a swing at the heartwood. */
91
+ export const HUNT_MIN_WOODWORK = 24;
92
+ /** The tree's level in the felling roll (types woodwork.ts woodcutSuccessChance): between alder (25) and ash (30). */
93
+ export const HUNT_TREE_LEVEL = 28;
94
+ /** Successful cuts, from everyone together, that fell the heartwood. PLACEHOLDER. */
95
+ export const HUNT_TREE_CUTS = 90;
96
+ /** The log a cut yields (alder is the Woodwork ladder's level-25 wood: a placeholder for rotwood), and how many a player gets per round. */
97
+ export const HUNT_CUT_LOG = 'alderwood';
98
+ export const HUNT_LOGS_PER_PLAYER = 12;
99
+ /** Woodwork XP for a scored cut. */
100
+ export const HUNT_CUT_XP = 30;
101
+ // ---- the scoring --------------------------------------------------------------------------------------------------------
102
+ export const HUNT_CUT_POINTS = 2;
103
+ export const HUNT_KILL_POINTS = 3;
104
+ /** Past these a cut or a kill still helps (the tree still falls) but scores nothing more. */
105
+ export const HUNT_CUT_CAP = 16;
106
+ export const HUNT_KILL_CAP = 8;
107
+ /** The least score that counts as having taken part (3 cuts, or 2 kills). Below it: no prize, no mark. */
108
+ export const HUNT_MIN_SCORE = 6;
109
+ /** Podium prizes need at least this many different accounts above the minimum, and the tree felled. */
110
+ export const HUNT_MIN_HUNTERS = 3;
111
+ /** Paid rounds per account per UTC day (alts and shared accounts cannot farm every round of the day). */
112
+ export const HUNT_DAILY_PAID_ROUNDS = 4;
113
+ export function huntScore(cuts, kills) {
114
+ return Math.min(Math.max(0, cuts), HUNT_CUT_CAP) * HUNT_CUT_POINTS + Math.min(Math.max(0, kills), HUNT_KILL_CAP) * HUNT_KILL_POINTS;
115
+ }
116
+ export function huntEntryScore(e) {
117
+ return huntScore(e.cuts, e.kills);
118
+ }
119
+ function baseEntry(entry, who, at) {
120
+ return entry ?? { key: who.key, account: who.account, name: who.name, cuts: 0, kills: 0, logs: 0, at };
121
+ }
122
+ /** One successful cut by this character. `gaveLog` is true when a log went to the bag. Returns a new entry (the old is untouched). */
123
+ export function huntWithCut(entry, who, gaveLog, at) {
124
+ const base = baseEntry(entry, who, at);
125
+ const next = { ...base, name: who.name, cuts: base.cuts + 1, logs: base.logs + (gaveLog ? 1 : 0) };
126
+ return { ...next, at: huntEntryScore(next) > huntEntryScore(base) ? at : base.at };
127
+ }
128
+ /** One brood kill by this character. */
129
+ export function huntWithKill(entry, who, at) {
130
+ const base = baseEntry(entry, who, at);
131
+ const next = { ...base, name: who.name, kills: base.kills + 1 };
132
+ return { ...next, at: huntEntryScore(next) > huntEntryScore(base) ? at : base.at };
133
+ }
134
+ /** Does a log still go to this character's bag (before the cut that would give it)? */
135
+ export function huntLogDue(entry) {
136
+ return (entry?.logs ?? 0) < HUNT_LOGS_PER_PLAYER;
137
+ }
138
+ export function huntQualifies(e) {
139
+ return huntEntryScore(e) >= HUNT_MIN_SCORE;
140
+ }
141
+ function accountOf(e) {
142
+ return e.account || `key:${e.key}`;
143
+ }
144
+ /**
145
+ * The ranking: higher score first, then whoever reached it first, then the key (a total order a test can pin). One place per ACCOUNT:
146
+ * of an account's characters only the best-placed one is listed. Entries below the minimum score are not ranked.
147
+ */
148
+ export function huntRanking(entries) {
149
+ const sorted = entries
150
+ .filter(huntQualifies)
151
+ .sort((a, b) => {
152
+ const sa = huntEntryScore(a);
153
+ const sb = huntEntryScore(b);
154
+ if (sb !== sa)
155
+ return sb - sa;
156
+ if (a.at !== b.at)
157
+ return a.at - b.at;
158
+ return a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
159
+ });
160
+ const seen = new Set();
161
+ const out = [];
162
+ for (const e of sorted) {
163
+ const acc = accountOf(e);
164
+ if (seen.has(acc))
165
+ continue;
166
+ seen.add(acc);
167
+ out.push(e);
168
+ }
169
+ return out;
170
+ }
171
+ /** The 1-based place of a character in the ranking (ranked entries only), or 0. */
172
+ export function huntPlaceOf(entries, key) {
173
+ const i = huntRanking(entries).findIndex((e) => e.key === key);
174
+ return i < 0 ? 0 : i + 1;
175
+ }
176
+ const RIBBONS = ['red', 'blue', 'bronze'];
177
+ export const HUNT_RIBBON_LABEL = { red: 'Red Ribbon', blue: 'Blue Ribbon', bronze: 'Bronze Ribbon' };
178
+ /** PLACEHOLDER prizes by place (felled tree only): Woodwork XP, Explorer XP and ash logs. */
179
+ export const HUNT_PODIUM_PRIZES = [
180
+ { woodworkXp: 600, explorerXp: 100, ash: 3 },
181
+ { woodworkXp: 400, explorerXp: 70, ash: 2 },
182
+ { woodworkXp: 250, explorerXp: 40, ash: 1 },
183
+ ];
184
+ /** Everyone paid who qualified. A tree that stood to the end halves the XP and gives no logs. */
185
+ export const HUNT_PARTICIPATION = { woodworkXp: 120, explorerXp: 20, alder: 2 };
186
+ /** Ledger marks (types explorerLedger.ts `hunt` page) a result can write. */
187
+ export const HUNT_MARK_ENTERED = 'hunt:entered';
188
+ export const HUNT_MARK_FELLED = 'hunt:felled';
189
+ export const HUNT_MARK_CUTTER = 'hunt:cutter';
190
+ export const HUNT_MARK_GUARD = 'hunt:guard';
191
+ export const HUNT_MARK_RIBBON = { red: 'hunt:red', blue: 'hunt:blue', bronze: 'hunt:bronze' };
192
+ /** Paid rounds this account has had on this UTC day. */
193
+ export function huntPaidToday(paid, account, day) {
194
+ const p = paid[account];
195
+ return p && p.day === day ? p.n : 0;
196
+ }
197
+ /** The record after one more paid round for these accounts (old days dropped). Returns a new object. */
198
+ export function huntWithPaid(paid, accounts, day) {
199
+ const next = {};
200
+ for (const [acc, p] of Object.entries(paid))
201
+ if (p.day === day)
202
+ next[acc] = p;
203
+ for (const acc of accounts)
204
+ next[acc] = { day, n: huntPaidToday(next, acc, day) + 1 };
205
+ return next;
206
+ }
207
+ /**
208
+ * Everything a finished round pays, by character key. One prize per account (the ranking lists an account once). An account that has
209
+ * had its four paid rounds today is skipped (the podium moves up to the next account). Pure, so a restart that finalises a round late
210
+ * pays exactly what the clock-time finalise would have.
211
+ */
212
+ export function huntPrizes(entries, input) {
213
+ const out = new Map();
214
+ const ranked = huntRanking(entries);
215
+ if (ranked.length === 0)
216
+ return out;
217
+ const eligible = ranked.filter((e) => huntPaidToday(input.paid, accountOf(e), input.day) < HUNT_DAILY_PAID_ROUNDS);
218
+ const podium = input.felled && ranked.length >= HUNT_MIN_HUNTERS;
219
+ const half = input.felled ? 1 : 0.5;
220
+ for (const e of eligible) {
221
+ const prize = {
222
+ woodworkXp: Math.floor(HUNT_PARTICIPATION.woodworkXp * half),
223
+ explorerXp: Math.floor(HUNT_PARTICIPATION.explorerXp * half),
224
+ items: input.felled ? [{ kind: HUNT_CUT_LOG, qty: HUNT_PARTICIPATION.alder }] : [],
225
+ marks: [HUNT_MARK_ENTERED],
226
+ text: '',
227
+ };
228
+ if (input.felled)
229
+ prize.marks.push(HUNT_MARK_FELLED);
230
+ if (e.cuts >= HUNT_CUT_CAP)
231
+ prize.marks.push(HUNT_MARK_CUTTER);
232
+ if (e.kills >= HUNT_KILL_CAP)
233
+ prize.marks.push(HUNT_MARK_GUARD);
234
+ out.set(e.key, prize);
235
+ }
236
+ const notes = new Map();
237
+ if (podium) {
238
+ for (let i = 0; i < Math.min(3, eligible.length); i++) {
239
+ const e = eligible[i];
240
+ const prize = out.get(e.key);
241
+ const row = HUNT_PODIUM_PRIZES[i];
242
+ prize.woodworkXp += row.woodworkXp;
243
+ prize.explorerXp += row.explorerXp;
244
+ prize.items.push({ kind: 'ashwood', qty: row.ash });
245
+ prize.marks.push(HUNT_MARK_RIBBON[RIBBONS[i]]);
246
+ notes.set(e.key, `${HUNT_RIBBON_LABEL[RIBBONS[i]]} for ${i === 0 ? '1st' : i === 1 ? '2nd' : '3rd'} place`);
247
+ }
248
+ }
249
+ for (const [key, prize] of out) {
250
+ const e = eligible.find((x) => x.key === key);
251
+ const base = notes.get(key) ?? (input.felled ? 'the heartwood fell' : 'thanks for trying');
252
+ prize.text = `Heartwood Hunt: ${base} (${e.cuts} cut${e.cuts === 1 ? '' : 's'}, ${e.kills} brood kill${e.kills === 1 ? '' : 's'}, score ${huntEntryScore(e)}). +${prize.woodworkXp} Woodwork XP, +${prize.explorerXp} Explorer XP.`;
253
+ }
254
+ return out;
255
+ }
256
+ /** The world chat line for a finished round. */
257
+ export function huntResultLine(entries, felled) {
258
+ const ranked = huntRanking(entries);
259
+ if (ranked.length === 0)
260
+ return felled ? 'The heartwood has fallen. Nobody scored enough to be named.' : 'The heartwood sinks back into the Grove. Nobody scored enough to be named.';
261
+ const top = ranked[0];
262
+ const lead = felled ? 'The heartwood has fallen!' : 'The heartwood sinks back into the Grove, unfelled.';
263
+ const podium = !felled ? ' (no ribbons for an unfelled tree)' : ranked.length < HUNT_MIN_HUNTERS ? ` (it takes ${HUNT_MIN_HUNTERS} hunters to hand out ribbons)` : '';
264
+ return `${lead} Top hunter: ${top.name}, score ${huntEntryScore(top)}${ranked[1] ? `; then ${ranked[1].name}${ranked[2] ? ` and ${ranked[2].name}` : ''}` : ''}.${podium}`;
265
+ }
266
+ // ---- the telling --------------------------------------------------------------------------------------------------------
267
+ export const HUNT_NAME = 'Heartwood Hunt';
268
+ /** The world chat line for a stage (idle and results have none: the results line is built from the standings). */
269
+ export function huntChatLine(stage, slot) {
270
+ const where = huntSpotFor(slot).label;
271
+ switch (stage) {
272
+ case 'soon':
273
+ return `World event: the Heartwood Hunt starts in ${span(HUNT_SOON_MS)}. A heartwood tree will rise in the Rotwood Grove (Woodwork ${HUNT_MIN_WOODWORK} to cut it, Combat to guard the cutters). The Grove is PvP ground.`;
274
+ case 'open':
275
+ return `World event: the HEARTWOOD rises in the Rotwood Grove, at ${where}! ${span(HUNT_ROUND_MS)}: cut it down while the Ent's brood hunts you. Cuts and brood kills score.`;
276
+ case 'last':
277
+ return `World event: ${span(HUNT_LAST_MS)} left in the Heartwood Hunt.`;
278
+ default:
279
+ return null;
280
+ }
281
+ }
282
+ /** The login line's piece about the hunt. */
283
+ export function huntTodayText(now) {
284
+ const c = huntClockAt(now);
285
+ if (huntIsOpen(c.stage))
286
+ return `the Heartwood Hunt is on now in the Rotwood Grove (${span(c.msToEnd)} left)`;
287
+ const next = huntNextRound(now);
288
+ return `the Heartwood Hunt rises in ${span(next.startsAt - now)}`;
289
+ }
290
+ /** What /hunt tells a player. */
291
+ export function huntStatusLines(clock, entries, myKey, cutsDone, now) {
292
+ const lines = [];
293
+ if (huntIsOpen(clock.stage)) {
294
+ lines.push(`Heartwood Hunt is ON in the Rotwood Grove, at ${huntSpotFor(clock.slot).label}: ${span(clock.msToEnd)} left. The tree has taken ${Math.min(cutsDone, HUNT_TREE_CUTS)} of ${HUNT_TREE_CUTS} cuts.`);
295
+ }
296
+ else if (clock.stage === 'results') {
297
+ lines.push('The Heartwood Hunt has ended; the results are in.');
298
+ }
299
+ else {
300
+ const next = huntNextRound(now);
301
+ lines.push(`Next Heartwood Hunt: in ${span(next.startsAt - now)}, in the Rotwood Grove.`);
302
+ }
303
+ if (huntIsOpen(clock.stage) || clock.stage === 'results') {
304
+ const ranked = huntRanking(entries);
305
+ if (ranked.length === 0)
306
+ lines.push('Nobody has scored enough to be ranked yet (' + HUNT_MIN_SCORE + ' points: 3 cuts or 2 brood kills).');
307
+ else
308
+ lines.push(`Top hunters: ${ranked.slice(0, 3).map((e, i) => `${i + 1}. ${e.name} ${huntEntryScore(e)}`).join(', ')}`);
309
+ if (myKey) {
310
+ const mine = entries.find((e) => e.key === myKey);
311
+ if (mine)
312
+ lines.push(`You: ${mine.cuts} cut${mine.cuts === 1 ? '' : 's'}, ${mine.kills} brood kill${mine.kills === 1 ? '' : 's'}, score ${huntEntryScore(mine)}${huntQualifies(mine) ? '' : ` (${HUNT_MIN_SCORE} to be ranked)`}.`);
313
+ }
314
+ }
315
+ return lines;
316
+ }
317
+ // ---- the Ent's brood and its grasp --------------------------------------------------------------------------------------
318
+ /**
319
+ * The Rotwood Ent's brood: moss wolves (the Grove's own kind), sent in waves while the tree stands. Levels follow the hunters' average
320
+ * Combat, clamped; the count follows how many are at the tree. PLACEHOLDERS.
321
+ */
322
+ export const HUNT_BROOD = {
323
+ kind: 'mosswolf',
324
+ idPrefix: 'hh-',
325
+ firstWave: 3,
326
+ waveEveryMs: 40_000,
327
+ perExtraHunter: 1,
328
+ waveMax: 7,
329
+ aliveCap: 14,
330
+ /** Wolves come out of the dead wood this far from the tree. */
331
+ spawnMin: 6,
332
+ spawnMax: 9,
333
+ aggroRadius: 10,
334
+ leashRadius: 16,
335
+ minLevel: 22,
336
+ maxLevel: 32,
337
+ /** A hunter is "at the tree" this close. */
338
+ nearTree: 12,
339
+ aggroText: "A wolf of the Ent's brood bursts from the roots at you!",
340
+ };
341
+ /** How many wolves a wave brings: the first wave is fixed; later ones grow with the hunters at the tree. */
342
+ export function huntWaveSize(wave, hunters) {
343
+ if (wave <= 0)
344
+ return HUNT_BROOD.firstWave;
345
+ return Math.min(HUNT_BROOD.waveMax, HUNT_BROOD.firstWave + Math.max(0, hunters - 1) * HUNT_BROOD.perExtraHunter);
346
+ }
347
+ /** The brood's level for a party's average Combat. */
348
+ export function huntBroodLevel(avgCombat) {
349
+ return Math.max(HUNT_BROOD.minLevel, Math.min(HUNT_BROOD.maxLevel, Math.round(avgCombat)));
350
+ }
351
+ /**
352
+ * The Ent's grasp, the mini-boss telegraph: the roots under the heartwood heave. A chat line goes out `HUNT_GRASP.leadMs` ahead
353
+ * naming the tiles; whoever is still within `radius` of the tree when it lands takes the blow, whoever stepped out takes nothing.
354
+ * (The real mini-boss, a drawn ground ring and a Sapling Ent, are logged as upgrades.)
355
+ */
356
+ export const HUNT_GRASP = {
357
+ everyMs: 50_000,
358
+ leadMs: 3_000,
359
+ radius: 2,
360
+ /** Raw damage before armour: PLACEHOLDER. */
361
+ damage: 14,
362
+ warn: "The roots under the heartwood heave! Step away from the trunk!",
363
+ hit: "The Ent's roots lash up and seize you!",
364
+ dodged: 'You step clear as the roots slam down.',
365
+ };
366
+ /** Who stands within `radius` (Chebyshev) of the centre. */
367
+ export function huntInGrasp(centre, players, radius = HUNT_GRASP.radius) {
368
+ return players.filter((p) => Math.max(Math.abs(Math.round(p.x) - centre.x), Math.abs(Math.round(p.y) - centre.z)) <= radius);
369
+ }
370
+ // ---- the forester and his camp ------------------------------------------------------------------------------------------
371
+ export const FORESTER_NAME = 'Forester Imre Thorne';
372
+ export const FORESTER_ID = 'forester';
373
+ /** The forester's lean-to camp on the way into the Grove, just south of the Grove's path end (z 400): a PvP-off pocket (types safePockets.ts). */
374
+ export const HEARTWOOD_CAMP = { minX: GROVE_CX - 6, maxX: GROVE_CX + 6, minZ: GROVE_CZ + 24, maxZ: GROVE_CZ + 32 };
375
+ export const FORESTER_SPOT = { x: GROVE_CX, z: GROVE_CZ + 28, faceX: GROVE_CX, faceZ: GROVE_CZ + 24 };
376
+ /** The camp's placard. */
377
+ export const HEARTWOOD_CAMP_SIGN = "The Forester's Camp. No fighting inside the lanterns. A heartwood rises in the Rotwood Grove, north, every three hours (Woodwork 24 to cut it). The Grove is PvP ground.";
378
+ /** Stand-in pieces from the Dreadwoods kit (logged as an upgrade): a tent, the fire, crates, a barrel, lanterns and a sign. */
379
+ export const HEARTWOOD_CAMP_PIECES = [
380
+ { id: 'hh-camp-tent', kind: 'dreadprop', style: 'tent-face90', x: GROVE_CX - 4, z: GROVE_CZ + 27 },
381
+ { id: 'hh-camp-fire', kind: 'campfire', style: 'beach-pit', x: GROVE_CX + 3, z: GROVE_CZ + 28, scale: 1 },
382
+ { id: 'hh-camp-crates', kind: 'dreadprop', style: 'crates', x: GROVE_CX + 5, z: GROVE_CZ + 26 },
383
+ { id: 'hh-camp-barrel', kind: 'barrel', style: 'barrel', x: GROVE_CX + 5, z: GROVE_CZ + 30, scale: 1 },
384
+ { id: 'hh-camp-lantern-w', kind: 'lantern', style: 'post-west', x: GROVE_CX - 5, z: GROVE_CZ + 31 },
385
+ { id: 'hh-camp-lantern-e', kind: 'lantern', style: 'post-east', x: GROVE_CX + 6, z: GROVE_CZ + 31 },
386
+ { id: 'hh-camp-sign', kind: 'signpost', style: 'placard-' + HEARTWOOD_CAMP_SIGN, x: GROVE_CX + 2, z: GROVE_CZ + 24, scale: 1.1 },
387
+ ];
388
+ export const HEARTWOOD_CAMP_ENTER = "You step into the forester's camp. Nobody can attack you here, and the Grove's wolves do not come this far.";
389
+ export const HEARTWOOD_CAMP_LEAVE = "You step out of the forester's camp. This is Dreadwoods ground again: other players can attack you.";
390
+ export function emptyHuntSave() {
391
+ return { v: 1, slot: -1, announced: null, finalized: true, felled: false, cutsDone: 0, waves: 0, entries: [], pending: {}, paid: {} };
392
+ }
393
+ /** At most this many prizes wait for one character, and entries are never more than this many. */
394
+ export const HUNT_PENDING_MAX = 5;
395
+ export const HUNT_MAX_ENTRIES = 1000;
396
+ function num(x, min, max) {
397
+ return typeof x === 'number' && Number.isFinite(x) && x >= min && x <= max ? x : null;
398
+ }
399
+ function parseEntry(raw) {
400
+ if (!raw || typeof raw !== 'object')
401
+ return null;
402
+ const r = raw;
403
+ const cuts = num(r.cuts, 0, 100_000);
404
+ const kills = num(r.kills, 0, 100_000);
405
+ const logs = num(r.logs, 0, 100_000);
406
+ const at = num(r.at, 0, 1e15);
407
+ if (typeof r.key !== 'string' || r.key.length === 0 || r.key.length > 80 || cuts === null || kills === null || logs === null || at === null)
408
+ return null;
409
+ return {
410
+ key: r.key,
411
+ account: typeof r.account === 'string' ? r.account.slice(0, 80) : '',
412
+ name: typeof r.name === 'string' ? r.name.slice(0, 40) : 'Hunter',
413
+ cuts: Math.floor(cuts),
414
+ kills: Math.floor(kills),
415
+ logs: Math.floor(logs),
416
+ at,
417
+ };
418
+ }
419
+ function parsePrize(raw) {
420
+ if (!raw || typeof raw !== 'object')
421
+ return null;
422
+ const r = raw;
423
+ const woodworkXp = num(r.woodworkXp, 0, 100_000);
424
+ const explorerXp = num(r.explorerXp, 0, 100_000);
425
+ if (woodworkXp === null || explorerXp === null || typeof r.text !== 'string')
426
+ return null;
427
+ const items = [];
428
+ if (Array.isArray(r.items)) {
429
+ for (const it of r.items.slice(0, 8)) {
430
+ if (it && typeof it === 'object' && typeof it.kind === 'string' && num(it.qty, 1, 1000) !== null) {
431
+ items.push({ kind: it.kind.slice(0, 60), qty: Math.floor(it.qty) });
432
+ }
433
+ }
434
+ }
435
+ const marks = Array.isArray(r.marks) ? r.marks.filter((m) => typeof m === 'string' && m.startsWith('hunt:')).slice(0, 12) : [];
436
+ return { woodworkXp: Math.floor(woodworkXp), explorerXp: Math.floor(explorerXp), items, marks, text: r.text.slice(0, 300) };
437
+ }
438
+ /** A saved state, checked field by field (it comes from the database); anything wrong gives the empty state. */
439
+ export function parseHuntSave(raw) {
440
+ if (!raw || typeof raw !== 'object')
441
+ return emptyHuntSave();
442
+ const r = raw;
443
+ if (r.v !== 1)
444
+ return emptyHuntSave();
445
+ const slot = num(r.slot, -1, 1e9);
446
+ const entries = Array.isArray(r.entries) ? r.entries.slice(0, 2000).map(parseEntry).filter((e) => e !== null) : [];
447
+ const seen = new Set();
448
+ const unique = entries.filter((e) => (seen.has(e.key) ? false : (seen.add(e.key), true)));
449
+ let announced = null;
450
+ const a = r.announced;
451
+ if (a && typeof a === 'object' && num(a.slot, -1, 1e9) !== null && isHuntStage(a.stage))
452
+ announced = { slot: Math.floor(a.slot), stage: a.stage };
453
+ const pending = {};
454
+ if (r.pending && typeof r.pending === 'object') {
455
+ for (const [key, list] of Object.entries(r.pending).slice(0, 5000)) {
456
+ if (!Array.isArray(list))
457
+ continue;
458
+ const prizes = list.map(parsePrize).filter((p) => p !== null).slice(-HUNT_PENDING_MAX);
459
+ if (prizes.length > 0)
460
+ pending[key] = prizes;
461
+ }
462
+ }
463
+ const paid = {};
464
+ if (r.paid && typeof r.paid === 'object') {
465
+ for (const [acc, raw2] of Object.entries(r.paid).slice(0, 5000)) {
466
+ const p = raw2;
467
+ if (!p || typeof p !== 'object')
468
+ continue;
469
+ const day = num(p.day, 0, 1e7);
470
+ const n = num(p.n, 0, 1000);
471
+ if (day === null || n === null)
472
+ continue;
473
+ paid[acc.slice(0, 80)] = { day: Math.floor(day), n: Math.floor(n) };
474
+ }
475
+ }
476
+ const cutsDone = num(r.cutsDone, 0, 1_000_000);
477
+ const waves = num(r.waves, 0, 100_000);
478
+ return {
479
+ v: 1,
480
+ slot: slot === null ? -1 : Math.floor(slot),
481
+ announced,
482
+ finalized: r.finalized === true,
483
+ felled: r.felled === true,
484
+ cutsDone: cutsDone === null ? 0 : Math.floor(cutsDone),
485
+ waves: waves === null ? 0 : Math.floor(waves),
486
+ entries: unique,
487
+ pending,
488
+ paid,
489
+ };
490
+ }
491
+ //# sourceMappingURL=heartwoodHunt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartwoodHunt.js","sourceRoot":"","sources":["../src/heartwoodHunt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * THE HEARTWOOD CHAIN (track T74, 2026-10-14): five story quests from Forester Imre Thorne, who keeps a camp (a PvP-off pocket) on the
3
+ * way into the Rotwood Grove. They teach, one step at a time, what the Heartwood Hunt asks (heartwoodHunt.ts): cut alder and ash
4
+ * (Woodwork 24-30), put down the Ent's brood (Combat 22+), take part in a hunt, and see a heartwood fall. Levels 24-32.
5
+ *
6
+ * All data, all existing step kinds: `deliver` (logs), `kill` (moss wolves), `reach` (the Grove's clearing) and `talk` with a
7
+ * `ledger` gate for the two quests that need a hunt (the server writes `hunt:entered` and `hunt:felled` when a finished hunt pays).
8
+ * Rewards are PLACEHOLDERS for the balance pass. This file only imports types from storyQuests.ts (an erased import), like
9
+ * skillQuests.ts, so the two do not form a cycle: storyQuests.ts spreads HEARTWOOD_QUESTS into STORY_QUESTS.
10
+ */
11
+ import type { StoryQuestDef } from './storyQuests.js';
12
+ export type HeartwoodQuestId = 'heartwoodTimber' | 'broodOfTheEnt' | 'readTheGrove' | 'firstHeartwoodHunt' | 'theHeartwoodFalls';
13
+ export declare const HEARTWOOD_QUEST_IDS: readonly HeartwoodQuestId[];
14
+ /** Combat the chain asks (the Grove's moss wolves are level 24; the brood runs 22-32). */
15
+ export declare const HEARTWOOD_QUEST_COMBAT = 22;
16
+ export declare const HEARTWOOD_QUESTS: Record<HeartwoodQuestId, StoryQuestDef>;
17
+ //# sourceMappingURL=heartwoodQuests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartwoodQuests.d.ts","sourceRoot":"","sources":["../src/heartwoodQuests.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,kBAAkB,CAAC;AAMnE,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG,eAAe,GAAG,cAAc,GAAG,oBAAoB,GAAG,mBAAmB,CAAC;AAEjI,eAAO,MAAM,mBAAmB,EAAE,SAAS,gBAAgB,EAAoG,CAAC;AAEhK,0FAA0F;AAC1F,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAWzC,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,EAAE,aAAa,CA0JpE,CAAC"}