PageSourceSearch

https://the-torchbearer.netlify.app/src/main.js?v=27Jul-TB8

js the-torchbearer.netlify.app collected 2026-10-03 11:30:43 UTC 6,806 bytes, 207 lines download raw bytes

1/* The Torchbearer — game config and run state.
2 *
3 * Run state is a single object rebuilt wholesale by SK.resetRun(), which is
4 * what guarantees a restart is truly clean: shards, HP, floor, score and
5 * stats all come back from one place.
6 */
7window.SK = window.SK || {};
8
9// Defaults in case a scene reads settings before MenuScene has loaded.
10SK.settings = SK.settings || { muted:false, music:true, shake:true,
11  shader:true, damageNumbers:true, minimap:true };
12
13SK.BUILD = '27Jul-TB8';
14SK.HIGH_KEY = 'shadowKingCrownfall.highScore';
15SK.DAILY_KEY = 'shadowKingCrownfall.daily.';
16
17/* Playtest shortcut, off unless ?dev=1 is in the URL. */
18SK.DEV = /[?&]dev=1/.test(window.location.search);
19
20SK.newRun = function (mode, classId) {
21  mode = mode || 'free';
22  var seedKey = SK.installRng(mode);
23  var cls = SK.CLASSES[classId || SK.chosenClass || SK.DEFAULT_CLASS];
24  var mods = SK.computeMods([], [], cls.id);
25  var maxHp = Math.max(1, cls.hp + mods.maxHpBonus - mods.startHpPenalty);
26  return {
27    mode: mode,
28    seedKey: seedKey,
29    floor: 0,
30    loop: 0,
31    score: 0,
32    hp: maxHp,
33    maxHp: maxHp,
34    shardIds: [],
35    pool: SK.SHARDS.map(function (s) { return s.id; }),
36    mods: mods,
37    classId: cls.id,
38    weaponId: cls.weapon,
39    weaponLevels: (function () { var o = {}; o[cls.weapon] = 1; return o; })(),
40    // id -> index into SK.RARITIES. You start with plain gear.
41    weaponRarities: (function () { var o = {}; o[cls.weapon] = 0; return o; })(),
42    weaponSuffixes: {},        // weapon id -> suffix id
43    power: 0,                  // rises as you clear; see SK.powerMods
44    armourId: 'none', armourRarity: 0,
45    trinketId: 'none', trinketRarity: 0,
46    inventory: [],          // consumable ids, up to SK.INVENTORY_SLOTS
47    artifactIds: [],        // permanent Sovereign drops
48    quirkIds: [],           // what the crypt did to you
49    coins: 0,
50    buffs: {},              // active timed effects, keyed by kind
51    bought: [],             // one-time shop purchases already made
52    shopFuryStart: 0,       // Wrath Sigil
53    shopCoinMult: 1,        // Greedy Palm
54    stats: {
55      kills: 0, elites: 0, bosses: 0, bestChain: 0, parries: 0, ultimates: 0,
56      roomsCleared: 0, damageTaken: 0, startedAt: Date.now()
57    }
58  };
59};
60
61SK.resetRun = function (mode, classId) {
62  SK.run = SK.newRun(mode, classId);
63  if (SK.game) SK.game.registry.set('run', SK.run);
64  return SK.run;
65};
66
67/* Taking a shard recomputes mods from the FULL shard list — never
68 * incremental, so an effect can't be applied twice across scenes. */
69SK.takeShard = function (run, id) {
70  if (run.shardIds.indexOf(id) !== -1) return run;
71
72  run.shardIds.push(id);
73  var at = run.pool.indexOf(id);
74  if (at !== -1) run.pool.splice(at, 1);
75
76  // Single recompute path (see SK.refreshRun): folds shards, artifacts, quirks
77  // AND worn gear. Iron Heart heals as it is taken; Ember Pact bites, but
78  // never to zero.
79  return SK.refreshRun(run);
80};
81
82/* ---- localStorage: never allowed to throw (private mode) ---------------- */
83
84SK.getHigh = function () {
85  try {
86    return parseInt(window.localStorage.getItem(SK.HIGH_KEY), 10) || 0;
87  } catch (e) { return 0; }
88};
89
90SK.setHigh = function (v) {
91  try {
92    window.localStorage.setItem(SK.HIGH_KEY, String(v));
93    return true;
94  } catch (e) { return false; }
95};
96
97SK.getDailyHigh = function (dayKey) {
98  try {
99    return parseInt(window.localStorage.getItem(SK.DAILY_KEY + dayKey), 10) || 0;
100  } catch (e) { return 0; }
101};
102
103SK.setDailyHigh = function (dayKey, v) {
104  try {
105    window.localStorage.setItem(SK.DAILY_KEY + dayKey, String(v));
106    return true;
107  } catch (e) { return false; }
108};
109
110/* ---- Phaser ------------------------------------------------------------ */
111
112SK.WIDTH = 800;
113SK.HEIGHT = 600;
114
115/* Boot integrity check.
116 *
117 * The scripts are separate files with no bundler, so a browser can serve a
118 * fresh DungeonScene.js next to a cached juice.js. The game then half-works
119 * and throws several seconds into play, which reads as a game bug and is not.
120 * Check the API surface up front and say plainly what is wrong.
121 */
122SK.REQUIRED_API = [
123  ['juice.coach', function () { return SK.juice && SK.juice.coach; }],
124  ['juice.telegraph', function () { return SK.juice && SK.juice.telegraph; }],
125  ['ui.panel', function () { return SK.ui && SK.ui.panel; }],
126  ['ui.keycap', function () { return SK.ui && SK.ui.keycap; }],
127  ['Sheet', function () { return SK.Sheet; }],
128  ['refreshRun', function () { return SK.refreshRun; }],
129  ['gearMods', function () { return SK.gearMods; }],
130  ['safeConsumable', function () { return SK.safeConsumable; }],
131  ['weaponFullName', function () { return SK.weaponFullName; }],
132  ['enemyName', function () { return SK.enemyName; }],
133  ['rollRarity', function () { return SK.rollRarity; }]
134];
135
136SK.checkApi = function () {
137  return SK.REQUIRED_API
138    .filter(function (r) { return !r[1](); })
139    .map(function (r) { return r[0]; });
140};
141
142window.addEventListener('load', function () {
143  if (!window.Phaser) return; // CDN fallback message already shown
144
145  var missing = SK.checkApi();
146  if (missing.length) {
147    var el = document.createElement('div');
148    el.style.cssText = 'position:fixed;inset:0;z-index:9999;background:#1a0f0c;' +
149      'color:#ffd45e;font:15px/1.6 system-ui,sans-serif;padding:40px;';
150    el.innerHTML = '<b style="font-size:20px">Stale files in the browser cache</b>' +
151      '<p>These scripts are out of date: <code>' + missing.join(', ') + '</code></p>' +
152      '<p>Hard-refresh to fix: <b>Cmd+Shift+R</b> (Mac) or <b>Ctrl+F5</b> (Windows).</p>' +
153      '<p style="color:#a8977d">Build ' + SK.BUILD + '. This is a caching problem, ' +
154      'not a fault in the game.</p>';
155    document.body.appendChild(el);
156    return;
157  }
158
159
160  SK.settings = SK.loadSettings();
161  SK.run = SK.newRun('free');
162
163  SK.game = new Phaser.Game({
164    type: Phaser.AUTO,
165    width: SK.WIDTH,
166    height: SK.HEIGHT,
167    backgroundColor: SK.CSS.void,
168    parent: 'game',
169    physics: {
170      default: 'arcade',
171      arcade: { debug: false }
172    },
173    scale: {
174      mode: Phaser.Scale.FIT,
175      autoCenter: Phaser.Scale.CENTER_BOTH
176    },
177    // Crisp pixel art: nearest-neighbour scaling, no smoothing.
178    pixelArt: true,
179    render: {
180      pixelArt: true,
181      antialias: false,
182      antialiasGL: false,
183      roundPixels: true
184    },
185    scene: [
186      SK.BootScene,
187      SK.TitleScene,
188      SK.LoadScene,
189      SK.DungeonScene,
190      SK.AspirantScene,
191      SK.ClassScene,
192      SK.MenuScene,
193      SK.LeaderScene,
194      SK.NameScene,
195      SK.ShardScene,
196      SK.ShopScene,
197      SK.EndScene
198    ]
199  });
200
201  SK.game.registry.set('run', SK.run);
202
203  // WebGL-only post-processing; silently absent under Canvas.
204  SK.game.events.once('ready', function () {
205    SK.registerShaders(SK.game);
206  });
207});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.