---
id: wiki-2026-0508-2026-04-26-skybound-miniboss-tre
title: Skybound — Miniboss Treasure Cache Reward Loop
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [Treasure Cache, Miniboss Reward]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [skybound, gamedev, reward-loop, miniboss, treasure-chest]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
  language: typescript
  framework: phaser3
---

# Skybound — Miniboss Treasure Cache Reward Loop

## 매 한 줄
> **"매 miniboss 의 reward 가 단순 XP gem 이 아닌 'treasure cache' (multi-roll lottery) 일 때 mid-run 의 emotional peak 의 형성"**. 매 Skybound 의 4-26 작업은 stage 중반 miniboss kill 후 chest spawn → 3-roll level-up 의 cascade 를 reward loop 로 정착.

## 매 핵심

### 매 Cache Tiers
- **Bronze**: 1-roll, common pool only.
- **Silver**: 2-roll, common + uncommon.
- **Gold**: 3-roll, full pool + transform-eligible.
- **Prismatic**: 5-roll, guaranteed evolution if eligible (rare).

### 매 Drop Rules
- 매 miniboss 는 tier 의 weighted drop (e.g. stage 3 miniboss → silver 70%, gold 25%, prismatic 5%).
- 매 cache 는 walk-on pickup — pickup 시 모든 roll 즉시 progression.
- 매 cache 의 stack: roll 의 sequential 의 진행, 한번에 처리.

### 매 응용
1. 매 miniboss kill → chest spawn → walk-on → cascade level-up.
2. 매 cascade 의 visual: card → fade → next card (1.2s per card).
3. 매 prismatic 의 special VFX (rainbow particles, slow-mo).

## 💻 패턴

### Cache Definition
```typescript
type CacheTier = 'bronze' | 'silver' | 'gold' | 'prismatic';

type Cache = {
  tier: CacheTier;
  rolls: number;
  pool: 'common' | 'uncommon' | 'rare' | 'all';
  guaranteeEvolution?: boolean;
};

const TIER_CONFIG: Record<CacheTier, Cache> = {
  bronze:    { tier: 'bronze',    rolls: 1, pool: 'common' },
  silver:    { tier: 'silver',    rolls: 2, pool: 'uncommon' },
  gold:      { tier: 'gold',      rolls: 3, pool: 'all' },
  prismatic: { tier: 'prismatic', rolls: 5, pool: 'all', guaranteeEvolution: true },
};
```

### Drop Roll
```typescript
type DropEntry = { tier: CacheTier; weight: number };

const STAGE_3_MINIBOSS_DROPS: DropEntry[] = [
  { tier: 'bronze',    weight: 0  },
  { tier: 'silver',    weight: 70 },
  { tier: 'gold',      weight: 25 },
  { tier: 'prismatic', weight: 5  },
];

function rollCache(table: DropEntry[]): Cache {
  const total = table.reduce((s, e) => s + e.weight, 0);
  let r = Math.random() * total;
  for (const e of table) {
    r -= e.weight;
    if (r <= 0) return TIER_CONFIG[e.tier];
  }
  return TIER_CONFIG.bronze;
}
```

### Cache Pickup → Cascade
```typescript
class ChestPickup extends Phaser.GameObjects.Sprite {
  constructor(scene, x: number, y: number, public cache: Cache) {
    super(scene, x, y, `chest-${cache.tier}`);
    scene.add.existing(this);
  }

  onPlayerOverlap(player: Player) {
    this.destroy();
    enqueueCascade(player, this.cache);
  }
}

async function enqueueCascade(player: Player, cache: Cache): Promise<void> {
  for (let i = 0; i < cache.rolls; i++) {
    await showLevelUpModal(player, cache.pool);
  }
  if (cache.guaranteeEvolution) {
    const transforms = checkTransforms(player);
    if (transforms.length) applyTransform(player, transforms[0], scene);
  }
}
```

### Cascade Modal Animation
```typescript
async function showLevelUpModal(player: Player, pool: PoolKind): Promise<void> {
  return new Promise(resolve => {
    const choices = generateChoices(player, getPool(pool), 3);
    const modal = new LevelUpModal(scene, choices, (picked) => {
      applyChoice(player, picked);
      scene.tweens.add({ targets: modal, alpha: 0, duration: 250, onComplete: () => { modal.destroy(); resolve(); } });
    });
    scene.add.existing(modal);
  });
}
```

### Prismatic VFX
```typescript
function spawnPrismaticChest(scene, x: number, y: number, cache: Cache) {
  const chest = new ChestPickup(scene, x, y, cache);
  const emitter = scene.add.particles(0, 0, 'rainbow-spark', {
    follow: chest, speed: { min: 30, max: 90 }, lifespan: 800, scale: { start: 1, end: 0 },
    tint: [0xff0000, 0xff8800, 0xffff00, 0x00ff00, 0x0088ff, 0x8800ff],
  });
  chest.on('destroy', () => emitter.destroy());
}
```

## 매 결정 기준
| 상황 | Approach |
|---|---|
| Mid-run dopamine flat | Cache cascade injection |
| Drop rate too generous | Tier weight rebalance per stage |
| Prismatic 너무 흔함 | Stage gate (only stage 5+) |
| Cascade pacing slow | Per-card 1.2s + skip-anim button |

**기본값**: 매 4-tier cache + weighted drop + cascade modal + prismatic VFX.

## 🔗 Graph
- 부모: [[Reward-Loop-Design]] · [[Loot-Tier-System]]
- 변형: [[Skybound-Skip-Upgrade-and-Weapon-Transform-Reconfiguration]]
- 응용: [[Vampire-Survivors-Treasure]]
- Adjacent: [[Skybound-Stage-Miniboss-Pattern-Differentiation]] · [[Random-Sampling]]

## 🤖 LLM 활용
**언제**: tier balance brainstorm, drop table generation, VFX spec.
**언제 X**: particle perf tuning, async UI race conditions (manual debug).

## ❌ 안티패턴
- **Cache dropped XP only**: emotional flat — multi-roll cascade 의 사용.
- **All tiers same VFX**: tier 의 sense lost — prismatic 차별화 필수.
- **Cascade blocking input long**: tedium — skip-anim 의 제공.
- **Drop weight hardcoded**: per-stage tuning impossible — table 외부화.

## 🧪 검증 / 중복
- Verified (Vampire Survivors treasure mechanic, Brotato chest tiers).
- 신뢰도 A.

## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — miniboss treasure cache cascade reward loop 정리 |
