Refine rogue progression and card pools

This commit is contained in:
2026-06-29 23:34:19 +09:00
parent b4a4560678
commit 95d6155086
13 changed files with 276 additions and 380 deletions

File diff suppressed because one or more lines are too long

View File

@@ -10,7 +10,7 @@
"unique": "f5def2e8022b4e59a17d3c16414034fe", "unique": "f5def2e8022b4e59a17d3c16414034fe",
"legend": "cff71f2e472041ce80c6fbd296f42e2d" "legend": "cff71f2e472041ce80c6fbd296f42e2d"
}, },
"bandit": { "rogue": {
"normal": "9487b06867bc46269ed1d855420f457f", "normal": "9487b06867bc46269ed1d855420f457f",
"unique": "b3081fb2fb1445fa90b12b01481a78ef", "unique": "b3081fb2fb1445fa90b12b01481a78ef",
"legend": "c357d2daf31a489d95b8fa47e50dd879" "legend": "c357d2daf31a489d95b8fa47e50dd879"
@@ -25,11 +25,13 @@
"firepoison": "magician", "firepoison": "magician",
"icelightning": "magician", "icelightning": "magician",
"cleric": "magician", "cleric": "magician",
"bandit": "bandit", "curse": "rogue",
"curse": "bandit", "shiv": "rogue",
"shiv": "bandit", "rogue": "rogue",
"poisoner": "bandit", "assassin": "rogue",
"trickster": "bandit" "thief": "rogue",
"hermit": "rogue",
"thiefmaster": "rogue"
}, },
"rewardWeights": { "rewardWeights": {
"normal": 70, "normal": 70,

View File

@@ -376,7 +376,7 @@
"name": "무력화", "name": "무력화",
"cost": 0, "cost": 0,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "피해를 3 줍니다. 약화를 1 부여합니다.", "desc": "피해를 3 줍니다. 약화를 1 부여합니다.",
"weak": 1, "weak": 1,
@@ -387,7 +387,7 @@
"name": "타격", "name": "타격",
"cost": 1, "cost": 1,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "피해를 6 줍니다.", "desc": "피해를 6 줍니다.",
"damage": 6, "damage": 6,
@@ -397,7 +397,7 @@
"name": "생존자", "name": "생존자",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "방어도를 8 얻습니다. 카드를 1장 버립니다.", "desc": "방어도를 8 얻습니다. 카드를 1장 버립니다.",
"block": 8, "block": 8,
@@ -408,7 +408,7 @@
"name": "수비", "name": "수비",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "방어도를 5 얻습니다.", "desc": "방어도를 5 얻습니다.",
"block": 5, "block": 5,
@@ -418,7 +418,7 @@
"name": "칼질", "name": "칼질",
"cost": 0, "cost": 0,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "피해를 6 줍니다.", "desc": "피해를 6 줍니다.",
"damage": 6, "damage": 6,
@@ -428,7 +428,7 @@
"name": "표창", "name": "표창",
"cost": 0, "cost": 0,
"kind": "Attack", "kind": "Attack",
"class": "shiv", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "피해를 4 줍니다. 소멸.", "desc": "피해를 4 줍니다. 소멸.",
"damage": 4, "damage": 4,
@@ -440,7 +440,7 @@
"name": "단검 분사", "name": "단검 분사",
"cost": 1, "cost": 1,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "모든 적에게 피해를 4만큼 2번 줍니다.", "desc": "모든 적에게 피해를 4만큼 2번 줍니다.",
"aoe": true, "aoe": true,
@@ -452,7 +452,7 @@
"name": "단검 투척", "name": "단검 투척",
"cost": 1, "cost": 1,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "피해를 9 줍니다. 카드를 1장 뽑습니다. 카드를 1장 버립니다.", "desc": "피해를 9 줍니다. 카드를 1장 뽑습니다. 카드를 1장 버립니다.",
"drawUntilHandSize": 6, "drawUntilHandSize": 6,
@@ -464,7 +464,7 @@
"name": "독 찌르기", "name": "독 찌르기",
"cost": 1, "cost": 1,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "피해를 6 줍니다. 중독을 3 부여합니다.", "desc": "피해를 6 줍니다. 중독을 3 부여합니다.",
"poison": 3, "poison": 3,
@@ -475,7 +475,7 @@
"name": "불의의 일격", "name": "불의의 일격",
"cost": 1, "cost": 1,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "피해를 8 줍니다. 약화를 1 부여합니다.", "desc": "피해를 8 줍니다. 약화를 1 부여합니다.",
"weak": 1, "weak": 1,
@@ -487,7 +487,7 @@
"name": "선제 타격", "name": "선제 타격",
"cost": 1, "cost": 1,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "피해를 3 줍니다. 표창을 2장 손으로 가져옵니다.", "desc": "피해를 3 줍니다. 표창을 2장 손으로 가져옵니다.",
"damage": 3, "damage": 3,
@@ -498,7 +498,7 @@
"name": "완수", "name": "완수",
"cost": 1, "cost": 1,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "피해를 7 줍니다. 손에 다른 카드가 5장 이상 있다면, 1번 추가로 적중합니다.", "desc": "피해를 7 줍니다. 손에 다른 카드가 5장 이상 있다면, 1번 추가로 적중합니다.",
"damage": 7, "damage": 7,
@@ -510,7 +510,7 @@
"name": "재주넘기", "name": "재주넘기",
"cost": 1, "cost": 1,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "교활. 모든 적에게 피해를 6 줍니다.", "desc": "교활. 모든 적에게 피해를 6 줍니다.",
"aoe": true, "aoe": true,
@@ -522,7 +522,7 @@
"name": "도탄", "name": "도탄",
"cost": 2, "cost": 2,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "교활. 무작위 적에게 피해를 3만큼 4번 줍니다.", "desc": "교활. 무작위 적에게 피해를 3만큼 4번 줍니다.",
"damage": 3, "damage": 3,
@@ -535,7 +535,7 @@
"name": "예비", "name": "예비",
"cost": 0, "cost": 0,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "카드를 1장 뽑습니다. 카드를 1장 버립니다.", "desc": "카드를 1장 뽑습니다. 카드를 1장 버립니다.",
"blockPerDamageDealtThisTurn": 1, "blockPerDamageDealtThisTurn": 1,
@@ -546,7 +546,7 @@
"name": "예측", "name": "예측",
"cost": 0, "cost": 0,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "이번 턴 동안 민첩을 2 얻습니다.", "desc": "이번 턴 동안 민첩을 2 얻습니다.",
"dex": 2, "dex": 2,
@@ -556,7 +556,7 @@
"name": "튕겨내기", "name": "튕겨내기",
"cost": 0, "cost": 0,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "방어도를 4 얻습니다.", "desc": "방어도를 4 얻습니다.",
"block": 4, "block": 4,
@@ -566,7 +566,7 @@
"name": "검무", "name": "검무",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "표창을 3장 손으로 가져옵니다. 소멸.", "desc": "표창을 3장 손으로 가져옵니다. 소멸.",
"addShiv": 3, "addShiv": 3,
@@ -577,7 +577,7 @@
"name": "공중제비", "name": "공중제비",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "방어도를 5 얻습니다. 카드를 2장 뽑습니다.", "desc": "방어도를 5 얻습니다. 카드를 2장 뽑습니다.",
"block": 5, "block": 5,
@@ -588,7 +588,7 @@
"name": "구르기", "name": "구르기",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "방어도를 4 얻습니다. 다음 턴에, 방어도를 4 얻습니다", "desc": "방어도를 4 얻습니다. 다음 턴에, 방어도를 4 얻습니다",
"block": 4, "block": 4,
@@ -599,7 +599,7 @@
"name": "귀를 찢는 비명", "name": "귀를 찢는 비명",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "이번 턴 동안 모든 적이 힘을 6 잃습니다. 소멸.", "desc": "이번 턴 동안 모든 적이 힘을 6 잃습니다. 소멸.",
"draw": 1, "draw": 1,
@@ -611,7 +611,7 @@
"name": "망토와 단검", "name": "망토와 단검",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "방어도를 6 얻습니다. 표창을 1장 손으로 가져옵니다.", "desc": "방어도를 6 얻습니다. 표창을 1장 손으로 가져옵니다.",
"block": 6, "block": 6,
@@ -622,7 +622,7 @@
"name": "맹독", "name": "맹독",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "중독을 5 부여합니다.", "desc": "중독을 5 부여합니다.",
"poison": 5, "poison": 5,
@@ -632,7 +632,7 @@
"name": "뱀 물기", "name": "뱀 물기",
"cost": 2, "cost": 2,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "보존. 중독을 7 부여합니다.", "desc": "보존. 중독을 7 부여합니다.",
"poison": 7, "poison": 7,
@@ -643,7 +643,7 @@
"name": "범접 불가", "name": "범접 불가",
"cost": 2, "cost": 2,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "normal", "rarity": "normal",
"desc": "교활. 방어도를 6 얻습니다.", "desc": "교활. 방어도를 6 얻습니다.",
"block": 6, "block": 6,
@@ -654,7 +654,7 @@
"name": "꼬챙이", "name": "꼬챙이",
"cost": 2, "cost": 2,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "피해를 8만큼 X번 줍니다.", "desc": "피해를 8만큼 X번 줍니다.",
"useAllEnergy": true, "useAllEnergy": true,
@@ -666,7 +666,7 @@
"name": "배신", "name": "배신",
"cost": 0, "cost": 0,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "선천성. 피해를 11 줍니다. 소멸.", "desc": "선천성. 피해를 11 줍니다. 소멸.",
"innate": true, "innate": true,
@@ -677,7 +677,7 @@
"name": "정밀한 베기", "name": "정밀한 베기",
"cost": 0, "cost": 0,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "피해를 13 줍니다. 손에 있는 다른 카드 1장당 피해량이 2 감소합니다.", "desc": "피해를 13 줍니다. 손에 있는 다른 카드 1장당 피해량이 2 감소합니다.",
"damage": 13, "damage": 13,
@@ -688,7 +688,7 @@
"name": "마무리", "name": "마무리",
"cost": 1, "cost": 1,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "이번 턴에 사용한 공격 카드 1장당 피해를 6 줍니다.", "desc": "이번 턴에 사용한 공격 카드 1장당 피해를 6 줍니다.",
"damage": 0, "damage": 0,
@@ -699,7 +699,7 @@
"name": "메멘토 모리", "name": "메멘토 모리",
"cost": 1, "cost": 1,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "피해를 9 줍니다. 이번 턴에 버린 카드 1장당 피해량이 4 증가합니다.", "desc": "피해를 9 줍니다. 이번 턴에 버린 카드 1장당 피해량이 4 증가합니다.",
"damage": 9, "damage": 9,
@@ -710,7 +710,7 @@
"name": "목 조르기", "name": "목 조르기",
"cost": 1, "cost": 1,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "피해를 8 줍니다. 이번 턴에 카드를 사용할 때마다, 대상 적이 체력을 2 잃습니다.", "desc": "피해를 8 줍니다. 이번 턴에 카드를 사용할 때마다, 대상 적이 체력을 2 잃습니다.",
"damage": 8, "damage": 8,
@@ -720,7 +720,7 @@
"name": "프레췌", "name": "프레췌",
"cost": 1, "cost": 1,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "손에 있는 스킬 카드 1장당 피해를 5 줍니다.", "desc": "손에 있는 스킬 카드 1장당 피해를 5 줍니다.",
"damage": 0, "damage": 0,
@@ -731,7 +731,7 @@
"name": "덮치기", "name": "덮치기",
"cost": 2, "cost": 2,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "피해를 12 줍니다. 다음에 사용하는 스킬 카드의 비용이 0 이 됩니다.", "desc": "피해를 12 줍니다. 다음에 사용하는 스킬 카드의 비용이 0 이 됩니다.",
"damage": 12, "damage": 12,
@@ -742,7 +742,7 @@
"name": "돌진", "name": "돌진",
"cost": 2, "cost": 2,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "방어도를 10 얻습니다. 피해를 10 줍니다.", "desc": "방어도를 10 얻습니다. 피해를 10 줍니다.",
"block": 10, "block": 10,
@@ -753,7 +753,7 @@
"name": "천적", "name": "천적",
"cost": 2, "cost": 2,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "피해를 15 줍니다. 다음 턴에, 카드를 2장 뽑습니다.", "desc": "피해를 15 줍니다. 다음 턴에, 카드를 2장 뽑습니다.",
"nextTurnDraw": 2, "nextTurnDraw": 2,
@@ -764,7 +764,7 @@
"name": "정밀 사격", "name": "정밀 사격",
"cost": 3, "cost": 3,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "피해를 15 줍니다. 이번 턴에 스킬을 사용할 때마다 비용이 1 감소합니다.", "desc": "피해를 15 줍니다. 이번 턴에 스킬을 사용할 때마다 비용이 1 감소합니다.",
"damage": 15, "damage": 15,
@@ -775,7 +775,7 @@
"name": "계산된 도박", "name": "계산된 도박",
"cost": 0, "cost": 0,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "손에 있는 모든 카드를 버린 뒤, 버린 카드의 수만큼 카드를 뽑습니다. 소멸.", "desc": "손에 있는 모든 카드를 버린 뒤, 버린 카드의 수만큼 카드를 뽑습니다. 소멸.",
"image": "c1e19219745e44c39ae6ac2f77e347d9", "image": "c1e19219745e44c39ae6ac2f77e347d9",
@@ -786,7 +786,7 @@
"name": "들춰내기", "name": "들춰내기",
"cost": 0, "cost": 0,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "대상 적의 모든 인공물과 방어도를 제거합니다. 취약을 2 부여합니다. 소멸.", "desc": "대상 적의 모든 인공물과 방어도를 제거합니다. 취약을 2 부여합니다. 소멸.",
"vuln": 2, "vuln": 2,
@@ -799,7 +799,7 @@
"name": "숨겨진 단검", "name": "숨겨진 단검",
"cost": 0, "cost": 0,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "카드를 2장 버립니다. 표창을 2장 손으로 가져옵니다.", "desc": "카드를 2장 버립니다. 표창을 2장 손으로 가져옵니다.",
"discard": 2, "discard": 2,
@@ -810,7 +810,7 @@
"name": "탈출구", "name": "탈출구",
"cost": 0, "cost": 0,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "카드를 1장 뽑습니다. 뽑은 카드가 스킬 카드라면, 방어도를 3 얻습니다.", "desc": "카드를 1장 뽑습니다. 뽑은 카드가 스킬 카드라면, 방어도를 3 얻습니다.",
"draw": 1, "draw": 1,
@@ -821,7 +821,7 @@
"name": "곡예", "name": "곡예",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "카드를 3장 뽑습니다. 카드를 1장 버립니다.", "desc": "카드를 3장 뽑습니다. 카드를 1장 버립니다.",
"draw": 3, "draw": 3,
@@ -832,7 +832,7 @@
"name": "손기술", "name": "손기술",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "방어도를 7 얻습니다. 이번 턴 동안 손에 있는 스킬 카드 1장에 교활을 추가합니다.", "desc": "방어도를 7 얻습니다. 이번 턴 동안 손에 있는 스킬 카드 1장에 교활을 추가합니다.",
"block": 7, "block": 7,
@@ -843,7 +843,7 @@
"name": "신기루", "name": "신기루",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "모든 적에게 부여된 중독과 동일한 만큼의 방어도를 얻습니다. 소멸.", "desc": "모든 적에게 부여된 중독과 동일한 만큼의 방어도를 얻습니다. 소멸.",
"draw": 1, "draw": 1,
@@ -853,7 +853,7 @@
"name": "전문성", "name": "전문성",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "손에 있는 카드가 6장이 될 때까지 카드를 뽑습니다.", "desc": "손에 있는 카드가 6장이 될 때까지 카드를 뽑습니다.",
"image": "c1e19219745e44c39ae6ac2f77e347d9", "image": "c1e19219745e44c39ae6ac2f77e347d9",
@@ -863,7 +863,7 @@
"name": "차오르는 독", "name": "차오르는 독",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "적이 중독을 보유하고 있다면, 중독을 9 부여합니다.", "desc": "적이 중독을 보유하고 있다면, 중독을 9 부여합니다.",
"poison": 9, "poison": 9,
@@ -874,7 +874,7 @@
"name": "흐릿함", "name": "흐릿함",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "방어도를 5 얻습니다. 다음 턴 시작 시 방어도가 사라지지 않습니다.", "desc": "방어도를 5 얻습니다. 다음 턴 시작 시 방어도가 사라지지 않습니다.",
"block": 5, "block": 5,
@@ -885,7 +885,7 @@
"name": "다리 걸기", "name": "다리 걸기",
"cost": 2, "cost": 2,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "약화를 2 부여합니다. 방어도를 11 얻습니다.", "desc": "약화를 2 부여합니다. 방어도를 11 얻습니다.",
"block": 11, "block": 11,
@@ -896,7 +896,7 @@
"name": "비책", "name": "비책",
"cost": 2, "cost": 2,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "표창을 3장 손으로 가져옵니다. 이 카드의 비용이 1 감소합니다.", "desc": "표창을 3장 손으로 가져옵니다. 이 카드의 비용이 1 감소합니다.",
"addShiv": 3, "addShiv": 3,
@@ -907,7 +907,7 @@
"name": "탄성 플라스크", "name": "탄성 플라스크",
"cost": 2, "cost": 2,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "무작위 적에게 중독을 3만큼 3번 부여합니다.", "desc": "무작위 적에게 중독을 3만큼 3번 부여합니다.",
"poison": 3, "poison": 3,
@@ -919,7 +919,7 @@
"name": "반사신경", "name": "반사신경",
"cost": 3, "cost": 3,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "교활. 카드를 2장 뽑습니다.", "desc": "교활. 카드를 2장 뽑습니다.",
"draw": 2, "draw": 2,
@@ -930,7 +930,7 @@
"name": "아지랑이", "name": "아지랑이",
"cost": 3, "cost": 3,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "교활. 모든 적에게 중독을 4 부여합니다.", "desc": "교활. 모든 적에게 중독을 4 부여합니다.",
"poison": 4, "poison": 4,
@@ -941,7 +941,7 @@
"name": "전략가", "name": "전략가",
"cost": 3, "cost": 3,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "교활. 을 얻습니다.", "desc": "교활. 을 얻습니다.",
"gainEnergy": 1, "gainEnergy": 1,
@@ -952,7 +952,7 @@
"name": "괜찮은 전략", "name": "괜찮은 전략",
"cost": 1, "cost": 1,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "내 턴 종료 시, 카드를 최대 1장까지 보존합니다.", "desc": "내 턴 종료 시, 카드를 최대 1장까지 보존합니다.",
"powerEffect": "retainOne", "powerEffect": "retainOne",
@@ -963,7 +963,7 @@
"name": "무한의 검날", "name": "무한의 검날",
"cost": 1, "cost": 1,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "내 턴 시작 시, 표창을 1장 손으로 가져옵니다.", "desc": "내 턴 시작 시, 표창을 1장 손으로 가져옵니다.",
"turnStartShiv": 1, "turnStartShiv": 1,
@@ -973,7 +973,7 @@
"name": "발놀림", "name": "발놀림",
"cost": 1, "cost": 1,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "민첩을 2 얻습니다.", "desc": "민첩을 2 얻습니다.",
"dex": 2, "dex": 2,
@@ -983,7 +983,7 @@
"name": "발병", "name": "발병",
"cost": 1, "cost": 1,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "독이 3번 부여될 때마다 모든 적에게 11 피해를 줍니다.", "desc": "독이 3번 부여될 때마다 모든 적에게 11 피해를 줍니다.",
"image": "19361e72087946b1888684185b40d935", "image": "19361e72087946b1888684185b40d935",
@@ -994,7 +994,7 @@
"name": "유독 가스", "name": "유독 가스",
"cost": 1, "cost": 1,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "내 턴 시작 시, 모든 적에게 중독을 2 부여합니다.", "desc": "내 턴 시작 시, 모든 적에게 중독을 2 부여합니다.",
"poison": 2, "poison": 2,
@@ -1006,7 +1006,7 @@
"name": "정밀", "name": "정밀",
"cost": 1, "cost": 1,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "표창의 피해량이 4 증가합니다.", "desc": "표창의 피해량이 4 증가합니다.",
"shivDamageBonus": 4, "shivDamageBonus": 4,
@@ -1016,7 +1016,7 @@
"name": "환영검", "name": "환영검",
"cost": 1, "cost": 1,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "표창이 보존을 얻습니다. 매 턴마다 처음으로 사용하는 표창의 피해량이 9 증가합니다.", "desc": "표창이 보존을 얻습니다. 매 턴마다 처음으로 사용하는 표창의 피해량이 9 증가합니다.",
"shivRetain": true, "shivRetain": true,
@@ -1027,7 +1027,7 @@
"name": "스피드스터", "name": "스피드스터",
"cost": 2, "cost": 2,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "unique", "rarity": "unique",
"desc": "내 턴 동안 카드를 뽑을 때마다, 모든 적에게 피해를 2 줍니다.", "desc": "내 턴 동안 카드를 뽑을 때마다, 모든 적에게 피해를 2 줍니다.",
"aoe": true, "aoe": true,
@@ -1038,7 +1038,7 @@
"name": "대단원의 막", "name": "대단원의 막",
"cost": 0, "cost": 0,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "뽑을 카드 더미에 카드가 없을 때만 사용할 수 있습니다. 모든 적에게 피해를 60 줍니다.", "desc": "뽑을 카드 더미에 카드가 없을 때만 사용할 수 있습니다. 모든 적에게 피해를 60 줍니다.",
"playableWhenDrawPileEmpty": true, "playableWhenDrawPileEmpty": true,
@@ -1050,7 +1050,7 @@
"name": "암살", "name": "암살",
"cost": 0, "cost": 0,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "선천성. 피해를 10 줍니다. 취약을 1 부여합니다. 소멸.", "desc": "선천성. 피해를 10 줍니다. 취약을 1 부여합니다. 소멸.",
"innate": true, "innate": true,
@@ -1062,7 +1062,7 @@
"name": "메아리 참격", "name": "메아리 참격",
"cost": 1, "cost": 1,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "모든 적에게 피해를 10 줍니다. 적을 처치할 때마다 이 효과를 반복합니다.", "desc": "모든 적에게 피해를 10 줍니다. 적을 처치할 때마다 이 효과를 반복합니다.",
"aoe": true, "aoe": true,
@@ -1074,7 +1074,7 @@
"name": "사냥", "name": "사냥",
"cost": 1, "cost": 1,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "피해를 10 줍니다. 치명타라면, 카드 보상을 추가로 얻습니다. 소멸.", "desc": "피해를 10 줍니다. 치명타라면, 카드 보상을 추가로 얻습니다. 소멸.",
"damage": 10, "damage": 10,
@@ -1085,7 +1085,7 @@
"name": "살해", "name": "살해",
"cost": 3, "cost": 3,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "피해를 1 줍니다. 이번 전투 동안 뽑은 카드 1장당 피해량이 1 증가합니다.", "desc": "피해를 1 줍니다. 이번 전투 동안 뽑은 카드 1장당 피해량이 1 증가합니다.",
"damage": 1, "damage": 1,
@@ -1096,7 +1096,7 @@
"name": "불쾌", "name": "불쾌",
"cost": 2, "cost": 2,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "적이 힘을 X 잃습니다. 약화를 X 부여합니다. 소멸.", "desc": "적이 힘을 X 잃습니다. 약화를 X 부여합니다. 소멸.",
"useAllEnergy": true, "useAllEnergy": true,
@@ -1107,7 +1107,7 @@
"name": "아드레날린", "name": "아드레날린",
"cost": 0, "cost": 0,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "를 얻습니다. 카드를 2장 뽑습니다. 소멸.", "desc": "를 얻습니다. 카드를 2장 뽑습니다. 소멸.",
"draw": 2, "draw": 2,
@@ -1118,7 +1118,7 @@
"name": "강철의 폭풍", "name": "강철의 폭풍",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "손에 있는 모든 카드를 버립니다. 버린 카드의 수만큼 표창을 손으로 가져옵니다.", "desc": "손에 있는 모든 카드를 버립니다. 버린 카드의 수만큼 표창을 손으로 가져옵니다.",
"discardAll": true, "discardAll": true,
@@ -1129,7 +1129,7 @@
"name": "그림자 걸음", "name": "그림자 걸음",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "손에 있는 모든 카드를 버립니다. 다음 턴에, 공격 카드의 피해량이 2배가 됩니다.", "desc": "손에 있는 모든 카드를 버립니다. 다음 턴에, 공격 카드의 피해량이 2배가 됩니다.",
"nextTurnAttackMultiplier": 2, "nextTurnAttackMultiplier": 2,
@@ -1140,7 +1140,7 @@
"name": "그림자 은신", "name": "그림자 은신",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "이번 턴 동안 얻는 방어도가 2배가 됩니다.", "desc": "이번 턴 동안 얻는 방어도가 2배가 됩니다.",
"blockGainMultiplier": 2, "blockGainMultiplier": 2,
@@ -1150,7 +1150,7 @@
"name": "부식성 파도", "name": "부식성 파도",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "이번 턴에 카드를 뽑을 때마다, 모든 적에게 중독을 2 부여합니다.", "desc": "이번 턴에 카드를 뽑을 때마다, 모든 적에게 중독을 2 부여합니다.",
"drawPoison": 2, "drawPoison": 2,
@@ -1160,7 +1160,7 @@
"name": "잉크 칼날", "name": "잉크 칼날",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "잉크투성이 표창을 2장 손으로 가져옵니다.", "desc": "잉크투성이 표창을 2장 손으로 가져옵니다.",
"addShiv": 2, "addShiv": 2,
@@ -1170,7 +1170,7 @@
"name": "폭주", "name": "폭주",
"cost": 1, "cost": 1,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "이번 턴에 다음에 사용하는 스킬 카드가 1번 추가로 사용됩니다.", "desc": "이번 턴에 다음에 사용하는 스킬 카드가 1번 추가로 사용됩니다.",
"draw": 1, "draw": 1,
@@ -1181,7 +1181,7 @@
"name": "칼날 함정", "name": "칼날 함정",
"cost": 2, "cost": 2,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "대상 적에게 소멸된 카드 더미에 있는 모든 표창을 사용합니다.", "desc": "대상 적에게 소멸된 카드 더미에 있는 모든 표창을 사용합니다.",
"draw": 1, "draw": 1,
@@ -1191,7 +1191,7 @@
"name": "불릿 타임", "name": "불릿 타임",
"cost": 3, "cost": 3,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "이번 턴 동안 더 이상 카드를 뽑을 수 없습니다. 이번 턴 동안 손에 있는 모든 카드를 비용 없이 사용할 수 있습니다.", "desc": "이번 턴 동안 더 이상 카드를 뽑을 수 없습니다. 이번 턴 동안 손에 있는 모든 카드를 비용 없이 사용할 수 있습니다.",
"handCostZeroThisTurn": true, "handCostZeroThisTurn": true,
@@ -1202,7 +1202,7 @@
"name": "악몽", "name": "악몽",
"cost": 3, "cost": 3,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "카드를 1장 선택합니다. 다음 턴에, 그 카드의 복사본을 3장 손으로 가져옵니다. 소멸.", "desc": "카드를 1장 선택합니다. 다음 턴에, 그 카드의 복사본을 3장 손으로 가져옵니다. 소멸.",
"nextTurnCopies": 3, "nextTurnCopies": 3,
@@ -1214,7 +1214,7 @@
"name": "작업 도구", "name": "작업 도구",
"cost": 1, "cost": 1,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "내 턴 시작 시, 카드를 1장 뽑고 카드를 1장 버립니다.", "desc": "내 턴 시작 시, 카드를 1장 뽑고 카드를 1장 버립니다.",
"turnStartDraw": 1, "turnStartDraw": 1,
@@ -1225,7 +1225,7 @@
"name": "잔상", "name": "잔상",
"cost": 1, "cost": 1,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "카드를 사용할 때마다, 방어도를 1 얻습니다.", "desc": "카드를 사용할 때마다, 방어도를 1 얻습니다.",
"image": "0946f69d84464df29b24b94c744c868d", "image": "0946f69d84464df29b24b94c744c868d",
@@ -1235,7 +1235,7 @@
"name": "촉진제", "name": "촉진제",
"cost": 1, "cost": 1,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "적 턴 시작 시 독이 한 번 더 틱합니다.", "desc": "적 턴 시작 시 독이 한 번 더 틱합니다.",
"image": "19361e72087946b1888684185b40d935", "image": "19361e72087946b1888684185b40d935",
@@ -1245,7 +1245,7 @@
"name": "독 바르기", "name": "독 바르기",
"cost": 2, "cost": 2,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "공격 카드가 막히지 않은 피해를 줄 때마다, 중독을 1 부여합니다.", "desc": "공격 카드가 막히지 않은 피해를 줄 때마다, 중독을 1 부여합니다.",
"attackPoison": 1, "attackPoison": 1,
@@ -1255,7 +1255,7 @@
"name": "설계의 대가", "name": "설계의 대가",
"cost": 2, "cost": 2,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "사용한 스킬 카드는 교활해집니다.", "desc": "사용한 스킬 카드는 교활해집니다.",
"image": "c1e19219745e44c39ae6ac2f77e347d9", "image": "c1e19219745e44c39ae6ac2f77e347d9",
@@ -1265,7 +1265,7 @@
"name": "추적", "name": "추적",
"cost": 2, "cost": 2,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "약화 상태의 적이 공격 카드로 받는 피해가 2배가 됩니다.", "desc": "약화 상태의 적이 공격 카드로 받는 피해가 2배가 됩니다.",
"attackDamageVsWeakMultiplier": 2, "attackDamageVsWeakMultiplier": 2,
@@ -1275,7 +1275,7 @@
"name": "칼날 부채", "name": "칼날 부채",
"cost": 2, "cost": 2,
"kind": "Skill", "kind": "Skill",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "표창이 이제 모든 적을 대상으로 합니다. 표창을 4장 손으로 가져옵니다.", "desc": "표창이 이제 모든 적을 대상으로 합니다. 표창을 4장 손으로 가져옵니다.",
"addShiv": 4, "addShiv": 4,
@@ -1286,7 +1286,7 @@
"name": "구렁이의 형상", "name": "구렁이의 형상",
"cost": 3, "cost": 3,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "카드를 사용할 때마다, 무작위 적에게 피해를 4 줍니다.", "desc": "카드를 사용할 때마다, 무작위 적에게 피해를 4 줍니다.",
"cardPlayedRandomDamage": 4, "cardPlayedRandomDamage": 4,
@@ -1296,7 +1296,7 @@
"name": "연마", "name": "연마",
"cost": 3, "cost": 3,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "교활. 민첩을 1 얻습니다. 가시를 4 얻습니다.", "desc": "교활. 민첩을 1 얻습니다. 가시를 4 얻습니다.",
"dex": 1, "dex": 1,
@@ -1308,7 +1308,7 @@
"name": "진압", "name": "진압",
"cost": 0, "cost": 0,
"kind": "Attack", "kind": "Attack",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "선천성. 피해를 11 줍니다. 약화를 3 부여합니다.", "desc": "선천성. 피해를 11 줍니다. 약화를 3 부여합니다.",
"innate": true, "innate": true,
@@ -1320,7 +1320,7 @@
"name": "유령의 형상", "name": "유령의 형상",
"cost": 3, "cost": 3,
"kind": "Power", "kind": "Power",
"class": "bandit", "class": "rogue",
"rarity": "legend", "rarity": "legend",
"desc": "불가침을 2 얻습니다. 내 턴 종료 시 민첩을 1 잃습니다.", "desc": "불가침을 2 얻습니다. 내 턴 종료 시 민첩을 1 잃습니다.",
"intangible": 2, "intangible": 2,
@@ -1353,18 +1353,18 @@
"MagicGuard", "MagicGuard",
"MagicClaw" "MagicClaw"
], ],
"bandit": [ "rogue": [
"SilentStrike",
"SilentStrike",
"SilentStrike",
"SilentStrike",
"SilentStrike",
"SilentDefend",
"SilentDefend",
"SilentDefend",
"SilentDefend",
"SilentDefend",
"Neutralize", "Neutralize",
"SilentStrike",
"SilentStrike",
"SilentStrike",
"SilentStrike",
"SilentStrike",
"SilentDefend",
"SilentDefend",
"SilentDefend",
"SilentDefend",
"SilentDefend",
"Survivor" "Survivor"
] ]
} }

