feat(magician): 시뮬 메커니즘 동기화 + 산출물 재생성

- poison 틱(행동 시작·사망 시 행동 생략·전멸 승리 체크)·aoe(개별 취약/방어)·heal 클램프·draw
- 테스트 4건 추가 — 전체 40건 통과

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-12 13:56:52 +09:00
parent e1d298f972
commit 7b6e181cb0
4 changed files with 219 additions and 356 deletions

File diff suppressed because one or more lines are too long

View File

@@ -106,7 +106,7 @@ export function simulateCombat(data, rng, stats) {
let pStr = 0, pWeak = 0, pVuln = 0; let pStr = 0, pWeak = 0, pVuln = 0;
const powers = []; const powers = [];
const mob = monsters.map((m) => ({ const mob = monsters.map((m) => ({
name: m.name, hp: m.maxHp, maxHp: m.maxHp, block: 0, str: 0, weak: 0, vuln: 0, name: m.name, hp: m.maxHp, maxHp: m.maxHp, block: 0, str: 0, weak: 0, vuln: 0, poison: 0,
intents: m.intents, intentIdx: 0, alive: true, intents: m.intents, intentIdx: 0, alive: true,
})); }));
let turns = 0; let turns = 0;
@@ -149,18 +149,30 @@ export function simulateCombat(data, rng, stats) {
const hitN = c.hits || 1; const hitN = c.hits || 1;
let totalNv = 0; let totalNv = 0;
for (let h = 0; h < hitN; h++) totalNv += calcAttack(c.damage || 0, pStr, pWeak, 0); for (let h = 0; h < hitN; h++) totalNv += calcAttack(c.damage || 0, pStr, pWeak, 0);
const dmg = target.vuln > 0 ? Math.floor(totalNv * 1.5) : totalNv; let dmg = totalNv; // 통계 보고용 (aoe는 1대상 기준)
if (c.pierce === true) { if (c.aoe === true) {
target.hp -= dmg; // 방어 무시 // 전체 공격 — 대상마다 취약/방어 개별 적용 (Lua PlayAoeFx 동기화)
if (target.hp < 0) target.hp = 0; for (const m2 of aliveList()) {
const d2 = m2.vuln > 0 ? Math.floor(totalNv * 1.5) : totalNv;
const r2 = applyDamage(m2.hp, m2.block, d2);
m2.hp = r2.hp; m2.block = r2.block;
if (m2.hp <= 0) m2.alive = false;
}
} else { } else {
const r = applyDamage(target.hp, target.block, dmg); dmg = target.vuln > 0 ? Math.floor(totalNv * 1.5) : totalNv;
target.hp = r.hp; target.block = r.block; if (c.pierce === true) {
target.hp -= dmg; // 방어 무시
if (target.hp < 0) target.hp = 0;
} else {
const r = applyDamage(target.hp, target.block, dmg);
target.hp = r.hp; target.block = r.block;
}
if (target.hp <= 0) target.alive = false;
} }
if (target.hp <= 0) target.alive = false;
if (c.block) pBlock += c.block; if (c.block) pBlock += c.block;
if (c.strength) pStr += c.strength; if (c.strength) pStr += c.strength;
if (c.selfVuln) pVuln += c.selfVuln; if (c.selfVuln) pVuln += c.selfVuln;
if (c.heal) pHp = Math.min(pHp + c.heal, PLAYER_HP);
if (stats) stats[id] = bump(stats[id], c.cost, dmg, c.block || 0); if (stats) stats[id] = bump(stats[id], c.cost, dmg, c.block || 0);
} else if (c.kind === 'Power') { } else if (c.kind === 'Power') {
if (c.powerEffect) powers.push(id); if (c.powerEffect) powers.push(id);
@@ -169,15 +181,18 @@ export function simulateCombat(data, rng, stats) {
pBlock += c.block || 0; pBlock += c.block || 0;
if (c.strength) pStr += c.strength; if (c.strength) pStr += c.strength;
if (c.selfVuln) pVuln += c.selfVuln; if (c.selfVuln) pVuln += c.selfVuln;
if (c.weak || c.vuln) { if (c.heal) pHp = Math.min(pHp + c.heal, PLAYER_HP);
if (c.weak || c.vuln || c.poison) {
const target = chooseTarget(alive, 0); const target = chooseTarget(alive, 0);
if (c.weak) target.weak += c.weak; if (c.weak) target.weak += c.weak;
if (c.vuln) target.vuln += c.vuln; if (c.vuln) target.vuln += c.vuln;
if (c.poison) target.poison += c.poison;
} }
if (stats) stats[id] = bump(stats[id], c.cost, 0, c.block || 0); if (stats) stats[id] = bump(stats[id], c.cost, 0, c.block || 0);
} }
hand.splice(idx, 1); hand.splice(idx, 1);
if (c.kind !== 'Power') discard.push(id); // 파워는 소멸 — Lua 동기화 if (c.kind !== 'Power') discard.push(id); // 파워는 소멸 — Lua 동기화
if (c.draw) draw(c.draw);
if (aliveList().length === 0) return { win: true, turns, playerHpRemaining: pHp }; if (aliveList().length === 0) return { win: true, turns, playerHpRemaining: pHp };
} }
discard.push(...hand); hand = []; discard.push(...hand); hand = [];
@@ -186,6 +201,12 @@ export function simulateCombat(data, rng, stats) {
if (pVuln > 0) pVuln--; if (pVuln > 0) pVuln--;
for (const m of mob) { for (const m of mob) {
if (!m.alive) continue; if (!m.alive) continue;
// 독 틱 — 행동 시작 시 (Lua EnemyActStep 동기화). 사망 시 행동 생략
if (m.poison > 0) {
m.hp -= m.poison;
m.poison--;
if (m.hp <= 0) { m.hp = 0; m.alive = false; continue; }
}
m.block = 0; // 매 턴 초기화 (이전 턴 블록 미이월) m.block = 0; // 매 턴 초기화 (이전 턴 블록 미이월)
const it = m.intents[m.intentIdx]; const it = m.intents[m.intentIdx];
if (it) { if (it) {
@@ -204,6 +225,8 @@ export function simulateCombat(data, rng, stats) {
if (m.vuln > 0) m.vuln--; if (m.vuln > 0) m.vuln--;
if (pHp <= 0) return { win: false, turns, playerHpRemaining: 0 }; if (pHp <= 0) return { win: false, turns, playerHpRemaining: 0 };
} }
// 독 사망 등 적 페이즈 중 전멸 처리 (Lua FinishEnemyTurn→CheckCombatEnd 동기화)
if (!mob.some((m) => m.alive)) return { win: true, turns, playerHpRemaining: pHp };
} }
return { win: false, turns, playerHpRemaining: pHp, draw: true }; return { win: false, turns, playerHpRemaining: pHp, draw: true };
} }

