메이플 전사 전직 스킬 카드 및 연계 기믹 구현 #110
File diff suppressed because one or more lines are too long
@@ -19,7 +19,9 @@
|
|||||||
"classToFrame": {
|
"classToFrame": {
|
||||||
"warrior": "warrior",
|
"warrior": "warrior",
|
||||||
"fighter": "warrior",
|
"fighter": "warrior",
|
||||||
|
"crusader": "warrior",
|
||||||
"page": "warrior",
|
"page": "warrior",
|
||||||
|
"knight": "warrior",
|
||||||
"spearman": "warrior",
|
"spearman": "warrior",
|
||||||
"magician": "magician",
|
"magician": "magician",
|
||||||
"firepoison": "magician",
|
"firepoison": "magician",
|
||||||
|
|||||||
572
data/cards.json
572
data/cards.json
@@ -45,7 +45,7 @@
|
|||||||
"fx": "48754be05be344358cddd55aa8fe11f4"
|
"fx": "48754be05be344358cddd55aa8fe11f4"
|
||||||
},
|
},
|
||||||
"MoltenFist": {
|
"MoltenFist": {
|
||||||
"name": "녹아내리는 주먹",
|
"name": "불꽃 강타",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 10,
|
"damage": 10,
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
"fx": "6f283d96d5804b4fb88009685a11c1f8"
|
"fx": "6f283d96d5804b4fb88009685a11c1f8"
|
||||||
},
|
},
|
||||||
"BodySlam": {
|
"BodySlam": {
|
||||||
"name": "몸통 박치기",
|
"name": "방패 밀어치기",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damageFromCurrentBlock": 1,
|
"damageFromCurrentBlock": 1,
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
"fx": "2799562e984c4a4da3b73e1f3431057c"
|
"fx": "2799562e984c4a4da3b73e1f3431057c"
|
||||||
},
|
},
|
||||||
"SwordBoomerang": {
|
"SwordBoomerang": {
|
||||||
"name": "부메랑 칼날",
|
"name": "회전 검격",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 3,
|
"damage": 3,
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
"fx": "1b0afc410a1a458598eb7ca2fb26e97d"
|
"fx": "1b0afc410a1a458598eb7ca2fb26e97d"
|
||||||
},
|
},
|
||||||
"SetupStrike": {
|
"SetupStrike": {
|
||||||
"name": "사전 타격",
|
"name": "기선 타격",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 7,
|
"damage": 7,
|
||||||
@@ -106,7 +106,7 @@
|
|||||||
"fx": "291b2298db88476f8ae3c6c78f53c9b7"
|
"fx": "291b2298db88476f8ae3c6c78f53c9b7"
|
||||||
},
|
},
|
||||||
"TwinStrike": {
|
"TwinStrike": {
|
||||||
"name": "이중 타격",
|
"name": "연속 타격",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 5,
|
"damage": 5,
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
"fx": "863812c5c2f84132ac7465b50ec2283e"
|
"fx": "863812c5c2f84132ac7465b50ec2283e"
|
||||||
},
|
},
|
||||||
"Breakthrough": {
|
"Breakthrough": {
|
||||||
"name": "정면 돌파",
|
"name": "전선 돌파",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 9,
|
"damage": 9,
|
||||||
@@ -130,7 +130,7 @@
|
|||||||
"fx": "e8a145a6c43d493f9ad50fab03b200aa"
|
"fx": "e8a145a6c43d493f9ad50fab03b200aa"
|
||||||
},
|
},
|
||||||
"Thunderclap": {
|
"Thunderclap": {
|
||||||
"name": "천둥",
|
"name": "전장의 벼락",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 4,
|
"damage": 4,
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
"fx": "48754be05be344358cddd55aa8fe11f4"
|
"fx": "48754be05be344358cddd55aa8fe11f4"
|
||||||
},
|
},
|
||||||
"IronWave": {
|
"IronWave": {
|
||||||
"name": "철의 파동",
|
"name": "강철 검기",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 5,
|
"damage": 5,
|
||||||
@@ -156,7 +156,7 @@
|
|||||||
"fx": "6f283d96d5804b4fb88009685a11c1f8"
|
"fx": "6f283d96d5804b4fb88009685a11c1f8"
|
||||||
},
|
},
|
||||||
"PommelStrike": {
|
"PommelStrike": {
|
||||||
"name": "폼멜 타격",
|
"name": "칼자루 타격",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 9,
|
"damage": 9,
|
||||||
@@ -168,7 +168,7 @@
|
|||||||
"fx": "997fa6999aa04dbb97a1dd99025fa2ba"
|
"fx": "997fa6999aa04dbb97a1dd99025fa2ba"
|
||||||
},
|
},
|
||||||
"PerfectedStrike": {
|
"PerfectedStrike": {
|
||||||
"name": "완벽한 타격",
|
"name": "숙련된 타격",
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 6,
|
"damage": 6,
|
||||||
@@ -181,7 +181,7 @@
|
|||||||
"fx": "2799562e984c4a4da3b73e1f3431057c"
|
"fx": "2799562e984c4a4da3b73e1f3431057c"
|
||||||
},
|
},
|
||||||
"Cinder": {
|
"Cinder": {
|
||||||
"name": "잿불",
|
"name": "잿불 검격",
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 18,
|
"damage": 18,
|
||||||
@@ -193,7 +193,7 @@
|
|||||||
"fx": "1b0afc410a1a458598eb7ca2fb26e97d"
|
"fx": "1b0afc410a1a458598eb7ca2fb26e97d"
|
||||||
},
|
},
|
||||||
"Bloodletting": {
|
"Bloodletting": {
|
||||||
"name": "사혈",
|
"name": "투지 분출",
|
||||||
"cost": 0,
|
"cost": 0,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"gainEnergy": 2,
|
"gainEnergy": 2,
|
||||||
@@ -203,7 +203,7 @@
|
|||||||
"rarity": "normal"
|
"rarity": "normal"
|
||||||
},
|
},
|
||||||
"Tremble": {
|
"Tremble": {
|
||||||
"name": "떨림",
|
"name": "위압",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"vuln": 3,
|
"vuln": 3,
|
||||||
@@ -225,7 +225,7 @@
|
|||||||
"rarity": "normal"
|
"rarity": "normal"
|
||||||
},
|
},
|
||||||
"TrueGrit": {
|
"TrueGrit": {
|
||||||
"name": "진정한 끈기",
|
"name": "강철 의지",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"block": 7,
|
"block": 7,
|
||||||
@@ -236,7 +236,7 @@
|
|||||||
"rarity": "normal"
|
"rarity": "normal"
|
||||||
},
|
},
|
||||||
"Havoc": {
|
"Havoc": {
|
||||||
"name": "파괴",
|
"name": "전투 전술",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"nextSkillCostZero": true,
|
"nextSkillCostZero": true,
|
||||||
@@ -246,7 +246,7 @@
|
|||||||
"rarity": "normal"
|
"rarity": "normal"
|
||||||
},
|
},
|
||||||
"ShrugItOff": {
|
"ShrugItOff": {
|
||||||
"name": "흘려보내기",
|
"name": "충격 흘리기",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"block": 8,
|
"block": 8,
|
||||||
@@ -257,7 +257,7 @@
|
|||||||
"rarity": "normal"
|
"rarity": "normal"
|
||||||
},
|
},
|
||||||
"BloodWall": {
|
"BloodWall": {
|
||||||
"name": "피의 벽",
|
"name": "붉은 방벽",
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"block": 16,
|
"block": 16,
|
||||||
@@ -281,7 +281,7 @@
|
|||||||
"fx": "1b0afc410a1a458598eb7ca2fb26e97d"
|
"fx": "1b0afc410a1a458598eb7ca2fb26e97d"
|
||||||
},
|
},
|
||||||
"Spite": {
|
"Spite": {
|
||||||
"name": "악의",
|
"name": "맹공",
|
||||||
"cost": 0,
|
"cost": 0,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 5,
|
"damage": 5,
|
||||||
@@ -293,7 +293,7 @@
|
|||||||
"fx": "291b2298db88476f8ae3c6c78f53c9b7"
|
"fx": "291b2298db88476f8ae3c6c78f53c9b7"
|
||||||
},
|
},
|
||||||
"Bully": {
|
"Bully": {
|
||||||
"name": "협박",
|
"name": "전장의 압박",
|
||||||
"cost": 0,
|
"cost": 0,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 4,
|
"damage": 4,
|
||||||
@@ -305,7 +305,7 @@
|
|||||||
"fx": "863812c5c2f84132ac7465b50ec2283e"
|
"fx": "863812c5c2f84132ac7465b50ec2283e"
|
||||||
},
|
},
|
||||||
"Pillage": {
|
"Pillage": {
|
||||||
"name": "갈취",
|
"name": "전리품 확보",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 6,
|
"damage": 6,
|
||||||
@@ -317,7 +317,7 @@
|
|||||||
"fx": "e8a145a6c43d493f9ad50fab03b200aa"
|
"fx": "e8a145a6c43d493f9ad50fab03b200aa"
|
||||||
},
|
},
|
||||||
"Rampage": {
|
"Rampage": {
|
||||||
"name": "광란",
|
"name": "거듭된 맹공",
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 12,
|
"damage": 12,
|
||||||
@@ -329,7 +329,7 @@
|
|||||||
"fx": "48754be05be344358cddd55aa8fe11f4"
|
"fx": "48754be05be344358cddd55aa8fe11f4"
|
||||||
},
|
},
|
||||||
"AshenStrike": {
|
"AshenStrike": {
|
||||||
"name": "잿빛 타격",
|
"name": "누적 타격",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 6,
|
"damage": 6,
|
||||||
@@ -341,7 +341,7 @@
|
|||||||
"fx": "6f283d96d5804b4fb88009685a11c1f8"
|
"fx": "6f283d96d5804b4fb88009685a11c1f8"
|
||||||
},
|
},
|
||||||
"Dismantle": {
|
"Dismantle": {
|
||||||
"name": "해체",
|
"name": "갑주 가르기",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 8,
|
"damage": 8,
|
||||||
@@ -353,7 +353,7 @@
|
|||||||
"fx": "997fa6999aa04dbb97a1dd99025fa2ba"
|
"fx": "997fa6999aa04dbb97a1dd99025fa2ba"
|
||||||
},
|
},
|
||||||
"Hemokinesis": {
|
"Hemokinesis": {
|
||||||
"name": "혈류",
|
"name": "혼신의 일격",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 15,
|
"damage": 15,
|
||||||
@@ -364,7 +364,7 @@
|
|||||||
"fx": "2799562e984c4a4da3b73e1f3431057c"
|
"fx": "2799562e984c4a4da3b73e1f3431057c"
|
||||||
},
|
},
|
||||||
"FightMe": {
|
"FightMe": {
|
||||||
"name": "덤벼라!",
|
"name": "결투 신청",
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 5,
|
"damage": 5,
|
||||||
@@ -377,7 +377,7 @@
|
|||||||
"fx": "1b0afc410a1a458598eb7ca2fb26e97d"
|
"fx": "1b0afc410a1a458598eb7ca2fb26e97d"
|
||||||
},
|
},
|
||||||
"Unrelenting": {
|
"Unrelenting": {
|
||||||
"name": "무자비",
|
"name": "진격의 일격",
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 14,
|
"damage": 14,
|
||||||
@@ -402,7 +402,7 @@
|
|||||||
"fx": "863812c5c2f84132ac7465b50ec2283e"
|
"fx": "863812c5c2f84132ac7465b50ec2283e"
|
||||||
},
|
},
|
||||||
"Bludgeon": {
|
"Bludgeon": {
|
||||||
"name": "몽둥이질",
|
"name": "대검 강타",
|
||||||
"cost": 3,
|
"cost": 3,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 32,
|
"damage": 32,
|
||||||
@@ -413,7 +413,7 @@
|
|||||||
"fx": "e8a145a6c43d493f9ad50fab03b200aa"
|
"fx": "e8a145a6c43d493f9ad50fab03b200aa"
|
||||||
},
|
},
|
||||||
"HowlFromBeyond": {
|
"HowlFromBeyond": {
|
||||||
"name": "저편의 울음소리",
|
"name": "전장의 포효",
|
||||||
"cost": 3,
|
"cost": 3,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 16,
|
"damage": 16,
|
||||||
@@ -426,7 +426,7 @@
|
|||||||
"fx": "48754be05be344358cddd55aa8fe11f4"
|
"fx": "48754be05be344358cddd55aa8fe11f4"
|
||||||
},
|
},
|
||||||
"Stomp": {
|
"Stomp": {
|
||||||
"name": "짓밟기",
|
"name": "진형 붕괴",
|
||||||
"cost": 3,
|
"cost": 3,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 12,
|
"damage": 12,
|
||||||
@@ -450,7 +450,7 @@
|
|||||||
"rarity": "unique"
|
"rarity": "unique"
|
||||||
},
|
},
|
||||||
"BattleTrance": {
|
"BattleTrance": {
|
||||||
"name": "전투 최면",
|
"name": "전투 집중",
|
||||||
"cost": 0,
|
"cost": 0,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"draw": 3,
|
"draw": 3,
|
||||||
@@ -461,7 +461,7 @@
|
|||||||
"rarity": "unique"
|
"rarity": "unique"
|
||||||
},
|
},
|
||||||
"Colossus": {
|
"Colossus": {
|
||||||
"name": "거상",
|
"name": "철벽 자세",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"block": 5,
|
"block": 5,
|
||||||
@@ -494,7 +494,7 @@
|
|||||||
"rarity": "unique"
|
"rarity": "unique"
|
||||||
},
|
},
|
||||||
"BurningPact": {
|
"BurningPact": {
|
||||||
"name": "불타는 조약",
|
"name": "결사의 각오",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"discard": 1,
|
"discard": 1,
|
||||||
@@ -505,7 +505,7 @@
|
|||||||
"rarity": "unique"
|
"rarity": "unique"
|
||||||
},
|
},
|
||||||
"EvilEye": {
|
"EvilEye": {
|
||||||
"name": "악마의 눈",
|
"name": "빈틈없는 방어",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"block": 16,
|
"block": 16,
|
||||||
@@ -515,7 +515,7 @@
|
|||||||
"rarity": "unique"
|
"rarity": "unique"
|
||||||
},
|
},
|
||||||
"ForgottenRitual": {
|
"ForgottenRitual": {
|
||||||
"name": "잊힌 의식",
|
"name": "비상 전력",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"gainEnergy": 2,
|
"gainEnergy": 2,
|
||||||
@@ -550,7 +550,7 @@
|
|||||||
"rarity": "unique"
|
"rarity": "unique"
|
||||||
},
|
},
|
||||||
"InfernalBlade": {
|
"InfernalBlade": {
|
||||||
"name": "지옥검",
|
"name": "임시 무장",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"addRandomCardCount": 1,
|
"addRandomCardCount": 1,
|
||||||
@@ -585,7 +585,7 @@
|
|||||||
"rarity": "unique"
|
"rarity": "unique"
|
||||||
},
|
},
|
||||||
"StoneArmor": {
|
"StoneArmor": {
|
||||||
"name": "돌 갑옷",
|
"name": "강철 갑옷",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Power",
|
"kind": "Power",
|
||||||
"powerEffect": "blockPerTurn",
|
"powerEffect": "blockPerTurn",
|
||||||
@@ -596,7 +596,7 @@
|
|||||||
"rarity": "unique"
|
"rarity": "unique"
|
||||||
},
|
},
|
||||||
"FeelNoPain": {
|
"FeelNoPain": {
|
||||||
"name": "무감각",
|
"name": "고통 인내",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Power",
|
"kind": "Power",
|
||||||
"powerEffect": "blockPerTurn",
|
"powerEffect": "blockPerTurn",
|
||||||
@@ -629,7 +629,7 @@
|
|||||||
"rarity": "unique"
|
"rarity": "unique"
|
||||||
},
|
},
|
||||||
"Juggling": {
|
"Juggling": {
|
||||||
"name": "저글링",
|
"name": "연속 공세",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Power",
|
"kind": "Power",
|
||||||
"cardPlayedRandomDamage": 3,
|
"cardPlayedRandomDamage": 3,
|
||||||
@@ -670,7 +670,7 @@
|
|||||||
"rarity": "unique"
|
"rarity": "unique"
|
||||||
},
|
},
|
||||||
"PactsEnd": {
|
"PactsEnd": {
|
||||||
"name": "조약의 끝",
|
"name": "최후의 일격",
|
||||||
"cost": 0,
|
"cost": 0,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 17,
|
"damage": 17,
|
||||||
@@ -722,7 +722,7 @@
|
|||||||
"fx": "997fa6999aa04dbb97a1dd99025fa2ba"
|
"fx": "997fa6999aa04dbb97a1dd99025fa2ba"
|
||||||
},
|
},
|
||||||
"TearAsunder": {
|
"TearAsunder": {
|
||||||
"name": "갈가리 찢기",
|
"name": "삼연참",
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 5,
|
"damage": 5,
|
||||||
@@ -734,7 +734,7 @@
|
|||||||
"fx": "2799562e984c4a4da3b73e1f3431057c"
|
"fx": "2799562e984c4a4da3b73e1f3431057c"
|
||||||
},
|
},
|
||||||
"FiendFire": {
|
"FiendFire": {
|
||||||
"name": "지옥불",
|
"name": "최후의 패",
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 0,
|
"damage": 0,
|
||||||
@@ -748,7 +748,7 @@
|
|||||||
"fx": "1b0afc410a1a458598eb7ca2fb26e97d"
|
"fx": "1b0afc410a1a458598eb7ca2fb26e97d"
|
||||||
},
|
},
|
||||||
"Mangle": {
|
"Mangle": {
|
||||||
"name": "난도질",
|
"name": "공포의 일격",
|
||||||
"cost": 3,
|
"cost": 3,
|
||||||
"kind": "Attack",
|
"kind": "Attack",
|
||||||
"damage": 15,
|
"damage": 15,
|
||||||
@@ -771,7 +771,7 @@
|
|||||||
"rarity": "legend"
|
"rarity": "legend"
|
||||||
},
|
},
|
||||||
"Cascade": {
|
"Cascade": {
|
||||||
"name": "연쇄",
|
"name": "연속 전개",
|
||||||
"cost": 0,
|
"cost": 0,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"useAllEnergy": true,
|
"useAllEnergy": true,
|
||||||
@@ -783,7 +783,7 @@
|
|||||||
"rarity": "legend"
|
"rarity": "legend"
|
||||||
},
|
},
|
||||||
"PrimalForce": {
|
"PrimalForce": {
|
||||||
"name": "원시의 힘",
|
"name": "전사의 본능",
|
||||||
"cost": 0,
|
"cost": 0,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"handCostZeroThisTurn": true,
|
"handCostZeroThisTurn": true,
|
||||||
@@ -793,7 +793,7 @@
|
|||||||
"rarity": "legend"
|
"rarity": "legend"
|
||||||
},
|
},
|
||||||
"Offering": {
|
"Offering": {
|
||||||
"name": "제물",
|
"name": "전력 방출",
|
||||||
"cost": 0,
|
"cost": 0,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"gainEnergy": 2,
|
"gainEnergy": 2,
|
||||||
@@ -805,7 +805,7 @@
|
|||||||
"rarity": "legend"
|
"rarity": "legend"
|
||||||
},
|
},
|
||||||
"OneTwoPunch": {
|
"OneTwoPunch": {
|
||||||
"name": "원투 펀치",
|
"name": "연계 전술",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"nextSkillRepeatCount": 1,
|
"nextSkillRepeatCount": 1,
|
||||||
@@ -815,7 +815,7 @@
|
|||||||
"rarity": "legend"
|
"rarity": "legend"
|
||||||
},
|
},
|
||||||
"Stoke": {
|
"Stoke": {
|
||||||
"name": "화력 증폭",
|
"name": "전투 재정비",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Skill",
|
"kind": "Skill",
|
||||||
"exhaustHandAll": true,
|
"exhaustHandAll": true,
|
||||||
@@ -849,7 +849,7 @@
|
|||||||
"rarity": "legend"
|
"rarity": "legend"
|
||||||
},
|
},
|
||||||
"Aggression": {
|
"Aggression": {
|
||||||
"name": "공격성",
|
"name": "공격 태세",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Power",
|
"kind": "Power",
|
||||||
"turnStartDraw": 1,
|
"turnStartDraw": 1,
|
||||||
@@ -859,7 +859,7 @@
|
|||||||
"rarity": "legend"
|
"rarity": "legend"
|
||||||
},
|
},
|
||||||
"Cruelty": {
|
"Cruelty": {
|
||||||
"name": "악랄함",
|
"name": "전투 광기",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Power",
|
"kind": "Power",
|
||||||
"powerEffect": "strengthPerTurn",
|
"powerEffect": "strengthPerTurn",
|
||||||
@@ -870,7 +870,7 @@
|
|||||||
"rarity": "legend"
|
"rarity": "legend"
|
||||||
},
|
},
|
||||||
"CrimsonMantle": {
|
"CrimsonMantle": {
|
||||||
"name": "핏빛 망토",
|
"name": "붉은 수호",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"kind": "Power",
|
"kind": "Power",
|
||||||
"powerEffect": "blockPerTurn",
|
"powerEffect": "blockPerTurn",
|
||||||
@@ -892,7 +892,7 @@
|
|||||||
"rarity": "legend"
|
"rarity": "legend"
|
||||||
},
|
},
|
||||||
"DarkEmbrace": {
|
"DarkEmbrace": {
|
||||||
"name": "어둠의 포옹",
|
"name": "소멸의 숙련",
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"kind": "Power",
|
"kind": "Power",
|
||||||
"drawOnExhaust": 1,
|
"drawOnExhaust": 1,
|
||||||
@@ -914,7 +914,7 @@
|
|||||||
"rarity": "legend"
|
"rarity": "legend"
|
||||||
},
|
},
|
||||||
"Juggernaut": {
|
"Juggernaut": {
|
||||||
"name": "절대적인 힘",
|
"name": "검격 파동",
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"kind": "Power",
|
"kind": "Power",
|
||||||
"cardPlayedRandomDamage": 5,
|
"cardPlayedRandomDamage": 5,
|
||||||
@@ -924,7 +924,7 @@
|
|||||||
"rarity": "legend"
|
"rarity": "legend"
|
||||||
},
|
},
|
||||||
"Hellraiser": {
|
"Hellraiser": {
|
||||||
"name": "지옥검무",
|
"name": "타격의 달인",
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"kind": "Power",
|
"kind": "Power",
|
||||||
"drawNameMatchAutoPlay": "타격",
|
"drawNameMatchAutoPlay": "타격",
|
||||||
@@ -945,7 +945,7 @@
|
|||||||
"rarity": "legend"
|
"rarity": "legend"
|
||||||
},
|
},
|
||||||
"DemonForm": {
|
"DemonForm": {
|
||||||
"name": "악마의 형상",
|
"name": "전신 투지",
|
||||||
"cost": 3,
|
"cost": 3,
|
||||||
"kind": "Power",
|
"kind": "Power",
|
||||||
"powerEffect": "strengthPerTurn",
|
"powerEffect": "strengthPerTurn",
|
||||||
@@ -955,6 +955,466 @@
|
|||||||
"class": "warrior",
|
"class": "warrior",
|
||||||
"rarity": "legend"
|
"rarity": "legend"
|
||||||
},
|
},
|
||||||
|
"SlashBlast": {
|
||||||
|
"name": "슬래시 블러스트",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Attack",
|
||||||
|
"damage": 7,
|
||||||
|
"aoe": true,
|
||||||
|
"damagePerCombo": 1,
|
||||||
|
"desc": "모든 적에게 피해 7. 콤보당 피해 +1",
|
||||||
|
"image": "863812c5c2f84132ac7465b50ec2283e",
|
||||||
|
"class": "warrior",
|
||||||
|
"rarity": "normal"
|
||||||
|
},
|
||||||
|
"WarriorLeap": {
|
||||||
|
"name": "워리어 리프",
|
||||||
|
"cost": 0,
|
||||||
|
"kind": "Skill",
|
||||||
|
"block": 4,
|
||||||
|
"nextTurnBlock": 4,
|
||||||
|
"exhaust": true,
|
||||||
|
"desc": "방어도 4. 다음 턴 방어도 4. 소멸.",
|
||||||
|
"image": "90a9bf8eeb844b578b4e2d93ac43fedf",
|
||||||
|
"class": "warrior",
|
||||||
|
"rarity": "normal"
|
||||||
|
},
|
||||||
|
"LeapAttack": {
|
||||||
|
"name": "리프 어택",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Attack",
|
||||||
|
"damage": 3,
|
||||||
|
"hits": 2,
|
||||||
|
"aoe": true,
|
||||||
|
"block": 5,
|
||||||
|
"desc": "모든 적에게 피해 3 x 2회. 방어도 5",
|
||||||
|
"image": "997fa6999aa04dbb97a1dd99025fa2ba",
|
||||||
|
"class": "warrior",
|
||||||
|
"rarity": "normal"
|
||||||
|
},
|
||||||
|
"IronBody": {
|
||||||
|
"name": "아이언 바디",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"powerEffect": "blockPerTurn",
|
||||||
|
"value": 3,
|
||||||
|
"thorns": 2,
|
||||||
|
"desc": "매턴 방어도 3. 가시 2",
|
||||||
|
"image": "90a9bf8eeb844b578b4e2d93ac43fedf",
|
||||||
|
"class": "warrior",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"WarriorMastery": {
|
||||||
|
"name": "워리어 마스터리",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"strength": 1,
|
||||||
|
"dex": 1,
|
||||||
|
"desc": "힘 1. 민첩 1",
|
||||||
|
"image": "e2580523efc6457385114b78ad0d7cce",
|
||||||
|
"class": "warrior",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"Brandish": {
|
||||||
|
"name": "브랜디쉬",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Attack",
|
||||||
|
"damage": 4,
|
||||||
|
"hits": 2,
|
||||||
|
"damagePerCombo": 1,
|
||||||
|
"comboGain": 1,
|
||||||
|
"desc": "피해 4 x 2회. 콤보당 피해 +1. 콤보 1 획득",
|
||||||
|
"image": "1bc3e52b330648faae9eafd5a205e37b",
|
||||||
|
"class": "fighter",
|
||||||
|
"rarity": "normal"
|
||||||
|
},
|
||||||
|
"FlashSlash": {
|
||||||
|
"name": "플래시 슬래시",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Attack",
|
||||||
|
"damage": 2,
|
||||||
|
"hits": 5,
|
||||||
|
"aoe": true,
|
||||||
|
"block": 4,
|
||||||
|
"comboGain": 2,
|
||||||
|
"exhaust": true,
|
||||||
|
"desc": "모든 적에게 피해 2 x 5회. 방어도 4. 콤보 2 획득. 소멸.",
|
||||||
|
"image": "291b2298db88476f8ae3c6c78f53c9b7",
|
||||||
|
"class": "fighter",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"ComboAttack": {
|
||||||
|
"name": "콤보 어택",
|
||||||
|
"cost": 0,
|
||||||
|
"kind": "Power",
|
||||||
|
"comboOnAttack": 1,
|
||||||
|
"comboMax": 5,
|
||||||
|
"attackDamagePerCombo": 0.5,
|
||||||
|
"desc": "공격마다 콤보 1 획득. 모든 공격이 콤보 2당 피해 +1. 최대 5",
|
||||||
|
"image": "e2580523efc6457385114b78ad0d7cce",
|
||||||
|
"class": "fighter",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"SpiritBlade": {
|
||||||
|
"name": "스피릿 블레이드",
|
||||||
|
"cost": 2,
|
||||||
|
"kind": "Power",
|
||||||
|
"strength": 2,
|
||||||
|
"thorns": 5,
|
||||||
|
"desc": "힘 2. 가시 5",
|
||||||
|
"image": "863812c5c2f84132ac7465b50ec2283e",
|
||||||
|
"class": "fighter",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"WeaponMastery": {
|
||||||
|
"name": "웨폰 마스터리",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"strength": 1,
|
||||||
|
"attackPlayedDamage": 1,
|
||||||
|
"desc": "힘 1. 공격 카드를 사용할 때마다 대상에게 피해 1",
|
||||||
|
"image": "1bc3e52b330648faae9eafd5a205e37b",
|
||||||
|
"class": "fighter",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"WeaponAcceleration": {
|
||||||
|
"name": "웨폰 액셀레이션",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"turnStartDraw": 1,
|
||||||
|
"comboGain": 2,
|
||||||
|
"desc": "콤보 2 획득. 턴 시작 시 카드 1장 추가로 뽑기",
|
||||||
|
"image": "291b2298db88476f8ae3c6c78f53c9b7",
|
||||||
|
"class": "fighter",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"FinalAttack": {
|
||||||
|
"name": "파이널 어택",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"attackPlayedDamage": 3,
|
||||||
|
"desc": "공격 카드를 사용할 때마다 대상에게 피해 3",
|
||||||
|
"image": "997fa6999aa04dbb97a1dd99025fa2ba",
|
||||||
|
"class": "fighter",
|
||||||
|
"rarity": "legend"
|
||||||
|
},
|
||||||
|
"FighterPhysicalTraining": {
|
||||||
|
"name": "피지컬 트레이닝",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"strength": 1,
|
||||||
|
"dex": 1,
|
||||||
|
"powerEffect": "blockPerTurn",
|
||||||
|
"value": 2,
|
||||||
|
"desc": "힘 1. 민첩 1. 매턴 방어도 2",
|
||||||
|
"image": "90a9bf8eeb844b578b4e2d93ac43fedf",
|
||||||
|
"class": "fighter",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"BraveSlash": {
|
||||||
|
"name": "브레이브 슬래시",
|
||||||
|
"cost": 2,
|
||||||
|
"kind": "Attack",
|
||||||
|
"damage": 5,
|
||||||
|
"hits": 3,
|
||||||
|
"damagePerCombo": 1,
|
||||||
|
"comboGain": 1,
|
||||||
|
"desc": "피해 5 x 3회. 콤보당 피해 +1. 콤보 1 획득",
|
||||||
|
"image": "863812c5c2f84132ac7465b50ec2283e",
|
||||||
|
"class": "crusader",
|
||||||
|
"rarity": "normal"
|
||||||
|
},
|
||||||
|
"AuraBlade": {
|
||||||
|
"name": "오라 블레이드",
|
||||||
|
"cost": 2,
|
||||||
|
"kind": "Attack",
|
||||||
|
"damage": 4,
|
||||||
|
"hits": 4,
|
||||||
|
"aoe": true,
|
||||||
|
"pierce": true,
|
||||||
|
"exhaust": true,
|
||||||
|
"desc": "모든 적에게 방어도를 무시하고 피해 4 x 4회. 소멸.",
|
||||||
|
"image": "291b2298db88476f8ae3c6c78f53c9b7",
|
||||||
|
"class": "crusader",
|
||||||
|
"rarity": "legend"
|
||||||
|
},
|
||||||
|
"Rush": {
|
||||||
|
"name": "돌진",
|
||||||
|
"cost": 2,
|
||||||
|
"kind": "Attack",
|
||||||
|
"damage": 8,
|
||||||
|
"aoe": true,
|
||||||
|
"block": 7,
|
||||||
|
"comboGain": 1,
|
||||||
|
"desc": "모든 적에게 피해 8. 방어도 7. 콤보 1 획득",
|
||||||
|
"image": "997fa6999aa04dbb97a1dd99025fa2ba",
|
||||||
|
"class": "crusader",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"ScarringSword": {
|
||||||
|
"name": "스카링 소드",
|
||||||
|
"cost": 2,
|
||||||
|
"kind": "Power",
|
||||||
|
"attackWeak": 1,
|
||||||
|
"desc": "공격 카드로 피해를 주면 대상에게 약화 1",
|
||||||
|
"image": "1bc3e52b330648faae9eafd5a205e37b",
|
||||||
|
"class": "crusader",
|
||||||
|
"rarity": "legend"
|
||||||
|
},
|
||||||
|
"ComboSynergy": {
|
||||||
|
"name": "콤보 시너지",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"comboOnAttack": 1,
|
||||||
|
"comboMax": 5,
|
||||||
|
"comboGain": 2,
|
||||||
|
"attackDamagePerCombo": 0.5,
|
||||||
|
"desc": "콤보 2 획득. 공격마다 콤보 1 획득. 모든 공격이 콤보 2당 피해 +1. 최대 5",
|
||||||
|
"image": "e2580523efc6457385114b78ad0d7cce",
|
||||||
|
"class": "crusader",
|
||||||
|
"rarity": "legend"
|
||||||
|
},
|
||||||
|
"SelfRecovery": {
|
||||||
|
"name": "셀프 리커버리",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"powerEffect": "healPerTurn",
|
||||||
|
"value": 3,
|
||||||
|
"desc": "턴 시작 시 HP 3 회복",
|
||||||
|
"image": "90a9bf8eeb844b578b4e2d93ac43fedf",
|
||||||
|
"class": "crusader",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"ChanceAttack": {
|
||||||
|
"name": "찬스 어택",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"attackDamageVsWeakMultiplier": 1.5,
|
||||||
|
"comboGain": 2,
|
||||||
|
"desc": "콤보 2 획득. 약화 상태인 적에게 주는 공격 피해 1.5배",
|
||||||
|
"image": "291b2298db88476f8ae3c6c78f53c9b7",
|
||||||
|
"class": "crusader",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"Endure": {
|
||||||
|
"name": "인듀어",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"removePlayerDebuffs": true,
|
||||||
|
"powerEffect": "blockPerTurn",
|
||||||
|
"value": 4,
|
||||||
|
"desc": "약화와 취약을 제거합니다. 매턴 방어도 4",
|
||||||
|
"image": "90a9bf8eeb844b578b4e2d93ac43fedf",
|
||||||
|
"class": "crusader",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"DivineSwing": {
|
||||||
|
"name": "디바인 스윙",
|
||||||
|
"cost": 2,
|
||||||
|
"kind": "Attack",
|
||||||
|
"damage": 3,
|
||||||
|
"hits": 4,
|
||||||
|
"aoe": true,
|
||||||
|
"weak": 1,
|
||||||
|
"affectsAllEnemies": true,
|
||||||
|
"holyForce": true,
|
||||||
|
"desc": "모든 적에게 피해 3 x 4회, 약화 1. 홀리 포스.",
|
||||||
|
"image": "863812c5c2f84132ac7465b50ec2283e",
|
||||||
|
"class": "page",
|
||||||
|
"rarity": "normal"
|
||||||
|
},
|
||||||
|
"HolyCharge": {
|
||||||
|
"name": "홀리 차지",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"holyChargeOnHolyForce": 1,
|
||||||
|
"holyChargeMax": 3,
|
||||||
|
"damageTakenReduction": 0.1,
|
||||||
|
"desc": "홀리 포스 카드를 사용하면 홀리 차지 1 획득. 최대 3. 받는 피해 10% 감소",
|
||||||
|
"image": "e2580523efc6457385114b78ad0d7cce",
|
||||||
|
"class": "page",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"PageOrder": {
|
||||||
|
"name": "페이지 오더",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Attack",
|
||||||
|
"damage": 3,
|
||||||
|
"hits": 2,
|
||||||
|
"aoe": true,
|
||||||
|
"weak": 1,
|
||||||
|
"affectsAllEnemies": true,
|
||||||
|
"draw": 1,
|
||||||
|
"desc": "모든 적에게 피해 3 x 2회, 약화 1. 카드 1장 뽑기",
|
||||||
|
"image": "291b2298db88476f8ae3c6c78f53c9b7",
|
||||||
|
"class": "page",
|
||||||
|
"rarity": "normal"
|
||||||
|
},
|
||||||
|
"PageWeaponAcceleration": {
|
||||||
|
"name": "웨폰 액셀레이션",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"strength": 1,
|
||||||
|
"turnStartDraw": 1,
|
||||||
|
"desc": "힘 1. 턴 시작 시 카드 1장 추가로 뽑기",
|
||||||
|
"image": "291b2298db88476f8ae3c6c78f53c9b7",
|
||||||
|
"class": "page",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"PageStance": {
|
||||||
|
"name": "스탠스",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"powerEffect": "blockPerTurn",
|
||||||
|
"value": 3,
|
||||||
|
"desc": "매턴 방어도 3",
|
||||||
|
"image": "90a9bf8eeb844b578b4e2d93ac43fedf",
|
||||||
|
"class": "page",
|
||||||
|
"rarity": "normal"
|
||||||
|
},
|
||||||
|
"PageWeaponMastery": {
|
||||||
|
"name": "웨폰 마스터리",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"cardPlayedBlock": 1,
|
||||||
|
"desc": "카드를 사용할 때마다 방어도 1",
|
||||||
|
"image": "1bc3e52b330648faae9eafd5a205e37b",
|
||||||
|
"class": "page",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"PageFinalAttack": {
|
||||||
|
"name": "파이널 어택",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"attackPlayedDamage": 2,
|
||||||
|
"desc": "공격 카드를 사용할 때마다 대상에게 피해 2",
|
||||||
|
"image": "997fa6999aa04dbb97a1dd99025fa2ba",
|
||||||
|
"class": "page",
|
||||||
|
"rarity": "legend"
|
||||||
|
},
|
||||||
|
"PagePhysicalTraining": {
|
||||||
|
"name": "피지컬 트레이닝",
|
||||||
|
"cost": 2,
|
||||||
|
"kind": "Power",
|
||||||
|
"strength": 1,
|
||||||
|
"dex": 1,
|
||||||
|
"powerEffect": "blockPerTurn",
|
||||||
|
"value": 2,
|
||||||
|
"desc": "힘 1. 민첩 1. 매턴 방어도 2",
|
||||||
|
"image": "90a9bf8eeb844b578b4e2d93ac43fedf",
|
||||||
|
"class": "page",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"DivineCharge": {
|
||||||
|
"name": "디바인 차지",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Attack",
|
||||||
|
"damage": 3,
|
||||||
|
"hits": 4,
|
||||||
|
"aoe": true,
|
||||||
|
"weak": 1,
|
||||||
|
"affectsAllEnemies": true,
|
||||||
|
"holyForce": true,
|
||||||
|
"damagePerHolyCharge": 1,
|
||||||
|
"desc": "모든 적에게 피해 3 x 4회, 약화 1. 홀리 차지당 피해 +1. 홀리 포스.",
|
||||||
|
"image": "863812c5c2f84132ac7465b50ec2283e",
|
||||||
|
"class": "knight",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"Restoration": {
|
||||||
|
"name": "리스토네이션",
|
||||||
|
"cost": 0,
|
||||||
|
"kind": "Skill",
|
||||||
|
"heal": 6,
|
||||||
|
"healPerHolyCharge": 4,
|
||||||
|
"holyChargeSpendAll": true,
|
||||||
|
"desc": "HP 6 회복. 홀리 차지당 추가로 4 회복한 뒤 모두 소비",
|
||||||
|
"image": "90a9bf8eeb844b578b4e2d93ac43fedf",
|
||||||
|
"class": "knight",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"KnightRush": {
|
||||||
|
"name": "돌진",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Attack",
|
||||||
|
"damage": 7,
|
||||||
|
"aoe": true,
|
||||||
|
"block": 4,
|
||||||
|
"blockPerHolyCharge": 2,
|
||||||
|
"desc": "모든 적에게 피해 7. 방어도 4, 홀리 차지당 방어도 +2",
|
||||||
|
"image": "997fa6999aa04dbb97a1dd99025fa2ba",
|
||||||
|
"class": "knight",
|
||||||
|
"rarity": "normal"
|
||||||
|
},
|
||||||
|
"NobleDemand": {
|
||||||
|
"name": "노블 디맨드",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Skill",
|
||||||
|
"weak": 2,
|
||||||
|
"affectsAllEnemies": true,
|
||||||
|
"removeEnemyBlock": true,
|
||||||
|
"enemyStrengthLossThisTurn": 3,
|
||||||
|
"desc": "모든 적의 방어도를 제거하고 약화 2. 이번 턴 적 전체 힘 -3",
|
||||||
|
"image": "291b2298db88476f8ae3c6c78f53c9b7",
|
||||||
|
"class": "knight",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"ParashockGuard": {
|
||||||
|
"name": "파라쇼크 가드",
|
||||||
|
"cost": 3,
|
||||||
|
"kind": "Power",
|
||||||
|
"strength": 1,
|
||||||
|
"thorns": 3,
|
||||||
|
"cardPlayedBlock": 1,
|
||||||
|
"desc": "힘 1. 가시 3. 카드를 사용할 때마다 방어도 1",
|
||||||
|
"image": "90a9bf8eeb844b578b4e2d93ac43fedf",
|
||||||
|
"class": "knight",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"CombatOrders": {
|
||||||
|
"name": "컴뱃 오더스",
|
||||||
|
"cost": 1,
|
||||||
|
"kind": "Power",
|
||||||
|
"nextSkillRepeatCount": 1,
|
||||||
|
"turnStartDraw": 1,
|
||||||
|
"desc": "다음 스킬을 1회 추가 발동. 턴 시작 시 카드 1장 추가로 뽑기",
|
||||||
|
"image": "e2580523efc6457385114b78ad0d7cce",
|
||||||
|
"class": "knight",
|
||||||
|
"rarity": "legend"
|
||||||
|
},
|
||||||
|
"KnightShieldMastery": {
|
||||||
|
"name": "실드 마스터리",
|
||||||
|
"cost": 2,
|
||||||
|
"kind": "Power",
|
||||||
|
"powerEffect": "blockPerTurn",
|
||||||
|
"value": 4,
|
||||||
|
"thorns": 1,
|
||||||
|
"desc": "매턴 방어도 4. 가시 1",
|
||||||
|
"image": "90a9bf8eeb844b578b4e2d93ac43fedf",
|
||||||
|
"class": "knight",
|
||||||
|
"rarity": "unique"
|
||||||
|
},
|
||||||
|
"Achilles": {
|
||||||
|
"name": "아킬레스",
|
||||||
|
"cost": 2,
|
||||||
|
"kind": "Power",
|
||||||
|
"damageTakenReduction": 0.25,
|
||||||
|
"desc": "받는 피해 25% 감소",
|
||||||
|
"image": "90a9bf8eeb844b578b4e2d93ac43fedf",
|
||||||
|
"class": "knight",
|
||||||
|
"rarity": "legend"
|
||||||
|
},
|
||||||
|
"BlessingArmor": {
|
||||||
|
"name": "블레싱 아머",
|
||||||
|
"cost": 2,
|
||||||
|
"kind": "Power",
|
||||||
|
"blockOnDamaged": 6,
|
||||||
|
"strengthOnDamagedOnce": 2,
|
||||||
|
"desc": "HP 피해를 받으면 방어도 6. 전투 중 처음 발동할 때 힘 2",
|
||||||
|
"image": "e2580523efc6457385114b78ad0d7cce",
|
||||||
|
"class": "knight",
|
||||||
|
"rarity": "legend"
|
||||||
|
},
|
||||||
"EnergyBolt": {
|
"EnergyBolt": {
|
||||||
"name": "에너지 볼트",
|
"name": "에너지 볼트",
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
@@ -2542,11 +3002,11 @@
|
|||||||
"Strike",
|
"Strike",
|
||||||
"Strike",
|
"Strike",
|
||||||
"Strike",
|
"Strike",
|
||||||
"Strike",
|
"SlashBlast",
|
||||||
"Defend",
|
|
||||||
"Defend",
|
"Defend",
|
||||||
"Defend",
|
"Defend",
|
||||||
"Defend",
|
"Defend",
|
||||||
|
"IronBody",
|
||||||
"Bash"
|
"Bash"
|
||||||
],
|
],
|
||||||
"magician": [
|
"magician": [
|
||||||
|
|||||||
BIN
data/cards.xlsx
BIN
data/cards.xlsx
Binary file not shown.
@@ -14,6 +14,10 @@ The goal is to keep card behavior reusable instead of hardcoding one-off card na
|
|||||||
- `damagePerDiscardedThisTurn`: bonus damage per card discarded this turn
|
- `damagePerDiscardedThisTurn`: bonus damage per card discarded this turn
|
||||||
- `damagePerSkillInHand`: bonus damage per skill card in hand
|
- `damagePerSkillInHand`: bonus damage per skill card in hand
|
||||||
- `damagePerCardDrawnThisCombat`: bonus damage per card drawn this combat
|
- `damagePerCardDrawnThisCombat`: bonus damage per card drawn this combat
|
||||||
|
- `damagePerCombo`: bonus base damage per current Combo
|
||||||
|
- `damagePerHolyCharge`: bonus base damage per current Holy Charge
|
||||||
|
- `attackDamagePerCombo`: Power field that adds base damage per current Combo to all Attacks
|
||||||
|
- `attackPlayedDamage`: Power field that deals extra damage after an Attack card is played
|
||||||
- `damagePerTurn`: damage applied at turn start
|
- `damagePerTurn`: damage applied at turn start
|
||||||
- `cardPlayedDamage`: damage when the card is played
|
- `cardPlayedDamage`: damage when the card is played
|
||||||
- `cardPlayedRandomDamage`: random damage when the card is played
|
- `cardPlayedRandomDamage`: random damage when the card is played
|
||||||
@@ -65,6 +69,21 @@ The goal is to keep card behavior reusable instead of hardcoding one-off card na
|
|||||||
- `thorns`: gain Thorns
|
- `thorns`: gain Thorns
|
||||||
- `selfVuln`: apply Vulnerable to self
|
- `selfVuln`: apply Vulnerable to self
|
||||||
- `extraPoisonTicks`: add extra poison ticks at enemy turn start
|
- `extraPoisonTicks`: add extra poison ticks at enemy turn start
|
||||||
|
- `comboGain`: gain Combo when the card resolves; Attack cards gain it after dealing damage
|
||||||
|
- `comboOnAttack`: Power field that gains Combo whenever an Attack card is played
|
||||||
|
- `comboMax`: Power field that raises the maximum Combo above the default 5
|
||||||
|
- `attackWeak`: Power field that applies Weak after an Attack card is played
|
||||||
|
- `removePlayerDebuffs`: remove player Weak and Vulnerable
|
||||||
|
- `holyForce`: marks a card as Holy Force for Holy Charge Power triggers
|
||||||
|
- `holyChargeGain`: gain Holy Charge directly
|
||||||
|
- `holyChargeOnHolyForce`: Power field that gains Holy Charge after a Holy Force card
|
||||||
|
- `holyChargeMax`: Power field that raises the maximum Holy Charge above the default 3
|
||||||
|
- `blockPerHolyCharge`: gain additional block per current Holy Charge
|
||||||
|
- `healPerHolyCharge`: heal additional HP per current Holy Charge
|
||||||
|
- `holyChargeSpendAll`: consume all Holy Charge after resolving the card
|
||||||
|
- `damageTakenReduction`: Power field that reduces incoming damage; total reduction is capped at 75%
|
||||||
|
- `blockOnDamaged`: Power field that grants block after taking HP damage
|
||||||
|
- `strengthOnDamagedOnce`: Power field that grants Strength on the first HP damage each combat
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
@@ -108,6 +127,7 @@ The goal is to keep card behavior reusable instead of hardcoding one-off card na
|
|||||||
- `powerEffect: "blockPerTurn"`
|
- `powerEffect: "blockPerTurn"`
|
||||||
- `powerEffect: "poisonPerTurn"`
|
- `powerEffect: "poisonPerTurn"`
|
||||||
- `powerEffect: "damagePerTurn"`
|
- `powerEffect: "damagePerTurn"`
|
||||||
|
- `powerEffect: "healPerTurn"`
|
||||||
- `powerEffect: "retainOne"`
|
- `powerEffect: "retainOne"`
|
||||||
- `powerEffect: "keepBlock"`
|
- `powerEffect: "keepBlock"`
|
||||||
- `turnStartShiv`: create Shivs at turn start
|
- `turnStartShiv`: create Shivs at turn start
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ import {
|
|||||||
simulateCombat,
|
simulateCombat,
|
||||||
} from './sim-balance.mjs';
|
} from './sim-balance.mjs';
|
||||||
|
|
||||||
const ROGUE_CLASSES = new Set(['rogue', 'thief', 'thiefmaster', 'assassin', 'hermit']);
|
const AUDITED_CLASSES = new Set([
|
||||||
|
'rogue', 'thief', 'thiefmaster', 'assassin', 'hermit',
|
||||||
|
'warrior', 'fighter', 'crusader', 'page', 'knight',
|
||||||
|
]);
|
||||||
|
|
||||||
const CONTEXT_DECKS = {
|
const CONTEXT_DECKS = {
|
||||||
rogue: [
|
rogue: [
|
||||||
@@ -38,6 +41,27 @@ const CONTEXT_DECKS = {
|
|||||||
'Survivor', 'LeadingStrike', 'BladeDance', 'JavelinAcceleration',
|
'Survivor', 'LeadingStrike', 'BladeDance', 'JavelinAcceleration',
|
||||||
'JavelinMastery', 'TripleThrow', 'SpiritJavelin', 'SkilledJavelin',
|
'JavelinMastery', 'TripleThrow', 'SpiritJavelin', 'SkilledJavelin',
|
||||||
],
|
],
|
||||||
|
warrior: [
|
||||||
|
'Strike', 'Strike', 'Strike', 'Strike',
|
||||||
|
'Defend', 'Defend', 'Defend', 'Defend',
|
||||||
|
'Bash', 'SlashBlast', 'IronBody', 'WarriorMastery',
|
||||||
|
],
|
||||||
|
fighter: [
|
||||||
|
'Strike', 'Strike', 'Strike', 'Defend', 'Defend', 'Defend',
|
||||||
|
'Bash', 'SlashBlast', 'ComboAttack', 'Brandish', 'WeaponMastery', 'FlashSlash',
|
||||||
|
],
|
||||||
|
crusader: [
|
||||||
|
'Strike', 'Strike', 'Defend', 'Defend', 'Bash', 'SlashBlast',
|
||||||
|
'ComboAttack', 'Brandish', 'WeaponMastery', 'BraveSlash', 'ComboSynergy', 'Rush',
|
||||||
|
],
|
||||||
|
page: [
|
||||||
|
'Strike', 'Strike', 'Strike', 'Defend', 'Defend', 'Defend',
|
||||||
|
'Bash', 'SlashBlast', 'HolyCharge', 'DivineSwing', 'PageOrder', 'PageStance',
|
||||||
|
],
|
||||||
|
knight: [
|
||||||
|
'Strike', 'Strike', 'Defend', 'Defend', 'Bash', 'SlashBlast',
|
||||||
|
'HolyCharge', 'DivineSwing', 'PageOrder', 'DivineCharge', 'KnightRush', 'Restoration',
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const ENCOUNTER_SCALE = {
|
const ENCOUNTER_SCALE = {
|
||||||
@@ -46,6 +70,11 @@ const ENCOUNTER_SCALE = {
|
|||||||
assassin: { hp: 2.25, attack: 1.65 },
|
assassin: { hp: 2.25, attack: 1.65 },
|
||||||
thiefmaster: { hp: 2.4, attack: 1.5 },
|
thiefmaster: { hp: 2.4, attack: 1.5 },
|
||||||
hermit: { hp: 2.6, attack: 1.65 },
|
hermit: { hp: 2.6, attack: 1.65 },
|
||||||
|
warrior: { hp: 1.9, attack: 1.5 },
|
||||||
|
fighter: { hp: 2.2, attack: 1.6 },
|
||||||
|
crusader: { hp: 2.6, attack: 1.7 },
|
||||||
|
page: { hp: 2.2, attack: 1.6 },
|
||||||
|
knight: { hp: 2.6, attack: 1.7 },
|
||||||
};
|
};
|
||||||
|
|
||||||
const median = (values) => {
|
const median = (values) => {
|
||||||
@@ -172,7 +201,7 @@ export function auditCardEfficiency({ runs = 300, seed = 20260701 } = {}) {
|
|||||||
|
|
||||||
const rows = [];
|
const rows = [];
|
||||||
for (const [id, card] of Object.entries(cards)) {
|
for (const [id, card] of Object.entries(cards)) {
|
||||||
if (!ROGUE_CLASSES.has(card.class)) continue;
|
if (!AUDITED_CLASSES.has(card.class)) continue;
|
||||||
const deck = CONTEXT_DECKS[card.class].slice();
|
const deck = CONTEXT_DECKS[card.class].slice();
|
||||||
deck[replacementIndex(deck, cards, card)] = id;
|
deck[replacementIndex(deck, cards, card)] = id;
|
||||||
const result = simulateDeck(scaledEncounter(data, card.class), deck, runs, seed, id);
|
const result = simulateDeck(scaledEncounter(data, card.class), deck, runs, seed, id);
|
||||||
@@ -204,7 +233,7 @@ function formatPercent(value) {
|
|||||||
|
|
||||||
export function formatEfficiencyReport(report) {
|
export function formatEfficiencyReport(report) {
|
||||||
const lines = [];
|
const lines = [];
|
||||||
lines.push(`도적 카드 효율 검증: 카드 ${report.rows.length}장, 카드당 ${report.runs}회`);
|
lines.push(`카드 효율 검증: 카드 ${report.rows.length}장, 카드당 ${report.runs}회`);
|
||||||
lines.push('기준 덱:');
|
lines.push('기준 덱:');
|
||||||
for (const [classId, baseline] of Object.entries(report.baselines)) {
|
for (const [classId, baseline] of Object.entries(report.baselines)) {
|
||||||
lines.push(` ${classId}: 승률 ${formatPercent(baseline.winRate)}, 평균 ${baseline.avgTurns.toFixed(2)}턴, 승리 HP ${baseline.avgHpOnWin.toFixed(1)}`);
|
lines.push(` ${classId}: 승률 ${formatPercent(baseline.winRate)}, 평균 ${baseline.avgTurns.toFixed(2)}턴, 승리 HP ${baseline.avgHpOnWin.toFixed(1)}`);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const cardsData = JSON.parse(readFileSync('data/cards.json', 'utf8'));
|
|||||||
const enemiesData = JSON.parse(readFileSync('data/enemies.json', 'utf8'));
|
const enemiesData = JSON.parse(readFileSync('data/enemies.json', 'utf8'));
|
||||||
const relicsData = JSON.parse(readFileSync('data/relics.json', 'utf8'));
|
const relicsData = JSON.parse(readFileSync('data/relics.json', 'utf8'));
|
||||||
|
|
||||||
const PLAYER_MAX_HP = 70;
|
const PLAYER_MAX_HP = { rogue: 70, warrior: 80 };
|
||||||
const REST_HEAL = 30;
|
const REST_HEAL = 30;
|
||||||
const SECTION_COUNT = 5;
|
const SECTION_COUNT = 5;
|
||||||
const NORMAL_FIGHTS = 4;
|
const NORMAL_FIGHTS = 4;
|
||||||
@@ -18,6 +18,8 @@ const BOSS_POOL = ['king_slime', 'slime_boss'];
|
|||||||
const JOBS = {
|
const JOBS = {
|
||||||
thief: { tier2: 'thief', tier3: 'thiefmaster', tier2Starter: 'DaggerAcceleration', tier3Starter: 'Venom' },
|
thief: { tier2: 'thief', tier3: 'thiefmaster', tier2Starter: 'DaggerAcceleration', tier3Starter: 'Venom' },
|
||||||
assassin: { tier2: 'assassin', tier3: 'hermit', tier2Starter: 'JavelinAcceleration', tier3Starter: 'SpiritJavelin' },
|
assassin: { tier2: 'assassin', tier3: 'hermit', tier2Starter: 'JavelinAcceleration', tier3Starter: 'SpiritJavelin' },
|
||||||
|
fighter: { root: 'warrior', tier2: 'fighter', tier3: 'crusader', tier2Starter: 'ComboAttack', tier3Starter: 'ComboSynergy' },
|
||||||
|
page: { root: 'warrior', tier2: 'page', tier3: 'knight', tier2Starter: 'HolyCharge', tier3Starter: 'DivineCharge' },
|
||||||
};
|
};
|
||||||
|
|
||||||
const LINEAGES = {
|
const LINEAGES = {
|
||||||
@@ -26,12 +28,17 @@ const LINEAGES = {
|
|||||||
thiefmaster: ['rogue', 'thief', 'thiefmaster'],
|
thiefmaster: ['rogue', 'thief', 'thiefmaster'],
|
||||||
assassin: ['rogue', 'assassin'],
|
assassin: ['rogue', 'assassin'],
|
||||||
hermit: ['rogue', 'assassin', 'hermit'],
|
hermit: ['rogue', 'assassin', 'hermit'],
|
||||||
|
warrior: ['warrior'],
|
||||||
|
fighter: ['warrior', 'fighter'],
|
||||||
|
crusader: ['warrior', 'fighter', 'crusader'],
|
||||||
|
page: ['warrior', 'page'],
|
||||||
|
knight: ['warrior', 'page', 'knight'],
|
||||||
};
|
};
|
||||||
|
|
||||||
const pick = (rng, values) => values[Math.floor(rng() * values.length)];
|
const pick = (rng, values) => values[Math.floor(rng() * values.length)];
|
||||||
|
|
||||||
export function campaignJobAtSection(branch, section) {
|
export function campaignJobAtSection(branch, section) {
|
||||||
if (section <= 1) return 'rogue';
|
if (section <= 1) return JOBS[branch].root || 'rogue';
|
||||||
if (section === 2) return JOBS[branch].tier2;
|
if (section === 2) return JOBS[branch].tier2;
|
||||||
return JOBS[branch].tier3;
|
return JOBS[branch].tier3;
|
||||||
}
|
}
|
||||||
@@ -102,11 +109,22 @@ function branchCardValue(card, branch, deck, id) {
|
|||||||
value += card.sly ? 5 : 0;
|
value += card.sly ? 5 : 0;
|
||||||
value += (card.discard || 0) * 2 + (card.drawPerDiscarded || 0) * 4;
|
value += (card.discard || 0) * 2 + (card.drawPerDiscarded || 0) * 4;
|
||||||
value += (card.poisonApplicationBurstDamage || 0) * 1.5;
|
value += (card.poisonApplicationBurstDamage || 0) * 1.5;
|
||||||
} else {
|
} else if (branch === 'assassin') {
|
||||||
value += (card.addShiv || 0) * 3 + (card.turnStartShiv || 0) * 8;
|
value += (card.addShiv || 0) * 3 + (card.turnStartShiv || 0) * 8;
|
||||||
value += (card.shivDamageBonus || 0) * 6 + (card.firstShivDamageBonus || 0) * 3;
|
value += (card.shivDamageBonus || 0) * 6 + (card.firstShivDamageBonus || 0) * 3;
|
||||||
value += card.shivAoe ? 12 : 0;
|
value += card.shivAoe ? 12 : 0;
|
||||||
value += card.shivRetain ? 5 : 0;
|
value += card.shivRetain ? 5 : 0;
|
||||||
|
} else if (branch === 'fighter') {
|
||||||
|
value += (card.hits || 1) * 1.5;
|
||||||
|
value += (card.comboGain || 0) * 5 + (card.comboOnAttack || 0) * 10;
|
||||||
|
value += (card.damagePerCombo || 0) * 8 + (card.attackDamagePerCombo || 0) * 12;
|
||||||
|
value += (card.attackPlayedDamage || 0) * 5;
|
||||||
|
} else if (branch === 'page') {
|
||||||
|
value += (card.block || 0) * 0.5 + (card.cardPlayedBlock || 0) * 7;
|
||||||
|
value += (card.holyChargeOnHolyForce || 0) * 12 + (card.damagePerHolyCharge || 0) * 7;
|
||||||
|
value += (card.blockPerHolyCharge || 0) * 6 + (card.healPerHolyCharge || 0) * 3;
|
||||||
|
value += (card.damageTakenReduction || 0) * 40;
|
||||||
|
value += (card.blockOnDamaged || 0) * 3 + (card.strengthOnDamagedOnce || 0) * 5;
|
||||||
}
|
}
|
||||||
const copies = deck.filter((cardId) => cardId === id).length;
|
const copies = deck.filter((cardId) => cardId === id).length;
|
||||||
value -= copies * (card.kind === 'Power' ? 10 : 3);
|
value -= copies * (card.kind === 'Power' ? 10 : 3);
|
||||||
@@ -203,11 +221,13 @@ export function simulateCampaign(branch, rng, {
|
|||||||
minimumRewardValue = 10,
|
minimumRewardValue = 10,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
if (!JOBS[branch]) throw new Error(`지원하지 않는 도적 분기: ${branch}`);
|
if (!JOBS[branch]) throw new Error(`지원하지 않는 도적 분기: ${branch}`);
|
||||||
|
const root = JOBS[branch].root || 'rogue';
|
||||||
|
const maxHp = PLAYER_MAX_HP[root];
|
||||||
const state = {
|
const state = {
|
||||||
hp: PLAYER_MAX_HP,
|
hp: maxHp,
|
||||||
maxHp: PLAYER_MAX_HP,
|
maxHp,
|
||||||
deck: cardsData.starterDecks.rogue.slice(),
|
deck: cardsData.starterDecks[root].slice(),
|
||||||
job: 'rogue',
|
job: root,
|
||||||
turns: 0,
|
turns: 0,
|
||||||
sectionCleared: 0,
|
sectionCleared: 0,
|
||||||
diedAt: '',
|
diedAt: '',
|
||||||
@@ -306,7 +326,7 @@ function main() {
|
|||||||
else if (args[i] === '--scale-step') scaleStep = Number.parseFloat(args[++i]);
|
else if (args[i] === '--scale-step') scaleStep = Number.parseFloat(args[++i]);
|
||||||
else if (args[i] === '--reward-min') minimumRewardValue = Number.parseFloat(args[++i]);
|
else if (args[i] === '--reward-min') minimumRewardValue = Number.parseFloat(args[++i]);
|
||||||
}
|
}
|
||||||
for (const branch of ['thief', 'assassin']) {
|
for (const branch of ['thief', 'assassin', 'fighter', 'page']) {
|
||||||
console.log(formatCampaignReport(runCampaignBatch(branch, runs, seed, { restHeal, sectionHeal, scaleStep, minimumRewardValue })));
|
console.log(formatCampaignReport(runCampaignBatch(branch, runs, seed, { restHeal, sectionHeal, scaleStep, minimumRewardValue })));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,16 @@ test('도적 전직 시점: 1섹션 Rogue, 2섹션 2차, 3섹션부터 3차', ()
|
|||||||
test('3차 직업은 자기 계보 카드만 사용', () => {
|
test('3차 직업은 자기 계보 카드만 사용', () => {
|
||||||
assert.deepEqual(playableClassesForJob('thiefmaster'), ['rogue', 'thief', 'thiefmaster']);
|
assert.deepEqual(playableClassesForJob('thiefmaster'), ['rogue', 'thief', 'thiefmaster']);
|
||||||
assert.deepEqual(playableClassesForJob('hermit'), ['rogue', 'assassin', 'hermit']);
|
assert.deepEqual(playableClassesForJob('hermit'), ['rogue', 'assassin', 'hermit']);
|
||||||
|
assert.deepEqual(playableClassesForJob('crusader'), ['warrior', 'fighter', 'crusader']);
|
||||||
|
assert.deepEqual(playableClassesForJob('knight'), ['warrior', 'page', 'knight']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('전사 전직 시점: 1섹션 Warrior, 2섹션 2차, 3섹션부터 3차', () => {
|
||||||
|
assert.equal(campaignJobAtSection('fighter', 1), 'warrior');
|
||||||
|
assert.equal(campaignJobAtSection('fighter', 2), 'fighter');
|
||||||
|
assert.equal(campaignJobAtSection('fighter', 3), 'crusader');
|
||||||
|
assert.equal(campaignJobAtSection('page', 2), 'page');
|
||||||
|
assert.equal(campaignJobAtSection('page', 5), 'knight');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('섹션 난이도는 3차 이후 더 빠르게 증가', () => {
|
test('섹션 난이도는 3차 이후 더 빠르게 증가', () => {
|
||||||
|
|||||||
@@ -246,6 +246,9 @@ export function simulateCombat(data, rng, stats) {
|
|||||||
let cardsDrawnThisCombat = 0;
|
let cardsDrawnThisCombat = 0;
|
||||||
let bonusRewardScreens = 0;
|
let bonusRewardScreens = 0;
|
||||||
let activeKillReward = 0;
|
let activeKillReward = 0;
|
||||||
|
let comboCount = 0;
|
||||||
|
let holyChargeCount = 0;
|
||||||
|
let damagePowerStrengthUsed = false;
|
||||||
let energy = 0;
|
let energy = 0;
|
||||||
const powers = [];
|
const powers = [];
|
||||||
const mob = monsters.map((m) => ({
|
const mob = monsters.map((m) => ({
|
||||||
@@ -467,6 +470,9 @@ export function simulateCombat(data, rng, stats) {
|
|||||||
base += countOwnedNameMatches(c.damageNameMatch) * c.damagePerOwnedNameMatch;
|
base += countOwnedNameMatches(c.damageNameMatch) * c.damagePerOwnedNameMatch;
|
||||||
}
|
}
|
||||||
if (c.damageFromCurrentBlock) base += pBlock * c.damageFromCurrentBlock;
|
if (c.damageFromCurrentBlock) base += pBlock * c.damageFromCurrentBlock;
|
||||||
|
const comboScale = (c.damagePerCombo || 0) + powerFieldTotal('attackDamagePerCombo');
|
||||||
|
if (comboScale) base += comboCount * comboScale;
|
||||||
|
if (c.damagePerHolyCharge) base += holyChargeCount * c.damagePerHolyCharge;
|
||||||
const otherHand = Math.max(0, hand.length - 1);
|
const otherHand = Math.max(0, hand.length - 1);
|
||||||
if (c.damagePerOtherHandCard) base += otherHand * c.damagePerOtherHandCard;
|
if (c.damagePerOtherHandCard) base += otherHand * c.damagePerOtherHandCard;
|
||||||
if (c.damagePerAttackPlayedThisTurn) base += turnAttackCardsPlayed * c.damagePerAttackPlayedThisTurn;
|
if (c.damagePerAttackPlayedThisTurn) base += turnAttackCardsPlayed * c.damagePerAttackPlayedThisTurn;
|
||||||
@@ -518,6 +524,23 @@ export function simulateCombat(data, rng, stats) {
|
|||||||
}
|
}
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
function powerFieldMax(field) {
|
||||||
|
let best = 0;
|
||||||
|
for (const pid of powers) best = Math.max(best, cards[pid]?.[field] || 0);
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
function comboMax() {
|
||||||
|
return Math.max(5, powerFieldMax('comboMax'));
|
||||||
|
}
|
||||||
|
function gainCombo(amount) {
|
||||||
|
if (amount > 0) comboCount = Math.min(comboMax(), comboCount + amount);
|
||||||
|
}
|
||||||
|
function holyChargeMax() {
|
||||||
|
return Math.max(3, powerFieldMax('holyChargeMax'));
|
||||||
|
}
|
||||||
|
function gainHolyCharge(amount) {
|
||||||
|
if (amount > 0) holyChargeCount = Math.min(holyChargeMax(), holyChargeCount + amount);
|
||||||
|
}
|
||||||
function triggerExhaust(count = 1) {
|
function triggerExhaust(count = 1) {
|
||||||
const drawOnExhaust = powerFieldTotal('drawOnExhaust');
|
const drawOnExhaust = powerFieldTotal('drawOnExhaust');
|
||||||
if (drawOnExhaust > 0 && count > 0) draw(drawOnExhaust * count);
|
if (drawOnExhaust > 0 && count > 0) draw(drawOnExhaust * count);
|
||||||
@@ -607,8 +630,9 @@ export function simulateCombat(data, rng, stats) {
|
|||||||
if (!target || !target.alive) return { killed: false, dealt: 0 };
|
if (!target || !target.alive) return { killed: false, dealt: 0 };
|
||||||
let dealt = amount;
|
let dealt = amount;
|
||||||
if (target.vuln > 0) dealt = Math.floor(dealt * 1.5);
|
if (target.vuln > 0) dealt = Math.floor(dealt * 1.5);
|
||||||
if (target.weak > 0 && c.attackDamageVsWeakMultiplier && c.attackDamageVsWeakMultiplier > 1) {
|
const weakMultiplier = Math.max(c.attackDamageVsWeakMultiplier || 1, powerFieldMax('attackDamageVsWeakMultiplier'));
|
||||||
dealt = Math.floor(dealt * c.attackDamageVsWeakMultiplier);
|
if (target.weak > 0 && weakMultiplier > 1) {
|
||||||
|
dealt = Math.floor(dealt * weakMultiplier);
|
||||||
}
|
}
|
||||||
if (c.pierce === true) {
|
if (c.pierce === true) {
|
||||||
target.hp -= dealt;
|
target.hp -= dealt;
|
||||||
@@ -669,11 +693,11 @@ export function simulateCombat(data, rng, stats) {
|
|||||||
roundKilled = resolveAttackRound();
|
roundKilled = resolveAttackRound();
|
||||||
} while (c.repeatOnKill === true && roundKilled === true && countAliveMonsters() > 0);
|
} while (c.repeatOnKill === true && roundKilled === true && countAliveMonsters() > 0);
|
||||||
}
|
}
|
||||||
if (c.block) blockGained = addBlock(c.block);
|
if (c.block) blockGained = addBlock(c.block + holyChargeCount * (c.blockPerHolyCharge || 0));
|
||||||
} else if (c.kind === 'Power') {
|
} else if (c.kind === 'Power') {
|
||||||
powers.push(id);
|
powers.push(id);
|
||||||
} else {
|
} else {
|
||||||
if (c.block) blockGained = addBlock(c.block);
|
if (c.block) blockGained = addBlock(c.block + holyChargeCount * (c.blockPerHolyCharge || 0));
|
||||||
const weakAmount = (c.weak || 0) + (c.xWeakPerEnergy || 0) * xEnergy;
|
const weakAmount = (c.weak || 0) + (c.xWeakPerEnergy || 0) * xEnergy;
|
||||||
const vulnAmount = c.vuln || 0;
|
const vulnAmount = c.vuln || 0;
|
||||||
if ((weakAmount || vulnAmount || c.poison || c.removeEnemyBlock || c.removeEnemyArtifact || c.enemyStrengthLossThisTurn) && alive.length) {
|
if ((weakAmount || vulnAmount || c.poison || c.removeEnemyBlock || c.removeEnemyArtifact || c.enemyStrengthLossThisTurn) && alive.length) {
|
||||||
@@ -705,8 +729,10 @@ export function simulateCombat(data, rng, stats) {
|
|||||||
if (c.dex) pDex += c.dex;
|
if (c.dex) pDex += c.dex;
|
||||||
if (c.thorns) pThorns += c.thorns;
|
if (c.thorns) pThorns += c.thorns;
|
||||||
if (c.selfVuln) pVuln += c.selfVuln;
|
if (c.selfVuln) pVuln += c.selfVuln;
|
||||||
if (c.heal) pHp = Math.min(pHp + c.heal, playerMaxHp);
|
if (c.heal) pHp = Math.min(pHp + c.heal + holyChargeCount * (c.healPerHolyCharge || 0), playerMaxHp);
|
||||||
if (c.gainEnergy) energy += c.gainEnergy;
|
if (c.gainEnergy) energy += c.gainEnergy;
|
||||||
|
if (c.kind !== 'Attack' && c.comboGain) gainCombo(c.comboGain);
|
||||||
|
if (c.removePlayerDebuffs === true) { pWeak = 0; pVuln = 0; }
|
||||||
activeKillReward = c.rewardOnKill || 0;
|
activeKillReward = c.rewardOnKill || 0;
|
||||||
if (c.intangible) pIntangible += c.intangible;
|
if (c.intangible) pIntangible += c.intangible;
|
||||||
queueNextTurnEffects(c);
|
queueNextTurnEffects(c);
|
||||||
@@ -766,6 +792,28 @@ export function simulateCombat(data, rng, stats) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (c.kind === 'Attack') {
|
||||||
|
gainCombo((c.comboGain || 0) + powerFieldTotal('comboOnAttack'));
|
||||||
|
const extraDamage = powerFieldTotal('attackPlayedDamage');
|
||||||
|
if (extraDamage > 0) {
|
||||||
|
const target = chooseTarget(aliveList(), extraDamage);
|
||||||
|
if (target) {
|
||||||
|
const r = applyDamage(target.hp, target.block, extraDamage);
|
||||||
|
target.hp = r.hp; target.block = r.block;
|
||||||
|
damageDealtThisTurn += extraDamage;
|
||||||
|
if (target.hp <= 0) target.alive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const attackWeak = powerFieldTotal('attackWeak');
|
||||||
|
if (attackWeak > 0) {
|
||||||
|
const target = chooseTarget(aliveList(), 0);
|
||||||
|
if (target) applyMonsterWeak(target, attackWeak);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let holyGain = c.holyChargeGain || 0;
|
||||||
|
if (c.holyForce === true) holyGain += powerFieldTotal('holyChargeOnHolyForce');
|
||||||
|
gainHolyCharge(holyGain);
|
||||||
|
if (c.holyChargeSpendAll === true) holyChargeCount = 0;
|
||||||
if (c.blockPerDamageDealtThisTurn && c.blockPerDamageDealtThisTurn > 0 && c.kind !== 'Power') {
|
if (c.blockPerDamageDealtThisTurn && c.blockPerDamageDealtThisTurn > 0 && c.kind !== 'Power') {
|
||||||
blockGained += addBlock(Math.max(0, damageDealtThisTurn * c.blockPerDamageDealtThisTurn));
|
blockGained += addBlock(Math.max(0, damageDealtThisTurn * c.blockPerDamageDealtThisTurn));
|
||||||
}
|
}
|
||||||
@@ -878,6 +926,8 @@ export function simulateCombat(data, rng, stats) {
|
|||||||
m.hp = r.hp; m.block = r.block;
|
m.hp = r.hp; m.block = r.block;
|
||||||
if (m.hp <= 0) m.alive = false;
|
if (m.hp <= 0) m.alive = false;
|
||||||
}
|
}
|
||||||
|
} else if (pc.powerEffect === 'healPerTurn') {
|
||||||
|
pHp = Math.min(playerMaxHp, pHp + (pc.value || 0));
|
||||||
}
|
}
|
||||||
if (pc.turnStartShiv) addCardsToHand('Shiv', pc.turnStartShiv);
|
if (pc.turnStartShiv) addCardsToHand('Shiv', pc.turnStartShiv);
|
||||||
if (pc.turnStartDraw) powerTurnDraw += pc.turnStartDraw;
|
if (pc.turnStartDraw) powerTurnDraw += pc.turnStartDraw;
|
||||||
@@ -991,8 +1041,18 @@ export function simulateCombat(data, rng, stats) {
|
|||||||
const atk = calcEnemyAttack(it.value, m.str, m.weak, pVuln, enemyStrengthLossThisTurn);
|
const atk = calcEnemyAttack(it.value, m.str, m.weak, pVuln, enemyStrengthLossThisTurn);
|
||||||
const beforeHp = pHp;
|
const beforeHp = pHp;
|
||||||
let incoming = atk;
|
let incoming = atk;
|
||||||
|
const reduction = Math.min(0.75, powerFieldTotal('damageTakenReduction'));
|
||||||
|
if (reduction > 0) incoming = Math.floor(incoming * (1 - reduction));
|
||||||
if (pIntangible > 0 && incoming > 1) incoming = 1;
|
if (pIntangible > 0 && incoming > 1) incoming = 1;
|
||||||
const r = applyDamage(pHp, pBlock, incoming); pHp = r.hp; pBlock = r.block;
|
const r = applyDamage(pHp, pBlock, incoming); pHp = r.hp; pBlock = r.block;
|
||||||
|
if (beforeHp > pHp) {
|
||||||
|
const reactiveBlock = powerFieldTotal('blockOnDamaged');
|
||||||
|
if (reactiveBlock > 0) addBlock(reactiveBlock);
|
||||||
|
if (!damagePowerStrengthUsed) {
|
||||||
|
const reactiveStrength = powerFieldTotal('strengthOnDamagedOnce');
|
||||||
|
if (reactiveStrength > 0) { pStr += reactiveStrength; damagePowerStrengthUsed = true; }
|
||||||
|
}
|
||||||
|
}
|
||||||
if (beforeHp > pHp && pThorns > 0) {
|
if (beforeHp > pHp && pThorns > 0) {
|
||||||
m.hp -= pThorns;
|
m.hp -= pThorns;
|
||||||
if (m.hp <= 0) m.alive = false;
|
if (m.hp <= 0) m.alive = false;
|
||||||
|
|||||||
@@ -1391,3 +1391,102 @@ test("simulateCombat: shivAoe makes Shivs hit all enemies", () => {
|
|||||||
assert.equal(r.win, true);
|
assert.equal(r.win, true);
|
||||||
assert.equal(r.turns, 1);
|
assert.equal(r.turns, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("simulateCombat: comboGain and damagePerCombo scale repeated attacks", () => {
|
||||||
|
const data = {
|
||||||
|
cards: {
|
||||||
|
Brandish: { name: "브랜디쉬", cost: 1, kind: "Attack", damage: 2, hits: 2, comboGain: 1, damagePerCombo: 1 },
|
||||||
|
},
|
||||||
|
starterDeck: ["Brandish"],
|
||||||
|
monsters: [{ name: "Dummy", maxHp: 14, intents: [{ kind: "Attack", value: 0 }] }],
|
||||||
|
};
|
||||||
|
const stats = {};
|
||||||
|
const r = simulateCombat(data, () => 0.999999, stats);
|
||||||
|
assert.equal(r.win, true);
|
||||||
|
assert.ok(stats.Brandish.damage > stats.Brandish.plays * 4);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("simulateCombat: comboMax power raises the combo cap", () => {
|
||||||
|
const data = {
|
||||||
|
cards: {
|
||||||
|
ComboSynergy: { name: "콤보 시너지", cost: 0, kind: "Power", comboMax: 8, comboOnAttack: 2, attackDamagePerCombo: 1, innate: true },
|
||||||
|
Hit: { name: "연속 베기", cost: 0, kind: "Attack", damage: 1 },
|
||||||
|
},
|
||||||
|
starterDeck: ["ComboSynergy", "Hit"],
|
||||||
|
monsters: [{ name: "Dummy", maxHp: 40, intents: [{ kind: "Attack", value: 0 }] }],
|
||||||
|
};
|
||||||
|
const stats = {};
|
||||||
|
const r = simulateCombat(data, () => 0.999999, stats);
|
||||||
|
assert.equal(r.win, true);
|
||||||
|
assert.ok(stats.Hit.damage > stats.Hit.plays);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("simulateCombat: healPerTurn power restores hp at turn start", () => {
|
||||||
|
const data = {
|
||||||
|
cards: {
|
||||||
|
Recovery: { name: "셀프 리커버리", cost: 0, kind: "Power", powerEffect: "healPerTurn", value: 3 },
|
||||||
|
Hit: { name: "마무리", cost: 1, kind: "Attack", damage: 1 },
|
||||||
|
},
|
||||||
|
starterDeck: ["Recovery", "Hit"],
|
||||||
|
monsters: [{ name: "Dummy", maxHp: 2, intents: [{ kind: "Attack", value: 2 }] }],
|
||||||
|
playerHp: 70,
|
||||||
|
playerMaxHp: 80,
|
||||||
|
};
|
||||||
|
const r = simulateCombat(data, () => 0.999999);
|
||||||
|
assert.equal(r.win, true);
|
||||||
|
assert.ok(r.playerHpRemaining >= 69);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("simulateCombat: Holy Charge scales repeated Holy Force attacks", () => {
|
||||||
|
const data = {
|
||||||
|
cards: {
|
||||||
|
ChargeStrike: { name: "차지 타격", cost: 1, kind: "Attack", damage: 2, holyChargeGain: 1, damagePerHolyCharge: 1 },
|
||||||
|
},
|
||||||
|
starterDeck: ["ChargeStrike"],
|
||||||
|
monsters: [{ name: "Dummy", maxHp: 14, intents: [{ kind: "Attack", value: 0 }] }],
|
||||||
|
};
|
||||||
|
const stats = {};
|
||||||
|
const r = simulateCombat(data, () => 0.999999, stats);
|
||||||
|
assert.equal(r.win, true);
|
||||||
|
assert.ok(stats.ChargeStrike.damage > stats.ChargeStrike.plays * 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("simulateCombat: damageTakenReduction lowers incoming HP damage", () => {
|
||||||
|
const data = {
|
||||||
|
cards: {
|
||||||
|
Achilles: { name: "아킬레스", cost: 3, kind: "Power", damageTakenReduction: 0.25, innate: true },
|
||||||
|
Wait1: { name: "대기", cost: 99, kind: "Status", unplayable: true, innate: true },
|
||||||
|
Wait2: { name: "대기", cost: 99, kind: "Status", unplayable: true, innate: true },
|
||||||
|
Wait3: { name: "대기", cost: 99, kind: "Status", unplayable: true, innate: true },
|
||||||
|
Wait4: { name: "대기", cost: 99, kind: "Status", unplayable: true, innate: true },
|
||||||
|
Finish: { name: "마무리", cost: 3, kind: "Power", cardPlayedDamage: 2 },
|
||||||
|
},
|
||||||
|
starterDeck: ["Finish", "Achilles", "Wait1", "Wait2", "Wait3", "Wait4"],
|
||||||
|
monsters: [{ name: "Dummy", maxHp: 2, intents: [{ kind: "Attack", value: 10 }] }],
|
||||||
|
};
|
||||||
|
const r = simulateCombat(data, () => 0.999999);
|
||||||
|
assert.equal(r.win, true);
|
||||||
|
assert.equal(r.playerHpRemaining, 73);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("simulateCombat: blockOnDamaged protects against later attackers", () => {
|
||||||
|
const data = {
|
||||||
|
cards: {
|
||||||
|
Armor: { name: "블레싱 아머", cost: 3, kind: "Power", blockOnDamaged: 6, strengthOnDamagedOnce: 2, innate: true },
|
||||||
|
Wait1: { name: "대기", cost: 99, kind: "Status", unplayable: true, innate: true },
|
||||||
|
Wait2: { name: "대기", cost: 99, kind: "Status", unplayable: true, innate: true },
|
||||||
|
Wait3: { name: "대기", cost: 99, kind: "Status", unplayable: true, innate: true },
|
||||||
|
Wait4: { name: "대기", cost: 99, kind: "Status", unplayable: true, innate: true },
|
||||||
|
Finish1: { name: "마무리", cost: 3, kind: "Power", cardPlayedDamage: 1 },
|
||||||
|
Finish2: { name: "마무리", cost: 3, kind: "Power", cardPlayedDamage: 1 },
|
||||||
|
},
|
||||||
|
starterDeck: ["Finish1", "Finish2", "Armor", "Wait1", "Wait2", "Wait3", "Wait4"],
|
||||||
|
monsters: [
|
||||||
|
{ name: "A", maxHp: 1, intents: [{ kind: "Attack", value: 5 }] },
|
||||||
|
{ name: "B", maxHp: 1, intents: [{ kind: "Attack", value: 5 }] },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const r = simulateCombat(data, () => 0.999999);
|
||||||
|
assert.equal(r.win, true);
|
||||||
|
assert.equal(r.playerHpRemaining, 70);
|
||||||
|
});
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ local function applyCardPlayHooks()
|
|||||||
if c.cardPlayedRandomDamage ~= nil and c.cardPlayedRandomDamage > 0 then
|
if c.cardPlayedRandomDamage ~= nil and c.cardPlayedRandomDamage > 0 then
|
||||||
self:DealDirectDamageToRandomMonster(c.cardPlayedRandomDamage)
|
self:DealDirectDamageToRandomMonster(c.cardPlayedRandomDamage)
|
||||||
end
|
end
|
||||||
|
self:ApplyAttackCardPlayHooks(c)
|
||||||
|
self:ApplyHolyForceCardPlayHooks(c)
|
||||||
end
|
end
|
||||||
applyCardPlayHooks()
|
applyCardPlayHooks()
|
||||||
if skillRepeat > 0 then
|
if skillRepeat > 0 then
|
||||||
@@ -550,6 +552,11 @@ for i = 1, #self.Monsters do
|
|||||||
if self.Monsters[i].alive == true then self.TargetIndex = i; break end
|
if self.Monsters[i].alive == true then self.TargetIndex = i; break end
|
||||||
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||||
method('DealDamageToPlayer', `local dmg = amount
|
method('DealDamageToPlayer', `local dmg = amount
|
||||||
|
local reduction = self:AddPowerFieldTotal("damageTakenReduction")
|
||||||
|
if reduction ~= nil and reduction > 0 then
|
||||||
|
reduction = math.min(0.75, reduction)
|
||||||
|
dmg = math.floor(dmg * (1 - reduction))
|
||||||
|
end
|
||||||
if self.PlayerBlock > 0 then
|
if self.PlayerBlock > 0 then
|
||||||
local absorbed = math.min(self.PlayerBlock, dmg)
|
local absorbed = math.min(self.PlayerBlock, dmg)
|
||||||
self.PlayerBlock = self.PlayerBlock - absorbed
|
self.PlayerBlock = self.PlayerBlock - absorbed
|
||||||
@@ -560,6 +567,17 @@ if dmg > 0 and self.PlayerIntangible ~= nil and self.PlayerIntangible > 0 and dm
|
|||||||
end
|
end
|
||||||
if dmg > 0 then
|
if dmg > 0 then
|
||||||
self.PlayerHp = self.PlayerHp - dmg
|
self.PlayerHp = self.PlayerHp - dmg
|
||||||
|
local reactiveBlock = self:AddPowerFieldTotal("blockOnDamaged")
|
||||||
|
if reactiveBlock ~= nil and reactiveBlock > 0 then
|
||||||
|
self:AddCardBlock(reactiveBlock)
|
||||||
|
end
|
||||||
|
if self.DamagePowerStrengthUsed ~= true then
|
||||||
|
local reactiveStrength = self:AddPowerFieldTotal("strengthOnDamagedOnce")
|
||||||
|
if reactiveStrength ~= nil and reactiveStrength > 0 then
|
||||||
|
self.PlayerStr = self.PlayerStr + reactiveStrength
|
||||||
|
self.DamagePowerStrengthUsed = true
|
||||||
|
end
|
||||||
|
end
|
||||||
local reflect = self.PlayerThorns or 0
|
local reflect = self.PlayerThorns or 0
|
||||||
if self:HasRelic("bronzeScales") then
|
if self:HasRelic("bronzeScales") then
|
||||||
reflect = reflect + 3
|
reflect = reflect + 3
|
||||||
|
|||||||
@@ -291,6 +291,8 @@ if self.PlayerPowers ~= nil then
|
|||||||
if self.Monsters ~= nil then
|
if self.Monsters ~= nil then
|
||||||
self:PlayAoeFx(pc.fx or pc.image, pc.value or 0)
|
self:PlayAoeFx(pc.fx or pc.image, pc.value or 0)
|
||||||
end
|
end
|
||||||
|
elseif pc.powerEffect == "healPerTurn" then
|
||||||
|
self.PlayerHp = math.min(self.PlayerMaxHp, self.PlayerHp + pc.value)
|
||||||
end
|
end
|
||||||
if pc.turnStartShiv ~= nil then
|
if pc.turnStartShiv ~= nil then
|
||||||
self:AddCardsToHand("Shiv", pc.turnStartShiv)
|
self:AddCardsToHand("Shiv", pc.turnStartShiv)
|
||||||
|
|||||||
@@ -346,6 +346,69 @@ countPile(self.DrawPile)
|
|||||||
countPile(self.DiscardPile)
|
countPile(self.DiscardPile)
|
||||||
countPile(self.ExhaustPile)
|
countPile(self.ExhaustPile)
|
||||||
return n`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'match' }], 0, 'number'),
|
return n`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'match' }], 0, 'number'),
|
||||||
|
method('MaxPowerField', `local best = 0
|
||||||
|
if self.PlayerPowers == nil then
|
||||||
|
return best
|
||||||
|
end
|
||||||
|
for i = 1, #self.PlayerPowers do
|
||||||
|
local powerCard = self.Cards[self.PlayerPowers[i]]
|
||||||
|
if powerCard ~= nil and powerCard[field] ~= nil and powerCard[field] > best then
|
||||||
|
best = powerCard[field]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return best`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'field' }], 0, 'number'),
|
||||||
|
method('GetComboMax', `local comboMax = 5
|
||||||
|
local powerMax = self:MaxPowerField("comboMax")
|
||||||
|
if powerMax ~= nil and powerMax > comboMax then
|
||||||
|
comboMax = powerMax
|
||||||
|
end
|
||||||
|
return comboMax`, [], 0, 'number'),
|
||||||
|
method('GainCombo', `if amount == nil or amount <= 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.ComboCount = math.min(self:GetComboMax(), (self.ComboCount or 0) + amount)`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' }]),
|
||||||
|
method('GetHolyChargeMax', `local chargeMax = 3
|
||||||
|
local powerMax = self:MaxPowerField("holyChargeMax")
|
||||||
|
if powerMax ~= nil and powerMax > chargeMax then
|
||||||
|
chargeMax = powerMax
|
||||||
|
end
|
||||||
|
return chargeMax`, [], 0, 'number'),
|
||||||
|
method('GainHolyCharge', `if amount == nil or amount <= 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.HolyChargeCount = math.min(self:GetHolyChargeMax(), (self.HolyChargeCount or 0) + amount)`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' }]),
|
||||||
|
method('ApplyHolyForceCardPlayHooks', `if c == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local gain = c.holyChargeGain or 0
|
||||||
|
if c.holyForce == true then
|
||||||
|
gain = gain + self:AddPowerFieldTotal("holyChargeOnHolyForce")
|
||||||
|
end
|
||||||
|
self:GainHolyCharge(gain)
|
||||||
|
if c.holyChargeSpendAll == true then
|
||||||
|
self.HolyChargeCount = 0
|
||||||
|
end`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }]),
|
||||||
|
method('ApplyAttackCardPlayHooks', `if c == nil or c.kind ~= "Attack" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local comboGain = c.comboGain or 0
|
||||||
|
comboGain = comboGain + self:AddPowerFieldTotal("comboOnAttack")
|
||||||
|
self:GainCombo(comboGain)
|
||||||
|
local extraDamage = self:AddPowerFieldTotal("attackPlayedDamage")
|
||||||
|
if extraDamage ~= nil and extraDamage > 0 then
|
||||||
|
self:DealDirectDamageToTarget(extraDamage)
|
||||||
|
end
|
||||||
|
local weakAmount = self:AddPowerFieldTotal("attackWeak")
|
||||||
|
if weakAmount ~= nil and weakAmount > 0 and self.Monsters ~= nil then
|
||||||
|
local target = self.Monsters[self.TargetIndex]
|
||||||
|
if target ~= nil and target.alive == true then
|
||||||
|
if target.artifact ~= nil and target.artifact > 0 then
|
||||||
|
target.artifact = target.artifact - 1
|
||||||
|
else
|
||||||
|
target.weak = (target.weak or 0) + weakAmount
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }]),
|
||||||
method('AttackBaseForCard', `local base2 = c.damage or 0
|
method('AttackBaseForCard', `local base2 = c.damage or 0
|
||||||
if c.damageNameMatch ~= nil and c.damagePerOwnedNameMatch ~= nil then
|
if c.damageNameMatch ~= nil and c.damagePerOwnedNameMatch ~= nil then
|
||||||
base2 = base2 + self:CountOwnedNameMatches(c.damageNameMatch) * c.damagePerOwnedNameMatch
|
base2 = base2 + self:CountOwnedNameMatches(c.damageNameMatch) * c.damagePerOwnedNameMatch
|
||||||
@@ -353,6 +416,14 @@ end
|
|||||||
if c.damageFromCurrentBlock ~= nil and c.damageFromCurrentBlock ~= 0 then
|
if c.damageFromCurrentBlock ~= nil and c.damageFromCurrentBlock ~= 0 then
|
||||||
base2 = base2 + (self.PlayerBlock or 0) * c.damageFromCurrentBlock
|
base2 = base2 + (self.PlayerBlock or 0) * c.damageFromCurrentBlock
|
||||||
end
|
end
|
||||||
|
local comboScale = c.damagePerCombo or 0
|
||||||
|
comboScale = comboScale + self:AddPowerFieldTotal("attackDamagePerCombo")
|
||||||
|
if comboScale ~= 0 then
|
||||||
|
base2 = base2 + (self.ComboCount or 0) * comboScale
|
||||||
|
end
|
||||||
|
if c.damagePerHolyCharge ~= nil and c.damagePerHolyCharge ~= 0 then
|
||||||
|
base2 = base2 + (self.HolyChargeCount or 0) * c.damagePerHolyCharge
|
||||||
|
end
|
||||||
local otherHand = 0
|
local otherHand = 0
|
||||||
if self.Hand ~= nil then
|
if self.Hand ~= nil then
|
||||||
otherHand = #self.Hand - 1
|
otherHand = #self.Hand - 1
|
||||||
@@ -431,6 +502,8 @@ local function applyCardPlayHooks()
|
|||||||
if c.cardPlayedRandomDamage ~= nil and c.cardPlayedRandomDamage > 0 then
|
if c.cardPlayedRandomDamage ~= nil and c.cardPlayedRandomDamage > 0 then
|
||||||
self:DealDirectDamageToRandomMonster(c.cardPlayedRandomDamage)
|
self:DealDirectDamageToRandomMonster(c.cardPlayedRandomDamage)
|
||||||
end
|
end
|
||||||
|
self:ApplyAttackCardPlayHooks(c)
|
||||||
|
self:ApplyHolyForceCardPlayHooks(c)
|
||||||
end
|
end
|
||||||
applyCardPlayHooks()
|
applyCardPlayHooks()
|
||||||
if skillRepeat > 0 then
|
if skillRepeat > 0 then
|
||||||
@@ -706,7 +779,7 @@ if c.kind == "Attack" then
|
|||||||
if c.damage ~= nil or c.xDamagePerEnergy ~= nil or c.damageFromCurrentBlock ~= nil then
|
if c.damage ~= nil or c.xDamagePerEnergy ~= nil or c.damageFromCurrentBlock ~= nil then
|
||||||
self:PlayerAttackMotion()
|
self:PlayerAttackMotion()
|
||||||
local baseDmg = self:AttackBaseForCard(slot, c)
|
local baseDmg = self:AttackBaseForCard(slot, c)
|
||||||
self.ActiveAttackDamageVsWeakMultiplier = c.attackDamageVsWeakMultiplier or 1
|
self.ActiveAttackDamageVsWeakMultiplier = math.max(c.attackDamageVsWeakMultiplier or 1, self:MaxPowerField("attackDamageVsWeakMultiplier"))
|
||||||
if c.xDamagePerEnergy ~= nil and c.xDamagePerEnergy > 0 then
|
if c.xDamagePerEnergy ~= nil and c.xDamagePerEnergy > 0 then
|
||||||
baseDmg = xEnergy * c.xDamagePerEnergy
|
baseDmg = xEnergy * c.xDamagePerEnergy
|
||||||
end
|
end
|
||||||
@@ -788,14 +861,14 @@ if c.kind == "Attack" then
|
|||||||
self.DamageDealtThisTurn = (self.DamageDealtThisTurn or 0) + totalDamage
|
self.DamageDealtThisTurn = (self.DamageDealtThisTurn or 0) + totalDamage
|
||||||
end
|
end
|
||||||
if c.block ~= nil then
|
if c.block ~= nil then
|
||||||
self:AddCardBlock(c.block)
|
self:AddCardBlock(c.block + (self.HolyChargeCount or 0) * (c.blockPerHolyCharge or 0))
|
||||||
end
|
end
|
||||||
if free ~= true then
|
if free ~= true then
|
||||||
self:ApplyRelics("cardPlayed")
|
self:ApplyRelics("cardPlayed")
|
||||||
end
|
end
|
||||||
elseif c.kind == "Skill" then
|
elseif c.kind == "Skill" then
|
||||||
if c.block ~= nil then
|
if c.block ~= nil then
|
||||||
self:AddCardBlock(c.block)
|
self:AddCardBlock(c.block + (self.HolyChargeCount or 0) * (c.blockPerHolyCharge or 0))
|
||||||
end
|
end
|
||||||
elseif c.kind == "Power" then
|
elseif c.kind == "Power" then
|
||||||
if free ~= true then
|
if free ~= true then
|
||||||
@@ -815,11 +888,19 @@ if c.selfVuln ~= nil then
|
|||||||
self.PlayerVuln = self.PlayerVuln + c.selfVuln
|
self.PlayerVuln = self.PlayerVuln + c.selfVuln
|
||||||
end
|
end
|
||||||
if c.heal ~= nil then
|
if c.heal ~= nil then
|
||||||
self.PlayerHp = math.min(self.PlayerHp + c.heal, self.PlayerMaxHp)
|
local healAmount = c.heal + (self.HolyChargeCount or 0) * (c.healPerHolyCharge or 0)
|
||||||
|
self.PlayerHp = math.min(self.PlayerHp + healAmount, self.PlayerMaxHp)
|
||||||
end
|
end
|
||||||
if c.gainEnergy ~= nil and c.gainEnergy ~= 0 then
|
if c.gainEnergy ~= nil and c.gainEnergy ~= 0 then
|
||||||
self.Energy = self.Energy + c.gainEnergy
|
self.Energy = self.Energy + c.gainEnergy
|
||||||
end
|
end
|
||||||
|
if c.kind ~= "Attack" and c.comboGain ~= nil and c.comboGain > 0 then
|
||||||
|
self:GainCombo(c.comboGain)
|
||||||
|
end
|
||||||
|
if c.removePlayerDebuffs == true then
|
||||||
|
self.PlayerWeak = 0
|
||||||
|
self.PlayerVuln = 0
|
||||||
|
end
|
||||||
if c.intangible ~= nil and c.intangible > 0 then
|
if c.intangible ~= nil and c.intangible > 0 then
|
||||||
self.PlayerIntangible = (self.PlayerIntangible or 0) + c.intangible
|
self.PlayerIntangible = (self.PlayerIntangible or 0) + c.intangible
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -80,6 +80,14 @@ if self.PlayerThorns ~= nil and self.PlayerThorns > 0 then
|
|||||||
if pb ~= "" then pb = pb .. " " end
|
if pb ~= "" then pb = pb .. " " end
|
||||||
pb = pb .. "가시" .. tostring(self.PlayerThorns)
|
pb = pb .. "가시" .. tostring(self.PlayerThorns)
|
||||||
end
|
end
|
||||||
|
if self.ComboCount ~= nil and self.ComboCount > 0 then
|
||||||
|
if pb ~= "" then pb = pb .. " " end
|
||||||
|
pb = pb .. "콤보 " .. tostring(self.ComboCount) .. "/" .. tostring(self:GetComboMax())
|
||||||
|
end
|
||||||
|
if self.HolyChargeCount ~= nil and self.HolyChargeCount > 0 then
|
||||||
|
if pb ~= "" then pb = pb .. " " end
|
||||||
|
pb = pb .. "홀리 차지 " .. tostring(self.HolyChargeCount) .. "/" .. tostring(self:GetHolyChargeMax())
|
||||||
|
end
|
||||||
if self.PlayerPowers ~= nil and #self.PlayerPowers > 0 then
|
if self.PlayerPowers ~= nil and #self.PlayerPowers > 0 then
|
||||||
local names = {}
|
local names = {}
|
||||||
for i = 1, #self.PlayerPowers do
|
for i = 1, #self.PlayerPowers do
|
||||||
|
|||||||
@@ -101,6 +101,9 @@ self.FightAttackCount = 0
|
|||||||
self.TurnAttackCardsPlayed = 0
|
self.TurnAttackCardsPlayed = 0
|
||||||
self.TurnDiscardedCards = 0
|
self.TurnDiscardedCards = 0
|
||||||
self.TurnCardsPlayedThisTurn = 0
|
self.TurnCardsPlayedThisTurn = 0
|
||||||
|
self.ComboCount = 0
|
||||||
|
self.HolyChargeCount = 0
|
||||||
|
self.DamagePowerStrengthUsed = false
|
||||||
self.DamageDealtThisTurn = 0
|
self.DamageDealtThisTurn = 0
|
||||||
self.DmgPopSeq = 0
|
self.DmgPopSeq = 0
|
||||||
self.FirstHpLossDone = false
|
self.FirstHpLossDone = false
|
||||||
|
|||||||
@@ -147,6 +147,9 @@ function writeCodeblocks() {
|
|||||||
prop('number', 'FightAttackCount', '0'),
|
prop('number', 'FightAttackCount', '0'),
|
||||||
prop('number', 'TurnAttackCardsPlayed', '0'),
|
prop('number', 'TurnAttackCardsPlayed', '0'),
|
||||||
prop('number', 'TurnCardsPlayedThisTurn', '0'),
|
prop('number', 'TurnCardsPlayedThisTurn', '0'),
|
||||||
|
prop('number', 'ComboCount', '0'),
|
||||||
|
prop('number', 'HolyChargeCount', '0'),
|
||||||
|
prop('boolean', 'DamagePowerStrengthUsed', 'false'),
|
||||||
prop('number', 'DamageDealtThisTurn', '0'),
|
prop('number', 'DamageDealtThisTurn', '0'),
|
||||||
prop('number', 'TurnDiscardedCards', '0'),
|
prop('number', 'TurnDiscardedCards', '0'),
|
||||||
prop('boolean', 'FirstHpLossDone', 'false'),
|
prop('boolean', 'FirstHpLossDone', 'false'),
|
||||||
|
|||||||
@@ -19,15 +19,15 @@ for (const cls of Object.keys(CLASSES)) {
|
|||||||
// 전직 옵션
|
// 전직 옵션
|
||||||
const JOBS = {
|
const JOBS = {
|
||||||
warrior: [
|
warrior: [
|
||||||
{ id: 'fighter', name: '파이터', desc: '연속 공격 계열\n이중 타격 · 난타\n악마의 형상', starter: 'TwinStrike', tier: 2, parent: 'warrior' },
|
{ id: 'fighter', name: '파이터', desc: '콤보와 다단 공격 특화\n공격으로 콤보를 쌓고\n추가타로 압박', starter: 'ComboAttack', tier: 2, parent: 'warrior' },
|
||||||
{ id: 'page', name: '페이지', desc: '방어·운영 계열\n전투의 북소리 · 무적\n바리케이드', starter: 'DrumOfBattle', tier: 2, parent: 'warrior' },
|
{ id: 'page', name: '페이지', desc: '홀리 포스와 방어 특화\n홀리 차지를 쌓아\n공격과 생존 강화', starter: 'HolyCharge', tier: 2, parent: 'warrior' },
|
||||||
{ id: 'spearman', name: '스피어맨', desc: '광역·장기전 계열\n대화재 · 소용돌이\n불의 심장', starter: 'Conflagration', tier: 2, parent: 'warrior' },
|
{ id: 'spearman', name: '스피어맨', desc: '광역·장기전 계열\n대화재 · 소용돌이\n불의 심장', starter: 'Conflagration', tier: 2, parent: 'warrior' },
|
||||||
],
|
],
|
||||||
fighter: [
|
fighter: [
|
||||||
{ id: 'crusader', name: '크루세이더', desc: '파이터의 3차 전직\n아이언클래드 공격 풀 계승\n전사 카드 사용', starter: '', tier: 3, parent: 'fighter' },
|
{ id: 'crusader', name: '크루세이더', desc: '파이터의 3차 전직\n콤보 상한과 연계 피해 강화\n파이터 카드 계승', starter: 'ComboSynergy', tier: 3, parent: 'fighter' },
|
||||||
],
|
],
|
||||||
page: [
|
page: [
|
||||||
{ id: 'knight', name: '나이트', desc: '페이지의 3차 전직\n아이언클래드 운영 풀 계승\n전사 카드 사용', starter: '', tier: 3, parent: 'page' },
|
{ id: 'knight', name: '나이트', desc: '페이지의 3차 전직\n홀리 차지를 공격·방어·회복으로 전환\n페이지 카드 계승', starter: 'DivineCharge', tier: 3, parent: 'page' },
|
||||||
],
|
],
|
||||||
spearman: [
|
spearman: [
|
||||||
{ id: 'berserker', name: '버서커', desc: '스피어맨의 3차 전직\n아이언클래드 장기전 풀 계승\n전사 카드 사용', starter: '', tier: 3, parent: 'spearman' },
|
{ id: 'berserker', name: '버서커', desc: '스피어맨의 3차 전직\n아이언클래드 장기전 풀 계승\n전사 카드 사용', starter: '', tier: 3, parent: 'spearman' },
|
||||||
@@ -225,6 +225,9 @@ function luaCardsTable(cards) {
|
|||||||
const fields = [`name = ${luaStr(c.name)}`, `cost = ${c.cost}`, `desc = ${luaStr(c.desc)}`, `kind = ${luaStr(c.kind)}`];
|
const fields = [`name = ${luaStr(c.name)}`, `cost = ${c.cost}`, `desc = ${luaStr(c.desc)}`, `kind = ${luaStr(c.kind)}`];
|
||||||
if (c.damage != null) fields.push(`damage = ${c.damage}`);
|
if (c.damage != null) fields.push(`damage = ${c.damage}`);
|
||||||
if (c.damageFromCurrentBlock != null) fields.push(`damageFromCurrentBlock = ${c.damageFromCurrentBlock}`);
|
if (c.damageFromCurrentBlock != null) fields.push(`damageFromCurrentBlock = ${c.damageFromCurrentBlock}`);
|
||||||
|
if (c.damagePerCombo != null) fields.push(`damagePerCombo = ${c.damagePerCombo}`);
|
||||||
|
if (c.damagePerHolyCharge != null) fields.push(`damagePerHolyCharge = ${c.damagePerHolyCharge}`);
|
||||||
|
if (c.attackDamagePerCombo != null) fields.push(`attackDamagePerCombo = ${c.attackDamagePerCombo}`);
|
||||||
if (c.damageNameMatch != null) fields.push(`damageNameMatch = ${luaStr(c.damageNameMatch)}`);
|
if (c.damageNameMatch != null) fields.push(`damageNameMatch = ${luaStr(c.damageNameMatch)}`);
|
||||||
if (c.damagePerOwnedNameMatch != null) fields.push(`damagePerOwnedNameMatch = ${c.damagePerOwnedNameMatch}`);
|
if (c.damagePerOwnedNameMatch != null) fields.push(`damagePerOwnedNameMatch = ${c.damagePerOwnedNameMatch}`);
|
||||||
if (c.damagePerOtherHandCard != null) fields.push(`damagePerOtherHandCard = ${c.damagePerOtherHandCard}`);
|
if (c.damagePerOtherHandCard != null) fields.push(`damagePerOtherHandCard = ${c.damagePerOtherHandCard}`);
|
||||||
@@ -235,6 +238,7 @@ function luaCardsTable(cards) {
|
|||||||
if (c.damagePerTurn != null) fields.push(`damagePerTurn = ${c.damagePerTurn}`);
|
if (c.damagePerTurn != null) fields.push(`damagePerTurn = ${c.damagePerTurn}`);
|
||||||
if (c.cardPlayedDamage != null) fields.push(`cardPlayedDamage = ${c.cardPlayedDamage}`);
|
if (c.cardPlayedDamage != null) fields.push(`cardPlayedDamage = ${c.cardPlayedDamage}`);
|
||||||
if (c.cardPlayedRandomDamage != null) fields.push(`cardPlayedRandomDamage = ${c.cardPlayedRandomDamage}`);
|
if (c.cardPlayedRandomDamage != null) fields.push(`cardPlayedRandomDamage = ${c.cardPlayedRandomDamage}`);
|
||||||
|
if (c.attackPlayedDamage != null) fields.push(`attackPlayedDamage = ${c.attackPlayedDamage}`);
|
||||||
if (c.firstCardDamageBonus != null) fields.push(`firstCardDamageBonus = ${c.firstCardDamageBonus}`);
|
if (c.firstCardDamageBonus != null) fields.push(`firstCardDamageBonus = ${c.firstCardDamageBonus}`);
|
||||||
if (c.rewardOnKill != null) fields.push(`rewardOnKill = ${c.rewardOnKill}`);
|
if (c.rewardOnKill != null) fields.push(`rewardOnKill = ${c.rewardOnKill}`);
|
||||||
if (c.maxHpOnKill != null) fields.push(`maxHpOnKill = ${c.maxHpOnKill}`);
|
if (c.maxHpOnKill != null) fields.push(`maxHpOnKill = ${c.maxHpOnKill}`);
|
||||||
@@ -251,6 +255,14 @@ function luaCardsTable(cards) {
|
|||||||
if (c.dex != null) fields.push(`dex = ${c.dex}`);
|
if (c.dex != null) fields.push(`dex = ${c.dex}`);
|
||||||
if (c.thorns != null) fields.push(`thorns = ${c.thorns}`);
|
if (c.thorns != null) fields.push(`thorns = ${c.thorns}`);
|
||||||
if (c.cardPlayedBlock != null) fields.push(`cardPlayedBlock = ${c.cardPlayedBlock}`);
|
if (c.cardPlayedBlock != null) fields.push(`cardPlayedBlock = ${c.cardPlayedBlock}`);
|
||||||
|
if (c.comboOnAttack != null) fields.push(`comboOnAttack = ${c.comboOnAttack}`);
|
||||||
|
if (c.comboMax != null) fields.push(`comboMax = ${c.comboMax}`);
|
||||||
|
if (c.attackWeak != null) fields.push(`attackWeak = ${c.attackWeak}`);
|
||||||
|
if (c.holyChargeOnHolyForce != null) fields.push(`holyChargeOnHolyForce = ${c.holyChargeOnHolyForce}`);
|
||||||
|
if (c.holyChargeMax != null) fields.push(`holyChargeMax = ${c.holyChargeMax}`);
|
||||||
|
if (c.damageTakenReduction != null) fields.push(`damageTakenReduction = ${c.damageTakenReduction}`);
|
||||||
|
if (c.blockOnDamaged != null) fields.push(`blockOnDamaged = ${c.blockOnDamaged}`);
|
||||||
|
if (c.strengthOnDamagedOnce != null) fields.push(`strengthOnDamagedOnce = ${c.strengthOnDamagedOnce}`);
|
||||||
if (c.drawOnExhaust != null) fields.push(`drawOnExhaust = ${c.drawOnExhaust}`);
|
if (c.drawOnExhaust != null) fields.push(`drawOnExhaust = ${c.drawOnExhaust}`);
|
||||||
if (c.drawNameMatchAutoPlay != null) fields.push(`drawNameMatchAutoPlay = ${luaStr(c.drawNameMatchAutoPlay)}`);
|
if (c.drawNameMatchAutoPlay != null) fields.push(`drawNameMatchAutoPlay = ${luaStr(c.drawNameMatchAutoPlay)}`);
|
||||||
if (c.weak != null) fields.push(`weak = ${c.weak}`);
|
if (c.weak != null) fields.push(`weak = ${c.weak}`);
|
||||||
@@ -280,7 +292,14 @@ function luaCardsTable(cards) {
|
|||||||
if (c.playTopDrawPileCount != null) fields.push(`playTopDrawPileCount = ${c.playTopDrawPileCount}`);
|
if (c.playTopDrawPileCount != null) fields.push(`playTopDrawPileCount = ${c.playTopDrawPileCount}`);
|
||||||
if (c.playTopDrawPileCountPerEnergy != null) fields.push(`playTopDrawPileCountPerEnergy = ${c.playTopDrawPileCountPerEnergy}`);
|
if (c.playTopDrawPileCountPerEnergy != null) fields.push(`playTopDrawPileCountPerEnergy = ${c.playTopDrawPileCountPerEnergy}`);
|
||||||
if (c.heal != null) fields.push(`heal = ${c.heal}`);
|
if (c.heal != null) fields.push(`heal = ${c.heal}`);
|
||||||
|
if (c.healPerHolyCharge != null) fields.push(`healPerHolyCharge = ${c.healPerHolyCharge}`);
|
||||||
if (c.gainEnergy != null) fields.push(`gainEnergy = ${c.gainEnergy}`);
|
if (c.gainEnergy != null) fields.push(`gainEnergy = ${c.gainEnergy}`);
|
||||||
|
if (c.comboGain != null) fields.push(`comboGain = ${c.comboGain}`);
|
||||||
|
if (c.removePlayerDebuffs === true) fields.push('removePlayerDebuffs = true');
|
||||||
|
if (c.holyForce === true) fields.push('holyForce = true');
|
||||||
|
if (c.holyChargeGain != null) fields.push(`holyChargeGain = ${c.holyChargeGain}`);
|
||||||
|
if (c.blockPerHolyCharge != null) fields.push(`blockPerHolyCharge = ${c.blockPerHolyCharge}`);
|
||||||
|
if (c.holyChargeSpendAll === true) fields.push('holyChargeSpendAll = true');
|
||||||
if (c.poison != null) fields.push(`poison = ${c.poison}`);
|
if (c.poison != null) fields.push(`poison = ${c.poison}`);
|
||||||
if (c.discard != null) fields.push(`discard = ${c.discard}`);
|
if (c.discard != null) fields.push(`discard = ${c.discard}`);
|
||||||
if (c.discardAll === true) fields.push('discardAll = true');
|
if (c.discardAll === true) fields.push('discardAll = true');
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ const POWER_FIELDS = [
|
|||||||
'shivDamageBonus', 'firstShivDamageBonus', 'shivRetain', 'shivAoe',
|
'shivDamageBonus', 'firstShivDamageBonus', 'shivRetain', 'shivAoe',
|
||||||
'attackPoison', 'drawDamage', 'drawPoison', 'attackDamageVsWeakMultiplier',
|
'attackPoison', 'drawDamage', 'drawPoison', 'attackDamageVsWeakMultiplier',
|
||||||
'cardPlayedBlock', 'cardPlayedDamage', 'cardPlayedRandomDamage',
|
'cardPlayedBlock', 'cardPlayedDamage', 'cardPlayedRandomDamage',
|
||||||
|
'comboOnAttack', 'comboMax', 'attackDamagePerCombo', 'attackPlayedDamage', 'attackWeak',
|
||||||
|
'holyChargeOnHolyForce', 'holyChargeMax', 'damageTakenReduction',
|
||||||
|
'blockOnDamaged', 'strengthOnDamagedOnce',
|
||||||
'drawOnExhaust', 'drawNameMatchAutoPlay',
|
'drawOnExhaust', 'drawNameMatchAutoPlay',
|
||||||
'extraPoisonTicks', 'poisonApplicationBurstEvery', 'poisonApplicationBurstDamage',
|
'extraPoisonTicks', 'poisonApplicationBurstEvery', 'poisonApplicationBurstDamage',
|
||||||
'skillSlyOnPlay', 'endTurnDexLoss',
|
'skillSlyOnPlay', 'endTurnDexLoss',
|
||||||
|
|||||||
Reference in New Issue
Block a user