feat(lobby): 로비 맵 흐름 통합 — 텔레포트·NPC 디스패치·StartRun map01·LobbyHud 슬림화 (P15)
- OnBeginPlay: 공격 키(Ctrl, 로비 한정) 바인딩 - ShowLobby→GoLobbyMap: 월드 시작·런 종료 시 로비 맵 텔레포트 - OnLobbyNpcInteract(id): 월드 NPC→기존 기능 패널 디스패치 - StartRun: 1막 진입 시 map01 물리 텔레포트(BuildMonsters CurrentMapName 필터 대응) - LobbyHud: 버튼-행 제거, 투명·비레이캐스트화(맵 노출·클릭 통과), 영혼/승천 미니 정보바만 유지 - BindLobbyButtons: NPC 바인딩 제거 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -2425,17 +2425,17 @@ function upsertUi() {
|
||||
displayOrder: 11,
|
||||
components: [
|
||||
transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 1920, y: 1080 }, pos: { x: 0, y: 0 }, align: ALIGN_CENTER }),
|
||||
sprite({ color: { r: 0.07, g: 0.08, b: 0.13, a: 1 }, type: 1, raycast: true }),
|
||||
// 로비가 물리 맵이 됨 — 투명 + 비레이캐스트로 맵을 가리지 않고 월드 NPC 클릭이 통과되게 함.
|
||||
sprite({ color: TRANSPARENT, type: 1, raycast: false }),
|
||||
],
|
||||
});
|
||||
lobbyRoot.jsonString.enable = false;
|
||||
lobby.push(lobbyRoot);
|
||||
const lobTexts = [
|
||||
['Title', 0, 470, 760, '메이플 로비', 48, GOLD],
|
||||
['Subtitle', 0, 408, 900, 'NPC를 클릭해 런을 준비하세요', 24, { r: 0.82, g: 0.86, b: 0.92, a: 1 }],
|
||||
['SoulLabel', 700, 470, 320, '영혼 0', 28, { r: 0.6, g: 0.85, b: 1, a: 1 }],
|
||||
['AscLabel', -560, 470, 380, '승천 0 / 해금 0', 22, { r: 0.9, g: 0.7, b: 0.5, a: 1 }],
|
||||
['Hint', 0, -430, 1300, '런을 클리어하거나 패배하면 로비로 돌아옵니다', 20, { r: 0.6, g: 0.64, b: 0.7, a: 1 }],
|
||||
['Title', 0, 478, 760, '메이플 로비', 40, GOLD],
|
||||
['SoulLabel', 700, 478, 320, '영혼 0', 28, { r: 0.6, g: 0.85, b: 1, a: 1 }],
|
||||
['AscLabel', -560, 478, 380, '승천 0 / 해금 0', 22, { r: 0.9, g: 0.7, b: 0.5, a: 1 }],
|
||||
['Hint', 0, -478, 1500, 'NPC에게 다가가 ↑ 또는 클릭으로 대화 · ← → 이동 · Ctrl 공격', 20, { r: 0.72, g: 0.76, b: 0.82, a: 1 }],
|
||||
];
|
||||
for (const [suffix, x, y, w, value, fs, color] of lobTexts) {
|
||||
lobby.push(entity({
|
||||
@@ -2466,62 +2466,7 @@ function upsertUi() {
|
||||
],
|
||||
}));
|
||||
}
|
||||
const npcs = [
|
||||
{ key: 'NpcRun', x: -540, name: '모험가', role: '런 시작', tint: { r: 0.74, g: 0.32, b: 0.28, a: 1 } },
|
||||
{ key: 'NpcCodex', x: -180, name: '사서', role: '카드 도감', tint: { r: 0.3, g: 0.55, b: 0.5, a: 1 } },
|
||||
{ key: 'NpcShop', x: 180, name: '상인', role: '영혼 상점', tint: { r: 0.55, g: 0.45, b: 0.75, a: 1 } },
|
||||
{ key: 'NpcBoard', x: 540, name: '안내원', role: '게시판', tint: { r: 0.4, g: 0.5, b: 0.7, a: 1 } },
|
||||
];
|
||||
for (const npc of npcs) {
|
||||
const base = `/ui/DefaultGroup/LobbyHud/${npc.key}`;
|
||||
lobby.push(entity({
|
||||
id: guid('lob', lobId++),
|
||||
path: base,
|
||||
modelId: 'uibutton', entryId: 'UIButton',
|
||||
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent',
|
||||
displayOrder: 4,
|
||||
components: [
|
||||
transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 240, y: 320 }, pos: { x: npc.x, y: 20 }, align: ALIGN_CENTER }),
|
||||
sprite({ color: { r: 0.13, g: 0.15, b: 0.2, a: 1 }, type: 1, raycast: true }),
|
||||
button(),
|
||||
],
|
||||
}));
|
||||
lobby.push(entity({
|
||||
id: guid('lob', lobId++),
|
||||
path: `${base}/Figure`,
|
||||
modelId: 'uisprite', entryId: 'UISprite',
|
||||
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
|
||||
displayOrder: 1,
|
||||
components: [
|
||||
transform({ parentW: 240, parentH: 320, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 130, y: 130 }, pos: { x: 0, y: 30 } }),
|
||||
sprite({ color: npc.tint, type: 1 }),
|
||||
],
|
||||
}));
|
||||
lobby.push(entity({
|
||||
id: guid('lob', lobId++),
|
||||
path: `${base}/Name`,
|
||||
modelId: 'uitext', entryId: 'UIText',
|
||||
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent',
|
||||
displayOrder: 2,
|
||||
components: [
|
||||
transform({ parentW: 240, parentH: 320, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 220, y: 40 }, pos: { x: 0, y: 122 } }),
|
||||
sprite({ color: TRANSPARENT }),
|
||||
text({ value: npc.name, fontSize: 28, bold: true, color: GOLD, alignment: 4 }),
|
||||
],
|
||||
}));
|
||||
lobby.push(entity({
|
||||
id: guid('lob', lobId++),
|
||||
path: `${base}/Role`,
|
||||
modelId: 'uitext', entryId: 'UIText',
|
||||
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent',
|
||||
displayOrder: 2,
|
||||
components: [
|
||||
transform({ parentW: 240, parentH: 320, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 220, y: 36 }, pos: { x: 0, y: -122 } }),
|
||||
sprite({ color: TRANSPARENT }),
|
||||
text({ value: npc.role, fontSize: 22, bold: false, color: { r: 0.86, g: 0.9, b: 0.94, a: 1 }, alignment: 4 }),
|
||||
],
|
||||
}));
|
||||
}
|
||||
// NPC 4종은 로비 물리 맵의 월드 엔티티(map/lobby.map + LobbyNpc codeblock)로 이동. UI 버튼 행 제거.
|
||||
emit('LobbyHud', lobby);
|
||||
|
||||
// ── BoardHud — 게시판(공지/팁) ──
|
||||
@@ -2743,6 +2688,8 @@ function writeCodeblocks() {
|
||||
const RELIC_PRICE = 60;
|
||||
const ACT_COUNT = 5;
|
||||
const ACT_MAPS = ['map01', 'map02', 'map03', 'map04', 'map05'];
|
||||
const LOBBY_MAP = 'lobby';
|
||||
const LOBBY_SPAWN = 'Vector3(-5, 0.03, 0)'; // 정찰: map01 지면 좌측
|
||||
const combat = codeblock('SlayDeckController', 'SlayDeckController', [
|
||||
prop('any', 'DrawPile'),
|
||||
prop('any', 'DiscardPile'),
|
||||
@@ -2771,6 +2718,7 @@ function writeCodeblocks() {
|
||||
prop('any', 'AllDeckCloseHandler'),
|
||||
prop('number', 'SoulPoints', '0'),
|
||||
prop('boolean', 'LobbyBound', 'false'),
|
||||
prop('number', 'LobbyTpTries', '0'),
|
||||
prop('boolean', 'CodexMode', 'false'),
|
||||
prop('any', 'CodexCards'),
|
||||
prop('any', 'SoulUnlocks'),
|
||||
@@ -2837,7 +2785,15 @@ local lp = _UserService.LocalPlayer
|
||||
if lp ~= nil then
|
||||
self:ReqLoadAscension(lp.PlayerComponent.UserId)
|
||||
self:ReqLoadSouls(lp.PlayerComponent.UserId)
|
||||
end`),
|
||||
end
|
||||
_InputService:ConnectEvent(KeyDownEvent, function(e)
|
||||
if e.key == KeyboardKey.LeftControl then
|
||||
local lp2 = _UserService.LocalPlayer
|
||||
if lp2 ~= nil and lp2.CurrentMapName == "${LOBBY_MAP}" and self.RunActive ~= true then
|
||||
self:PlayerAttackMotion()
|
||||
end
|
||||
end
|
||||
end)`),
|
||||
method('ReqLoadAscension', `local ds = _DataStorageService:GetUserDataStorage(userId)
|
||||
local errCode, value = ds:GetAndWait("ascensionUnlocked")
|
||||
local n = 0
|
||||
@@ -2990,7 +2946,35 @@ self:ShowState("lobby")
|
||||
self:SetEntityEnabled("/ui/DefaultGroup/BoardHud", false)
|
||||
self:SetEntityEnabled("/ui/DefaultGroup/SoulShopHud", false)
|
||||
self:BindLobbyButtons()
|
||||
self:BindMenuButtons()`),
|
||||
self:BindMenuButtons()
|
||||
self:GoLobbyMap()`),
|
||||
method('GoLobbyMap', `self.LobbyTpTries = 0
|
||||
local eventId = 0
|
||||
local function go()
|
||||
self.LobbyTpTries = self.LobbyTpTries + 1
|
||||
local lp = _UserService.LocalPlayer
|
||||
if lp ~= nil then
|
||||
if lp.CurrentMapName ~= "${LOBBY_MAP}" then
|
||||
_TeleportService:TeleportToMapPosition(lp, ${LOBBY_SPAWN}, "${LOBBY_MAP}")
|
||||
end
|
||||
_TimerService:ClearTimer(eventId)
|
||||
elseif self.LobbyTpTries > 50 then
|
||||
_TimerService:ClearTimer(eventId)
|
||||
end
|
||||
end
|
||||
eventId = _TimerService:SetTimerRepeat(go, 0.1)`),
|
||||
method('OnLobbyNpcInteract', `if self.RunActive == true then
|
||||
return
|
||||
end
|
||||
if id == "run" then
|
||||
self:ShowCharacterSelect()
|
||||
elseif id == "codex" then
|
||||
self:ShowCodex()
|
||||
elseif id == "shop" then
|
||||
self:ShowSoulShop()
|
||||
elseif id == "board" then
|
||||
self:ShowBoard()
|
||||
end`, [{ Type: 'string', DefaultValue: '""', SyncDirection: 0, Attributes: [], Name: 'id' }]),
|
||||
method('RenderSoulLabel', `local s = self.SoulPoints or 0
|
||||
self:SetText("/ui/DefaultGroup/LobbyHud/SoulLabel", "영혼 " .. string.format("%d", s))
|
||||
self:SetText("/ui/DefaultGroup/SoulShopHud/Souls", "영혼 " .. string.format("%d", s))`),
|
||||
@@ -3004,10 +2988,6 @@ local function bindClick(path, fn)
|
||||
e:ConnectEvent(ButtonClickEvent, fn)
|
||||
end
|
||||
end
|
||||
bindClick("/ui/DefaultGroup/LobbyHud/NpcRun", function() self:ShowCharacterSelect() end)
|
||||
bindClick("/ui/DefaultGroup/LobbyHud/NpcCodex", function() self:ShowCodex() end)
|
||||
bindClick("/ui/DefaultGroup/LobbyHud/NpcShop", function() self:ShowSoulShop() end)
|
||||
bindClick("/ui/DefaultGroup/LobbyHud/NpcBoard", function() self:ShowBoard() end)
|
||||
bindClick("/ui/DefaultGroup/LobbyHud/AscMinus", function() self:AdjustAscension(-1) end)
|
||||
bindClick("/ui/DefaultGroup/LobbyHud/AscPlus", function() self:AdjustAscension(1) end)
|
||||
bindClick("/ui/DefaultGroup/BoardHud/Close", function() self:CloseBoard() end)
|
||||
@@ -3229,6 +3209,7 @@ self:BindButtons()
|
||||
self:AddRelic("${RELICS.startingRelic}")
|
||||
self:ApplySoulUnlocks()
|
||||
self:RenderPotions()
|
||||
self:TeleportToActMap()
|
||||
self:ShowMap()`),
|
||||
method('StartCombat', `self:ShowState("combat")
|
||||
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud/Result", false)
|
||||
|
||||
3076
ui/DefaultGroup.ui
3076
ui/DefaultGroup.ui
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user