Binary file not shown.

View File

@@ -1,7 +1,7 @@
{ {
"portraits": { "portraits": {
"warrior": "28c88fdc5ab44f34a8b3fc1e19d4ce78", "warrior": "28c88fdc5ab44f34a8b3fc1e19d4ce78",
"magician": "3b9ea1f066a744bb859df47fef817277", "magician": "3b9ea1f066a744bb859df47fef817277",
"bandit": "efa920e58d31426486ef974106e7dc8b" "rogue": "efa920e58d31426486ef974106e7dc8b"
} }
} }

View File

@@ -11,14 +11,14 @@ self:RenderCharacterSelect()`, [
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'className' }, { Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'className' },
]), ]),
method('RenderCharacterSelect', `local base = "/ui/SelectUIGroup/CharacterSelectHud" method('RenderCharacterSelect', `local base = "/ui/SelectUIGroup/CharacterSelectHud"
local arts = { { p = "/WarriorButton/Art", c = "warrior" }, { p = "/MageButton/Art", c = "magician" }, { p = "/BanditButton/Art", c = "bandit" } } local arts = { { p = "/WarriorButton/Art", c = "warrior" }, { p = "/MageButton/Art", c = "magician" }, { p = "/BanditButton/Art", c = "rogue" } }
for i = 1, #arts do for i = 1, #arts do
local e = _EntityService:GetEntityByPath(base .. arts[i].p) local e = _EntityService:GetEntityByPath(base .. arts[i].p)
if e ~= nil and e.SpriteGUIRendererComponent ~= nil and self.ClassPortraits ~= nil and self.ClassPortraits[arts[i].c] ~= nil then if e ~= nil and e.SpriteGUIRendererComponent ~= nil and self.ClassPortraits ~= nil and self.ClassPortraits[arts[i].c] ~= nil then
e.SpriteGUIRendererComponent.ImageRUID = self.ClassPortraits[arts[i].c] e.SpriteGUIRendererComponent.ImageRUID = self.ClassPortraits[arts[i].c]
end end
end end
local btns = { { p = "/WarriorButton", c = "warrior" }, { p = "/MageButton", c = "magician" }, { p = "/BanditButton", c = "bandit" } } local btns = { { p = "/WarriorButton", c = "warrior" }, { p = "/MageButton", c = "magician" }, { p = "/BanditButton", c = "rogue" } }
for i = 1, #btns do for i = 1, #btns do
local e = _EntityService:GetEntityByPath(base .. btns[i].p) local e = _EntityService:GetEntityByPath(base .. btns[i].p)
if e ~= nil then if e ~= nil then
@@ -43,17 +43,17 @@ if self.SelectedClass == "warrior" then
name = "전사" name = "전사"
eng = "Warrior" eng = "Warrior"
btnName = "/WarriorButton" btnName = "/WarriorButton"
desc = "직업군 · 모험가" .. nl .. "방어를 쌓고 버티다 강하게 역공하는 단단한 탱커." desc = "직업군 · 모험가" .. nl .. "방어를 쌓고 버티는 공격형 전사."
elseif self.SelectedClass == "bandit" then elseif self.SelectedClass == "rogue" then
name = "도적" name = "도적"
eng = "Thief" eng = "Rogue"
btnName = "/BanditButton" btnName = "/BanditButton"
desc = "직업군 · 모험가" .. nl .. "표창 난사와 독으로 빠르게 몰아치는 민첩한 직업." desc = "직업군 · 모험가" .. nl .. "기동성과 콤보로 빠르게 움직이는 도적."
elseif self.SelectedClass == "magician" then elseif self.SelectedClass == "magician" then
name = "법사" name = "법사"
eng = "Magician" eng = "Magician"
btnName = "/MageButton" btnName = "/MageButton"
desc = "직업군 · 모험가" .. nl .. "약하지만 게이지 운용으로 화력을 집중하는 원소 마법사." desc = "직업군 · 모험가" .. nl .. "주문과 원소로 전장을 장악하는 마법사."
end end
if btnName ~= "" then if btnName ~= "" then
local art = _EntityService:GetEntityByPath(base .. btnName .. "/Art") local art = _EntityService:GetEntityByPath(base .. btnName .. "/Art")
@@ -65,7 +65,7 @@ end
self:SetText(base .. "/SelectedClass", name) self:SetText(base .. "/SelectedClass", name)
self:SetText(base .. "/SelectedClass/SelectedClassEng", eng) self:SetText(base .. "/SelectedClass/SelectedClassEng", eng)
self:SetText(base .. "/SelectedClassStatus", desc)`), self:SetText(base .. "/SelectedClassStatus", desc)`),
method('StartNewGame', `if self.SelectedClass ~= "warrior" and self.SelectedClass ~= "bandit" and self.SelectedClass ~= "magician" then method('StartNewGame', `if self.SelectedClass ~= "warrior" and self.SelectedClass ~= "rogue" and self.SelectedClass ~= "magician" then
self:SetText("/ui/SelectUIGroup/CharacterSelectHud/SelectedClassStatus", "직업을 먼저 선택하세요") self:SetText("/ui/SelectUIGroup/CharacterSelectHud/SelectedClassStatus", "직업을 먼저 선택하세요")
return return
end end

View File

@@ -707,7 +707,7 @@ if anyAlive == false then
end end
end end
if node ~= nil and node.type == "boss" then if node ~= nil and node.type == "boss" then
if self.PlayerJob == "" and self.Floor < self.RunLength then if self:ShouldOfferJobChoice() == true then
self:ShowJobChoice() self:ShowJobChoice()
else else
if self.PlayerJob ~= "" then self:AwardSouls(1) end if self.PlayerJob ~= "" then self:AwardSouls(1) end

View File

@@ -77,7 +77,7 @@ if thiefTab ~= nil and (thiefTab.ButtonComponent ~= nil or thiefTab:AddComponent
thiefTab:DisconnectEvent(ButtonClickEvent, self.ThiefDeckTabHandler) thiefTab:DisconnectEvent(ButtonClickEvent, self.ThiefDeckTabHandler)
self.ThiefDeckTabHandler = nil self.ThiefDeckTabHandler = nil
end end
self.ThiefDeckTabHandler = thiefTab:ConnectEvent(ButtonClickEvent, function() self:SetClassDeckTab("bandit") end) self.ThiefDeckTabHandler = thiefTab:ConnectEvent(ButtonClickEvent, function() self:SetClassDeckTab("rogue") end)
end end
local mageTab = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/MageTab") local mageTab = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/MageTab")
if mageTab ~= nil and (mageTab.ButtonComponent ~= nil or mageTab:AddComponent("ButtonComponent") ~= nil) then if mageTab ~= nil and (mageTab.ButtonComponent ~= nil or mageTab:AddComponent("ButtonComponent") ~= nil) then
@@ -101,8 +101,8 @@ end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], N
return return
end end
local className = self.SelectedClass local className = self.SelectedClass
if className ~= "warrior" and className ~= "magician" and className ~= "bandit" then if className ~= "warrior" and className ~= "magician" and className ~= "rogue" then
className = "bandit" className = "rogue"
end end
self.CodexMode = false self.CodexMode = false
self.ClassDeckMode = true self.ClassDeckMode = true
@@ -119,8 +119,8 @@ self:Toast("테스트 카드 추가 모드")`),
end end
self.ClassDeckCards = {} self.ClassDeckCards = {}
self.ClassDeckTitle = "직업 덱" self.ClassDeckTitle = "직업 덱"
if className ~= "warrior" and className ~= "magician" and className ~= "bandit" then if className ~= "warrior" and className ~= "magician" and className ~= "rogue" then
className = "bandit" className = "rogue"
end end
self.ClassDeckClass = className self.ClassDeckClass = className
local allowed = {} local allowed = {}
@@ -137,10 +137,8 @@ elseif className == "magician" then
allowed["cleric"] = true allowed["cleric"] = true
self.ClassDeckTitle = "마법사 전체 덱" self.ClassDeckTitle = "마법사 전체 덱"
else else
allowed["bandit"] = true local pools = self.ClassPools or {}
allowed["shiv"] = true allowed = pools[className] or allowed
allowed["poisoner"] = true
allowed["trickster"] = true
self.ClassDeckTitle = "도적 전체 덱" self.ClassDeckTitle = "도적 전체 덱"
end end
for id, c in pairs(self.Cards) do for id, c in pairs(self.Cards) do
@@ -162,7 +160,7 @@ self:RenderAllDeck()
self:RenderClassDeckTabs()`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'className' }]), self:RenderClassDeckTabs()`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'className' }]),
method('RenderClassDeckTabs', `local tabs = { method('RenderClassDeckTabs', `local tabs = {
{ path = "/ui/DeckUIGroup/DeckAllHud/WarriorTab", cls = "warrior" }, { path = "/ui/DeckUIGroup/DeckAllHud/WarriorTab", cls = "warrior" },
{ path = "/ui/DeckUIGroup/DeckAllHud/ThiefTab", cls = "bandit" }, { path = "/ui/DeckUIGroup/DeckAllHud/ThiefTab", cls = "rogue" },
{ path = "/ui/DeckUIGroup/DeckAllHud/MageTab", cls = "magician" }, { path = "/ui/DeckUIGroup/DeckAllHud/MageTab", cls = "magician" },
} }
for i = 1, #tabs do for i = 1, #tabs do

