# Tower Dungeon

## Overview
Tower Dungeon is the game's modern squad PvE climb. The live implementation is centered on the **Tower Dungeon sidebar page**, not chat commands: players form a 1-3 player squad, clear floors 1-100, fight scripted bosses every 10 floors, and earn **Tower Tokens** plus Tower-exclusive crate rewards.

The chat command layer was intentionally reduced. Only status/help/stat lookups remain in chat; run creation, invites, readying, combat, checkpoint recovery, shop purchases, and leaderboards are handled through the sidebar/socket UI.

## Commands

### Chat commands

| Command | What it does | Notes |
|---|---|---|
| `.tower` | Shows Tower help | Same as `.tower help` |
| `.tower help` | Explains that Tower is sidebar-driven | Lists the remaining chat commands |
| `.tower status` | Shows your active run, floor, squad state, and current total Tower Tokens for the run | Returns an error if you are not in a run |
| `.tower stats` | Shows your personal tower record | Reads persistent `tower_player_stats` |


### Sidebar / UI actions
The Tower sidebar uses socket events instead of public chat commands. The main player actions are:

- Create run
- Join run by run ID / invite
- Send invite / accept invite / decline invite / view pending invites
- Toggle ready
- Start run
- Submit combat actions (`attack`, `defend`, `heal`, `heal_ally`, `barrier`, `resurrection`, `potion`)
- Set focus target
- Advance to the next floor
- Resume from checkpoint after a wipe
- Boss retry ready / retry / quit
- Leave run / kick member
- Run chat and global Tower chat
- Buy Tower shop items
- Exchange coins for Tower Tokens
- View active-run leaderboard

## Core Mechanics

### Squad rules
- Squad size: **1-3 players**.
- Each player brings up to **3 animals** from their **currently active team**.
- Team loadout is re-read from the database when entering combat floors, so safezone changes to team/weapon/enchant setup affect the next fight.
- Only the **leader** can invite, start, advance, or kick.
- Joining and inviting are only allowed while the run is still on **floor 1**.

### Floor structure
- **100 total floors**.
- **Boss floors:** `10, 20, 30, 40, 50, 60, 70, 80, 90, 100`.
- **Safezone/checkpoint floors:** `1, 11, 21, 31, 41, 51, 61, 71, 81, 91`.
- Floor `1` is a safezone. Combat actually starts at **floor 2**.

### Ready checks
- All members must be ready before the leader can start the run.
- On non-solo squads, all members must also be ready before advancing from a safezone/transition state.
- After a floor clear, the server resets the squad's ready state to `false` for the next transition.

### Floor transitions and checkpointing
When a checkpoint floor is entered, the server saves:
- squad state
- checkpoint floor
- accumulated Tower Tokens for the run

If the squad wipes, the run is restored to the **latest checkpoint** rather than deleted immediately.

### Wipes and retry logic
The current runtime constants in `towerManager.js` are:

- **Wipe cooldown:** `180s`
- **Boss retry cooldown:** `180s`

This is important because some comments/schema notes still mention 6 hours, but the live code is using **3-minute dev-tuned cooldowns**.

#### Normal wipe
- Run enters `wipe` phase.
- Squad reverts to the latest checkpoint.
- Animals are revived to full HP.
- Players are placed on the wipe cooldown.
- After cooldown expiry, the leader can resume from the checkpoint safezone.

#### Boss wipe
Boss floors have a special retry flow:
- First boss wipe grants a retry path instead of immediately ending progression.
- `bossRetry.totalFailures` increments on each boss wipe.
- A retry consumes the available retry when used.
- If no retry remains, the boss retry cooldown is applied.
- Choosing to quit the retry also applies the boss retry cooldown and returns the squad to the latest checkpoint safezone.

### Real-time combat runtime
Tower uses its own real-time combat engine, not the normal PvP battle loop.

- Global combat tick: **every 100ms**
- Client snapshot broadcast: **every 300ms**
- Inactivity timeout: **6 minutes** with no valid actions
- Solo disconnect reconnect window during active combat: **15 seconds**

