feat: add play apps and layout tools

This commit is contained in:
2026-05-25 17:29:21 +09:00
parent f59522ffc4
commit 51e0099bea
46 changed files with 37152 additions and 119 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,683 @@
export type EquipmentSlot =
| 'weapon'
| 'helmet'
| 'shoulders'
| 'chest'
| 'belt'
| 'gloves'
| 'boots'
| 'ring'
| 'necklace'
| 'bracelet'
| 'artifact';
export type InventoryItem = {
id: string;
name: string;
category: 'weapon' | 'armor' | 'accessory' | 'consumable' | 'material';
rarity: 'common' | 'rare' | 'epic';
icon: string;
description: string;
attack?: number;
defense?: number;
critRate?: number;
spellPower?: number;
maxMpBonus?: number;
manaAbsorbChance?: number;
heal?: number;
mpRestore?: number;
healOverTimeTotal?: number;
healOverTimeTicks?: number;
healOverTimeIntervalMs?: number;
autoHealMultiplier?: number;
moveSpeedMultiplier?: number;
effectDurationMs?: number;
quantity?: number;
slot?: EquipmentSlot;
};
export type SkillDefinition = {
id: string;
name: string;
description: string;
manaCost: number;
cooldownMs: number;
damage: number;
range: number;
castTimeMs: number;
accentLabel: string;
color: string;
icon: string;
role: 'attack' | 'buff' | 'summon';
durationMs?: number;
};
export type QuestDefinition = {
id: string;
title: string;
description: string;
progressType: 'kill' | 'collect';
target: string;
requiredCount: number;
turnInNpcId: string;
turnInItemId?: string;
rewardGold: number;
rewardExp: number;
rewardItemId?: string;
};
export type NpcDefinition = {
id: string;
name: string;
role: 'quest' | 'shop' | 'guide';
description: string;
x: number;
y: number;
};
export type EnemyDefinition = {
id: string;
name: string;
role: 'normal' | 'boss';
level: number;
maxHp: number;
maxMp: number;
attack: number;
expReward: number;
goldReward: number;
lootTable: Array<{
itemId: string;
chance: number;
minQuantity?: number;
maxQuantity?: number;
}>;
x: number;
y: number;
patrolRadius: number;
tint: number;
};
export const THE_QUEST_WORLD_SIZE = {
width: 2200,
height: 1600,
} as const;
export const THE_QUEST_STAGE_PORTAL = {
x: 1870,
y: 258,
radius: 118,
} as const;
export const THE_QUEST_SKILLS: SkillDefinition[] = [
{
id: 'energy-bolt',
name: '에너지 볼트',
description: '짧은 쿨다운으로 마력 탄환을 날려 기본 견제를 이어 갑니다.',
manaCost: 0,
cooldownMs: 640,
damage: 16,
range: 214,
castTimeMs: 0,
accentLabel: '기본기',
color: '#9ecfff',
icon: '✦',
role: 'attack',
},
{
id: 'fire-arrow',
name: '파이어 애로우',
description: '시전이 빠른 화염 탄환으로 체력을 깎아 두기 좋은 견제 마법입니다.',
manaCost: 10,
cooldownMs: 2100,
damage: 34,
range: 224,
castTimeMs: 120,
accentLabel: '화염',
color: '#ffb06f',
icon: '➶',
role: 'attack',
},
{
id: 'ice-dagger',
name: '아이스 대거',
description: '날카로운 냉기 단검을 날려 강한 단일 피해를 줍니다.',
manaCost: 16,
cooldownMs: 3200,
damage: 52,
range: 238,
castTimeMs: 180,
accentLabel: '빙결',
color: '#8fe7ff',
icon: '❄',
role: 'attack',
},
{
id: 'lightning',
name: '라이트닝',
description: '가까운 적을 기준으로 번개를 연쇄시켜 다수를 태웁니다.',
manaCost: 24,
cooldownMs: 5200,
damage: 46,
range: 244,
castTimeMs: 220,
accentLabel: '연쇄',
color: '#ffd36f',
icon: '⚡',
role: 'attack',
},
{
id: 'fireball',
name: '파이어볼',
description: '폭발하는 화염구를 떨어뜨려 반경 적을 한 번에 태웁니다.',
manaCost: 30,
cooldownMs: 7600,
damage: 68,
range: 182,
castTimeMs: 280,
accentLabel: '광역',
color: '#ff9a6a',
icon: '☄',
role: 'attack',
},
{
id: 'greater-haste',
name: '그레이터 헤이스트',
description: '이동과 시전 리듬을 끌어올려 위험한 구간을 빠르게 돌파합니다.',
manaCost: 22,
cooldownMs: 11800,
damage: 0,
range: 0,
castTimeMs: 120,
accentLabel: '가속',
color: '#d4c0ff',
icon: '⟡',
role: 'buff',
durationMs: 10000,
},
{
id: 'magic-shield',
name: '매직 실드',
description: '마력 보호막으로 받는 피해를 줄이며 난전을 버팁니다.',
manaCost: 26,
cooldownMs: 12600,
damage: 0,
range: 0,
castTimeMs: 120,
accentLabel: '보호',
color: '#7fcfff',
icon: '⬡',
role: 'buff',
durationMs: 9200,
},
{
id: 'summon-skeleton',
name: '서먼 스켈레톤',
description: '언데드 하수인을 불러 주변 적을 압박하고 마나 순환을 돕습니다.',
manaCost: 34,
cooldownMs: 15000,
damage: 30,
range: 168,
castTimeMs: 180,
accentLabel: '소환',
color: '#d8f0ff',
icon: '☠',
role: 'summon',
durationMs: 15000,
},
];
export const THE_QUEST_ITEMS: InventoryItem[] = [
{
id: 'apprentice-staff',
name: '수습 마도 지팡이',
category: 'weapon',
rarity: 'rare',
icon: '🪄',
description: '기본 주문 위력을 끌어올리고 낮은 확률로 적 MP를 흡수합니다.',
attack: 8,
spellPower: 12,
maxMpBonus: 16,
manaAbsorbChance: 0.16,
slot: 'weapon',
},
{
id: 'scribe-hood',
name: '스크라이브 후드',
category: 'armor',
rarity: 'common',
icon: '🪖',
description: '집중을 돕는 천 후드. 치명과 MP를 살짝 높입니다.',
defense: 4,
critRate: 0.02,
maxMpBonus: 10,
slot: 'helmet',
},
{
id: 'astral-mantle',
name: '아스트랄 맨틀',
category: 'armor',
rarity: 'rare',
icon: '🧥',
description: '별가루를 엮은 로브. 주문 저항과 MP 풀을 함께 보강합니다.',
defense: 8,
maxMpBonus: 18,
slot: 'chest',
},
{
id: 'moon-spaulders',
name: '문 스폴더',
category: 'armor',
rarity: 'rare',
icon: '🪽',
description: '달빛 견갑. 치명 감각과 주문 회전을 보조합니다.',
defense: 4,
critRate: 0.03,
spellPower: 4,
slot: 'shoulders',
},
{
id: 'rune-gloves',
name: '룬 글러브',
category: 'armor',
rarity: 'common',
icon: '🧤',
description: '시전 안정화를 돕는 장갑. 주문 위력이 조금 오릅니다.',
spellPower: 6,
slot: 'gloves',
},
{
id: 'mist-belt',
name: '미스트 벨트',
category: 'armor',
rarity: 'common',
icon: '🧷',
description: '마력 응축 벨트. 방어와 MP를 함께 보정합니다.',
defense: 3,
maxMpBonus: 12,
slot: 'belt',
},
{
id: 'trail-boots',
name: '트레일 부츠',
category: 'armor',
rarity: 'common',
icon: '🥾',
description: '이동용 부츠. 기본 방어를 보강합니다.',
defense: 3,
slot: 'boots',
},
{
id: 'moon-ring',
name: '문링',
category: 'accessory',
rarity: 'epic',
icon: '💍',
description: '달의 조율 반지. 치명과 주문 위력을 크게 높입니다.',
critRate: 0.08,
spellPower: 8,
slot: 'ring',
},
{
id: 'ember-bracelet',
name: '엠버 브레이슬릿',
category: 'accessory',
rarity: 'rare',
icon: '📿',
description: '주문 가속 팔찌. MP와 주문 위력을 함께 높입니다.',
spellPower: 5,
maxMpBonus: 14,
slot: 'bracelet',
},
{
id: 'forest-relic',
name: '포레스트 렐릭',
category: 'accessory',
rarity: 'epic',
icon: '🜂',
description: '숲의 비전이 담긴 유물. 전반적인 마도사 성능을 끌어올립니다.',
attack: 4,
defense: 4,
spellPower: 6,
critRate: 0.04,
slot: 'artifact',
},
{
id: 'moonbranch-staff',
name: '문브랜치 스태프',
category: 'weapon',
rarity: 'rare',
icon: '🪄',
description: '달가지 지팡이. 주문 위력과 마나 흡수 확률이 더 높습니다.',
attack: 10,
spellPower: 16,
maxMpBonus: 20,
manaAbsorbChance: 0.22,
slot: 'weapon',
},
{
id: 'slimecore-cane',
name: '슬라임코어 케인',
category: 'weapon',
rarity: 'epic',
icon: '🔮',
description: '슬라임 코어를 박아 넣은 지팡이. 주문 위력과 흡수량이 크게 오릅니다.',
attack: 12,
spellPower: 20,
maxMpBonus: 28,
manaAbsorbChance: 0.28,
slot: 'weapon',
},
{
id: 'moss-guard',
name: '모스 가드',
category: 'armor',
rarity: 'rare',
icon: '🥋',
description: '이끼 섬유를 엮은 외투. 생존력과 MP를 함께 올립니다.',
defense: 12,
maxMpBonus: 16,
slot: 'chest',
},
{
id: 'owl-visor',
name: '아울 바이저',
category: 'armor',
rarity: 'rare',
icon: '⛑',
description: '시야 보정 바이저. 방어와 치명을 함께 올립니다.',
defense: 6,
critRate: 0.03,
slot: 'helmet',
},
{
id: 'river-striders',
name: '리버 스트라이더',
category: 'armor',
rarity: 'rare',
icon: '👢',
description: '습지 돌파 장화. 안정적인 하체 방어를 제공합니다.',
defense: 5,
slot: 'boots',
},
{
id: 'river-charm',
name: '리버 참',
category: 'accessory',
rarity: 'epic',
icon: '🪬',
description: '강의 기운이 담긴 부적. MP와 치명타 확률을 높입니다.',
critRate: 0.1,
maxMpBonus: 24,
slot: 'necklace',
},
{
id: 'sun-band',
name: '선 밴드',
category: 'accessory',
rarity: 'rare',
icon: '💠',
description: '햇빛 결정 보조 반지. 주문 위력이 추가로 오릅니다.',
spellPower: 7,
slot: 'ring',
},
{
id: 'mist-pendant',
name: '미스트 펜던트',
category: 'accessory',
rarity: 'epic',
icon: '📿',
description: '안개 정수 목걸이. 방어와 MP를 동시에 보강합니다.',
defense: 4,
maxMpBonus: 26,
critRate: 0.05,
slot: 'necklace',
},
{
id: 'hp-potion',
name: '체력 포션',
category: 'consumable',
rarity: 'common',
icon: '🧪',
description: '체력을 순차적으로 180 회복합니다.',
healOverTimeTotal: 180,
healOverTimeTicks: 6,
healOverTimeIntervalMs: 900,
quantity: 5,
},
{
id: 'auto-heal-elixir',
name: '특수 회복 엘릭서',
category: 'consumable',
rarity: 'rare',
icon: '✨',
description: '18초 동안 자동 회복량을 2.5배로 끌어올립니다.',
autoHealMultiplier: 2.5,
effectDurationMs: 18000,
quantity: 2,
},
{
id: 'celerity-potion',
name: '가속 물약',
category: 'consumable',
rarity: 'rare',
icon: '⚡',
description: '14초 동안 모든 이동 속도를 2배로 가속합니다.',
moveSpeedMultiplier: 2,
effectDurationMs: 14000,
quantity: 2,
},
{
id: 'slime-gel',
name: '슬라임 젤',
category: 'material',
rarity: 'common',
icon: '🫧',
description: '연금술 재료. 퀘스트와 촉매 제작에 사용됩니다.',
quantity: 0,
},
];
export const THE_QUEST_QUESTS: QuestDefinition[] = [
{
id: 'slime-hunt',
title: '[메인] 푸른 숲의 정화',
description: '포탈 근처 슬라임 8마리를 정리한 뒤 기사단장 브롬에게 보고하세요.',
progressType: 'kill',
target: 'slime',
requiredCount: 8,
turnInNpcId: 'brom',
rewardGold: 120,
rewardExp: 90,
rewardItemId: 'hp-potion',
},
{
id: 'slime-gel',
title: '[서브] 연금 재료 수집',
description: '슬라임 젤 12개를 모은 뒤 상인 미라에게 직접 전달하세요.',
progressType: 'collect',
target: 'slime-gel',
requiredCount: 12,
turnInNpcId: 'mira',
turnInItemId: 'slime-gel',
rewardGold: 160,
rewardExp: 120,
rewardItemId: 'celerity-potion',
},
];
export const THE_QUEST_NPCS: NpcDefinition[] = [
{
id: 'lyra',
name: '리라',
role: 'guide',
description: '초반 진행과 조작을 안내하는 길드 안내원.',
x: 1080,
y: 730,
},
{
id: 'brom',
name: '브롬',
role: 'quest',
description: '사냥 퀘스트를 제공하는 기사단장.',
x: 1470,
y: 960,
},
{
id: 'mira',
name: '미라',
role: 'shop',
description: '포션과 장비 재료를 취급하는 상인.',
x: 880,
y: 1160,
},
];
export function createInitialEnemies(): EnemyDefinition[] {
return [
{
id: 'slime-1',
name: '슬라임',
role: 'normal',
level: 10,
maxHp: 250,
maxMp: 26,
attack: 18,
expReward: 28,
goldReward: 16,
lootTable: [
{ itemId: 'slime-gel', chance: 1, minQuantity: 1, maxQuantity: 2 },
{ itemId: 'hp-potion', chance: 0.24, minQuantity: 1, maxQuantity: 1 },
{ itemId: 'moonbranch-staff', chance: 0.08, minQuantity: 1, maxQuantity: 1 },
],
x: 1260,
y: 760,
patrolRadius: 72,
tint: 0x6fd0ff,
},
{
id: 'slime-2',
name: '슬라임',
role: 'normal',
level: 10,
maxHp: 250,
maxMp: 24,
attack: 18,
expReward: 28,
goldReward: 16,
lootTable: [
{ itemId: 'slime-gel', chance: 1, minQuantity: 1, maxQuantity: 2 },
{ itemId: 'celerity-potion', chance: 0.18, minQuantity: 1, maxQuantity: 1 },
{ itemId: 'moss-guard', chance: 0.08, minQuantity: 1, maxQuantity: 1 },
],
x: 1410,
y: 900,
patrolRadius: 84,
tint: 0x7be08f,
},
{
id: 'slime-3',
name: '엘더 슬라임',
role: 'normal',
level: 11,
maxHp: 310,
maxMp: 42,
attack: 20,
expReward: 32,
goldReward: 18,
lootTable: [
{ itemId: 'slime-gel', chance: 1, minQuantity: 2, maxQuantity: 3 },
{ itemId: 'hp-potion', chance: 0.3, minQuantity: 1, maxQuantity: 1 },
{ itemId: 'moonbranch-staff', chance: 0.12, minQuantity: 1, maxQuantity: 1 },
],
x: 1540,
y: 840,
patrolRadius: 80,
tint: 0x86d0ff,
},
{
id: 'slime-4',
name: '문글림 슬라임',
role: 'normal',
level: 11,
maxHp: 320,
maxMp: 56,
attack: 21,
expReward: 32,
goldReward: 18,
lootTable: [
{ itemId: 'slime-gel', chance: 1, minQuantity: 2, maxQuantity: 3 },
{ itemId: 'auto-heal-elixir', chance: 0.24, minQuantity: 1, maxQuantity: 1 },
{ itemId: 'river-charm', chance: 0.1, minQuantity: 1, maxQuantity: 1 },
],
x: 1360,
y: 1060,
patrolRadius: 78,
tint: 0x7ce8ff,
},
{
id: 'slime-5',
name: '가디언 슬라임',
role: 'normal',
level: 12,
maxHp: 390,
maxMp: 64,
attack: 24,
expReward: 40,
goldReward: 20,
lootTable: [
{ itemId: 'slime-gel', chance: 1, minQuantity: 2, maxQuantity: 4 },
{ itemId: 'hp-potion', chance: 0.3, minQuantity: 1, maxQuantity: 2 },
{ itemId: 'slimecore-cane', chance: 0.18, minQuantity: 1, maxQuantity: 1 },
{ itemId: 'moss-guard', chance: 0.14, minQuantity: 1, maxQuantity: 1 },
],
x: 1670,
y: 970,
patrolRadius: 90,
tint: 0x65d6ff,
},
{
id: 'slime-6',
name: '에메랄드 슬라임',
role: 'normal',
level: 12,
maxHp: 380,
maxMp: 52,
attack: 23,
expReward: 40,
goldReward: 20,
lootTable: [
{ itemId: 'slime-gel', chance: 1, minQuantity: 2, maxQuantity: 4 },
{ itemId: 'celerity-potion', chance: 0.3, minQuantity: 1, maxQuantity: 1 },
{ itemId: 'moonbranch-staff', chance: 0.12, minQuantity: 1, maxQuantity: 1 },
{ itemId: 'river-charm', chance: 0.14, minQuantity: 1, maxQuantity: 1 },
],
x: 1210,
y: 1180,
patrolRadius: 96,
tint: 0x80f0b0,
},
{
id: 'stage-boss',
name: '포탈 수호자 크라운 슬라임',
role: 'boss',
level: 14,
maxHp: 920,
maxMp: 180,
attack: 38,
expReward: 120,
goldReward: 88,
lootTable: [
{ itemId: 'slime-gel', chance: 1, minQuantity: 4, maxQuantity: 6 },
{ itemId: 'hp-potion', chance: 0.75, minQuantity: 2, maxQuantity: 3 },
{ itemId: 'auto-heal-elixir', chance: 0.54, minQuantity: 1, maxQuantity: 2 },
{ itemId: 'celerity-potion', chance: 0.58, minQuantity: 1, maxQuantity: 2 },
{ itemId: 'mist-pendant', chance: 0.24, minQuantity: 1, maxQuantity: 1 },
{ itemId: 'slimecore-cane', chance: 0.28, minQuantity: 1, maxQuantity: 1 },
],
x: 1820,
y: 360,
patrolRadius: 64,
tint: 0xffb86a,
},
];
}

File diff suppressed because it is too large Load Diff