@doodle-engine/cli 0.0.2 → 0.0.3

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.
package/dist/create.js DELETED
@@ -1,716 +0,0 @@
1
- #!/usr/bin/env node
2
- import b from "prompts";
3
- import { mkdir as _, writeFile as a } from "fs/promises";
4
- import { join as o } from "path";
5
- import { crayon as e } from "crayon.js";
6
- const d = "ðŸū", l = "🐕", h = "ðŸĶī", y = "âœĻ", m = "📁", s = "✅", f = "🚀";
7
- async function k() {
8
- const t = process.argv.slice(2);
9
- t.length === 0 && (console.log(""), console.log(e.red(` ${l} Woof! You forgot the project name!`)), console.log(""), console.log(e.yellow(" Usage: npx create-doodle-engine-game <project-name>")), console.log(""), process.exit(1));
10
- const n = t[0], r = o(process.cwd(), n);
11
- console.log(""), console.log(e.bold.magenta(` ${d} Doodle Engine ${d}`)), console.log(e.dim(" Text-based RPG and Adventure Game Scaffolder")), console.log(""), console.log(` ${l} Creating new game: ${e.bold.cyan(n)}`), console.log("");
12
- const { useDefaultRenderer: i } = await b({
13
- type: "confirm",
14
- name: "useDefaultRenderer",
15
- message: "Use default renderer?",
16
- initial: !0
17
- });
18
- i === void 0 && (console.log(e.yellow(`
19
- ${h} No worries, maybe next time! Woof!`)), process.exit(0)), console.log(""), await E(r, n, i), console.log(""), console.log(e.bold.green(` ${s} Project created successfully!`)), console.log(""), console.log(e.dim(` ${m} ${r}`)), console.log(""), console.log(e.bold(" Next steps:")), console.log(e.cyan(` cd ${n}`)), console.log(e.cyan(" npm install ") + e.dim("# or: yarn install / pnpm install")), console.log(e.cyan(" npm run dev ") + e.dim("# or: yarn dev / pnpm dev")), console.log(""), console.log(e.dim(` ${f} Happy game making! ${d}`)), console.log("");
20
- }
21
- async function E(t, n, r) {
22
- const i = [
23
- "content/locations",
24
- "content/characters",
25
- "content/items",
26
- "content/dialogues",
27
- "content/quests",
28
- "content/journal",
29
- "content/locales",
30
- "content/maps",
31
- "assets/images/banners",
32
- "assets/images/portraits",
33
- "assets/images/items",
34
- "assets/images/maps",
35
- "assets/audio/music",
36
- "assets/audio/sfx",
37
- "assets/audio/voice",
38
- "src"
39
- ];
40
- console.log(` ${m} ${e.bold("Creating directories...")}`);
41
- for (const p of i)
42
- await _(o(t, p), { recursive: !0 });
43
- console.log(e.green(` ${s} Directories created`)), console.log("");
44
- const u = {
45
- name: n,
46
- version: "0.1.0",
47
- type: "module",
48
- scripts: {
49
- dev: "doodle dev",
50
- build: "doodle build",
51
- preview: "vite preview"
52
- },
53
- dependencies: {
54
- "@doodle-engine/core": "latest",
55
- "@doodle-engine/react": "latest",
56
- react: "^19.0.0",
57
- "react-dom": "^19.0.0"
58
- },
59
- devDependencies: {
60
- "@doodle-engine/cli": "latest",
61
- "@types/react": "^19.0.0",
62
- "@types/react-dom": "^19.0.0",
63
- "@vitejs/plugin-react": "^4.3.0",
64
- typescript: "^5.7.0",
65
- vite: "^6.0.0"
66
- }
67
- };
68
- console.log(` ${y} ${e.bold("Writing project files...")}`), await a(
69
- o(t, "package.json"),
70
- JSON.stringify(u, null, 2)
71
- );
72
- const g = {
73
- compilerOptions: {
74
- target: "ES2024",
75
- lib: ["ES2024", "DOM", "DOM.Iterable"],
76
- module: "ESNext",
77
- moduleResolution: "bundler",
78
- jsx: "react-jsx",
79
- strict: !0,
80
- skipLibCheck: !0,
81
- esModuleInterop: !0,
82
- forceConsistentCasingInFileNames: !0,
83
- resolveJsonModule: !0,
84
- isolatedModules: !0,
85
- noEmit: !0
86
- },
87
- include: ["src"]
88
- };
89
- await a(
90
- o(t, "tsconfig.json"),
91
- JSON.stringify(g, null, 2)
92
- ), await a(o(t, "index.html"), `<!doctype html>
93
- <html lang="en">
94
- <head>
95
- <meta charset="UTF-8" />
96
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
97
- <title>Doodle Engine Game</title>
98
- </head>
99
- <body>
100
- <div id="root"></div>
101
- <script type="module" src="/src/main.tsx"><\/script>
102
- </body>
103
- </html>
104
- `), await a(o(t, "src/main.tsx"), `import { StrictMode } from 'react'
105
- import { createRoot } from 'react-dom/client'
106
- import { App } from './App'
107
- import './index.css'
108
-
109
- createRoot(document.getElementById('root')!).render(
110
- <StrictMode>
111
- <App />
112
- </StrictMode>,
113
- )
114
- `);
115
- let c;
116
- r ? c = `import { useEffect, useState } from 'react'
117
- import type { ContentRegistry, GameConfig } from '@doodle-engine/core'
118
- import { GameShell } from '@doodle-engine/react'
119
-
120
- export function App() {
121
- const [content, setContent] = useState<{ registry: ContentRegistry; config: GameConfig } | null>(null)
122
-
123
- useEffect(() => {
124
- fetch('/api/content')
125
- .then(res => res.json())
126
- .then(data => setContent({ registry: data.registry, config: data.config }))
127
- }, [])
128
-
129
- if (!content) {
130
- return <div style={{ padding: '2rem', fontFamily: 'sans-serif' }}>Loading game...</div>
131
- }
132
-
133
- return (
134
- <GameShell
135
- registry={content.registry}
136
- config={content.config}
137
- title="My Doodle Game"
138
- subtitle="A text-based adventure"
139
- splashDuration={2000}
140
- availableLocales={[{ code: 'en', label: 'English' }]}
141
- />
142
- )
143
- }
144
- ` : c = `import { useEffect, useState } from 'react'
145
- import { Engine } from '@doodle-engine/core'
146
- import type { GameState, Snapshot } from '@doodle-engine/core'
147
- import { GameProvider, useGame } from '@doodle-engine/react'
148
-
149
- export function App() {
150
- const [game, setGame] = useState<{ engine: Engine; snapshot: Snapshot } | null>(null)
151
-
152
- useEffect(() => {
153
- fetch('/api/content')
154
- .then(res => res.json())
155
- .then(data => {
156
- const engine = new Engine(data.registry, createEmptyState())
157
- const snapshot = engine.newGame(data.config)
158
- setGame({ engine, snapshot })
159
- })
160
- }, [])
161
-
162
- if (!game) {
163
- return <div style={{ padding: '2rem', fontFamily: 'sans-serif' }}>Loading game...</div>
164
- }
165
-
166
- return (
167
- <GameProvider engine={game.engine} initialSnapshot={game.snapshot}>
168
- <GameUI />
169
- </GameProvider>
170
- )
171
- }
172
-
173
- function GameUI() {
174
- const { snapshot, actions } = useGame()
175
-
176
- return (
177
- <div style={{ padding: '2rem', fontFamily: 'sans-serif', maxWidth: '800px', margin: '0 auto' }}>
178
- <h1>{snapshot.location.name}</h1>
179
- <p>{snapshot.location.description}</p>
180
-
181
- {snapshot.dialogue && (
182
- <div style={{ background: '#f0f0f0', padding: '1rem', borderRadius: '8px', margin: '1rem 0' }}>
183
- <strong>{snapshot.dialogue.speakerName}:</strong>
184
- <p>{snapshot.dialogue.text}</p>
185
- {snapshot.choices.map(choice => (
186
- <button
187
- key={choice.id}
188
- onClick={() => actions.selectChoice(choice.id)}
189
- style={{ display: 'block', margin: '0.5rem 0', padding: '0.5rem 1rem', cursor: 'pointer' }}
190
- >
191
- {choice.text}
192
- </button>
193
- ))}
194
- </div>
195
- )}
196
-
197
- {!snapshot.dialogue && snapshot.charactersHere.length > 0 && (
198
- <div>
199
- <h2>Characters here</h2>
200
- {snapshot.charactersHere.map(char => (
201
- <button
202
- key={char.id}
203
- onClick={() => actions.talkTo(char.id)}
204
- style={{ display: 'block', margin: '0.5rem 0', padding: '0.5rem 1rem', cursor: 'pointer' }}
205
- >
206
- Talk to {char.name}
207
- </button>
208
- ))}
209
- </div>
210
- )}
211
- </div>
212
- )
213
- }
214
-
215
- function createEmptyState(): GameState {
216
- return {
217
- currentLocation: '',
218
- currentTime: { day: 1, hour: 0 },
219
- flags: {},
220
- variables: {},
221
- inventory: [],
222
- questProgress: {},
223
- unlockedJournalEntries: [],
224
- playerNotes: [],
225
- dialogueState: null,
226
- characterState: {},
227
- itemLocations: {},
228
- mapEnabled: true,
229
- notifications: [],
230
- pendingSounds: [],
231
- pendingVideo: null,
232
- currentLocale: 'en',
233
- }
234
- }
235
- `, await a(o(t, "src/App.tsx"), c), await a(o(t, "src/index.css"), `body {
236
- margin: 0;
237
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
238
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
239
- sans-serif;
240
- -webkit-font-smoothing: antialiased;
241
- -moz-osx-font-smoothing: grayscale;
242
- }
243
- `), console.log(e.green(` ${s} Source files created`)), console.log(""), console.log(` ${h} ${e.bold("Writing starter content...")}`), await a(o(t, "content/game.yaml"), `# Game Configuration
244
- startLocation: tavern
245
- startTime:
246
- day: 1
247
- hour: 8
248
- startFlags: {}
249
- startVariables:
250
- gold: 100
251
- reputation: 0
252
- _drinksBought: 0
253
- startInventory: []
254
- `), await a(o(t, "content/locations/tavern.yaml"), `id: tavern
255
- name: "@location.tavern.name"
256
- description: "@location.tavern.description"
257
- banner: ""
258
- music: ""
259
- ambient: ""
260
- `), await a(o(t, "content/locations/market.yaml"), `id: market
261
- name: "@location.market.name"
262
- description: "@location.market.description"
263
- banner: ""
264
- music: ""
265
- ambient: ""
266
- `), await a(o(t, "content/characters/bartender.yaml"), `id: bartender
267
- name: "@character.bartender.name"
268
- biography: "@character.bartender.bio"
269
- portrait: ""
270
- location: tavern
271
- dialogue: bartender_greeting
272
- stats: {}
273
- `), await a(o(t, "content/characters/merchant.yaml"), `id: merchant
274
- name: "@character.merchant.name"
275
- biography: "@character.merchant.bio"
276
- portrait: ""
277
- location: market
278
- dialogue: merchant_intro
279
- stats: {}
280
- `), await a(o(t, "content/items/old_coin.yaml"), `id: old_coin
281
- name: "@item.old_coin.name"
282
- description: "@item.old_coin.description"
283
- icon: ""
284
- image: ""
285
- location: tavern
286
- stats: {}
287
- `), await a(o(t, "content/maps/town.yaml"), `id: town
288
- name: "@map.town.name"
289
- image: ""
290
- scale: 1
291
- locations:
292
- - id: tavern
293
- x: 100
294
- y: 200
295
- - id: market
296
- x: 300
297
- y: 150
298
- `), await a(o(t, "content/quests/odd_jobs.yaml"), `id: odd_jobs
299
- name: "@quest.odd_jobs.name"
300
- description: "@quest.odd_jobs.description"
301
- stages:
302
- - id: started
303
- description: "@quest.odd_jobs.stage.started"
304
- - id: talked_to_merchant
305
- description: "@quest.odd_jobs.stage.talked_to_merchant"
306
- - id: complete
307
- description: "@quest.odd_jobs.stage.complete"
308
- `), await a(o(t, "content/journal/tavern_discovery.yaml"), `id: tavern_discovery
309
- title: "@journal.tavern_discovery.title"
310
- text: "@journal.tavern_discovery.text"
311
- category: places
312
- `), await a(o(t, "content/journal/odd_jobs_accepted.yaml"), `id: odd_jobs_accepted
313
- title: "@journal.odd_jobs_accepted.title"
314
- text: "@journal.odd_jobs_accepted.text"
315
- category: quests
316
- `), await a(o(t, "content/journal/market_square.yaml"), `id: market_square
317
- title: "@journal.market_square.title"
318
- text: "@journal.market_square.text"
319
- category: places
320
- `), await a(o(t, "content/dialogues/tavern_intro.dlg"), `TRIGGER tavern
321
- REQUIRE notFlag seenTavernIntro
322
-
323
- NODE start
324
- NARRATOR: @narrator.tavern_intro
325
- SET flag seenTavernIntro
326
-
327
- CHOICE @narrator.choice.look_around
328
- END dialogue
329
- END
330
- `), await a(o(t, "content/dialogues/market_intro.dlg"), `TRIGGER market
331
- REQUIRE notFlag seenMarketIntro
332
-
333
- NODE start
334
- NARRATOR: @narrator.market_intro
335
- SET flag seenMarketIntro
336
- ADD journalEntry market_square
337
-
338
- CHOICE @narrator.choice.look_around
339
- END dialogue
340
- END
341
- `), await a(o(t, "content/dialogues/bartender_greeting.dlg"), `NODE start
342
- BARTENDER: @bartender.greeting
343
-
344
- # Always available — ask for rumors (demonstrates: flag, relationship, journalEntry)
345
- CHOICE @bartender.choice.whats_news
346
- SET flag metBartender
347
- ADD relationship bartender 1
348
- GOTO rumors
349
- END
350
-
351
- # Always available — buy a drink (demonstrates: variable change, flag)
352
- CHOICE @bartender.choice.order_drink
353
- GOTO order_drink
354
- END
355
-
356
- # Only before accepting the quest (demonstrates: notFlag condition)
357
- CHOICE @bartender.choice.looking_for_work
358
- REQUIRE notFlag acceptedOddJobs
359
- GOTO work_intro
360
- END
361
-
362
- # Only while quest is active at "started" stage (demonstrates: questAtStage condition)
363
- CHOICE @bartender.choice.about_that_job
364
- REQUIRE questAtStage odd_jobs started
365
- GOTO work_followup
366
- END
367
-
368
- # Only after quest is complete (demonstrates: questAtStage condition)
369
- CHOICE @bartender.choice.thanks_for_work
370
- REQUIRE questAtStage odd_jobs complete
371
- GOTO work_done
372
- END
373
-
374
- CHOICE @bartender.choice.nevermind
375
- GOTO farewell
376
- END
377
-
378
- NODE rumors
379
- BARTENDER: @bartender.rumors
380
- ADD journalEntry tavern_discovery
381
- ADD item old_coin
382
- NOTIFY @notification.journal_updated
383
-
384
- CHOICE @bartender.choice.tell_me_more
385
- GOTO rumors_detail
386
- END
387
-
388
- CHOICE @bartender.choice.back_to_chat
389
- GOTO start
390
- END
391
-
392
- NODE rumors_detail
393
- BARTENDER: @bartender.rumors_detail
394
-
395
- CHOICE @bartender.choice.interesting
396
- GOTO start
397
- END
398
-
399
- NODE order_drink
400
- BARTENDER: @bartender.order_drink
401
-
402
- # Only if player can afford it (demonstrates: variableGreaterThan condition)
403
- CHOICE @bartender.choice.sure_pay
404
- REQUIRE variableGreaterThan gold 4
405
- ADD variable gold -5
406
- ADD variable _drinksBought 1
407
- ADD variable reputation 1
408
- SET flag hadDrink
409
- ADD relationship bartender 1
410
- NOTIFY @notification.bought_drink
411
- GOTO after_drink
412
- END
413
-
414
- # Always available as an out
415
- CHOICE @bartender.choice.too_rich
416
- GOTO start
417
- END
418
-
419
- NODE after_drink
420
- BARTENDER: @bartender.after_drink
421
-
422
- CHOICE @bartender.choice.back_to_chat
423
- GOTO start
424
- END
425
-
426
- NODE work_intro
427
- BARTENDER: @bartender.work_intro
428
-
429
- CHOICE @bartender.choice.accept_work
430
- SET flag acceptedOddJobs
431
- SET questStage odd_jobs started
432
- ADD journalEntry odd_jobs_accepted
433
- ADD relationship bartender 2
434
- ADD variable reputation 5
435
- NOTIFY @notification.quest_started
436
- GOTO work_accepted
437
- END
438
-
439
- CHOICE @bartender.choice.not_interested
440
- GOTO start
441
- END
442
-
443
- NODE work_accepted
444
- BARTENDER: @bartender.work_accepted
445
-
446
- CHOICE @bartender.choice.on_my_way
447
- GOTO farewell
448
- END
449
-
450
- CHOICE @bartender.choice.more_details
451
- GOTO work_details
452
- END
453
-
454
- NODE work_details
455
- BARTENDER: @bartender.work_details
456
-
457
- CHOICE @bartender.choice.got_it
458
- GOTO farewell
459
- END
460
-
461
- NODE work_followup
462
- BARTENDER: @bartender.work_followup
463
-
464
- CHOICE @bartender.choice.on_my_way
465
- GOTO farewell
466
- END
467
-
468
- NODE work_done
469
- BARTENDER: @bartender.work_done
470
- ADD relationship bartender 3
471
-
472
- CHOICE @bartender.choice.anytime
473
- GOTO start
474
- END
475
-
476
- NODE farewell
477
- BARTENDER: @bartender.farewell
478
- END dialogue
479
- `), await a(o(t, "content/dialogues/merchant_intro.dlg"), `NODE start
480
- MERCHANT: @merchant.greeting
481
-
482
- CHOICE @merchant.choice.browse_wares
483
- GOTO browse
484
- END
485
-
486
- # Only appears when quest is at "started" (bartender sent you)
487
- CHOICE @merchant.choice.heard_about_work
488
- REQUIRE questAtStage odd_jobs started
489
- GOTO odd_jobs_talk
490
- END
491
-
492
- # Only appears after talking to merchant about the job
493
- CHOICE @merchant.choice.delivery_done
494
- REQUIRE questAtStage odd_jobs talked_to_merchant
495
- GOTO quest_complete
496
- END
497
-
498
- CHOICE @merchant.choice.whats_this_place
499
- GOTO about_market
500
- END
501
-
502
- CHOICE @merchant.choice.goodbye
503
- GOTO farewell
504
- END
505
-
506
- NODE browse
507
- MERCHANT: @merchant.browse
508
-
509
- # Conditional purchase — need enough gold (demonstrates: variableGreaterThan)
510
- CHOICE @merchant.choice.buy_map
511
- REQUIRE variableGreaterThan gold 19
512
- ADD variable gold -20
513
- SET flag boughtMap
514
- NOTIFY @notification.bought_map
515
- GOTO sold_map
516
- END
517
-
518
- CHOICE @merchant.choice.too_pricey
519
- GOTO too_pricey
520
- END
521
-
522
- NODE sold_map
523
- MERCHANT: @merchant.sold_map
524
-
525
- CHOICE @merchant.choice.thanks_info
526
- GOTO start
527
- END
528
-
529
- NODE too_pricey
530
- MERCHANT: @merchant.too_pricey
531
-
532
- CHOICE @merchant.choice.back_to_browse
533
- GOTO start
534
- END
535
-
536
- NODE odd_jobs_talk
537
- MERCHANT: @merchant.odd_jobs
538
-
539
- CHOICE @merchant.choice.accept_task
540
- SET questStage odd_jobs talked_to_merchant
541
- ADD relationship merchant 1
542
- NOTIFY @notification.quest_updated
543
- GOTO task_details
544
- END
545
-
546
- CHOICE @merchant.choice.need_to_think
547
- GOTO farewell
548
- END
549
-
550
- NODE task_details
551
- MERCHANT: @merchant.task_details
552
-
553
- CHOICE @merchant.choice.on_it
554
- GOTO farewell
555
- END
556
-
557
- NODE quest_complete
558
- MERCHANT: @merchant.quest_complete
559
- SET questStage odd_jobs complete
560
- ADD variable gold 50
561
- ADD variable reputation 10
562
- ADD relationship merchant 3
563
- NOTIFY @notification.quest_complete
564
-
565
- CHOICE @merchant.choice.glad_to_help
566
- GOTO farewell
567
- END
568
-
569
- NODE about_market
570
- MERCHANT: @merchant.about_market
571
-
572
- CHOICE @merchant.choice.thanks_info
573
- GOTO start
574
- END
575
-
576
- NODE farewell
577
- MERCHANT: @merchant.farewell
578
- END dialogue
579
- `), await a(o(t, "content/locales/en.yaml"), `# ===================
580
- # Narrator Intros
581
- # ===================
582
- narrator.tavern_intro: "You push open the heavy oak door and step inside. The warmth hits you first, then the smell — stale ale, wood smoke, and something frying in the kitchen. A few patrons hunch over their mugs. Behind the bar, a broad-shouldered man wipes down glasses, watching you with quiet interest."
583
- narrator.market_intro: "The market square opens up before you, a riot of color and noise. Stalls line every side, draped in bright awnings. Merchants call out their prices, children dart between carts, and somewhere a street musician plays an out-of-tune fiddle."
584
- narrator.choice.look_around: "Look around."
585
-
586
- # ===================
587
- # Locations
588
- # ===================
589
- location.tavern.name: "The Salty Dog"
590
- location.tavern.description: "A dimly lit tavern smelling of salt and stale ale. Candles flicker on rough wooden tables, and the murmur of conversation fills the air."
591
- location.market.name: "Market Square"
592
- location.market.description: "A bustling open-air market where merchants hawk their wares. The smell of fresh bread mingles with exotic spices."
593
-
594
- # ===================
595
- # Characters
596
- # ===================
597
- character.bartender.name: "Marcus the Bartender"
598
- character.bartender.bio: "A gruff man with kind eyes who's heard every story twice. He keeps the peace at The Salty Dog with a firm hand and a generous pour."
599
- character.merchant.name: "Elena the Merchant"
600
- character.merchant.bio: "A sharp-eyed trader who always seems to know the value of everything, and the price of everyone."
601
-
602
- # ===================
603
- # Items
604
- # ===================
605
- item.old_coin.name: "Old Coin"
606
- item.old_coin.description: "A tarnished coin with strange markings. It doesn't match any currency you've seen before."
607
-
608
- # ===================
609
- # Maps
610
- # ===================
611
- map.town.name: "Town"
612
-
613
- # ===================
614
- # Quests
615
- # ===================
616
- quest.odd_jobs.name: "Odd Jobs"
617
- quest.odd_jobs.description: "The bartender mentioned someone at the market who could use a hand."
618
- quest.odd_jobs.stage.started: "Marcus mentioned work at the market. I should talk to the merchant there."
619
- quest.odd_jobs.stage.talked_to_merchant: "Elena needs a delivery watched. Time to head to the docks."
620
- quest.odd_jobs.stage.complete: "Job well done. Elena paid 50 gold for the trouble."
621
-
622
- # ===================
623
- # Journal Entries
624
- # ===================
625
- journal.tavern_discovery.title: "The Salty Dog"
626
- journal.tavern_discovery.text: "I found a tavern in the docks district called The Salty Dog. The bartender, Marcus, seems well-connected. Word is there's been strange folk around the docks at night."
627
- journal.odd_jobs_accepted.title: "Work at the Market"
628
- journal.odd_jobs_accepted.text: "Marcus pointed me toward a merchant in the market square — Elena. She's looking for someone reliable. Should head over and introduce myself."
629
- journal.market_square.title: "Market Square"
630
- journal.market_square.text: "The market square is the heart of this little town. Elena has been trading here for fifteen years. A good place to resupply."
631
-
632
- # ===================
633
- # Bartender Dialogue
634
- # ===================
635
- bartender.greeting: "Welcome to the Salty Dog, stranger. What can I get you?"
636
- bartender.farewell: "Take care out there. The streets aren't as safe as they used to be."
637
-
638
- # Choices
639
- bartender.choice.whats_news: "What's the news around here?"
640
- bartender.choice.order_drink: "I'll have a drink."
641
- bartender.choice.looking_for_work: "I'm looking for work."
642
- bartender.choice.about_that_job: "About that job you mentioned..."
643
- bartender.choice.thanks_for_work: "Thanks for putting me onto that work."
644
- bartender.choice.nevermind: "Never mind, just passing through."
645
- bartender.choice.tell_me_more: "Tell me more about that."
646
- bartender.choice.interesting: "Interesting. I'll keep that in mind."
647
- bartender.choice.sure_pay: "Sure, here's five gold."
648
- bartender.choice.too_rich: "On second thought, I'll pass."
649
- bartender.choice.back_to_chat: "So, what else?"
650
- bartender.choice.accept_work: "Sure, I could use the coin."
651
- bartender.choice.not_interested: "Not right now, thanks."
652
- bartender.choice.on_my_way: "I'll head there now."
653
- bartender.choice.more_details: "What exactly do they need?"
654
- bartender.choice.got_it: "Got it. I'll take care of it."
655
- bartender.choice.anytime: "Anytime."
656
-
657
- # Responses
658
- bartender.rumors: "Word is there's been strange folk poking around the docks at night. And the merchant in the market square has been looking for hired help. Oh — found this on the floor the other day. Strange markings. You can have it."
659
- bartender.rumors_detail: "Some say they've seen lights out on the old pier after midnight. Probably smugglers, but who knows these days. Keep your wits about you."
660
- bartender.order_drink: "Five gold for the house special — strongest thing this side of the river. What do you say?"
661
- bartender.after_drink: "Glad you like it! Brewed it myself. Now then, anything else?"
662
- bartender.work_intro: "Well now, you look capable enough. There's a merchant over in the market square — Elena — she's been asking around for someone reliable. Tell her Marcus sent you."
663
- bartender.work_accepted: "Good on you. Elena's fair with pay. Head to the market square when you're ready."
664
- bartender.work_details: "Something about a shipment that needs escorting. Nothing too dangerous, she says — but then, that's what they always say."
665
- bartender.work_followup: "Still working on that job for Elena? She's over at the market square if you haven't found her yet. Don't keep her waiting too long."
666
- bartender.work_done: "I heard Elena's singing your praises. Good work out there — I knew you had it in you."
667
-
668
- # ===================
669
- # Merchant Dialogue
670
- # ===================
671
- merchant.greeting: "Welcome, welcome! Elena's Emporium has everything you need, and plenty you didn't know you wanted."
672
- merchant.farewell: "Safe travels! Come back anytime."
673
-
674
- # Choices
675
- merchant.choice.browse_wares: "Let me see what you've got."
676
- merchant.choice.heard_about_work: "Marcus sent me about some work."
677
- merchant.choice.delivery_done: "The delivery is done."
678
- merchant.choice.whats_this_place: "Tell me about the market."
679
- merchant.choice.goodbye: "Just browsing. Goodbye."
680
- merchant.choice.buy_map: "I'll take the map. (20 gold)"
681
- merchant.choice.too_pricey: "A bit rich for my blood."
682
- merchant.choice.accept_task: "I'm in. What do you need?"
683
- merchant.choice.need_to_think: "Let me think about it."
684
- merchant.choice.thanks_info: "Thanks for the info."
685
- merchant.choice.back_to_browse: "I'll keep looking around."
686
- merchant.choice.on_it: "Consider it done."
687
- merchant.choice.glad_to_help: "Glad I could help."
688
-
689
- # Responses
690
- merchant.browse: "Take a look! I've got a fine map of the area if you're new around here. Only twenty gold — a bargain for not getting lost."
691
- merchant.sold_map: "Excellent choice! This'll keep you from wandering into the wrong part of town."
692
- merchant.too_pricey: "Ha! You'd pay twice that if you got lost in the docks at night. But no rush — I'll be here."
693
- merchant.odd_jobs: "Ah, Marcus sent you? Good man. I've got a shipment coming in and could use someone to keep an eye on things. Interested?"
694
- merchant.task_details: "Head down to the docks at sundown. You'll meet my contact there — a woman named Ria. Make sure the cargo gets here in one piece."
695
- merchant.quest_complete: "Everything arrived in perfect condition! You've earned this — fifty gold, as promised. If I need help again, you'll be the first I call."
696
- merchant.about_market: "Market Square is the heart of this little town. You can find just about anything here if you know where to look. I've been trading here for fifteen years."
697
-
698
- # ===================
699
- # Notifications
700
- # ===================
701
- notification.journal_updated: "Journal Updated"
702
- notification.quest_started: "New Quest: Odd Jobs"
703
- notification.quest_updated: "Quest Updated: Odd Jobs"
704
- notification.quest_complete: "Quest Complete: Odd Jobs (+50 gold, +10 reputation)"
705
- notification.bought_drink: "Bought a drink (-5 gold)"
706
- notification.bought_map: "Bought a map (-20 gold)"
707
- `), console.log(e.green(` ${s} Starter content created`)), console.log(""), console.log(e.dim(" Content includes:")), console.log(e.dim(" 2 locations (tavern, market)")), console.log(e.dim(" 2 characters (bartender, merchant)")), console.log(e.dim(" 1 item (old coin)")), console.log(e.dim(" 1 map (town)")), console.log(e.dim(" 1 quest with 3 stages")), console.log(e.dim(" 3 journal entries")), console.log(e.dim(" 4 dialogues (2 narrator intros, 2 NPC conversations)")), console.log(e.dim(" English locale with all strings")), await a(o(t, ".gitignore"), `node_modules
708
- dist
709
- .DS_Store
710
- *.log
711
- `);
712
- }
713
- k().catch((t) => {
714
- console.error(e.red(`
715
- ${l} Ruh roh! Something went wrong:`), t), process.exit(1);
716
- });