If a solo player disconnects in combat:
- the run is paused,
- they get 15 seconds to reconnect,
- if they fail, the run is reverted to the last checkpoint.

### Player action set
The tick processor resolves these player actions:

- `attack`
- `defend`
- `heal`
- `heal_ally`
- `barrier`
- `resurrection`
- `potion`
- `focus_target`

`validateAction()` and priority mapping still mention `enchant`, but the live tick resolution switch does **not** execute a separate `enchant` action.

### Damage model highlights
- A player's attack damage is based on the **combined ATK of all alive animals** on that player's team.
- The selected active animal's weapon governs crit/lifesteal-style weapon behavior.
- Tower support items are consumed from persistent inventory while inside combat.

## Boss Mechanics
Tower bosses are scripted encounter checks, not just stat walls.

| Floor | Boss | Live mechanic |
|---|---|---|
| 10 | SCP-173 | Players need **Potion of Deep Focus** before the countdown resolves, or they are killed |
| 20 | Clicker | Attacking without **Potion of Stealth** kills the acting player |
| 30 | Nemesis | Marks a player and repeatedly crushes the marked target |
| 40 | SCP-096 | Acting without **Potion of Mind Sight** triggers lethal punishment/rage behavior |
| 50 | Time Lag Warden | Adds heavy cooldown pressure / time distortion |
| 60 | Mirror Doppelganger | Reflection fight; the intended counterplay is to stop reacting to its ragebait|
| 70 | Illusionist | Repeated battlefield shuffle/distortion effects |
| 80 | Puppet Master | Redirects attacks and redirects heals unless players use the safe window |
| 90 | Mahoraga | Regenerates every 6s until players break adaptation with 20% burst damage (10s break) |
| 100 | Scarlet King | Rotates through earlier boss mechanics in sequence |

### Boss counter items sold in Tower Shop
- `deep_focus` counters **SCP-173**
- `stealth` counters **Clicker**
- `mind_sight` counters **SCP-096**
- `speed` is a general cooldown-reduction potion

## Tower Shop and Currency

### Currency
- Persistent Tower currency is stored as **`users.tower_tokens`**.
- Tower run state also tracks run-local totals as `totalTokens` / legacy `totalCoins`.

### Coin exchange
- **1,000 coins -> 200 Tower Tokens**

### Shop catalog
Tower shop items are stored in inventory as `item_type='tower_item'`.

| Item ID | Name | Price | Effect |
|---|---|---:|---|
| `healing_orb_1` | Lvl 1 Healing Orb | 90 | Heals up to 500 HP |
| `healing_orb_2` | Lvl 2 Healing Orb | 180 | Heals up to 1,000 HP |
| `healing_orb_3` | Lvl 3 Healing Orb | 300 | Heals up to 2,000 HP |
| `barrier_1` | Lvl 1 Barrier | 120 | 50% damage reduction for 5s |
| `barrier_2` | Lvl 2 Barrier | 240 | 50% damage reduction for 10s |
| `barrier_3` | Lvl 3 Barrier | 360 | 50% damage reduction for 15s |
| `resurrection_staff_1` | Lvl 1 Resurrection Staff | 180 | Revive one dead animal at 25% max HP |
| `resurrection_staff_2` | Lvl 2 Resurrection Staff | 420 | Revive one dead animal at 50% max HP |
| `mind_sight` | Potion of Mind Sight | 500 | Counters SCP-096 |
| `stealth` | Potion of Stealth | 400 | Counters Clicker |
| `deep_focus` | Potion of Deep Focus | 400 | Counters SCP-173 |
| `speed` | Potion of Speed | 300 | Reduces cooldowns by 2s for 15s, minimum cooldown 500ms |

## Rewards

### Tower Token formula
Per cleared floor, each player is credited Tower Tokens using:

```text
base = floor(50 + floor*20 + (floor/5)^2)
reward = base                // normal floor
reward = base * 3            // boss floor
```

### Boss milestone bonuses
Boss floors add extra token bonuses:

