Compare commits
3 Commits
926733dbef
...
222ed92807
| Author | SHA1 | Date | |
|---|---|---|---|
| 222ed92807 | |||
| 72750f3647 | |||
| 1291c52346 |
@@ -3666,7 +3666,7 @@
|
||||
"Name": "amount"
|
||||
}
|
||||
],
|
||||
"Code": "if self.Monsters == nil then\n\treturn false\nend\nlocal killCount = 0\nfor i = 1, #self.Monsters do\n\tlocal m = self.Monsters[i]\n\tif m ~= nil and m.alive == true then\n\t\tlocal dmg = amount\n\t\tif m.vuln > 0 then\n\t\t\tdmg = math.floor(dmg * 1.5)\n\t\tend\n\t\tif m.block > 0 then\n\t\t\tlocal absorbed = math.min(m.block, dmg)\n\t\t\tm.block = m.block - absorbed\n\t\t\tdmg = dmg - absorbed\n\t\tend\n\t\tm.hp = m.hp - dmg\n\t\tif dmg > 0 then\n\t\t\tself.DamageDealtThisTurn = (self.DamageDealtThisTurn or 0) + dmg\n\t\tend\n\t\tself:ShowDmgPop(i, dmg)\n\t\tself:MonsterHitMotion(i)\n\t\tif m.hp <= 0 then\n\t\t\tm.hp = 0\n\t\t\tself:KillMonster(m.slot)\n\t\t\tkillCount = killCount + 1\n\t\tend\n\tend\nend\nif killCount > 0 and self.ActiveKillReward ~= nil and self.ActiveKillReward > 0 then\n\tself.BonusRewardScreens = (self.BonusRewardScreens or 0) + (killCount * self.ActiveKillReward)\nend\nself:RenderCombat()\nself:CheckCombatEnd()\nreturn killCount > 0",
|
||||
"Code": "if self.Monsters == nil then\n\treturn false\nend\nlocal killCount = 0\nfor i = 1, #self.Monsters do\n\tlocal m = self.Monsters[i]\n\tif m ~= nil and m.alive == true then\n\t\tlocal dmg = amount\n\t\tif m.vuln > 0 then\n\t\t\tdmg = math.floor(dmg * 1.5)\n\t\tend\n\t\tif m.block > 0 then\n\t\t\tlocal absorbed = math.min(m.block, dmg)\n\t\t\tm.block = m.block - absorbed\n\t\t\tdmg = dmg - absorbed\n\t\tend\n\t\tm.hp = m.hp - dmg\n\t\tif dmg > 0 then\n\t\t\tself.DamageDealtThisTurn = (self.DamageDealtThisTurn or 0) + dmg\n\t\t\tlocal poison = self:AddPowerFieldTotal(\"attackPoison\")\n\t\t\tif poison ~= nil and poison > 0 then\n\t\t\t\tself:ApplyPoisonToMonster(m, poison)\n\t\t\tend\n\t\tend\n\t\tself:ShowDmgPop(i, dmg)\n\t\tself:MonsterHitMotion(i)\n\t\tif m.hp <= 0 then\n\t\t\tm.hp = 0\n\t\t\tself:KillMonster(m.slot)\n\t\t\tkillCount = killCount + 1\n\t\tend\n\tend\nend\nif killCount > 0 and self.ActiveKillReward ~= nil and self.ActiveKillReward > 0 then\n\tself.BonusRewardScreens = (self.BonusRewardScreens or 0) + (killCount * self.ActiveKillReward)\nend\nself:RenderCombat()\nself:CheckCombatEnd()\nreturn killCount > 0",
|
||||
"Scope": 2,
|
||||
"ExecSpace": 6,
|
||||
"Attributes": [],
|
||||
|
||||
@@ -55,7 +55,8 @@ export function calcAttack(base, str, weak, vulnOnTarget) {
|
||||
}
|
||||
|
||||
export function calcEnemyAttack(base, str, weak, vulnOnTarget, strengthLoss = 0) {
|
||||
return calcAttack(base, Math.max(0, str - strengthLoss), weak, vulnOnTarget);
|
||||
// Lua EnemyActStep 동기화: 힘 손실은 (value+str) 전체에서 차감(음수 힘 허용), 최종 calcAttack이 0 클램프.
|
||||
return calcAttack(base, str - strengthLoss, weak, vulnOnTarget);
|
||||
}
|
||||
|
||||
// 방어 우선 차감 후 hp 적용 → { hp, block }
|
||||
@@ -422,6 +423,9 @@ export function simulateCombat(data, rng, stats) {
|
||||
const hitN = (c.hits || 1) + bonusHits;
|
||||
let useAoe = c.aoe === true;
|
||||
if (c.class === 'shiv' && shivAoeThisCombat === true) useAoe = true;
|
||||
if (c.class === 'shiv' && !shivFirstDamageBonusUsed && powerFieldTotal('firstShivDamageBonus') > 0) {
|
||||
shivFirstDamageBonusUsed = true;
|
||||
}
|
||||
const perHit = calcAttack(baseDamage || 0, pStr, pWeak, 0) * turnAttackMultiplier;
|
||||
const dealToTarget = (target, amount) => {
|
||||
if (!target || !target.alive) return { killed: false, dealt: 0 };
|
||||
@@ -515,9 +519,6 @@ export function simulateCombat(data, rng, stats) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c.class === 'shiv' && !shivFirstDamageBonusUsed && powerFieldTotal('firstShivDamageBonus') > 0) {
|
||||
shivFirstDamageBonusUsed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c.strength) pStr += c.strength;
|
||||
@@ -721,7 +722,7 @@ export function simulateCombat(data, rng, stats) {
|
||||
const it = m.intents.length ? m.intents[Math.floor(rng() * m.intents.length)] : null;
|
||||
if (it) {
|
||||
if (it.kind === 'Attack') {
|
||||
const atk = calcAttack(it.value, Math.max(0, m.str - enemyStrengthLossThisTurn), m.weak, pVuln);
|
||||
const atk = calcEnemyAttack(it.value, m.str, m.weak, pVuln, enemyStrengthLossThisTurn);
|
||||
const beforeHp = pHp;
|
||||
let incoming = atk;
|
||||
if (pIntangible > 0 && incoming > 1) incoming = 1;
|
||||
|
||||
@@ -895,6 +895,29 @@ test("calcEnemyAttack: enemyStrengthLossThisTurn reduces enemy attack damage", (
|
||||
assert.equal(calcEnemyAttack(10, 6, 0, 0, 0), 16);
|
||||
});
|
||||
|
||||
test("calcEnemyAttack: 힘 손실이 base 아래로 공격을 낮춘다 (음수 힘, Lua 동기화)", () => {
|
||||
// 적 str=0, loss=6 → 힘 -6 → 10-6=4. JS가 str을 0에서 클램프하면 10(버그). Lua는 전체에서 차감.
|
||||
assert.equal(calcEnemyAttack(10, 0, 0, 0, 6), 4);
|
||||
assert.equal(calcEnemyAttack(10, 3, 0, 0, 6), 7);
|
||||
assert.equal(calcEnemyAttack(5, 0, 0, 0, 6), 0); // 5-6=-1 → 0 클램프
|
||||
});
|
||||
|
||||
test('simulateCombat: firstShivDamageBonus는 턴당 첫 Shiv에만 적용 (Lua 동기화)', () => {
|
||||
// PhantomBlades(firstShivDamageBonus 9) 활성. 턴당 3 Shiv 사용(에너지3·cost1).
|
||||
// 정답(첫 Shiv만 +9): 턴1 = 10+1+1=12 → 13HP에 1 남김 → 2턴.
|
||||
// 버그(모든 Shiv +9): 턴1 = 10*3=30 → 1턴.
|
||||
const data = {
|
||||
cards: {
|
||||
PhantomBlades: { name: '환영검', cost: 0, kind: 'Power', firstShivDamageBonus: 9 },
|
||||
Shiv: { name: '시브', cost: 1, kind: 'Attack', class: 'shiv', damage: 1 },
|
||||
},
|
||||
starterDeck: ['PhantomBlades', 'Shiv', 'Shiv', 'Shiv', 'Shiv'],
|
||||
monsters: [{ name: '적', maxHp: 13, intents: [{ kind: 'Attack', value: 0 }] }],
|
||||
};
|
||||
const r = simulateCombat(data, mulberry32(1));
|
||||
assert.equal(r.turns, 2);
|
||||
});
|
||||
|
||||
test("simulateCombat: repeatOnKill repeats an attack until no kill occurs", () => {
|
||||
const shared = {
|
||||
cards: {
|
||||
|
||||
@@ -392,6 +392,10 @@ for i = 1, #self.Monsters do
|
||||
m.hp = m.hp - dmg
|
||||
if dmg > 0 then
|
||||
self.DamageDealtThisTurn = (self.DamageDealtThisTurn or 0) + dmg
|
||||
local poison = self:AddPowerFieldTotal("attackPoison")
|
||||
if poison ~= nil and poison > 0 then
|
||||
self:ApplyPoisonToMonster(m, poison)
|
||||
end
|
||||
end
|
||||
self:ShowDmgPop(i, dmg)
|
||||
self:MonsterHitMotion(i)
|
||||
|
||||
Reference in New Issue
Block a user