@2025-6-19/clawfight 1.3.0 → 1.5.0
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/index.js +1059 -25
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -148,6 +148,29 @@ ${archetype.values}
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
// src/lib/types.ts
|
|
151
|
+
var EQUIP_RARITY_WEIGHTS = {
|
|
152
|
+
common: 60,
|
|
153
|
+
rare: 25,
|
|
154
|
+
epic: 12,
|
|
155
|
+
legendary: 3
|
|
156
|
+
};
|
|
157
|
+
var EQUIP_RARITY_LABELS = {
|
|
158
|
+
common: "\u666E\u901A",
|
|
159
|
+
rare: "\u7A00\u6709",
|
|
160
|
+
epic: "\u53F2\u8BD7",
|
|
161
|
+
legendary: "\u4F20\u8BF4"
|
|
162
|
+
};
|
|
163
|
+
var SLOT_LABELS = {
|
|
164
|
+
claw: "\u94B3",
|
|
165
|
+
shell: "\u58F3",
|
|
166
|
+
charm: "\u9970"
|
|
167
|
+
};
|
|
168
|
+
var SLOT_ICONS = {
|
|
169
|
+
claw: "\u2694\uFE0F",
|
|
170
|
+
shell: "\u{1F6E1}\uFE0F",
|
|
171
|
+
charm: "\u{1F48E}"
|
|
172
|
+
};
|
|
173
|
+
var MAX_INVENTORY = 6;
|
|
151
174
|
var RARITY_WEIGHTS = {
|
|
152
175
|
common: 70,
|
|
153
176
|
calico: 20,
|
|
@@ -238,7 +261,128 @@ var zh = {
|
|
|
238
261
|
wake_no_bonus: "\uFF08\u4F11\u7720\u4E0D\u8DB3 4 \u5C0F\u65F6\uFF0C\u65E0\u52A0\u6210\uFF09",
|
|
239
262
|
wake_ready: "\u{1F7E2} {name} \u7CBE\u795E\u7115\u53D1\uFF0C\u51C6\u5907\u597D\u518D\u6B21\u51FA\u51FB\uFF01",
|
|
240
263
|
duration_minutes: "{n} \u5206\u949F",
|
|
241
|
-
duration_hours: "{n} \u5C0F\u65F6"
|
|
264
|
+
duration_hours: "{n} \u5C0F\u65F6",
|
|
265
|
+
depth_display: "\u6DF1\u5EA6:{depth}",
|
|
266
|
+
soul_trait: " \u6027\u683C\u7279\u8D28: [{trait}]",
|
|
267
|
+
equip_drop: "\u{1F381} \u83B7\u5F97: {item}",
|
|
268
|
+
auto_equip: "\u{1F99E} {name}\uFF08{reason}\uFF09\u2192 \u81EA\u52A8\u88C5\u5907 {item}",
|
|
269
|
+
auto_swap: "\u{1F99E} {name}\uFF08{reason}\uFF09\u2192 \u6362\u4E0B {old}\uFF0C\u88C5\u5907 {item}",
|
|
270
|
+
auto_discard: "\u{1F99E} {name} \u4E22\u5F03\u4E86 {item}\uFF08{reason}\uFF09",
|
|
271
|
+
equip_degrade: "\u{1F527} \u78E8\u635F: {items}",
|
|
272
|
+
equip_broken: "\u{1F4A5} \u635F\u574F: {items}",
|
|
273
|
+
equip_inv_full: "\u{1F4E6} \u80CC\u5305\u5DF2\u6EE1({max})\uFF0C\u4E22\u5F03\u4E86 {item}",
|
|
274
|
+
equip_title: "\u{1F392} \u88C5\u5907\u7BA1\u7406",
|
|
275
|
+
equip_slot_empty: " {icon} {slot}: (\u7A7A)",
|
|
276
|
+
equip_slot_item: " {icon} {slot}: {item}",
|
|
277
|
+
equip_inv_title: "\u{1F4E6} \u80CC\u5305 ({count}/{max}):",
|
|
278
|
+
equip_inv_item: " [{index}] {item}",
|
|
279
|
+
equip_inv_empty: " (\u7A7A)",
|
|
280
|
+
equip_equipped: "\u2705 \u5DF2\u88C5\u5907 {item} \u2192 {slot}",
|
|
281
|
+
equip_swapped: "\u{1F504} \u66FF\u6362 {old} \u2192 {item}",
|
|
282
|
+
equip_dropped: "\u{1F5D1}\uFE0F \u5DF2\u4E22\u5F03 {item}",
|
|
283
|
+
equip_unequipped: "\u{1F4E4} \u5DF2\u5378\u4E0B {item}",
|
|
284
|
+
equip_bad_index: "\u26A0\uFE0F \u65E0\u6548\u7F16\u53F7\u3002\u67E5\u770B\u80CC\u5305: npx clawfight equip",
|
|
285
|
+
equip_usage: "\u7528\u6CD5: equip / equip <\u7F16\u53F7> / equip drop <\u7F16\u53F7> / equip unequip <\u69FD\u4F4D>",
|
|
286
|
+
achieve_unlock: "\u{1F3C6} \u6210\u5C31\u89E3\u9501: {name} \u2014 {desc}",
|
|
287
|
+
achieve_title: "\u{1F3C6} \u6210\u5C31 ({count}/{total}):",
|
|
288
|
+
achieve_item: " \u2705 {name} \u2014 {desc}",
|
|
289
|
+
achieve_locked: " \u{1F512} {name} \u2014 {desc}",
|
|
290
|
+
achieve_none: " \u8FD8\u6CA1\u6709\u89E3\u9501\u4EFB\u4F55\u6210\u5C31\u3002\u7EE7\u7EED\u5192\u9669\u5427\uFF01",
|
|
291
|
+
patrol_depth: "\u{1F4CA} Lv.{level} | EXP:{exp}/{next} | \u4ECA\u65E5:{today}/{cap} | \u6DF1\u5EA6:{depth} | \u80CC\u5305:{inv}/{inv_max}",
|
|
292
|
+
depth_reset: "\u{1F4A4} \u6DF1\u5EA6\u5DF2\u91CD\u7F6E",
|
|
293
|
+
dg_connecting: "\u{1F4E1} \u8FDE\u63A5\u5730\u4E0B\u57CE\u670D\u52A1\u5668...",
|
|
294
|
+
dg_resume: "\u{1F3F0} \u68C0\u6D4B\u5230\u8FDB\u884C\u4E2D\u7684\u5730\u4E0B\u57CE\u63A2\u7D22\uFF1A",
|
|
295
|
+
dg_no_maps: "\u{1F5FA}\uFE0F \u6CA1\u6709\u5730\u4E0B\u57CE\u5730\u56FE\u3002\u7EE7\u7EED\u5DE1\u903B\u83B7\u53D6\u5730\u56FE\uFF01",
|
|
296
|
+
dg_bad_map_index: "\u26A0\uFE0F \u65E0\u6548\u5730\u56FE\u7F16\u53F7\uFF08\u5171{count}\u5F20\uFF09",
|
|
297
|
+
dg_entering: "\u{1F3F0} \u8FDB\u5165\u5730\u4E0B\u57CE: {theme} | {rooms}\u623F\u95F4 | {diff}",
|
|
298
|
+
dg_no_active: "\u26A0\uFE0F \u6CA1\u6709\u8FDB\u884C\u4E2D\u7684\u5730\u4E0B\u57CE\u3002\u5148\u7528 explore \u8FDB\u5165\u4E00\u4E2A\u3002",
|
|
299
|
+
dg_complete: "\u{1F389} \u5730\u4E0B\u57CE\u901A\u5173\uFF01",
|
|
300
|
+
dg_failed: "\u{1F480} \u5730\u4E0B\u57CE\u63A2\u7D22\u5931\u8D25\u2026HP\u5F52\u96F6",
|
|
301
|
+
dg_rewards_exp: "\u{1F4CA} \u5730\u4E0B\u57CE\u7ECF\u9A8C: +{exp}",
|
|
302
|
+
dg_abandoning: "\u{1F3F3}\uFE0F \u653E\u5F03\u5730\u4E0B\u57CE\u63A2\u7D22...",
|
|
303
|
+
dg_abandoned: "\u{1F3F3}\uFE0F \u5DF2\u64A4\u9000 | EXP+{exp} | \u6218\u5229\u54C1\xD7{loot} | \u6DF1\u5EA6\u2192{depth}",
|
|
304
|
+
dg_maps_title: "\u{1F5FA}\uFE0F \u5730\u4E0B\u57CE\u5730\u56FE\uFF08{count}\u5F20\uFF09:",
|
|
305
|
+
dg_rooms: "\u623F\u95F4",
|
|
306
|
+
dg_maps_hint: " \u{1F4A1} \u7528\u6CD5: explore <\u7F16\u53F7> \u8FDB\u5165 | explore maps \u67E5\u770B",
|
|
307
|
+
dg_map_found: "\u{1F5FA}\uFE0F \u53D1\u73B0\u5730\u4E0B\u57CE\u5730\u56FE: {theme} ({rooms}\u623F\u95F4, {diff})",
|
|
308
|
+
dg_summary: "\u{1F4CA} Lv.{level} | EXP:{exp}/{next} | \u4ECA\u65E5:{today}/{cap}",
|
|
309
|
+
dg_theme_coral_maze: "\u73CA\u745A\u8FF7\u5BAB",
|
|
310
|
+
dg_theme_deep_rift: "\u6DF1\u6D77\u88C2\u9699",
|
|
311
|
+
dg_theme_thermal_vent: "\u70ED\u6CC9\u55B7\u53E3",
|
|
312
|
+
dg_theme_ice_cavern: "\u51B0\u6676\u6D1E\u7A74",
|
|
313
|
+
dg_theme_shipwreck: "\u6C89\u8239\u9057\u8FF9",
|
|
314
|
+
dg_theme_abyss_trench: "\u6DF1\u6E0A\u6D77\u6C9F",
|
|
315
|
+
dg_theme_tide_pool: "\u6F6E\u6C50\u6D45\u6EE9",
|
|
316
|
+
dg_theme_void_rift: "\u865A\u7A7A\u88C2\u7F1D",
|
|
317
|
+
dg_risk_low: "\u4F4E\u98CE\u9669",
|
|
318
|
+
dg_risk_mid: "\u4E2D\u98CE\u9669",
|
|
319
|
+
dg_risk_high: "\u9AD8\u98CE\u9669",
|
|
320
|
+
dg_diff_easy: "\u7B80\u5355",
|
|
321
|
+
dg_diff_normal: "\u666E\u901A",
|
|
322
|
+
dg_diff_hard: "\u56F0\u96BE",
|
|
323
|
+
dg_diff_nightmare: "\u5669\u68A6",
|
|
324
|
+
dg_charge_attack: "\u731B\u529B\u51B2\u51FB",
|
|
325
|
+
dg_defensive_stance: "\u9632\u5FA1\u59FF\u6001",
|
|
326
|
+
dg_rush_strike: "\u95EA\u7535\u7A81\u88AD",
|
|
327
|
+
dg_counter_wait: "\u4F3A\u673A\u53CD\u51FB",
|
|
328
|
+
dg_open_golden_chest: "\u6253\u5F00\u91D1\u8272\u5B9D\u7BB1",
|
|
329
|
+
dg_open_stone_chest: "\u6253\u5F00\u77F3\u8D28\u5B9D\u7BB1",
|
|
330
|
+
dg_reach_deep_cache: "\u63A2\u7D22\u6DF1\u5C42\u5B9D\u85CF",
|
|
331
|
+
dg_take_surface_loot: "\u62FE\u53D6\u8868\u5C42\u6218\u5229\u54C1",
|
|
332
|
+
dg_disarm_mechanism: "\u62C6\u89E3\u673A\u5173",
|
|
333
|
+
dg_dodge_through: "\u7075\u5DE7\u95EA\u907F",
|
|
334
|
+
dg_brute_force: "\u86EE\u529B\u7A81\u7834",
|
|
335
|
+
dg_careful_bypass: "\u5C0F\u5FC3\u7ED5\u884C",
|
|
336
|
+
dg_deep_rest: "\u6DF1\u5EA6\u4F11\u606F",
|
|
337
|
+
dg_search_hidden: "\u641C\u7D22\u9690\u85CF\u7269",
|
|
338
|
+
dg_investigate: "\u8C03\u67E5\u7EBF\u7D22",
|
|
339
|
+
dg_proceed_cautiously: "\u8C28\u614E\u524D\u884C",
|
|
340
|
+
dg_touch_artifact: "\u89E6\u78B0\u795E\u5668",
|
|
341
|
+
dg_observe_only: "\u4EC5\u89C2\u5BDF",
|
|
342
|
+
dg_all_out_assault: "\u5168\u529B\u8FDB\u653B",
|
|
343
|
+
dg_tactical_approach: "\u7B56\u7565\u63A5\u8FD1",
|
|
344
|
+
dg_bravery_bonus: "\u52C7\u6C14\u52A0\u6210: ATK+20%",
|
|
345
|
+
dg_curiosity_bonus: "\u597D\u5947\u5FC3\u52A0\u6210: \u53D1\u73B0\u7387\u2191",
|
|
346
|
+
dg_temper_bonus: "\u66B4\u6012\u52A0\u6210: \u62C6\u89E3\u529B\u2191",
|
|
347
|
+
dg_charge_attack_success: "\u731B\u529B\u51B2\u51FB\u547D\u4E2D\uFF01",
|
|
348
|
+
dg_charge_attack_fail: "\u731B\u529B\u51B2\u51FB\u843D\u7A7A\uFF01\u53D7\u5230{damage}\u70B9\u4F24\u5BB3",
|
|
349
|
+
dg_defensive_stance_success: "\u9632\u5FA1\u59FF\u6001\u6210\u529F\uFF01\u5B89\u5168\u5EA6\u8FC7",
|
|
350
|
+
dg_defensive_stance_fail: "\u9632\u5FA1\u59FF\u6001\u88AB\u7A81\u7834\uFF01\u53D7\u5230{damage}\u70B9\u4F24\u5BB3",
|
|
351
|
+
dg_rush_strike_success: "\u95EA\u7535\u7A81\u88AD\u5F97\u624B\uFF01",
|
|
352
|
+
dg_rush_strike_fail: "\u7A81\u88AD\u5931\u8D25\uFF01\u53D7\u5230{damage}\u70B9\u4F24\u5BB3",
|
|
353
|
+
dg_counter_wait_success: "\u53CD\u51FB\u6210\u529F\uFF01",
|
|
354
|
+
dg_counter_wait_fail: "\u53CD\u51FB\u65F6\u673A\u5931\u8BEF\uFF01\u53D7\u5230{damage}\u70B9\u4F24\u5BB3",
|
|
355
|
+
dg_open_golden_chest_success: "\u91D1\u8272\u5B9D\u7BB1\u5F00\u542F\uFF01\u5B9D\u7269\u95EA\u8000",
|
|
356
|
+
dg_open_golden_chest_fail: "\u9677\u9631\u89E6\u53D1\uFF01\u53D7\u5230{damage}\u70B9\u4F24\u5BB3",
|
|
357
|
+
dg_open_stone_chest_success: "\u77F3\u8D28\u5B9D\u7BB1\u5F00\u542F\uFF01\u83B7\u5F97\u7269\u54C1",
|
|
358
|
+
dg_open_stone_chest_fail: "\u5B9D\u7BB1\u662F\u7A7A\u7684...",
|
|
359
|
+
dg_reach_deep_cache_success: "\u53D1\u73B0\u6DF1\u5C42\u5B9D\u85CF\uFF01",
|
|
360
|
+
dg_reach_deep_cache_fail: "\u6DF1\u5C42\u641C\u7D22\u65E0\u679C",
|
|
361
|
+
dg_take_surface_loot_success: "\u62FE\u53D6\u8868\u5C42\u6218\u5229\u54C1\uFF01",
|
|
362
|
+
dg_take_surface_loot_fail: "\u4EC0\u4E48\u90FD\u6CA1\u627E\u5230",
|
|
363
|
+
dg_disarm_mechanism_success: "\u673A\u5173\u62C6\u89E3\u6210\u529F\uFF01",
|
|
364
|
+
dg_disarm_mechanism_fail: "\u673A\u5173\u89E6\u53D1\uFF01\u53D7\u5230{damage}\u70B9\u4F24\u5BB3",
|
|
365
|
+
dg_dodge_through_success: "\u7075\u5DE7\u5730\u95EA\u907F\u4E86\u673A\u5173\uFF01",
|
|
366
|
+
dg_dodge_through_fail: "\u95EA\u907F\u5931\u8D25\uFF01\u53D7\u5230{damage}\u70B9\u4F24\u5BB3",
|
|
367
|
+
dg_brute_force_success: "\u86EE\u529B\u7A81\u7834\u6210\u529F\uFF01",
|
|
368
|
+
dg_brute_force_fail: "\u86EE\u529B\u7A81\u7834\u5931\u8D25\uFF01\u53D7\u5230{damage}\u70B9\u4F24\u5BB3",
|
|
369
|
+
dg_careful_bypass_success: "\u5C0F\u5FC3\u7ED5\u884C\u6210\u529F\uFF01",
|
|
370
|
+
dg_careful_bypass_fail: "\u7ED5\u884C\u5931\u8D25\u2026",
|
|
371
|
+
dg_rest_healed: "\u4F11\u606F\u6062\u590D HP+{heal}",
|
|
372
|
+
dg_search_hidden_success: "\u641C\u7D22\u5230\u9690\u85CF\u7269\u54C1\uFF01",
|
|
373
|
+
dg_search_hidden_fail: "\u641C\u7D22\u672A\u679C",
|
|
374
|
+
dg_investigate_success: "\u8C03\u67E5\u53D1\u73B0\u4E86\u79D8\u5BC6\uFF01",
|
|
375
|
+
dg_investigate_fail: "\u8C03\u67E5\u65E0\u679C",
|
|
376
|
+
dg_proceed_cautiously_success: "\u8C28\u614E\u524D\u884C\uFF0C\u5B89\u5168\u901A\u8FC7",
|
|
377
|
+
dg_proceed_cautiously_fail: "\u610F\u5916\u906D\u9047\uFF01\u53D7\u5230{damage}\u70B9\u4F24\u5BB3",
|
|
378
|
+
dg_touch_artifact_success: "\u795E\u5668\u91CA\u653E\u4E86\u529B\u91CF\uFF01",
|
|
379
|
+
dg_touch_artifact_fail: "\u795E\u5668\u53CD\u566C\uFF01\u53D7\u5230{damage}\u70B9\u4F24\u5BB3",
|
|
380
|
+
dg_observe_only_success: "\u89C2\u5BDF\u5230\u4E86\u6709\u7528\u7684\u7EBF\u7D22",
|
|
381
|
+
dg_observe_only_fail: "\u4EC0\u4E48\u4E5F\u6CA1\u53D1\u73B0",
|
|
382
|
+
dg_all_out_assault_success: "\u5168\u529B\u8FDB\u653B\u594F\u6548\uFF01Boss\u53D7\u5230\u91CD\u521B",
|
|
383
|
+
dg_all_out_assault_fail: "Boss\u53CD\u51FB\uFF01\u53D7\u5230{damage}\u70B9\u4F24\u5BB3",
|
|
384
|
+
dg_tactical_approach_success: "\u7B56\u7565\u63A5\u8FD1\u6210\u529F\uFF01\u627E\u5230\u5F31\u70B9",
|
|
385
|
+
dg_tactical_approach_fail: "Boss\u8BC6\u7834\u7B56\u7565\uFF01\u53D7\u5230{damage}\u70B9\u4F24\u5BB3"
|
|
242
386
|
};
|
|
243
387
|
var en = {
|
|
244
388
|
no_lobster: "\u{1F95A} No lobster yet. Run npx clawfight hatch to hatch one!",
|
|
@@ -309,7 +453,128 @@ var en = {
|
|
|
309
453
|
wake_no_bonus: "(Less than 4 hours, no bonus)",
|
|
310
454
|
wake_ready: "\u{1F7E2} {name} is refreshed and ready to go!",
|
|
311
455
|
duration_minutes: "{n} min",
|
|
312
|
-
duration_hours: "{n} hours"
|
|
456
|
+
duration_hours: "{n} hours",
|
|
457
|
+
depth_display: "Depth:{depth}",
|
|
458
|
+
soul_trait: " Traits: [{trait}]",
|
|
459
|
+
equip_drop: "\u{1F381} Loot: {item}",
|
|
460
|
+
auto_equip: "\u{1F99E} {name} ({reason}) \u2192 auto-equipped {item}",
|
|
461
|
+
auto_swap: "\u{1F99E} {name} ({reason}) \u2192 swapped out {old} for {item}",
|
|
462
|
+
auto_discard: "\u{1F99E} {name} discarded {item} ({reason})",
|
|
463
|
+
equip_degrade: "\u{1F527} Worn: {items}",
|
|
464
|
+
equip_broken: "\u{1F4A5} Broken: {items}",
|
|
465
|
+
equip_inv_full: "\u{1F4E6} Inventory full({max}), discarded {item}",
|
|
466
|
+
equip_title: "\u{1F392} Equipment",
|
|
467
|
+
equip_slot_empty: " {icon} {slot}: (empty)",
|
|
468
|
+
equip_slot_item: " {icon} {slot}: {item}",
|
|
469
|
+
equip_inv_title: "\u{1F4E6} Inventory ({count}/{max}):",
|
|
470
|
+
equip_inv_item: " [{index}] {item}",
|
|
471
|
+
equip_inv_empty: " (empty)",
|
|
472
|
+
equip_equipped: "\u2705 Equipped {item} \u2192 {slot}",
|
|
473
|
+
equip_swapped: "\u{1F504} Swapped {old} \u2192 {item}",
|
|
474
|
+
equip_dropped: "\u{1F5D1}\uFE0F Discarded {item}",
|
|
475
|
+
equip_unequipped: "\u{1F4E4} Unequipped {item}",
|
|
476
|
+
equip_bad_index: "\u26A0\uFE0F Invalid index. Check: npx clawfight equip",
|
|
477
|
+
equip_usage: "Usage: equip / equip <index> / equip drop <index> / equip unequip <slot>",
|
|
478
|
+
achieve_unlock: "\u{1F3C6} Achievement: {name} \u2014 {desc}",
|
|
479
|
+
achieve_title: "\u{1F3C6} Achievements ({count}/{total}):",
|
|
480
|
+
achieve_item: " \u2705 {name} \u2014 {desc}",
|
|
481
|
+
achieve_locked: " \u{1F512} {name} \u2014 {desc}",
|
|
482
|
+
achieve_none: " No achievements yet. Keep exploring!",
|
|
483
|
+
patrol_depth: "\u{1F4CA} Lv.{level} | EXP:{exp}/{next} | Today:{today}/{cap} | Depth:{depth} | Bag:{inv}/{inv_max}",
|
|
484
|
+
depth_reset: "\u{1F4A4} Depth reset",
|
|
485
|
+
dg_connecting: "\u{1F4E1} Connecting to dungeon server...",
|
|
486
|
+
dg_resume: "\u{1F3F0} Active dungeon detected:",
|
|
487
|
+
dg_no_maps: "\u{1F5FA}\uFE0F No dungeon maps. Keep patrolling to find some!",
|
|
488
|
+
dg_bad_map_index: "\u26A0\uFE0F Invalid map index (have {count})",
|
|
489
|
+
dg_entering: "\u{1F3F0} Entering dungeon: {theme} | {rooms} rooms | {diff}",
|
|
490
|
+
dg_no_active: "\u26A0\uFE0F No active dungeon. Use explore to enter one.",
|
|
491
|
+
dg_complete: "\u{1F389} Dungeon cleared!",
|
|
492
|
+
dg_failed: "\u{1F480} Dungeon failed\u2026 HP reached zero",
|
|
493
|
+
dg_rewards_exp: "\u{1F4CA} Dungeon EXP: +{exp}",
|
|
494
|
+
dg_abandoning: "\u{1F3F3}\uFE0F Abandoning dungeon...",
|
|
495
|
+
dg_abandoned: "\u{1F3F3}\uFE0F Retreated | EXP+{exp} | Loot\xD7{loot} | Depth\u2192{depth}",
|
|
496
|
+
dg_maps_title: "\u{1F5FA}\uFE0F Dungeon maps ({count}):",
|
|
497
|
+
dg_rooms: " rooms",
|
|
498
|
+
dg_maps_hint: " \u{1F4A1} Usage: explore <index> to enter | explore maps to view",
|
|
499
|
+
dg_map_found: "\u{1F5FA}\uFE0F Found dungeon map: {theme} ({rooms} rooms, {diff})",
|
|
500
|
+
dg_summary: "\u{1F4CA} Lv.{level} | EXP:{exp}/{next} | Today:{today}/{cap}",
|
|
501
|
+
dg_theme_coral_maze: "Coral Maze",
|
|
502
|
+
dg_theme_deep_rift: "Deep Rift",
|
|
503
|
+
dg_theme_thermal_vent: "Thermal Vent",
|
|
504
|
+
dg_theme_ice_cavern: "Ice Cavern",
|
|
505
|
+
dg_theme_shipwreck: "Shipwreck",
|
|
506
|
+
dg_theme_abyss_trench: "Abyss Trench",
|
|
507
|
+
dg_theme_tide_pool: "Tide Pool",
|
|
508
|
+
dg_theme_void_rift: "Void Rift",
|
|
509
|
+
dg_risk_low: "Low",
|
|
510
|
+
dg_risk_mid: "Mid",
|
|
511
|
+
dg_risk_high: "High",
|
|
512
|
+
dg_diff_easy: "Easy",
|
|
513
|
+
dg_diff_normal: "Normal",
|
|
514
|
+
dg_diff_hard: "Hard",
|
|
515
|
+
dg_diff_nightmare: "Nightmare",
|
|
516
|
+
dg_charge_attack: "Charge Attack",
|
|
517
|
+
dg_defensive_stance: "Defensive Stance",
|
|
518
|
+
dg_rush_strike: "Rush Strike",
|
|
519
|
+
dg_counter_wait: "Counter Wait",
|
|
520
|
+
dg_open_golden_chest: "Open Golden Chest",
|
|
521
|
+
dg_open_stone_chest: "Open Stone Chest",
|
|
522
|
+
dg_reach_deep_cache: "Reach Deep Cache",
|
|
523
|
+
dg_take_surface_loot: "Take Surface Loot",
|
|
524
|
+
dg_disarm_mechanism: "Disarm Mechanism",
|
|
525
|
+
dg_dodge_through: "Dodge Through",
|
|
526
|
+
dg_brute_force: "Brute Force",
|
|
527
|
+
dg_careful_bypass: "Careful Bypass",
|
|
528
|
+
dg_deep_rest: "Deep Rest",
|
|
529
|
+
dg_search_hidden: "Search Hidden",
|
|
530
|
+
dg_investigate: "Investigate",
|
|
531
|
+
dg_proceed_cautiously: "Proceed Cautiously",
|
|
532
|
+
dg_touch_artifact: "Touch Artifact",
|
|
533
|
+
dg_observe_only: "Observe Only",
|
|
534
|
+
dg_all_out_assault: "All-Out Assault",
|
|
535
|
+
dg_tactical_approach: "Tactical Approach",
|
|
536
|
+
dg_bravery_bonus: "Bravery bonus: ATK+20%",
|
|
537
|
+
dg_curiosity_bonus: "Curiosity bonus: Discovery\u2191",
|
|
538
|
+
dg_temper_bonus: "Temper bonus: Disarm\u2191",
|
|
539
|
+
dg_charge_attack_success: "Charge hit!",
|
|
540
|
+
dg_charge_attack_fail: "Charge missed! Took {damage} damage",
|
|
541
|
+
dg_defensive_stance_success: "Defense held!",
|
|
542
|
+
dg_defensive_stance_fail: "Defense breached! Took {damage} damage",
|
|
543
|
+
dg_rush_strike_success: "Rush strike landed!",
|
|
544
|
+
dg_rush_strike_fail: "Rush failed! Took {damage} damage",
|
|
545
|
+
dg_counter_wait_success: "Counter hit!",
|
|
546
|
+
dg_counter_wait_fail: "Counter mistimed! Took {damage} damage",
|
|
547
|
+
dg_open_golden_chest_success: "Golden chest opened! Treasure shines",
|
|
548
|
+
dg_open_golden_chest_fail: "Trap triggered! Took {damage} damage",
|
|
549
|
+
dg_open_stone_chest_success: "Stone chest opened! Item found",
|
|
550
|
+
dg_open_stone_chest_fail: "Chest was empty...",
|
|
551
|
+
dg_reach_deep_cache_success: "Deep cache found!",
|
|
552
|
+
dg_reach_deep_cache_fail: "Deep search failed",
|
|
553
|
+
dg_take_surface_loot_success: "Surface loot collected!",
|
|
554
|
+
dg_take_surface_loot_fail: "Nothing found",
|
|
555
|
+
dg_disarm_mechanism_success: "Mechanism disarmed!",
|
|
556
|
+
dg_disarm_mechanism_fail: "Trap triggered! Took {damage} damage",
|
|
557
|
+
dg_dodge_through_success: "Dodged through the trap!",
|
|
558
|
+
dg_dodge_through_fail: "Dodge failed! Took {damage} damage",
|
|
559
|
+
dg_brute_force_success: "Brute force worked!",
|
|
560
|
+
dg_brute_force_fail: "Brute force failed! Took {damage} damage",
|
|
561
|
+
dg_careful_bypass_success: "Bypassed safely!",
|
|
562
|
+
dg_careful_bypass_fail: "Bypass failed\u2026",
|
|
563
|
+
dg_rest_healed: "Rested. HP+{heal}",
|
|
564
|
+
dg_search_hidden_success: "Found hidden item!",
|
|
565
|
+
dg_search_hidden_fail: "Search found nothing",
|
|
566
|
+
dg_investigate_success: "Investigation uncovered a secret!",
|
|
567
|
+
dg_investigate_fail: "Investigation found nothing",
|
|
568
|
+
dg_proceed_cautiously_success: "Proceeded safely",
|
|
569
|
+
dg_proceed_cautiously_fail: "Unexpected encounter! Took {damage} damage",
|
|
570
|
+
dg_touch_artifact_success: "Artifact releases power!",
|
|
571
|
+
dg_touch_artifact_fail: "Artifact backlash! Took {damage} damage",
|
|
572
|
+
dg_observe_only_success: "Observed useful clue",
|
|
573
|
+
dg_observe_only_fail: "Nothing observed",
|
|
574
|
+
dg_all_out_assault_success: "All-out assault devastated the Boss!",
|
|
575
|
+
dg_all_out_assault_fail: "Boss counterattacked! Took {damage} damage",
|
|
576
|
+
dg_tactical_approach_success: "Tactical approach found weakness!",
|
|
577
|
+
dg_tactical_approach_fail: "Boss saw through the strategy! Took {damage} damage"
|
|
313
578
|
};
|
|
314
579
|
function detectLocale() {
|
|
315
580
|
const lang = process.env.LANG || process.env.LANGUAGE || process.env.LC_ALL || "";
|
|
@@ -394,7 +659,15 @@ async function hatch(name) {
|
|
|
394
659
|
last_patrol: "",
|
|
395
660
|
last_battle: "",
|
|
396
661
|
today_exp: 0,
|
|
397
|
-
daily_exp_cap: 100
|
|
662
|
+
daily_exp_cap: 100,
|
|
663
|
+
equipped: {},
|
|
664
|
+
inventory: [],
|
|
665
|
+
depth: 0,
|
|
666
|
+
achievements: [],
|
|
667
|
+
dungeon_maps: [],
|
|
668
|
+
dungeons_completed: 0,
|
|
669
|
+
boss_kills: 0,
|
|
670
|
+
dungeon_epics_found: 0
|
|
398
671
|
};
|
|
399
672
|
await writeLobster(lobster);
|
|
400
673
|
const soulMd = buildSoulMarkdown(lobsterName, soul, rarity, "coastal");
|
|
@@ -419,6 +692,191 @@ async function hatch(name) {
|
|
|
419
692
|
console.log(t("hatch_next"));
|
|
420
693
|
}
|
|
421
694
|
|
|
695
|
+
// src/lib/equipment.ts
|
|
696
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
697
|
+
var SLOT_STATS = {
|
|
698
|
+
claw: ["attack", "speed"],
|
|
699
|
+
shell: ["hp", "defense"],
|
|
700
|
+
charm: ["luck", "intimidation"]
|
|
701
|
+
};
|
|
702
|
+
var NAMES = {
|
|
703
|
+
claw: {
|
|
704
|
+
common: ["\u94C1\u94B3\u5957", "\u77F3\u523A\u94B3", "\u78E8\u7259\u5957"],
|
|
705
|
+
rare: ["\u73CA\u745A\u523A\u94B3", "\u9CA8\u9F7F\u5957", "\u950B\u5203\u94B3"],
|
|
706
|
+
epic: ["\u6DF1\u6D77\u952F\u9F7F", "\u96F7\u9706\u4E4B\u94B3", "\u9F99\u9AA8\u94B3"],
|
|
707
|
+
legendary: ["\u6BC1\u706D\u4E4B\u94B3", "\u6D77\u795E\u4E4B\u63E1", "\u6DF7\u6C8C\u88C2\u722A"]
|
|
708
|
+
},
|
|
709
|
+
shell: {
|
|
710
|
+
common: ["\u77F3\u7532\u58F3", "\u786C\u76AE\u7532", "\u6CE5\u6C99\u76FE"],
|
|
711
|
+
rare: ["\u73CA\u745A\u94E0", "\u6D77\u85FB\u7EC7\u7532", "\u8D1D\u58F3\u76FE"],
|
|
712
|
+
epic: ["\u73CD\u73E0\u9F99\u94E0", "\u6DF1\u6E0A\u58F3\u7532", "\u51B0\u6676\u7532"],
|
|
713
|
+
legendary: ["\u4E0D\u706D\u7532\u58F3", "\u6D77\u795E\u4E4B\u94E0", "\u8679\u5149\u94E0"]
|
|
714
|
+
},
|
|
715
|
+
charm: {
|
|
716
|
+
common: ["\u5C0F\u6D77\u661F", "\u788E\u8D1D\u58F3", "\u6D77\u8349\u7ED3"],
|
|
717
|
+
rare: ["\u9CA8\u7259\u94FE", "\u73CA\u745A\u5760", "\u6F6E\u6C50\u73E0"],
|
|
718
|
+
epic: ["\u6DF1\u6D77\u4E4B\u773C", "\u96F7\u66B4\u6838", "\u5E7B\u6D77\u73E0"],
|
|
719
|
+
legendary: ["\u6D77\u795E\u4E4B\u5FC3", "\u547D\u8FD0\u4E4B\u73E0", "\u6DF7\u6C8C\u4E4B\u773C"]
|
|
720
|
+
}
|
|
721
|
+
};
|
|
722
|
+
var RARITY_MUL = { common: 1, rare: 2, epic: 3, legendary: 5 };
|
|
723
|
+
var RARITY_DUR = { common: 8, rare: 12, epic: 18, legendary: 30 };
|
|
724
|
+
var RARITY_POWER = { common: 1, rare: 1.5, epic: 2, legendary: 3 };
|
|
725
|
+
function pick(arr) {
|
|
726
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
727
|
+
}
|
|
728
|
+
function rollRarity2(depth, soul) {
|
|
729
|
+
const w = { ...EQUIP_RARITY_WEIGHTS };
|
|
730
|
+
w.rare += depth * 3;
|
|
731
|
+
w.epic += depth * 1.5;
|
|
732
|
+
w.legendary += depth * 0.5;
|
|
733
|
+
if (soul.talkativeness <= 3) {
|
|
734
|
+
w.rare += 5;
|
|
735
|
+
w.epic += 3;
|
|
736
|
+
w.legendary += 1;
|
|
737
|
+
}
|
|
738
|
+
const total = Object.values(w).reduce((a, b) => a + b, 0);
|
|
739
|
+
let roll = Math.random() * total;
|
|
740
|
+
for (const [r, weight] of Object.entries(w)) {
|
|
741
|
+
roll -= weight;
|
|
742
|
+
if (roll <= 0) return r;
|
|
743
|
+
}
|
|
744
|
+
return "common";
|
|
745
|
+
}
|
|
746
|
+
function rollLevel(depth, soul) {
|
|
747
|
+
let lv = Math.floor(depth / 3) + 1;
|
|
748
|
+
if (soul.curiosity >= 7) lv++;
|
|
749
|
+
return Math.min(5, Math.max(1, lv));
|
|
750
|
+
}
|
|
751
|
+
function generateEquipment(depth, soul) {
|
|
752
|
+
const slot = pick(["claw", "shell", "charm"]);
|
|
753
|
+
const rarity = rollRarity2(depth, soul);
|
|
754
|
+
const level = rollLevel(depth, soul);
|
|
755
|
+
const mul = RARITY_MUL[rarity];
|
|
756
|
+
const levelMul = 1 + (level - 1) * 0.3;
|
|
757
|
+
const keys = SLOT_STATS[slot];
|
|
758
|
+
let dur = RARITY_DUR[rarity];
|
|
759
|
+
if (soul.bravery <= 3) dur += 2;
|
|
760
|
+
const bonuses = {};
|
|
761
|
+
for (const k of keys) {
|
|
762
|
+
bonuses[k] = Math.ceil(Math.random() * 2 * mul * levelMul);
|
|
763
|
+
}
|
|
764
|
+
const allStats = ["hp", "attack", "defense", "speed", "intimidation", "luck"];
|
|
765
|
+
if (Math.random() < 0.2 * mul) {
|
|
766
|
+
const extra = allStats.filter((s) => !keys.includes(s));
|
|
767
|
+
if (extra.length) bonuses[pick(extra)] = Math.ceil(Math.random() * mul * levelMul);
|
|
768
|
+
}
|
|
769
|
+
return {
|
|
770
|
+
id: randomUUID2().slice(0, 8),
|
|
771
|
+
name: pick(NAMES[slot][rarity]),
|
|
772
|
+
slot,
|
|
773
|
+
rarity,
|
|
774
|
+
level,
|
|
775
|
+
bonuses,
|
|
776
|
+
durability: dur,
|
|
777
|
+
max_durability: dur
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
function powerScore(e) {
|
|
781
|
+
const sum = Object.values(e.bonuses).reduce((a, b) => a + (b ?? 0), 0);
|
|
782
|
+
const lv = e.level ?? 1;
|
|
783
|
+
return sum * RARITY_POWER[e.rarity] * lv * (e.durability / e.max_durability);
|
|
784
|
+
}
|
|
785
|
+
function shouldDrop(depth, soul) {
|
|
786
|
+
let chance = Math.min(0.8, 0.25 + depth * 0.05);
|
|
787
|
+
if (soul.bravery >= 7) chance += 0.1;
|
|
788
|
+
if (soul.bravery <= 3) chance -= 0.1;
|
|
789
|
+
return Math.random() < Math.max(0.05, chance);
|
|
790
|
+
}
|
|
791
|
+
function depthPenalty(soul) {
|
|
792
|
+
if (soul.temper >= 7) return 3;
|
|
793
|
+
if (soul.bravery >= 7) return 1;
|
|
794
|
+
return 2;
|
|
795
|
+
}
|
|
796
|
+
function winExpMultiplier(soul) {
|
|
797
|
+
if (soul.temper >= 7) return 1.2;
|
|
798
|
+
return 1;
|
|
799
|
+
}
|
|
800
|
+
function autoManageLoot(lobster, loot) {
|
|
801
|
+
const actions = [];
|
|
802
|
+
if (!lobster.equipped) lobster.equipped = {};
|
|
803
|
+
if (!lobster.inventory) lobster.inventory = [];
|
|
804
|
+
const current = lobster.equipped[loot.slot];
|
|
805
|
+
const lootPower = powerScore(loot);
|
|
806
|
+
if (!current) {
|
|
807
|
+
lobster.equipped[loot.slot] = loot;
|
|
808
|
+
actions.push({ type: "auto_equip", item: loot, reason: slotReason(lobster.soul, loot.slot) });
|
|
809
|
+
return actions;
|
|
810
|
+
}
|
|
811
|
+
const currentPower = powerScore(current);
|
|
812
|
+
if (lootPower > currentPower) {
|
|
813
|
+
lobster.equipped[loot.slot] = loot;
|
|
814
|
+
if (lobster.inventory.length < MAX_INVENTORY) {
|
|
815
|
+
lobster.inventory.push(current);
|
|
816
|
+
}
|
|
817
|
+
actions.push({ type: "auto_swap", item: loot, old: current, reason: slotReason(lobster.soul, loot.slot) });
|
|
818
|
+
return actions;
|
|
819
|
+
}
|
|
820
|
+
if (lobster.inventory.length < MAX_INVENTORY) {
|
|
821
|
+
lobster.inventory.push(loot);
|
|
822
|
+
return actions;
|
|
823
|
+
}
|
|
824
|
+
let worstIdx = -1;
|
|
825
|
+
let worstScore = Infinity;
|
|
826
|
+
for (let i = 0; i < lobster.inventory.length; i++) {
|
|
827
|
+
const s = powerScore(lobster.inventory[i]);
|
|
828
|
+
if (s < worstScore) {
|
|
829
|
+
worstScore = s;
|
|
830
|
+
worstIdx = i;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
if (worstIdx >= 0 && lootPower > worstScore) {
|
|
834
|
+
const discarded = lobster.inventory[worstIdx];
|
|
835
|
+
lobster.inventory[worstIdx] = loot;
|
|
836
|
+
actions.push({ type: "auto_discard", item: discarded, reason: "\u54C1\u8D28\u4E0D\u8DB3" });
|
|
837
|
+
} else {
|
|
838
|
+
actions.push({ type: "auto_discard", item: loot, reason: "\u54C1\u8D28\u4E0D\u8DB3" });
|
|
839
|
+
}
|
|
840
|
+
return actions;
|
|
841
|
+
}
|
|
842
|
+
function slotReason(soul, slot) {
|
|
843
|
+
if (slot === "claw" && soul.bravery >= 7) return "\u52C7\u731B\u672C\u80FD";
|
|
844
|
+
if (slot === "claw" && soul.temper >= 7) return "\u66B4\u8E81\u5929\u6027";
|
|
845
|
+
if (slot === "shell" && soul.bravery <= 3) return "\u8C28\u614E\u76F4\u89C9";
|
|
846
|
+
if (slot === "charm" && soul.curiosity >= 7) return "\u597D\u5947\u5FC3\u9A71\u4F7F";
|
|
847
|
+
return "\u81EA\u884C\u5224\u65AD";
|
|
848
|
+
}
|
|
849
|
+
function getEffectiveStats(lobster) {
|
|
850
|
+
const s = { ...lobster.stats };
|
|
851
|
+
if (!lobster.equipped) return s;
|
|
852
|
+
for (const eq of Object.values(lobster.equipped)) {
|
|
853
|
+
if (!eq || eq.durability <= 0) continue;
|
|
854
|
+
for (const [k, v] of Object.entries(eq.bonuses)) {
|
|
855
|
+
s[k] += v;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
return s;
|
|
859
|
+
}
|
|
860
|
+
function degradeEquipment(lobster) {
|
|
861
|
+
const broken = [];
|
|
862
|
+
if (!lobster.equipped) return broken;
|
|
863
|
+
for (const [slot, eq] of Object.entries(lobster.equipped)) {
|
|
864
|
+
if (!eq) continue;
|
|
865
|
+
eq.durability--;
|
|
866
|
+
if (eq.durability <= 0) {
|
|
867
|
+
broken.push(eq.name);
|
|
868
|
+
delete lobster.equipped[slot];
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
return broken;
|
|
872
|
+
}
|
|
873
|
+
function formatEquip(e) {
|
|
874
|
+
const lv = (e.level ?? 1) > 1 ? `+${e.level}` : "";
|
|
875
|
+
const label = EQUIP_RARITY_LABELS[e.rarity] || e.rarity;
|
|
876
|
+
const b = Object.entries(e.bonuses).map(([k, v]) => `${k}+${v}`).join(" ");
|
|
877
|
+
return `[${label}${lv}] ${e.name} ${b} (${e.durability}/${e.max_durability})`;
|
|
878
|
+
}
|
|
879
|
+
|
|
422
880
|
// src/commands/status.ts
|
|
423
881
|
function bar(current, max, width = 20) {
|
|
424
882
|
const filled = Math.round(current / Math.max(max, 1) * width);
|
|
@@ -433,6 +891,7 @@ async function status() {
|
|
|
433
891
|
const totalBattles = lobster.wins + lobster.losses;
|
|
434
892
|
const winRate = totalBattles > 0 ? Math.round(lobster.wins / totalBattles * 100) : 0;
|
|
435
893
|
const expPct = lobster.exp_to_next > 0 ? Math.round(lobster.exp / lobster.exp_to_next * 100) : 0;
|
|
894
|
+
const eff = getEffectiveStats(lobster);
|
|
436
895
|
const statusEmoji = {
|
|
437
896
|
active: "\u{1F7E2} \u6D3B\u8DC3",
|
|
438
897
|
molting: "\u{1F7E1} \u8715\u58F3\u4E2D",
|
|
@@ -443,28 +902,54 @@ async function status() {
|
|
|
443
902
|
console.log("\u251C" + "\u2500".repeat(44) + "\u2524");
|
|
444
903
|
console.log(`\u2502 \u7B49\u7EA7: Lv.${String(lobster.level).padEnd(5)} \u7A00\u6709\u5EA6: ${(RARITY_LABELS[lobster.rarity] || lobster.rarity).padEnd(15)}\u2502`);
|
|
445
904
|
console.log(`\u2502 \u72B6\u6001: ${(statusEmoji[lobster.status] || lobster.status).padEnd(36)}\u2502`);
|
|
446
|
-
console.log(`\u2502 \u73AF\u5883: ${lobster.environment.padEnd(
|
|
905
|
+
console.log(`\u2502 \u73AF\u5883: ${lobster.environment.padEnd(20)} \u6DF1\u5EA6: ${String(lobster.depth ?? 0).padEnd(13)}\u2502`);
|
|
447
906
|
console.log("\u251C" + "\u2500".repeat(44) + "\u2524");
|
|
448
907
|
console.log(`\u2502 EXP: ${bar(lobster.exp, lobster.exp_to_next)} ${String(expPct).padStart(3)}% \u2502`);
|
|
449
908
|
console.log(`\u2502 ${String(lobster.exp).padStart(5)} / ${String(lobster.exp_to_next).padEnd(28)}\u2502`);
|
|
450
909
|
console.log("\u251C" + "\u2500".repeat(44) + "\u2524");
|
|
451
|
-
console.log(`\u2502 \u2764\uFE0F HP: ${String(
|
|
452
|
-
console.log(`\u2502 \u{1F6E1}\uFE0F DEF: ${String(
|
|
453
|
-
console.log(`\u2502 \u{1F441}\uFE0F INT: ${String(
|
|
910
|
+
console.log(`\u2502 \u2764\uFE0F HP: ${String(eff.hp).padEnd(6)} \u2694\uFE0F ATK: ${String(eff.attack).padEnd(15)}\u2502`);
|
|
911
|
+
console.log(`\u2502 \u{1F6E1}\uFE0F DEF: ${String(eff.defense).padEnd(6)} \u{1F4A8} SPD: ${String(eff.speed).padEnd(15)}\u2502`);
|
|
912
|
+
console.log(`\u2502 \u{1F441}\uFE0F INT: ${String(eff.intimidation).padEnd(6)} \u{1F340} LCK: ${String(eff.luck).padEnd(15)}\u2502`);
|
|
454
913
|
console.log("\u251C" + "\u2500".repeat(44) + "\u2524");
|
|
455
914
|
console.log(`\u2502 \u6218\u7EE9: ${lobster.wins}\u80DC ${lobster.losses}\u8D1F (\u80DC\u7387${winRate}%)${" ".repeat(Math.max(0, 20 - String(lobster.wins).length - String(lobster.losses).length - String(winRate).length))}\u2502`);
|
|
456
915
|
console.log(`\u2502 \u8FDE\u80DC: ${lobster.streak} \u58F0\u671B: ${lobster.reputation} \u5DE1\u903B: ${lobster.patrol_count}${" ".repeat(Math.max(0, 15 - String(lobster.streak).length - String(lobster.reputation).length - String(lobster.patrol_count).length))}\u2502`);
|
|
916
|
+
const slots = ["claw", "shell", "charm"];
|
|
917
|
+
const hasEquip = slots.some((s) => lobster.equipped?.[s]);
|
|
918
|
+
if (hasEquip) {
|
|
919
|
+
console.log("\u251C" + "\u2500".repeat(44) + "\u2524");
|
|
920
|
+
for (const s of slots) {
|
|
921
|
+
const eq = lobster.equipped?.[s];
|
|
922
|
+
const label = `${SLOT_ICONS[s]} ${SLOT_LABELS[s]}`;
|
|
923
|
+
const lv = eq && (eq.level ?? 1) > 1 ? `+${eq.level}` : "";
|
|
924
|
+
const info = eq ? `${eq.name}${lv}(${eq.durability}/${eq.max_durability})` : "-";
|
|
925
|
+
console.log(`\u2502 ${label}: ${info.padEnd(36)}\u2502`);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
const invCount = lobster.inventory?.length ?? 0;
|
|
929
|
+
if (invCount > 0) {
|
|
930
|
+
console.log(`\u2502 \u{1F4E6} \u80CC\u5305: ${invCount}/${MAX_INVENTORY}${" ".repeat(31 - String(invCount).length - String(MAX_INVENTORY).length)}\u2502`);
|
|
931
|
+
}
|
|
457
932
|
console.log("\u251C" + "\u2500".repeat(44) + "\u2524");
|
|
458
933
|
console.log(`\u2502 \u6027\u683C: \u2502`);
|
|
459
934
|
console.log(`\u2502 \u52C7\u6C14 ${lobster.soul.bravery}/10 | \u597D\u5947 ${lobster.soul.curiosity}/10 | \u8BDD\u91CF ${lobster.soul.talkativeness}/10 | \u813E\u6C14 ${lobster.soul.temper}/10 \u2502`);
|
|
935
|
+
const mapCount = lobster.dungeon_maps?.length ?? 0;
|
|
936
|
+
const dgCompleted = lobster.dungeons_completed ?? 0;
|
|
937
|
+
if (mapCount > 0 || dgCompleted > 0) {
|
|
938
|
+
console.log(`\u2502 \u{1F3F0} \u5730\u4E0B\u57CE: ${dgCompleted}\u901A\u5173 \u{1F5FA}\uFE0F \u5730\u56FE: ${mapCount}${" ".repeat(Math.max(0, 19 - String(dgCompleted).length - String(mapCount).length))}\u2502`);
|
|
939
|
+
}
|
|
940
|
+
if (lobster.active_dungeon) {
|
|
941
|
+
console.log(`\u2502 \u26A1 \u8FDB\u884C\u4E2D\u5730\u4E0B\u57CE: \u6709${" ".repeat(24)}\u2502`);
|
|
942
|
+
}
|
|
943
|
+
const achieveCount = lobster.achievements?.length ?? 0;
|
|
944
|
+
if (achieveCount > 0) {
|
|
945
|
+
console.log(`\u2502 \u{1F3C6} \u6210\u5C31: ${achieveCount}${" ".repeat(33 - String(achieveCount).length)}\u2502`);
|
|
946
|
+
}
|
|
460
947
|
console.log("\u2514" + "\u2500".repeat(44) + "\u2518");
|
|
461
948
|
console.log("\n" + t("status_battle_code", { code: lobster.id.slice(0, 8) }));
|
|
462
949
|
const soulText = await readSoul();
|
|
463
950
|
if (soulText) {
|
|
464
951
|
const firstLine = soulText.split("\n").find((l) => l.trim() && !l.startsWith("#"));
|
|
465
|
-
if (firstLine) {
|
|
466
|
-
console.log(`\u{1F4DC} \u7075\u9B42: ${firstLine.trim().slice(0, 60)}`);
|
|
467
|
-
}
|
|
952
|
+
if (firstLine) console.log(`\u{1F4DC} \u7075\u9B42: ${firstLine.trim().slice(0, 60)}`);
|
|
468
953
|
}
|
|
469
954
|
}
|
|
470
955
|
|
|
@@ -472,7 +957,7 @@ async function status() {
|
|
|
472
957
|
import { createHash } from "crypto";
|
|
473
958
|
var API_BASE = "https://api.clawfight.online";
|
|
474
959
|
function statsHash(lobster) {
|
|
475
|
-
const raw = JSON.stringify(lobster
|
|
960
|
+
const raw = JSON.stringify(getEffectiveStats(lobster));
|
|
476
961
|
return createHash("sha256").update(raw).digest("hex");
|
|
477
962
|
}
|
|
478
963
|
function getProxyUrl() {
|
|
@@ -507,7 +992,7 @@ async function apiPatrol(lobster) {
|
|
|
507
992
|
lobster_id: lobster.id,
|
|
508
993
|
level: lobster.level,
|
|
509
994
|
stats_hash: statsHash(lobster),
|
|
510
|
-
stats: lobster
|
|
995
|
+
stats: getEffectiveStats(lobster),
|
|
511
996
|
environment: lobster.environment,
|
|
512
997
|
name: lobster.name,
|
|
513
998
|
color: lobster.rarity,
|
|
@@ -556,6 +1041,74 @@ async function apiLeaderboard(limit = 20) {
|
|
|
556
1041
|
return null;
|
|
557
1042
|
}
|
|
558
1043
|
}
|
|
1044
|
+
async function apiDungeonEnter(lobster, theme) {
|
|
1045
|
+
try {
|
|
1046
|
+
const pfetch = await getProxiedFetch();
|
|
1047
|
+
const res = await pfetch(`${API_BASE}/api/dungeon/enter`, {
|
|
1048
|
+
method: "POST",
|
|
1049
|
+
headers: { "Content-Type": "application/json; charset=utf-8" },
|
|
1050
|
+
body: JSON.stringify({
|
|
1051
|
+
lobster_id: lobster.id,
|
|
1052
|
+
level: lobster.level,
|
|
1053
|
+
stats: getEffectiveStats(lobster),
|
|
1054
|
+
soul: lobster.soul,
|
|
1055
|
+
depth: lobster.depth ?? 0,
|
|
1056
|
+
environment: lobster.environment,
|
|
1057
|
+
theme
|
|
1058
|
+
}),
|
|
1059
|
+
signal: AbortSignal.timeout(1e4)
|
|
1060
|
+
});
|
|
1061
|
+
if (!res.ok) {
|
|
1062
|
+
const err = await res.json();
|
|
1063
|
+
return { error: err.error };
|
|
1064
|
+
}
|
|
1065
|
+
return await res.json();
|
|
1066
|
+
} catch {
|
|
1067
|
+
return null;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
async function apiDungeonAct(dungeonId, lobsterId, choice) {
|
|
1071
|
+
try {
|
|
1072
|
+
const pfetch = await getProxiedFetch();
|
|
1073
|
+
const res = await pfetch(`${API_BASE}/api/dungeon/act`, {
|
|
1074
|
+
method: "POST",
|
|
1075
|
+
headers: { "Content-Type": "application/json; charset=utf-8" },
|
|
1076
|
+
body: JSON.stringify({ dungeon_id: dungeonId, lobster_id: lobsterId, choice }),
|
|
1077
|
+
signal: AbortSignal.timeout(1e4)
|
|
1078
|
+
});
|
|
1079
|
+
if (!res.ok) return null;
|
|
1080
|
+
return await res.json();
|
|
1081
|
+
} catch {
|
|
1082
|
+
return null;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
async function apiDungeonState(lobsterId) {
|
|
1086
|
+
try {
|
|
1087
|
+
const pfetch = await getProxiedFetch();
|
|
1088
|
+
const res = await pfetch(`${API_BASE}/api/dungeon/state?lobster_id=${lobsterId}`, {
|
|
1089
|
+
signal: AbortSignal.timeout(1e4)
|
|
1090
|
+
});
|
|
1091
|
+
if (!res.ok) return null;
|
|
1092
|
+
return await res.json();
|
|
1093
|
+
} catch {
|
|
1094
|
+
return null;
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
async function apiDungeonAbandon(lobsterId) {
|
|
1098
|
+
try {
|
|
1099
|
+
const pfetch = await getProxiedFetch();
|
|
1100
|
+
const res = await pfetch(`${API_BASE}/api/dungeon/abandon`, {
|
|
1101
|
+
method: "POST",
|
|
1102
|
+
headers: { "Content-Type": "application/json; charset=utf-8" },
|
|
1103
|
+
body: JSON.stringify({ lobster_id: lobsterId }),
|
|
1104
|
+
signal: AbortSignal.timeout(1e4)
|
|
1105
|
+
});
|
|
1106
|
+
if (!res.ok) return null;
|
|
1107
|
+
return await res.json();
|
|
1108
|
+
} catch {
|
|
1109
|
+
return null;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
559
1112
|
|
|
560
1113
|
// src/lib/events.ts
|
|
561
1114
|
import { readFile as readFile2 } from "fs/promises";
|
|
@@ -595,11 +1148,11 @@ async function rollEvent(lobster) {
|
|
|
595
1148
|
});
|
|
596
1149
|
if (candidates.length === 0) return null;
|
|
597
1150
|
const totalWeight = candidates.reduce((s, c) => s + c.probability, 0);
|
|
598
|
-
let
|
|
1151
|
+
let pick2 = Math.random() * totalWeight;
|
|
599
1152
|
let chosen = null;
|
|
600
1153
|
for (const c of candidates) {
|
|
601
|
-
|
|
602
|
-
if (
|
|
1154
|
+
pick2 -= c.probability;
|
|
1155
|
+
if (pick2 <= 0) {
|
|
603
1156
|
chosen = c;
|
|
604
1157
|
break;
|
|
605
1158
|
}
|
|
@@ -630,6 +1183,43 @@ function applyEventEffects(lobster, effects) {
|
|
|
630
1183
|
return changes;
|
|
631
1184
|
}
|
|
632
1185
|
|
|
1186
|
+
// src/lib/achievements.ts
|
|
1187
|
+
var ACHIEVEMENTS = {
|
|
1188
|
+
first_blood: { name: "\u521D\u6218\u544A\u6377", desc: "\u8D62\u5F97\u9996\u80DC", check: (l) => l.wins >= 1 },
|
|
1189
|
+
veteran: { name: "\u6C99\u573A\u8001\u5175", desc: "10\u80DC", check: (l) => l.wins >= 10 },
|
|
1190
|
+
warlord: { name: "\u6DF1\u6D77\u6218\u795E", desc: "50\u80DC", check: (l) => l.wins >= 50 },
|
|
1191
|
+
explorer: { name: "\u6D77\u57DF\u63A2\u7D22\u8005", desc: "20\u6B21\u5DE1\u903B", check: (l) => l.patrol_count >= 20 },
|
|
1192
|
+
deep_diver: { name: "\u6DF1\u6F5C\u8005", desc: "\u6DF1\u5EA65", check: (l) => (l.depth ?? 0) >= 5 },
|
|
1193
|
+
abyss_walker: { name: "\u6DF1\u6E0A\u884C\u8005", desc: "\u6DF1\u5EA610", check: (l) => (l.depth ?? 0) >= 10 },
|
|
1194
|
+
fully_armed: { name: "\u5168\u526F\u6B66\u88C5", desc: "\u88C5\u5907\u6EE13\u69FD", check: (l) => {
|
|
1195
|
+
if (!l.equipped) return false;
|
|
1196
|
+
return !!(l.equipped.claw && l.equipped.shell && l.equipped.charm);
|
|
1197
|
+
} },
|
|
1198
|
+
survivor: { name: "\u767E\u6298\u4E0D\u6320", desc: "\u7D2F\u8BA110\u8D1F\u540E\u4ECD\u5728\u6218\u6597", check: (l) => l.losses >= 10 && l.wins > 0 },
|
|
1199
|
+
streak_5: { name: "\u52BF\u4E0D\u53EF\u6321", desc: "5\u8FDE\u80DC", check: (l) => l.streak >= 5 },
|
|
1200
|
+
streak_10: { name: "\u65E0\u4EBA\u80FD\u654C", desc: "10\u8FDE\u80DC", check: (l) => l.streak >= 10 },
|
|
1201
|
+
high_level: { name: "\u738B\u8005\u9F99\u867E", desc: "\u8FBE\u523010\u7EA7", check: (l) => l.level >= 10 },
|
|
1202
|
+
molt_master: { name: "\u8715\u53D8\u5927\u5E08", desc: "\u8715\u58F33\u6B21", check: (l) => l.molt_count >= 3 },
|
|
1203
|
+
first_dungeon: { name: "\u521D\u63A2\u5730\u4E0B\u57CE", desc: "\u5B8C\u6210\u9996\u4E2A\u5730\u4E0B\u57CE", check: (l) => (l.dungeons_completed ?? 0) >= 1 },
|
|
1204
|
+
dungeon_master: { name: "\u5730\u4E0B\u57CE\u4E4B\u738B", desc: "\u5B8C\u621010\u4E2A\u5730\u4E0B\u57CE", check: (l) => (l.dungeons_completed ?? 0) >= 10 },
|
|
1205
|
+
boss_slayer: { name: "Boss\u730E\u624B", desc: "\u51FB\u8D25\u5730\u4E0B\u57CEBoss", check: (l) => (l.boss_kills ?? 0) >= 1 },
|
|
1206
|
+
perfect_run: { name: "\u5B8C\u7F8E\u901A\u5173", desc: "\u6EE1HP\u901A\u5173\u5730\u4E0B\u57CE", check: () => false },
|
|
1207
|
+
treasure_hunter: { name: "\u5BFB\u5B9D\u730E\u4EBA", desc: "\u5728\u5730\u4E0B\u57CE\u83B7\u5F975\u4EF6\u53F2\u8BD7+\u88C5\u5907", check: (l) => (l.dungeon_epics_found ?? 0) >= 5 }
|
|
1208
|
+
};
|
|
1209
|
+
function checkAchievements(lobster) {
|
|
1210
|
+
const unlocked = [];
|
|
1211
|
+
const existing = new Set(lobster.achievements ?? []);
|
|
1212
|
+
for (const [id, def] of Object.entries(ACHIEVEMENTS)) {
|
|
1213
|
+
if (existing.has(id)) continue;
|
|
1214
|
+
if (def.check(lobster)) {
|
|
1215
|
+
unlocked.push(id);
|
|
1216
|
+
if (!lobster.achievements) lobster.achievements = [];
|
|
1217
|
+
lobster.achievements.push(id);
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
return unlocked;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
633
1223
|
// src/commands/patrol.ts
|
|
634
1224
|
var PATROL_EXP = 15;
|
|
635
1225
|
async function patrol() {
|
|
@@ -648,10 +1238,12 @@ async function patrol() {
|
|
|
648
1238
|
}
|
|
649
1239
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
650
1240
|
const lastDay = lobster.last_patrol ? lobster.last_patrol.split("T")[0] : "";
|
|
651
|
-
if (today !== lastDay)
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
1241
|
+
if (today !== lastDay) lobster.today_exp = 0;
|
|
1242
|
+
const depth = lobster.depth ?? 0;
|
|
1243
|
+
const soul = lobster.soul;
|
|
1244
|
+
const trait = soulTag(soul);
|
|
1245
|
+
console.log("\n" + t("patrol_start", { name: lobster.name }) + ` [${t("depth_display", { depth })}]`);
|
|
1246
|
+
if (trait) console.log(t("soul_trait", { trait }));
|
|
655
1247
|
console.log("\u2500".repeat(40));
|
|
656
1248
|
const expGain = Math.min(PATROL_EXP, lobster.daily_exp_cap - lobster.today_exp);
|
|
657
1249
|
if (expGain > 0) {
|
|
@@ -665,9 +1257,7 @@ async function patrol() {
|
|
|
665
1257
|
console.log(t("event_prefix", { category: eventResult.event.category, id: eventResult.event.id }));
|
|
666
1258
|
console.log(` ${eventResult.narrative}`);
|
|
667
1259
|
const changes = applyEventEffects(lobster, eventResult.event.effects);
|
|
668
|
-
if (changes.length > 0) {
|
|
669
|
-
console.log(t("event_effects", { changes: changes.join(", ") }));
|
|
670
|
-
}
|
|
1260
|
+
if (changes.length > 0) console.log(t("event_effects", { changes: changes.join(", ") }));
|
|
671
1261
|
await appendLog(`\u{1F3B2} ${eventResult.event.id}: ${eventResult.narrative.slice(0, 60)}...`);
|
|
672
1262
|
}
|
|
673
1263
|
checkLevelUp(lobster);
|
|
@@ -691,8 +1281,12 @@ async function patrol() {
|
|
|
691
1281
|
lobster.losses++;
|
|
692
1282
|
lobster.streak = Math.min(0, lobster.streak) - 1;
|
|
693
1283
|
lobster.reputation = Math.max(0, lobster.reputation - 1);
|
|
1284
|
+
const penalty = depthPenalty(soul);
|
|
1285
|
+
lobster.depth = Math.max(0, (lobster.depth ?? 0) - penalty);
|
|
694
1286
|
}
|
|
695
|
-
|
|
1287
|
+
let battleExp = br.exp_gain;
|
|
1288
|
+
if (br.result === "win") battleExp = Math.floor(battleExp * winExpMultiplier(soul));
|
|
1289
|
+
battleExp = Math.min(battleExp, lobster.daily_exp_cap - lobster.today_exp);
|
|
696
1290
|
if (battleExp > 0) {
|
|
697
1291
|
lobster.exp += battleExp;
|
|
698
1292
|
lobster.today_exp += battleExp;
|
|
@@ -700,6 +1294,8 @@ async function patrol() {
|
|
|
700
1294
|
lobster.last_battle = (/* @__PURE__ */ new Date()).toISOString();
|
|
701
1295
|
console.log(t("patrol_exp_stats", { exp: battleExp, wins: lobster.wins, losses: lobster.losses, streak: lobster.streak }));
|
|
702
1296
|
await appendLog(`\u2694\uFE0F VS ${opp.name}(Lv.${opp.level}) \u2192 ${br.result} (${br.rounds}R)`);
|
|
1297
|
+
const broken = degradeEquipment(lobster);
|
|
1298
|
+
if (broken.length) console.log(t("equip_broken", { items: broken.join(", ") }));
|
|
703
1299
|
checkLevelUp(lobster);
|
|
704
1300
|
} else if (serverResponse.encounter && serverResponse.opponent) {
|
|
705
1301
|
console.log(t("patrol_no_battle", { name: serverResponse.opponent.name, level: serverResponse.opponent.level }));
|
|
@@ -709,9 +1305,86 @@ async function patrol() {
|
|
|
709
1305
|
} else {
|
|
710
1306
|
console.log(t("patrol_offline"));
|
|
711
1307
|
}
|
|
1308
|
+
lobster.depth = (lobster.depth ?? 0) + 1;
|
|
1309
|
+
if (shouldDrop(depth, soul)) {
|
|
1310
|
+
const loot = generateEquipment(depth, soul);
|
|
1311
|
+
console.log(t("equip_drop", { item: formatEquip(loot) }));
|
|
1312
|
+
await appendLog(`\u{1F381} ${loot.rarity}+${loot.level} ${loot.name}`);
|
|
1313
|
+
const actions = autoManageLoot(lobster, loot);
|
|
1314
|
+
for (const a of actions) {
|
|
1315
|
+
switch (a.type) {
|
|
1316
|
+
case "auto_equip":
|
|
1317
|
+
console.log(t("auto_equip", { name: lobster.name, item: formatEquip(a.item), reason: a.reason }));
|
|
1318
|
+
break;
|
|
1319
|
+
case "auto_swap":
|
|
1320
|
+
console.log(t("auto_swap", { name: lobster.name, item: formatEquip(a.item), old: a.old.name, reason: a.reason }));
|
|
1321
|
+
break;
|
|
1322
|
+
case "auto_discard":
|
|
1323
|
+
console.log(t("auto_discard", { name: lobster.name, item: a.item.name, reason: a.reason }));
|
|
1324
|
+
break;
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
if (shouldDropMap(lobster.depth ?? 0, lobster.soul)) {
|
|
1329
|
+
const map = generateMap(lobster.depth ?? 0, lobster.environment);
|
|
1330
|
+
if (!lobster.dungeon_maps) lobster.dungeon_maps = [];
|
|
1331
|
+
if (lobster.dungeon_maps.length < 5) {
|
|
1332
|
+
lobster.dungeon_maps.push(map);
|
|
1333
|
+
console.log(t("dg_map_found", { theme: t(`dg_theme_${map.theme}`), rooms: map.rooms, diff: t(`dg_diff_${map.difficulty}`) }));
|
|
1334
|
+
await appendLog(`\u{1F5FA}\uFE0F \u53D1\u73B0\u5730\u56FE: ${map.theme} (${map.rooms}\u623F\u95F4, ${map.difficulty})`);
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
const newAchievements = checkAchievements(lobster);
|
|
1338
|
+
for (const id of newAchievements) {
|
|
1339
|
+
const def = ACHIEVEMENTS[id];
|
|
1340
|
+
console.log(t("achieve_unlock", { name: def.name, desc: def.desc }));
|
|
1341
|
+
}
|
|
712
1342
|
await writeLobster(lobster);
|
|
713
1343
|
console.log("\u2500".repeat(40));
|
|
714
|
-
|
|
1344
|
+
const inv = lobster.inventory?.length ?? 0;
|
|
1345
|
+
console.log(t("patrol_depth", {
|
|
1346
|
+
level: lobster.level,
|
|
1347
|
+
exp: lobster.exp,
|
|
1348
|
+
next: lobster.exp_to_next,
|
|
1349
|
+
today: lobster.today_exp,
|
|
1350
|
+
cap: lobster.daily_exp_cap,
|
|
1351
|
+
depth: lobster.depth ?? 0,
|
|
1352
|
+
inv,
|
|
1353
|
+
inv_max: MAX_INVENTORY
|
|
1354
|
+
}));
|
|
1355
|
+
}
|
|
1356
|
+
function soulTag(soul) {
|
|
1357
|
+
const tags = [];
|
|
1358
|
+
if (soul.bravery >= 7) tags.push("\u52C7\u731B");
|
|
1359
|
+
if (soul.bravery <= 3) tags.push("\u8C28\u614E");
|
|
1360
|
+
if (soul.curiosity >= 7) tags.push("\u535A\u5B66");
|
|
1361
|
+
if (soul.curiosity <= 3) tags.push("\u4E13\u6CE8");
|
|
1362
|
+
if (soul.talkativeness <= 3) tags.push("\u9690\u533F");
|
|
1363
|
+
if (soul.temper >= 7) tags.push("\u66B4\u70C8");
|
|
1364
|
+
if (soul.temper <= 3) tags.push("\u6C89\u7A33");
|
|
1365
|
+
return tags.join("\xB7");
|
|
1366
|
+
}
|
|
1367
|
+
var ENV_THEMES = {
|
|
1368
|
+
coastal: ["coral_maze", "shipwreck", "tide_pool"],
|
|
1369
|
+
"deep-sea": ["deep_rift", "abyss_trench"],
|
|
1370
|
+
"hot-spring": ["thermal_vent", "coral_maze"],
|
|
1371
|
+
polar: ["ice_cavern", "deep_rift"],
|
|
1372
|
+
space: ["void_rift", "abyss_trench"],
|
|
1373
|
+
freshwater: ["tide_pool", "coral_maze"]
|
|
1374
|
+
};
|
|
1375
|
+
function shouldDropMap(depth, soul) {
|
|
1376
|
+
let chance = Math.min(0.5, 0.1 + depth * 0.03);
|
|
1377
|
+
if (soul.curiosity >= 7) chance += 0.1;
|
|
1378
|
+
return Math.random() < chance;
|
|
1379
|
+
}
|
|
1380
|
+
function generateMap(depth, environment) {
|
|
1381
|
+
const themes = ENV_THEMES[environment] || ENV_THEMES.coastal;
|
|
1382
|
+
const theme = themes[Math.floor(Math.random() * themes.length)];
|
|
1383
|
+
const rooms = Math.min(5, 3 + Math.floor(depth / 5));
|
|
1384
|
+
const difficulties = ["easy", "normal", "hard", "nightmare"];
|
|
1385
|
+
const di = Math.min(3, Math.floor(depth / 3));
|
|
1386
|
+
const difficulty = difficulties[di];
|
|
1387
|
+
return { theme, rooms, difficulty };
|
|
715
1388
|
}
|
|
716
1389
|
function checkLevelUp(lobster) {
|
|
717
1390
|
const l = lobster;
|
|
@@ -894,6 +1567,8 @@ async function rest() {
|
|
|
894
1567
|
}
|
|
895
1568
|
lobster.status = "hibernating";
|
|
896
1569
|
lobster.hibernated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
1570
|
+
const hadDepth = lobster.depth && lobster.depth > 0;
|
|
1571
|
+
if (hadDepth) lobster.depth = 0;
|
|
897
1572
|
await writeLobster(lobster);
|
|
898
1573
|
await appendLog(`\u{1F4A4} ${lobster.name} \u2192 hibernation`);
|
|
899
1574
|
console.log("\n" + "\u2500".repeat(40));
|
|
@@ -901,6 +1576,7 @@ async function rest() {
|
|
|
901
1576
|
console.log(t("rest_desc2"));
|
|
902
1577
|
console.log(t("rest_desc3"));
|
|
903
1578
|
console.log(t("rest_desc4"));
|
|
1579
|
+
if (hadDepth) console.log(t("depth_reset"));
|
|
904
1580
|
console.log("\u2500".repeat(40));
|
|
905
1581
|
console.log("\n" + t("rest_wake_hint"));
|
|
906
1582
|
}
|
|
@@ -952,9 +1628,358 @@ async function wake() {
|
|
|
952
1628
|
console.log("\n" + t("wake_ready", { name: lobster.name }));
|
|
953
1629
|
}
|
|
954
1630
|
|
|
1631
|
+
// src/commands/equip.ts
|
|
1632
|
+
var SLOTS = ["claw", "shell", "charm"];
|
|
1633
|
+
async function equip(action, arg) {
|
|
1634
|
+
const lobster = await readLobster();
|
|
1635
|
+
if (!lobster) {
|
|
1636
|
+
console.log("\n" + t("no_lobster"));
|
|
1637
|
+
return;
|
|
1638
|
+
}
|
|
1639
|
+
if (!lobster.equipped) lobster.equipped = {};
|
|
1640
|
+
if (!lobster.inventory) lobster.inventory = [];
|
|
1641
|
+
if (!action) {
|
|
1642
|
+
console.log("\n" + t("equip_title"));
|
|
1643
|
+
console.log("\u2500".repeat(40));
|
|
1644
|
+
for (const s of SLOTS) {
|
|
1645
|
+
const eq = lobster.equipped[s];
|
|
1646
|
+
if (eq) {
|
|
1647
|
+
console.log(t("equip_slot_item", { icon: SLOT_ICONS[s], slot: SLOT_LABELS[s], item: formatEquip(eq) }));
|
|
1648
|
+
} else {
|
|
1649
|
+
console.log(t("equip_slot_empty", { icon: SLOT_ICONS[s], slot: SLOT_LABELS[s] }));
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
console.log();
|
|
1653
|
+
console.log(t("equip_inv_title", { count: lobster.inventory.length, max: MAX_INVENTORY }));
|
|
1654
|
+
if (lobster.inventory.length === 0) {
|
|
1655
|
+
console.log(t("equip_inv_empty"));
|
|
1656
|
+
} else {
|
|
1657
|
+
for (let i = 0; i < lobster.inventory.length; i++) {
|
|
1658
|
+
console.log(t("equip_inv_item", { index: i + 1, item: formatEquip(lobster.inventory[i]) }));
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
console.log("\u2500".repeat(40));
|
|
1662
|
+
console.log(t("equip_usage"));
|
|
1663
|
+
return;
|
|
1664
|
+
}
|
|
1665
|
+
if (action === "drop") {
|
|
1666
|
+
const idx2 = parseInt(arg || "", 10) - 1;
|
|
1667
|
+
if (isNaN(idx2) || idx2 < 0 || idx2 >= lobster.inventory.length) {
|
|
1668
|
+
console.log("\n" + t("equip_bad_index"));
|
|
1669
|
+
return;
|
|
1670
|
+
}
|
|
1671
|
+
const removed = lobster.inventory.splice(idx2, 1)[0];
|
|
1672
|
+
await writeLobster(lobster);
|
|
1673
|
+
console.log("\n" + t("equip_dropped", { item: formatEquip(removed) }));
|
|
1674
|
+
return;
|
|
1675
|
+
}
|
|
1676
|
+
if (action === "unequip") {
|
|
1677
|
+
const slot = arg;
|
|
1678
|
+
if (!slot || !SLOTS.includes(slot)) {
|
|
1679
|
+
console.log("\n" + t("equip_bad_index"));
|
|
1680
|
+
return;
|
|
1681
|
+
}
|
|
1682
|
+
const eq = lobster.equipped[slot];
|
|
1683
|
+
if (!eq) {
|
|
1684
|
+
console.log("\n" + t("equip_slot_empty", { icon: SLOT_ICONS[slot], slot: SLOT_LABELS[slot] }));
|
|
1685
|
+
return;
|
|
1686
|
+
}
|
|
1687
|
+
if (lobster.inventory.length >= MAX_INVENTORY) {
|
|
1688
|
+
console.log("\n" + t("equip_inv_full", { max: MAX_INVENTORY, item: eq.name }));
|
|
1689
|
+
return;
|
|
1690
|
+
}
|
|
1691
|
+
lobster.inventory.push(eq);
|
|
1692
|
+
delete lobster.equipped[slot];
|
|
1693
|
+
await writeLobster(lobster);
|
|
1694
|
+
console.log("\n" + t("equip_unequipped", { item: formatEquip(eq) }));
|
|
1695
|
+
return;
|
|
1696
|
+
}
|
|
1697
|
+
const idx = parseInt(action, 10) - 1;
|
|
1698
|
+
if (isNaN(idx) || idx < 0 || idx >= lobster.inventory.length) {
|
|
1699
|
+
console.log("\n" + t("equip_bad_index"));
|
|
1700
|
+
return;
|
|
1701
|
+
}
|
|
1702
|
+
const item = lobster.inventory[idx];
|
|
1703
|
+
const existing = lobster.equipped[item.slot];
|
|
1704
|
+
lobster.inventory.splice(idx, 1);
|
|
1705
|
+
lobster.equipped[item.slot] = item;
|
|
1706
|
+
if (existing) {
|
|
1707
|
+
lobster.inventory.push(existing);
|
|
1708
|
+
await writeLobster(lobster);
|
|
1709
|
+
console.log("\n" + t("equip_swapped", { old: existing.name, item: formatEquip(item) }));
|
|
1710
|
+
} else {
|
|
1711
|
+
await writeLobster(lobster);
|
|
1712
|
+
console.log("\n" + t("equip_equipped", { item: formatEquip(item), slot: SLOT_LABELS[item.slot] }));
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
// src/commands/achievements.ts
|
|
1717
|
+
async function achievements() {
|
|
1718
|
+
const lobster = await readLobster();
|
|
1719
|
+
if (!lobster) {
|
|
1720
|
+
console.log("\n" + t("no_lobster"));
|
|
1721
|
+
return;
|
|
1722
|
+
}
|
|
1723
|
+
const unlocked = new Set(lobster.achievements ?? []);
|
|
1724
|
+
const total = Object.keys(ACHIEVEMENTS).length;
|
|
1725
|
+
console.log("\n" + t("achieve_title", { count: unlocked.size, total }));
|
|
1726
|
+
console.log("\u2500".repeat(40));
|
|
1727
|
+
for (const [id, def] of Object.entries(ACHIEVEMENTS)) {
|
|
1728
|
+
if (unlocked.has(id)) {
|
|
1729
|
+
console.log(t("achieve_item", { name: def.name, desc: def.desc }));
|
|
1730
|
+
} else {
|
|
1731
|
+
console.log(t("achieve_locked", { name: def.name, desc: def.desc }));
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
console.log("\u2500".repeat(40));
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
// src/commands/explore.ts
|
|
1738
|
+
var RISK_ICON = { low: "\u{1F7E2}", mid: "\u{1F7E1}", high: "\u{1F534}" };
|
|
1739
|
+
var THEME_ICON = {
|
|
1740
|
+
coral_maze: "\u{1FAB8}",
|
|
1741
|
+
deep_rift: "\u{1F30A}",
|
|
1742
|
+
thermal_vent: "\u{1F30B}",
|
|
1743
|
+
ice_cavern: "\u2744\uFE0F",
|
|
1744
|
+
shipwreck: "\u{1F6A2}",
|
|
1745
|
+
abyss_trench: "\u{1F573}\uFE0F",
|
|
1746
|
+
tide_pool: "\u{1F3D6}\uFE0F",
|
|
1747
|
+
void_rift: "\u{1F300}"
|
|
1748
|
+
};
|
|
1749
|
+
function formatRoom(room, theme) {
|
|
1750
|
+
const icon = THEME_ICON[theme] || "\u{1F3D4}\uFE0F";
|
|
1751
|
+
const lines = [];
|
|
1752
|
+
lines.push(`${icon} ${t(`dg_theme_${theme}`)} | ${room.index + 1}/${room.total} | HP:${room.hp.current}/${room.hp.max}`);
|
|
1753
|
+
const c1 = room.choices[0];
|
|
1754
|
+
const c2 = room.choices[1];
|
|
1755
|
+
lines.push(` [1] ${t(`dg_${c1.key}`)} (${c1.stat.toUpperCase()}, ${RISK_ICON[c1.risk]}${t(`dg_risk_${c1.risk}`)}) [2] ${t(`dg_${c2.key}`)} (${c2.stat.toUpperCase()}, ${RISK_ICON[c2.risk]}${t(`dg_risk_${c2.risk}`)})`);
|
|
1756
|
+
if (c1.soul_hint) lines.push(` \u{1F99E} ${t(`dg_${c1.soul_hint}`)}`);
|
|
1757
|
+
if (c2.soul_hint) lines.push(` \u{1F99E} ${t(`dg_${c2.soul_hint}`)}`);
|
|
1758
|
+
return lines.join("\n");
|
|
1759
|
+
}
|
|
1760
|
+
function lootToEquipment(l) {
|
|
1761
|
+
return { ...l, id: Math.random().toString(36).slice(2, 10) };
|
|
1762
|
+
}
|
|
1763
|
+
async function explore(action) {
|
|
1764
|
+
const lobster = await readLobster();
|
|
1765
|
+
if (!lobster) {
|
|
1766
|
+
console.log("\n" + t("no_lobster"));
|
|
1767
|
+
return;
|
|
1768
|
+
}
|
|
1769
|
+
if (lobster.status === "molting") {
|
|
1770
|
+
console.log("\n" + t("status_cant_patrol_molt", { name: lobster.name }));
|
|
1771
|
+
return;
|
|
1772
|
+
}
|
|
1773
|
+
if (lobster.status === "hibernating") {
|
|
1774
|
+
console.log("\n" + t("status_cant_patrol_hibernate", { name: lobster.name }));
|
|
1775
|
+
return;
|
|
1776
|
+
}
|
|
1777
|
+
if (action === "abandon") {
|
|
1778
|
+
return await abandonDungeon(lobster);
|
|
1779
|
+
}
|
|
1780
|
+
if (action === "1" || action === "2") {
|
|
1781
|
+
return await makeChoice(lobster, parseInt(action));
|
|
1782
|
+
}
|
|
1783
|
+
if (action === "maps") {
|
|
1784
|
+
return showMaps(lobster);
|
|
1785
|
+
}
|
|
1786
|
+
return await enterOrResume(lobster, action);
|
|
1787
|
+
}
|
|
1788
|
+
async function enterOrResume(lobster, mapIndex) {
|
|
1789
|
+
console.log("\n" + t("dg_connecting"));
|
|
1790
|
+
const stateRes = await apiDungeonState(lobster.id);
|
|
1791
|
+
if (!stateRes) {
|
|
1792
|
+
console.log(t("patrol_offline"));
|
|
1793
|
+
return;
|
|
1794
|
+
}
|
|
1795
|
+
if (stateRes.active && stateRes.room) {
|
|
1796
|
+
console.log(t("dg_resume"));
|
|
1797
|
+
console.log(formatRoom(stateRes.room, stateRes.theme));
|
|
1798
|
+
return;
|
|
1799
|
+
}
|
|
1800
|
+
const maps = lobster.dungeon_maps || [];
|
|
1801
|
+
if (maps.length === 0) {
|
|
1802
|
+
console.log(t("dg_no_maps"));
|
|
1803
|
+
return;
|
|
1804
|
+
}
|
|
1805
|
+
let idx = 0;
|
|
1806
|
+
if (mapIndex && !isNaN(parseInt(mapIndex))) {
|
|
1807
|
+
idx = parseInt(mapIndex) - 1;
|
|
1808
|
+
if (idx < 0 || idx >= maps.length) {
|
|
1809
|
+
console.log(t("dg_bad_map_index", { count: maps.length }));
|
|
1810
|
+
return;
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
const map = maps[idx];
|
|
1814
|
+
console.log(t("dg_entering", { theme: t(`dg_theme_${map.theme}`), rooms: map.rooms, diff: t(`dg_diff_${map.difficulty}`) }));
|
|
1815
|
+
const res = await apiDungeonEnter(lobster, map.theme);
|
|
1816
|
+
if (!res) {
|
|
1817
|
+
console.log(t("patrol_offline"));
|
|
1818
|
+
return;
|
|
1819
|
+
}
|
|
1820
|
+
if (res.error) {
|
|
1821
|
+
console.log(`\u26A0\uFE0F ${res.error}`);
|
|
1822
|
+
return;
|
|
1823
|
+
}
|
|
1824
|
+
lobster.active_dungeon = res.dungeon_id;
|
|
1825
|
+
maps.splice(idx, 1);
|
|
1826
|
+
lobster.dungeon_maps = maps;
|
|
1827
|
+
await writeLobster(lobster);
|
|
1828
|
+
await appendLog(`\u{1F5FA}\uFE0F \u8FDB\u5165\u5730\u4E0B\u57CE: ${map.theme} (${map.rooms}\u623F\u95F4)`);
|
|
1829
|
+
console.log("\u2500".repeat(40));
|
|
1830
|
+
console.log(formatRoom(res.room, res.theme));
|
|
1831
|
+
}
|
|
1832
|
+
async function makeChoice(lobster, choice) {
|
|
1833
|
+
if (!lobster.active_dungeon) {
|
|
1834
|
+
console.log("\n" + t("dg_no_active"));
|
|
1835
|
+
return;
|
|
1836
|
+
}
|
|
1837
|
+
console.log("");
|
|
1838
|
+
const res = await apiDungeonAct(lobster.active_dungeon, lobster.id, choice);
|
|
1839
|
+
if (!res) {
|
|
1840
|
+
console.log(t("patrol_offline"));
|
|
1841
|
+
return;
|
|
1842
|
+
}
|
|
1843
|
+
const o = res.outcome;
|
|
1844
|
+
const icon = o.success ? "\u2705" : "\u274C";
|
|
1845
|
+
console.log(`${icon} ${t(`dg_${o.key}`, { damage: o.damage_taken, heal: o.hp_healed })} | EXP+${o.exp_gained}`);
|
|
1846
|
+
if (o.damage_taken > 0) console.log(` \u{1F494} HP -${o.damage_taken} \u2192 ${res.hp.current}/${res.hp.max}`);
|
|
1847
|
+
if (o.hp_healed > 0) console.log(` \u{1F49A} HP +${o.hp_healed} \u2192 ${res.hp.current}/${res.hp.max}`);
|
|
1848
|
+
if (o.soul_activated) console.log(` \u{1F99E} ${t(`dg_${o.soul_activated}`)}`);
|
|
1849
|
+
if (o.loot) {
|
|
1850
|
+
const equip2 = lootToEquipment(o.loot);
|
|
1851
|
+
console.log(` ${t("equip_drop", { item: formatEquip(equip2) })}`);
|
|
1852
|
+
}
|
|
1853
|
+
if (res.status === "completed" || res.status === "failed") {
|
|
1854
|
+
console.log("\u2500".repeat(40));
|
|
1855
|
+
if (res.status === "completed") {
|
|
1856
|
+
console.log(t("dg_complete"));
|
|
1857
|
+
lobster.dungeons_completed = (lobster.dungeons_completed ?? 0) + 1;
|
|
1858
|
+
} else {
|
|
1859
|
+
console.log(t("dg_failed"));
|
|
1860
|
+
}
|
|
1861
|
+
if (res.rewards) {
|
|
1862
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1863
|
+
const lastDay = lobster.last_patrol ? lobster.last_patrol.split("T")[0] : "";
|
|
1864
|
+
if (today !== lastDay) lobster.today_exp = 0;
|
|
1865
|
+
const expGain = Math.min(res.rewards.total_exp, lobster.daily_exp_cap - lobster.today_exp);
|
|
1866
|
+
if (expGain > 0) {
|
|
1867
|
+
lobster.exp += expGain;
|
|
1868
|
+
lobster.today_exp += expGain;
|
|
1869
|
+
}
|
|
1870
|
+
console.log(t("dg_rewards_exp", { exp: expGain }));
|
|
1871
|
+
for (const loot of res.rewards.loot) {
|
|
1872
|
+
const equip2 = lootToEquipment(loot);
|
|
1873
|
+
console.log(` ${t("equip_drop", { item: formatEquip(equip2) })}`);
|
|
1874
|
+
if (loot.rarity === "epic" || loot.rarity === "legendary") {
|
|
1875
|
+
lobster.dungeon_epics_found = (lobster.dungeon_epics_found ?? 0) + 1;
|
|
1876
|
+
}
|
|
1877
|
+
const actions = autoManageLoot(lobster, equip2);
|
|
1878
|
+
for (const a of actions) {
|
|
1879
|
+
if (a.type === "auto_equip") console.log(` ${t("auto_equip", { name: lobster.name, item: formatEquip(a.item), reason: a.reason })}`);
|
|
1880
|
+
else if (a.type === "auto_swap") console.log(` ${t("auto_swap", { name: lobster.name, item: formatEquip(a.item), old: a.old.name, reason: a.reason })}`);
|
|
1881
|
+
else if (a.type === "auto_discard") console.log(` ${t("auto_discard", { name: lobster.name, item: a.item.name, reason: a.reason })}`);
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
checkLevelUp2(lobster);
|
|
1885
|
+
for (const loot of res.rewards.loot) {
|
|
1886
|
+
if (loot.rarity === "epic" || loot.rarity === "legendary") {
|
|
1887
|
+
const room = res.rewards.loot.indexOf(loot);
|
|
1888
|
+
if (room === res.rewards.loot.length - 1) {
|
|
1889
|
+
lobster.boss_kills = (lobster.boss_kills ?? 0) + 1;
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
await appendLog(`\u{1F3F0} \u5730\u4E0B\u57CE${res.status === "completed" ? "\u901A\u5173" : "\u5931\u8D25"}: EXP+${expGain}, \u6218\u5229\u54C1\xD7${res.rewards.loot.length}`);
|
|
1894
|
+
}
|
|
1895
|
+
lobster.active_dungeon = void 0;
|
|
1896
|
+
const newAch = checkAchievements(lobster);
|
|
1897
|
+
for (const id of newAch) {
|
|
1898
|
+
const def = ACHIEVEMENTS[id];
|
|
1899
|
+
console.log(t("achieve_unlock", { name: def.name, desc: def.desc }));
|
|
1900
|
+
}
|
|
1901
|
+
await writeLobster(lobster);
|
|
1902
|
+
console.log(t("dg_summary", {
|
|
1903
|
+
level: lobster.level,
|
|
1904
|
+
exp: lobster.exp,
|
|
1905
|
+
next: lobster.exp_to_next,
|
|
1906
|
+
today: lobster.today_exp,
|
|
1907
|
+
cap: lobster.daily_exp_cap
|
|
1908
|
+
}));
|
|
1909
|
+
return;
|
|
1910
|
+
}
|
|
1911
|
+
if (res.next_room) {
|
|
1912
|
+
console.log("\u2500".repeat(40));
|
|
1913
|
+
const stateRes = await apiDungeonState(lobster.id);
|
|
1914
|
+
const theme = stateRes?.theme || "";
|
|
1915
|
+
console.log(formatRoom(res.next_room, theme));
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
async function abandonDungeon(lobster) {
|
|
1919
|
+
if (!lobster.active_dungeon) {
|
|
1920
|
+
console.log("\n" + t("dg_no_active"));
|
|
1921
|
+
return;
|
|
1922
|
+
}
|
|
1923
|
+
console.log("\n" + t("dg_abandoning"));
|
|
1924
|
+
const res = await apiDungeonAbandon(lobster.id);
|
|
1925
|
+
if (!res) {
|
|
1926
|
+
console.log(t("patrol_offline"));
|
|
1927
|
+
return;
|
|
1928
|
+
}
|
|
1929
|
+
const expGain = Math.min(res.partial_exp, lobster.daily_exp_cap - lobster.today_exp);
|
|
1930
|
+
if (expGain > 0) {
|
|
1931
|
+
lobster.exp += expGain;
|
|
1932
|
+
lobster.today_exp += expGain;
|
|
1933
|
+
}
|
|
1934
|
+
for (const loot of res.partial_loot) {
|
|
1935
|
+
const equip2 = lootToEquipment(loot);
|
|
1936
|
+
autoManageLoot(lobster, equip2);
|
|
1937
|
+
}
|
|
1938
|
+
lobster.active_dungeon = void 0;
|
|
1939
|
+
const penalty = Math.max(0, (lobster.depth ?? 0) - 2);
|
|
1940
|
+
lobster.depth = penalty;
|
|
1941
|
+
await writeLobster(lobster);
|
|
1942
|
+
await appendLog(`\u{1F3F0} \u653E\u5F03\u5730\u4E0B\u57CE: EXP+${expGain}, \u6DF1\u5EA6\u2192${lobster.depth}`);
|
|
1943
|
+
console.log(t("dg_abandoned", { exp: expGain, loot: res.partial_loot.length, depth: lobster.depth }));
|
|
1944
|
+
}
|
|
1945
|
+
function showMaps(lobster) {
|
|
1946
|
+
const maps = lobster.dungeon_maps || [];
|
|
1947
|
+
if (maps.length === 0) {
|
|
1948
|
+
console.log("\n" + t("dg_no_maps"));
|
|
1949
|
+
return;
|
|
1950
|
+
}
|
|
1951
|
+
console.log("\n" + t("dg_maps_title", { count: maps.length }));
|
|
1952
|
+
for (let i = 0; i < maps.length; i++) {
|
|
1953
|
+
const m = maps[i];
|
|
1954
|
+
const icon = THEME_ICON[m.theme] || "\u{1F3D4}\uFE0F";
|
|
1955
|
+
console.log(` [${i + 1}] ${icon} ${t(`dg_theme_${m.theme}`)} | ${m.rooms}${t("dg_rooms")} | ${t(`dg_diff_${m.difficulty}`)}`);
|
|
1956
|
+
}
|
|
1957
|
+
console.log(t("dg_maps_hint"));
|
|
1958
|
+
}
|
|
1959
|
+
function checkLevelUp2(lobster) {
|
|
1960
|
+
while (lobster.exp >= lobster.exp_to_next) {
|
|
1961
|
+
lobster.exp -= lobster.exp_to_next;
|
|
1962
|
+
lobster.level++;
|
|
1963
|
+
lobster.exp_to_next = calcExpToNext(lobster.level);
|
|
1964
|
+
const statKeys = ["hp", "attack", "defense", "speed", "intimidation", "luck"];
|
|
1965
|
+
const gains = [];
|
|
1966
|
+
for (const key of statKeys) {
|
|
1967
|
+
const gain = 1 + Math.floor(Math.random() * 3);
|
|
1968
|
+
lobster.stats[key] += gain;
|
|
1969
|
+
gains.push(`${key}+${gain}`);
|
|
1970
|
+
}
|
|
1971
|
+
console.log("\n" + t("level_up", { level: lobster.level, gains: gains.join(", ") }));
|
|
1972
|
+
if (lobster.level % 5 === 0) {
|
|
1973
|
+
console.log(t("molt_trigger"));
|
|
1974
|
+
lobster.status = "molting";
|
|
1975
|
+
lobster.molt_count++;
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
|
|
955
1980
|
// src/index.ts
|
|
956
1981
|
var program = new Command();
|
|
957
|
-
program.name("clawfight").description("\u{1F99E} ClawFight \u2014 \u9F99\u867E\u7535\u5B50\u5BA0\u7269\u5BF9\u6218").version("1.
|
|
1982
|
+
program.name("clawfight").description("\u{1F99E} ClawFight \u2014 \u9F99\u867E\u7535\u5B50\u5BA0\u7269\u5BF9\u6218").version("1.5.0");
|
|
958
1983
|
program.command("hatch").description("\u5B75\u5316\u4E00\u53EA\u65B0\u9F99\u867E").argument("[name]", "\u4E3A\u9F99\u867E\u53D6\u540D").action(async (name) => {
|
|
959
1984
|
await hatch(name);
|
|
960
1985
|
});
|
|
@@ -979,4 +2004,13 @@ program.command("rest").description("\u8FDB\u5165\u4F11\u7720\uFF08\u6682\u505C\
|
|
|
979
2004
|
program.command("wake").description("\u4ECE\u4F11\u7720\u4E2D\u5524\u9192\uFF08\u9644\u5E26\u6062\u590D\u52A0\u6210\uFF09").action(async () => {
|
|
980
2005
|
await wake();
|
|
981
2006
|
});
|
|
2007
|
+
program.command("equip").description("\u88C5\u5907\u7BA1\u7406\uFF08\u67E5\u770B/\u7A7F\u6234/\u5378\u4E0B/\u4E22\u5F03\uFF09").argument("[action]", "\u7F16\u53F7(\u88C5\u5907) / drop / unequip").argument("[arg]", "\u7F16\u53F7\u6216\u69FD\u4F4D(claw/shell/charm)").action(async (action, arg) => {
|
|
2008
|
+
await equip(action, arg);
|
|
2009
|
+
});
|
|
2010
|
+
program.command("achievements").alias("ach").description("\u67E5\u770B\u6210\u5C31").action(async () => {
|
|
2011
|
+
await achievements();
|
|
2012
|
+
});
|
|
2013
|
+
program.command("explore").alias("dg").description("\u5730\u4E0B\u57CE\u63A2\u7D22\uFF08\u8FDB\u5165/\u9009\u62E9/\u653E\u5F03/\u67E5\u770B\u5730\u56FE\uFF09").argument("[action]", "1|2(\u9009\u62E9) / abandon(\u653E\u5F03) / maps(\u67E5\u770B\u5730\u56FE) / \u5730\u56FE\u7F16\u53F7(\u8FDB\u5165)").action(async (action) => {
|
|
2014
|
+
await explore(action);
|
|
2015
|
+
});
|
|
982
2016
|
program.parse();
|