View File

@@ -280,3 +280,59 @@ test('simulateCombat: blockPerTurn 파워 — 매턴 방어로 약공 무효', (
assert.equal(r.draw, true); assert.equal(r.draw, true);
assert.equal(r.playerHpRemaining, 77); assert.equal(r.playerHpRemaining, 77);
}); });
test('simulateCombat: poison — 적 행동 시작 시 틱·1 감소·독 사망 시 승리 처리', () => {
const data = {
cards: { PB: { name: '포이즌', cost: 3, kind: 'Skill', poison: 4 } },
starterDeck: ['PB', 'PB', 'PB', 'PB', 'PB'],
monsters: [{ name: '적', maxHp: 10, intents: [{ kind: 'Defend', value: 0 }] }],
};
// T1: 독4 부여 → 틱 4 (hp 6, 독 3). T2: +4 → 7 틱 → hp 0 사망 → 승리
const r = simulateCombat(data, mulberry32(1));
assert.equal(r.win, true);
assert.equal(r.turns, 2);
});
test('simulateCombat: aoe — 모든 생존 적에게 피해', () => {
const data = {
cards: { TB: { name: '썬더 볼트', cost: 3, kind: 'Attack', damage: 6, aoe: true } },
starterDeck: ['TB', 'TB', 'TB', 'TB', 'TB'],
monsters: [
{ name: 'A', maxHp: 6, intents: [{ kind: 'Attack', value: 5 }] },
{ name: 'B', maxHp: 6, intents: [{ kind: 'Attack', value: 5 }] },
{ name: 'C', maxHp: 6, intents: [{ kind: 'Attack', value: 5 }] },
],
};
const r = simulateCombat(data, mulberry32(1));
assert.equal(r.win, true);
assert.equal(r.turns, 1);
});
test('simulateCombat: heal — 최대 HP 클램프', () => {
const data = {
cards: { H: { name: '힐', cost: 1, kind: 'Skill', heal: 10 } },
starterDeck: ['H', 'H', 'H', 'H', 'H'],
monsters: [{ name: '적', maxHp: 9999, intents: [{ kind: 'Attack', value: 10 }] }],
};
// 매턴: 힐로 80까지 회복(클램프) → 적 10 → 70. MAX_TURNS 도달 시 hp 70
const r = simulateCombat(data, mulberry32(1));
assert.equal(r.draw, true);
assert.equal(r.playerHpRemaining, 70);
});
test('simulateCombat: draw — 카드 드로로 손패 보충', () => {
const data = {
cards: {
D: { name: '텔레포트류', cost: 0, kind: 'Skill', draw: 1, block: 0 },
Hit: { name: '타격', cost: 1, kind: 'Attack', damage: 1 },
},
starterDeck: ['D', 'D', 'D', 'D', 'D', 'Hit', 'Hit', 'Hit'],
monsters: [{ name: '적', maxHp: 4, intents: [{ kind: 'Defend', value: 0 }] }],
};
// 드로 덕에 첫 턴 히트 3장 전부 접근 → 늦어도 2턴 내 처치 (시드 무관)
for (let s = 1; s <= 10; s++) {
const r = simulateCombat(data, mulberry32(s));
assert.equal(r.win, true, `seed ${s}`);
assert.ok(r.turns <= 2, `seed ${s}: ${r.turns}`);
}
});

