Examples
Examples
Labs, cards, uptime, enemy stats, saves, modules, Effective Paths, and the package glossary.
Lab Costs
Coins and research time for the next levels.
Live
- Coin cost (levels 0 → 10)
- 18.759K
- Research time
- 15h 45m
10 levels · lab max 99
Code
import { LAB_CATALOG } from 'thetowersdk/data'
import { formatNumberForDisplay } from 'thetowersdk/formatting'
// Find the lab by its display name
const lab = LAB_CATALOG.find((l) => l.name === 'Attack Speed')
// Levels are 0-based in the array; level 10 → index 10
const from = 10
const steps = 10
const next = lab.levels.slice(from, from + steps)
// Each level has a coin cost
const coins = next.reduce((sum, level) => sum + level.cost, 0)
// Format like the game (1.1q, 2.3s, …)
console.log(formatNumberForDisplay(coins))Death Wave × Golden Bot
DW duration comes from Quantity × 4s per wave; results match the Uptime Calculator columns.
Live
| Source | Cooldown | Duration | Uptime |
|---|---|---|---|
| Death Wave | 220s | 16s (4 × 4s) | 7.3% |
| Golden Bot | 90s | 25s | 27.8% |
Code
import { BOT_UPGRADES_DATA, estimateBotUptimeFraction, uwStoneChartData } from 'thetowersdk/data'
const dw = Object.values(uwStoneChartData).find((w) => w.name === 'Death Wave')
const dwCd = Number(String(dw.stats.find((s) => s.name === 'Cooldown').levels[8].value).replace(/s$/i, ''))
const dwWaves = Number(String(dw.stats.find((s) => s.name === 'Quantity').levels[3].value).replace(/^x/i, ''))
const dwDur = dwWaves * 4 // Uptime Calculator wave time
const gb = BOT_UPGRADES_DATA.find((b) => b.name === 'Golden Bot')
const gbCd = gb.stats.Cooldown.levels['10']
const gbDur = gb.stats.Duration.levels['10']
const gbUptime = estimateBotUptimeFraction(gbDur, gbCd)
console.log({ dwCd, dwDur, gbCd, gbDur, gbUptime })Enemy Stats
Base health and damage for a farm tier or tournament league base.
Live
- Base enemy health
- 1.343S
- Base enemy damage
- 110.445T
Code
import {
computeWaveBaseHealth,
computeWaveBaseDamage,
} from 'thetowersdk/mechanics'
import { formatNumberForDisplay } from 'thetowersdk/formatting'
// Farm tier 10, or tournament Copper as tier 1 + tournament:true
const hp = computeWaveBaseHealth({ tier: 10, wave: 4500, tournament: false })
const dmg = computeWaveBaseDamage({ tier: 10, wave: 4500, tournament: false })
console.log(formatNumberForDisplay(hp))
console.log(formatNumberForDisplay(dmg))Read A Save
Sample extractor shapes from a decoded playerInfo.dat (decode runs in Node).
Sample
Decode playerInfo.dat, then pull labs, modules, cards, ultimate weapons, bots,
vault, relics, lifetime stats, and battle reports from the same root:
{
"labs": {
"researchedCount": 142,
"maxedCount": 38,
"bySlug": {
"attack_speed": 45,
"labs_speed": 99
}
},
"modules": {
"owned": 48,
"equipped": {
"cannon": "Dimension Core",
"armor": "Anti-Cube Portal",
"generator": "Galaxy Compressor",
"core": "Sharp Fortitude"
}
},
"cards": {
"unlocked": 62,
"masteriesStarted": 11
},
"ultimateWeapons": {
"unlocked": [
"Golden Tower",
"Black Hole",
"Death Wave",
"Chrono Field"
],
"stonesSpent": 18420
},
"bots": {
"unlocked": [
"Golden Bot",
"Flame Bot",
"Thunder Bot"
],
"medalsSpent": 3200
},
"vault": {
"harmonyNodes": 18,
"powerNodes": 12
},
"relics": {
"owned": 27
},
"lifetime": {
"totalWaves": 2450000,
"highestTier": {
"farm": 18,
"tournament": "Champion"
}
},
"battleReports": {
"recentRuns": 40
},
"warnings": [
"cards extractor: save predates card mastery fields"
]
} thetowersdk/node decodes the file; thetowersdk/save extractors return typed slices (plus warnings when a field is missing or legacy).
Code
import { readFile } from 'node:fs/promises'
import { decodePlayerInfoSaveBytes } from 'thetowersdk/node'
import {
readLabsFromSaveRoot,
readModulesFromSaveRoot,
readCardsFromSaveRoot,
readUltimateWeaponsFromSaveRoot,
readBotsFromSaveRoot,
readVaultFromSaveRoot,
} from 'thetowersdk/save'
const { parsedRoot } = decodePlayerInfoSaveBytes(
await readFile('playerInfo.dat')
)
const labs = readLabsFromSaveRoot(parsedRoot)
const modules = readModulesFromSaveRoot(parsedRoot)
const cards = readCardsFromSaveRoot(parsedRoot)
const uws = readUltimateWeaponsFromSaveRoot(parsedRoot)
const bots = readBotsFromSaveRoot(parsedRoot)
const vault = readVaultFromSaveRoot(parsedRoot)Generate A Cost Table
Level, value, cost and running total, generated from the catalog.
Live
Shards to level 161
5K
Code
import { uwStoneChartData } from 'thetowersdk/data'
import { formatNumberForDisplay } from 'thetowersdk/formatting'
const gt = Object.values(uwStoneChartData).find((w) => w.name === 'Golden Tower')
const multiplier = gt.stats.find((s) => s.name === 'Multiplier')
// Level, value, cost, running total — the table players actually want.
let running = 0
const rows = multiplier.levels.map((l) => {
if (typeof l.cost === 'number') running += l.cost
return [l.level, l.value, l.cost, formatNumberForDisplay(running)]
})Module Shard Cost
Shards to take a module from one level to the next.
Live
Gem cost (range)
1.6K
| Level | Copies | Gems |
|---|---|---|
| 0 → 1 | 1 | 20 |
| 1 → 2 | 2 | 40 |
| 2 → 3 | 5 | 100 |
| 3 → 4 | 8 | 160 |
| 4 → 5 | 12 | 240 |
| 5 → 6 | 20 | 400 |
| 6 → 7 | 32 | 640 |
Code
import { getModuleShardUpgradeCost } from 'thetowersdk/data'
import { formatNumberForDisplay } from 'thetowersdk/formatting'
// Cost to reach level 161 from 160
const shards = getModuleShardUpgradeCost(161)
console.log(formatNumberForDisplay(shards))Card Gem Cost
Gems to raise a card from one level to another (copies × 20).
Live
- 1. Coins / Kill Bonus lv 1
- 2. Coins / Kill Bonus lv 2
- 3. Coins / Kill Bonus lv 3
- 4. Coins / Kill Bonus lv 4
- 5. Coins / Kill Bonus lv 5
21 candidates skipped (with reasons on the full object).
Code
import { cardLevelUpgradeGemCost } from 'thetowersdk/mechanics'
import { formatNumberForDisplay } from 'thetowersdk/formatting'
const gems = cardLevelUpgradeGemCost(0, 7)
console.log(formatNumberForDisplay(gems))Effective Paths
Next economy buys from your starting levels, including what was skipped.
Live
CF — Chrono Field
ultimate-weapon
Chrono Field ultimate weapon.
Code
import {
planEffectiveEconomyPath,
ZERO_EFFECTIVE_ECONOMY_LEVELS,
zeroEffectiveEconomyConfig,
} from 'thetowersdk/mechanics'
const levels = {
...ZERO_EFFECTIVE_ECONOMY_LEVELS,
time: {
...ZERO_EFFECTIVE_ECONOMY_LEVELS.time,
coinsPerKillBonus: 20,
},
}
const plan = planEffectiveEconomyPath({
config: zeroEffectiveEconomyConfig(),
levels,
variant: 'time',
steps: 5,
})
console.log(plan.steps.map((s) => s.name))
console.log(plan.excluded.length, 'skipped')