feat(bandit): implement sly discard trigger
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -396,7 +396,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "방어도를 8 얻습니다. 카드를 1장 버립니다.",
|
"desc": "방어도를 8 얻습니다. 카드를 1장 버립니다.",
|
||||||
"block": 8
|
"block": 8,
|
||||||
|
"discard": 1
|
||||||
},
|
},
|
||||||
"SilentDefend": {
|
"SilentDefend": {
|
||||||
"name": "수비",
|
"name": "수비",
|
||||||
@@ -435,7 +436,8 @@
|
|||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "피해를 9 줍니다. 카드를 1장 뽑습니다. 카드를 1장 버립니다.",
|
"desc": "피해를 9 줍니다. 카드를 1장 뽑습니다. 카드를 1장 버립니다.",
|
||||||
"draw": 1,
|
"draw": 1,
|
||||||
"damage": 9
|
"damage": 9,
|
||||||
|
"discard": 1
|
||||||
},
|
},
|
||||||
"PoisonedStab": {
|
"PoisonedStab": {
|
||||||
"name": "독 찌르기",
|
"name": "독 찌르기",
|
||||||
@@ -483,7 +485,8 @@
|
|||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "교활. 모든 적에게 피해를 6 줍니다.",
|
"desc": "교활. 모든 적에게 피해를 6 줍니다.",
|
||||||
"aoe": true,
|
"aoe": true,
|
||||||
"damage": 6
|
"damage": 6,
|
||||||
|
"sly": true
|
||||||
},
|
},
|
||||||
"Ricochet": {
|
"Ricochet": {
|
||||||
"name": "도탄",
|
"name": "도탄",
|
||||||
@@ -493,7 +496,8 @@
|
|||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "교활. 무작위 적에게 피해를 3만큼 4번 줍니다.",
|
"desc": "교활. 무작위 적에게 피해를 3만큼 4번 줍니다.",
|
||||||
"damage": 3,
|
"damage": 3,
|
||||||
"hits": 4
|
"hits": 4,
|
||||||
|
"sly": true
|
||||||
},
|
},
|
||||||
"Prepared": {
|
"Prepared": {
|
||||||
"name": "예비",
|
"name": "예비",
|
||||||
@@ -502,7 +506,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "카드를 1장 뽑습니다. 카드를 1장 버립니다.",
|
"desc": "카드를 1장 뽑습니다. 카드를 1장 버립니다.",
|
||||||
"draw": 1
|
"draw": 1,
|
||||||
|
"discard": 1
|
||||||
},
|
},
|
||||||
"Anticipate": {
|
"Anticipate": {
|
||||||
"name": "예측",
|
"name": "예측",
|
||||||
@@ -596,7 +601,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "교활. 방어도를 6 얻습니다.",
|
"desc": "교활. 방어도를 6 얻습니다.",
|
||||||
"block": 6
|
"block": 6,
|
||||||
|
"sly": true
|
||||||
},
|
},
|
||||||
"Skewer": {
|
"Skewer": {
|
||||||
"name": "꼬챙이",
|
"name": "꼬챙이",
|
||||||
@@ -725,7 +731,8 @@
|
|||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "카드를 2장 버립니다. 단도를 2장 손으로 가져옵니다.",
|
"desc": "카드를 2장 버립니다. 단도를 2장 손으로 가져옵니다.",
|
||||||
"damage": 4,
|
"damage": 4,
|
||||||
"hits": 2
|
"hits": 2,
|
||||||
|
"discard": 2
|
||||||
},
|
},
|
||||||
"EscapePlan": {
|
"EscapePlan": {
|
||||||
"name": "탈출구",
|
"name": "탈출구",
|
||||||
@@ -744,7 +751,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "카드를 3장 뽑습니다. 카드를 1장 버립니다.",
|
"desc": "카드를 3장 뽑습니다. 카드를 1장 버립니다.",
|
||||||
"draw": 3
|
"draw": 3,
|
||||||
|
"discard": 1
|
||||||
},
|
},
|
||||||
"HandTrick": {
|
"HandTrick": {
|
||||||
"name": "손기술",
|
"name": "손기술",
|
||||||
@@ -827,7 +835,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "교활. 카드를 2장 뽑습니다.",
|
"desc": "교활. 카드를 2장 뽑습니다.",
|
||||||
"draw": 2
|
"draw": 2,
|
||||||
|
"sly": true
|
||||||
},
|
},
|
||||||
"Haze": {
|
"Haze": {
|
||||||
"name": "아지랑이",
|
"name": "아지랑이",
|
||||||
@@ -836,7 +845,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "교활. 모든 적에게 중독을 4 부여합니다.",
|
"desc": "교활. 모든 적에게 중독을 4 부여합니다.",
|
||||||
"poison": 4
|
"poison": 4,
|
||||||
|
"sly": true
|
||||||
},
|
},
|
||||||
"Tactician": {
|
"Tactician": {
|
||||||
"name": "전략가",
|
"name": "전략가",
|
||||||
@@ -846,7 +856,8 @@
|
|||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "교활. 을 얻습니다.",
|
"desc": "교활. 을 얻습니다.",
|
||||||
"powerEffect": "energyPerTurn",
|
"powerEffect": "energyPerTurn",
|
||||||
"value": 1
|
"value": 1,
|
||||||
|
"sly": true
|
||||||
},
|
},
|
||||||
"WellLaidPlans": {
|
"WellLaidPlans": {
|
||||||
"name": "괜찮은 전략",
|
"name": "괜찮은 전략",
|
||||||
@@ -1008,7 +1019,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "손에 있는 모든 카드를 버립니다. 버린 카드의 수만큼 단도를 손으로 가져옵니다.",
|
"desc": "손에 있는 모든 카드를 버립니다. 버린 카드의 수만큼 단도를 손으로 가져옵니다.",
|
||||||
"draw": 1
|
"draw": 1,
|
||||||
|
"discardAll": true
|
||||||
},
|
},
|
||||||
"ShadowStep": {
|
"ShadowStep": {
|
||||||
"name": "그림자 걸음",
|
"name": "그림자 걸음",
|
||||||
@@ -1017,7 +1029,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "손에 있는 모든 카드를 버립니다. 다음 턴에, 공격 카드의 피해량이 2배가 됩니다.",
|
"desc": "손에 있는 모든 카드를 버립니다. 다음 턴에, 공격 카드의 피해량이 2배가 됩니다.",
|
||||||
"draw": 1
|
"draw": 1,
|
||||||
|
"discardAll": true
|
||||||
},
|
},
|
||||||
"Shadowmeld": {
|
"Shadowmeld": {
|
||||||
"name": "그림자 은신",
|
"name": "그림자 은신",
|
||||||
@@ -1093,7 +1106,8 @@
|
|||||||
"desc": "내 턴 시작 시, 카드를 1장 뽑고 카드를 1장 버립니다.",
|
"desc": "내 턴 시작 시, 카드를 1장 뽑고 카드를 1장 버립니다.",
|
||||||
"draw": 1,
|
"draw": 1,
|
||||||
"powerEffect": "energyPerTurn",
|
"powerEffect": "energyPerTurn",
|
||||||
"value": 1
|
"value": 1,
|
||||||
|
"discard": 1
|
||||||
},
|
},
|
||||||
"Afterimage": {
|
"Afterimage": {
|
||||||
"name": "잔상",
|
"name": "잔상",
|
||||||
@@ -1178,7 +1192,8 @@
|
|||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "교활. 민첩을 1 얻습니다. 가시를 4 얻습니다.",
|
"desc": "교활. 민첩을 1 얻습니다. 가시를 4 얻습니다.",
|
||||||
"powerEffect": "blockPerTurn",
|
"powerEffect": "blockPerTurn",
|
||||||
"value": 2
|
"value": 2,
|
||||||
|
"sly": true
|
||||||
},
|
},
|
||||||
"Suppress": {
|
"Suppress": {
|
||||||
"name": "진압",
|
"name": "진압",
|
||||||
@@ -1216,7 +1231,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "교활. 다른 플레이어가 적을 공격할 때마다, 방어도를 1 얻습니다.",
|
"desc": "교활. 다른 플레이어가 적을 공격할 때마다, 방어도를 1 얻습니다.",
|
||||||
"block": 1
|
"block": 1,
|
||||||
|
"sly": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"starterDecks": {
|
"starterDecks": {
|
||||||
|
|||||||
@@ -124,10 +124,81 @@ export function simulateCombat(data, rng, stats) {
|
|||||||
if (drawPile.length === 0) break;
|
if (drawPile.length === 0) break;
|
||||||
const card = drawPile.pop();
|
const card = drawPile.pop();
|
||||||
// 손패 10장 상한 — 초과 드로는 자동 버림 (Lua DrawCards 동기화)
|
// 손패 10장 상한 — 초과 드로는 자동 버림 (Lua DrawCards 동기화)
|
||||||
if (hand.length >= 10) discard.push(card); else hand.push(card);
|
if (hand.length >= 10) {
|
||||||
|
discard.push(card);
|
||||||
|
triggerSly(card);
|
||||||
|
} else hand.push(card);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const aliveList = () => mob.filter((m) => m.alive);
|
const aliveList = () => mob.filter((m) => m.alive);
|
||||||
|
function resolveCardEffects(id, c, costSpent, recordStats = true) {
|
||||||
|
const alive = aliveList();
|
||||||
|
let dmg = 0;
|
||||||
|
if (c.kind === 'Attack') {
|
||||||
|
if (alive.length && c.damage) {
|
||||||
|
const target = chooseTarget(alive, calcAttack(c.damage || 0, pStr, pWeak, 0));
|
||||||
|
if (c.weak) target.weak += c.weak;
|
||||||
|
if (c.vuln) target.vuln += c.vuln;
|
||||||
|
const hitN = c.hits || 1;
|
||||||
|
let totalNv = 0;
|
||||||
|
for (let h = 0; h < hitN; h++) totalNv += calcAttack(c.damage || 0, pStr, pWeak, 0);
|
||||||
|
dmg = totalNv;
|
||||||
|
if (c.aoe === true) {
|
||||||
|
for (const m2 of aliveList()) {
|
||||||
|
const d2 = m2.vuln > 0 ? Math.floor(totalNv * 1.5) : totalNv;
|
||||||
|
const r2 = applyDamage(m2.hp, m2.block, d2);
|
||||||
|
m2.hp = r2.hp; m2.block = r2.block;
|
||||||
|
if (m2.hp <= 0) m2.alive = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dmg = target.vuln > 0 ? Math.floor(totalNv * 1.5) : totalNv;
|
||||||
|
if (c.pierce === true) {
|
||||||
|
target.hp -= dmg;
|
||||||
|
if (target.hp < 0) target.hp = 0;
|
||||||
|
} else {
|
||||||
|
const r = applyDamage(target.hp, target.block, dmg);
|
||||||
|
target.hp = r.hp; target.block = r.block;
|
||||||
|
}
|
||||||
|
if (target.hp <= 0) target.alive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c.block) pBlock += c.block;
|
||||||
|
} else if (c.kind === 'Power') {
|
||||||
|
if (c.powerEffect && recordStats) powers.push(id);
|
||||||
|
} else {
|
||||||
|
pBlock += c.block || 0;
|
||||||
|
if ((c.weak || c.vuln || c.poison) && alive.length) {
|
||||||
|
const target = chooseTarget(alive, 0);
|
||||||
|
if (c.weak) target.weak += c.weak;
|
||||||
|
if (c.vuln) target.vuln += c.vuln;
|
||||||
|
if (c.poison) target.poison += c.poison;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c.strength) pStr += c.strength;
|
||||||
|
if (c.selfVuln) pVuln += c.selfVuln;
|
||||||
|
if (c.heal) pHp = Math.min(pHp + c.heal, PLAYER_HP);
|
||||||
|
if (c.draw) draw(c.draw);
|
||||||
|
if (recordStats && stats) stats[id] = bump(stats[id], costSpent, dmg, c.block || 0);
|
||||||
|
}
|
||||||
|
function triggerSly(id) {
|
||||||
|
const c = cards[id];
|
||||||
|
if (!c?.sly) return;
|
||||||
|
resolveCardEffects(id, c, 0, false);
|
||||||
|
}
|
||||||
|
function discardHandCard(idx, trigger = true) {
|
||||||
|
const [id] = hand.splice(idx, 1);
|
||||||
|
if (!id) return;
|
||||||
|
discard.push(id);
|
||||||
|
if (trigger) triggerSly(id);
|
||||||
|
}
|
||||||
|
function applyDiscardEffects(c) {
|
||||||
|
if (c.discardAll) {
|
||||||
|
while (hand.length) discardHandCard(hand.length - 1, true);
|
||||||
|
} else if (c.discard) {
|
||||||
|
const n = Math.min(c.discard, hand.length);
|
||||||
|
for (let i = 0; i < n; i++) discardHandCard(hand.length - 1, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (turns < MAX_TURNS) {
|
while (turns < MAX_TURNS) {
|
||||||
turns++;
|
turns++;
|
||||||
@@ -149,59 +220,10 @@ export function simulateCombat(data, rng, stats) {
|
|||||||
if (idx < 0) break;
|
if (idx < 0) break;
|
||||||
const id = hand[idx], c = cards[id];
|
const id = hand[idx], c = cards[id];
|
||||||
energy -= c.cost;
|
energy -= c.cost;
|
||||||
if (c.kind === 'Attack') {
|
resolveCardEffects(id, c, c.cost);
|
||||||
const target = chooseTarget(alive, calcAttack(c.damage || 0, pStr, pWeak, 0));
|
|
||||||
// 카드 디버프는 피해보다 먼저 적용 — Lua PlayCard(즉시 부여) + 지연 데미지(0.35s) 동기화
|
|
||||||
if (c.weak) target.weak += c.weak;
|
|
||||||
if (c.vuln) target.vuln += c.vuln;
|
|
||||||
// 다단히트: 타격마다 힘·약화 적용 합산, 취약은 합산값에 1회 (Lua 동기화)
|
|
||||||
const hitN = c.hits || 1;
|
|
||||||
let totalNv = 0;
|
|
||||||
for (let h = 0; h < hitN; h++) totalNv += calcAttack(c.damage || 0, pStr, pWeak, 0);
|
|
||||||
let dmg = totalNv; // 통계 보고용 (aoe는 1대상 기준)
|
|
||||||
if (c.aoe === true) {
|
|
||||||
// 전체 공격 — 대상마다 취약/방어 개별 적용 (Lua PlayAoeFx 동기화)
|
|
||||||
for (const m2 of aliveList()) {
|
|
||||||
const d2 = m2.vuln > 0 ? Math.floor(totalNv * 1.5) : totalNv;
|
|
||||||
const r2 = applyDamage(m2.hp, m2.block, d2);
|
|
||||||
m2.hp = r2.hp; m2.block = r2.block;
|
|
||||||
if (m2.hp <= 0) m2.alive = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dmg = target.vuln > 0 ? Math.floor(totalNv * 1.5) : totalNv;
|
|
||||||
if (c.pierce === true) {
|
|
||||||
target.hp -= dmg; // 방어 무시
|
|
||||||
if (target.hp < 0) target.hp = 0;
|
|
||||||
} else {
|
|
||||||
const r = applyDamage(target.hp, target.block, dmg);
|
|
||||||
target.hp = r.hp; target.block = r.block;
|
|
||||||
}
|
|
||||||
if (target.hp <= 0) target.alive = false;
|
|
||||||
}
|
|
||||||
if (c.block) pBlock += c.block;
|
|
||||||
if (c.strength) pStr += c.strength;
|
|
||||||
if (c.selfVuln) pVuln += c.selfVuln;
|
|
||||||
if (c.heal) pHp = Math.min(pHp + c.heal, PLAYER_HP);
|
|
||||||
if (stats) stats[id] = bump(stats[id], c.cost, dmg, c.block || 0);
|
|
||||||
} else if (c.kind === 'Power') {
|
|
||||||
if (c.powerEffect) powers.push(id);
|
|
||||||
if (stats) stats[id] = bump(stats[id], c.cost, 0, 0);
|
|
||||||
} else {
|
|
||||||
pBlock += c.block || 0;
|
|
||||||
if (c.strength) pStr += c.strength;
|
|
||||||
if (c.selfVuln) pVuln += c.selfVuln;
|
|
||||||
if (c.heal) pHp = Math.min(pHp + c.heal, PLAYER_HP);
|
|
||||||
if (c.weak || c.vuln || c.poison) {
|
|
||||||
const target = chooseTarget(alive, 0);
|
|
||||||
if (c.weak) target.weak += c.weak;
|
|
||||||
if (c.vuln) target.vuln += c.vuln;
|
|
||||||
if (c.poison) target.poison += c.poison;
|
|
||||||
}
|
|
||||||
if (stats) stats[id] = bump(stats[id], c.cost, 0, c.block || 0);
|
|
||||||
}
|
|
||||||
hand.splice(idx, 1);
|
hand.splice(idx, 1);
|
||||||
if (c.kind !== 'Power') discard.push(id); // 파워는 소멸 — Lua 동기화
|
if (c.kind !== 'Power') discard.push(id);
|
||||||
if (c.draw) draw(c.draw);
|
applyDiscardEffects(c);
|
||||||
if (aliveList().length === 0) return { win: true, turns, playerHpRemaining: pHp };
|
if (aliveList().length === 0) return { win: true, turns, playerHpRemaining: pHp };
|
||||||
}
|
}
|
||||||
// 화상(endTurnDamage) — 손패에 있으면 턴 종료 시 피해 (Lua EndPlayerTurn 동기화)
|
// 화상(endTurnDamage) — 손패에 있으면 턴 종료 시 피해 (Lua EndPlayerTurn 동기화)
|
||||||
|
|||||||
@@ -375,3 +375,18 @@ test('simulateCombat: endTurnDamage(화상)이 턴 종료 시 누적 피해', ()
|
|||||||
assert.equal(r.win, false);
|
assert.equal(r.win, false);
|
||||||
assert.notEqual(r.draw, true);
|
assert.notEqual(r.draw, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("simulateCombat: sly discarded card resolves for free", () => {
|
||||||
|
const data = {
|
||||||
|
cards: {
|
||||||
|
Toss: { name: "Toss", cost: 1, kind: "Skill", discardAll: true },
|
||||||
|
SlyHit: { name: "SlyHit", cost: 99, kind: "Attack", damage: 10, sly: true },
|
||||||
|
Blank: { name: "Blank", cost: 99, kind: "Skill", block: 0 },
|
||||||
|
},
|
||||||
|
starterDeck: ["Toss", "SlyHit", "Blank", "Blank", "Blank"],
|
||||||
|
monsters: [{ name: "Dummy", maxHp: 10, intents: [{ kind: "Defend", value: 0 }] }],
|
||||||
|
};
|
||||||
|
const r = simulateCombat(data, mulberry32(1));
|
||||||
|
assert.equal(r.win, true);
|
||||||
|
assert.equal(r.turns, 1);
|
||||||
|
});
|
||||||
|
|||||||
@@ -149,6 +149,9 @@ function luaCardsTable(cards) {
|
|||||||
if (c.draw != null) fields.push(`draw = ${c.draw}`);
|
if (c.draw != null) fields.push(`draw = ${c.draw}`);
|
||||||
if (c.heal != null) fields.push(`heal = ${c.heal}`);
|
if (c.heal != null) fields.push(`heal = ${c.heal}`);
|
||||||
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.discardAll === true) fields.push('discardAll = true');
|
||||||
|
if (c.sly === true) fields.push('sly = true');
|
||||||
if (c.aoe === true) fields.push('aoe = true');
|
if (c.aoe === true) fields.push('aoe = true');
|
||||||
if (c.unplayable === true) fields.push('unplayable = true');
|
if (c.unplayable === true) fields.push('unplayable = true');
|
||||||
if (c.curse === true) fields.push('curse = true');
|
if (c.curse === true) fields.push('curse = true');
|
||||||
@@ -3690,6 +3693,7 @@ for i = 1, amount do
|
|||||||
\tlocal cardId = table.remove(self.DrawPile)
|
\tlocal cardId = table.remove(self.DrawPile)
|
||||||
\tif #self.Hand >= 10 then
|
\tif #self.Hand >= 10 then
|
||||||
\t\ttable.insert(self.DiscardPile, cardId)
|
\t\ttable.insert(self.DiscardPile, cardId)
|
||||||
|
\t\tself:TriggerSly(cardId)
|
||||||
\telse
|
\telse
|
||||||
\t\ttable.insert(self.Hand, cardId)
|
\t\ttable.insert(self.Hand, cardId)
|
||||||
\t\tif #self.Hand <= 5 then
|
\t\tif #self.Hand <= 5 then
|
||||||
@@ -4139,6 +4143,106 @@ if dmg < 0 then
|
|||||||
dmg = 0
|
dmg = 0
|
||||||
end
|
end
|
||||||
return dmg`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'base' }], 0, 'number'),
|
return dmg`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'base' }], 0, 'number'),
|
||||||
|
method('ResolveCardEffects', `if c == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if c.kind == "Attack" then
|
||||||
|
if c.damage ~= nil then
|
||||||
|
self:PlayerAttackMotion()
|
||||||
|
local total = 0
|
||||||
|
local hitN = c.hits or 1
|
||||||
|
for h = 1, hitN do
|
||||||
|
total = total + self:CalcPlayerAttack(c.damage)
|
||||||
|
end
|
||||||
|
if c.aoe == true then
|
||||||
|
self:PlayAoeFx(c.fx or c.image, total)
|
||||||
|
else
|
||||||
|
self:PlayAttackFx(self.TargetIndex, c.fx or c.image, total, c.pierce == true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if c.block ~= nil then
|
||||||
|
self.PlayerBlock = self.PlayerBlock + c.block
|
||||||
|
end
|
||||||
|
if free ~= true then
|
||||||
|
self:ApplyRelics("cardPlayed")
|
||||||
|
end
|
||||||
|
elseif c.kind == "Skill" then
|
||||||
|
if c.block ~= nil then
|
||||||
|
self.PlayerBlock = self.PlayerBlock + c.block
|
||||||
|
end
|
||||||
|
elseif c.kind == "Power" then
|
||||||
|
if c.powerEffect ~= nil and free ~= true then
|
||||||
|
table.insert(self.PlayerPowers, cardId)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if c.strength ~= nil then
|
||||||
|
self.PlayerStr = self.PlayerStr + c.strength
|
||||||
|
end
|
||||||
|
if c.selfVuln ~= nil then
|
||||||
|
self.PlayerVuln = self.PlayerVuln + c.selfVuln
|
||||||
|
end
|
||||||
|
if c.heal ~= nil then
|
||||||
|
self.PlayerHp = math.min(self.PlayerHp + c.heal, self.PlayerMaxHp)
|
||||||
|
end
|
||||||
|
if c.weak ~= nil or c.vuln ~= nil or c.poison ~= nil then
|
||||||
|
local tm = self.Monsters[self.TargetIndex]
|
||||||
|
if tm == nil or tm.alive ~= true then
|
||||||
|
for i = 1, #self.Monsters do
|
||||||
|
if self.Monsters[i].alive == true then tm = self.Monsters[i]; self.TargetIndex = i; break end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if tm ~= nil and tm.alive == true then
|
||||||
|
if c.weak ~= nil then tm.weak = tm.weak + c.weak end
|
||||||
|
if c.poison ~= nil then tm.poison = (tm.poison or 0) + c.poison end
|
||||||
|
if c.vuln ~= nil then
|
||||||
|
tm.vuln = tm.vuln + c.vuln
|
||||||
|
if self:HasRelic("championBelt") then
|
||||||
|
tm.weak = tm.weak + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if c.draw ~= nil then
|
||||||
|
self:DrawCards(c.draw, true)
|
||||||
|
end`, [
|
||||||
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
||||||
|
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' },
|
||||||
|
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'free' },
|
||||||
|
]),
|
||||||
|
method('TriggerSly', `local c = self.Cards[cardId]
|
||||||
|
if c == nil or c.sly ~= true then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self:Toast("교활 발동: " .. c.name)
|
||||||
|
self:ResolveCardEffects(cardId, c, true)`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' }]),
|
||||||
|
method('DiscardHandCard', `if self.Hand == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local cardId = self.Hand[slot]
|
||||||
|
if cardId == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
table.remove(self.Hand, slot)
|
||||||
|
table.insert(self.DiscardPile, cardId)
|
||||||
|
if triggerSly == true then
|
||||||
|
self:TriggerSly(cardId)
|
||||||
|
end`, [
|
||||||
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||||
|
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'triggerSly' },
|
||||||
|
]),
|
||||||
|
method('DiscardCardEffects', `if c == nil or self.Hand == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if c.discardAll == true then
|
||||||
|
while #self.Hand > 0 do
|
||||||
|
self:DiscardHandCard(#self.Hand, true)
|
||||||
|
end
|
||||||
|
elseif c.discard ~= nil then
|
||||||
|
local n = math.min(c.discard, #self.Hand)
|
||||||
|
for i = 1, n do
|
||||||
|
self:DiscardHandCard(#self.Hand, true)
|
||||||
|
end
|
||||||
|
end`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }]),
|
||||||
method('PlayCard', `if self.CombatOver == true or self.FxBusy == true or self.TurnBusy == true then
|
method('PlayCard', `if self.CombatOver == true or self.FxBusy == true or self.TurnBusy == true then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -4162,62 +4266,12 @@ if self.Energy < c.cost then
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
self.Energy = self.Energy - c.cost
|
self.Energy = self.Energy - c.cost
|
||||||
if c.kind == "Attack" then
|
self:ResolveCardEffects(cardId, c, false)
|
||||||
if c.damage ~= nil then
|
|
||||||
self:PlayerAttackMotion()
|
|
||||||
local total = 0
|
|
||||||
local hitN = c.hits or 1
|
|
||||||
for h = 1, hitN do
|
|
||||||
total = total + self:CalcPlayerAttack(c.damage)
|
|
||||||
end
|
|
||||||
if c.aoe == true then
|
|
||||||
self:PlayAoeFx(c.fx or c.image, total)
|
|
||||||
else
|
|
||||||
self:PlayAttackFx(self.TargetIndex, c.fx or c.image, total, c.pierce == true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if c.block ~= nil then
|
|
||||||
self.PlayerBlock = self.PlayerBlock + c.block
|
|
||||||
end
|
|
||||||
self:ApplyRelics("cardPlayed")
|
|
||||||
elseif c.kind == "Skill" then
|
|
||||||
if c.block ~= nil then
|
|
||||||
self.PlayerBlock = self.PlayerBlock + c.block
|
|
||||||
end
|
|
||||||
elseif c.kind == "Power" then
|
|
||||||
if c.powerEffect ~= nil then
|
|
||||||
table.insert(self.PlayerPowers, cardId)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if c.strength ~= nil then
|
|
||||||
self.PlayerStr = self.PlayerStr + c.strength
|
|
||||||
end
|
|
||||||
if c.selfVuln ~= nil then
|
|
||||||
self.PlayerVuln = self.PlayerVuln + c.selfVuln
|
|
||||||
end
|
|
||||||
if c.heal ~= nil then
|
|
||||||
self.PlayerHp = math.min(self.PlayerHp + c.heal, self.PlayerMaxHp)
|
|
||||||
end
|
|
||||||
if c.weak ~= nil or c.vuln ~= nil or c.poison ~= nil then
|
|
||||||
local tm = self.Monsters[self.TargetIndex]
|
|
||||||
if tm ~= nil and tm.alive == true then
|
|
||||||
if c.weak ~= nil then tm.weak = tm.weak + c.weak end
|
|
||||||
if c.poison ~= nil then tm.poison = (tm.poison or 0) + c.poison end
|
|
||||||
if c.vuln ~= nil then
|
|
||||||
tm.vuln = tm.vuln + c.vuln
|
|
||||||
if self:HasRelic("championBelt") then
|
|
||||||
tm.weak = tm.weak + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
table.remove(self.Hand, slot)
|
table.remove(self.Hand, slot)
|
||||||
if c.kind ~= "Power" then
|
if c.kind ~= "Power" then
|
||||||
table.insert(self.DiscardPile, cardId)
|
table.insert(self.DiscardPile, cardId)
|
||||||
end
|
end
|
||||||
if c.draw ~= nil then
|
self:DiscardCardEffects(c)
|
||||||
self:DrawCards(c.draw, true)
|
|
||||||
end
|
|
||||||
self:RenderHand(false)
|
self:RenderHand(false)
|
||||||
self:RenderPiles()
|
self:RenderPiles()
|
||||||
self:RenderCombat()
|
self:RenderCombat()
|
||||||
|
|||||||
Reference in New Issue
Block a user