| Floor | Bonus Tokens |
|---|---:|
| 10 | 2,000 |
| 20 | 5,000 |
| 30 | 10,000 |
| 40 | 15,000 |
| 50 | 25,000 |
| 60 | 40,000 |
| 70 | 60,000 |
| 80 | 80,000 |
| 90 | 120,000 |
| 100 | 500,000 |

### Crate reward floors
Tower crate rewards are separate from token payouts.

| Floor | Reward |
|---|---|
| 5, 15, 25, 35, 45 | 1x `mythic_crate` |
| 55, 65, 75, 85, 95 | 1x `legendary_crate` |
| 10 | 1x `legendary_crate` |
| 20 | 2x `legendary_crate` |
| 30 | 1x `fabled_crate` |
| 40 | 1x `fabled_crate` + 1x `legendary_crate` |
| 50 | 1x `fabled_crate` + 2x `legendary_crate` |
| 60 | 1x `gods_crate` + 1x `legendary_crate` |
| 70 | 1x `gods_crate` + 2x `legendary_crate` |
| 80 | 1x `ascendant_crate` + 1x `fabled_crate` |
| 90 | 2x `ascendant_crate` + 1x `fabled_crate` |
| 100 | 1x `infinity_crate` + 2x `ascendant_crate` |

### Tower crate opening commands
Tower crates are opened through chat:

- `.mythic crate`
- `.legendary crate`
- `.fabled crate`
- `.gods crate`
- `.ascendant crate`
- `.infinity crate`

## Database / Storage Details

### Core tower tables
Tower persistence creates and uses these SQLite tables:

- `tower_runs`
- `tower_run_members`
- `tower_checkpoints`
- `tower_floor_progress`
- `tower_loot_history`
- `tower_player_stats`
- `tower_crate_claims`
- `tower_cooldowns`
- `tower_invites`
- `tower_chat_messages`
- `tower_global_chat`

### Persistent player economy fields
- `users.tower_tokens` stores each player's Tower Token wallet.
- Tower shop inventory uses `inventory.item_type='tower_item'`.
- Tower crates are stored in the general `inventory` table under `item_type='crate'`.

### Active-state runtime storage
- Active run state is cached in Redis and mirrored to SQLite snapshot JSON (`tower_runs.run_state_json`).
- Player-to-run mappings, action queues, combat state, cooldown blobs, invites, and logs are cached in Redis.
- If Redis is unavailable, the system falls back to in-memory Maps for some live state.

### Leaderboards and stats
- `.tower stats` reads from `tower_player_stats`.
- The sidebar "leaderboard" is an **active-run floor leaderboard**, not a permanent all-time leaderboard.
- `tower_player_stats.highest_floor` and `run_cycle` feed the profile system's adventurer rank.
- **Adventurer Rank Tiers**:
  - **SS**: Completed 2 or more run cycles (`run_cycle >= 2`).
  - **S**: Completed 1 run cycle (`run_cycle == 1`) or reached Floor 100+ (`highest_floor >= 100`).
  - **A**: Highest floor reached is 90+ (`highest_floor >= 90`).
  - **B**: Highest floor reached is 70+ (`highest_floor >= 70`).
  - **C**: Highest floor reached is 50+ (`highest_floor >= 50`).
  - **D**: Highest floor reached is 30+ (`highest_floor >= 30`).
  - **E**: Highest floor reached is 10+ (`highest_floor >= 10`).
  - **F**: Highest floor reached is below 10.

## Strategic Tips / Balance Notes
- Treat Tower as a **checkpoint-based endurance mode**, not a sprint. Safezones are the place to swap team setups and weapons.
- Because teams are reloaded from the DB on combat floor entry, changing loadouts in safezones actually matters.
- Save tokens for the boss-counter potions if your squad is learning the scripted fights.
- Tower crates, not normal shop purchases, are the main way to access the higher Tower-exclusive reward ladder.
- The reward generator still rolls a `rareDrop`, but `handleFloorComplete()` currently only persists **Tower Tokens** and **crate rewards**. In practice, the live reward path does **not** award those rolled rare drops.
- The schema/comments mention 6-hour wipe cooldowns, but the live code currently enforces **180-second** cooldowns.