View File

@@ -1,5 +1,5 @@
import { method, RUN_LENGTH, GOLD_PER_WIN, CARD_PRICE, REST_HEAL, RELIC_PRICE, ACT_COUNT, ACT_MAPS, LOBBY_MAP, LOBBY_SPAWN } from '../lib/codeblock.mjs'; import { method, RUN_LENGTH, GOLD_PER_WIN, CARD_PRICE, REST_HEAL, RELIC_PRICE, ACT_COUNT, ACT_MAPS, LOBBY_MAP, LOBBY_SPAWN } from '../lib/codeblock.mjs';
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, CARDFRAMES, RARITIES, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, POTIONS, luaSoulShopTable, frameRuid, luaFramesTable, luaNodeIconsTable, luaRelicsTable, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs'; import { CARDS, ENEMIES, CLASSES, JOBS, CLASS_POOLS, SOUL_UNLOCKS, CARDFRAMES, RARITIES, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, POTIONS, luaSoulShopTable, frameRuid, luaFramesTable, luaNodeIconsTable, luaRelicsTable, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable, luaClassPoolsTable } from '../lib/data.mjs';
import { UI_FILE, COMMON_FILE, UI_ROOT, GENERATED_UI_SECTIONS, UI_APPEND_ORDER, DISABLED_STOCK_CONTROLS, TRANSPARENT, DARK, GOLD, ATTACK, DEFEND, SKILL, DAMAGE_DIGIT_RUIDS, DAMAGE_POP_MAX_DIGITS, DAMAGE_POP_DIGIT_W, DAMAGE_POP_DIGIT_H, DAMAGE_POP_DIGIT_SPACING, MAX_MONSTERS, HEAD_OFFSET_Y, HP_BAR_W, WHITE, CARD_NAME_TEXT, CARD_DESC_TEXT, cardFaceLayout, CARD_W, CARD_H, CARD_SPACING, CARD_XS, ALIGN_CENTER, ALIGN_BOTTOM_CENTER, guid, transform, sprite, button, text, scrollLayoutGroup, popupLayerFor, uiOrderFor, displayOrderFor, applySortingOverride, entity, uiPath, sectionRoot, isGeneratedUiEntity, appendUiSection } from '../lib/ui-helpers.mjs'; import { UI_FILE, COMMON_FILE, UI_ROOT, GENERATED_UI_SECTIONS, UI_APPEND_ORDER, DISABLED_STOCK_CONTROLS, TRANSPARENT, DARK, GOLD, ATTACK, DEFEND, SKILL, DAMAGE_DIGIT_RUIDS, DAMAGE_POP_MAX_DIGITS, DAMAGE_POP_DIGIT_W, DAMAGE_POP_DIGIT_H, DAMAGE_POP_DIGIT_SPACING, MAX_MONSTERS, HEAD_OFFSET_Y, HP_BAR_W, WHITE, CARD_NAME_TEXT, CARD_DESC_TEXT, cardFaceLayout, CARD_W, CARD_H, CARD_SPACING, CARD_XS, ALIGN_CENTER, ALIGN_BOTTOM_CENTER, guid, transform, sprite, button, text, scrollLayoutGroup, popupLayerFor, uiOrderFor, displayOrderFor, applySortingOverride, entity, uiPath, sectionRoot, isGeneratedUiEntity, appendUiSection } from '../lib/ui-helpers.mjs';
export const jobMethods = [ export const jobMethods = [
@@ -20,9 +20,32 @@ if kind == "relic" then
else else
self:ShowJobSelect() self:ShowJobSelect()
end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'kind' }]), end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'kind' }]),
method('ShowJobSelect', `local opts = self.Jobs[self.SelectedClass] method('ShouldOfferJobChoice', `if self.Floor >= self.RunLength then
if opts == nil then return false
opts = self.Jobs["warrior"] end
if self.PlayerJob == "" then
return true
end
if self.PlayerJob == "assassin" or self.PlayerJob == "thief" then
return true
end
return false`, [], 0, 'boolean'),
method('CurrentJobChoices', `if self.PlayerJob == "" then
local baseClass = self.SelectedClass
if baseClass == "rogue" then
return self.Jobs["rogue"]
end
return self.Jobs[baseClass] or self.Jobs["rogue"]
elseif self.PlayerJob == "assassin" then
return self.Jobs["assassin"]
elseif self.PlayerJob == "thief" then
return self.Jobs["thief"]
end
return nil`, [], 0, 'any'),
method('ShowJobSelect', `local opts = self:CurrentJobChoices()
if opts == nil or #opts <= 0 then
self:ContinueAfterBoss()
return
end end
self.JobOpts = opts self.JobOpts = opts
for i = 1, 3 do for i = 1, 3 do
@@ -34,7 +57,7 @@ for i = 1, 3 do
self:SetText(base .. "/Desc", o.desc) self:SetText(base .. "/Desc", o.desc)
local sc = self.Cards[o.starter] local sc = self.Cards[o.starter]
if sc ~= nil then if sc ~= nil then
self:SetText(base .. "/Starter", "대표 카드: " .. sc.name) self:SetText(base .. "/Starter", "기본 카드: " .. sc.name)
end end
else else
self:SetEntityEnabled(base, false) self:SetEntityEnabled(base, false)
@@ -52,15 +75,28 @@ self:SetEntityEnabled("/ui/SelectUIGroup/JobSelectHud", true)`),
end end
if self.SelectedClass == "warrior" then if self.SelectedClass == "warrior" then
return "전사" return "전사"
elseif self.SelectedClass == "bandit" then elseif self.SelectedClass == "rogue" then
return "도적" return "도적"
elseif self.SelectedClass == "magician" then elseif self.SelectedClass == "magician" then
return "마법사" return "마법사"
end end
return "플레이어"`, [], 0, 'string'), return "플레이어"`, [], 0, 'string'),
method('SetJob', `self.PlayerJob = jobId method('SetJob', `local prevJob = self.PlayerJob
local tier = 2
if prevJob == "assassin" or prevJob == "thief" then
tier = 3
end
self.PlayerJob = jobId
local starter = "" local starter = ""
local opts = self.Jobs[self.SelectedClass] or {} local opts = {}
if prevJob == "" then
local baseClass = self.SelectedClass
opts = self.Jobs[baseClass] or self.Jobs["rogue"] or {}
elseif prevJob == "assassin" then
opts = self.Jobs["assassin"] or {}
elseif prevJob == "thief" then
opts = self.Jobs["thief"] or {}
end
for i = 1, #opts do for i = 1, #opts do
if opts[i].id == jobId then if opts[i].id == jobId then
starter = opts[i].starter starter = opts[i].starter
@@ -70,7 +106,7 @@ if starter ~= "" then
table.insert(self.RunDeck, starter) table.insert(self.RunDeck, starter)
local sc = self.Cards[starter] local sc = self.Cards[starter]
if sc ~= nil then if sc ~= nil then
self:Toast("2차 전직: " .. self:JobLabel() .. "! 신규 카드 — " .. sc.name) self:Toast(tostring(tier) .. "차 전직: " .. self:JobLabel() .. "! 신규 카드 — " .. sc.name)
end end
end end
self:SetText("/ui/RunUIGroup/CombatHud/PlayerPanel/Name", self:JobLabel()) self:SetText("/ui/RunUIGroup/CombatHud/PlayerPanel/Name", self:JobLabel())

View File

@@ -5,7 +5,10 @@ import { UI_FILE, COMMON_FILE, UI_ROOT, GENERATED_UI_SECTIONS, UI_APPEND_ORDER,
export const rewardMethods = [ export const rewardMethods = [
method('CardPool', `local pool = {} method('CardPool', `local pool = {}
for id, c in pairs(self.Cards) do for id, c in pairs(self.Cards) do
if c.token ~= true and (c.class == self.SelectedClass or (self.PlayerJob ~= "" and c.class == self.PlayerJob)) then local pools = self.ClassPools or {}
local basePool = pools[self.SelectedClass] or pools.rogue or {}
local jobPool = pools[self.PlayerJob] or {}
if c.token ~= true and ((basePool[c.class] == true) or (self.PlayerJob ~= "" and jobPool[c.class] == true)) then
table.insert(pool, id) table.insert(pool, id)
end end
end end

View File

@@ -1,17 +1,17 @@
import { method, RUN_LENGTH, GOLD_PER_WIN, CARD_PRICE, REST_HEAL, RELIC_PRICE, ACT_COUNT, ACT_MAPS, LOBBY_MAP, LOBBY_SPAWN } from '../lib/codeblock.mjs'; import { method, RUN_LENGTH, GOLD_PER_WIN, CARD_PRICE, REST_HEAL, RELIC_PRICE, ACT_COUNT, ACT_MAPS, LOBBY_MAP, LOBBY_SPAWN } from '../lib/codeblock.mjs';
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, CARDFRAMES, RARITIES, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, POTIONS, luaSoulShopTable, frameRuid, luaFramesTable, luaNodeIconsTable, luaCharsTable, luaRelicsTable, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs'; import { CARDS, ENEMIES, CLASSES, JOBS, CLASS_POOLS, SOUL_UNLOCKS, CARDFRAMES, RARITIES, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, POTIONS, luaSoulShopTable, frameRuid, luaFramesTable, luaNodeIconsTable, luaCharsTable, luaClassPoolsTable, luaRelicsTable, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
import { UI_FILE, COMMON_FILE, UI_ROOT, GENERATED_UI_SECTIONS, UI_APPEND_ORDER, DISABLED_STOCK_CONTROLS, TRANSPARENT, DARK, GOLD, ATTACK, DEFEND, SKILL, DAMAGE_DIGIT_RUIDS, DAMAGE_POP_MAX_DIGITS, DAMAGE_POP_DIGIT_W, DAMAGE_POP_DIGIT_H, DAMAGE_POP_DIGIT_SPACING, MAX_MONSTERS, HEAD_OFFSET_Y, HP_BAR_W, WHITE, CARD_NAME_TEXT, CARD_DESC_TEXT, cardFaceLayout, CARD_W, CARD_H, CARD_SPACING, CARD_XS, ALIGN_CENTER, ALIGN_BOTTOM_CENTER, guid, transform, sprite, button, text, scrollLayoutGroup, popupLayerFor, uiOrderFor, displayOrderFor, applySortingOverride, entity, uiPath, sectionRoot, isGeneratedUiEntity, appendUiSection } from '../lib/ui-helpers.mjs'; import { UI_FILE, COMMON_FILE, UI_ROOT, GENERATED_UI_SECTIONS, UI_APPEND_ORDER, DISABLED_STOCK_CONTROLS, TRANSPARENT, DARK, GOLD, ATTACK, DEFEND, SKILL, DAMAGE_DIGIT_RUIDS, DAMAGE_POP_MAX_DIGITS, DAMAGE_POP_DIGIT_W, DAMAGE_POP_DIGIT_H, DAMAGE_POP_DIGIT_SPACING, MAX_MONSTERS, HEAD_OFFSET_Y, HP_BAR_W, WHITE, CARD_NAME_TEXT, CARD_DESC_TEXT, cardFaceLayout, CARD_W, CARD_H, CARD_SPACING, CARD_XS, ALIGN_CENTER, ALIGN_BOTTOM_CENTER, guid, transform, sprite, button, text, scrollLayoutGroup, popupLayerFor, uiOrderFor, displayOrderFor, applySortingOverride, entity, uiPath, sectionRoot, isGeneratedUiEntity, appendUiSection } from '../lib/ui-helpers.mjs';
export const runMethods = [ export const runMethods = [
method('StartRun', `if self.SelectedClass == "magician" then method('StartRun', `if self.SelectedClass == "magician" then
self.PlayerMaxHp = ${CLASSES.magician.maxHp} \tself.PlayerMaxHp = ${CLASSES.magician.maxHp}
self.RunDeck = { ${CARDS.starterDecks.magician.map(luaStr).join(', ')} } \tself.RunDeck = { ${CARDS.starterDecks.magician.map(luaStr).join(', ')} }
elseif self.SelectedClass == "bandit" then elseif self.SelectedClass == "rogue" then
self.PlayerMaxHp = ${CLASSES.bandit.maxHp} \tself.PlayerMaxHp = ${CLASSES.rogue.maxHp}
self.RunDeck = { ${CARDS.starterDecks.bandit.map(luaStr).join(', ')} } \tself.RunDeck = { ${CARDS.starterDecks.rogue.map(luaStr).join(', ')} }
else else
self.PlayerMaxHp = ${CLASSES.warrior.maxHp} \tself.PlayerMaxHp = ${CLASSES.warrior.maxHp}
self.RunDeck = { ${CARDS.starterDecks.warrior.map(luaStr).join(', ')} } \tself.RunDeck = { ${CARDS.starterDecks.warrior.map(luaStr).join(', ')} }
end end
self.PlayerMaxHp = self.PlayerMaxHp - self:AscStartHpPenalty() self.PlayerMaxHp = self.PlayerMaxHp - self:AscStartHpPenalty()
self.PlayerHp = self.PlayerMaxHp self.PlayerHp = self.PlayerMaxHp
@@ -30,6 +30,7 @@ self.CurrentNodeId = ""
self.CurrentEnemyId = "" self.CurrentEnemyId = ""
self.PlayerJob = "" self.PlayerJob = ""
${luaJobsTable(JOBS)} ${luaJobsTable(JOBS)}
${luaClassPoolsTable()}
${luaFramesTable()} ${luaFramesTable()}
${luaNodeIconsTable()} ${luaNodeIconsTable()}
${luaCharsTable()} ${luaCharsTable()}
@@ -46,16 +47,16 @@ if lp ~= nil then cam = lp.CameraComponent end
if cam == nil then cam = _CameraService:GetCurrentCameraComponent() end if cam == nil then cam = _CameraService:GetCurrentCameraComponent() end
if cam ~= nil then cam.ConfineCameraArea = false end if cam ~= nil then cam.ConfineCameraArea = false end
_TimerService:SetTimerOnce(function() _TimerService:SetTimerOnce(function()
local cc = nil \tlocal cc = nil
local lp2 = _UserService.LocalPlayer \tlocal lp2 = _UserService.LocalPlayer
if lp2 ~= nil then cc = lp2.CameraComponent end \tif lp2 ~= nil then cc = lp2.CameraComponent end
if cc == nil then cc = _CameraService:GetCurrentCameraComponent() end \tif cc == nil then cc = _CameraService:GetCurrentCameraComponent() end
if cc ~= nil then \tif cc ~= nil then
cc.ZoomRatio = ${CAM.zoomRatio} \t\tcc.ZoomRatio = ${CAM.zoomRatio}
cc.CameraOffset = Vector2(${CAM.cameraOffsetX}, ${CAM.cameraOffsetY}) \t\tcc.CameraOffset = Vector2(${CAM.cameraOffsetX}, ${CAM.cameraOffsetY})
cc.ScreenOffset = Vector2(${CAM.screenOffsetX}, ${CAM.screenOffsetY}) \t\tcc.ScreenOffset = Vector2(${CAM.screenOffsetX}, ${CAM.screenOffsetY})
cc.ConfineCameraArea = true \t\tcc.ConfineCameraArea = true
end \tend
end, 0.2)`), end, 0.2)`),
method('StartCombat', `self:ShowState("combat") method('StartCombat', `self:ShowState("combat")
self:KickCombatCamera() self:KickCombatCamera()
@@ -122,7 +123,7 @@ self.Hand = {}
${luaCardsTable(CARDS.cards)} ${luaCardsTable(CARDS.cards)}
self.DrawPile = {} self.DrawPile = {}
for i = 1, #self.RunDeck do for i = 1, #self.RunDeck do
self.DrawPile[i] = self.RunDeck[i] \tself.DrawPile[i] = self.RunDeck[i]
end end
self:Shuffle(self.DrawPile) self:Shuffle(self.DrawPile)
self:PrepareCombatDrawPile() self:PrepareCombatDrawPile()
@@ -133,123 +134,14 @@ self:ApplyRelics("combatStart")
self:RenderCombat() self:RenderCombat()
local slotTid = 0 local slotTid = 0
slotTid = _TimerService:SetTimerRepeat(function() slotTid = _TimerService:SetTimerRepeat(function()
if self.CombatOver == true or self.Monsters == nil or #self.Monsters == 0 then \tif self.CombatOver == true or self.Monsters == nil or #self.Monsters == 0 then
_TimerService:ClearTimer(slotTid) \t\t_TimerService:ClearTimer(slotTid)
return \t\treturn
end \tend
for i = 1, #self.Monsters do \tfor i = 1, #self.Monsters do
if self.Monsters[i] ~= nil and self.Monsters[i].alive == true then \t\tif self.Monsters[i] ~= nil and self.Monsters[i].alive == true then
self:PositionMonsterSlot(i) \t\t\tself:PositionMonsterSlot(i)
end \t\tend
end \tend
end, 0.15)`), end, 0.15)`),
method('RegisterMonster', `if self.Registered == nil then
self.Registered = {}
end
local g = group
if g == nil or g == "" then g = "combat" end
local mp = mapName
if mp == nil then mp = "" end
table.insert(self.Registered, { entity = monster, enemyId = enemyId, group = g, map = mp })`, [
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'monster' },
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'enemyId' },
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'group' },
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'mapName' },
]),
method('BuildMonsters', `self.Monsters = {}
local g = "combat"
local node = self.MapNodes[self.CurrentNodeId]
if node ~= nil and node.type ~= nil then g = node.type end
local pmap = ""
local lp = _UserService.LocalPlayer
if lp ~= nil and lp.CurrentMapName ~= nil then pmap = lp.CurrentMapName end
local reg = self.Registered or {}
for i = 1, #reg do
if reg[i].entity ~= nil and isvalid(reg[i].entity) then
reg[i].entity:SetVisible(false)
end
end
local byGroup = {}
for i = 1, #reg do
local r = reg[i]
if r.entity ~= nil and isvalid(r.entity) and (r.map == nil or r.map == "" or pmap == "" or r.map == pmap) then
local gg = r.group
if gg == nil or gg == "" then gg = "combat" end
if byGroup[gg] == nil then byGroup[gg] = {} end
local x = 0
if r.entity.TransformComponent ~= nil then
x = r.entity.TransformComponent.WorldPosition.x
end
table.insert(byGroup[gg], { entity = r.entity, enemyId = r.enemyId, x = x })
end
end
-- 노드 타입별 랜덤 구성: 일반 1~3 / 엘리트 1+일반0~2 / 보스 1
local chosen = {}
local function takeFrom(key, k)
local src = byGroup[key] or {}
local pool = {}
for i = 1, #src do pool[i] = src[i] end
self:Shuffle(pool)
local taken = 0
for i = 1, #pool do
if taken >= k then break end
table.insert(chosen, pool[i])
taken = taken + 1
end
end
if g == "boss" then
takeFrom("boss", 1)
elseif g == "elite" then
takeFrom("elite", 1)
takeFrom("combat", math.random(0, 2))
else
takeFrom("combat", math.random(1, 3))
end
if #chosen == 0 then takeFrom(g, 1) end
if #chosen == 0 then takeFrom("combat", 1) end
table.sort(chosen, function(a, b) return a.x < b.x end)
local mult = 1 + (self.Floor - 1) * 0.45
if g == "elite" or g == "boss" then
mult = mult + self:AscEliteBonus()
end
local n = #chosen
if n > ${MAX_MONSTERS} then n = ${MAX_MONSTERS} end
for i = 1, n do
local item = chosen[i]
local e = self.Enemies[item.enemyId]
if e == nil then e = { name = item.enemyId, maxHp = 10, intents = { { kind = "Attack", value = 5 } } } end
local intents = {}
for k = 1, #e.intents do
local v = e.intents[k].value or 0
if e.intents[k].kind == "Attack" then
v = math.floor(v * mult * self:AscAtkMult())
elseif e.intents[k].kind ~= "Debuff" then
v = math.floor(v * mult)
end
intents[k] = { kind = e.intents[k].kind, value = v, effect = e.intents[k].effect, card = e.intents[k].card, count = e.intents[k].count }
end
local maxHp = math.floor(e.maxHp * mult * self:AscHpMult())
local hitClip = nil
local standClip = nil
if item.entity.StateAnimationComponent ~= nil then
pcall(function()
hitClip = item.entity.StateAnimationComponent.ActionSheet["hit"]
standClip = item.entity.StateAnimationComponent.ActionSheet["stand"]
end)
end
local startIdx = 1
if #intents > 0 then startIdx = math.random(1, #intents) end
self.Monsters[i] = { entity = item.entity, enemyId = item.enemyId, name = e.name,
hp = maxHp, maxHp = maxHp, block = 0, str = e.str or 0, weak = 0, vuln = 0, poison = 0, artifact = e.artifact or 0,
hitClip = hitClip, standClip = standClip, motionBusy = false,
intents = intents, intentIdx = startIdx, alive = true, slot = i }
self:ReviveMonsterEntity(item.entity)
self:PositionMonsterSlot(i)
end
self.TargetIndex = 1`),
method('ReviveMonsterEntity', `if monster == nil or not isvalid(monster) then
return
end
monster:SetEnable(true)
monster:SetVisible(true)`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'monster' }]),
]; ];

View File

@@ -75,7 +75,7 @@ if thief ~= nil and (thief.ButtonComponent ~= nil or thief:AddComponent("ButtonC
thief:DisconnectEvent(ButtonClickEvent, self.ThiefSelectHandler) thief:DisconnectEvent(ButtonClickEvent, self.ThiefSelectHandler)
self.ThiefSelectHandler = nil self.ThiefSelectHandler = nil
end end
self.ThiefSelectHandler = thief:ConnectEvent(ButtonClickEvent, function() self:SelectClass("bandit") end) self.ThiefSelectHandler = thief:ConnectEvent(ButtonClickEvent, function() self:SelectClass("rogue") end)
end end
local mage = _EntityService:GetEntityByPath("/ui/SelectUIGroup/CharacterSelectHud/MageButton") local mage = _EntityService:GetEntityByPath("/ui/SelectUIGroup/CharacterSelectHud/MageButton")
if mage ~= nil and (mage.ButtonComponent ~= nil or mage:AddComponent("ButtonComponent") ~= nil) then if mage ~= nil and (mage.ButtonComponent ~= nil or mage:AddComponent("ButtonComponent") ~= nil) then

View File

@@ -6,7 +6,7 @@ const ENEMIES = JSON.parse(readFileSync('data/enemies.json', 'utf8'));
// 검증 (fail-fast): 잘못된 데이터면 생성 중단 // 검증 (fail-fast): 잘못된 데이터면 생성 중단
const CLASSES = { const CLASSES = {
warrior: { label: '전사', maxHp: 80 }, warrior: { label: '전사', maxHp: 80 },
bandit: { label: '도적', maxHp: 70 }, rogue: { label: '도적', maxHp: 70 },
magician: { label: '마법사', maxHp: 70 }, magician: { label: '마법사', maxHp: 70 },
}; };
for (const cls of Object.keys(CLASSES)) { for (const cls of Object.keys(CLASSES)) {
@@ -27,18 +27,35 @@ const JOBS = {
{ id: 'icelightning', name: '위자드(썬·콜)', desc: '광역·빙결 특화\n썬더 볼트(전체)\n콜드 빔 · 칠링 스텝', starter: 'ThunderBolt' }, { id: 'icelightning', name: '위자드(썬·콜)', desc: '광역·빙결 특화\n썬더 볼트(전체)\n콜드 빔 · 칠링 스텝', starter: 'ThunderBolt' },
{ id: 'cleric', name: '클레릭', desc: '회복·축복 특화\n힐 · 블레스\n홀리 애로우', starter: 'Heal' }, { id: 'cleric', name: '클레릭', desc: '회복·축복 특화\n힐 · 블레스\n홀리 애로우', starter: 'Heal' },
], ],
bandit: [ rogue: [
{ id: 'shiv', name: 'Shiv', desc: 'Many small attacks\nBlade Dance\nAccuracy · After Image', starter: 'BladeDance' }, { id: 'assassin', name: '어쌔신', desc: '단일 폭딜\n표창 · 검무\n치명타 연계', starter: 'BladeDance' },
{ id: 'poisoner', name: 'Poison', desc: 'Poison scaling\nDeadly Poison\nCatalyst · Noxious Fumes', starter: 'DeadlyPoison' }, { id: 'thief', name: '시프', desc: '독과 순환\n중독 · 플라스크\n손패 운영', starter: 'DeadlyPoison' },
{ id: 'trickster', name: 'Trickster', desc: 'Draw and tempo\nAcrobatics\nAdrenaline · Tools', starter: 'Acrobatics' },
], ],
assassin: [
{ id: 'hermit', name: '허밋', desc: '교활한 마무리\n회피 · 잔상\n턴 순환', starter: 'Footwork' },
],
thief: [
{ id: 'thiefmaster', name: '시프마스터', desc: '고급 운영\n교활 · 반복\n스킬 연계', starter: 'MasterPlanner' },
],
};
const CLASS_POOLS = {
warrior: ['warrior', 'fighter', 'page', 'spearman'],
magician: ['magician', 'firepoison', 'icelightning', 'cleric'],
rogue: ['rogue'],
assassin: ['rogue', 'assassin'],
thief: ['rogue', 'thief'],
hermit: ['rogue', 'assassin', 'hermit'],
thiefmaster: ['rogue', 'thief', 'thiefmaster'],
}; };
for (const [cls, jobs] of Object.entries(JOBS)) { for (const [cls, jobs] of Object.entries(JOBS)) {
for (const j of jobs) { for (const j of jobs) {
if (!CARDS.cards[j.starter]) throw new Error(`[gen-slaydeck] JOBS.${cls}.${j.id} 대표 카드 없음: ${j.starter}`); if (!CARDS.cards[j.starter]) throw new Error(`[gen-slaydeck] JOBS.${cls}.${j.id} starter 카드 없음: ${j.starter}`);
} }
} }
// 영혼(soul) 메타 해금 — 2차 전직 후 보스 클리어로 영혼 적립, 로비 영혼상점에서 구매 → 다음 런 이점 function luaClassPoolsTable() {
const rows = Object.entries(CLASS_POOLS).map(([cls, list]) => '\t' + cls + ' = { ' + list.map((c) => c + ' = true').join(', ') + ' },').join('\n');
return 'self.ClassPools = {\n' + rows + '\n}';
}
const SOUL_UNLOCKS = [ const SOUL_UNLOCKS = [
{ key: 'meso', name: '두둑한 지갑', desc: '런 시작 시 메소 +60', cost: 3 }, { key: 'meso', name: '두둑한 지갑', desc: '런 시작 시 메소 +60', cost: 3 },
{ key: 'hp', name: '단련된 육체', desc: '시작 최대 HP +15', cost: 4 }, { key: 'hp', name: '단련된 육체', desc: '시작 최대 HP +15', cost: 4 },
@@ -101,7 +118,7 @@ if (!/^[0-9a-f]{32}$/.test(NODEICONS.background || '')) throw new Error('[gen-sl
// 캐릭터 선택 초상화 (메이커 임포트 RUID, data/characters.json 단일 소스 — 교체 시 이 파일만 수정 후 재생성) // 캐릭터 선택 초상화 (메이커 임포트 RUID, data/characters.json 단일 소스 — 교체 시 이 파일만 수정 후 재생성)
const CHARS = JSON.parse(readFileSync('data/characters.json', 'utf8')); const CHARS = JSON.parse(readFileSync('data/characters.json', 'utf8'));
for (const c of ['warrior', 'magician', 'bandit']) { for (const c of ['warrior', 'magician', 'rogue']) {
if (!/^[0-9a-f]{32}$/.test((CHARS.portraits || {})[c] || '')) throw new Error(`[gen-slaydeck] characters.json portraits.${c} RUID 누락/형식오류`); if (!/^[0-9a-f]{32}$/.test((CHARS.portraits || {})[c] || '')) throw new Error(`[gen-slaydeck] characters.json portraits.${c} RUID 누락/형식오류`);
} }
@@ -262,4 +279,4 @@ function luaDeckTable(deck) {
return `self.DrawPile = { ${deck.map(luaStr).join(', ')} }`; return `self.DrawPile = { ${deck.map(luaStr).join(', ')} }`;
} }
export { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, luaCharsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable }; export { CARDS, ENEMIES, CLASSES, JOBS, CLASS_POOLS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, luaCharsTable, luaClassPoolsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable };