Add shared bandit effect hooks
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// AI 전투 밸런스 시뮬레이터 — 오프라인 몬테카를로.
|
||||
// AI 전투 밸런스 시뮬레이터 — 오프라인 몬테카를로.
|
||||
// ⚠️ 전투 규칙은 tools/deck/gen-slaydeck.mjs 의 Lua(SlayDeckController)와 동기화 유지할 것.
|
||||
// (데이터는 data/*.json 공유, 규칙 로직은 JS로 중복 재현)
|
||||
import { readFileSync } from 'node:fs';
|
||||
@@ -159,6 +159,10 @@ export function simulateCombat(data, rng, stats) {
|
||||
let nextTurnAttackMultiplier = 1, turnAttackMultiplier = 1;
|
||||
let nextTurnAddCards = [];
|
||||
let turnAttackCardsPlayed = 0, turnDiscardedCards = 0;
|
||||
let shivFirstDamageBonusUsed = false;
|
||||
let drawDamageThisTurn = 0;
|
||||
let drawPoisonThisTurn = 0;
|
||||
let shivAoeThisCombat = false;
|
||||
let cardsDrawnThisCombat = 0;
|
||||
let bonusRewardScreens = 0;
|
||||
let activeKillReward = 0;
|
||||
@@ -179,6 +183,23 @@ export function simulateCombat(data, rng, stats) {
|
||||
const card = drawPile.pop();
|
||||
drawn.push(card);
|
||||
cardsDrawnThisCombat++;
|
||||
const drawDamage = powerFieldTotal('drawDamage') + drawDamageThisTurn;
|
||||
const drawPoison = powerFieldTotal('drawPoison') + drawPoisonThisTurn;
|
||||
if ((drawDamage > 0 || drawPoison > 0) && mob.some((m) => m.alive)) {
|
||||
for (const m of mob) {
|
||||
if (!m.alive) continue;
|
||||
let dmg = drawDamage;
|
||||
if (m.vuln > 0) dmg = Math.floor(dmg * 1.5);
|
||||
if (m.block > 0) {
|
||||
const absorbed = Math.min(m.block, dmg);
|
||||
m.block -= absorbed;
|
||||
dmg -= absorbed;
|
||||
}
|
||||
if (drawPoison > 0) m.poison += drawPoison;
|
||||
if (dmg > 0) m.hp -= dmg;
|
||||
if (m.hp <= 0) { m.hp = 0; m.alive = false; }
|
||||
}
|
||||
}
|
||||
// 손패 10장 상한 — 초과 드로는 자동 버림 (Lua DrawCards 동기화)
|
||||
if (hand.length >= 10) {
|
||||
discard.push(card);
|
||||
@@ -236,6 +257,10 @@ export function simulateCombat(data, rng, stats) {
|
||||
if (c.damagePerDiscardedThisTurn) base += turnDiscardedCards * c.damagePerDiscardedThisTurn;
|
||||
if (c.damagePerSkillInHand) base += countOtherHandSkills(id) * c.damagePerSkillInHand;
|
||||
if (c.damagePerCardDrawnThisCombat) base += cardsDrawnThisCombat * c.damagePerCardDrawnThisCombat;
|
||||
if (c.class === 'shiv') {
|
||||
if (powerFieldTotal('shivDamageBonus') > 0) base += powerFieldTotal('shivDamageBonus');
|
||||
if (!shivFirstDamageBonusUsed && powerFieldTotal('firstShivDamageBonus') > 0) base += powerFieldTotal('firstShivDamageBonus');
|
||||
}
|
||||
if (base < 0) base = 0;
|
||||
return base;
|
||||
}
|
||||
@@ -286,6 +311,9 @@ export function simulateCombat(data, rng, stats) {
|
||||
if (c.skillCostReductionThisTurn && c.skillCostReductionThisTurn > 0) skillCostReductionThisTurn += c.skillCostReductionThisTurn;
|
||||
if (c.handCostZeroThisTurn === true) handCostZeroThisTurn = true;
|
||||
if (c.drawDisabledThisTurn === true) drawDisabledThisTurn = true;
|
||||
if (c.drawDamage && c.kind !== 'Power') drawDamageThisTurn += c.drawDamage;
|
||||
if (c.drawPoison && c.kind !== 'Power') drawPoisonThisTurn += c.drawPoison;
|
||||
if (c.shivAoe === true && c.kind !== 'Power') shivAoeThisCombat = true;
|
||||
const xEnergy = costSpent || 0;
|
||||
if (c.kind === 'Attack') {
|
||||
if (alive.length && (c.damage || c.xDamagePerEnergy)) {
|
||||
@@ -300,9 +328,14 @@ export function simulateCombat(data, rng, stats) {
|
||||
let totalNv = 0;
|
||||
for (let h = 0; h < hitN; h++) totalNv += calcAttack(baseDamage || 0, pStr, pWeak, 0) * turnAttackMultiplier;
|
||||
dmg = totalNv;
|
||||
if (c.aoe === true) {
|
||||
let useAoe = c.aoe === true;
|
||||
if (c.class === 'shiv' && shivAoeThisCombat === true) useAoe = true;
|
||||
if (useAoe === true) {
|
||||
for (const m2 of aliveList()) {
|
||||
const d2 = m2.vuln > 0 ? Math.floor(totalNv * 1.5) : totalNv;
|
||||
let d2 = m2.vuln > 0 ? Math.floor(totalNv * 1.5) : totalNv;
|
||||
if (m2.weak > 0 && c.attackDamageVsWeakMultiplier && c.attackDamageVsWeakMultiplier > 1) {
|
||||
d2 = Math.floor(d2 * c.attackDamageVsWeakMultiplier);
|
||||
}
|
||||
const r2 = applyDamage(m2.hp, m2.block, d2);
|
||||
m2.hp = r2.hp; m2.block = r2.block;
|
||||
const attackPoison = powerFieldTotal('attackPoison');
|
||||
@@ -314,6 +347,9 @@ export function simulateCombat(data, rng, stats) {
|
||||
}
|
||||
} else {
|
||||
dmg = target.vuln > 0 ? Math.floor(totalNv * 1.5) : totalNv;
|
||||
if (target.weak > 0 && c.attackDamageVsWeakMultiplier && c.attackDamageVsWeakMultiplier > 1) {
|
||||
dmg = Math.floor(dmg * c.attackDamageVsWeakMultiplier);
|
||||
}
|
||||
if (c.pierce === true) {
|
||||
target.hp -= dmg;
|
||||
if (target.hp < 0) target.hp = 0;
|
||||
@@ -339,7 +375,18 @@ export function simulateCombat(data, rng, stats) {
|
||||
const target = chooseTarget(alive, 0);
|
||||
if (weakAmount) target.weak += weakAmount;
|
||||
if (c.vuln) target.vuln += c.vuln;
|
||||
if (c.poison) target.poison += c.poison;
|
||||
if (c.poison) {
|
||||
const poisonHits = c.poisonHits || 1;
|
||||
for (let i = 0; i < poisonHits; i++) {
|
||||
const target2 = c.poisonRandomTargets === true
|
||||
? alive[Math.floor(rng() * alive.length)]
|
||||
: target;
|
||||
if (target2) target2.poison += c.poison;
|
||||
}
|
||||
}
|
||||
if (c.class === 'shiv' && !shivFirstDamageBonusUsed && powerFieldTotal('firstShivDamageBonus') > 0) {
|
||||
shivFirstDamageBonusUsed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c.strength) pStr += c.strength;
|
||||
@@ -413,6 +460,10 @@ export function simulateCombat(data, rng, stats) {
|
||||
turns++;
|
||||
turnAttackCardsPlayed = 0;
|
||||
turnDiscardedCards = 0;
|
||||
shivFirstDamageBonusUsed = false;
|
||||
drawDamageThisTurn = 0;
|
||||
drawPoisonThisTurn = 0;
|
||||
shivAoeThisCombat = false;
|
||||
blockGainMultiplier = 1;
|
||||
handCostZeroThisTurn = false;
|
||||
drawDisabledThisTurn = false;
|
||||
@@ -530,7 +581,7 @@ export function simulateCombat(data, rng, stats) {
|
||||
const kept = [];
|
||||
for (const hid of hand) {
|
||||
const hc = cards[hid];
|
||||
if (hc?.retain === true) kept.push(hid);
|
||||
if (hc?.retain === true || (hc?.class === 'shiv' && powerFieldTotal('shivRetain') > 0)) kept.push(hid);
|
||||
else discard.push(hid);
|
||||
}
|
||||
hand = kept;
|
||||
|
||||
@@ -914,3 +914,38 @@ test("simulateCombat: damagePerCardDrawnThisCombat scales murder", () => {
|
||||
assert.equal(r.win, true);
|
||||
assert.ok(stats.Murder.damage > 1);
|
||||
});
|
||||
|
||||
test("simulateCombat: shiv damage bonuses stack and first Shiv bonus applies once per turn", () => {
|
||||
const data = {
|
||||
cards: {
|
||||
Accuracy: { name: "Accuracy", cost: 1, kind: "Power", shivDamageBonus: 2 },
|
||||
PhantomBlades: { name: "PhantomBlades", cost: 1, kind: "Power", firstShivDamageBonus: 3 },
|
||||
Shiv: { name: "Shiv", cost: 0, kind: "Attack", class: "shiv", damage: 1 },
|
||||
},
|
||||
starterDeck: ["Accuracy", "PhantomBlades", "Shiv"],
|
||||
monsters: [{ name: "Dummy", maxHp: 6, intents: [{ kind: "Attack", value: 0 }] }],
|
||||
};
|
||||
const r = simulateCombat(data, () => 0.999999);
|
||||
assert.equal(r.win, true);
|
||||
assert.equal(r.turns, 1);
|
||||
});
|
||||
|
||||
test("simulateCombat: shivAoe makes Shivs hit all enemies", () => {
|
||||
const data = {
|
||||
cards: {
|
||||
FanOfKnives: { name: "FanOfKnives", cost: 2, kind: "Skill", addShiv: 2, shivAoe: true },
|
||||
Accuracy: { name: "Accuracy", cost: 1, kind: "Power", shivDamageBonus: 2 },
|
||||
Shiv: { name: "Shiv", cost: 0, kind: "Attack", class: "shiv", damage: 1 },
|
||||
Pass: { name: "Pass", cost: 99, kind: "Skill" },
|
||||
},
|
||||
starterDeck: ["Accuracy", "FanOfKnives", "Pass"],
|
||||
monsters: [
|
||||
{ name: "A", maxHp: 3, intents: [{ kind: "Attack", value: 0 }] },
|
||||
{ name: "B", maxHp: 3, intents: [{ kind: "Attack", value: 0 }] },
|
||||
{ name: "C", maxHp: 3, intents: [{ kind: "Attack", value: 0 }] },
|
||||
],
|
||||
};
|
||||
const r = simulateCombat(data, () => 0.999999);
|
||||
assert.equal(r.win, true);
|
||||
assert.equal(r.turns, 1);
|
||||
});
|
||||
|
||||
@@ -271,6 +271,9 @@ local dmg = amount
|
||||
if m.vuln > 0 then
|
||||
dmg = math.floor(dmg * 1.5)
|
||||
end
|
||||
if m.weak > 0 and self.ActiveAttackDamageVsWeakMultiplier ~= nil and self.ActiveAttackDamageVsWeakMultiplier > 1 then
|
||||
dmg = math.floor(dmg * self.ActiveAttackDamageVsWeakMultiplier)
|
||||
end
|
||||
if m.block > 0 and pierce ~= true then
|
||||
local absorbed = math.min(m.block, dmg)
|
||||
m.block = m.block - absorbed
|
||||
@@ -345,6 +348,7 @@ return killed`, [
|
||||
method('PlayAttackFx', `local m = self.Monsters[targetIndex]
|
||||
if m == nil or m.alive ~= true or m.entity == nil or not isvalid(m.entity) then
|
||||
self:DealDamageToTarget(damage, pierce)
|
||||
self.ActiveAttackDamageVsWeakMultiplier = 1
|
||||
self:RenderCombat()
|
||||
self:CheckCombatEnd()
|
||||
return
|
||||
@@ -370,11 +374,15 @@ _TimerService:SetTimerOnce(function()
|
||||
if mt ~= nil and mt.alive == true and mt.vuln > 0 then
|
||||
shown = math.floor(damage * 1.5)
|
||||
end
|
||||
if mt ~= nil and mt.alive == true and mt.weak > 0 and self.ActiveAttackDamageVsWeakMultiplier ~= nil and self.ActiveAttackDamageVsWeakMultiplier > 1 then
|
||||
shown = math.floor(shown * self.ActiveAttackDamageVsWeakMultiplier)
|
||||
end
|
||||
local killed = self:DealDamageToTarget(damage, pierce)
|
||||
if killed == true and self.ActiveKillReward ~= nil and self.ActiveKillReward > 0 then
|
||||
self.BonusRewardScreens = (self.BonusRewardScreens or 0) + self.ActiveKillReward
|
||||
end
|
||||
self.ActiveKillReward = 0
|
||||
self.ActiveAttackDamageVsWeakMultiplier = 1
|
||||
self:ShowDmgPop(targetIndex, shown)
|
||||
self:RenderCombat()
|
||||
self:CheckCombatEnd()
|
||||
@@ -406,6 +414,9 @@ _TimerService:SetTimerOnce(function()
|
||||
if m.vuln > 0 then
|
||||
dmg = math.floor(dmg * 1.5)
|
||||
end
|
||||
if m.weak > 0 and self.ActiveAttackDamageVsWeakMultiplier ~= nil and self.ActiveAttackDamageVsWeakMultiplier > 1 then
|
||||
dmg = math.floor(dmg * self.ActiveAttackDamageVsWeakMultiplier)
|
||||
end
|
||||
if m.block > 0 then
|
||||
local absorbed = math.min(m.block, dmg)
|
||||
m.block = m.block - absorbed
|
||||
@@ -431,6 +442,7 @@ _TimerService:SetTimerOnce(function()
|
||||
self.BonusRewardScreens = (self.BonusRewardScreens or 0) + (killCount * self.ActiveKillReward)
|
||||
end
|
||||
self.ActiveKillReward = 0
|
||||
self.ActiveAttackDamageVsWeakMultiplier = 1
|
||||
self:RenderCombat()
|
||||
self:CheckCombatEnd()
|
||||
end, 0.35)`, [
|
||||
|
||||
@@ -247,6 +247,11 @@ end
|
||||
self.TurnAttackMultiplier = self.NextTurnAttackMultiplier or 1
|
||||
self.NextTurnAttackMultiplier = 1
|
||||
self.CardsDrawnThisCombat = self.CardsDrawnThisCombat or 0
|
||||
self.ShivFirstDamageBonusUsed = false
|
||||
self.ActiveAttackDamageVsWeakMultiplier = 1
|
||||
self.DrawDamageThisTurn = 0
|
||||
self.DrawPoisonThisTurn = 0
|
||||
self.ShivAoeThisCombat = false
|
||||
self.HandCostZeroThisTurn = false
|
||||
self.DrawDisabledThisTurn = false
|
||||
local powerTurnDraw = 0
|
||||
@@ -419,7 +424,7 @@ local kept = {}
|
||||
for i = 1, #self.Hand do
|
||||
\tlocal cardId = self.Hand[i]
|
||||
\tlocal c = self.Cards[cardId]
|
||||
\tif c ~= nil and (c.retain == true or i == retainSlot) then
|
||||
\tif c ~= nil and (c.retain == true or (c.class == "shiv" and self:HasPowerField("shivRetain") == true) or i == retainSlot) then
|
||||
\t\ttable.insert(kept, cardId)
|
||||
\telse
|
||||
\t\ttable.insert(self.DiscardPile, cardId)
|
||||
|
||||
@@ -311,6 +311,14 @@ end
|
||||
if c.damagePerCardDrawnThisCombat ~= nil then
|
||||
base2 = base2 + (self.CardsDrawnThisCombat or 0) * c.damagePerCardDrawnThisCombat
|
||||
end
|
||||
if c.class == "shiv" then
|
||||
if self:HasPowerField("shivDamageBonus") == true then
|
||||
base2 = base2 + self:AddPowerFieldTotal("shivDamageBonus")
|
||||
end
|
||||
if self.ShivFirstDamageBonusUsed ~= true and self:HasPowerField("firstShivDamageBonus") == true then
|
||||
base2 = base2 + self:AddPowerFieldTotal("firstShivDamageBonus")
|
||||
end
|
||||
end
|
||||
if base2 < 0 then
|
||||
base2 = 0
|
||||
end
|
||||
@@ -394,6 +402,15 @@ end
|
||||
if c.drawDisabledThisTurn == true then
|
||||
self.DrawDisabledThisTurn = true
|
||||
end
|
||||
if c.drawDamage ~= nil and c.drawDamage > 0 and c.kind ~= "Power" then
|
||||
self.DrawDamageThisTurn = (self.DrawDamageThisTurn or 0) + c.drawDamage
|
||||
end
|
||||
if c.drawPoison ~= nil and c.drawPoison > 0 and c.kind ~= "Power" then
|
||||
self.DrawPoisonThisTurn = (self.DrawPoisonThisTurn or 0) + c.drawPoison
|
||||
end
|
||||
if c.shivAoe == true and c.kind ~= "Power" then
|
||||
self.ShivAoeThisCombat = true
|
||||
end
|
||||
local xEnergy = energySpent or 0
|
||||
local weakAmount = c.weak or 0
|
||||
local vulnAmount = c.vuln or 0
|
||||
@@ -405,6 +422,7 @@ if c.kind == "Attack" then
|
||||
if c.damage ~= nil or c.xDamagePerEnergy ~= nil then
|
||||
self:PlayerAttackMotion()
|
||||
local baseDmg = self:AttackBaseForCard(slot, c)
|
||||
self.ActiveAttackDamageVsWeakMultiplier = c.attackDamageVsWeakMultiplier or 1
|
||||
if c.xDamagePerEnergy ~= nil and c.xDamagePerEnergy > 0 then
|
||||
baseDmg = xEnergy * c.xDamagePerEnergy
|
||||
end
|
||||
@@ -423,7 +441,14 @@ if c.kind == "Attack" then
|
||||
for h = 1, hitN do
|
||||
total = total + self:CalcPlayerAttack(baseDmg)
|
||||
end
|
||||
if c.aoe == true then
|
||||
local useAoe = c.aoe == true
|
||||
if c.class == "shiv" and (self.ShivAoeThisCombat == true or self:HasPowerField("shivAoe") == true) then
|
||||
useAoe = true
|
||||
end
|
||||
if c.class == "shiv" and self.ShivFirstDamageBonusUsed ~= true and self:HasPowerField("firstShivDamageBonus") == true then
|
||||
self.ShivFirstDamageBonusUsed = true
|
||||
end
|
||||
if useAoe == true then
|
||||
self:PlayAoeFx(c.fx or c.image, total)
|
||||
else
|
||||
self:PlayAttackFx(self.TargetIndex, c.fx or c.image, total, c.pierce == true)
|
||||
@@ -475,7 +500,27 @@ if c.weak ~= nil or c.vuln ~= nil or c.poison ~= nil or c.xWeakPerEnergy ~= nil
|
||||
end
|
||||
if tm ~= nil and tm.alive == true then
|
||||
if weakAmount ~= nil and weakAmount > 0 then tm.weak = tm.weak + weakAmount end
|
||||
if poisonAmount ~= nil and poisonAmount > 0 then tm.poison = (tm.poison or 0) + poisonAmount end
|
||||
if poisonAmount ~= nil and poisonAmount > 0 then
|
||||
local poisonHits = c.poisonHits or 1
|
||||
for pi = 1, poisonHits do
|
||||
local target = tm
|
||||
if c.poisonRandomTargets == true and self.Monsters ~= nil then
|
||||
local alive = {}
|
||||
for mi = 1, #self.Monsters do
|
||||
local om = self.Monsters[mi]
|
||||
if om ~= nil and om.alive == true then
|
||||
table.insert(alive, om)
|
||||
end
|
||||
end
|
||||
if #alive > 0 then
|
||||
target = alive[math.random(#alive)]
|
||||
end
|
||||
end
|
||||
if target ~= nil and target.alive == true then
|
||||
target.poison = (target.poison or 0) + poisonAmount
|
||||
end
|
||||
end
|
||||
end
|
||||
if vulnAmount ~= nil and vulnAmount > 0 then
|
||||
tm.vuln = tm.vuln + vulnAmount
|
||||
if self:HasRelic("championBelt") then
|
||||
@@ -512,6 +557,38 @@ if c.drawSkillBlock ~= nil and c.drawSkillBlock > 0 then
|
||||
end
|
||||
end
|
||||
end
|
||||
local drawDamage = self:AddPowerFieldTotal("drawDamage") + (self.DrawDamageThisTurn or 0)
|
||||
local drawPoison = self:AddPowerFieldTotal("drawPoison") + (self.DrawPoisonThisTurn or 0)
|
||||
if (drawDamage ~= nil and drawDamage > 0) or (drawPoison ~= nil and drawPoison > 0) then
|
||||
for mi = 1, #self.Monsters do
|
||||
local m2 = self.Monsters[mi]
|
||||
if m2 ~= nil and m2.alive == true then
|
||||
local dmg = drawDamage or 0
|
||||
if m2.vuln > 0 then
|
||||
dmg = math.floor(dmg * 1.5)
|
||||
end
|
||||
if m2.block > 0 then
|
||||
local absorbed = math.min(m2.block, dmg)
|
||||
m2.block = m2.block - absorbed
|
||||
dmg = dmg - absorbed
|
||||
end
|
||||
if drawPoison ~= nil and drawPoison > 0 then
|
||||
m2.poison = (m2.poison or 0) + drawPoison
|
||||
end
|
||||
if dmg > 0 then
|
||||
m2.hp = m2.hp - dmg
|
||||
end
|
||||
self:ShowDmgPop(mi, dmg)
|
||||
self:MonsterHitMotion(mi)
|
||||
if m2.hp <= 0 then
|
||||
m2.hp = 0
|
||||
self:KillMonster(m2.slot)
|
||||
end
|
||||
end
|
||||
end
|
||||
self:RenderCombat()
|
||||
self:CheckCombatEnd()
|
||||
end
|
||||
if c.addShiv ~= nil and c.discard == nil and c.discardAll ~= true then
|
||||
self:AddCardsToHand("Shiv", c.addShiv)
|
||||
end`, [
|
||||
|
||||
@@ -74,6 +74,11 @@ self.DrawDisabledThisTurn = false
|
||||
self.NextSkillCostZero = false
|
||||
self.NextSkillRepeatCount = 0
|
||||
self.SkillCostReductionThisTurn = 0
|
||||
self.ShivFirstDamageBonusUsed = false
|
||||
self.ActiveAttackDamageVsWeakMultiplier = 1
|
||||
self.DrawDamageThisTurn = 0
|
||||
self.DrawPoisonThisTurn = 0
|
||||
self.ShivAoeThisCombat = false
|
||||
self.PlayerStr = 0
|
||||
self.PlayerDex = 0
|
||||
self.PlayerThorns = 0
|
||||
|
||||
@@ -192,6 +192,8 @@ function luaCardsTable(cards) {
|
||||
if (c.draw != null) fields.push(`draw = ${c.draw}`);
|
||||
if (c.drawUntilHandSize != null) fields.push(`drawUntilHandSize = ${c.drawUntilHandSize}`);
|
||||
if (c.drawSkillBlock != null) fields.push(`drawSkillBlock = ${c.drawSkillBlock}`);
|
||||
if (c.drawDamage != null) fields.push(`drawDamage = ${c.drawDamage}`);
|
||||
if (c.drawPoison != null) fields.push(`drawPoison = ${c.drawPoison}`);
|
||||
if (c.heal != null) fields.push(`heal = ${c.heal}`);
|
||||
if (c.gainEnergy != null) fields.push(`gainEnergy = ${c.gainEnergy}`);
|
||||
if (c.poison != null) fields.push(`poison = ${c.poison}`);
|
||||
@@ -206,6 +208,13 @@ function luaCardsTable(cards) {
|
||||
if (c.drawDisabledThisTurn === true) fields.push('drawDisabledThisTurn = true');
|
||||
if (c.addShivPerDiscard === true) fields.push('addShivPerDiscard = true');
|
||||
if (c.useAllEnergy === true) fields.push('useAllEnergy = true');
|
||||
if (c.shivDamageBonus != null) fields.push(`shivDamageBonus = ${c.shivDamageBonus}`);
|
||||
if (c.firstShivDamageBonus != null) fields.push(`firstShivDamageBonus = ${c.firstShivDamageBonus}`);
|
||||
if (c.shivRetain === true) fields.push('shivRetain = true');
|
||||
if (c.shivAoe === true) fields.push('shivAoe = true');
|
||||
if (c.attackDamageVsWeakMultiplier != null) fields.push(`attackDamageVsWeakMultiplier = ${c.attackDamageVsWeakMultiplier}`);
|
||||
if (c.poisonHits != null) fields.push(`poisonHits = ${c.poisonHits}`);
|
||||
if (c.poisonRandomTargets === true) fields.push('poisonRandomTargets = true');
|
||||
if (c.xDamagePerEnergy != null) fields.push(`xDamagePerEnergy = ${c.xDamagePerEnergy}`);
|
||||
if (c.xWeakPerEnergy != null) fields.push(`xWeakPerEnergy = ${c.xWeakPerEnergy}`);
|
||||
if (c.nextTurnBlock != null) fields.push(`nextTurnBlock = ${c.nextTurnBlock}`);
|
||||
|
||||
Reference in New Issue
Block a user