View File

@@ -75219,11 +75219,11 @@
}, },
{ {
"id": "0e40000c-0000-4000-8000-00000e40000c", "id": "0e40000c-0000-4000-8000-00000e40000c",
"path": "/ui/DefaultGroup/JobSelectHud/Job_fighter", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot1",
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent", "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent",
"jsonString": { "jsonString": {
"name": "Job_fighter", "name": "Job_slot1",
"path": "/ui/DefaultGroup/JobSelectHud/Job_fighter", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot1",
"nameEditable": true, "nameEditable": true,
"enable": true, "enable": true,
"visible": true, "visible": true,
@@ -75407,11 +75407,11 @@
}, },
{ {
"id": "0e40000d-0000-4000-8000-00000e40000d", "id": "0e40000d-0000-4000-8000-00000e40000d",
"path": "/ui/DefaultGroup/JobSelectHud/Job_fighter/Name", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot1/Name",
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent",
"jsonString": { "jsonString": {
"name": "Name", "name": "Name",
"path": "/ui/DefaultGroup/JobSelectHud/Job_fighter/Name", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot1/Name",
"nameEditable": true, "nameEditable": true,
"enable": true, "enable": true,
"visible": true, "visible": true,
@@ -75585,7 +75585,7 @@
"bottom": 0 "bottom": 0
}, },
"SizeFit": false, "SizeFit": false,
"Text": "파이터", "Text": "",
"UseOutLine": true, "UseOutLine": true,
"Enable": true "Enable": true
} }
@@ -75595,11 +75595,11 @@
}, },
{ {
"id": "0e40000e-0000-4000-8000-00000e40000e", "id": "0e40000e-0000-4000-8000-00000e40000e",
"path": "/ui/DefaultGroup/JobSelectHud/Job_fighter/Desc", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot1/Desc",
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent",
"jsonString": { "jsonString": {
"name": "Desc", "name": "Desc",
"path": "/ui/DefaultGroup/JobSelectHud/Job_fighter/Desc", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot1/Desc",
"nameEditable": true, "nameEditable": true,
"enable": true, "enable": true,
"visible": true, "visible": true,
@@ -75773,7 +75773,7 @@
"bottom": 0 "bottom": 0
}, },
"SizeFit": false, "SizeFit": false,
"Text": "공격 특화\n콤보 어택 · 버서크\n라이징 어택", "Text": "",
"UseOutLine": true, "UseOutLine": true,
"Enable": true "Enable": true
} }
@@ -75783,11 +75783,11 @@
}, },
{ {
"id": "0e40000f-0000-4000-8000-00000e40000f", "id": "0e40000f-0000-4000-8000-00000e40000f",
"path": "/ui/DefaultGroup/JobSelectHud/Job_fighter/Starter", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot1/Starter",
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent",
"jsonString": { "jsonString": {
"name": "Starter", "name": "Starter",
"path": "/ui/DefaultGroup/JobSelectHud/Job_fighter/Starter", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot1/Starter",
"nameEditable": true, "nameEditable": true,
"enable": true, "enable": true,
"visible": true, "visible": true,
@@ -75961,7 +75961,7 @@
"bottom": 0 "bottom": 0
}, },
"SizeFit": false, "SizeFit": false,
"Text": "대표 카드: 콤보 어택", "Text": "",
"UseOutLine": true, "UseOutLine": true,
"Enable": true "Enable": true
} }
@@ -75971,11 +75971,11 @@
}, },
{ {
"id": "0e400010-0000-4000-8000-00000e400010", "id": "0e400010-0000-4000-8000-00000e400010",
"path": "/ui/DefaultGroup/JobSelectHud/Job_page", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot2",
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent", "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent",
"jsonString": { "jsonString": {
"name": "Job_page", "name": "Job_slot2",
"path": "/ui/DefaultGroup/JobSelectHud/Job_page", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot2",
"nameEditable": true, "nameEditable": true,
"enable": true, "enable": true,
"visible": true, "visible": true,
@@ -76159,11 +76159,11 @@
}, },
{ {
"id": "0e400011-0000-4000-8000-00000e400011", "id": "0e400011-0000-4000-8000-00000e400011",
"path": "/ui/DefaultGroup/JobSelectHud/Job_page/Name", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot2/Name",
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent",
"jsonString": { "jsonString": {
"name": "Name", "name": "Name",
"path": "/ui/DefaultGroup/JobSelectHud/Job_page/Name", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot2/Name",
"nameEditable": true, "nameEditable": true,
"enable": true, "enable": true,
"visible": true, "visible": true,
@@ -76337,7 +76337,7 @@
"bottom": 0 "bottom": 0
}, },
"SizeFit": false, "SizeFit": false,
"Text": "페이지", "Text": "",
"UseOutLine": true, "UseOutLine": true,
"Enable": true "Enable": true
} }
@@ -76347,11 +76347,11 @@
}, },
{ {
"id": "0e400012-0000-4000-8000-00000e400012", "id": "0e400012-0000-4000-8000-00000e400012",
"path": "/ui/DefaultGroup/JobSelectHud/Job_page/Desc", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot2/Desc",
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent",
"jsonString": { "jsonString": {
"name": "Desc", "name": "Desc",
"path": "/ui/DefaultGroup/JobSelectHud/Job_page/Desc", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot2/Desc",
"nameEditable": true, "nameEditable": true,
"enable": true, "enable": true,
"visible": true, "visible": true,
@@ -76525,7 +76525,7 @@
"bottom": 0 "bottom": 0
}, },
"SizeFit": false, "SizeFit": false,
"Text": "속성 차지 특화\n썬더/블리자드 차지\n파워 가드", "Text": "",
"UseOutLine": true, "UseOutLine": true,
"Enable": true "Enable": true
} }
@@ -76535,11 +76535,11 @@
}, },
{ {
"id": "0e400013-0000-4000-8000-00000e400013", "id": "0e400013-0000-4000-8000-00000e400013",
"path": "/ui/DefaultGroup/JobSelectHud/Job_page/Starter", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot2/Starter",
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent",
"jsonString": { "jsonString": {
"name": "Starter", "name": "Starter",
"path": "/ui/DefaultGroup/JobSelectHud/Job_page/Starter", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot2/Starter",
"nameEditable": true, "nameEditable": true,
"enable": true, "enable": true,
"visible": true, "visible": true,
@@ -76713,7 +76713,7 @@
"bottom": 0 "bottom": 0
}, },
"SizeFit": false, "SizeFit": false,
"Text": "대표 카드: 썬더 차지", "Text": "",
"UseOutLine": true, "UseOutLine": true,
"Enable": true "Enable": true
} }
@@ -76723,11 +76723,11 @@
}, },
{ {
"id": "0e400014-0000-4000-8000-00000e400014", "id": "0e400014-0000-4000-8000-00000e400014",
"path": "/ui/DefaultGroup/JobSelectHud/Job_spearman", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot3",
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent", "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent",
"jsonString": { "jsonString": {
"name": "Job_spearman", "name": "Job_slot3",
"path": "/ui/DefaultGroup/JobSelectHud/Job_spearman", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot3",
"nameEditable": true, "nameEditable": true,
"enable": true, "enable": true,
"visible": true, "visible": true,
@@ -76911,11 +76911,11 @@
}, },
{ {
"id": "0e400015-0000-4000-8000-00000e400015", "id": "0e400015-0000-4000-8000-00000e400015",
"path": "/ui/DefaultGroup/JobSelectHud/Job_spearman/Name", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot3/Name",
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent",
"jsonString": { "jsonString": {
"name": "Name", "name": "Name",
"path": "/ui/DefaultGroup/JobSelectHud/Job_spearman/Name", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot3/Name",
"nameEditable": true, "nameEditable": true,
"enable": true, "enable": true,
"visible": true, "visible": true,
@@ -77089,7 +77089,7 @@
"bottom": 0 "bottom": 0
}, },
"SizeFit": false, "SizeFit": false,
"Text": "스피어맨", "Text": "",
"UseOutLine": true, "UseOutLine": true,
"Enable": true "Enable": true
} }
@@ -77099,11 +77099,11 @@
}, },
{ {
"id": "0e400016-0000-4000-8000-00000e400016", "id": "0e400016-0000-4000-8000-00000e400016",
"path": "/ui/DefaultGroup/JobSelectHud/Job_spearman/Desc", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot3/Desc",
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent",
"jsonString": { "jsonString": {
"name": "Desc", "name": "Desc",
"path": "/ui/DefaultGroup/JobSelectHud/Job_spearman/Desc", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot3/Desc",
"nameEditable": true, "nameEditable": true,
"enable": true, "enable": true,
"visible": true, "visible": true,
@@ -77277,7 +77277,7 @@
"bottom": 0 "bottom": 0
}, },
"SizeFit": false, "SizeFit": false,
"Text": "방어·관통 특화\n피어스 · 아이언 월\n하이퍼 바디", "Text": "",
"UseOutLine": true, "UseOutLine": true,
"Enable": true "Enable": true
} }
@@ -77287,11 +77287,11 @@
}, },
{ {
"id": "0e400017-0000-4000-8000-00000e400017", "id": "0e400017-0000-4000-8000-00000e400017",
"path": "/ui/DefaultGroup/JobSelectHud/Job_spearman/Starter", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot3/Starter",
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent",
"jsonString": { "jsonString": {
"name": "Starter", "name": "Starter",
"path": "/ui/DefaultGroup/JobSelectHud/Job_spearman/Starter", "path": "/ui/DefaultGroup/JobSelectHud/Job_slot3/Starter",
"nameEditable": true, "nameEditable": true,
"enable": true, "enable": true,
"visible": true, "visible": true,
@@ -77465,7 +77465,7 @@
"bottom": 0 "bottom": 0
}, },
"SizeFit": false, "SizeFit": false,
"Text": "대표 카드: 피어스", "Text": "",
"UseOutLine": true, "UseOutLine": true,
"Enable": true "Enable": true
} }
@@ -289904,9 +289904,9 @@
"PreserveSprite": 0, "PreserveSprite": 0,
"StartFrameIndex": 0, "StartFrameIndex": 0,
"Color": { "Color": {
"r": 0.11, "r": 0.16,
"g": 0.12, "g": 0.2,
"b": 0.14, "b": 0.26,
"a": 1 "a": 1
}, },
"DropShadow": false, "DropShadow": false,
@@ -289936,7 +289936,7 @@
"a": 1 "a": 1
}, },
"OutlineWidth": 3, "OutlineWidth": 3,
"RaycastTarget": false, "RaycastTarget": true,
"Type": 1, "Type": 1,
"Enable": true "Enable": true
}, },
@@ -289985,7 +289985,7 @@
"KeyCode": 0, "KeyCode": 0,
"OverrideSorting": false, "OverrideSorting": false,
"Transition": 1, "Transition": 1,
"Enable": false "Enable": true
} }
], ],
"@version": 1 "@version": 1
@@ -290143,9 +290143,9 @@
"DropShadowDistance": 32, "DropShadowDistance": 32,
"Font": 0, "Font": 0,
"FontColor": { "FontColor": {
"r": 0.55, "r": 0.94,
"g": 0.58, "g": 0.74,
"b": 0.62, "b": 0.26,
"a": 1 "a": 1
}, },
"FontSize": 34, "FontSize": 34,
@@ -290280,9 +290280,9 @@
"PreserveSprite": 0, "PreserveSprite": 0,
"StartFrameIndex": 0, "StartFrameIndex": 0,
"Color": { "Color": {
"r": 0.18, "r": 0.3,
"g": 0.19, "g": 0.4,
"b": 0.21, "b": 0.75,
"a": 1 "a": 1
}, },
"DropShadow": false, "DropShadow": false,
@@ -290472,9 +290472,9 @@
"DropShadowDistance": 32, "DropShadowDistance": 32,
"Font": 0, "Font": 0,
"FontColor": { "FontColor": {
"r": 0.52, "r": 0.86,
"g": 0.55, "g": 0.9,
"b": 0.59, "b": 0.94,
"a": 1 "a": 1
}, },
"FontSize": 20, "FontSize": 20,
@@ -290500,7 +290500,7 @@
"bottom": 0 "bottom": 0
}, },
"SizeFit": false, "SizeFit": false,
"Text": "추후 열림", "Text": "마법 원거리 딜러",
"UseOutLine": true, "UseOutLine": true,
"Enable": true "Enable": true
} }
@@ -290508,288 +290508,6 @@
"@version": 1 "@version": 1
} }
}, },
{
"id": "0e000098-0000-4000-8000-00000e000098",
"path": "/ui/DefaultGroup/CharacterSelectHud/MageButton/LockBody",
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent",
"jsonString": {
"name": "LockBody",
"path": "/ui/DefaultGroup/CharacterSelectHud/MageButton/LockBody",
"nameEditable": true,
"enable": true,
"visible": true,
"localize": true,
"displayOrder": 3,
"pathConstraints": "/////",
"revision": 1,
"origin": {
"type": "Model",
"entry_id": "UISprite",
"sub_entity_id": null,
"root_entity_id": null,
"replaced_model_id": null
},
"modelId": "uisprite",
"@components": [
{
"@type": "MOD.Core.UITransformComponent",
"ActivePlatform": 255,
"AlignmentOption": 0,
"AnchorsMax": {
"x": 0.5,
"y": 0.5
},
"AnchorsMin": {
"x": 0.5,
"y": 0.5
},
"MobileOnly": false,
"OffsetMax": {
"x": 38,
"y": 33
},
"OffsetMin": {
"x": -38,
"y": -25
},
"Pivot": {
"x": 0.5,
"y": 0.5
},
"RectSize": {
"x": 76,
"y": 58
},
"UIMode": 1,
"UIScale": {
"x": 1,
"y": 1,
"z": 1
},
"UIVersion": 2,
"anchoredPosition": {
"x": 0,
"y": 4
},
"Position": {
"x": 0,
"y": 4,
"z": 0
},
"QuaternionRotation": {
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"Scale": {
"x": 1,
"y": 1,
"z": 1
},
"Enable": true
},
{
"@type": "MOD.Core.SpriteGUIRendererComponent",
"AnimClipPlayType": 0,
"EndFrameIndex": 2147483647,
"ImageRUID": {
"DataId": ""
},
"LocalPosition": {
"x": 0,
"y": 0
},
"LocalScale": {
"x": 1,
"y": 1
},
"OverrideSorting": false,
"PlayRate": 1,
"PreserveSprite": 0,
"StartFrameIndex": 0,
"Color": {
"r": 0.78,
"g": 0.69,
"b": 0.42,
"a": 1
},
"DropShadow": false,
"DropShadowAngle": 30,
"DropShadowColor": {
"r": 0,
"g": 0,
"b": 0,
"a": 0.72
},
"DropShadowDistance": 32,
"FillAmount": 1,
"FillCenter": true,
"FillClockWise": true,
"FillMethod": 0,
"FillOrigin": 0,
"FlipX": false,
"FlipY": false,
"FrameColumn": 1,
"FrameRate": 0,
"FrameRow": 1,
"Outline": false,
"OutlineColor": {
"r": 0,
"g": 0,
"b": 0,
"a": 1
},
"OutlineWidth": 3,
"RaycastTarget": false,
"Type": 1,
"Enable": true
}
],
"@version": 1
}
},
{
"id": "0e0000a2-0000-4000-8000-00000e0000a2",
"path": "/ui/DefaultGroup/CharacterSelectHud/MageButton/LockShackle",
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent",
"jsonString": {
"name": "LockShackle",
"path": "/ui/DefaultGroup/CharacterSelectHud/MageButton/LockShackle",
"nameEditable": true,
"enable": true,
"visible": true,
"localize": true,
"displayOrder": 4,
"pathConstraints": "/////",
"revision": 1,
"origin": {
"type": "Model",
"entry_id": "UISprite",
"sub_entity_id": null,
"root_entity_id": null,
"replaced_model_id": null
},
"modelId": "uisprite",
"@components": [
{
"@type": "MOD.Core.UITransformComponent",
"ActivePlatform": 255,
"AlignmentOption": 0,
"AnchorsMax": {
"x": 0.5,
"y": 0.5
},
"AnchorsMin": {
"x": 0.5,
"y": 0.5
},
"MobileOnly": false,
"OffsetMax": {
"x": 27,
"y": 69
},
"OffsetMin": {
"x": -27,
"y": 27
},
"Pivot": {
"x": 0.5,
"y": 0.5
},
"RectSize": {
"x": 54,
"y": 42
},
"UIMode": 1,
"UIScale": {
"x": 1,
"y": 1,
"z": 1
},
"UIVersion": 2,
"anchoredPosition": {
"x": 0,
"y": 48
},
"Position": {
"x": 0,
"y": 48,
"z": 0
},
"QuaternionRotation": {
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"Scale": {
"x": 1,
"y": 1,
"z": 1
},
"Enable": true
},
{
"@type": "MOD.Core.SpriteGUIRendererComponent",
"AnimClipPlayType": 0,
"EndFrameIndex": 2147483647,
"ImageRUID": {
"DataId": ""
},
"LocalPosition": {
"x": 0,
"y": 0
},
"LocalScale": {
"x": 1,
"y": 1
},
"OverrideSorting": false,
"PlayRate": 1,
"PreserveSprite": 0,
"StartFrameIndex": 0,
"Color": {
"r": 0.78,
"g": 0.69,
"b": 0.42,
"a": 1
},
"DropShadow": false,
"DropShadowAngle": 30,
"DropShadowColor": {
"r": 0,
"g": 0,
"b": 0,
"a": 0.72
},
"DropShadowDistance": 32,
"FillAmount": 1,
"FillCenter": true,
"FillClockWise": true,
"FillMethod": 0,
"FillOrigin": 0,
"FlipX": false,
"FlipY": false,
"FrameColumn": 1,
"FrameRate": 0,
"FrameRow": 1,
"Outline": false,
"OutlineColor": {
"r": 0,
"g": 0,
"b": 0,
"a": 1
},
"OutlineWidth": 3,
"RaycastTarget": false,
"Type": 1,
"Enable": true
}
],
"@version": 1
}
},
{ {
"id": "0e0000b4-0000-4000-8000-00000e0000b4", "id": "0e0000b4-0000-4000-8000-00000e0000b4",
"path": "/ui/DefaultGroup/CharacterSelectHud/StartButton", "path": "/ui/DefaultGroup/CharacterSelectHud/StartButton",