---
id: wiki-2026-0508-2026-04-26-skybound-skip-upgrade
title: Skybound — Skip Upgrade and Weapon Transform Reconfiguration
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [Skip Upgrade Mechanic, Weapon Transform]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [skybound, gamedev, upgrade-system, weapon-transform, choice-design]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
  language: typescript
  framework: phaser3
---

# Skybound — Skip Upgrade and Weapon Transform Reconfiguration

## 매 한 줄
> **"매 level-up choice 의 design 은 'skip option' + 'weapon transform' 의 조합 으로 build path agency 의 maximize"**. 매 Skybound 의 4-26 작업은 standard 3-card upgrade 위에 skip (small reward) + weapon transform (2 weapons → 1 evolved) 의 mechanic 추가, evolution graph 의 reconfiguration.

## 매 핵심

### 매 Choice Mechanics
- **Standard Pick**: 3 random choice 중 1 — basic loop.
- **Skip**: choice reject + small XP/gold/heal — bad-RNG escape valve.
- **Reroll**: 1 reroll/level (limited stock) — guided RNG.
- **Banish**: remove option from future pool — long-term build steering.
- **Transform**: 2 specific weapons + passive prereq → evolved weapon.

### 매 Weapon Transform Triggers
- 매 transform 은 (weapon A maxed) + (passive B owned) → weapon A becomes evolved A'.
- 매 evolved weapon 의 max level 의 X — terminal form.
- 매 transform 시 base weapon slot 의 freed (원래 의 기획 — 4-26 변경 후 slot 의 retained).

### 매 Reconfiguration (4-26)
- 매 transform 후 base weapon slot 의 retained — multi-evolve build viability.
- 매 evolved weapon 에 cosmetic visual 차별화 강화.
- 매 transform notification 의 full-screen freeze + audio sting.

## 💻 패턴

### Upgrade Choice Generator
```typescript
type Choice =
  | { kind: 'weapon'; weaponId: string; toLevel: number }
  | { kind: 'passive'; passiveId: string; toLevel: number }
  | { kind: 'skip'; reward: SkipReward };

function generateChoices(player: Player, pool: UpgradePool, count = 3): Choice[] {
  const eligible = pool.filter(u => isEligible(u, player) && !player.banished.has(u.id));
  const picks = sample(eligible, count);
  return picks.map(p => toChoice(p, player));
}

function rollSkip(): Choice {
  const r = Math.random();
  if (r < 0.5) return { kind: 'skip', reward: { kind: 'gold', amount: 50 } };
  if (r < 0.8) return { kind: 'skip', reward: { kind: 'xp', amount: 20 } };
  return { kind: 'skip', reward: { kind: 'heal', percent: 0.1 } };
}
```

### Weapon Transform Rules
```typescript
type TransformRule = {
  weaponId: string;
  passiveId: string;
  evolvedWeaponId: string;
};

const TRANSFORM_RULES: TransformRule[] = [
  { weaponId: 'cannon',     passiveId: 'gunpowder',  evolvedWeaponId: 'mega-cannon' },
  { weaponId: 'missile',    passiveId: 'targeting',  evolvedWeaponId: 'swarm-missile' },
  { weaponId: 'flak',       passiveId: 'shrapnel',   evolvedWeaponId: 'meteor-flak' },
];

function checkTransforms(player: Player): TransformRule[] {
  return TRANSFORM_RULES.filter(rule => {
    const w = player.weapons.find(w => w.id === rule.weaponId);
    const p = player.passives.find(p => p.id === rule.passiveId);
    return w && w.level >= w.maxLevel && p && p.level >= 1 && !player.weapons.some(w => w.id === rule.evolvedWeaponId);
  });
}
```

### Apply Transform (4-26 reconfig — slot retained)
```typescript
function applyTransform(player: Player, rule: TransformRule, scene: Phaser.Scene): void {
  // Old behavior: remove base weapon. New (4-26): keep base.
  const evolved = createWeapon(rule.evolvedWeaponId);
  player.weapons.push(evolved); // base weapon retained in its slot

  scene.scene.pause();
  scene.add.image(W/2, H/2, `evolved-${rule.evolvedWeaponId}-banner`).setDepth(1000);
  scene.sound.play('transform-sting');
  scene.time.delayedCall(2500, () => scene.scene.resume());
}
```

### Banish + Reroll Stock
```typescript
class ChoiceMeta {
  rerollStock = 1;
  banishStock = 0;

  reroll(level: number): Choice[] | null {
    if (this.rerollStock <= 0) return null;
    this.rerollStock--;
    return generateChoices(player, pool);
  }

  banish(player: Player, choice: Choice): boolean {
    if (this.banishStock <= 0) return false;
    this.banishStock--;
    if (choice.kind !== 'skip') player.banished.add(idOf(choice));
    return true;
  }
}
```

### Choice UI (with skip card)
```typescript
class LevelUpModal extends Phaser.GameObjects.Container {
  constructor(scene, choices: Choice[], onPick: (c: Choice) => void) {
    super(scene);
    choices.forEach((c, i) => {
      const card = makeCard(scene, c).setPosition(i * 320, 0).setInteractive();
      card.on('pointerdown', () => onPick(c));
      this.add(card);
    });
    const skipCard = makeCard(scene, rollSkip()).setPosition(choices.length * 320, 0).setInteractive();
    skipCard.on('pointerdown', () => onPick(rollSkip()));
    this.add(skipCard);
  }
}
```

## 매 결정 기준
| 상황 | Approach |
|---|---|
| RNG too punishing | Skip + reroll + banish triumvirate |
| Build path 의 monotony | Transform with prereq passive |
| Slot pressure | 4-26 reconfig: transform retains slot |
| New player overwhelm | Tutorial: introduce mechanics 1-by-1 |

**기본값**: 매 3-card + skip + 1 reroll + transform-retains-slot.

## 🔗 Graph
- 부모: [[Roguelike-Upgrade-Loop]] · [[Choice-Architecture]]
- 변형: [[Skybound-Skill-Concept-and-Hangar-Layout-Overlap-Fix]]
- 응용: [[Vampire-Survivors-Evolution-Graph]]
- Adjacent: [[Skybound-Miniboss-Treasure-Cache-Reward-Loop]] · [[Discriminated-Unions]]

## 🤖 LLM 활용
**언제**: weapon evolution chart, prereq passive brainstorm, skip reward tuning.
**언제 X**: visual transform animation timing.

## ❌ 안티패턴
- **No skip option**: bad-roll lockup — skip 의 always available.
- **Transform removes slot**: build flexibility 망 — 4-26 reconfig 의 사용.
- **Reroll unlimited**: tension 망 — stock-based.
- **Evolved weapon levelable**: power creep — terminal form 의 lock.

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

## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — skip + transform reconfig (slot retained) 정리 |
