Compare commits
3 Commits
b4a4560678
...
926733dbef
| Author | SHA1 | Date | |
|---|---|---|---|
| 926733dbef | |||
| d7813f9912 | |||
| e6f351420b |
File diff suppressed because one or more lines are too long
@@ -342,7 +342,7 @@ export function simulateCombat(data, rng, stats) {
|
|||||||
if (c.damagePerDiscardedThisTurn) base += turnDiscardedCards * c.damagePerDiscardedThisTurn;
|
if (c.damagePerDiscardedThisTurn) base += turnDiscardedCards * c.damagePerDiscardedThisTurn;
|
||||||
if (c.damagePerSkillInHand) base += countOtherHandSkills(id) * c.damagePerSkillInHand;
|
if (c.damagePerSkillInHand) base += countOtherHandSkills(id) * c.damagePerSkillInHand;
|
||||||
if (c.damagePerCardDrawnThisCombat) base += cardsDrawnThisCombat * c.damagePerCardDrawnThisCombat;
|
if (c.damagePerCardDrawnThisCombat) base += cardsDrawnThisCombat * c.damagePerCardDrawnThisCombat;
|
||||||
if (c.class === 'Attack' && turnCardsPlayedThisTurn === 0 && c.firstCardDamageBonus) base += c.firstCardDamageBonus;
|
if (c.kind === 'Attack' && turnCardsPlayedThisTurn === 0 && c.firstCardDamageBonus) base += c.firstCardDamageBonus;
|
||||||
if (c.class === 'shiv') {
|
if (c.class === 'shiv') {
|
||||||
if (powerFieldTotal('shivDamageBonus') > 0) base += powerFieldTotal('shivDamageBonus');
|
if (powerFieldTotal('shivDamageBonus') > 0) base += powerFieldTotal('shivDamageBonus');
|
||||||
if (!shivFirstDamageBonusUsed && powerFieldTotal('firstShivDamageBonus') > 0) base += powerFieldTotal('firstShivDamageBonus');
|
if (!shivFirstDamageBonusUsed && powerFieldTotal('firstShivDamageBonus') > 0) base += powerFieldTotal('firstShivDamageBonus');
|
||||||
|
|||||||
@@ -262,6 +262,19 @@ test('simulateCombat: 카드 취약 부여가 같은 카드 피해에 선적용
|
|||||||
assert.equal(r.turns, 1);
|
assert.equal(r.turns, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('simulateCombat: firstCardDamageBonus가 턴 첫 카드에 적용 (kind===Attack, Lua 동기화)', () => {
|
||||||
|
// ChargedBlow처럼 class=warrior·kind=Attack인 카드의 첫-카드 보너스.
|
||||||
|
// 게이트가 class==="Attack"이면 영구 false라 미발동(버그) → 5뎀/2턴.
|
||||||
|
// kind==="Attack"이면 5+2=7 → 1턴 처치.
|
||||||
|
const data = {
|
||||||
|
cards: { CB: { name: '차지블로우', cost: 3, kind: 'Attack', class: 'warrior', damage: 5, firstCardDamageBonus: 2 } },
|
||||||
|
starterDeck: ['CB', 'CB', 'CB', 'CB', 'CB'],
|
||||||
|
monsters: [{ name: '적', maxHp: 7, intents: [{ kind: 'Defend', value: 0 }] }],
|
||||||
|
};
|
||||||
|
const r = simulateCombat(data, mulberry32(1));
|
||||||
|
assert.equal(r.turns, 1);
|
||||||
|
});
|
||||||
|
|
||||||
test('simulateCombat: Power(매턴 힘) 누적', () => {
|
test('simulateCombat: Power(매턴 힘) 누적', () => {
|
||||||
const data = {
|
const data = {
|
||||||
cards: {
|
cards: {
|
||||||
|
|||||||
@@ -682,7 +682,10 @@ self.NextTurnAddCards = {}
|
|||||||
self:UpdateDiscardPrompt()
|
self:UpdateDiscardPrompt()
|
||||||
self:RenderHand(false)
|
self:RenderHand(false)
|
||||||
self:RenderPiles()`),
|
self:RenderPiles()`),
|
||||||
method('CheckCombatEnd', `local anyAlive = false
|
method('CheckCombatEnd', `if self.CombatOver == true then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local anyAlive = false
|
||||||
for i = 1, #self.Monsters do
|
for i = 1, #self.Monsters do
|
||||||
if self.Monsters[i].alive == true then anyAlive = true; break end
|
if self.Monsters[i].alive == true then anyAlive = true; break end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ for i = #list, 2, -1 do
|
|||||||
\tlocal j = math.random(1, i)
|
\tlocal j = math.random(1, i)
|
||||||
\tlist[i], list[j] = list[j], list[i]
|
\tlist[i], list[j] = list[j], list[i]
|
||||||
end`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'list' }]),
|
end`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'list' }]),
|
||||||
method('BindButtons', `local endTurn = _EntityService:GetEntityByPath("/ui/RunUIGroup/DeckHud/EndTurnButton")
|
method('BindButtons', `if self.ButtonsBound == true then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.ButtonsBound = true
|
||||||
|
local endTurn = _EntityService:GetEntityByPath("/ui/RunUIGroup/DeckHud/EndTurnButton")
|
||||||
if endTurn ~= nil and (endTurn.ButtonComponent ~= nil or endTurn:AddComponent("ButtonComponent") ~= nil) then
|
if endTurn ~= nil and (endTurn.ButtonComponent ~= nil or endTurn:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.EndTurnHandler ~= nil then
|
if self.EndTurnHandler ~= nil then
|
||||||
endTurn:DisconnectEvent(ButtonClickEvent, self.EndTurnHandler)
|
endTurn:DisconnectEvent(ButtonClickEvent, self.EndTurnHandler)
|
||||||
@@ -471,6 +475,7 @@ for i = 1, amount do
|
|||||||
\tlocal cardId = table.remove(self.DrawPile)
|
\tlocal cardId = table.remove(self.DrawPile)
|
||||||
\ttable.insert(drawnCards, cardId)
|
\ttable.insert(drawnCards, cardId)
|
||||||
\tself.CardsDrawnThisCombat = (self.CardsDrawnThisCombat or 0) + 1
|
\tself.CardsDrawnThisCombat = (self.CardsDrawnThisCombat or 0) + 1
|
||||||
|
\tself:ApplyDrawTrigger()
|
||||||
\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)
|
\t\tself:TriggerSly(cardId)
|
||||||
|
|||||||
@@ -3,6 +3,42 @@ import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, CARDFRAMES, RARITIES, MAP_
|
|||||||
import { UI_FILE, COMMON_FILE, UI_ROOT, GENERATED_UI_SECTIONS, UI_APPEND_ORDER, DISABLED_STOCK_CONTROLS, TRANSPARENT, DARK, GOLD, ATTACK, DEFEND, SKILL, DAMAGE_DIGIT_RUIDS, DAMAGE_POP_MAX_DIGITS, DAMAGE_POP_DIGIT_W, DAMAGE_POP_DIGIT_H, DAMAGE_POP_DIGIT_SPACING, MAX_MONSTERS, HEAD_OFFSET_Y, HP_BAR_W, WHITE, CARD_NAME_TEXT, CARD_DESC_TEXT, cardFaceLayout, CARD_W, CARD_H, CARD_SPACING, CARD_XS, ALIGN_CENTER, ALIGN_BOTTOM_CENTER, guid, transform, sprite, button, text, scrollLayoutGroup, popupLayerFor, uiOrderFor, displayOrderFor, applySortingOverride, entity, uiPath, sectionRoot, isGeneratedUiEntity, appendUiSection } from '../lib/ui-helpers.mjs';
|
import { UI_FILE, COMMON_FILE, UI_ROOT, GENERATED_UI_SECTIONS, UI_APPEND_ORDER, DISABLED_STOCK_CONTROLS, TRANSPARENT, DARK, GOLD, ATTACK, DEFEND, SKILL, DAMAGE_DIGIT_RUIDS, DAMAGE_POP_MAX_DIGITS, DAMAGE_POP_DIGIT_W, DAMAGE_POP_DIGIT_H, DAMAGE_POP_DIGIT_SPACING, MAX_MONSTERS, HEAD_OFFSET_Y, HP_BAR_W, WHITE, CARD_NAME_TEXT, CARD_DESC_TEXT, cardFaceLayout, CARD_W, CARD_H, CARD_SPACING, CARD_XS, ALIGN_CENTER, ALIGN_BOTTOM_CENTER, guid, transform, sprite, button, text, scrollLayoutGroup, popupLayerFor, uiOrderFor, displayOrderFor, applySortingOverride, entity, uiPath, sectionRoot, isGeneratedUiEntity, appendUiSection } from '../lib/ui-helpers.mjs';
|
||||||
|
|
||||||
export const handMethods = [
|
export const handMethods = [
|
||||||
|
method('ApplyDrawTrigger', `if self.Monsters == nil then
|
||||||
|
return
|
||||||
|
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
|
||||||
|
self:ApplyPoisonToMonster(m2, drawPoison)
|
||||||
|
end
|
||||||
|
if dmg > 0 then
|
||||||
|
m2.hp = m2.hp - dmg
|
||||||
|
self.DamageDealtThisTurn = (self.DamageDealtThisTurn or 0) + 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`),
|
||||||
method('GetHandSlotX', `local n = 0
|
method('GetHandSlotX', `local n = 0
|
||||||
if self.Hand ~= nil then
|
if self.Hand ~= nil then
|
||||||
n = #self.Hand
|
n = #self.Hand
|
||||||
@@ -311,7 +347,7 @@ end
|
|||||||
if c.damagePerCardDrawnThisCombat ~= nil then
|
if c.damagePerCardDrawnThisCombat ~= nil then
|
||||||
base2 = base2 + (self.CardsDrawnThisCombat or 0) * c.damagePerCardDrawnThisCombat
|
base2 = base2 + (self.CardsDrawnThisCombat or 0) * c.damagePerCardDrawnThisCombat
|
||||||
end
|
end
|
||||||
if c.class == "Attack" and (self.TurnCardsPlayedThisTurn or 0) == 0 and c.firstCardDamageBonus ~= nil then
|
if c.kind == "Attack" and (self.TurnCardsPlayedThisTurn or 0) == 0 and c.firstCardDamageBonus ~= nil then
|
||||||
base2 = base2 + c.firstCardDamageBonus
|
base2 = base2 + c.firstCardDamageBonus
|
||||||
end
|
end
|
||||||
if c.class == "shiv" then
|
if c.class == "shiv" then
|
||||||
@@ -681,39 +717,6 @@ if c.drawSkillBlock ~= nil and c.drawSkillBlock > 0 then
|
|||||||
end
|
end
|
||||||
end
|
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
|
|
||||||
self:ApplyPoisonToMonster(m2, drawPoison)
|
|
||||||
end
|
|
||||||
if dmg > 0 then
|
|
||||||
m2.hp = m2.hp - dmg
|
|
||||||
self.DamageDealtThisTurn = (self.DamageDealtThisTurn or 0) + 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
|
if c.addShiv ~= nil and c.discard == nil and c.discardAll ~= true then
|
||||||
self:AddCardsToHand("Shiv", c.addShiv)
|
self:AddCardsToHand("Shiv", c.addShiv)
|
||||||
end`, [
|
end`, [
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ function writeCodeblocks() {
|
|||||||
prop('any', 'AllDeckCloseHandler'),
|
prop('any', 'AllDeckCloseHandler'),
|
||||||
prop('number', 'SoulPoints', '0'),
|
prop('number', 'SoulPoints', '0'),
|
||||||
prop('boolean', 'LobbyBound', 'false'),
|
prop('boolean', 'LobbyBound', 'false'),
|
||||||
|
prop('boolean', 'ButtonsBound', 'false'),
|
||||||
prop('number', 'LobbyTpTries', '0'),
|
prop('number', 'LobbyTpTries', '0'),
|
||||||
prop('boolean', 'CodexMode', 'false'),
|
prop('boolean', 'CodexMode', 'false'),
|
||||||
prop('any', 'CodexCards'),
|
prop('any', 'CodexCards'),
|
||||||
|
|||||||
Reference in New Issue
Block a user