feat: P14 — 반복 런·로비·영혼·도적·몬스터 랜덤성 (요청 17항목) #52
File diff suppressed because one or more lines are too long
@@ -122,7 +122,9 @@ export function simulateCombat(data, rng, stats) {
|
||||
for (let k = 0; k < n; k++) {
|
||||
if (drawPile.length === 0) { drawPile = shuffle(discard, rng); discard = []; }
|
||||
if (drawPile.length === 0) break;
|
||||
hand.push(drawPile.pop());
|
||||
const card = drawPile.pop();
|
||||
// 손패 10장 상한 — 초과 드로는 자동 버림 (Lua DrawCards 동기화)
|
||||
if (hand.length >= 10) discard.push(card); else hand.push(card);
|
||||
}
|
||||
}
|
||||
const aliveList = () => mob.filter((m) => m.alive);
|
||||
|
||||
@@ -497,20 +497,39 @@ function upsertUi() {
|
||||
|
||||
// 카드 미리보기(초기 정적 표시 — 런타임 RenderHand가 덮어씀): 카드 종류를 순환해 다양성 표시
|
||||
const previewIds = Object.keys(CARDS.cards);
|
||||
const cards = Array.from({ length: 5 }, (_, i) => {
|
||||
const cards = Array.from({ length: 10 }, (_, i) => {
|
||||
const c = CARDS.cards[previewIds[i % previewIds.length]];
|
||||
return { name: c.name, cost: String(c.cost), desc: c.desc, frame: frameRuid(c) };
|
||||
});
|
||||
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
const card = byPath.get(`/ui/DefaultGroup/CardHand/Card${i}`);
|
||||
if (!card) continue;
|
||||
// 손패 슬롯 10개 (최대 손패 한도). Card1~5는 기존 엔티티, Card6~10은 신규 생성.
|
||||
for (let i = 1; i <= 10; i++) {
|
||||
const cardPath = `/ui/DefaultGroup/CardHand/Card${i}`;
|
||||
let card = byPath.get(cardPath);
|
||||
if (!card) {
|
||||
card = entity({
|
||||
id: guid('dck', 500 + i),
|
||||
path: cardPath,
|
||||
modelId: 'uisprite',
|
||||
entryId: 'UISprite',
|
||||
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent,MOD.Core.UITouchReceiveComponent',
|
||||
displayOrder: 4,
|
||||
components: [
|
||||
transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: CARD_W, y: CARD_H }, pos: { x: 0, y: 0 } }),
|
||||
sprite({ color: WHITE, type: 0, raycast: true }),
|
||||
button(),
|
||||
],
|
||||
});
|
||||
ui.ContentProto.Entities.push(card);
|
||||
byPath.set(cardPath, card);
|
||||
}
|
||||
const tr = card.jsonString['@components'].find((c) => c['@type'] === 'MOD.Core.UITransformComponent');
|
||||
const sp = card.jsonString['@components'].find((c) => c['@type'] === 'MOD.Core.SpriteGUIRendererComponent');
|
||||
const sx = -680 + (i - 1) * 150;
|
||||
tr.RectSize = { x: CARD_W, y: CARD_H };
|
||||
tr.anchoredPosition = { x: CARD_XS[i - 1], y: 0 };
|
||||
tr.OffsetMin = { x: CARD_XS[i - 1] - CARD_W / 2, y: -CARD_H / 2 };
|
||||
tr.OffsetMax = { x: CARD_XS[i - 1] + CARD_W / 2, y: CARD_H / 2 };
|
||||
tr.anchoredPosition = { x: sx, y: 0 };
|
||||
tr.OffsetMin = { x: sx - CARD_W / 2, y: -CARD_H / 2 };
|
||||
tr.OffsetMax = { x: sx + CARD_W / 2, y: CARD_H / 2 };
|
||||
sp.ImageRUID = { DataId: cards[i - 1].frame };
|
||||
sp.Type = 0;
|
||||
sp.Color = WHITE;
|
||||
@@ -2932,12 +2951,14 @@ if allDeckClose ~= nil and allDeckClose.ButtonComponent ~= nil then
|
||||
end
|
||||
self.AllDeckCloseHandler = allDeckClose:ConnectEvent(ButtonClickEvent, function() self:CloseAllDeck() end)
|
||||
end
|
||||
for i = 1, 5 do
|
||||
for i = 1, 10 do
|
||||
local cardEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(i))
|
||||
if cardEntity ~= nil and cardEntity.UITouchReceiveComponent ~= nil then
|
||||
cardEntity:ConnectEvent(UITouchBeginDragEvent, function(ev) self:OnCardDragBegin(i) end)
|
||||
cardEntity:ConnectEvent(UITouchDragEvent, function(ev) self:OnCardDrag(i, ev.TouchPoint) end)
|
||||
cardEntity:ConnectEvent(UITouchEndDragEvent, function(ev) self:OnCardDragEnd(i, ev.TouchPoint) end)
|
||||
cardEntity:ConnectEvent(UITouchEnterEvent, function() self:HoverCard(i) end)
|
||||
cardEntity:ConnectEvent(UITouchExitEvent, function() self:UnhoverCard(i) end)
|
||||
end
|
||||
end
|
||||
for i = 1, 3 do
|
||||
@@ -3116,7 +3137,11 @@ self:EnemyTurn()`),
|
||||
\t\tbreak
|
||||
\tend
|
||||
\tlocal cardId = table.remove(self.DrawPile)
|
||||
\ttable.insert(self.Hand, cardId)
|
||||
\tif #self.Hand >= 10 then
|
||||
\t\ttable.insert(self.DiscardPile, cardId)
|
||||
\telse
|
||||
\t\ttable.insert(self.Hand, cardId)
|
||||
\tend
|
||||
end
|
||||
self:RenderPiles()`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' }]),
|
||||
method('RecycleDiscardIntoDraw', `if self.DiscardPile == nil or #self.DiscardPile <= 0 then
|
||||
@@ -3236,8 +3261,12 @@ end`),
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
||||
]),
|
||||
method('RenderHand', `local drawStart = Vector2(-590, 8)
|
||||
for i = 1, 5 do
|
||||
method('RenderHand', `local n = #self.Hand
|
||||
local spacing = 175
|
||||
if n > 8 then spacing = math.floor(1400 / n) end
|
||||
local startX = -((n - 1) * spacing) / 2
|
||||
local drawStart = Vector2(-590, 8)
|
||||
for i = 1, 10 do
|
||||
\tlocal cardEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(i))
|
||||
\tif cardEntity ~= nil then
|
||||
\t\tlocal cardId = self.Hand[i]
|
||||
@@ -3245,9 +3274,13 @@ for i = 1, 5 do
|
||||
\t\t\tcardEntity.Enable = false
|
||||
\t\telse
|
||||
\t\t\tcardEntity.Enable = true
|
||||
\t\t\tif cardEntity.UITransformComponent ~= nil then cardEntity.UITransformComponent.UIScale = Vector3(1, 1, 1) end
|
||||
\t\t\tself:ApplyCardVisual(i, cardId)
|
||||
\t\t\tlocal tx = startX + (i - 1) * spacing
|
||||
\t\t\tif animate == true then
|
||||
\t\t\t\tself:AnimateCardFrom(i, drawStart, Vector2((i - 3) * 200, 0), 0.16 + i * 0.045)
|
||||
\t\t\t\tself:AnimateCardFrom(i, drawStart, Vector2(tx, 0), 0.16 + i * 0.03)
|
||||
\t\t\telse
|
||||
\t\t\t\tif cardEntity.UITransformComponent ~= nil then cardEntity.UITransformComponent.anchoredPosition = Vector2(tx, 0) end
|
||||
\t\t\tend
|
||||
\t\tend
|
||||
\tend
|
||||
@@ -4354,6 +4387,28 @@ if count > 10 then
|
||||
of = "+" .. tostring(count - 9)
|
||||
end
|
||||
self:SetText("/ui/DefaultGroup/CombatHud/TopBar/RelicOverflow", of)`),
|
||||
method('HoverCard', `if self.DragSlot ~= nil and self.DragSlot > 0 then
|
||||
return
|
||||
end
|
||||
local cardId = self.Hand[slot]
|
||||
if cardId == nil then
|
||||
return
|
||||
end
|
||||
local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(slot))
|
||||
local tx = 0
|
||||
if e ~= nil and e.UITransformComponent ~= nil then
|
||||
tx = e.UITransformComponent.anchoredPosition.x
|
||||
e.UITransformComponent.UIScale = Vector3(1.3, 1.3, 1)
|
||||
end
|
||||
local c = self.Cards[cardId]
|
||||
if c ~= nil then
|
||||
self:ShowTooltip(c.name, c.desc, tx)
|
||||
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||
method('UnhoverCard', `local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(slot))
|
||||
if e ~= nil and e.UITransformComponent ~= nil then
|
||||
e.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
||||
end
|
||||
self:HideTooltip()`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||
method('ShowTooltip', `self:SetText("/ui/DefaultGroup/CombatHud/TooltipBox/Name", name)
|
||||
self:SetText("/ui/DefaultGroup/CombatHud/TooltipBox/Desc", desc)
|
||||
local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/TooltipBox")
|
||||
|
||||
4515
ui/DefaultGroup.ui
4515
ui/DefaultGroup.ui
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user