Compare commits
32 Commits
feature/ch
...
4fa0bc85c0
| Author | SHA1 | Date | |
|---|---|---|---|
| 4fa0bc85c0 | |||
| db76870d4e | |||
| 491833b025 | |||
| 83de73c2c1 | |||
| b06ad8e8ee | |||
| 578f4416b2 | |||
| bc80b96875 | |||
| f2828deb19 | |||
| b549abc3b3 | |||
| 5b21e7f436 | |||
| b42d5fcf51 | |||
| 43530bee60 | |||
| 9b8884da81 | |||
| 2b3d77c588 | |||
| 3efb6993c7 | |||
| 5f8475d018 | |||
| afac34d7b5 | |||
| a917a6d82b | |||
| 9fba9b5aaa | |||
| 54d9632534 | |||
| c274322887 | |||
| 5900af087e | |||
| b0d3da2f39 | |||
| 6ef0ba48f6 | |||
| 1b1fce3d6e | |||
| c34a1126fb | |||
| 964cf7cc3d | |||
| 098571e9aa | |||
| ea832ad846 | |||
| 4288c4101b | |||
| 2bb7360a47 | |||
| 2f9c325c96 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -7,6 +7,8 @@
|
|||||||
# Claude Code 로컬 설정 — 단, 팀 공유 하네스 설정(settings.json)은 커밋 (RULES.md 참조)
|
# Claude Code 로컬 설정 — 단, 팀 공유 하네스 설정(settings.json)은 커밋 (RULES.md 참조)
|
||||||
.claude/*
|
.claude/*
|
||||||
!.claude/settings.json
|
!.claude/settings.json
|
||||||
|
# 개인 스킬(superpowers) 브레인스토밍/계획 산출물 — 로컬 전용, 협업 공유 X (프로젝트 설계 문서 docs/*.md 는 추적 유지)
|
||||||
|
docs/superpowers/
|
||||||
|
|
||||||
# === OS / 에디터 잡파일 ===
|
# === OS / 에디터 잡파일 ===
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
@@ -23,3 +25,5 @@ AGENTS.md
|
|||||||
Environment/
|
Environment/
|
||||||
McpScreenshots/
|
McpScreenshots/
|
||||||
*.log
|
*.log
|
||||||
|
# 메이커가 재편(reorg) 중 부모를 잃은 엔티티를 모아두는 임시 폴더 (잡파일)
|
||||||
|
Mislocated/
|
||||||
|
|||||||
142
Global/UIButton.model
Normal file
142
Global/UIButton.model
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
{
|
||||||
|
"Id": "",
|
||||||
|
"GameId": "",
|
||||||
|
"EntryKey": "model://uibutton",
|
||||||
|
"ContentType": "x-mod/model",
|
||||||
|
"Content": "",
|
||||||
|
"Usage": 0,
|
||||||
|
"UsePublish": 1,
|
||||||
|
"UseService": 0,
|
||||||
|
"CoreVersion": "26.5.0.0",
|
||||||
|
"StudioVersion": "0.1.0.0",
|
||||||
|
"DynamicLoading": 0,
|
||||||
|
"ContentProto": {
|
||||||
|
"Use": "Json",
|
||||||
|
"Json": {
|
||||||
|
"Version": 1,
|
||||||
|
"Name": "UIButton",
|
||||||
|
"BaseModelId": null,
|
||||||
|
"Id": "uibutton",
|
||||||
|
"Components": [
|
||||||
|
"MOD.Core.UITransformComponent",
|
||||||
|
"MOD.Core.SpriteGUIRendererComponent"
|
||||||
|
],
|
||||||
|
"Properties": [
|
||||||
|
{
|
||||||
|
"Type": {
|
||||||
|
"$type": "MODNativeType",
|
||||||
|
"type": "MOD.Core.MODVector2, MOD.Core, Version=26.5.0.0, Culture=neutral, PublicKeyToken=null"
|
||||||
|
},
|
||||||
|
"Name": "RectSize",
|
||||||
|
"DisplayName": "RectSize",
|
||||||
|
"ShowInInspector": true,
|
||||||
|
"Link": {
|
||||||
|
"Target": {
|
||||||
|
"$type": "MODNativeType",
|
||||||
|
"type": "MOD.Core.UITransformComponent, MOD.Core, Version=26.5.0.0, Culture=neutral, PublicKeyToken=null"
|
||||||
|
},
|
||||||
|
"Property": "RectSize"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Type": {
|
||||||
|
"$type": "MODNativeType",
|
||||||
|
"type": "MOD.Core.MODDataRef, MOD.Core, Version=26.5.0.0, Culture=neutral, PublicKeyToken=null"
|
||||||
|
},
|
||||||
|
"Name": "ImageRUID",
|
||||||
|
"DisplayName": "ImageRUID",
|
||||||
|
"ShowInInspector": true,
|
||||||
|
"Link": {
|
||||||
|
"Target": {
|
||||||
|
"$type": "MODNativeType",
|
||||||
|
"type": "MOD.Core.SpriteGUIRendererComponent, MOD.Core, Version=26.5.0.0, Culture=neutral, PublicKeyToken=null"
|
||||||
|
},
|
||||||
|
"Property": "ImageRUID"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Type": {
|
||||||
|
"$type": "MODNativeType",
|
||||||
|
"type": "MOD.Core.MODColor, MOD.Core, Version=26.5.0.0, Culture=neutral, PublicKeyToken=null"
|
||||||
|
},
|
||||||
|
"Name": "Color",
|
||||||
|
"DisplayName": "Color",
|
||||||
|
"ShowInInspector": true,
|
||||||
|
"Link": {
|
||||||
|
"Target": {
|
||||||
|
"$type": "MODNativeType",
|
||||||
|
"type": "MOD.Core.SpriteGUIRendererComponent, MOD.Core, Version=26.5.0.0, Culture=neutral, PublicKeyToken=null"
|
||||||
|
},
|
||||||
|
"Property": "Color"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Values": [
|
||||||
|
{
|
||||||
|
"TargetType": "MOD.Core.UITransformComponent",
|
||||||
|
"Name": "anchoredPosition",
|
||||||
|
"ValueType": {
|
||||||
|
"$type": "MODNativeType",
|
||||||
|
"type": "MOD.Core.MODVector2, MOD.Core, Version=26.5.0.0, Culture=neutral, PublicKeyToken=null"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"$type": "MOD.Core.MODVector2, MOD.Core",
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TargetType": "MOD.Core.UITransformComponent",
|
||||||
|
"Name": "RectSize",
|
||||||
|
"ValueType": {
|
||||||
|
"$type": "MODNativeType",
|
||||||
|
"type": "MOD.Core.MODVector2, MOD.Core, Version=26.5.0.0, Culture=neutral, PublicKeyToken=null"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"$type": "MOD.Core.MODVector2, MOD.Core",
|
||||||
|
"x": 200.0,
|
||||||
|
"y": 75.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TargetType": "MOD.Core.UITransformComponent",
|
||||||
|
"Name": "AlignmentOption",
|
||||||
|
"ValueType": {
|
||||||
|
"$type": "MODNativeType",
|
||||||
|
"type": "MOD.Core.AlignmentType, MOD.Core, Version=26.5.0.0, Culture=neutral, PublicKeyToken=null"
|
||||||
|
},
|
||||||
|
"Value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TargetType": "MOD.Core.SpriteGUIRendererComponent",
|
||||||
|
"Name": "ImageRUID",
|
||||||
|
"ValueType": {
|
||||||
|
"$type": "MODNativeType",
|
||||||
|
"type": "MOD.Core.MODDataRef, MOD.Core, Version=26.5.0.0, Culture=neutral, PublicKeyToken=null"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"$type": "MOD.Core.MODDataRef, MOD.Core",
|
||||||
|
"DataId": "cc3457b8e97b3e14f9d5c39ccdd640bf"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TargetType": "MOD.Core.SpriteGUIRendererComponent",
|
||||||
|
"Name": "Color",
|
||||||
|
"ValueType": {
|
||||||
|
"$type": "MODNativeType",
|
||||||
|
"type": "MOD.Core.MODColor, MOD.Core, Version=26.5.0.0, Culture=neutral, PublicKeyToken=null"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"$type": "MOD.Core.MODColor, MOD.Core",
|
||||||
|
"r": 1.0,
|
||||||
|
"g": 1.0,
|
||||||
|
"b": 1.0,
|
||||||
|
"a": 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"EventLinks": [],
|
||||||
|
"Children": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,10 +32,10 @@
|
|||||||
{
|
{
|
||||||
"@type": "script.SlayDeckController",
|
"@type": "script.SlayDeckController",
|
||||||
"Enable": true,
|
"Enable": true,
|
||||||
"Energy": 0.0,
|
"Energy": 0,
|
||||||
"MaxEnergy": 3.0,
|
"MaxEnergy": 3,
|
||||||
"Turn": 0.0,
|
"Turn": 0,
|
||||||
"TweenEventId": 0.0
|
"TweenEventId": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"@version": 1
|
"@version": 1
|
||||||
|
|||||||
34
README.md
34
README.md
@@ -77,9 +77,9 @@ slaymaple/
|
|||||||
│ ├── player/ # gen-player-lock.mjs(전투맵 입력 잠금) · freeze-turn-player.mjs(모델 이동 정지) · gen-lobby-npc.mjs(LobbyNpc·LobbyMobility codeblock)
|
│ ├── player/ # gen-player-lock.mjs(전투맵 입력 잠금) · freeze-turn-player.mjs(모델 이동 정지) · gen-lobby-npc.mjs(LobbyNpc·LobbyMobility codeblock)
|
||||||
│ ├── monster/ # gen-combat-monster.mjs(EnemyId 마커) · freeze-turn-monsters.mjs(필드 AI 정지)
|
│ ├── monster/ # gen-combat-monster.mjs(EnemyId 마커) · freeze-turn-monsters.mjs(필드 AI 정지)
|
||||||
│ ├── balance/ # sim-balance.mjs(전투 밸런스 몬테카를로 시뮬) · sim-balance.test.mjs
|
│ ├── balance/ # sim-balance.mjs(전투 밸런스 몬테카를로 시뮬) · sim-balance.test.mjs
|
||||||
│ ├── verify/ # count.mjs(산출물 카운트 검증 헬퍼 — 경로 내장)
|
│ ├── verify/ # count.mjs·uimap.mjs·cbgap.mjs(산출물 카운트/UIGroup 매핑/재연결 GAP 검증 — 경로 내장)
|
||||||
│ └── git/ # gitea-pr.mjs(UTF-8 안전 PR 생성/수정/머지 — RULES.md 참조)
|
│ └── git/ # gitea-pr.mjs(UTF-8 안전 PR 생성/수정/머지 — RULES.md 참조)
|
||||||
├── ui/ # UI 그룹 (DefaultGroup 8.3MB 산출물 / PopupGroup / ToastGroup)
|
├── ui/ # UIGroup 7종 — 메이커 저작(Default/Select/Lobby/Run/Deck/Popup/Toast)
|
||||||
├── docs/
|
├── docs/
|
||||||
│ ├── slaymaple_basic_framework.md # 전투 프레임워크 설계 문서
|
│ ├── slaymaple_basic_framework.md # 전투 프레임워크 설계 문서
|
||||||
│ ├── ui-generation-structure.md # UI 생성 구조 문서
|
│ ├── ui-generation-structure.md # UI 생성 구조 문서
|
||||||
@@ -89,11 +89,19 @@ slaymaple/
|
|||||||
└── README.md
|
└── README.md
|
||||||
```
|
```
|
||||||
|
|
||||||
> ⚠️ **`map/*.map` · `ui/DefaultGroup.ui` · `*.codeblock` · `Global/*.gamelogic`는 생성 산출물**입니다 — 직접 편집하면 다음 재생성 때 사라집니다. 게임 변경은 `data/*.json` 또는 `tools/`의 생성기를 고친 뒤 재생성하세요(자세한 규칙은 [`RULES.md`](RULES.md)).
|
> ⚠️ **`map/*.map` · `SlayDeckController.codeblock` · `Global/common.gamelogic`는 생성 산출물**입니다 — 직접 편집하면 재생성 때 사라집니다. 게임 로직 변경은 `data/*.json`·`tools/`의 생성기를 고쳐 재생성하세요. **`ui/*.ui`는 메이커 저작**(생성기 미생성)이라 메이커에서만 편집합니다(자세한 규칙은 [`RULES.md`](RULES.md)).
|
||||||
> `.mcp.json`, `.codex/` 는 **Authorization 토큰이 포함**되어 있어 git에서 제외됩니다(`.gitignore`). 각자 로컬에서 직접 구성하세요.
|
> `.mcp.json`, `.codex/` 는 **Authorization 토큰이 포함**되어 있어 git에서 제외됩니다(`.gitignore`). 각자 로컬에서 직접 구성하세요.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 직업 컨셉
|
||||||
|
|
||||||
|
3직업 모두 Slay the Spire 2 차용 + 메이플 IP 재해석. 카드 덱 상세 설계는 [`docs/deck-concept.md`](docs/deck-concept.md) 참조.
|
||||||
|
|
||||||
|
- **⚔️ 전사 (탱커, Ironclad 차용)** — **파이터**: 공격을 *연속*으로 내면 콤보가 쌓이고(방어·파워 등 비공격 카드를 쓰면 콤보 리셋) 콤보로 데미지 증가 버프 = 브루저. **페이지**: 위협 디버프로 버티며 방어도 축적 → **바디 슬램(방어 비례 피해)** 카운터. **스피어맨**: 하이퍼바디·아이언월 유지/리치형.
|
||||||
|
- **🗡️ 도적 (단검·독, Silent 차용)** — 표창 난사 / 독 / 교활·버림. **어쌔신**(표창·크리·흡혈) / **시프**(단검 난타·독). *형 구현 완료(Silent 88장)*.
|
||||||
|
- **🔮 법사 (약체·게이지, Defect 차용)** — **위자드(불/독)**: 독을 묻히고 *독 걸린 적에 불 카드 → 추가 데미지*(독뎀 시너지). **위자드(썬/콜)**: 오브로 썬더(다중 공격)·콜드(빙결=취약+피해), 오브 획득·다중 소모 운용. **클레릭**: 오브 없이 회복·버프 + 언데드엔 힐로 공격하는 보조 힐러.
|
||||||
|
|
||||||
## 게임 프레임워크 현황
|
## 게임 프레임워크 현황
|
||||||
|
|
||||||
**StS2풍 덱빌더 로그라이크가 end-to-end로 완성**됐고, 이제 **로비 마을을 기점으로 반복 런**이 돕니다:
|
**StS2풍 덱빌더 로그라이크가 end-to-end로 완성**됐고, 이제 **로비 마을을 기점으로 반복 런**이 돕니다:
|
||||||
@@ -104,7 +112,7 @@ slaymaple/
|
|||||||
→ 런 클리어(승천 해금) → 로비 복귀(영혼 정산) → 다음 런 …
|
→ 런 클리어(승천 해금) → 로비 복귀(영혼 정산) → 다음 런 …
|
||||||
```
|
```
|
||||||
|
|
||||||
게임 전체는 `/common` 엔티티에 부착된 **`SlayDeckController` 단일 컴포넌트**로 동작하며, 모든 산출물(`ui/DefaultGroup.ui` · `SlayDeckController.codeblock` · `common.gamelogic`)은 **`tools/deck/gen-slaydeck.mjs` 단일 소스에서 생성**됩니다(결정적 출력, 직접 편집 금지 — `RULES.md` 참조). 게임 데이터는 **`data/*.json`** 가 단일 소스, 맵 구조는 **런타임 절차 생성**(`GenerateMap` Lua ↔ `tools/map/rogue-map.mjs` JS 미러).
|
게임 전체는 `/common` 엔티티에 부착된 **`SlayDeckController` 단일 컴포넌트**로 동작합니다. **UI는 메이커 저작**(7개 UIGroup: Default/Select/Lobby/Run/Deck/Popup/Toast)이고, 컨트롤러가 엔티티 경로(`/ui/<UIGroup>/<Hud>/...`)로 내용을 런타임 주입합니다. 생성기 `tools/deck/gen-slaydeck.mjs`는 **`SlayDeckController.codeblock` + `common.gamelogic`만 생성**(`.ui` 미접근, 결정적 출력 — `RULES.md` 참조). 게임 데이터는 **`data/*.json`**, 맵 구조는 **런타임 절차 생성**(`GenerateMap` Lua ↔ `tools/map/rogue-map.mjs` JS 미러).
|
||||||
|
|
||||||
### 구현된 기능 (배포 퀄리티 P1~P15, PR #34~#57)
|
### 구현된 기능 (배포 퀄리티 P1~P15, PR #34~#57)
|
||||||
|
|
||||||
@@ -125,7 +133,7 @@ slaymaple/
|
|||||||
| **밸런스 시뮬** | `tools/balance/sim-balance.mjs` — 전투 규칙 JS 미러(몬테카를로) + `tools/map/rogue-map.mjs`(맵 생성 미러) + node 단위테스트 |
|
| **밸런스 시뮬** | `tools/balance/sim-balance.mjs` — 전투 규칙 JS 미러(몬테카를로) + `tools/map/rogue-map.mjs`(맵 생성 미러) + node 단위테스트 |
|
||||||
|
|
||||||
> ⚠️ 수치(적 스탯·경제·승천 배율)는 1차 조정 상태입니다. 정밀 밸런싱은 `sim-balance.mjs`로 검증하며 진행합니다.
|
> ⚠️ 수치(적 스탯·경제·승천 배율)는 1차 조정 상태입니다. 정밀 밸런싱은 `sim-balance.mjs`로 검증하며 진행합니다.
|
||||||
> ℹ️ 도적(Silent) 카드 88장은 효과·프레임은 적용됐으나 **카드 아이콘(image/fx) 미할당** 상태입니다(전사·마법사 카드는 실 스킬 아이콘 적용 완료).
|
> ℹ️ 도적(Silent) 카드 88장은 STS Silent 완역 포트 + **공식 스킬 아이콘 적용 완료**(PR #73). 남은 작업은 카드명 메이플 재서사(어쌔신/시프)·멀티플레이어 전제 카드 싱글 정리 — [`docs/deck-concept.md`](docs/deck-concept.md) 참조.
|
||||||
|
|
||||||
### 유용한 스크립트 호출
|
### 유용한 스크립트 호출
|
||||||
`/common` 엔티티(또는 Play Test 컨텍스트)에서:
|
`/common` 엔티티(또는 Play Test 컨텍스트)에서:
|
||||||
@@ -149,9 +157,20 @@ c:AdjustAscension(1) -- 메뉴에서 승천 단계 +1
|
|||||||
밸런스 검증: `node tools/balance/sim-balance.mjs [N] [--seed S]` · 테스트: `node --test tools/balance/sim-balance.test.mjs tools/map/rogue-map.test.mjs`.
|
밸런스 검증: `node tools/balance/sim-balance.mjs [N] [--seed S]` · 테스트: `node --test tools/balance/sim-balance.test.mjs tools/map/rogue-map.test.mjs`.
|
||||||
상세 설계는 [`docs/slaymaple_basic_framework.md`](docs/slaymaple_basic_framework.md) 및 `docs/superpowers/specs/` 참조.
|
상세 설계는 [`docs/slaymaple_basic_framework.md`](docs/slaymaple_basic_framework.md) 및 `docs/superpowers/specs/` 참조.
|
||||||
|
|
||||||
|
### 디버그 단축키
|
||||||
|
|
||||||
|
개발·QA용 키보드 단축키. **전투 중**(런 활성 + 전투 진행 중)에만 동작합니다.
|
||||||
|
|
||||||
|
| 단축키 | 기능 |
|
||||||
|
|---|---|
|
||||||
|
| **Ctrl + Shift + C** | **카드 picker** — 직업 전체 카드 패널을 띄우고, 카드를 클릭하면 **즉시 손패에 추가**. 상단 탭(전사/도적/마법사)으로 직업별 카드 풀 전환. 카드 효과·메커니즘 즉석 테스트용 |
|
||||||
|
| **Ctrl + Shift + E** | **에너지 치트** — 현재 에너지를 최대치로 회복 |
|
||||||
|
|
||||||
|
> 카드 picker는 메이커 저작 UI `DeckUIGroup/DeckAllHud`(120 슬롯 그리드 + 직업 탭 3종)를 사용하고, 컨트롤러가 런타임에 카드 비주얼·버튼을 바인딩합니다. 구현: 키 바인딩 `tools/deck/cb/boot.mjs`, picker 로직 `tools/deck/cb/deckview.mjs`(`OpenDebugCardPicker`/`OnAllDeckCardButton`), 버튼 바인딩 `tools/deck/cb/deckturn.mjs`(`BindButtons`). 옛 picker UI 생성기 `tools/deck/legacy/hud/deckall.mjs`는 UI 메이커-저작 전환 후 **휴면**(Maker UI가 대체).
|
||||||
|
|
||||||
### 산출물 재생성
|
### 산출물 재생성
|
||||||
```bash
|
```bash
|
||||||
node tools/deck/gen-slaydeck.mjs # 게임 전체(UI·컨트롤러·common·맵 인카운터)
|
node tools/deck/gen-slaydeck.mjs # 컨트롤러+common (UI는 메이커 저작 — 미생성)
|
||||||
node tools/map/gen-maps.mjs # map01~05 배경/타일
|
node tools/map/gen-maps.mjs # map01~05 배경/타일
|
||||||
node tools/map/gen-lobby-map.mjs # 로비 맵 + NPC 배치
|
node tools/map/gen-lobby-map.mjs # 로비 맵 + NPC 배치
|
||||||
node tools/player/gen-lobby-npc.mjs # 로비 codeblock(LobbyNpc·LobbyMobility)
|
node tools/player/gen-lobby-npc.mjs # 로비 codeblock(LobbyNpc·LobbyMobility)
|
||||||
@@ -165,7 +184,7 @@ node tools/monster/gen-combat-monster.mjs # 몬스터 EnemyId 마커
|
|||||||
|
|
||||||
## 아키텍처 메모
|
## 아키텍처 메모
|
||||||
|
|
||||||
현재 게임 전체 로직이 `SlayDeckController` 단일 codeblock에 모여 있습니다. 초기 설계의 3분할(`SlayCardCatalog`/`SlayRunState`/`SlayCombatManager`)은 **기능적으로 모두 구현**됐으나 아직 한 컴포넌트 안에 있습니다. 맵 NPC·카메라·입력 잠금 등 **맵 단위 동작은 별도 codeblock**(LobbyNpc/LobbyMobility/MapCamera/PlayerLock/CombatMonster)으로 분리해 각 맵 루트/엔티티에 부착합니다. 카드/적/맵/유물/프레임/카메라 데이터는 `data/*.json`로 외부화돼 있습니다.
|
현재 게임 전체 로직이 `SlayDeckController` 단일 codeblock에 모여 있습니다. 초기 설계의 3분할(`SlayCardCatalog`/`SlayRunState`/`SlayCombatManager`)은 **기능적으로 모두 구현**됐으나 아직 한 컴포넌트 안에 있습니다. 맵 NPC·카메라·입력 잠금 등 **맵 단위 동작은 별도 codeblock**(LobbyNpc/LobbyMobility/MapCamera/PlayerLock/CombatMonster)으로 분리해 각 맵 루트/엔티티에 부착합니다. 카드/적/맵/유물/프레임/카메라 데이터는 `data/*.json`로 외부화돼 있습니다. **2026-06-17**: UI를 단일 `DefaultGroup`에서 7개 UIGroup(Select/Lobby/Run/Deck 등)으로 분리해 **메이커 저작으로 전환** — 생성기는 더 이상 `.ui`를 만들지 않고, 컨트롤러가 새 UIGroup 경로로 재연결됨(옛 UI emit `hud/*`·`gen-cardhand`는 `tools/deck/legacy/` 휴면). 재연결 무결성은 `tools/verify/cbgap.mjs`(GAP 0)로 검증.
|
||||||
|
|
||||||
> ⚠️ **전투 규칙과 맵 생성은 Lua(gen-slaydeck 내장)와 JS 미러(sim-balance/rogue-map)로 이중 구현**입니다. 한쪽을 고치면 반드시 다른 쪽도 동기화하고 테스트하세요(`RULES.md` §6).
|
> ⚠️ **전투 규칙과 맵 생성은 Lua(gen-slaydeck 내장)와 JS 미러(sim-balance/rogue-map)로 이중 구현**입니다. 한쪽을 고치면 반드시 다른 쪽도 동기화하고 테스트하세요(`RULES.md` §6).
|
||||||
|
|
||||||
@@ -173,6 +192,7 @@ node tools/monster/gen-combat-monster.mjs # 몬스터 EnemyId 마커
|
|||||||
|
|
||||||
## 향후 개선 계획 (후속 후보)
|
## 향후 개선 계획 (후속 후보)
|
||||||
- [x] 전투 루프 · 런 루프 · 절차 생성 맵 · 상점/휴식/유물 방 · 유물 19종 · 물약 · 버프/디버프 · Power · 전직(전사/법사/도적 2차) · 승천+개인 저장 · 전투 모션 · 커스텀 프레임 · **반복 런·로비 맵·NPC·영혼·메소·카메라 추종 (P1~P15 완료)**
|
- [x] 전투 루프 · 런 루프 · 절차 생성 맵 · 상점/휴식/유물 방 · 유물 19종 · 물약 · 버프/디버프 · Power · 전직(전사/법사/도적 2차) · 승천+개인 저장 · 전투 모션 · 커스텀 프레임 · **반복 런·로비 맵·NPC·영혼·메소·카메라 추종 (P1~P15 완료)**
|
||||||
|
- [x] **UI 메이커-저작 전환** — 단일 DefaultGroup → 7개 UIGroup 분리, 생성기 UI 저작 폐기(`tools/deck/legacy/`), 컨트롤러 경로 재연결(cbgap GAP 0), MainMenu→로비→run NPC→charselect 부트 흐름 (2026-06-17)
|
||||||
- [ ] **도적 카드 아이콘** — Silent 88장에 실 스킬 아이콘(image/fx) 할당, 2차 전직 설명 한글화
|
- [ ] **도적 카드 아이콘** — Silent 88장에 실 스킬 아이콘(image/fx) 할당, 2차 전직 설명 한글화
|
||||||
- [ ] **런 이어하기** — 진행 중 런 직렬화 저장(UserDataStorage 확장, 메뉴 "이어하기" 활성화)
|
- [ ] **런 이어하기** — 진행 중 런 직렬화 저장(UserDataStorage 확장, 메뉴 "이어하기" 활성화)
|
||||||
- [ ] **카드 제거/업그레이드** — 상점 카드 제거 슬롯, 휴식 노드에서 카드 강화
|
- [ ] **카드 제거/업그레이드** — 상점 카드 제거 슬롯, 휴식 노드에서 카드 강화
|
||||||
|
|||||||
14
RULES.md
14
RULES.md
@@ -11,8 +11,8 @@ Claude Code는 `CLAUDE.md`가 이 파일을 임포트하므로 자동 적용된
|
|||||||
|
|
||||||
| 산출물 (절대 Read/Edit 금지) | 크기 | 단일 소스 (여기만 편집) | 재생성 명령 |
|
| 산출물 (절대 Read/Edit 금지) | 크기 | 단일 소스 (여기만 편집) | 재생성 명령 |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `ui/DefaultGroup.ui` | **~7.1MB** | `data/*.json` + `tools/deck/`(`gen-slaydeck.mjs`+`lib/`+`hud/`) | `node tools/deck/gen-slaydeck.mjs` |
|
| `ui/*.ui` (Default·Select·Lobby·Run·Deck·Popup·Toast UIGroup 7종) | 9KB~4.5MB | **메이커 저작 (생성기 미생성, 2026-06-17~)** — 메이커에서 시각 편집 | (없음) |
|
||||||
| `RootDesk/MyDesk/SlayDeckController.codeblock` | ~270KB | 〃 | 〃 |
|
| `RootDesk/MyDesk/SlayDeckController.codeblock` | ~270KB | `data/*.json` + `tools/deck/`(`gen-slaydeck.mjs`+`lib/`+`cb/`) | `node tools/deck/gen-slaydeck.mjs` |
|
||||||
| `Global/common.gamelogic` | ~1KB | 〃 | 〃 |
|
| `Global/common.gamelogic` | ~1KB | 〃 | 〃 |
|
||||||
| `map/map01.map`~`map05.map`, `map/lobby.map` | 각 ~210KB | `tools/map/`·`tools/monster/`·`tools/camera/`·`tools/player/` (↓ 보조 생성기) | 해당 생성기 |
|
| `map/map01.map`~`map05.map`, `map/lobby.map` | 각 ~210KB | `tools/map/`·`tools/monster/`·`tools/camera/`·`tools/player/` (↓ 보조 생성기) | 해당 생성기 |
|
||||||
| `RootDesk/MyDesk/CombatMonster.codeblock` | ~2KB | `tools/monster/gen-combat-monster.mjs` | `node tools/monster/gen-combat-monster.mjs` |
|
| `RootDesk/MyDesk/CombatMonster.codeblock` | ~2KB | `tools/monster/gen-combat-monster.mjs` | `node tools/monster/gen-combat-monster.mjs` |
|
||||||
@@ -21,11 +21,11 @@ Claude Code는 `CLAUDE.md`가 이 파일을 임포트하므로 자동 적용된
|
|||||||
| `RootDesk/MyDesk/LobbyNpc.codeblock`·`LobbyMobility.codeblock` | 각 ~2-3KB | `tools/player/gen-lobby-npc.mjs` | `node tools/player/gen-lobby-npc.mjs` |
|
| `RootDesk/MyDesk/LobbyNpc.codeblock`·`LobbyMobility.codeblock` | 각 ~2-3KB | `tools/player/gen-lobby-npc.mjs` | `node tools/player/gen-lobby-npc.mjs` |
|
||||||
| `Global/SectorConfig.config` | ~1KB | `tools/map/gen-maps.mjs`·`gen-lobby-map.mjs` (패치) | 해당 생성기 |
|
| `Global/SectorConfig.config` | ~1KB | `tools/map/gen-maps.mjs`·`gen-lobby-map.mjs` (패치) | 해당 생성기 |
|
||||||
|
|
||||||
- `.claude/settings.json`의 permissions.deny가 위 파일의 Read/Edit/Write 도구 사용을 차단한다 (이 저장소를 열면 자동 적용). deny는 **glob** — `ui/*.ui`·`map/*.map`·`RootDesk/MyDesk/*.codeblock`·`Global/common.gamelogic`·`Global/SectorConfig.config`. 따라서 **메이커 저작 codeblock/UI**(`Monster`·`MonsterAttack`·`PlayerAttack`·`PlayerHit`·`UIPopup`·`UIToast`.codeblock, `ui/PopupGroup.ui`·`ui/ToastGroup.ui`)**도** Read/Edit 금지 — 이들은 생성기가 없으니 **메이커에서** 편집한다(텍스트 도구로 X). codeblock은 한 줄짜리 JSON이라 Read 시 토큰 폭발.
|
- `.claude/settings.json`의 permissions.deny가 위 파일의 Read/Edit/Write 도구 사용을 차단한다 (이 저장소를 열면 자동 적용). deny는 **glob** — `ui/*.ui`·`map/*.map`·`RootDesk/MyDesk/*.codeblock`·`Global/common.gamelogic`·`Global/SectorConfig.config`. 따라서 **메이커 저작 codeblock/UI**(`Monster`·`MonsterAttack`·`PlayerAttack`·`PlayerHit`·`UIPopup`·`UIToast`.codeblock, **그리고 모든 `ui/*.ui`** — UI는 6개 UIGroup으로 메이커 저작)**도** Read/Edit 금지 — 이들은 생성기가 없으니 **메이커에서** 편집한다(텍스트 도구로 X). codeblock은 한 줄짜리 JSON이라 Read 시 토큰 폭발.
|
||||||
- 게임 로직·UI 수정 = **`tools/deck/gen-slaydeck.mjs`(오케스트레이터 + codeblock Lua) 또는 `data/*.json`(데이터)을 수정** → 재생성 → 산출물은 통째로 커밋.
|
- **게임 로직 수정** = `tools/deck/gen-slaydeck.mjs`(오케스트레이터) + `tools/deck/cb/*.mjs`(codeblock Lua) 또는 `data/*.json`(데이터) 수정 → 재생성(`SlayDeckController.codeblock`+`common.gamelogic`만, **`.ui` 미접근**) → 통째로 커밋. **UI 수정 = 메이커에서**(생성기는 UI를 안 만든다).
|
||||||
- **UI emit은 HUD별 모듈** `tools/deck/hud/*.mjs`(shop·combat·map·deckall·soulshop 등 15종 — **charselect는 제외: Phase 2에서 메이커 저작 stock으로 이관**, 아래), **codeblock 메서드(Lua)는 기능별 모듈** `tools/deck/cb/*.mjs`(boot·state·combat·hand·deckview·items·map·shop 등 17종, 메서드 161개를 연속런으로). **공유분**: UI 헬퍼·상수·데이터·lua 테이블 = `tools/deck/lib/ui-helpers.mjs`·`tools/deck/lib/data.mjs`, method/prop/codeblock 헬퍼·writeCodeblocks 상수 = `tools/deck/lib/codeblock.mjs`. 특정 화면 UI 수정은 `hud/<name>.mjs`, 특정 메서드 수정은 `cb/<name>.mjs`만(의존: orchestrator→{hud,cb}→lib 단방향). prop 103개는 오케스트레이터 writeCodeblocks에 유지. **cb 모듈은 원본 메서드 순서 보존이 바이트동일 조건** — 새 메서드는 해당 기능 모듈의 알맞은 위치에 추가하고 writeCodeblocks의 spread 순서 유지.
|
- **codeblock 메서드(Lua)는 기능별 모듈** `tools/deck/cb/*.mjs`(boot·state·combat·hand·deckview·items·map·shop 등 17종). **공유분**: 상수·데이터·lua 테이블 = `tools/deck/lib/{ui-helpers,data,codeblock}.mjs`(cb가 import — `MAX_MONSTERS`=4 등). prop 103개는 오케스트레이터 `writeCodeblocks`에 유지. 특정 메서드 수정은 `cb/<name>.mjs`만(의존: orchestrator→cb→lib 단방향). **cb 모듈은 원본 메서드 순서 보존이 바이트동일 조건**. **UI emit(옛 `hud/*.mjs` 15종·`gen-cardhand.mjs`)은 `tools/deck/legacy/`로 이관 — 휴면(생성기 미사용)**: UI가 메이커 저작이라 생성기가 안 만든다. (롤백용 `legacy/upsert-ui.mjs`는 직접 실행 시에만 옛 `DefaultGroup.ui`를 재생성.)
|
||||||
- 리팩터 시 **출력 바이트-동일 검증**: `node tools/deck/gen-slaydeck.mjs` 후 `node tools/verify/diffcheck.mjs [ref]`(워킹트리 vs ref(기본 HEAD) 줄바꿈 정규화 비교 — 산출물 경로를 명령줄에 노출 안 해 deny 회피). 산출물 ` M`은 보통 autocrlf churn이니 `git checkout --`로 복원.
|
- 리팩터 시 **출력 바이트-동일 검증**: `node tools/deck/gen-slaydeck.mjs` 후 `node tools/verify/diffcheck.mjs [ref]`(워킹트리 vs ref(기본 HEAD) 줄바꿈 정규화 비교 — 산출물 경로를 명령줄에 노출 안 해 deny 회피). 산출물 ` M`은 보통 autocrlf churn이니 `git checkout --`로 복원.
|
||||||
- **하이브리드(메이커 저작) 화면 — charselect 파일럿(Phase 2)**: `CharacterSelectHud`는 `GENERATED_UI_SECTIONS`에서 빠져 **생성기가 안 만들고 안 덮음** = `ui/DefaultGroup.ui`의 charselect 엔티티는 **메이커에서 시각 편집하는 stock**. 컨트롤러(`cb/charselect.mjs`)가 경로(`CharacterSelectHud/{Warrior,Thief,Mage}Button/Art` 등 — 메이커가 이 경로 유지 필수)로 이미지(`self.ClassPortraits`, `data/characters.json` 시드)·선택테두리·상태를 **런타임 주입**. 즉 레이아웃=메이커, 내용=컨트롤러. charselect 레이아웃 수정은 `hud/`가 아니라 **메이커에서**.
|
- **UI 전면 메이커 저작 (2026-06-17~)**: 단일 `DefaultGroup`을 7개 UIGroup으로 분리 — `DefaultGroup`(MainMenu+월드조작), `SelectUIGroup`(charselect/job), `LobbyUIGroup`(lobby/board/soulshop), `RunUIGroup`(combat/map/shop/rest/treasure/reward/cardhand/deck), `DeckUIGroup`(덱 도감), `PopupGroup`·`ToastGroup`. 컨트롤러(`cb/*.mjs`)는 엔티티 **경로**(`/ui/<UIGroup>/<Hud>/...`)로 텍스트·이미지·표시숨김·상태기반 위치/크기/색을 **런타임 주입**(레이아웃=메이커, 내용=컨트롤러 — 메이커가 이 경로 유지 필수). 몬스터 슬롯 = `RunUIGroup/CombatHud/MonsterStatus{1..4}`(자식 Name·Hp·Intent·HpBarFill·Buffs·BlockBadge·TargetMarker; TargetFrame 없음). **부트 흐름**: `OnBeginPlay`→MainMenu→(`MainMenu/NewGameButton`)→로비→run NPC(`OnLobbyNpcInteract` id=="run")→charselect→런. **재연결 검증**: `node tools/verify/cbgap.mjs`(cb 참조 경로↔.ui GAP 0이어야) + 재생성 후 `git status -- ui/` 변경 0(생성기 .ui 미접근 증명). 섹션→UIGroup 일괄 remap 마이그레이션은 `tools/deck/reconnect-ui-paths.mjs`(멱등). UIGroup별 .ui 분포 확인은 `tools/verify/uimap.mjs`.
|
||||||
- **머지 충돌(gen-slaydeck.mjs)**: 다른 브랜치가 단일체를 수정해 충돌나면, 그쪽 버전(`git checkout --theirs tools/deck/gen-slaydeck.mjs`)을 취해 **콘텐츠 마커 기반으로 재모듈화**(라인인덱스 X — 줄 추가에 안전·export 이름 자동 파생·`const x=[]` 직전 전문 상수 walk-back 포함) 후 `node tools/verify/diffcheck.mjs origin/main`으로 ui·codeblock 바이트-동일 확인(손실 0 증명). codeblock 메서드·patchCommon은 오케스트레이터 잔류라 그쪽 변경은 자동 보존됨.
|
- **머지 충돌(gen-slaydeck.mjs)**: 다른 브랜치가 단일체를 수정해 충돌나면, 그쪽 버전(`git checkout --theirs tools/deck/gen-slaydeck.mjs`)을 취해 **콘텐츠 마커 기반으로 재모듈화**(라인인덱스 X — 줄 추가에 안전·export 이름 자동 파생·`const x=[]` 직전 전문 상수 walk-back 포함) 후 `node tools/verify/diffcheck.mjs origin/main`으로 ui·codeblock 바이트-동일 확인(손실 0 증명). codeblock 메서드·patchCommon은 오케스트레이터 잔류라 그쪽 변경은 자동 보존됨.
|
||||||
- **보조 생성기**(각자 자기 산출물의 단일 소스 — 위 표의 메인 `gen-slaydeck.mjs` 외):
|
- **보조 생성기**(각자 자기 산출물의 단일 소스 — 위 표의 메인 `gen-slaydeck.mjs` 외):
|
||||||
- `tools/camera/gen-camera.mjs` → `MapCamera.codeblock` + map01~05 카메라 부착 (값 `data/camera.json`)
|
- `tools/camera/gen-camera.mjs` → `MapCamera.codeblock` + map01~05 카메라 부착 (값 `data/camera.json`)
|
||||||
@@ -37,7 +37,7 @@ Claude Code는 `CLAUDE.md`가 이 파일을 임포트하므로 자동 적용된
|
|||||||
- `tools/player/gen-player-lock.mjs` → `PlayerLock.codeblock` + map01~05 부착
|
- `tools/player/gen-player-lock.mjs` → `PlayerLock.codeblock` + map01~05 부착
|
||||||
- `tools/player/gen-lobby-npc.mjs` → `LobbyNpc.codeblock`·`LobbyMobility.codeblock`
|
- `tools/player/gen-lobby-npc.mjs` → `LobbyNpc.codeblock`·`LobbyMobility.codeblock`
|
||||||
- `tools/player/freeze-turn-player.mjs` → `Global/DefaultPlayer.model` 이동 0 고정
|
- `tools/player/freeze-turn-player.mjs` → `Global/DefaultPlayer.model` 이동 0 고정
|
||||||
- `tools/deck/gen-cardhand.mjs` → `DefaultGroup.ui` 카드핸드 보조 패처
|
- (옛 `tools/deck/gen-cardhand.mjs`·`hud/*.mjs`는 `tools/deck/legacy/`로 이관 — 휴면, UI 메이커 저작 전환)
|
||||||
|
|
||||||
## 2. 산출물 검증은 카운트로, 내용 출력 금지
|
## 2. 산출물 검증은 카운트로, 내용 출력 금지
|
||||||
|
|
||||||
|
|||||||
23
RootDesk/MyDesk/Character select bg.sprite
Normal file
23
RootDesk/MyDesk/Character select bg.sprite
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"Id": "",
|
||||||
|
"GameId": "",
|
||||||
|
"EntryKey": "sprite://7629b520ced54d508b040681d06741fb",
|
||||||
|
"ContentType": "x-mod/sprite",
|
||||||
|
"Content": "",
|
||||||
|
"Usage": 0,
|
||||||
|
"UsePublish": 1,
|
||||||
|
"UseService": 0,
|
||||||
|
"CoreVersion": "26.5.0.0",
|
||||||
|
"StudioVersion": "0.1.0.0",
|
||||||
|
"DynamicLoading": 0,
|
||||||
|
"ContentProto": {
|
||||||
|
"Use": "Json",
|
||||||
|
"Json": {
|
||||||
|
"upload_keyname": "30/54/30542a379cb74d2d807104635740a8ea/sprite/7629b520ced54d508b040681d06741fb/639172208899179951",
|
||||||
|
"upload_hash": "C84DCE36101CF3F05E74F93F9B416E7D08D8B78B699E22CF8A6784994115DDAE",
|
||||||
|
"name": "Character select bg",
|
||||||
|
"resource_guid": "7629b520ced54d508b040681d06741fb",
|
||||||
|
"resource_version": "6a316d1a3d5de2eb0c7d345b"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
RootDesk/MyDesk/MapleTree.codeblock
Normal file
36
RootDesk/MyDesk/MapleTree.codeblock
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"Id": "",
|
||||||
|
"GameId": "",
|
||||||
|
"EntryKey": "codeblock://4a220aa8-e014-4c7b-8234-fff8c5c66686",
|
||||||
|
"ContentType": "x-mod/codeblock",
|
||||||
|
"Content": "",
|
||||||
|
"Usage": 0,
|
||||||
|
"UsePublish": 1,
|
||||||
|
"UseService": 0,
|
||||||
|
"CoreVersion": "26.5.0.0",
|
||||||
|
"StudioVersion": "0.1.0.0",
|
||||||
|
"DynamicLoading": 0,
|
||||||
|
"ContentProto": {
|
||||||
|
"Use": "Json",
|
||||||
|
"Json": {
|
||||||
|
"CoreVersion": {
|
||||||
|
"Major": 0,
|
||||||
|
"Minor": 2
|
||||||
|
},
|
||||||
|
"ScriptVersion": {
|
||||||
|
"Major": 1,
|
||||||
|
"Minor": 1
|
||||||
|
},
|
||||||
|
"Description": "",
|
||||||
|
"Id": "4a220aa8-e014-4c7b-8234-fff8c5c66686",
|
||||||
|
"Language": 1,
|
||||||
|
"Name": "MapleTree",
|
||||||
|
"Type": 1,
|
||||||
|
"Source": 0,
|
||||||
|
"Target": null,
|
||||||
|
"Properties": [],
|
||||||
|
"Methods": [],
|
||||||
|
"EntityEventHandlers": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
23
RootDesk/MyDesk/Thumnail.sprite
Normal file
23
RootDesk/MyDesk/Thumnail.sprite
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"Id": "",
|
||||||
|
"GameId": "",
|
||||||
|
"EntryKey": "sprite://41ad73da083d41b0ae30bf7b86794376",
|
||||||
|
"ContentType": "x-mod/sprite",
|
||||||
|
"Content": "",
|
||||||
|
"Usage": 0,
|
||||||
|
"UsePublish": 1,
|
||||||
|
"UseService": 0,
|
||||||
|
"CoreVersion": "26.5.0.0",
|
||||||
|
"StudioVersion": "0.1.0.0",
|
||||||
|
"DynamicLoading": 0,
|
||||||
|
"ContentProto": {
|
||||||
|
"Use": "Json",
|
||||||
|
"Json": {
|
||||||
|
"upload_keyname": "30/54/30542a379cb74d2d807104635740a8ea/sprite/41ad73da083d41b0ae30bf7b86794376/639172145413258274",
|
||||||
|
"upload_hash": "CFC620F96E1621FEE5594456FC8A4157BC6EF0D3E7661C5543293200FD364A85",
|
||||||
|
"name": "Thumnail",
|
||||||
|
"resource_guid": "41ad73da083d41b0ae30bf7b86794376",
|
||||||
|
"resource_version": "6a31544d335c959bb11f45eb"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
RootDesk/MyDesk/restBgImage.sprite
Normal file
23
RootDesk/MyDesk/restBgImage.sprite
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"Id": "",
|
||||||
|
"GameId": "",
|
||||||
|
"EntryKey": "sprite://477679b832b44e099a30e4905078dbcb",
|
||||||
|
"ContentType": "x-mod/sprite",
|
||||||
|
"Content": "",
|
||||||
|
"Usage": 0,
|
||||||
|
"UsePublish": 1,
|
||||||
|
"UseService": 0,
|
||||||
|
"CoreVersion": "26.5.0.0",
|
||||||
|
"StudioVersion": "0.1.0.0",
|
||||||
|
"DynamicLoading": 0,
|
||||||
|
"ContentProto": {
|
||||||
|
"Use": "Json",
|
||||||
|
"Json": {
|
||||||
|
"upload_keyname": "30/54/30542a379cb74d2d807104635740a8ea/sprite/477679b832b44e099a30e4905078dbcb/639172226341792721",
|
||||||
|
"upload_hash": "3E30B07C24C4BC4E373CDEA653035146D2F50ACC6484F6E9DA34E6179BB38F15",
|
||||||
|
"name": "restBgImage",
|
||||||
|
"resource_guid": "477679b832b44e099a30e4905078dbcb",
|
||||||
|
"resource_version": "6a3173ea002bbe95706406b6"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
RootDesk/MyDesk/shopBgImage.sprite
Normal file
23
RootDesk/MyDesk/shopBgImage.sprite
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"Id": "",
|
||||||
|
"GameId": "",
|
||||||
|
"EntryKey": "sprite://28f3b10ac0334fbfbf29677bf963c57a",
|
||||||
|
"ContentType": "x-mod/sprite",
|
||||||
|
"Content": "",
|
||||||
|
"Usage": 0,
|
||||||
|
"UsePublish": 1,
|
||||||
|
"UseService": 0,
|
||||||
|
"CoreVersion": "26.5.0.0",
|
||||||
|
"StudioVersion": "0.1.0.0",
|
||||||
|
"DynamicLoading": 0,
|
||||||
|
"ContentProto": {
|
||||||
|
"Use": "Json",
|
||||||
|
"Json": {
|
||||||
|
"upload_keyname": "30/54/30542a379cb74d2d807104635740a8ea/sprite/28f3b10ac0334fbfbf29677bf963c57a/639172222414073214",
|
||||||
|
"upload_hash": "01BE0B58F480BA86DA1D18BFE25C01E1B27219A14FE2DCD73456A7A48553CF15",
|
||||||
|
"name": "shopBgImage",
|
||||||
|
"resource_guid": "28f3b10ac0334fbfbf29677bf963c57a",
|
||||||
|
"resource_version": "6a3172612c6a274be88a130e"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
RootDesk/MyDesk/treasureBgImage.sprite
Normal file
23
RootDesk/MyDesk/treasureBgImage.sprite
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"Id": "",
|
||||||
|
"GameId": "",
|
||||||
|
"EntryKey": "sprite://dd6193fd37da4b12bcdbcdcf2fbe8e40",
|
||||||
|
"ContentType": "x-mod/sprite",
|
||||||
|
"Content": "",
|
||||||
|
"Usage": 0,
|
||||||
|
"UsePublish": 1,
|
||||||
|
"UseService": 0,
|
||||||
|
"CoreVersion": "26.5.0.0",
|
||||||
|
"StudioVersion": "0.1.0.0",
|
||||||
|
"DynamicLoading": 0,
|
||||||
|
"ContentProto": {
|
||||||
|
"Use": "Json",
|
||||||
|
"Json": {
|
||||||
|
"upload_keyname": "30/54/30542a379cb74d2d807104635740a8ea/sprite/dd6193fd37da4b12bcdbcdcf2fbe8e40/639172228832890845",
|
||||||
|
"upload_hash": "3EDD046B291806637ADD12A77BF94CF00BDD9F4F9912C132B14323D9DE5F297C",
|
||||||
|
"name": "treasureBgImage",
|
||||||
|
"resource_guid": "dd6193fd37da4b12bcdbcdcf2fbe8e40",
|
||||||
|
"resource_version": "6a3174e32a2802c06419f288"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
282
data/cards.json
282
data/cards.json
@@ -378,7 +378,8 @@
|
|||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "피해를 3 줍니다. 약화를 1 부여합니다.",
|
"desc": "피해를 3 줍니다. 약화를 1 부여합니다.",
|
||||||
"weak": 1,
|
"weak": 1,
|
||||||
"damage": 3
|
"damage": 3,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"SilentStrike": {
|
"SilentStrike": {
|
||||||
"name": "타격",
|
"name": "타격",
|
||||||
@@ -387,7 +388,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "피해를 6 줍니다.",
|
"desc": "피해를 6 줍니다.",
|
||||||
"damage": 6
|
"damage": 6,
|
||||||
|
"image": "92a5020c978c46bdabab910598118b86"
|
||||||
},
|
},
|
||||||
"Survivor": {
|
"Survivor": {
|
||||||
"name": "생존자",
|
"name": "생존자",
|
||||||
@@ -397,7 +399,8 @@
|
|||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "방어도를 8 얻습니다. 카드를 1장 버립니다.",
|
"desc": "방어도를 8 얻습니다. 카드를 1장 버립니다.",
|
||||||
"block": 8,
|
"block": 8,
|
||||||
"discard": 1
|
"discard": 1,
|
||||||
|
"image": "49c8f279bfa64bf3954037f17da0052d"
|
||||||
},
|
},
|
||||||
"SilentDefend": {
|
"SilentDefend": {
|
||||||
"name": "수비",
|
"name": "수비",
|
||||||
@@ -406,7 +409,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "방어도를 5 얻습니다.",
|
"desc": "방어도를 5 얻습니다.",
|
||||||
"block": 5
|
"block": 5,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"Slice": {
|
"Slice": {
|
||||||
"name": "칼질",
|
"name": "칼질",
|
||||||
@@ -415,7 +419,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "피해를 6 줍니다.",
|
"desc": "피해를 6 줍니다.",
|
||||||
"damage": 6
|
"damage": 6,
|
||||||
|
"image": "92a5020c978c46bdabab910598118b86"
|
||||||
},
|
},
|
||||||
"Shiv": {
|
"Shiv": {
|
||||||
"name": "표창",
|
"name": "표창",
|
||||||
@@ -426,7 +431,8 @@
|
|||||||
"desc": "피해를 4 줍니다. 소멸.",
|
"desc": "피해를 4 줍니다. 소멸.",
|
||||||
"damage": 4,
|
"damage": 4,
|
||||||
"exhaust": true,
|
"exhaust": true,
|
||||||
"token": true
|
"token": true,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"DaggerSpray": {
|
"DaggerSpray": {
|
||||||
"name": "단검 분사",
|
"name": "단검 분사",
|
||||||
@@ -437,7 +443,8 @@
|
|||||||
"desc": "모든 적에게 피해를 4만큼 2번 줍니다.",
|
"desc": "모든 적에게 피해를 4만큼 2번 줍니다.",
|
||||||
"aoe": true,
|
"aoe": true,
|
||||||
"damage": 4,
|
"damage": 4,
|
||||||
"hits": 2
|
"hits": 2,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"DaggerThrow": {
|
"DaggerThrow": {
|
||||||
"name": "단검 투척",
|
"name": "단검 투척",
|
||||||
@@ -448,7 +455,8 @@
|
|||||||
"desc": "피해를 9 줍니다. 카드를 1장 뽑습니다. 카드를 1장 버립니다.",
|
"desc": "피해를 9 줍니다. 카드를 1장 뽑습니다. 카드를 1장 버립니다.",
|
||||||
"draw": 1,
|
"draw": 1,
|
||||||
"damage": 9,
|
"damage": 9,
|
||||||
"discard": 1
|
"discard": 1,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"PoisonedStab": {
|
"PoisonedStab": {
|
||||||
"name": "독 찌르기",
|
"name": "독 찌르기",
|
||||||
@@ -458,7 +466,8 @@
|
|||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "피해를 6 줍니다. 중독을 3 부여합니다.",
|
"desc": "피해를 6 줍니다. 중독을 3 부여합니다.",
|
||||||
"poison": 3,
|
"poison": 3,
|
||||||
"damage": 6
|
"damage": 6,
|
||||||
|
"image": "19361e72087946b1888684185b40d935"
|
||||||
},
|
},
|
||||||
"SuckerPunch": {
|
"SuckerPunch": {
|
||||||
"name": "불의의 일격",
|
"name": "불의의 일격",
|
||||||
@@ -468,7 +477,8 @@
|
|||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "피해를 8 줍니다. 약화를 1 부여합니다.",
|
"desc": "피해를 8 줍니다. 약화를 1 부여합니다.",
|
||||||
"weak": 1,
|
"weak": 1,
|
||||||
"damage": 8
|
"damage": 8,
|
||||||
|
"image": "92a5020c978c46bdabab910598118b86"
|
||||||
},
|
},
|
||||||
"LeadingStrike": {
|
"LeadingStrike": {
|
||||||
"name": "선제 타격",
|
"name": "선제 타격",
|
||||||
@@ -478,7 +488,8 @@
|
|||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "피해를 3 줍니다. 표창을 2장 손으로 가져옵니다.",
|
"desc": "피해를 3 줍니다. 표창을 2장 손으로 가져옵니다.",
|
||||||
"damage": 3,
|
"damage": 3,
|
||||||
"addShiv": 2
|
"addShiv": 2,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"FollowThrough": {
|
"FollowThrough": {
|
||||||
"name": "완수",
|
"name": "완수",
|
||||||
@@ -487,7 +498,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "피해를 7 줍니다. 손에 다른 카드가 5장 이상 있다면, 1번 추가로 적중합니다.",
|
"desc": "피해를 7 줍니다. 손에 다른 카드가 5장 이상 있다면, 1번 추가로 적중합니다.",
|
||||||
"damage": 7
|
"damage": 7,
|
||||||
|
"image": "92a5020c978c46bdabab910598118b86"
|
||||||
},
|
},
|
||||||
"FlickFlack": {
|
"FlickFlack": {
|
||||||
"name": "재주넘기",
|
"name": "재주넘기",
|
||||||
@@ -498,7 +510,8 @@
|
|||||||
"desc": "교활. 모든 적에게 피해를 6 줍니다.",
|
"desc": "교활. 모든 적에게 피해를 6 줍니다.",
|
||||||
"aoe": true,
|
"aoe": true,
|
||||||
"damage": 6,
|
"damage": 6,
|
||||||
"sly": true
|
"sly": true,
|
||||||
|
"image": "91a2d1c16cb041549adbf1a0d7b1f37f"
|
||||||
},
|
},
|
||||||
"Ricochet": {
|
"Ricochet": {
|
||||||
"name": "도탄",
|
"name": "도탄",
|
||||||
@@ -509,7 +522,8 @@
|
|||||||
"desc": "교활. 무작위 적에게 피해를 3만큼 4번 줍니다.",
|
"desc": "교활. 무작위 적에게 피해를 3만큼 4번 줍니다.",
|
||||||
"damage": 3,
|
"damage": 3,
|
||||||
"hits": 4,
|
"hits": 4,
|
||||||
"sly": true
|
"sly": true,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"Prepared": {
|
"Prepared": {
|
||||||
"name": "예비",
|
"name": "예비",
|
||||||
@@ -519,7 +533,8 @@
|
|||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "카드를 1장 뽑습니다. 카드를 1장 버립니다.",
|
"desc": "카드를 1장 뽑습니다. 카드를 1장 버립니다.",
|
||||||
"draw": 1,
|
"draw": 1,
|
||||||
"discard": 1
|
"discard": 1,
|
||||||
|
"image": "c1e19219745e44c39ae6ac2f77e347d9"
|
||||||
},
|
},
|
||||||
"Anticipate": {
|
"Anticipate": {
|
||||||
"name": "예측",
|
"name": "예측",
|
||||||
@@ -528,7 +543,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "이번 턴 동안 민첩을 2 얻습니다.",
|
"desc": "이번 턴 동안 민첩을 2 얻습니다.",
|
||||||
"dex": 2
|
"dex": 2,
|
||||||
|
"image": "49c8f279bfa64bf3954037f17da0052d"
|
||||||
},
|
},
|
||||||
"Deflect": {
|
"Deflect": {
|
||||||
"name": "튕겨내기",
|
"name": "튕겨내기",
|
||||||
@@ -537,7 +553,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "방어도를 4 얻습니다.",
|
"desc": "방어도를 4 얻습니다.",
|
||||||
"block": 4
|
"block": 4,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"BladeDance": {
|
"BladeDance": {
|
||||||
"name": "검무",
|
"name": "검무",
|
||||||
@@ -547,7 +564,8 @@
|
|||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "표창을 3장 손으로 가져옵니다. 소멸.",
|
"desc": "표창을 3장 손으로 가져옵니다. 소멸.",
|
||||||
"addShiv": 3,
|
"addShiv": 3,
|
||||||
"exhaust": true
|
"exhaust": true,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"Backflip": {
|
"Backflip": {
|
||||||
"name": "공중제비",
|
"name": "공중제비",
|
||||||
@@ -557,7 +575,8 @@
|
|||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "방어도를 5 얻습니다. 카드를 2장 뽑습니다.",
|
"desc": "방어도를 5 얻습니다. 카드를 2장 뽑습니다.",
|
||||||
"block": 5,
|
"block": 5,
|
||||||
"draw": 2
|
"draw": 2,
|
||||||
|
"image": "91a2d1c16cb041549adbf1a0d7b1f37f"
|
||||||
},
|
},
|
||||||
"DodgeAndRoll": {
|
"DodgeAndRoll": {
|
||||||
"name": "구르기",
|
"name": "구르기",
|
||||||
@@ -566,7 +585,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "방어도를 4 얻습니다. 다음 턴에, 방어도를 4 얻습니다",
|
"desc": "방어도를 4 얻습니다. 다음 턴에, 방어도를 4 얻습니다",
|
||||||
"block": 4
|
"block": 4,
|
||||||
|
"image": "91a2d1c16cb041549adbf1a0d7b1f37f"
|
||||||
},
|
},
|
||||||
"PiercingWail": {
|
"PiercingWail": {
|
||||||
"name": "귀를 찢는 비명",
|
"name": "귀를 찢는 비명",
|
||||||
@@ -575,7 +595,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "이번 턴 동안 모든 적이 힘을 6 잃습니다. 소멸.",
|
"desc": "이번 턴 동안 모든 적이 힘을 6 잃습니다. 소멸.",
|
||||||
"draw": 1
|
"draw": 1,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"CloakAndDagger": {
|
"CloakAndDagger": {
|
||||||
"name": "망토와 단검",
|
"name": "망토와 단검",
|
||||||
@@ -585,7 +606,8 @@
|
|||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "방어도를 6 얻습니다. 표창을 1장 손으로 가져옵니다.",
|
"desc": "방어도를 6 얻습니다. 표창을 1장 손으로 가져옵니다.",
|
||||||
"block": 6,
|
"block": 6,
|
||||||
"addShiv": 1
|
"addShiv": 1,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"DeadlyPoison": {
|
"DeadlyPoison": {
|
||||||
"name": "맹독",
|
"name": "맹독",
|
||||||
@@ -594,7 +616,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "중독을 5 부여합니다.",
|
"desc": "중독을 5 부여합니다.",
|
||||||
"poison": 5
|
"poison": 5,
|
||||||
|
"image": "19361e72087946b1888684185b40d935"
|
||||||
},
|
},
|
||||||
"Snakebite": {
|
"Snakebite": {
|
||||||
"name": "뱀 물기",
|
"name": "뱀 물기",
|
||||||
@@ -604,7 +627,8 @@
|
|||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "보존. 중독을 7 부여합니다.",
|
"desc": "보존. 중독을 7 부여합니다.",
|
||||||
"poison": 7,
|
"poison": 7,
|
||||||
"retain": true
|
"retain": true,
|
||||||
|
"image": "19361e72087946b1888684185b40d935"
|
||||||
},
|
},
|
||||||
"Untouchable": {
|
"Untouchable": {
|
||||||
"name": "범접 불가",
|
"name": "범접 불가",
|
||||||
@@ -614,7 +638,8 @@
|
|||||||
"rarity": "normal",
|
"rarity": "normal",
|
||||||
"desc": "교활. 방어도를 6 얻습니다.",
|
"desc": "교활. 방어도를 6 얻습니다.",
|
||||||
"block": 6,
|
"block": 6,
|
||||||
"sly": true
|
"sly": true,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"Skewer": {
|
"Skewer": {
|
||||||
"name": "꼬챙이",
|
"name": "꼬챙이",
|
||||||
@@ -623,7 +648,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "피해를 8만큼 X번 줍니다.",
|
"desc": "피해를 8만큼 X번 줍니다.",
|
||||||
"draw": 1
|
"draw": 1,
|
||||||
|
"image": "92a5020c978c46bdabab910598118b86"
|
||||||
},
|
},
|
||||||
"Backstab": {
|
"Backstab": {
|
||||||
"name": "배신",
|
"name": "배신",
|
||||||
@@ -632,7 +658,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "선천성. 피해를 11 줍니다. 소멸.",
|
"desc": "선천성. 피해를 11 줍니다. 소멸.",
|
||||||
"damage": 11
|
"damage": 11,
|
||||||
|
"image": "b1360ed0c4b942309d240634b8f36872"
|
||||||
},
|
},
|
||||||
"PreciseCut": {
|
"PreciseCut": {
|
||||||
"name": "정밀한 베기",
|
"name": "정밀한 베기",
|
||||||
@@ -641,7 +668,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "피해를 13 줍니다. 손에 있는 다른 카드 1장당 피해량이 2 감소합니다.",
|
"desc": "피해를 13 줍니다. 손에 있는 다른 카드 1장당 피해량이 2 감소합니다.",
|
||||||
"damage": 13
|
"damage": 13,
|
||||||
|
"image": "92a5020c978c46bdabab910598118b86"
|
||||||
},
|
},
|
||||||
"Finisher": {
|
"Finisher": {
|
||||||
"name": "마무리",
|
"name": "마무리",
|
||||||
@@ -650,7 +678,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "이번 턴에 사용한 공격 카드 1장당 피해를 6 줍니다.",
|
"desc": "이번 턴에 사용한 공격 카드 1장당 피해를 6 줍니다.",
|
||||||
"damage": 6
|
"damage": 6,
|
||||||
|
"image": "b1360ed0c4b942309d240634b8f36872"
|
||||||
},
|
},
|
||||||
"MementoMori": {
|
"MementoMori": {
|
||||||
"name": "메멘토 모리",
|
"name": "메멘토 모리",
|
||||||
@@ -659,7 +688,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "피해를 9 줍니다. 이번 턴에 버린 카드 1장당 피해량이 4 증가합니다.",
|
"desc": "피해를 9 줍니다. 이번 턴에 버린 카드 1장당 피해량이 4 증가합니다.",
|
||||||
"damage": 9
|
"damage": 9,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"Strangle": {
|
"Strangle": {
|
||||||
"name": "목 조르기",
|
"name": "목 조르기",
|
||||||
@@ -668,7 +698,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "피해를 8 줍니다. 이번 턴에 카드를 사용할 때마다, 대상 적이 체력을 2 잃습니다.",
|
"desc": "피해를 8 줍니다. 이번 턴에 카드를 사용할 때마다, 대상 적이 체력을 2 잃습니다.",
|
||||||
"damage": 8
|
"damage": 8,
|
||||||
|
"image": "92a5020c978c46bdabab910598118b86"
|
||||||
},
|
},
|
||||||
"Flechettes": {
|
"Flechettes": {
|
||||||
"name": "프레췌",
|
"name": "프레췌",
|
||||||
@@ -677,7 +708,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "손에 있는 스킬 카드 1장당 피해를 5 줍니다.",
|
"desc": "손에 있는 스킬 카드 1장당 피해를 5 줍니다.",
|
||||||
"damage": 5
|
"damage": 5,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"Pounce": {
|
"Pounce": {
|
||||||
"name": "덮치기",
|
"name": "덮치기",
|
||||||
@@ -686,7 +718,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "피해를 12 줍니다. 다음에 사용하는 스킬 카드의 비용이 0 이 됩니다.",
|
"desc": "피해를 12 줍니다. 다음에 사용하는 스킬 카드의 비용이 0 이 됩니다.",
|
||||||
"damage": 12
|
"damage": 12,
|
||||||
|
"image": "91a2d1c16cb041549adbf1a0d7b1f37f"
|
||||||
},
|
},
|
||||||
"Dash": {
|
"Dash": {
|
||||||
"name": "돌진",
|
"name": "돌진",
|
||||||
@@ -696,7 +729,8 @@
|
|||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "방어도를 10 얻습니다. 피해를 10 줍니다.",
|
"desc": "방어도를 10 얻습니다. 피해를 10 줍니다.",
|
||||||
"block": 10,
|
"block": 10,
|
||||||
"damage": 10
|
"damage": 10,
|
||||||
|
"image": "91a2d1c16cb041549adbf1a0d7b1f37f"
|
||||||
},
|
},
|
||||||
"Predator": {
|
"Predator": {
|
||||||
"name": "천적",
|
"name": "천적",
|
||||||
@@ -706,7 +740,8 @@
|
|||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "피해를 15 줍니다. 다음 턴에, 카드를 2장 뽑습니다.",
|
"desc": "피해를 15 줍니다. 다음 턴에, 카드를 2장 뽑습니다.",
|
||||||
"draw": 2,
|
"draw": 2,
|
||||||
"damage": 15
|
"damage": 15,
|
||||||
|
"image": "b1360ed0c4b942309d240634b8f36872"
|
||||||
},
|
},
|
||||||
"Pinpoint": {
|
"Pinpoint": {
|
||||||
"name": "정밀 사격",
|
"name": "정밀 사격",
|
||||||
@@ -715,7 +750,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "피해를 15 줍니다. 이번 턴에 스킬을 사용할 때마다 비용이 1 감소합니다.",
|
"desc": "피해를 15 줍니다. 이번 턴에 스킬을 사용할 때마다 비용이 1 감소합니다.",
|
||||||
"damage": 15
|
"damage": 15,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"CalculatedGamble": {
|
"CalculatedGamble": {
|
||||||
"name": "계산된 도박",
|
"name": "계산된 도박",
|
||||||
@@ -724,7 +760,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "손에 있는 모든 카드를 버린 뒤, 버린 카드의 수만큼 카드를 뽑습니다. 소멸.",
|
"desc": "손에 있는 모든 카드를 버린 뒤, 버린 카드의 수만큼 카드를 뽑습니다. 소멸.",
|
||||||
"draw": 1
|
"draw": 1,
|
||||||
|
"image": "c1e19219745e44c39ae6ac2f77e347d9"
|
||||||
},
|
},
|
||||||
"Expose": {
|
"Expose": {
|
||||||
"name": "들춰내기",
|
"name": "들춰내기",
|
||||||
@@ -733,7 +770,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "대상 적의 모든 인공물과 방어도를 제거합니다. 취약을 2 부여합니다. 소멸.",
|
"desc": "대상 적의 모든 인공물과 방어도를 제거합니다. 취약을 2 부여합니다. 소멸.",
|
||||||
"vuln": 2
|
"vuln": 2,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"HiddenDaggers": {
|
"HiddenDaggers": {
|
||||||
"name": "숨겨진 단검",
|
"name": "숨겨진 단검",
|
||||||
@@ -743,7 +781,8 @@
|
|||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "카드를 2장 버립니다. 표창을 2장 손으로 가져옵니다.",
|
"desc": "카드를 2장 버립니다. 표창을 2장 손으로 가져옵니다.",
|
||||||
"discard": 2,
|
"discard": 2,
|
||||||
"addShiv": 2
|
"addShiv": 2,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"EscapePlan": {
|
"EscapePlan": {
|
||||||
"name": "탈출구",
|
"name": "탈출구",
|
||||||
@@ -753,7 +792,8 @@
|
|||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "카드를 1장 뽑습니다. 뽑은 카드가 스킬 카드라면, 방어도를 3 얻습니다.",
|
"desc": "카드를 1장 뽑습니다. 뽑은 카드가 스킬 카드라면, 방어도를 3 얻습니다.",
|
||||||
"block": 3,
|
"block": 3,
|
||||||
"draw": 1
|
"draw": 1,
|
||||||
|
"image": "91a2d1c16cb041549adbf1a0d7b1f37f"
|
||||||
},
|
},
|
||||||
"Acrobatics": {
|
"Acrobatics": {
|
||||||
"name": "곡예",
|
"name": "곡예",
|
||||||
@@ -763,7 +803,8 @@
|
|||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "카드를 3장 뽑습니다. 카드를 1장 버립니다.",
|
"desc": "카드를 3장 뽑습니다. 카드를 1장 버립니다.",
|
||||||
"draw": 3,
|
"draw": 3,
|
||||||
"discard": 1
|
"discard": 1,
|
||||||
|
"image": "91a2d1c16cb041549adbf1a0d7b1f37f"
|
||||||
},
|
},
|
||||||
"HandTrick": {
|
"HandTrick": {
|
||||||
"name": "손기술",
|
"name": "손기술",
|
||||||
@@ -772,7 +813,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "방어도를 7 얻습니다. 이번 턴 동안 손에 있는 스킬 카드 1장에 교활을 추가합니다.",
|
"desc": "방어도를 7 얻습니다. 이번 턴 동안 손에 있는 스킬 카드 1장에 교활을 추가합니다.",
|
||||||
"block": 7
|
"block": 7,
|
||||||
|
"image": "c1e19219745e44c39ae6ac2f77e347d9"
|
||||||
},
|
},
|
||||||
"Mirage": {
|
"Mirage": {
|
||||||
"name": "신기루",
|
"name": "신기루",
|
||||||
@@ -781,7 +823,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "모든 적에게 부여된 중독과 동일한 만큼의 방어도를 얻습니다. 소멸.",
|
"desc": "모든 적에게 부여된 중독과 동일한 만큼의 방어도를 얻습니다. 소멸.",
|
||||||
"draw": 1
|
"draw": 1,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"Expertise": {
|
"Expertise": {
|
||||||
"name": "전문성",
|
"name": "전문성",
|
||||||
@@ -790,7 +833,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "손에 있는 카드가 6장이 될 때까지 카드를 뽑습니다.",
|
"desc": "손에 있는 카드가 6장이 될 때까지 카드를 뽑습니다.",
|
||||||
"draw": 1
|
"draw": 1,
|
||||||
|
"image": "c1e19219745e44c39ae6ac2f77e347d9"
|
||||||
},
|
},
|
||||||
"BubbleBubble": {
|
"BubbleBubble": {
|
||||||
"name": "차오르는 독",
|
"name": "차오르는 독",
|
||||||
@@ -799,7 +843,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "적이 중독을 보유하고 있다면, 중독을 9 부여합니다.",
|
"desc": "적이 중독을 보유하고 있다면, 중독을 9 부여합니다.",
|
||||||
"poison": 9
|
"poison": 9,
|
||||||
|
"image": "19361e72087946b1888684185b40d935"
|
||||||
},
|
},
|
||||||
"Blur": {
|
"Blur": {
|
||||||
"name": "흐릿함",
|
"name": "흐릿함",
|
||||||
@@ -808,7 +853,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "방어도를 5 얻습니다. 다음 턴 시작 시 방어도가 사라지지 않습니다.",
|
"desc": "방어도를 5 얻습니다. 다음 턴 시작 시 방어도가 사라지지 않습니다.",
|
||||||
"block": 5
|
"block": 5,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"LegSweep": {
|
"LegSweep": {
|
||||||
"name": "다리 걸기",
|
"name": "다리 걸기",
|
||||||
@@ -818,7 +864,8 @@
|
|||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "약화를 2 부여합니다. 방어도를 11 얻습니다.",
|
"desc": "약화를 2 부여합니다. 방어도를 11 얻습니다.",
|
||||||
"block": 11,
|
"block": 11,
|
||||||
"weak": 2
|
"weak": 2,
|
||||||
|
"image": "91a2d1c16cb041549adbf1a0d7b1f37f"
|
||||||
},
|
},
|
||||||
"UpMySleeve": {
|
"UpMySleeve": {
|
||||||
"name": "비책",
|
"name": "비책",
|
||||||
@@ -827,7 +874,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "표창을 3장 손으로 가져옵니다. 이 카드의 비용이 1 감소합니다.",
|
"desc": "표창을 3장 손으로 가져옵니다. 이 카드의 비용이 1 감소합니다.",
|
||||||
"addShiv": 3
|
"addShiv": 3,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"BouncingFlask": {
|
"BouncingFlask": {
|
||||||
"name": "탄성 플라스크",
|
"name": "탄성 플라스크",
|
||||||
@@ -836,7 +884,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "무작위 적에게 중독을 3만큼 3번 부여합니다.",
|
"desc": "무작위 적에게 중독을 3만큼 3번 부여합니다.",
|
||||||
"poison": 9
|
"poison": 9,
|
||||||
|
"image": "19361e72087946b1888684185b40d935"
|
||||||
},
|
},
|
||||||
"Reflex": {
|
"Reflex": {
|
||||||
"name": "반사신경",
|
"name": "반사신경",
|
||||||
@@ -846,7 +895,8 @@
|
|||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "교활. 카드를 2장 뽑습니다.",
|
"desc": "교활. 카드를 2장 뽑습니다.",
|
||||||
"draw": 2,
|
"draw": 2,
|
||||||
"sly": true
|
"sly": true,
|
||||||
|
"image": "49c8f279bfa64bf3954037f17da0052d"
|
||||||
},
|
},
|
||||||
"Haze": {
|
"Haze": {
|
||||||
"name": "아지랑이",
|
"name": "아지랑이",
|
||||||
@@ -856,7 +906,8 @@
|
|||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "교활. 모든 적에게 중독을 4 부여합니다.",
|
"desc": "교활. 모든 적에게 중독을 4 부여합니다.",
|
||||||
"poison": 4,
|
"poison": 4,
|
||||||
"sly": true
|
"sly": true,
|
||||||
|
"image": "19361e72087946b1888684185b40d935"
|
||||||
},
|
},
|
||||||
"Tactician": {
|
"Tactician": {
|
||||||
"name": "전략가",
|
"name": "전략가",
|
||||||
@@ -867,7 +918,8 @@
|
|||||||
"desc": "교활. 을 얻습니다.",
|
"desc": "교활. 을 얻습니다.",
|
||||||
"powerEffect": "energyPerTurn",
|
"powerEffect": "energyPerTurn",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
"sly": true
|
"sly": true,
|
||||||
|
"image": "c1e19219745e44c39ae6ac2f77e347d9"
|
||||||
},
|
},
|
||||||
"WellLaidPlans": {
|
"WellLaidPlans": {
|
||||||
"name": "괜찮은 전략",
|
"name": "괜찮은 전략",
|
||||||
@@ -876,8 +928,9 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "내 턴 종료 시, 카드를 최대 1장까지 보존합니다.",
|
"desc": "내 턴 종료 시, 카드를 최대 1장까지 보존합니다.",
|
||||||
"powerEffect": "blockPerTurn",
|
"powerEffect": "retainOne",
|
||||||
"value": 2
|
"value": 1,
|
||||||
|
"image": "c1e19219745e44c39ae6ac2f77e347d9"
|
||||||
},
|
},
|
||||||
"InfiniteBlades": {
|
"InfiniteBlades": {
|
||||||
"name": "무한의 검날",
|
"name": "무한의 검날",
|
||||||
@@ -886,7 +939,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "내 턴 시작 시, 표창을 1장 손으로 가져옵니다.",
|
"desc": "내 턴 시작 시, 표창을 1장 손으로 가져옵니다.",
|
||||||
"turnStartShiv": 1
|
"turnStartShiv": 1,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"Footwork": {
|
"Footwork": {
|
||||||
"name": "발놀림",
|
"name": "발놀림",
|
||||||
@@ -895,7 +949,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "민첩을 2 얻습니다.",
|
"desc": "민첩을 2 얻습니다.",
|
||||||
"dex": 2
|
"dex": 2,
|
||||||
|
"image": "49c8f279bfa64bf3954037f17da0052d"
|
||||||
},
|
},
|
||||||
"Outbreak": {
|
"Outbreak": {
|
||||||
"name": "발병",
|
"name": "발병",
|
||||||
@@ -907,7 +962,8 @@
|
|||||||
"aoe": true,
|
"aoe": true,
|
||||||
"powerEffect": "strengthPerTurn",
|
"powerEffect": "strengthPerTurn",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
"damage": 11
|
"damage": 11,
|
||||||
|
"image": "19361e72087946b1888684185b40d935"
|
||||||
},
|
},
|
||||||
"NoxiousFumes": {
|
"NoxiousFumes": {
|
||||||
"name": "유독 가스",
|
"name": "유독 가스",
|
||||||
@@ -918,7 +974,8 @@
|
|||||||
"desc": "내 턴 시작 시, 모든 적에게 중독을 2 부여합니다.",
|
"desc": "내 턴 시작 시, 모든 적에게 중독을 2 부여합니다.",
|
||||||
"poison": 2,
|
"poison": 2,
|
||||||
"powerEffect": "strengthPerTurn",
|
"powerEffect": "strengthPerTurn",
|
||||||
"value": 1
|
"value": 1,
|
||||||
|
"image": "19361e72087946b1888684185b40d935"
|
||||||
},
|
},
|
||||||
"Accuracy": {
|
"Accuracy": {
|
||||||
"name": "정밀",
|
"name": "정밀",
|
||||||
@@ -928,7 +985,8 @@
|
|||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "표창의 피해량이 4 증가합니다.",
|
"desc": "표창의 피해량이 4 증가합니다.",
|
||||||
"powerEffect": "strengthPerTurn",
|
"powerEffect": "strengthPerTurn",
|
||||||
"value": 1
|
"value": 1,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"PhantomBlades": {
|
"PhantomBlades": {
|
||||||
"name": "환영검",
|
"name": "환영검",
|
||||||
@@ -938,7 +996,8 @@
|
|||||||
"rarity": "unique",
|
"rarity": "unique",
|
||||||
"desc": "표창이 보존을 얻습니다. 매 턴마다 처음으로 사용하는 표창의 피해량이 9 증가합니다.",
|
"desc": "표창이 보존을 얻습니다. 매 턴마다 처음으로 사용하는 표창의 피해량이 9 증가합니다.",
|
||||||
"powerEffect": "strengthPerTurn",
|
"powerEffect": "strengthPerTurn",
|
||||||
"value": 1
|
"value": 1,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"Speedster": {
|
"Speedster": {
|
||||||
"name": "스피드스터",
|
"name": "스피드스터",
|
||||||
@@ -950,7 +1009,8 @@
|
|||||||
"aoe": true,
|
"aoe": true,
|
||||||
"powerEffect": "strengthPerTurn",
|
"powerEffect": "strengthPerTurn",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
"damage": 2
|
"damage": 2,
|
||||||
|
"image": "91a2d1c16cb041549adbf1a0d7b1f37f"
|
||||||
},
|
},
|
||||||
"GrandFinale": {
|
"GrandFinale": {
|
||||||
"name": "대단원의 막",
|
"name": "대단원의 막",
|
||||||
@@ -960,7 +1020,8 @@
|
|||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "뽑을 카드 더미에 카드가 없을 때만 사용할 수 있습니다. 모든 적에게 피해를 60 줍니다.",
|
"desc": "뽑을 카드 더미에 카드가 없을 때만 사용할 수 있습니다. 모든 적에게 피해를 60 줍니다.",
|
||||||
"aoe": true,
|
"aoe": true,
|
||||||
"damage": 60
|
"damage": 60,
|
||||||
|
"image": "dbdbb1b56ae54672ae68ac6882fff6a2"
|
||||||
},
|
},
|
||||||
"Assassinate": {
|
"Assassinate": {
|
||||||
"name": "암살",
|
"name": "암살",
|
||||||
@@ -970,7 +1031,8 @@
|
|||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "선천성. 피해를 10 줍니다. 취약을 1 부여합니다. 소멸.",
|
"desc": "선천성. 피해를 10 줍니다. 취약을 1 부여합니다. 소멸.",
|
||||||
"vuln": 1,
|
"vuln": 1,
|
||||||
"damage": 10
|
"damage": 10,
|
||||||
|
"image": "b1360ed0c4b942309d240634b8f36872"
|
||||||
},
|
},
|
||||||
"EchoingSlash": {
|
"EchoingSlash": {
|
||||||
"name": "메아리 참격",
|
"name": "메아리 참격",
|
||||||
@@ -980,7 +1042,8 @@
|
|||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "모든 적에게 피해를 10 줍니다. 적을 처치할 때마다 이 효과를 반복합니다.",
|
"desc": "모든 적에게 피해를 10 줍니다. 적을 처치할 때마다 이 효과를 반복합니다.",
|
||||||
"aoe": true,
|
"aoe": true,
|
||||||
"damage": 10
|
"damage": 10,
|
||||||
|
"image": "dbdbb1b56ae54672ae68ac6882fff6a2"
|
||||||
},
|
},
|
||||||
"TheHunt": {
|
"TheHunt": {
|
||||||
"name": "사냥",
|
"name": "사냥",
|
||||||
@@ -989,7 +1052,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "피해를 10 줍니다. 치명타라면, 카드 보상을 추가로 얻습니다. 소멸.",
|
"desc": "피해를 10 줍니다. 치명타라면, 카드 보상을 추가로 얻습니다. 소멸.",
|
||||||
"damage": 10
|
"damage": 10,
|
||||||
|
"image": "b1360ed0c4b942309d240634b8f36872"
|
||||||
},
|
},
|
||||||
"Murder": {
|
"Murder": {
|
||||||
"name": "살해",
|
"name": "살해",
|
||||||
@@ -998,7 +1062,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "피해를 1 줍니다. 이번 전투 동안 뽑은 카드 1장당 피해량이 1 증가합니다.",
|
"desc": "피해를 1 줍니다. 이번 전투 동안 뽑은 카드 1장당 피해량이 1 증가합니다.",
|
||||||
"damage": 1
|
"damage": 1,
|
||||||
|
"image": "b1360ed0c4b942309d240634b8f36872"
|
||||||
},
|
},
|
||||||
"Malaise": {
|
"Malaise": {
|
||||||
"name": "불쾌",
|
"name": "불쾌",
|
||||||
@@ -1007,7 +1072,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "적이 힘을 X 잃습니다. 약화를 X 부여합니다. 소멸.",
|
"desc": "적이 힘을 X 잃습니다. 약화를 X 부여합니다. 소멸.",
|
||||||
"weak": 3
|
"weak": 3,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"Adrenaline": {
|
"Adrenaline": {
|
||||||
"name": "아드레날린",
|
"name": "아드레날린",
|
||||||
@@ -1018,7 +1084,8 @@
|
|||||||
"desc": "를 얻습니다. 카드를 2장 뽑습니다. 소멸.",
|
"desc": "를 얻습니다. 카드를 2장 뽑습니다. 소멸.",
|
||||||
"draw": 2,
|
"draw": 2,
|
||||||
"powerEffect": "energyPerTurn",
|
"powerEffect": "energyPerTurn",
|
||||||
"value": 1
|
"value": 1,
|
||||||
|
"image": "91a2d1c16cb041549adbf1a0d7b1f37f"
|
||||||
},
|
},
|
||||||
"StormOfSteel": {
|
"StormOfSteel": {
|
||||||
"name": "강철의 폭풍",
|
"name": "강철의 폭풍",
|
||||||
@@ -1028,7 +1095,8 @@
|
|||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "손에 있는 모든 카드를 버립니다. 버린 카드의 수만큼 표창을 손으로 가져옵니다.",
|
"desc": "손에 있는 모든 카드를 버립니다. 버린 카드의 수만큼 표창을 손으로 가져옵니다.",
|
||||||
"discardAll": true,
|
"discardAll": true,
|
||||||
"addShivPerDiscard": true
|
"addShivPerDiscard": true,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"ShadowStep": {
|
"ShadowStep": {
|
||||||
"name": "그림자 걸음",
|
"name": "그림자 걸음",
|
||||||
@@ -1038,7 +1106,8 @@
|
|||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "손에 있는 모든 카드를 버립니다. 다음 턴에, 공격 카드의 피해량이 2배가 됩니다.",
|
"desc": "손에 있는 모든 카드를 버립니다. 다음 턴에, 공격 카드의 피해량이 2배가 됩니다.",
|
||||||
"draw": 1,
|
"draw": 1,
|
||||||
"discardAll": true
|
"discardAll": true,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"Shadowmeld": {
|
"Shadowmeld": {
|
||||||
"name": "그림자 은신",
|
"name": "그림자 은신",
|
||||||
@@ -1047,7 +1116,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "이번 턴 동안 얻는 방어도가 2배가 됩니다.",
|
"desc": "이번 턴 동안 얻는 방어도가 2배가 됩니다.",
|
||||||
"draw": 1
|
"draw": 1,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"CorrosiveWave": {
|
"CorrosiveWave": {
|
||||||
"name": "부식성 파도",
|
"name": "부식성 파도",
|
||||||
@@ -1056,7 +1126,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "이번 턴에 카드를 뽑을 때마다, 모든 적에게 중독을 2 부여합니다.",
|
"desc": "이번 턴에 카드를 뽑을 때마다, 모든 적에게 중독을 2 부여합니다.",
|
||||||
"poison": 2
|
"poison": 2,
|
||||||
|
"image": "19361e72087946b1888684185b40d935"
|
||||||
},
|
},
|
||||||
"BladeOfInk": {
|
"BladeOfInk": {
|
||||||
"name": "잉크 칼날",
|
"name": "잉크 칼날",
|
||||||
@@ -1065,7 +1136,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "잉크투성이 표창을 2장 손으로 가져옵니다.",
|
"desc": "잉크투성이 표창을 2장 손으로 가져옵니다.",
|
||||||
"addShiv": 2
|
"addShiv": 2,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"Burst": {
|
"Burst": {
|
||||||
"name": "폭주",
|
"name": "폭주",
|
||||||
@@ -1074,7 +1146,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "이번 턴에 다음에 사용하는 스킬 카드가 1번 추가로 사용됩니다.",
|
"desc": "이번 턴에 다음에 사용하는 스킬 카드가 1번 추가로 사용됩니다.",
|
||||||
"draw": 1
|
"draw": 1,
|
||||||
|
"image": "91a2d1c16cb041549adbf1a0d7b1f37f"
|
||||||
},
|
},
|
||||||
"KnifeTrap": {
|
"KnifeTrap": {
|
||||||
"name": "칼날 함정",
|
"name": "칼날 함정",
|
||||||
@@ -1083,7 +1156,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "대상 적에게 소멸된 카드 더미에 있는 모든 표창을 사용합니다.",
|
"desc": "대상 적에게 소멸된 카드 더미에 있는 모든 표창을 사용합니다.",
|
||||||
"draw": 1
|
"draw": 1,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"BulletTime": {
|
"BulletTime": {
|
||||||
"name": "불릿 타임",
|
"name": "불릿 타임",
|
||||||
@@ -1093,7 +1167,8 @@
|
|||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "이번 턴 동안 더 이상 카드를 뽑을 수 없습니다. 이번 턴 동안 손에 있는 모든 카드를 비용 없이 사용할 수 있습니다.",
|
"desc": "이번 턴 동안 더 이상 카드를 뽑을 수 없습니다. 이번 턴 동안 손에 있는 모든 카드를 비용 없이 사용할 수 있습니다.",
|
||||||
"powerEffect": "energyPerTurn",
|
"powerEffect": "energyPerTurn",
|
||||||
"value": 1
|
"value": 1,
|
||||||
|
"image": "91a2d1c16cb041549adbf1a0d7b1f37f"
|
||||||
},
|
},
|
||||||
"Nightmare": {
|
"Nightmare": {
|
||||||
"name": "악몽",
|
"name": "악몽",
|
||||||
@@ -1102,7 +1177,8 @@
|
|||||||
"class": "bandit",
|
"class": "bandit",
|
||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "카드를 1장 선택합니다. 다음 턴에, 그 카드의 복사본을 3장 손으로 가져옵니다. 소멸.",
|
"desc": "카드를 1장 선택합니다. 다음 턴에, 그 카드의 복사본을 3장 손으로 가져옵니다. 소멸.",
|
||||||
"draw": 1
|
"draw": 1,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"ToolsOfTheTrade": {
|
"ToolsOfTheTrade": {
|
||||||
"name": "작업 도구",
|
"name": "작업 도구",
|
||||||
@@ -1114,7 +1190,8 @@
|
|||||||
"draw": 1,
|
"draw": 1,
|
||||||
"powerEffect": "energyPerTurn",
|
"powerEffect": "energyPerTurn",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
"discard": 1
|
"discard": 1,
|
||||||
|
"image": "c1e19219745e44c39ae6ac2f77e347d9"
|
||||||
},
|
},
|
||||||
"Afterimage": {
|
"Afterimage": {
|
||||||
"name": "잔상",
|
"name": "잔상",
|
||||||
@@ -1125,7 +1202,8 @@
|
|||||||
"desc": "카드를 사용할 때마다, 방어도를 1 얻습니다.",
|
"desc": "카드를 사용할 때마다, 방어도를 1 얻습니다.",
|
||||||
"block": 1,
|
"block": 1,
|
||||||
"powerEffect": "blockPerTurn",
|
"powerEffect": "blockPerTurn",
|
||||||
"value": 2
|
"value": 2,
|
||||||
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
},
|
},
|
||||||
"Accelerant": {
|
"Accelerant": {
|
||||||
"name": "촉진제",
|
"name": "촉진제",
|
||||||
@@ -1135,7 +1213,8 @@
|
|||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "중독이 1번 추가로 발동합니다.",
|
"desc": "중독이 1번 추가로 발동합니다.",
|
||||||
"powerEffect": "strengthPerTurn",
|
"powerEffect": "strengthPerTurn",
|
||||||
"value": 1
|
"value": 1,
|
||||||
|
"image": "19361e72087946b1888684185b40d935"
|
||||||
},
|
},
|
||||||
"Envenom": {
|
"Envenom": {
|
||||||
"name": "독 바르기",
|
"name": "독 바르기",
|
||||||
@@ -1146,7 +1225,8 @@
|
|||||||
"desc": "공격 카드가 막히지 않은 피해를 줄 때마다, 중독을 1 부여합니다.",
|
"desc": "공격 카드가 막히지 않은 피해를 줄 때마다, 중독을 1 부여합니다.",
|
||||||
"poison": 1,
|
"poison": 1,
|
||||||
"powerEffect": "strengthPerTurn",
|
"powerEffect": "strengthPerTurn",
|
||||||
"value": 1
|
"value": 1,
|
||||||
|
"image": "19361e72087946b1888684185b40d935"
|
||||||
},
|
},
|
||||||
"MasterPlanner": {
|
"MasterPlanner": {
|
||||||
"name": "설계의 대가",
|
"name": "설계의 대가",
|
||||||
@@ -1156,7 +1236,8 @@
|
|||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "스킬 카드를 사용 시, 그 카드가 교활을 얻습니다.",
|
"desc": "스킬 카드를 사용 시, 그 카드가 교활을 얻습니다.",
|
||||||
"powerEffect": "strengthPerTurn",
|
"powerEffect": "strengthPerTurn",
|
||||||
"value": 1
|
"value": 1,
|
||||||
|
"image": "c1e19219745e44c39ae6ac2f77e347d9"
|
||||||
},
|
},
|
||||||
"Tracking": {
|
"Tracking": {
|
||||||
"name": "추적",
|
"name": "추적",
|
||||||
@@ -1166,7 +1247,8 @@
|
|||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "약화 상태의 적이 공격 카드로 받는 피해가 2배가 됩니다.",
|
"desc": "약화 상태의 적이 공격 카드로 받는 피해가 2배가 됩니다.",
|
||||||
"powerEffect": "strengthPerTurn",
|
"powerEffect": "strengthPerTurn",
|
||||||
"value": 1
|
"value": 1,
|
||||||
|
"image": "b1360ed0c4b942309d240634b8f36872"
|
||||||
},
|
},
|
||||||
"FanOfKnives": {
|
"FanOfKnives": {
|
||||||
"name": "칼날 부채",
|
"name": "칼날 부채",
|
||||||
@@ -1177,7 +1259,8 @@
|
|||||||
"desc": "표창이 이제 모든 적을 대상으로 합니다. 표창을 4장 손으로 가져옵니다.",
|
"desc": "표창이 이제 모든 적을 대상으로 합니다. 표창을 4장 손으로 가져옵니다.",
|
||||||
"powerEffect": "strengthPerTurn",
|
"powerEffect": "strengthPerTurn",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
"addShiv": 4
|
"addShiv": 4,
|
||||||
|
"image": "1b0f2dc8abd0434990eee1befefcbe0d"
|
||||||
},
|
},
|
||||||
"SerpentForm": {
|
"SerpentForm": {
|
||||||
"name": "구렁이의 형상",
|
"name": "구렁이의 형상",
|
||||||
@@ -1188,7 +1271,8 @@
|
|||||||
"desc": "카드를 사용할 때마다, 무작위 적에게 피해를 4 줍니다.",
|
"desc": "카드를 사용할 때마다, 무작위 적에게 피해를 4 줍니다.",
|
||||||
"powerEffect": "strengthPerTurn",
|
"powerEffect": "strengthPerTurn",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
"damage": 4
|
"damage": 4,
|
||||||
|
"image": "19361e72087946b1888684185b40d935"
|
||||||
},
|
},
|
||||||
"Abrasive": {
|
"Abrasive": {
|
||||||
"name": "연마",
|
"name": "연마",
|
||||||
@@ -1199,7 +1283,8 @@
|
|||||||
"desc": "교활. 민첩을 1 얻습니다. 가시를 4 얻습니다.",
|
"desc": "교활. 민첩을 1 얻습니다. 가시를 4 얻습니다.",
|
||||||
"dex": 1,
|
"dex": 1,
|
||||||
"thorns": 4,
|
"thorns": 4,
|
||||||
"sly": true
|
"sly": true,
|
||||||
|
"image": "49c8f279bfa64bf3954037f17da0052d"
|
||||||
},
|
},
|
||||||
"Suppress": {
|
"Suppress": {
|
||||||
"name": "진압",
|
"name": "진압",
|
||||||
@@ -1209,7 +1294,8 @@
|
|||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "선천성. 피해를 11 줍니다. 약화를 3 부여합니다.",
|
"desc": "선천성. 피해를 11 줍니다. 약화를 3 부여합니다.",
|
||||||
"weak": 3,
|
"weak": 3,
|
||||||
"damage": 11
|
"damage": 11,
|
||||||
|
"image": "b1360ed0c4b942309d240634b8f36872"
|
||||||
},
|
},
|
||||||
"WraithForm": {
|
"WraithForm": {
|
||||||
"name": "유령의 형상",
|
"name": "유령의 형상",
|
||||||
@@ -1219,26 +1305,8 @@
|
|||||||
"rarity": "legend",
|
"rarity": "legend",
|
||||||
"desc": "불가침을 2 얻습니다. 내 턴 종료 시 민첩을 1 잃습니다.",
|
"desc": "불가침을 2 얻습니다. 내 턴 종료 시 민첩을 1 잃습니다.",
|
||||||
"powerEffect": "blockPerTurn",
|
"powerEffect": "blockPerTurn",
|
||||||
"value": 8
|
"value": 8,
|
||||||
},
|
"image": "0946f69d84464df29b24b94c744c868d"
|
||||||
"Flanking": {
|
|
||||||
"name": "측면 공격",
|
|
||||||
"cost": 2,
|
|
||||||
"kind": "Skill",
|
|
||||||
"class": "bandit",
|
|
||||||
"rarity": "legend",
|
|
||||||
"desc": "이번 턴에 대상 적이 다른 플레이어에게 받는 피해량이 2배가 됩니다.",
|
|
||||||
"draw": 1
|
|
||||||
},
|
|
||||||
"Sneaky": {
|
|
||||||
"name": "비열함",
|
|
||||||
"cost": 2,
|
|
||||||
"kind": "Skill",
|
|
||||||
"class": "bandit",
|
|
||||||
"rarity": "legend",
|
|
||||||
"desc": "교활. 다른 플레이어가 적을 공격할 때마다, 방어도를 1 얻습니다.",
|
|
||||||
"block": 1,
|
|
||||||
"sly": true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"starterDecks": {
|
"starterDecks": {
|
||||||
|
|||||||
@@ -119,6 +119,65 @@
|
|||||||
{ "kind": "Attack", "value": 12 },
|
{ "kind": "Attack", "value": 12 },
|
||||||
{ "kind": "Attack", "value": 24 }
|
{ "kind": "Attack", "value": 24 }
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"octopus": {
|
||||||
|
"name": "문어",
|
||||||
|
"maxHp": 15,
|
||||||
|
"intents": [
|
||||||
|
{ "kind": "Attack", "value": 5 },
|
||||||
|
{ "kind": "Attack", "value": 6 },
|
||||||
|
{ "kind": "Defend", "value": 4 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"kapa_drake": {
|
||||||
|
"name": "카파 드레이크",
|
||||||
|
"maxHp": 24,
|
||||||
|
"intents": [
|
||||||
|
{ "kind": "Attack", "value": 9 },
|
||||||
|
{ "kind": "Attack", "value": 6 },
|
||||||
|
{ "kind": "Defend", "value": 6 },
|
||||||
|
{ "kind": "Attack", "value": 11 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"junior_neki": {
|
||||||
|
"name": "주니어 네키",
|
||||||
|
"maxHp": 18,
|
||||||
|
"intents": [
|
||||||
|
{ "kind": "Attack", "value": 6 },
|
||||||
|
{ "kind": "Attack", "value": 8 },
|
||||||
|
{ "kind": "Debuff", "effect": "weak", "value": 1 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"junior_bugi": {
|
||||||
|
"name": "주니어 부기",
|
||||||
|
"maxHp": 20,
|
||||||
|
"intents": [
|
||||||
|
{ "kind": "Attack", "value": 7 },
|
||||||
|
{ "kind": "Defend", "value": 5 },
|
||||||
|
{ "kind": "Attack", "value": 9 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dile": {
|
||||||
|
"name": "다일",
|
||||||
|
"maxHp": 65,
|
||||||
|
"intents": [
|
||||||
|
{ "kind": "Attack", "value": 13 },
|
||||||
|
{ "kind": "Defend", "value": 9 },
|
||||||
|
{ "kind": "Attack", "value": 8 },
|
||||||
|
{ "kind": "Attack", "value": 16 },
|
||||||
|
{ "kind": "Debuff", "effect": "weak", "value": 1 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mano": {
|
||||||
|
"name": "마노",
|
||||||
|
"maxHp": 80,
|
||||||
|
"intents": [
|
||||||
|
{ "kind": "Defend", "value": 12 },
|
||||||
|
{ "kind": "Attack", "value": 14 },
|
||||||
|
{ "kind": "Debuff", "effect": "vuln", "value": 1 },
|
||||||
|
{ "kind": "Attack", "value": 10 },
|
||||||
|
{ "kind": "AddCard", "card": "Wound", "count": 1 }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"activeEnemy": "slime",
|
"activeEnemy": "slime",
|
||||||
|
|||||||
86
docs/deck-concept.md
Normal file
86
docs/deck-concept.md
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# SlayMaple 덱 컨셉 & 직업 스킬셋
|
||||||
|
|
||||||
|
> SlayMaple 카드 덱의 **직업별 컨셉 · 메이플 스킬셋 · Slay the Spire 2 차용 매칭** 설계 문서.
|
||||||
|
> 원칙: 카드 한 장 = **STS2 메커니즘(뼈대) + 메이플 스킬(외형)**. STS 고유 *표현*(카드명·아트·UI)은 모방 금지, *메커니즘*만 차용(IP 해석 심사 대비).
|
||||||
|
> 수치(데미지·코스트·등급)는 `tools/balance/sim-balance.mjs`로 검증. 본 문서는 *어떤 스킬을 어떤 카드로* 만들지의 설계도.
|
||||||
|
|
||||||
|
기준: 메이플 = **클래식(빅뱅 이전)** 스킬 외형, STS = **Slay the Spire 2**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 직업 ↔ STS2 매칭 요약
|
||||||
|
|
||||||
|
| 직업 | 컨셉 | STS2 차용 |
|
||||||
|
|---|---|---|
|
||||||
|
| ⚔️ 전사 | 단단한 탱커/브루저 | The Ironclad (힘·방어·소멸) |
|
||||||
|
| 🗡️ 도적 | 단검 난사 / 독 | The Silent (표창·독·교활) |
|
||||||
|
| 🔮 법사 | 약체 + 게이지 운용 | The Defect (오브·집중) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚔️ 전사 (Warrior) — HP80 · 탱커
|
||||||
|
|
||||||
|
방어를 쌓고 버티다 역공하는 브루저. Ironclad의 두 축을 2차 전직으로 분화.
|
||||||
|
|
||||||
|
### 파이터 — 콤보 브루저형 탱커
|
||||||
|
- **콤보 규칙**: 공격 카드를 **연속으로** 사용하면 콤보가 쌓인다. **방어·파워 등 비공격(Skill/Power) 카드를 사용하면 콤보가 리셋(0)** 된다.
|
||||||
|
- 콤보가 쌓일수록 **데미지 증가 버프(힘 계열)** 를 받는다 → 방어를 포기하고 공격을 몰아칠수록 강해지는 리스크/리워드.
|
||||||
|
- 차용: Ironclad 힘 스택/Demon Form + 콤보. 메이플 외형: 콤보 어택·분노·브랜디시.
|
||||||
|
|
||||||
|
### 페이지 — 방어 축적 → 바디 슬램 카운터
|
||||||
|
- **위협**(전체 적 약화+취약 디버프)로 버티며 **방어도를 축적**(아이언 월 등 + 방어 유지 retain).
|
||||||
|
- **바디 슬램**: 현재 방어도에 비례한 피해로 카운터. 파워 가드(반사) 보조.
|
||||||
|
- 차용: Ironclad 방어 빌드(Barricade+Entrench→Body Slam). 메이플 외형: 위협·아이언 월·파워 가드.
|
||||||
|
|
||||||
|
### 스피어맨 — 유지/리치형
|
||||||
|
- 하이퍼 바디(최대 HP↑)·아이언 월(방어 유지)·창 리치 광역. 공격 스케일(파이터)·방어 카운터(페이지)와 구분되는 지속 탱.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗡️ 도적 (Thief) — HP70 · 단검/독
|
||||||
|
|
||||||
|
Slay the Spire *Silent* 차용. **형(codex)이 Silent 88장 완역 포트 + 스킬 아이콘 적용 완료.** 3대 아키타입:
|
||||||
|
|
||||||
|
- **표창(Shiv) 난사**: 0코스트 표창 토큰 대량 생성 → 공격마다 연계. (정밀=표창 피해↑, 칼날 부채=표창 전체화)
|
||||||
|
- **독(Poison)**: 중독 중첩 → 매턴 틱뎀. (유독 가스·발병·촉진제·독 바르기)
|
||||||
|
- **교활(Sly)·버림(discard)**: 버려질 때 무료 발동, 얇은 덱 빠른 순환.
|
||||||
|
|
||||||
|
### 2차 갈래
|
||||||
|
- **어쌔신** — 표창 난사 + 크리 / 흡혈(드레인) 중심.
|
||||||
|
- **시프** — 단검 난타(새비지 블로우 = 다단히트) + 독 / 버림 중심.
|
||||||
|
|
||||||
|
> 남은 작업: 카드명이 STS 직역(무력화·배신·아드레날린 등) → **어쌔신/시프 메이플 스킬명으로 재서사** + 멀티플레이어 전제 카드(측면 공격·비열함·추적) 싱글 출품용 정리.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔮 법사 (Magician) — HP70 · 약체/게이지
|
||||||
|
|
||||||
|
몸은 약하나 **게이지(오브) 운용**으로 다중 공격·화력 집중. **오브 메커니즘은 위자드(불/독·썬/콜)에만 적용**, 클레릭은 별도 보조 컨셉.
|
||||||
|
|
||||||
|
### 위자드(불/독) — 독 + 불 시너지
|
||||||
|
- **독을 묻히는 스킬**(포이즌 브레스 등)으로 대상에 독을 부여(독뎀 = DoT).
|
||||||
|
- **독이 묻은 적에게 불 카드(파이어 애로우 등)를 쓰면 추가 데미지** — *독뎀 상수* 보너스(독 스택/상수 비례).
|
||||||
|
- 즉 "독 깔기 → 불로 폭발"의 2단 콤보. 불·독 오브로 운용.
|
||||||
|
|
||||||
|
### 위자드(썬/콜) — 오브 운용(썬더 다중 / 콜드 빙결)
|
||||||
|
- **오브로 썬더·콜드를 보유**. **썬더 = 다중 공격 특화**(AoE·다단). **콜드 = 빙결 부여**(빙결 = *취약과 동일 효과* 를 데미지와 함께).
|
||||||
|
- **오브를 사용하는 만큼 오브를 획득하거나 다중 소모**하는 방식 — 오브 수급/소비 운용이 핵심.
|
||||||
|
|
||||||
|
### 클레릭 — 보조(회복·버프) · 오브 없음
|
||||||
|
- **회복 스킬**(힐)과 **각종 버프**(블레스 등) 중심의 서포트.
|
||||||
|
- **언데드 계열 몬스터에게는 힐로 공격** 가능 — 보조 힐러 정체성.
|
||||||
|
|
||||||
|
> ⚠️ 위자드 오브/게이지·전사 콤보 스택·바디 슬램·독뎀 시너지는 **신규 메커니즘** — `tools/deck/gen-slaydeck.mjs`(전투 규칙) + `tools/balance/sim-balance.mjs`(JS 미러) 양쪽 구현·동기화 필요.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 차용 경계 (IP 심사 대비)
|
||||||
|
|
||||||
|
- 차용 OK = **메커니즘**(콤보 스택·방어→피해 전환·독+불 시너지·오브 게이지·빙결=취약 등 시스템).
|
||||||
|
- 모방 금지 = STS 고유 **표현**(카드명·아트·UI 직접 사용).
|
||||||
|
- 만점 루트 = STS2 메커니즘을 **메이플 스킬·외형으로 완전 재서사화**.
|
||||||
|
|
||||||
|
## 참고
|
||||||
|
|
||||||
|
- 카드 데이터 단일 소스: `data/cards.json` (현 122장: 전사 18·마법사 14·도적 88 + Shiv·저주)
|
||||||
|
- 메이플 스킬 외형 매핑·STS2 캐릭터 상세는 박재오 개인 위키 `프로젝트-메이플-덱빌딩-스킬구성` / `프로젝트-메이플-STS2-차용-덱컨셉` 참조.
|
||||||
12477
map/lobby.map
12477
map/lobby.map
File diff suppressed because it is too large
Load Diff
1712
map/map01.map
1712
map/map01.map
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,18 @@ ${luaCharsTable()}
|
|||||||
${luaSoulShopTable(SOUL_UNLOCKS)}
|
${luaSoulShopTable(SOUL_UNLOCKS)}
|
||||||
self.SoulUnlocks = {}
|
self.SoulUnlocks = {}
|
||||||
self.SoulPoints = self.SoulPoints or 0
|
self.SoulPoints = self.SoulPoints or 0
|
||||||
self:ShowLobby()
|
local uiTries = 0
|
||||||
|
local uiInit = 0
|
||||||
|
uiInit = _TimerService:SetTimerRepeat(function()
|
||||||
|
uiTries = uiTries + 1
|
||||||
|
if _EntityService:GetEntityByPath("/ui/DeckUIGroup") ~= nil then
|
||||||
|
self:ActivateUIGroups()
|
||||||
|
self:ShowMainMenu()
|
||||||
|
_TimerService:ClearTimer(uiInit)
|
||||||
|
elseif uiTries > 80 then
|
||||||
|
_TimerService:ClearTimer(uiInit)
|
||||||
|
end
|
||||||
|
end, 0.1)
|
||||||
local lp = _UserService.LocalPlayer
|
local lp = _UserService.LocalPlayer
|
||||||
if lp ~= nil then
|
if lp ~= nil then
|
||||||
self:ReqLoadAscension(lp.PlayerComponent.UserId)
|
self:ReqLoadAscension(lp.PlayerComponent.UserId)
|
||||||
@@ -18,12 +29,36 @@ if lp ~= nil then
|
|||||||
end
|
end
|
||||||
_InputService:ConnectEvent(KeyDownEvent, function(e)
|
_InputService:ConnectEvent(KeyDownEvent, function(e)
|
||||||
if e.key == KeyboardKey.LeftControl then
|
if e.key == KeyboardKey.LeftControl then
|
||||||
|
self.DebugCtrlDown = true
|
||||||
local lp2 = _UserService.LocalPlayer
|
local lp2 = _UserService.LocalPlayer
|
||||||
if lp2 ~= nil and lp2.CurrentMapName == "${LOBBY_MAP}" and self.RunActive ~= true then
|
if lp2 ~= nil and lp2.CurrentMapName == "${LOBBY_MAP}" and self.RunActive ~= true then
|
||||||
self:PlayerAttackMotion()
|
self:PlayerAttackMotion()
|
||||||
end
|
end
|
||||||
|
elseif e.key == KeyboardKey.LeftShift or e.key == KeyboardKey.RightShift then
|
||||||
|
self.DebugShiftDown = true
|
||||||
|
elseif e.key == KeyboardKey.C then
|
||||||
|
if self.DebugCtrlDown == true and self.DebugShiftDown == true then
|
||||||
|
self:OpenDebugCardPicker()
|
||||||
|
end
|
||||||
|
elseif e.key == KeyboardKey.E then
|
||||||
|
if self.DebugCtrlDown == true and self.DebugShiftDown == true then
|
||||||
|
self:CheatFillEnergy()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
_InputService:ConnectEvent(KeyUpEvent, function(e)
|
||||||
|
if e.key == KeyboardKey.LeftControl then
|
||||||
|
self.DebugCtrlDown = false
|
||||||
|
elseif e.key == KeyboardKey.LeftShift or e.key == KeyboardKey.RightShift then
|
||||||
|
self.DebugShiftDown = false
|
||||||
end
|
end
|
||||||
end)`),
|
end)`),
|
||||||
|
method('CheatFillEnergy', `if self.RunActive ~= true or self.CombatOver == true then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.Energy = self.MaxEnergy
|
||||||
|
self:RenderPiles()
|
||||||
|
self:Toast("치트: 에너지 회복")`),
|
||||||
method('ReqLoadAscension', `local ds = _DataStorageService:GetUserDataStorage(userId)
|
method('ReqLoadAscension', `local ds = _DataStorageService:GetUserDataStorage(userId)
|
||||||
local errCode, value = ds:GetAndWait("ascensionUnlocked")
|
local errCode, value = ds:GetAndWait("ascensionUnlocked")
|
||||||
local n = 0
|
local n = 0
|
||||||
@@ -50,7 +85,7 @@ if v > self.AscensionUnlocked then v = self.AscensionUnlocked end
|
|||||||
self.AscensionLevel = v
|
self.AscensionLevel = v
|
||||||
self:RenderAscension()`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'delta' }]),
|
self:RenderAscension()`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'delta' }]),
|
||||||
method('RenderAscension', `self:SetText("/ui/DefaultGroup/MainMenu/AscLabel", "승천 " .. string.format("%d", self.AscensionLevel) .. " / 해금 " .. string.format("%d", self.AscensionUnlocked))
|
method('RenderAscension', `self:SetText("/ui/DefaultGroup/MainMenu/AscLabel", "승천 " .. string.format("%d", self.AscensionLevel) .. " / 해금 " .. string.format("%d", self.AscensionUnlocked))
|
||||||
self:SetText("/ui/DefaultGroup/LobbyHud/AscLabel", "승천 " .. string.format("%d", self.AscensionLevel) .. " / 해금 " .. string.format("%d", self.AscensionUnlocked))`),
|
self:SetText("/ui/LobbyUIGroup/LobbyHud/AscLabel", "승천 " .. string.format("%d", self.AscensionLevel) .. " / 해금 " .. string.format("%d", self.AscensionUnlocked))`),
|
||||||
method('AscHpMult', `local m = 1
|
method('AscHpMult', `local m = 1
|
||||||
if self.AscensionLevel >= 1 then m = m + 0.1 end
|
if self.AscensionLevel >= 1 then m = m + 0.1 end
|
||||||
if self.AscensionLevel >= 6 then m = m + 0.1 end
|
if self.AscensionLevel >= 6 then m = m + 0.1 end
|
||||||
|
|||||||
@@ -10,19 +10,19 @@ self:RenderCharacterSelect()`),
|
|||||||
self:RenderCharacterSelect()`, [
|
self:RenderCharacterSelect()`, [
|
||||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'className' },
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'className' },
|
||||||
]),
|
]),
|
||||||
method('RenderCharacterSelect', `local warriorArt = _EntityService:GetEntityByPath("/ui/DefaultGroup/CharacterSelectHud/WarriorButton/Art")
|
method('RenderCharacterSelect', `local warriorArt = _EntityService:GetEntityByPath("/ui/SelectUIGroup/CharacterSelectHud/WarriorButton/Art")
|
||||||
if warriorArt ~= nil and warriorArt.SpriteGUIRendererComponent ~= nil and self.ClassPortraits ~= nil and self.ClassPortraits["warrior"] ~= nil then
|
if warriorArt ~= nil and warriorArt.SpriteGUIRendererComponent ~= nil and self.ClassPortraits ~= nil and self.ClassPortraits["warrior"] ~= nil then
|
||||||
warriorArt.SpriteGUIRendererComponent.ImageRUID = self.ClassPortraits["warrior"]
|
warriorArt.SpriteGUIRendererComponent.ImageRUID = self.ClassPortraits["warrior"]
|
||||||
end
|
end
|
||||||
local mageArt = _EntityService:GetEntityByPath("/ui/DefaultGroup/CharacterSelectHud/MageButton/Art")
|
local mageArt = _EntityService:GetEntityByPath("/ui/SelectUIGroup/CharacterSelectHud/MageButton/Art")
|
||||||
if mageArt ~= nil and mageArt.SpriteGUIRendererComponent ~= nil and self.ClassPortraits ~= nil and self.ClassPortraits["magician"] ~= nil then
|
if mageArt ~= nil and mageArt.SpriteGUIRendererComponent ~= nil and self.ClassPortraits ~= nil and self.ClassPortraits["magician"] ~= nil then
|
||||||
mageArt.SpriteGUIRendererComponent.ImageRUID = self.ClassPortraits["magician"]
|
mageArt.SpriteGUIRendererComponent.ImageRUID = self.ClassPortraits["magician"]
|
||||||
end
|
end
|
||||||
local thiefArt = _EntityService:GetEntityByPath("/ui/DefaultGroup/CharacterSelectHud/ThiefButton/Art")
|
local thiefArt = _EntityService:GetEntityByPath("/ui/SelectUIGroup/CharacterSelectHud/ThiefButton/Art")
|
||||||
if thiefArt ~= nil and thiefArt.SpriteGUIRendererComponent ~= nil and self.ClassPortraits ~= nil and self.ClassPortraits["bandit"] ~= nil then
|
if thiefArt ~= nil and thiefArt.SpriteGUIRendererComponent ~= nil and self.ClassPortraits ~= nil and self.ClassPortraits["bandit"] ~= nil then
|
||||||
thiefArt.SpriteGUIRendererComponent.ImageRUID = self.ClassPortraits["bandit"]
|
thiefArt.SpriteGUIRendererComponent.ImageRUID = self.ClassPortraits["bandit"]
|
||||||
end
|
end
|
||||||
local warrior = _EntityService:GetEntityByPath("/ui/DefaultGroup/CharacterSelectHud/WarriorButton")
|
local warrior = _EntityService:GetEntityByPath("/ui/SelectUIGroup/CharacterSelectHud/WarriorButton")
|
||||||
if warrior ~= nil and warrior.SpriteGUIRendererComponent ~= nil then
|
if warrior ~= nil and warrior.SpriteGUIRendererComponent ~= nil then
|
||||||
if self.SelectedClass == "warrior" then
|
if self.SelectedClass == "warrior" then
|
||||||
warrior.SpriteGUIRendererComponent.Color = Color(1, 0.82, 0.3, 1)
|
warrior.SpriteGUIRendererComponent.Color = Color(1, 0.82, 0.3, 1)
|
||||||
@@ -30,7 +30,7 @@ if warrior ~= nil and warrior.SpriteGUIRendererComponent ~= nil then
|
|||||||
warrior.SpriteGUIRendererComponent.Color = Color(0.16, 0.2, 0.26, 1)
|
warrior.SpriteGUIRendererComponent.Color = Color(0.16, 0.2, 0.26, 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local mage = _EntityService:GetEntityByPath("/ui/DefaultGroup/CharacterSelectHud/MageButton")
|
local mage = _EntityService:GetEntityByPath("/ui/SelectUIGroup/CharacterSelectHud/MageButton")
|
||||||
if mage ~= nil and mage.SpriteGUIRendererComponent ~= nil then
|
if mage ~= nil and mage.SpriteGUIRendererComponent ~= nil then
|
||||||
if self.SelectedClass == "magician" then
|
if self.SelectedClass == "magician" then
|
||||||
mage.SpriteGUIRendererComponent.Color = Color(1, 0.82, 0.3, 1)
|
mage.SpriteGUIRendererComponent.Color = Color(1, 0.82, 0.3, 1)
|
||||||
@@ -38,7 +38,7 @@ if mage ~= nil and mage.SpriteGUIRendererComponent ~= nil then
|
|||||||
mage.SpriteGUIRendererComponent.Color = Color(0.16, 0.2, 0.26, 1)
|
mage.SpriteGUIRendererComponent.Color = Color(0.16, 0.2, 0.26, 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local thief = _EntityService:GetEntityByPath("/ui/DefaultGroup/CharacterSelectHud/ThiefButton")
|
local thief = _EntityService:GetEntityByPath("/ui/SelectUIGroup/CharacterSelectHud/ThiefButton")
|
||||||
if thief ~= nil and thief.SpriteGUIRendererComponent ~= nil then
|
if thief ~= nil and thief.SpriteGUIRendererComponent ~= nil then
|
||||||
if self.SelectedClass == "bandit" then
|
if self.SelectedClass == "bandit" then
|
||||||
thief.SpriteGUIRendererComponent.Color = Color(1, 0.82, 0.3, 1)
|
thief.SpriteGUIRendererComponent.Color = Color(1, 0.82, 0.3, 1)
|
||||||
@@ -47,16 +47,16 @@ if thief ~= nil and thief.SpriteGUIRendererComponent ~= nil then
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if self.SelectedClass == "warrior" then
|
if self.SelectedClass == "warrior" then
|
||||||
self:SetText("/ui/DefaultGroup/CharacterSelectHud/Status", "전사 선택됨")
|
self:SetText("/ui/SelectUIGroup/CharacterSelectHud/Status", "전사 선택됨")
|
||||||
elseif self.SelectedClass == "bandit" then
|
elseif self.SelectedClass == "bandit" then
|
||||||
self:SetText("/ui/DefaultGroup/CharacterSelectHud/Status", "도적 선택됨")
|
self:SetText("/ui/SelectUIGroup/CharacterSelectHud/Status", "도적 선택됨")
|
||||||
elseif self.SelectedClass == "magician" then
|
elseif self.SelectedClass == "magician" then
|
||||||
self:SetText("/ui/DefaultGroup/CharacterSelectHud/Status", "마법사 선택됨")
|
self:SetText("/ui/SelectUIGroup/CharacterSelectHud/Status", "마법사 선택됨")
|
||||||
else
|
else
|
||||||
self:SetText("/ui/DefaultGroup/CharacterSelectHud/Status", "직업을 선택하고 시작하세요")
|
self:SetText("/ui/SelectUIGroup/CharacterSelectHud/Status", "직업을 선택하고 시작하세요")
|
||||||
end`),
|
end`),
|
||||||
method('StartNewGame', `if self.SelectedClass ~= "warrior" and self.SelectedClass ~= "bandit" and self.SelectedClass ~= "magician" then
|
method('StartNewGame', `if self.SelectedClass ~= "warrior" and self.SelectedClass ~= "bandit" and self.SelectedClass ~= "magician" then
|
||||||
self:SetText("/ui/DefaultGroup/CharacterSelectHud/Status", "직업을 먼저 선택하세요")
|
self:SetText("/ui/SelectUIGroup/CharacterSelectHud/Status", "직업을 먼저 선택하세요")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
self:StartRun()`),
|
self:StartRun()`),
|
||||||
@@ -66,5 +66,5 @@ if e ~= nil then
|
|||||||
end`, [
|
end`, [
|
||||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' },
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' },
|
||||||
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'enabled' },
|
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'enabled' },
|
||||||
]),
|
], 2),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ export const combatMethods = [
|
|||||||
self:SelectDiscardSlot(slot)
|
self:SelectDiscardSlot(slot)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
if self:IsRetainSelecting() == true then
|
||||||
|
self:SelectRetainSlot(slot)
|
||||||
|
return
|
||||||
|
end
|
||||||
if self.CombatOver == true or self.FxBusy == true or self.TurnBusy == true then
|
if self.CombatOver == true or self.FxBusy == true or self.TurnBusy == true then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -50,6 +54,8 @@ self:RenderCombat()
|
|||||||
self:CheckCombatEnd()`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
self:CheckCombatEnd()`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||||
method('OnCardButton', `if self:IsDiscardSelecting() == true then
|
method('OnCardButton', `if self:IsDiscardSelecting() == true then
|
||||||
self:SelectDiscardSlot(slot)
|
self:SelectDiscardSlot(slot)
|
||||||
|
elseif self:IsRetainSelecting() == true then
|
||||||
|
self:SelectRetainSlot(slot)
|
||||||
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||||
method('FindMonsterAtTouch', `local best = 0
|
method('FindMonsterAtTouch', `local best = 0
|
||||||
local bestDist = 200
|
local bestDist = 200
|
||||||
@@ -75,9 +81,8 @@ for i = 1, #self.Monsters do
|
|||||||
local m = self.Monsters[i]
|
local m = self.Monsters[i]
|
||||||
local active = false
|
local active = false
|
||||||
if m ~= nil and m.alive == true and i == shownTarget then active = true end
|
if m ~= nil and m.alive == true and i == shownTarget then active = true end
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud/MonsterSlot" .. tostring(i) .. "/TargetFrame", active)
|
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/MonsterStatus" .. tostring(i) .. "/TargetMarker", active and dragActive)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud/MonsterSlot" .. tostring(i) .. "/TargetMarker", active and dragActive)
|
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/MonsterStatus" .. tostring(i) .. "/TargetMarker/Label", active and dragActive)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud/MonsterSlot" .. tostring(i) .. "/TargetMarker/Label", active and dragActive)
|
|
||||||
end`),
|
end`),
|
||||||
method('OnCardDragBegin', `if self.CombatOver == true or self.FxBusy == true or self.TurnBusy == true then
|
method('OnCardDragBegin', `if self.CombatOver == true or self.FxBusy == true or self.TurnBusy == true then
|
||||||
return
|
return
|
||||||
@@ -90,7 +95,7 @@ if self.CardHoverTweenId ~= nil and self.CardHoverTweenId ~= 0 then
|
|||||||
self.CardHoverTweenId = 0
|
self.CardHoverTweenId = 0
|
||||||
end
|
end
|
||||||
for i = 1, 10 do
|
for i = 1, 10 do
|
||||||
local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(i))
|
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(i))
|
||||||
if e ~= nil and e.UITransformComponent ~= nil then
|
if e ~= nil and e.UITransformComponent ~= nil then
|
||||||
e.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
e.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
||||||
e.UITransformComponent.anchoredPosition = Vector2(self:GetHandSlotX(i), 0)
|
e.UITransformComponent.anchoredPosition = Vector2(self:GetHandSlotX(i), 0)
|
||||||
@@ -102,7 +107,7 @@ self:RenderTargetFrames()`, [{ Type: 'number', DefaultValue: null, SyncDirection
|
|||||||
method('OnCardDrag', `if self.DragSlot ~= slot then
|
method('OnCardDrag', `if self.DragSlot ~= slot then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(slot))
|
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||||
if e ~= nil and e.UITransformComponent ~= nil then
|
if e ~= nil and e.UITransformComponent ~= nil then
|
||||||
local ui = _UILogic:ScreenToUIPosition(touchPoint)
|
local ui = _UILogic:ScreenToUIPosition(touchPoint)
|
||||||
e.UITransformComponent.anchoredPosition = Vector2(ui.x, ui.y + 360)
|
e.UITransformComponent.anchoredPosition = Vector2(ui.x, ui.y + 360)
|
||||||
@@ -124,7 +129,7 @@ end`, [
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
self.DragSlot = 0
|
self.DragSlot = 0
|
||||||
local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(slot))
|
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||||
if e ~= nil and e.UITransformComponent ~= nil then
|
if e ~= nil and e.UITransformComponent ~= nil then
|
||||||
e.UITransformComponent.anchoredPosition = Vector2(self:GetHandSlotX(slot), 0)
|
e.UITransformComponent.anchoredPosition = Vector2(self:GetHandSlotX(slot), 0)
|
||||||
e.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
e.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
||||||
@@ -137,6 +142,10 @@ self:ResolveCardDrop(slot, touchPoint)`, [
|
|||||||
self:SelectDiscardSlot(slot)
|
self:SelectDiscardSlot(slot)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
if self:IsRetainSelecting() == true then
|
||||||
|
self:SelectRetainSlot(slot)
|
||||||
|
return
|
||||||
|
end
|
||||||
if self.CombatOver == true or self.FxBusy == true or self.TurnBusy == true then
|
if self.CombatOver == true or self.FxBusy == true or self.TurnBusy == true then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -207,7 +216,7 @@ if m == nil or m.alive ~= true or m.entity == nil or not isvalid(m.entity) then
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
self.FxBusy = true
|
self.FxBusy = true
|
||||||
local fx = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/SkillFx")
|
local fx = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/SkillFx")
|
||||||
if fx ~= nil then
|
if fx ~= nil then
|
||||||
if fx.SpriteGUIRendererComponent ~= nil and image ~= nil and image ~= "" then
|
if fx.SpriteGUIRendererComponent ~= nil and image ~= nil and image ~= "" then
|
||||||
fx.SpriteGUIRendererComponent.ImageRUID = image
|
fx.SpriteGUIRendererComponent.ImageRUID = image
|
||||||
@@ -238,7 +247,7 @@ end, 0.35)`, [
|
|||||||
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'pierce' },
|
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'pierce' },
|
||||||
]),
|
]),
|
||||||
method('PlayAoeFx', `self.FxBusy = true
|
method('PlayAoeFx', `self.FxBusy = true
|
||||||
local fx = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/SkillFx")
|
local fx = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/SkillFx")
|
||||||
if fx ~= nil then
|
if fx ~= nil then
|
||||||
if fx.SpriteGUIRendererComponent ~= nil and image ~= nil and image ~= "" then
|
if fx.SpriteGUIRendererComponent ~= nil and image ~= nil and image ~= "" then
|
||||||
fx.SpriteGUIRendererComponent.ImageRUID = image
|
fx.SpriteGUIRendererComponent.ImageRUID = image
|
||||||
@@ -287,7 +296,7 @@ if m.entity ~= nil and isvalid(m.entity) then
|
|||||||
local ent = m.entity
|
local ent = m.entity
|
||||||
_TimerService:SetTimerOnce(function() if isvalid(ent) then ent:SetVisible(false) end end, 0.4)
|
_TimerService:SetTimerOnce(function() if isvalid(ent) then ent:SetVisible(false) end end, 0.4)
|
||||||
end
|
end
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud/MonsterSlot" .. tostring(slot), false)
|
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/MonsterStatus" .. tostring(slot), false)
|
||||||
for i = 1, #self.Monsters do
|
for i = 1, #self.Monsters do
|
||||||
if self.Monsters[i].alive == true then self.TargetIndex = i; break end
|
if self.Monsters[i].alive == true then self.TargetIndex = i; break end
|
||||||
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||||
@@ -341,7 +350,7 @@ if idx == 0 or self.PlayerHp <= 0 then
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
local m = self.Monsters[idx]
|
local m = self.Monsters[idx]
|
||||||
local base = "/ui/DefaultGroup/CombatHud/MonsterSlot" .. tostring(idx)
|
local base = "/ui/RunUIGroup/CombatHud/MonsterStatus" .. tostring(idx)
|
||||||
self:SetEntityEnabled(base .. "/ActFrame", true)
|
self:SetEntityEnabled(base .. "/ActFrame", true)
|
||||||
_TimerService:SetTimerOnce(function()
|
_TimerService:SetTimerOnce(function()
|
||||||
if m.poison ~= nil and m.poison > 0 then
|
if m.poison ~= nil and m.poison > 0 then
|
||||||
@@ -417,6 +426,7 @@ self.DiscardSelectRemaining = 0
|
|||||||
self.DiscardSelectTotal = 0
|
self.DiscardSelectTotal = 0
|
||||||
self.DiscardPostShiv = 0
|
self.DiscardPostShiv = 0
|
||||||
self.DiscardShivPerPick = 0
|
self.DiscardShivPerPick = 0
|
||||||
|
self.RetainSelectActive = false
|
||||||
self:UpdateDiscardPrompt()
|
self:UpdateDiscardPrompt()
|
||||||
self:RenderHand(false)
|
self:RenderHand(false)
|
||||||
self:RenderPiles()`),
|
self:RenderPiles()`),
|
||||||
|
|||||||
@@ -10,56 +10,56 @@ 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/DefaultGroup/DeckHud/EndTurnButton")
|
method('BindButtons', `local endTurn = _EntityService:GetEntityByPath("/ui/RunUIGroup/DeckHud/EndTurnButton")
|
||||||
if endTurn ~= nil and endTurn.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)
|
||||||
self.EndTurnHandler = nil
|
self.EndTurnHandler = nil
|
||||||
end
|
end
|
||||||
self.EndTurnHandler = endTurn:ConnectEvent(ButtonClickEvent, function() self:EndPlayerTurn() end)
|
self.EndTurnHandler = endTurn:ConnectEvent(ButtonClickEvent, function() self:EndPlayerTurn() end)
|
||||||
end
|
end
|
||||||
local drawPile = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckHud/DrawPile")
|
local drawPile = _EntityService:GetEntityByPath("/ui/RunUIGroup/DeckHud/DrawPile")
|
||||||
if drawPile ~= nil and drawPile.ButtonComponent ~= nil then
|
if drawPile ~= nil and (drawPile.ButtonComponent ~= nil or drawPile:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.DrawPileHandler ~= nil then
|
if self.DrawPileHandler ~= nil then
|
||||||
drawPile:DisconnectEvent(ButtonClickEvent, self.DrawPileHandler)
|
drawPile:DisconnectEvent(ButtonClickEvent, self.DrawPileHandler)
|
||||||
self.DrawPileHandler = nil
|
self.DrawPileHandler = nil
|
||||||
end
|
end
|
||||||
self.DrawPileHandler = drawPile:ConnectEvent(ButtonClickEvent, function() self:OpenDeckInspect("draw") end)
|
self.DrawPileHandler = drawPile:ConnectEvent(ButtonClickEvent, function() self:OpenDeckInspect("draw") end)
|
||||||
end
|
end
|
||||||
local discardPile = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckHud/DiscardPile")
|
local discardPile = _EntityService:GetEntityByPath("/ui/RunUIGroup/DeckHud/DiscardPile")
|
||||||
if discardPile ~= nil and discardPile.ButtonComponent ~= nil then
|
if discardPile ~= nil and (discardPile.ButtonComponent ~= nil or discardPile:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.DiscardPileHandler ~= nil then
|
if self.DiscardPileHandler ~= nil then
|
||||||
discardPile:DisconnectEvent(ButtonClickEvent, self.DiscardPileHandler)
|
discardPile:DisconnectEvent(ButtonClickEvent, self.DiscardPileHandler)
|
||||||
self.DiscardPileHandler = nil
|
self.DiscardPileHandler = nil
|
||||||
end
|
end
|
||||||
self.DiscardPileHandler = discardPile:ConnectEvent(ButtonClickEvent, function() self:OpenDeckInspect("discard") end)
|
self.DiscardPileHandler = discardPile:ConnectEvent(ButtonClickEvent, function() self:OpenDeckInspect("discard") end)
|
||||||
end
|
end
|
||||||
local exhaustPile = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckHud/ExhaustPile")
|
local exhaustPile = _EntityService:GetEntityByPath("/ui/RunUIGroup/DeckHud/ExhaustPile")
|
||||||
if exhaustPile ~= nil and exhaustPile.ButtonComponent ~= nil then
|
if exhaustPile ~= nil and (exhaustPile.ButtonComponent ~= nil or exhaustPile:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.ExhaustPileHandler ~= nil then
|
if self.ExhaustPileHandler ~= nil then
|
||||||
exhaustPile:DisconnectEvent(ButtonClickEvent, self.ExhaustPileHandler)
|
exhaustPile:DisconnectEvent(ButtonClickEvent, self.ExhaustPileHandler)
|
||||||
self.ExhaustPileHandler = nil
|
self.ExhaustPileHandler = nil
|
||||||
end
|
end
|
||||||
self.ExhaustPileHandler = exhaustPile:ConnectEvent(ButtonClickEvent, function() self:OpenDeckInspect("exhaust") end)
|
self.ExhaustPileHandler = exhaustPile:ConnectEvent(ButtonClickEvent, function() self:OpenDeckInspect("exhaust") end)
|
||||||
end
|
end
|
||||||
local inspectClose = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckInspectHud/Close")
|
local inspectClose = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckInspectHud/Close")
|
||||||
if inspectClose ~= nil and inspectClose.ButtonComponent ~= nil then
|
if inspectClose ~= nil and (inspectClose.ButtonComponent ~= nil or inspectClose:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.DeckInspectCloseHandler ~= nil then
|
if self.DeckInspectCloseHandler ~= nil then
|
||||||
inspectClose:DisconnectEvent(ButtonClickEvent, self.DeckInspectCloseHandler)
|
inspectClose:DisconnectEvent(ButtonClickEvent, self.DeckInspectCloseHandler)
|
||||||
self.DeckInspectCloseHandler = nil
|
self.DeckInspectCloseHandler = nil
|
||||||
end
|
end
|
||||||
self.DeckInspectCloseHandler = inspectClose:ConnectEvent(ButtonClickEvent, function() self:CloseDeckInspect() end)
|
self.DeckInspectCloseHandler = inspectClose:ConnectEvent(ButtonClickEvent, function() self:CloseDeckInspect() end)
|
||||||
end
|
end
|
||||||
local allDeckButton = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/TopBar/AllDeckButton")
|
local allDeckButton = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/TopBar/AllDeckButton")
|
||||||
if allDeckButton ~= nil and allDeckButton.ButtonComponent ~= nil then
|
if allDeckButton ~= nil and (allDeckButton.ButtonComponent ~= nil or allDeckButton:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.AllDeckHandler ~= nil then
|
if self.AllDeckHandler ~= nil then
|
||||||
allDeckButton:DisconnectEvent(ButtonClickEvent, self.AllDeckHandler)
|
allDeckButton:DisconnectEvent(ButtonClickEvent, self.AllDeckHandler)
|
||||||
self.AllDeckHandler = nil
|
self.AllDeckHandler = nil
|
||||||
end
|
end
|
||||||
self.AllDeckHandler = allDeckButton:ConnectEvent(ButtonClickEvent, function() self:OpenAllDeck() end)
|
self.AllDeckHandler = allDeckButton:ConnectEvent(ButtonClickEvent, function() self:OpenAllDeck() end)
|
||||||
end
|
end
|
||||||
local allDeckClose = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckAllHud/Close")
|
local allDeckClose = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Close")
|
||||||
if allDeckClose ~= nil and allDeckClose.ButtonComponent ~= nil then
|
if allDeckClose ~= nil and (allDeckClose.ButtonComponent ~= nil or allDeckClose:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.AllDeckCloseHandler ~= nil then
|
if self.AllDeckCloseHandler ~= nil then
|
||||||
allDeckClose:DisconnectEvent(ButtonClickEvent, self.AllDeckCloseHandler)
|
allDeckClose:DisconnectEvent(ButtonClickEvent, self.AllDeckCloseHandler)
|
||||||
self.AllDeckCloseHandler = nil
|
self.AllDeckCloseHandler = nil
|
||||||
@@ -67,10 +67,20 @@ if allDeckClose ~= nil and allDeckClose.ButtonComponent ~= nil then
|
|||||||
self.AllDeckCloseHandler = allDeckClose:ConnectEvent(ButtonClickEvent, function() self:CloseAllDeck() end)
|
self.AllDeckCloseHandler = allDeckClose:ConnectEvent(ButtonClickEvent, function() self:CloseAllDeck() end)
|
||||||
end
|
end
|
||||||
self:BindClassDeckTabs()
|
self:BindClassDeckTabs()
|
||||||
|
for i = 1, 120 do
|
||||||
|
local allCard = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(i))
|
||||||
|
if allCard ~= nil and (allCard.ButtonComponent ~= nil or allCard:AddComponent("ButtonComponent") ~= nil) then
|
||||||
|
if allCard.SpriteGUIRendererComponent ~= nil then
|
||||||
|
allCard.SpriteGUIRendererComponent.RaycastTarget = true
|
||||||
|
end
|
||||||
|
local slot = i
|
||||||
|
allCard:ConnectEvent(ButtonClickEvent, function() self:OnAllDeckCardButton(slot) end)
|
||||||
|
end
|
||||||
|
end
|
||||||
for i = 1, 10 do
|
for i = 1, 10 do
|
||||||
local cardEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(i))
|
local cardEntity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(i))
|
||||||
if cardEntity ~= nil and cardEntity.UITouchReceiveComponent ~= nil then
|
if cardEntity ~= nil and cardEntity.UITouchReceiveComponent ~= nil then
|
||||||
local cardPath = "/ui/DefaultGroup/CardHand/Card" .. tostring(i)
|
local cardPath = "/ui/RunUIGroup/CardHand/Card" .. tostring(i)
|
||||||
cardEntity:ConnectEvent(UITouchEnterEvent, function() self:SetCardHover(cardPath, true) end)
|
cardEntity:ConnectEvent(UITouchEnterEvent, function() self:SetCardHover(cardPath, true) end)
|
||||||
cardEntity:ConnectEvent(UITouchExitEvent, function() self:SetCardHover(cardPath, false) end)
|
cardEntity:ConnectEvent(UITouchExitEvent, function() self:SetCardHover(cardPath, false) end)
|
||||||
cardEntity:ConnectEvent(UITouchBeginDragEvent, function(ev) self:OnCardDragBegin(i) end)
|
cardEntity:ConnectEvent(UITouchBeginDragEvent, function(ev) self:OnCardDragBegin(i) end)
|
||||||
@@ -78,24 +88,24 @@ for i = 1, 10 do
|
|||||||
cardEntity:ConnectEvent(UITouchEndDragEvent, function(ev) self:OnCardDragEnd(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(UITouchEnterEvent, function() self:HoverCard(i) end)
|
||||||
cardEntity:ConnectEvent(UITouchExitEvent, function() self:UnhoverCard(i) end)
|
cardEntity:ConnectEvent(UITouchExitEvent, function() self:UnhoverCard(i) end)
|
||||||
if cardEntity.ButtonComponent ~= nil then
|
if (cardEntity.ButtonComponent ~= nil or cardEntity:AddComponent("ButtonComponent") ~= nil) then
|
||||||
cardEntity:ConnectEvent(ButtonClickEvent, function() self:OnCardButton(i) end)
|
cardEntity:ConnectEvent(ButtonClickEvent, function() self:OnCardButton(i) end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for i = 1, 3 do
|
for i = 1, 3 do
|
||||||
local rc = _EntityService:GetEntityByPath("/ui/DefaultGroup/RewardHud/Reward" .. tostring(i))
|
local rc = _EntityService:GetEntityByPath("/ui/RunUIGroup/RewardHud/Reward" .. tostring(i))
|
||||||
if rc ~= nil and rc.ButtonComponent ~= nil then
|
if rc ~= nil and (rc.ButtonComponent ~= nil or rc:AddComponent("ButtonComponent") ~= nil) then
|
||||||
rc:ConnectEvent(ButtonClickEvent, function() self:PickReward(i) end)
|
rc:ConnectEvent(ButtonClickEvent, function() self:PickReward(i) end)
|
||||||
if rc.UITouchReceiveComponent ~= nil then
|
if rc.UITouchReceiveComponent ~= nil then
|
||||||
local cardPath = "/ui/DefaultGroup/RewardHud/Reward" .. tostring(i)
|
local cardPath = "/ui/RunUIGroup/RewardHud/Reward" .. tostring(i)
|
||||||
rc:ConnectEvent(UITouchEnterEvent, function() self:SetCardHover(cardPath, true) end)
|
rc:ConnectEvent(UITouchEnterEvent, function() self:SetCardHover(cardPath, true) end)
|
||||||
rc:ConnectEvent(UITouchExitEvent, function() self:SetCardHover(cardPath, false) end)
|
rc:ConnectEvent(UITouchExitEvent, function() self:SetCardHover(cardPath, false) end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local skip = _EntityService:GetEntityByPath("/ui/DefaultGroup/RewardHud/Skip")
|
local skip = _EntityService:GetEntityByPath("/ui/RunUIGroup/RewardHud/Skip")
|
||||||
if skip ~= nil and skip.ButtonComponent ~= nil then
|
if skip ~= nil and (skip.ButtonComponent ~= nil or skip:AddComponent("ButtonComponent") ~= nil) then
|
||||||
skip:ConnectEvent(ButtonClickEvent, function() self:PickReward(0) end)
|
skip:ConnectEvent(ButtonClickEvent, function() self:PickReward(0) end)
|
||||||
end
|
end
|
||||||
local mapNodeIds = {}
|
local mapNodeIds = {}
|
||||||
@@ -107,42 +117,42 @@ end
|
|||||||
table.insert(mapNodeIds, "boss")
|
table.insert(mapNodeIds, "boss")
|
||||||
for i = 1, #mapNodeIds do
|
for i = 1, #mapNodeIds do
|
||||||
local nid = mapNodeIds[i]
|
local nid = mapNodeIds[i]
|
||||||
local mn = _EntityService:GetEntityByPath("/ui/DefaultGroup/MapHud/Node_" .. nid)
|
local mn = _EntityService:GetEntityByPath("/ui/RunUIGroup/MapHud/Node_" .. nid)
|
||||||
if mn ~= nil and mn.ButtonComponent ~= nil then
|
if mn ~= nil and (mn.ButtonComponent ~= nil or mn:AddComponent("ButtonComponent") ~= nil) then
|
||||||
mn:ConnectEvent(ButtonClickEvent, function() self:PickNode(nid) end)
|
mn:ConnectEvent(ButtonClickEvent, function() self:PickNode(nid) end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for i = 1, 3 do
|
for i = 1, 3 do
|
||||||
local sc = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud/Card" .. tostring(i))
|
local sc = _EntityService:GetEntityByPath("/ui/RunUIGroup/ShopHud/Card" .. tostring(i))
|
||||||
if sc ~= nil and sc.ButtonComponent ~= nil then
|
if sc ~= nil and (sc.ButtonComponent ~= nil or sc:AddComponent("ButtonComponent") ~= nil) then
|
||||||
sc:ConnectEvent(ButtonClickEvent, function() self:BuyCard(i) end)
|
sc:ConnectEvent(ButtonClickEvent, function() self:BuyCard(i) end)
|
||||||
if sc.UITouchReceiveComponent ~= nil then
|
if sc.UITouchReceiveComponent ~= nil then
|
||||||
local cardPath = "/ui/DefaultGroup/ShopHud/Card" .. tostring(i)
|
local cardPath = "/ui/RunUIGroup/ShopHud/Card" .. tostring(i)
|
||||||
sc:ConnectEvent(UITouchEnterEvent, function() self:SetCardHover(cardPath, true) end)
|
sc:ConnectEvent(UITouchEnterEvent, function() self:SetCardHover(cardPath, true) end)
|
||||||
sc:ConnectEvent(UITouchExitEvent, function() self:SetCardHover(cardPath, false) end)
|
sc:ConnectEvent(UITouchExitEvent, function() self:SetCardHover(cardPath, false) end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local shopLeave = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud/Leave")
|
local shopLeave = _EntityService:GetEntityByPath("/ui/RunUIGroup/ShopHud/Leave")
|
||||||
if shopLeave ~= nil and shopLeave.ButtonComponent ~= nil then
|
if shopLeave ~= nil and (shopLeave.ButtonComponent ~= nil or shopLeave:AddComponent("ButtonComponent") ~= nil) then
|
||||||
shopLeave:ConnectEvent(ButtonClickEvent, function() self:LeaveNode() end)
|
shopLeave:ConnectEvent(ButtonClickEvent, function() self:LeaveNode() end)
|
||||||
end
|
end
|
||||||
local shopRelic = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud/Relic")
|
local shopRelic = _EntityService:GetEntityByPath("/ui/RunUIGroup/ShopHud/Relic")
|
||||||
if shopRelic ~= nil and shopRelic.ButtonComponent ~= nil then
|
if shopRelic ~= nil and (shopRelic.ButtonComponent ~= nil or shopRelic:AddComponent("ButtonComponent") ~= nil) then
|
||||||
shopRelic:ConnectEvent(ButtonClickEvent, function() self:BuyRelic() end)
|
shopRelic:ConnectEvent(ButtonClickEvent, function() self:BuyRelic() end)
|
||||||
end
|
end
|
||||||
local restLeave = _EntityService:GetEntityByPath("/ui/DefaultGroup/RestHud/Leave")
|
local restLeave = _EntityService:GetEntityByPath("/ui/RunUIGroup/RestHud/Leave")
|
||||||
if restLeave ~= nil and restLeave.ButtonComponent ~= nil then
|
if restLeave ~= nil and (restLeave.ButtonComponent ~= nil or restLeave:AddComponent("ButtonComponent") ~= nil) then
|
||||||
restLeave:ConnectEvent(ButtonClickEvent, function() self:LeaveNode() end)
|
restLeave:ConnectEvent(ButtonClickEvent, function() self:LeaveNode() end)
|
||||||
end
|
end
|
||||||
for i = 1, ${MAX_MONSTERS} do
|
for i = 1, ${MAX_MONSTERS} do
|
||||||
local ms = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/MonsterSlot" .. tostring(i))
|
local ms = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/MonsterStatus" .. tostring(i))
|
||||||
if ms ~= nil and ms.ButtonComponent ~= nil then
|
if ms ~= nil and (ms.ButtonComponent ~= nil or ms:AddComponent("ButtonComponent") ~= nil) then
|
||||||
ms:ConnectEvent(ButtonClickEvent, function() self:SetTarget(i) end)
|
ms:ConnectEvent(ButtonClickEvent, function() self:SetTarget(i) end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for i = 1, 10 do
|
for i = 1, 10 do
|
||||||
local rs = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/TopBar/RelicSlot" .. tostring(i))
|
local rs = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/TopBar/RelicSlot" .. tostring(i))
|
||||||
if rs ~= nil and rs.UITouchReceiveComponent ~= nil then
|
if rs ~= nil and rs.UITouchReceiveComponent ~= nil then
|
||||||
local idx = i
|
local idx = i
|
||||||
rs:ConnectEvent(UITouchEnterEvent, function()
|
rs:ConnectEvent(UITouchEnterEvent, function()
|
||||||
@@ -156,7 +166,7 @@ for i = 1, 10 do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
for i = 1, 5 do
|
for i = 1, 5 do
|
||||||
local ps = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/TopBar/PotionSlot" .. tostring(i))
|
local ps = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/TopBar/PotionSlot" .. tostring(i))
|
||||||
if ps ~= nil and ps.UITouchReceiveComponent ~= nil then
|
if ps ~= nil and ps.UITouchReceiveComponent ~= nil then
|
||||||
local idx = i
|
local idx = i
|
||||||
ps:ConnectEvent(UITouchEnterEvent, function()
|
ps:ConnectEvent(UITouchEnterEvent, function()
|
||||||
@@ -170,42 +180,42 @@ for i = 1, 5 do
|
|||||||
ps:ConnectEvent(UITouchDownEvent, function() self:OpenPotionMenu(idx) end)
|
ps:ConnectEvent(UITouchDownEvent, function() self:OpenPotionMenu(idx) end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local pmUse = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/PotionMenu/Use")
|
local pmUse = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/PotionMenu/Use")
|
||||||
if pmUse ~= nil and pmUse.ButtonComponent ~= nil then
|
if pmUse ~= nil and (pmUse.ButtonComponent ~= nil or pmUse:AddComponent("ButtonComponent") ~= nil) then
|
||||||
pmUse:ConnectEvent(ButtonClickEvent, function() self:UsePotion() end)
|
pmUse:ConnectEvent(ButtonClickEvent, function() self:UsePotion() end)
|
||||||
end
|
end
|
||||||
local pmToss = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/PotionMenu/Toss")
|
local pmToss = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/PotionMenu/Toss")
|
||||||
if pmToss ~= nil and pmToss.ButtonComponent ~= nil then
|
if pmToss ~= nil and (pmToss.ButtonComponent ~= nil or pmToss:AddComponent("ButtonComponent") ~= nil) then
|
||||||
pmToss:ConnectEvent(ButtonClickEvent, function() self:TossPotion() end)
|
pmToss:ConnectEvent(ButtonClickEvent, function() self:TossPotion() end)
|
||||||
end
|
end
|
||||||
local pmClose = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/PotionMenu/Close")
|
local pmClose = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/PotionMenu/Close")
|
||||||
if pmClose ~= nil and pmClose.ButtonComponent ~= nil then
|
if pmClose ~= nil and (pmClose.ButtonComponent ~= nil or pmClose:AddComponent("ButtonComponent") ~= nil) then
|
||||||
pmClose:ConnectEvent(ButtonClickEvent, function() self:ClosePotionMenu() end)
|
pmClose:ConnectEvent(ButtonClickEvent, function() self:ClosePotionMenu() end)
|
||||||
end
|
end
|
||||||
local shopPotion = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud/Potion")
|
local shopPotion = _EntityService:GetEntityByPath("/ui/RunUIGroup/ShopHud/Potion")
|
||||||
if shopPotion ~= nil and shopPotion.ButtonComponent ~= nil then
|
if shopPotion ~= nil and (shopPotion.ButtonComponent ~= nil or shopPotion:AddComponent("ButtonComponent") ~= nil) then
|
||||||
shopPotion:ConnectEvent(ButtonClickEvent, function() self:BuyPotion() end)
|
shopPotion:ConnectEvent(ButtonClickEvent, function() self:BuyPotion() end)
|
||||||
end
|
end
|
||||||
local chest = _EntityService:GetEntityByPath("/ui/DefaultGroup/TreasureHud/Chest")
|
local chest = _EntityService:GetEntityByPath("/ui/RunUIGroup/TreasureHud/Chest")
|
||||||
if chest ~= nil and chest.ButtonComponent ~= nil then
|
if chest ~= nil and (chest.ButtonComponent ~= nil or chest:AddComponent("ButtonComponent") ~= nil) then
|
||||||
chest:ConnectEvent(ButtonClickEvent, function() self:OpenChest() end)
|
chest:ConnectEvent(ButtonClickEvent, function() self:OpenChest() end)
|
||||||
end
|
end
|
||||||
local treasureLeave = _EntityService:GetEntityByPath("/ui/DefaultGroup/TreasureHud/Leave")
|
local treasureLeave = _EntityService:GetEntityByPath("/ui/RunUIGroup/TreasureHud/Leave")
|
||||||
if treasureLeave ~= nil and treasureLeave.ButtonComponent ~= nil then
|
if treasureLeave ~= nil and (treasureLeave.ButtonComponent ~= nil or treasureLeave:AddComponent("ButtonComponent") ~= nil) then
|
||||||
treasureLeave:ConnectEvent(ButtonClickEvent, function() self:LeaveNode() end)
|
treasureLeave:ConnectEvent(ButtonClickEvent, function() self:LeaveNode() end)
|
||||||
end
|
end
|
||||||
local jcRelic = _EntityService:GetEntityByPath("/ui/DefaultGroup/JobChoiceHud/RelicButton")
|
local jcRelic = _EntityService:GetEntityByPath("/ui/SelectUIGroup/JobChoiceHud/RelicButton")
|
||||||
if jcRelic ~= nil and jcRelic.ButtonComponent ~= nil then
|
if jcRelic ~= nil and (jcRelic.ButtonComponent ~= nil or jcRelic:AddComponent("ButtonComponent") ~= nil) then
|
||||||
jcRelic:ConnectEvent(ButtonClickEvent, function() self:PickJobReward("relic") end)
|
jcRelic:ConnectEvent(ButtonClickEvent, function() self:PickJobReward("relic") end)
|
||||||
end
|
end
|
||||||
local jcJob = _EntityService:GetEntityByPath("/ui/DefaultGroup/JobChoiceHud/JobButton")
|
local jcJob = _EntityService:GetEntityByPath("/ui/SelectUIGroup/JobChoiceHud/JobButton")
|
||||||
if jcJob ~= nil and jcJob.ButtonComponent ~= nil then
|
if jcJob ~= nil and (jcJob.ButtonComponent ~= nil or jcJob:AddComponent("ButtonComponent") ~= nil) then
|
||||||
jcJob:ConnectEvent(ButtonClickEvent, function() self:PickJobReward("job") end)
|
jcJob:ConnectEvent(ButtonClickEvent, function() self:PickJobReward("job") end)
|
||||||
end
|
end
|
||||||
for i = 1, 3 do
|
for i = 1, 3 do
|
||||||
local slotIdx = i
|
local slotIdx = i
|
||||||
local jb = _EntityService:GetEntityByPath("/ui/DefaultGroup/JobSelectHud/Job_slot" .. tostring(i))
|
local jb = _EntityService:GetEntityByPath("/ui/SelectUIGroup/JobSelectHud/Job_slot" .. tostring(i))
|
||||||
if jb ~= nil and jb.ButtonComponent ~= nil then
|
if jb ~= nil and (jb.ButtonComponent ~= nil or jb:AddComponent("ButtonComponent") ~= nil) then
|
||||||
jb:ConnectEvent(ButtonClickEvent, function()
|
jb:ConnectEvent(ButtonClickEvent, function()
|
||||||
if self.JobOpts ~= nil and self.JobOpts[slotIdx] ~= nil then
|
if self.JobOpts ~= nil and self.JobOpts[slotIdx] ~= nil then
|
||||||
self:SetJob(self.JobOpts[slotIdx].id)
|
self:SetJob(self.JobOpts[slotIdx].id)
|
||||||
@@ -214,6 +224,8 @@ for i = 1, 3 do
|
|||||||
end
|
end
|
||||||
end`),
|
end`),
|
||||||
method('StartPlayerTurn', `self.Turn = self.Turn + 1
|
method('StartPlayerTurn', `self.Turn = self.Turn + 1
|
||||||
|
self.RetainSelectActive = false
|
||||||
|
self:UpdateDiscardPrompt()
|
||||||
self.Energy = self.MaxEnergy
|
self.Energy = self.MaxEnergy
|
||||||
self:ApplyRelics("turnStart")
|
self:ApplyRelics("turnStart")
|
||||||
self.PlayerBlock = 0
|
self.PlayerBlock = 0
|
||||||
@@ -241,6 +253,33 @@ end
|
|||||||
self:DrawCards(5)
|
self:DrawCards(5)
|
||||||
self:RenderHand(true)
|
self:RenderHand(true)
|
||||||
self:RenderCombat()`),
|
self:RenderCombat()`),
|
||||||
|
method('HasPowerEffect', `if self.PlayerPowers == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
for i = 1, #self.PlayerPowers do
|
||||||
|
local pc = self.Cards[self.PlayerPowers[i]]
|
||||||
|
if pc ~= nil and pc.powerEffect == effect then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'effect' }], 0, 'boolean'),
|
||||||
|
method('ShouldOfferRetain', `if self:HasPowerEffect("retainOne") ~= true then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if self.Hand == nil or #self.Hand <= 0 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
for i = 1, #self.Hand do
|
||||||
|
local c = self.Cards[self.Hand[i]]
|
||||||
|
if c ~= nil and c.retain ~= true then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false`, [], 0, 'boolean'),
|
||||||
|
method('BeginRetainSelection', `self.RetainSelectActive = true
|
||||||
|
self:UpdateDiscardPrompt()
|
||||||
|
self:Toast("보존할 카드를 선택하세요")
|
||||||
|
self:RenderHand(false)`, []),
|
||||||
method('EndPlayerTurn', `if self.CombatOver == true or self.FxBusy == true or self.TurnBusy == true then
|
method('EndPlayerTurn', `if self.CombatOver == true or self.FxBusy == true or self.TurnBusy == true then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -248,6 +287,17 @@ if self:IsDiscardSelecting() == true then
|
|||||||
self:Toast("버릴 카드를 먼저 선택하세요")
|
self:Toast("버릴 카드를 먼저 선택하세요")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
if self:IsRetainSelecting() == true then
|
||||||
|
self:FinishPlayerTurn(0)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if self:ShouldOfferRetain() == true then
|
||||||
|
self:BeginRetainSelection()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self:FinishPlayerTurn(0)`),
|
||||||
|
method('FinishPlayerTurn', `self.RetainSelectActive = false
|
||||||
|
self:UpdateDiscardPrompt()
|
||||||
local burn = 0
|
local burn = 0
|
||||||
for bi = 1, #self.Hand do
|
for bi = 1, #self.Hand do
|
||||||
\tlocal hc = self.Cards[self.Hand[bi]]
|
\tlocal hc = self.Cards[self.Hand[bi]]
|
||||||
@@ -263,7 +313,7 @@ local kept = {}
|
|||||||
for i = 1, #self.Hand do
|
for i = 1, #self.Hand do
|
||||||
\tlocal cardId = self.Hand[i]
|
\tlocal cardId = self.Hand[i]
|
||||||
\tlocal c = self.Cards[cardId]
|
\tlocal c = self.Cards[cardId]
|
||||||
\tif c ~= nil and c.retain == true then
|
\tif c ~= nil and (c.retain == true or i == retainSlot) then
|
||||||
\t\ttable.insert(kept, cardId)
|
\t\ttable.insert(kept, cardId)
|
||||||
\telse
|
\telse
|
||||||
\t\ttable.insert(self.DiscardPile, cardId)
|
\t\ttable.insert(self.DiscardPile, cardId)
|
||||||
@@ -274,8 +324,9 @@ if self.PlayerWeak > 0 then self.PlayerWeak = self.PlayerWeak - 1 end
|
|||||||
if self.PlayerVuln > 0 then self.PlayerVuln = self.PlayerVuln - 1 end
|
if self.PlayerVuln > 0 then self.PlayerVuln = self.PlayerVuln - 1 end
|
||||||
self:RenderHand(false)
|
self:RenderHand(false)
|
||||||
self:RenderPiles()
|
self:RenderPiles()
|
||||||
self:EnemyTurn()`),
|
self:EnemyTurn()`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'retainSlot' }]),
|
||||||
method('DrawCards', `local drawnSlots = {}
|
method('DrawCards', `local drawnSlots = {}
|
||||||
|
local drewAny = false
|
||||||
for i = 1, amount do
|
for i = 1, amount do
|
||||||
\tif #self.DrawPile <= 0 then
|
\tif #self.DrawPile <= 0 then
|
||||||
\t\tself:RecycleDiscardIntoDraw()
|
\t\tself:RecycleDiscardIntoDraw()
|
||||||
@@ -289,14 +340,15 @@ for i = 1, amount do
|
|||||||
\t\tself:TriggerSly(cardId)
|
\t\tself:TriggerSly(cardId)
|
||||||
\telse
|
\telse
|
||||||
\t\ttable.insert(self.Hand, cardId)
|
\t\ttable.insert(self.Hand, cardId)
|
||||||
\t\tif #self.Hand <= 5 then
|
\t\tdrewAny = true
|
||||||
\t\t\ttable.insert(drawnSlots, #self.Hand)
|
\t\ttable.insert(drawnSlots, #self.Hand)
|
||||||
\t\tend
|
|
||||||
\tend
|
\tend
|
||||||
end
|
end
|
||||||
self:RenderPiles()
|
self:RenderPiles()
|
||||||
if animate == true and #drawnSlots > 0 then
|
if drewAny == true then
|
||||||
\tself:RenderHand(false)
|
\tself:RenderHand(false)
|
||||||
|
end
|
||||||
|
if animate == true and #drawnSlots > 0 then
|
||||||
\tlocal drawStart = Vector2(-590, 8)
|
\tlocal drawStart = Vector2(-590, 8)
|
||||||
\tfor i = 1, #drawnSlots do
|
\tfor i = 1, #drawnSlots do
|
||||||
\t\tlocal slot = drawnSlots[i]
|
\t\tlocal slot = drawnSlots[i]
|
||||||
@@ -333,11 +385,11 @@ for i = 1, #self.DiscardPile do
|
|||||||
end
|
end
|
||||||
self.DiscardPile = {}
|
self.DiscardPile = {}
|
||||||
self:Shuffle(self.DrawPile)`),
|
self:Shuffle(self.DrawPile)`),
|
||||||
method('RenderPiles', `self:SetText("/ui/DefaultGroup/DeckHud/DrawPile/Count", self:FormatNumber(#self.DrawPile))
|
method('RenderPiles', `self:SetText("/ui/RunUIGroup/DeckHud/DrawPile/Count", self:FormatNumber(#self.DrawPile))
|
||||||
self:SetText("/ui/DefaultGroup/DeckHud/DiscardPile/Count", self:FormatNumber(#self.DiscardPile))
|
self:SetText("/ui/RunUIGroup/DeckHud/DiscardPile/Count", self:FormatNumber(#self.DiscardPile))
|
||||||
self:SetText("/ui/DefaultGroup/DeckHud/ExhaustPile/Count", self:FormatNumber(#(self.ExhaustPile or {})))
|
self:SetText("/ui/RunUIGroup/DeckHud/ExhaustPile/Count", self:FormatNumber(#(self.ExhaustPile or {})))
|
||||||
self:SetText("/ui/DefaultGroup/DeckHud/EnergyOrb/Value", string.format("%d", self.Energy) .. "/" .. string.format("%d", self.MaxEnergy))
|
self:SetText("/ui/RunUIGroup/DeckHud/EnergyOrb/Value", string.format("%d", self.Energy) .. "/" .. string.format("%d", self.MaxEnergy))
|
||||||
local inspect = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckInspectHud")
|
local inspect = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckInspectHud")
|
||||||
if inspect ~= nil and inspect.Enable == true and self.DeckInspectKind ~= "" then
|
if inspect ~= nil and inspect.Enable == true and self.DeckInspectKind ~= "" then
|
||||||
self:OpenDeckInspect(self.DeckInspectKind)
|
self:OpenDeckInspect(self.DeckInspectKind)
|
||||||
end`),
|
end`),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const deckViewMethods = [
|
|||||||
method('OpenDeckInspect', `self.DeckInspectKind = kind
|
method('OpenDeckInspect', `self.DeckInspectKind = kind
|
||||||
if self.DeckAllOpen == true then
|
if self.DeckAllOpen == true then
|
||||||
self.DeckAllOpen = false
|
self.DeckAllOpen = false
|
||||||
local allHud = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckAllHud")
|
local allHud = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud")
|
||||||
if allHud ~= nil then
|
if allHud ~= nil then
|
||||||
allHud.Enable = false
|
allHud.Enable = false
|
||||||
end
|
end
|
||||||
@@ -24,12 +24,12 @@ else
|
|||||||
title = "뽑을 덱"
|
title = "뽑을 덱"
|
||||||
end
|
end
|
||||||
self:RenderDeckInspect(pile, title)
|
self:RenderDeckInspect(pile, title)
|
||||||
local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckInspectHud")
|
local hud = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckInspectHud")
|
||||||
if hud ~= nil then
|
if hud ~= nil then
|
||||||
hud.Enable = true
|
hud.Enable = true
|
||||||
end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'kind' }]),
|
end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'kind' }]),
|
||||||
method('CloseDeckInspect', `self.DeckInspectKind = ""
|
method('CloseDeckInspect', `self.DeckInspectKind = ""
|
||||||
local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckInspectHud")
|
local hud = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckInspectHud")
|
||||||
if hud ~= nil then
|
if hud ~= nil then
|
||||||
hud.Enable = false
|
hud.Enable = false
|
||||||
end`),
|
end`),
|
||||||
@@ -41,51 +41,46 @@ local suffix = " (" .. tostring(count) .. ")"
|
|||||||
if count > 60 then
|
if count > 60 then
|
||||||
suffix = suffix .. " - 60장까지 표시"
|
suffix = suffix .. " - 60장까지 표시"
|
||||||
end
|
end
|
||||||
self:SetText("/ui/DefaultGroup/DeckInspectHud/Title", title .. suffix)
|
self:SetText("/ui/DeckUIGroup/DeckInspectHud/Title", title .. suffix)
|
||||||
local empty = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckInspectHud/Empty")
|
self:SetEntityEnabled("/ui/DeckUIGroup/DeckInspectHud/Empty", count <= 0)
|
||||||
if empty ~= nil then
|
|
||||||
empty.Enable = count <= 0
|
|
||||||
end
|
|
||||||
for i = 1, 60 do
|
for i = 1, 60 do
|
||||||
local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckInspectHud/Grid/Card" .. tostring(i))
|
local path = "/ui/DeckUIGroup/DeckInspectHud/Grid/Card" .. tostring(i)
|
||||||
if e ~= nil then
|
local cardId = nil
|
||||||
local cardId = nil
|
if pile ~= nil then
|
||||||
if pile ~= nil then
|
cardId = pile[i]
|
||||||
cardId = pile[i]
|
end
|
||||||
end
|
if cardId == nil then
|
||||||
if cardId == nil then
|
self:SetEntityEnabled(path, false)
|
||||||
e.Enable = false
|
else
|
||||||
else
|
self:SetEntityEnabled(path, true)
|
||||||
e.Enable = true
|
self:ApplyInspectCardVisual(i, cardId)
|
||||||
self:ApplyInspectCardVisual(i, cardId)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end`, [
|
end`, [
|
||||||
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'pile' },
|
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'pile' },
|
||||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'title' },
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'title' },
|
||||||
]),
|
]),
|
||||||
method('ApplyInspectCardVisual', `self:ApplyCardFace("/ui/DefaultGroup/DeckInspectHud/Grid/Card" .. tostring(slot), cardId)`, [
|
method('ApplyInspectCardVisual', `self:ApplyCardFace("/ui/DeckUIGroup/DeckInspectHud/Grid/Card" .. tostring(slot), cardId)`, [
|
||||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
||||||
]),
|
]),
|
||||||
method('BindClassDeckTabs', `local warriorTab = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckAllHud/WarriorTab")
|
method('BindClassDeckTabs', `local warriorTab = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/WarriorTab")
|
||||||
if warriorTab ~= nil and warriorTab.ButtonComponent ~= nil then
|
if warriorTab ~= nil and (warriorTab.ButtonComponent ~= nil or warriorTab:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.WarriorDeckTabHandler ~= nil then
|
if self.WarriorDeckTabHandler ~= nil then
|
||||||
warriorTab:DisconnectEvent(ButtonClickEvent, self.WarriorDeckTabHandler)
|
warriorTab:DisconnectEvent(ButtonClickEvent, self.WarriorDeckTabHandler)
|
||||||
self.WarriorDeckTabHandler = nil
|
self.WarriorDeckTabHandler = nil
|
||||||
end
|
end
|
||||||
self.WarriorDeckTabHandler = warriorTab:ConnectEvent(ButtonClickEvent, function() self:SetClassDeckTab("warrior") end)
|
self.WarriorDeckTabHandler = warriorTab:ConnectEvent(ButtonClickEvent, function() self:SetClassDeckTab("warrior") end)
|
||||||
end
|
end
|
||||||
local thiefTab = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckAllHud/ThiefTab")
|
local thiefTab = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/ThiefTab")
|
||||||
if thiefTab ~= nil and thiefTab.ButtonComponent ~= nil then
|
if thiefTab ~= nil and (thiefTab.ButtonComponent ~= nil or thiefTab:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.ThiefDeckTabHandler ~= nil then
|
if self.ThiefDeckTabHandler ~= nil then
|
||||||
thiefTab:DisconnectEvent(ButtonClickEvent, self.ThiefDeckTabHandler)
|
thiefTab:DisconnectEvent(ButtonClickEvent, self.ThiefDeckTabHandler)
|
||||||
self.ThiefDeckTabHandler = nil
|
self.ThiefDeckTabHandler = nil
|
||||||
end
|
end
|
||||||
self.ThiefDeckTabHandler = thiefTab:ConnectEvent(ButtonClickEvent, function() self:SetClassDeckTab("bandit") end)
|
self.ThiefDeckTabHandler = thiefTab:ConnectEvent(ButtonClickEvent, function() self:SetClassDeckTab("bandit") end)
|
||||||
end
|
end
|
||||||
local mageTab = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckAllHud/MageTab")
|
local mageTab = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/MageTab")
|
||||||
if mageTab ~= nil and mageTab.ButtonComponent ~= nil then
|
if mageTab ~= nil and (mageTab.ButtonComponent ~= nil or mageTab:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.MageDeckTabHandler ~= nil then
|
if self.MageDeckTabHandler ~= nil then
|
||||||
mageTab:DisconnectEvent(ButtonClickEvent, self.MageDeckTabHandler)
|
mageTab:DisconnectEvent(ButtonClickEvent, self.MageDeckTabHandler)
|
||||||
self.MageDeckTabHandler = nil
|
self.MageDeckTabHandler = nil
|
||||||
@@ -94,12 +89,31 @@ if mageTab ~= nil and mageTab.ButtonComponent ~= nil then
|
|||||||
end`),
|
end`),
|
||||||
method('OpenClassDeck', `self.CodexMode = false
|
method('OpenClassDeck', `self.CodexMode = false
|
||||||
self.ClassDeckMode = true
|
self.ClassDeckMode = true
|
||||||
|
self.DebugCardPickerMode = false
|
||||||
self.DeckAllOpen = true
|
self.DeckAllOpen = true
|
||||||
self:SetClassDeckTab(className)
|
self:SetClassDeckTab(className)
|
||||||
local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckAllHud")
|
local hud = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud")
|
||||||
if hud ~= nil then
|
if hud ~= nil then
|
||||||
hud.Enable = true
|
hud.Enable = true
|
||||||
end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'className' }]),
|
end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'className' }]),
|
||||||
|
method('OpenDebugCardPicker', `if self.RunActive ~= true or self.CombatOver == true or self.Hand == nil then
|
||||||
|
self:Toast("전투 중에만 테스트 카드를 추가할 수 있습니다")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local className = self.SelectedClass
|
||||||
|
if className ~= "warrior" and className ~= "magician" and className ~= "bandit" then
|
||||||
|
className = "bandit"
|
||||||
|
end
|
||||||
|
self.CodexMode = false
|
||||||
|
self.ClassDeckMode = true
|
||||||
|
self.DebugCardPickerMode = true
|
||||||
|
self.DeckAllOpen = true
|
||||||
|
self:SetClassDeckTab(className)
|
||||||
|
local hud = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud")
|
||||||
|
if hud ~= nil then
|
||||||
|
hud.Enable = true
|
||||||
|
end
|
||||||
|
self:Toast("테스트 카드 추가 모드")`),
|
||||||
method('SetClassDeckTab', `if self.ClassDeckMode ~= true then
|
method('SetClassDeckTab', `if self.ClassDeckMode ~= true then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -147,39 +161,38 @@ end)
|
|||||||
self:RenderAllDeck()
|
self:RenderAllDeck()
|
||||||
self:RenderClassDeckTabs()`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'className' }]),
|
self:RenderClassDeckTabs()`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'className' }]),
|
||||||
method('RenderClassDeckTabs', `local tabs = {
|
method('RenderClassDeckTabs', `local tabs = {
|
||||||
{ path = "/ui/DefaultGroup/DeckAllHud/WarriorTab", cls = "warrior" },
|
{ path = "/ui/DeckUIGroup/DeckAllHud/WarriorTab", cls = "warrior" },
|
||||||
{ path = "/ui/DefaultGroup/DeckAllHud/ThiefTab", cls = "bandit" },
|
{ path = "/ui/DeckUIGroup/DeckAllHud/ThiefTab", cls = "bandit" },
|
||||||
{ path = "/ui/DefaultGroup/DeckAllHud/MageTab", cls = "magician" },
|
{ path = "/ui/DeckUIGroup/DeckAllHud/MageTab", cls = "magician" },
|
||||||
}
|
}
|
||||||
for i = 1, #tabs do
|
for i = 1, #tabs do
|
||||||
|
self:SetEntityEnabled(tabs[i].path, self.ClassDeckMode == true)
|
||||||
local e = _EntityService:GetEntityByPath(tabs[i].path)
|
local e = _EntityService:GetEntityByPath(tabs[i].path)
|
||||||
if e ~= nil then
|
if e ~= nil and e.SpriteGUIRendererComponent ~= nil then
|
||||||
e.Enable = self.ClassDeckMode == true
|
if self.ClassDeckClass == tabs[i].cls then
|
||||||
if e.SpriteGUIRendererComponent ~= nil then
|
e.SpriteGUIRendererComponent.Color = Color(0.22, 0.28, 0.34, 1)
|
||||||
if self.ClassDeckClass == tabs[i].cls then
|
else
|
||||||
e.SpriteGUIRendererComponent.Color = Color(0.22, 0.28, 0.34, 1)
|
e.SpriteGUIRendererComponent.Color = Color(0.11, 0.13, 0.16, 1)
|
||||||
else
|
|
||||||
e.SpriteGUIRendererComponent.Color = Color(0.11, 0.13, 0.16, 1)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end`),
|
end`),
|
||||||
method('OpenAllDeck', `local inspectHud = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckInspectHud")
|
method('OpenAllDeck', `local inspectHud = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckInspectHud")
|
||||||
if inspectHud ~= nil then
|
if inspectHud ~= nil then
|
||||||
inspectHud.Enable = false
|
inspectHud.Enable = false
|
||||||
end
|
end
|
||||||
self.DeckInspectKind = ""
|
self.DeckInspectKind = ""
|
||||||
self.ClassDeckMode = false
|
self.ClassDeckMode = false
|
||||||
self.ClassDeckClass = ""
|
self.ClassDeckClass = ""
|
||||||
|
self.DebugCardPickerMode = false
|
||||||
self:RenderClassDeckTabs()
|
self:RenderClassDeckTabs()
|
||||||
self.DeckAllOpen = true
|
self.DeckAllOpen = true
|
||||||
self:RenderAllDeck()
|
self:RenderAllDeck()
|
||||||
local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckAllHud")
|
local hud = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud")
|
||||||
if hud ~= nil then
|
if hud ~= nil then
|
||||||
hud.Enable = true
|
hud.Enable = true
|
||||||
end`),
|
end`),
|
||||||
method('CloseAllDeck', `self.DeckAllOpen = false
|
method('CloseAllDeck', `self.DeckAllOpen = false
|
||||||
local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckAllHud")
|
local hud = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud")
|
||||||
if hud ~= nil then
|
if hud ~= nil then
|
||||||
hud.Enable = false
|
hud.Enable = false
|
||||||
end
|
end
|
||||||
@@ -189,6 +202,7 @@ if self.ClassDeckMode == true then
|
|||||||
self.ClassDeckTitle = ""
|
self.ClassDeckTitle = ""
|
||||||
self.ClassDeckClass = ""
|
self.ClassDeckClass = ""
|
||||||
end
|
end
|
||||||
|
self.DebugCardPickerMode = false
|
||||||
self:RenderClassDeckTabs()
|
self:RenderClassDeckTabs()
|
||||||
if self.CodexMode == true then
|
if self.CodexMode == true then
|
||||||
self.CodexMode = false
|
self.CodexMode = false
|
||||||
@@ -199,31 +213,46 @@ local title = "모든 덱"
|
|||||||
if self.ClassDeckMode == true then
|
if self.ClassDeckMode == true then
|
||||||
pile = self.ClassDeckCards or {}
|
pile = self.ClassDeckCards or {}
|
||||||
title = self.ClassDeckTitle
|
title = self.ClassDeckTitle
|
||||||
|
if self.DebugCardPickerMode == true then
|
||||||
|
title = title .. " - 테스트 카드 추가"
|
||||||
|
end
|
||||||
elseif self.CodexMode == true then
|
elseif self.CodexMode == true then
|
||||||
pile = self.CodexCards or {}
|
pile = self.CodexCards or {}
|
||||||
title = "카드 도감"
|
title = "카드 도감"
|
||||||
end
|
end
|
||||||
local count = #pile
|
local count = #pile
|
||||||
self:SetText("/ui/DefaultGroup/DeckAllHud/Title", title .. " (" .. tostring(count) .. ")")
|
self:SetText("/ui/DeckUIGroup/DeckAllHud/Title", title .. " (" .. tostring(count) .. ")")
|
||||||
self:RenderClassDeckTabs()
|
self:RenderClassDeckTabs()
|
||||||
local empty = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckAllHud/Empty")
|
self:SetEntityEnabled("/ui/DeckUIGroup/DeckAllHud/Empty", count <= 0)
|
||||||
if empty ~= nil then
|
|
||||||
empty.Enable = count <= 0
|
|
||||||
end
|
|
||||||
for i = 1, 120 do
|
for i = 1, 120 do
|
||||||
local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckAllHud/Grid/Card" .. tostring(i))
|
local path = "/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(i)
|
||||||
if e ~= nil then
|
local cardId = pile[i]
|
||||||
local cardId = pile[i]
|
if cardId == nil then
|
||||||
if cardId == nil then
|
self:SetEntityEnabled(path, false)
|
||||||
e.Enable = false
|
else
|
||||||
else
|
self:SetEntityEnabled(path, true)
|
||||||
e.Enable = true
|
self:ApplyAllDeckCardVisual(i, cardId)
|
||||||
self:ApplyAllDeckCardVisual(i, cardId)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end`),
|
end`),
|
||||||
method('ApplyAllDeckCardVisual', `self:ApplyCardFace("/ui/DefaultGroup/DeckAllHud/Grid/Card" .. tostring(slot), cardId)`, [
|
method('ApplyAllDeckCardVisual', `self:ApplyCardFace("/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(slot), cardId)`, [
|
||||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
||||||
]),
|
]),
|
||||||
|
method('OnAllDeckCardButton', `if self.DebugCardPickerMode ~= true then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if self.ClassDeckCards == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local cardId = self.ClassDeckCards[slot]
|
||||||
|
if cardId == nil or self.Cards == nil or self.Cards[cardId] == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self:AddCardsToHand(cardId, 1)
|
||||||
|
local c = self.Cards[cardId]
|
||||||
|
local name = cardId
|
||||||
|
if c.name ~= nil then name = c.name end
|
||||||
|
self:Toast("테스트 카드 추가: " .. name)`, [
|
||||||
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||||
|
]),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ if n > 8 then spacing = math.floor(1400 / n) end
|
|||||||
local startX = -((n - 1) * spacing) / 2
|
local startX = -((n - 1) * spacing) / 2
|
||||||
local drawStart = Vector2(-590, 8)
|
local drawStart = Vector2(-590, 8)
|
||||||
for i = 1, 10 do
|
for i = 1, 10 do
|
||||||
\tlocal cardEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(i))
|
\tlocal cardEntity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(i))
|
||||||
\tif cardEntity ~= nil then
|
\tif cardEntity ~= nil then
|
||||||
\t\tlocal cardId = self.Hand[i]
|
\t\tlocal cardId = self.Hand[i]
|
||||||
\t\tif cardId == nil then
|
\t\tif cardId == nil then
|
||||||
@@ -81,11 +81,11 @@ local xs = {}
|
|||||||
local baseY = 0
|
local baseY = 0
|
||||||
local hoverIndex = 0
|
local hoverIndex = 0
|
||||||
local push = 110
|
local push = 110
|
||||||
if string.find(path, "/ui/DefaultGroup/CardHand/Card") == 1 then
|
if string.find(path, "/ui/RunUIGroup/CardHand/Card") == 1 then
|
||||||
if self.DragSlot ~= nil and self.DragSlot > 0 then
|
if self.DragSlot ~= nil and self.DragSlot > 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
prefix = "/ui/DefaultGroup/CardHand/Card"
|
prefix = "/ui/RunUIGroup/CardHand/Card"
|
||||||
count = 0
|
count = 0
|
||||||
if self.Hand ~= nil then count = #self.Hand end
|
if self.Hand ~= nil then count = #self.Hand end
|
||||||
for i = 1, count do
|
for i = 1, count do
|
||||||
@@ -93,14 +93,14 @@ if string.find(path, "/ui/DefaultGroup/CardHand/Card") == 1 then
|
|||||||
end
|
end
|
||||||
baseY = 0
|
baseY = 0
|
||||||
hoverIndex = tonumber(string.match(path, "Card(%d+)")) or 0
|
hoverIndex = tonumber(string.match(path, "Card(%d+)")) or 0
|
||||||
elseif string.find(path, "/ui/DefaultGroup/RewardHud/Reward") == 1 then
|
elseif string.find(path, "/ui/RunUIGroup/RewardHud/Reward") == 1 then
|
||||||
prefix = "/ui/DefaultGroup/RewardHud/Reward"
|
prefix = "/ui/RunUIGroup/RewardHud/Reward"
|
||||||
count = 3
|
count = 3
|
||||||
xs = { -300, 0, 300 }
|
xs = { -300, 0, 300 }
|
||||||
baseY = 0
|
baseY = 0
|
||||||
hoverIndex = tonumber(string.match(path, "Reward(%d+)")) or 0
|
hoverIndex = tonumber(string.match(path, "Reward(%d+)")) or 0
|
||||||
elseif string.find(path, "/ui/DefaultGroup/ShopHud/Card") == 1 then
|
elseif string.find(path, "/ui/RunUIGroup/ShopHud/Card") == 1 then
|
||||||
prefix = "/ui/DefaultGroup/ShopHud/Card"
|
prefix = "/ui/RunUIGroup/ShopHud/Card"
|
||||||
count = 3
|
count = 3
|
||||||
xs = { -300, 0, 300 }
|
xs = { -300, 0, 300 }
|
||||||
baseY = 20
|
baseY = 20
|
||||||
@@ -159,7 +159,7 @@ self.CardHoverTweenId = eventId`, [
|
|||||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' },
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' },
|
||||||
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'hover' },
|
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'hover' },
|
||||||
]),
|
]),
|
||||||
method('ApplyCardVisual', `self:ApplyCardFace("/ui/DefaultGroup/CardHand/Card" .. tostring(slot), cardId)`, [
|
method('ApplyCardVisual', `self:ApplyCardFace("/ui/RunUIGroup/CardHand/Card" .. tostring(slot), cardId)`, [
|
||||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
||||||
]),
|
]),
|
||||||
@@ -181,7 +181,7 @@ if math.abs(n - math.floor(n)) < 0.00001 then
|
|||||||
return string.format("%d", math.floor(n))
|
return string.format("%d", math.floor(n))
|
||||||
end
|
end
|
||||||
return tostring(n)`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'value' }], 0, 'string'),
|
return tostring(n)`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'value' }], 0, 'string'),
|
||||||
method('AnimateCardFrom', `local cardEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(slot))
|
method('AnimateCardFrom', `local cardEntity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||||
if cardEntity == nil or cardEntity.UITransformComponent == nil then
|
if cardEntity == nil or cardEntity.UITransformComponent == nil then
|
||||||
\treturn
|
\treturn
|
||||||
end
|
end
|
||||||
@@ -203,6 +203,68 @@ end, 1 / 60)`, [
|
|||||||
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'toPos' },
|
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'toPos' },
|
||||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'duration' },
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'duration' },
|
||||||
]),
|
]),
|
||||||
|
method('AnimateDiscardCards', `if cardIds == nil or slots == nil then
|
||||||
|
\treturn
|
||||||
|
end
|
||||||
|
local target = Vector2(590, 8)
|
||||||
|
local duration = 0.18
|
||||||
|
for i = 1, #cardIds do
|
||||||
|
\tlocal slot = slots[i] or i
|
||||||
|
\tlocal e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||||
|
\tif e ~= nil then
|
||||||
|
\t\te.Enable = true
|
||||||
|
\t\tself:ApplyCardFace("/ui/RunUIGroup/CardHand/Card" .. tostring(slot), cardIds[i])
|
||||||
|
\t\tif e.UITransformComponent ~= nil then
|
||||||
|
\t\t\tlocal sx = 0
|
||||||
|
\t\t\tif startXs ~= nil and startXs[i] ~= nil then sx = startXs[i] else sx = self:GetHandSlotX(slot) end
|
||||||
|
\t\t\te.UITransformComponent.anchoredPosition = Vector2(sx, 0)
|
||||||
|
\t\t\te.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
||||||
|
\t\tend
|
||||||
|
\tend
|
||||||
|
end
|
||||||
|
local elapsed = 0
|
||||||
|
local eventId = 0
|
||||||
|
eventId = _TimerService:SetTimerRepeat(function()
|
||||||
|
\telapsed = elapsed + 1 / 60
|
||||||
|
\tlocal t = math.min(elapsed / duration, 1)
|
||||||
|
\tlocal eased = _TweenLogic:Ease(0, 1, 1, EaseType.SineEaseIn, t)
|
||||||
|
\tfor i = 1, #cardIds do
|
||||||
|
\t\tlocal slot = slots[i] or i
|
||||||
|
\t\tlocal e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||||
|
\t\tif e ~= nil and e.UITransformComponent ~= nil then
|
||||||
|
\t\t\tlocal sx = 0
|
||||||
|
\t\t\tif startXs ~= nil and startXs[i] ~= nil then sx = startXs[i] else sx = self:GetHandSlotX(slot) end
|
||||||
|
\t\t\tlocal x = sx + (target.x - sx) * eased
|
||||||
|
\t\t\tlocal y = 0 + (target.y - 0) * eased
|
||||||
|
\t\t\tlocal s = 1 - 0.25 * eased
|
||||||
|
\t\t\te.UITransformComponent.anchoredPosition = Vector2(x, y)
|
||||||
|
\t\t\te.UITransformComponent.UIScale = Vector3(s, s, 1)
|
||||||
|
\t\tend
|
||||||
|
\tend
|
||||||
|
\tif t >= 1 then
|
||||||
|
\t\t_TimerService:ClearTimer(eventId)
|
||||||
|
\t\tfor i = 1, #cardIds do
|
||||||
|
\t\t\tlocal slot = slots[i] or i
|
||||||
|
\t\t\tlocal e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||||
|
\t\t\tif e ~= nil then
|
||||||
|
\t\t\t\tif self.Hand ~= nil and self.Hand[slot] ~= nil then
|
||||||
|
\t\t\t\t\te.Enable = true
|
||||||
|
\t\t\t\t\tself:ApplyCardVisual(slot, self.Hand[slot])
|
||||||
|
\t\t\t\t\tif e.UITransformComponent ~= nil then
|
||||||
|
\t\t\t\t\t\te.UITransformComponent.anchoredPosition = Vector2(self:GetHandSlotX(slot), 0)
|
||||||
|
\t\t\t\t\t\te.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
||||||
|
\t\t\t\t\tend
|
||||||
|
\t\t\t\telse
|
||||||
|
\t\t\t\t\te.Enable = false
|
||||||
|
\t\t\t\tend
|
||||||
|
\t\t\tend
|
||||||
|
\t\tend
|
||||||
|
\tend
|
||||||
|
end, 1 / 60)`, [
|
||||||
|
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardIds' },
|
||||||
|
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'startXs' },
|
||||||
|
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slots' },
|
||||||
|
]),
|
||||||
method('AddCardBlock', `local amount = base or 0
|
method('AddCardBlock', `local amount = base or 0
|
||||||
if amount > 0 and self.PlayerDex ~= nil then
|
if amount > 0 and self.PlayerDex ~= nil then
|
||||||
amount = amount + self.PlayerDex
|
amount = amount + self.PlayerDex
|
||||||
@@ -319,22 +381,31 @@ local cardId = self.Hand[slot]
|
|||||||
if cardId == nil then
|
if cardId == nil then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
local startX = self:GetHandSlotX(slot)
|
||||||
table.remove(self.Hand, slot)
|
table.remove(self.Hand, slot)
|
||||||
table.insert(self.DiscardPile, cardId)
|
table.insert(self.DiscardPile, cardId)
|
||||||
if triggerSly == true then
|
if triggerSly == true then
|
||||||
self:TriggerSly(cardId)
|
self:TriggerSly(cardId)
|
||||||
|
end
|
||||||
|
if animate == true then
|
||||||
|
self:AnimateDiscardCards({ cardId }, { startX }, { slot })
|
||||||
end`, [
|
end`, [
|
||||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||||
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'triggerSly' },
|
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'triggerSly' },
|
||||||
|
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'animate' },
|
||||||
]),
|
]),
|
||||||
method('IsDiscardSelecting', `return self.DiscardSelectRemaining ~= nil and self.DiscardSelectRemaining > 0`, [], 0, 'boolean'),
|
method('IsDiscardSelecting', `return self.DiscardSelectRemaining ~= nil and self.DiscardSelectRemaining > 0`, [], 0, 'boolean'),
|
||||||
method('UpdateDiscardPrompt', `local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/DiscardPrompt")
|
method('IsRetainSelecting', `return self.RetainSelectActive == true`, [], 0, 'boolean'),
|
||||||
|
method('UpdateDiscardPrompt', `local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/DiscardPrompt")
|
||||||
if e == nil then
|
if e == nil then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if self:IsDiscardSelecting() == true then
|
if self:IsDiscardSelecting() == true then
|
||||||
local picked = self.DiscardSelectTotal - self.DiscardSelectRemaining
|
local picked = self.DiscardSelectTotal - self.DiscardSelectRemaining
|
||||||
self:SetText("/ui/DefaultGroup/CombatHud/DiscardPrompt", "버릴 카드 선택 " .. self:FormatNumber(picked + 1) .. "/" .. self:FormatNumber(self.DiscardSelectTotal))
|
self:SetText("/ui/RunUIGroup/CombatHud/DiscardPrompt", "버릴 카드 선택 " .. self:FormatNumber(picked + 1) .. "/" .. self:FormatNumber(self.DiscardSelectTotal))
|
||||||
|
e.Enable = true
|
||||||
|
elseif self:IsRetainSelecting() == true then
|
||||||
|
self:SetText("/ui/RunUIGroup/CombatHud/DiscardPrompt", "보존할 카드 선택 (턴 종료: 건너뛰기)")
|
||||||
e.Enable = true
|
e.Enable = true
|
||||||
else
|
else
|
||||||
e.Enable = false
|
e.Enable = false
|
||||||
@@ -342,10 +413,11 @@ end`),
|
|||||||
method('BeginDiscardSelection', `if c == nil or self.Hand == nil then
|
method('BeginDiscardSelection', `if c == nil or self.Hand == nil then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local n = 0
|
|
||||||
if c.discardAll == true then
|
if c.discardAll == true then
|
||||||
n = #self.Hand
|
return self:AutoDiscardHand(c)
|
||||||
elseif c.discard ~= nil then
|
end
|
||||||
|
local n = 0
|
||||||
|
if c.discard ~= nil then
|
||||||
n = math.min(c.discard, #self.Hand)
|
n = math.min(c.discard, #self.Hand)
|
||||||
end
|
end
|
||||||
if n <= 0 then
|
if n <= 0 then
|
||||||
@@ -363,6 +435,54 @@ if c.addShivPerDiscard == true then
|
|||||||
end
|
end
|
||||||
self:UpdateDiscardPrompt()
|
self:UpdateDiscardPrompt()
|
||||||
self:Toast("버릴 카드를 선택하세요")
|
self:Toast("버릴 카드를 선택하세요")
|
||||||
|
return true`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }], 0, 'boolean'),
|
||||||
|
method('SelectRetainSlot', `if self:IsRetainSelecting() ~= true then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if self.Hand == nil or self.Hand[slot] == nil then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
self:FinishPlayerTurn(slot)
|
||||||
|
return true`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }], 0, 'boolean'),
|
||||||
|
method('AutoDiscardHand', `if c == nil or self.Hand == nil or #self.Hand <= 0 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local cardIds = {}
|
||||||
|
local startXs = {}
|
||||||
|
local slots = {}
|
||||||
|
local n = #self.Hand
|
||||||
|
for i = 1, n do
|
||||||
|
local cardId = self.Hand[i]
|
||||||
|
table.insert(cardIds, cardId)
|
||||||
|
table.insert(startXs, self:GetHandSlotX(i))
|
||||||
|
table.insert(slots, i)
|
||||||
|
table.insert(self.DiscardPile, cardId)
|
||||||
|
end
|
||||||
|
self.Hand = {}
|
||||||
|
local shivCount = 0
|
||||||
|
if c.addShiv ~= nil then shivCount = shivCount + c.addShiv end
|
||||||
|
if c.addShivPerDiscard == true then shivCount = shivCount + n end
|
||||||
|
self.DiscardSelectRemaining = 0
|
||||||
|
self.DiscardSelectTotal = 0
|
||||||
|
self.DiscardPostShiv = 0
|
||||||
|
self.DiscardShivPerPick = 0
|
||||||
|
self:UpdateDiscardPrompt()
|
||||||
|
self:AnimateDiscardCards(cardIds, startXs, slots)
|
||||||
|
for i = 1, #cardIds do
|
||||||
|
self:TriggerSly(cardIds[i])
|
||||||
|
end
|
||||||
|
self:RenderPiles()
|
||||||
|
self:RenderCombat()
|
||||||
|
_TimerService:SetTimerOnce(function()
|
||||||
|
if shivCount > 0 then
|
||||||
|
self:AddCardsToHand("Shiv", shivCount)
|
||||||
|
else
|
||||||
|
self:RenderHand(false)
|
||||||
|
self:RenderPiles()
|
||||||
|
end
|
||||||
|
self:RenderCombat()
|
||||||
|
self:CheckCombatEnd()
|
||||||
|
end, 0.22)
|
||||||
return true`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }], 0, 'boolean'),
|
return true`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }], 0, 'boolean'),
|
||||||
method('FinishDiscardSelection', `self.DiscardSelectRemaining = 0
|
method('FinishDiscardSelection', `self.DiscardSelectRemaining = 0
|
||||||
self.DiscardSelectTotal = 0
|
self.DiscardSelectTotal = 0
|
||||||
@@ -370,13 +490,21 @@ local shivCount = self.DiscardPostShiv or 0
|
|||||||
self.DiscardPostShiv = 0
|
self.DiscardPostShiv = 0
|
||||||
self.DiscardShivPerPick = 0
|
self.DiscardShivPerPick = 0
|
||||||
self:UpdateDiscardPrompt()
|
self:UpdateDiscardPrompt()
|
||||||
if shivCount > 0 then
|
local finish = function()
|
||||||
self:AddCardsToHand("Shiv", shivCount)
|
if shivCount > 0 then
|
||||||
|
self:AddCardsToHand("Shiv", shivCount)
|
||||||
|
else
|
||||||
|
self:RenderHand(false)
|
||||||
|
self:RenderPiles()
|
||||||
|
end
|
||||||
|
self:RenderCombat()
|
||||||
|
self:CheckCombatEnd()
|
||||||
end
|
end
|
||||||
self:RenderHand(false)
|
if delayRender == true then
|
||||||
self:RenderPiles()
|
_TimerService:SetTimerOnce(finish, 0.22)
|
||||||
self:RenderCombat()
|
else
|
||||||
self:CheckCombatEnd()`),
|
finish()
|
||||||
|
end`, [{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'delayRender' }]),
|
||||||
method('SelectDiscardSlot', `if self:IsDiscardSelecting() ~= true then
|
method('SelectDiscardSlot', `if self:IsDiscardSelecting() ~= true then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@@ -384,18 +512,18 @@ if self.Hand == nil or self.Hand[slot] == nil then
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
local discarded = self.Hand[slot]
|
local discarded = self.Hand[slot]
|
||||||
self:DiscardHandCard(slot, true)
|
self:DiscardHandCard(slot, true, true)
|
||||||
if discarded ~= nil and self.DiscardShivPerPick ~= nil and self.DiscardShivPerPick > 0 then
|
if discarded ~= nil and self.DiscardShivPerPick ~= nil and self.DiscardShivPerPick > 0 then
|
||||||
self.DiscardPostShiv = (self.DiscardPostShiv or 0) + self.DiscardShivPerPick
|
self.DiscardPostShiv = (self.DiscardPostShiv or 0) + self.DiscardShivPerPick
|
||||||
end
|
end
|
||||||
self.DiscardSelectRemaining = self.DiscardSelectRemaining - 1
|
self.DiscardSelectRemaining = self.DiscardSelectRemaining - 1
|
||||||
if self.DiscardSelectRemaining <= 0 or #self.Hand <= 0 then
|
if self.DiscardSelectRemaining <= 0 or #self.Hand <= 0 then
|
||||||
self:FinishDiscardSelection()
|
self:FinishDiscardSelection(true)
|
||||||
else
|
else
|
||||||
self:UpdateDiscardPrompt()
|
self:UpdateDiscardPrompt()
|
||||||
self:RenderHand(false)
|
|
||||||
self:RenderPiles()
|
self:RenderPiles()
|
||||||
self:RenderCombat()
|
self:RenderCombat()
|
||||||
|
_TimerService:SetTimerOnce(function() self:RenderHand(false) end, 0.22)
|
||||||
end
|
end
|
||||||
return true`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }], 0, 'boolean'),
|
return true`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }], 0, 'boolean'),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ if self:AddPotion(pid) == true then
|
|||||||
self:Toast("물약 획득: " .. p.name)
|
self:Toast("물약 획득: " .. p.name)
|
||||||
end`),
|
end`),
|
||||||
method('RenderPotions', `for i = 1, 5 do
|
method('RenderPotions', `for i = 1, 5 do
|
||||||
local base = "/ui/DefaultGroup/CombatHud/TopBar/PotionSlot" .. tostring(i)
|
local base = "/ui/RunUIGroup/CombatHud/TopBar/PotionSlot" .. tostring(i)
|
||||||
local e = _EntityService:GetEntityByPath(base)
|
local e = _EntityService:GetEntityByPath(base)
|
||||||
if e ~= nil and e.SpriteGUIRendererComponent ~= nil then
|
if e ~= nil and e.SpriteGUIRendererComponent ~= nil then
|
||||||
local pid = nil
|
local pid = nil
|
||||||
@@ -121,11 +121,11 @@ self.PotionMenuSlot = slot
|
|||||||
local pid = self.RunPotions[slot]
|
local pid = self.RunPotions[slot]
|
||||||
local p = self.Potions[pid]
|
local p = self.Potions[pid]
|
||||||
if p ~= nil then
|
if p ~= nil then
|
||||||
self:SetText("/ui/DefaultGroup/CombatHud/PotionMenu/Title", p.name .. " — " .. p.desc)
|
self:SetText("/ui/RunUIGroup/CombatHud/PotionMenu/Title", p.name .. " — " .. p.desc)
|
||||||
end
|
end
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud/PotionMenu", true)`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/PotionMenu", true)`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||||
method('ClosePotionMenu', `self.PotionMenuSlot = 0
|
method('ClosePotionMenu', `self.PotionMenuSlot = 0
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud/PotionMenu", false)`),
|
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/PotionMenu", false)`),
|
||||||
method('UsePotion', `if self.PotionMenuSlot <= 0 then
|
method('UsePotion', `if self.PotionMenuSlot <= 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -133,8 +133,8 @@ if self.CombatOver == true or self.TurnBusy == true or self.FxBusy == true then
|
|||||||
self:Toast("지금은 사용할 수 없습니다")
|
self:Toast("지금은 사용할 수 없습니다")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local combat = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud")
|
local combat = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud")
|
||||||
local hand = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand")
|
local hand = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand")
|
||||||
if combat == nil or combat.Enable ~= true or hand == nil or hand.Enable ~= true then
|
if combat == nil or combat.Enable ~= true or hand == nil or hand.Enable ~= true then
|
||||||
self:Toast("전투 중에만 사용할 수 있습니다")
|
self:Toast("전투 중에만 사용할 수 있습니다")
|
||||||
return
|
return
|
||||||
@@ -189,7 +189,7 @@ if self.RunRelics ~= nil then
|
|||||||
count = #self.RunRelics
|
count = #self.RunRelics
|
||||||
end
|
end
|
||||||
for i = 1, 10 do
|
for i = 1, 10 do
|
||||||
local base = "/ui/DefaultGroup/CombatHud/TopBar/RelicSlot" .. tostring(i)
|
local base = "/ui/RunUIGroup/CombatHud/TopBar/RelicSlot" .. tostring(i)
|
||||||
local e = _EntityService:GetEntityByPath(base)
|
local e = _EntityService:GetEntityByPath(base)
|
||||||
if e ~= nil and e.SpriteGUIRendererComponent ~= nil then
|
if e ~= nil and e.SpriteGUIRendererComponent ~= nil then
|
||||||
local rid = nil
|
local rid = nil
|
||||||
@@ -209,5 +209,5 @@ local of = ""
|
|||||||
if count > 10 then
|
if count > 10 then
|
||||||
of = "+" .. tostring(count - 9)
|
of = "+" .. tostring(count - 9)
|
||||||
end
|
end
|
||||||
self:SetText("/ui/DefaultGroup/CombatHud/TopBar/RelicOverflow", of)`),
|
self:SetText("/ui/RunUIGroup/CombatHud/TopBar/RelicOverflow", of)`),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ 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 jobMethods = [
|
export const jobMethods = [
|
||||||
method('ShowJobChoice', `self:SetEntityEnabled("/ui/DefaultGroup/CardHand", false)
|
method('ShowJobChoice', `self:SetEntityEnabled("/ui/RunUIGroup/CardHand", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/DeckHud", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/DeckHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/JobChoiceHud", true)`),
|
self:SetEntityEnabled("/ui/SelectUIGroup/JobChoiceHud", true)`),
|
||||||
method('PickJobReward', `self:SetEntityEnabled("/ui/DefaultGroup/JobChoiceHud", false)
|
method('PickJobReward', `self:SetEntityEnabled("/ui/SelectUIGroup/JobChoiceHud", false)
|
||||||
if kind == "relic" then
|
if kind == "relic" then
|
||||||
local bid = self:PickNewRelic()
|
local bid = self:PickNewRelic()
|
||||||
if bid ~= "" then
|
if bid ~= "" then
|
||||||
@@ -26,7 +26,7 @@ if opts == nil then
|
|||||||
end
|
end
|
||||||
self.JobOpts = opts
|
self.JobOpts = opts
|
||||||
for i = 1, 3 do
|
for i = 1, 3 do
|
||||||
local base = "/ui/DefaultGroup/JobSelectHud/Job_slot" .. tostring(i)
|
local base = "/ui/SelectUIGroup/JobSelectHud/Job_slot" .. tostring(i)
|
||||||
local o = opts[i]
|
local o = opts[i]
|
||||||
if o ~= nil then
|
if o ~= nil then
|
||||||
self:SetEntityEnabled(base, true)
|
self:SetEntityEnabled(base, true)
|
||||||
@@ -40,7 +40,7 @@ for i = 1, 3 do
|
|||||||
self:SetEntityEnabled(base, false)
|
self:SetEntityEnabled(base, false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/JobSelectHud", true)`),
|
self:SetEntityEnabled("/ui/SelectUIGroup/JobSelectHud", true)`),
|
||||||
method('JobLabel', `if self.PlayerJob ~= "" and self.Jobs ~= nil then
|
method('JobLabel', `if self.PlayerJob ~= "" and self.Jobs ~= nil then
|
||||||
for cls, list in pairs(self.Jobs) do
|
for cls, list in pairs(self.Jobs) do
|
||||||
for i = 1, #list do
|
for i = 1, #list do
|
||||||
@@ -73,7 +73,7 @@ if starter ~= "" then
|
|||||||
self:Toast("2차 전직: " .. self:JobLabel() .. "! 신규 카드 — " .. sc.name)
|
self:Toast("2차 전직: " .. self:JobLabel() .. "! 신규 카드 — " .. sc.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self:SetText("/ui/DefaultGroup/CombatHud/PlayerPanel/Name", self:JobLabel())
|
self:SetText("/ui/RunUIGroup/CombatHud/PlayerPanel/Name", self:JobLabel())
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/JobSelectHud", false)
|
self:SetEntityEnabled("/ui/SelectUIGroup/JobSelectHud", false)
|
||||||
self:ContinueAfterBoss()`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'jobId' }]),
|
self:ContinueAfterBoss()`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'jobId' }]),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ for i = 1, #list do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
return false`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'id' }], 0, 'boolean'),
|
return false`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'id' }], 0, 'boolean'),
|
||||||
method('RenderMapNode', `local base = "/ui/DefaultGroup/MapHud/Node_" .. id
|
method('RenderMapNode', `local base = "/ui/RunUIGroup/MapHud/Node_" .. id
|
||||||
local e = _EntityService:GetEntityByPath(base)
|
local e = _EntityService:GetEntityByPath(base)
|
||||||
if e == nil then
|
if e == nil then
|
||||||
return
|
return
|
||||||
@@ -151,7 +151,7 @@ if e.SpriteGUIRendererComponent ~= nil then
|
|||||||
e.SpriteGUIRendererComponent.Color = Color(0.68, 0.68, 0.72, 0.85)
|
e.SpriteGUIRendererComponent.Color = Color(0.68, 0.68, 0.72, 0.85)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if e.ButtonComponent ~= nil then
|
if (e.ButtonComponent ~= nil or e:AddComponent("ButtonComponent") ~= nil) then
|
||||||
e.ButtonComponent.Enable = reachable
|
e.ButtonComponent.Enable = reachable
|
||||||
end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'id' }]),
|
end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'id' }]),
|
||||||
method('RenderMapDots', `local node = self.MapNodes[fromId]
|
method('RenderMapDots', `local node = self.MapNodes[fromId]
|
||||||
@@ -162,7 +162,7 @@ if node ~= nil then
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
for k = 1, 3 do
|
for k = 1, 3 do
|
||||||
local d = _EntityService:GetEntityByPath("/ui/DefaultGroup/MapHud/Dot_" .. dotId .. "_" .. tostring(k))
|
local d = _EntityService:GetEntityByPath("/ui/RunUIGroup/MapHud/Dot_" .. dotId .. "_" .. tostring(k))
|
||||||
if d ~= nil then
|
if d ~= nil then
|
||||||
d.Enable = has
|
d.Enable = has
|
||||||
if has == true and d.SpriteGUIRendererComponent ~= nil then
|
if has == true and d.SpriteGUIRendererComponent ~= nil then
|
||||||
@@ -210,7 +210,7 @@ if self.VisitedNodes == nil then
|
|||||||
self.VisitedNodes = {}
|
self.VisitedNodes = {}
|
||||||
end
|
end
|
||||||
table.insert(self.VisitedNodes, id)
|
table.insert(self.VisitedNodes, id)
|
||||||
local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/MapHud")
|
local hud = _EntityService:GetEntityByPath("/ui/RunUIGroup/MapHud")
|
||||||
if hud ~= nil then
|
if hud ~= nil then
|
||||||
hud.Enable = false
|
hud.Enable = false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ return table.concat(parts, " ")`, [
|
|||||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'poison' },
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'poison' },
|
||||||
], 0, 'string'),
|
], 0, 'string'),
|
||||||
method('RenderCombat', `for i = 1, ${MAX_MONSTERS} do
|
method('RenderCombat', `for i = 1, ${MAX_MONSTERS} do
|
||||||
local base = "/ui/DefaultGroup/CombatHud/MonsterSlot" .. tostring(i)
|
local base = "/ui/RunUIGroup/CombatHud/MonsterStatus" .. tostring(i)
|
||||||
local m = self.Monsters[i]
|
local m = self.Monsters[i]
|
||||||
if m ~= nil and m.alive == true then
|
if m ~= nil and m.alive == true then
|
||||||
self:SetEntityEnabled(base, true)
|
self:SetEntityEnabled(base, true)
|
||||||
@@ -41,7 +41,6 @@ return table.concat(parts, " ")`, [
|
|||||||
local dragActive = self.DragTargetIndex ~= nil and self.DragTargetIndex > 0
|
local dragActive = self.DragTargetIndex ~= nil and self.DragTargetIndex > 0
|
||||||
local shownTarget = self.TargetIndex
|
local shownTarget = self.TargetIndex
|
||||||
if dragActive == true then shownTarget = self.DragTargetIndex end
|
if dragActive == true then shownTarget = self.DragTargetIndex end
|
||||||
self:SetEntityEnabled(base .. "/TargetFrame", i == shownTarget)
|
|
||||||
self:SetEntityEnabled(base .. "/TargetMarker", i == shownTarget and dragActive)
|
self:SetEntityEnabled(base .. "/TargetMarker", i == shownTarget and dragActive)
|
||||||
self:SetEntityEnabled(base .. "/TargetMarker/Label", i == shownTarget and dragActive)
|
self:SetEntityEnabled(base .. "/TargetMarker/Label", i == shownTarget and dragActive)
|
||||||
local intentEntity = _EntityService:GetEntityByPath(base .. "/Intent")
|
local intentEntity = _EntityService:GetEntityByPath(base .. "/Intent")
|
||||||
@@ -64,10 +63,10 @@ return table.concat(parts, " ")`, [
|
|||||||
self:SetEntityEnabled(base, false)
|
self:SetEntityEnabled(base, false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self:SetText("/ui/DefaultGroup/CombatHud/PlayerPanel/HpText", string.format("%d", self.PlayerHp) .. "/" .. string.format("%d", self.PlayerMaxHp))
|
self:SetText("/ui/RunUIGroup/CombatHud/PlayerPanel/HpText", string.format("%d", self.PlayerHp) .. "/" .. string.format("%d", self.PlayerMaxHp))
|
||||||
self:SetHpBar("/ui/DefaultGroup/CombatHud/PlayerPanel/HpBarFill", self.PlayerHp, self.PlayerMaxHp, 220)
|
self:SetHpBar("/ui/RunUIGroup/CombatHud/PlayerPanel/HpBarFill", self.PlayerHp, self.PlayerMaxHp, 220)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud/PlayerPanel/BlockBadge", self.PlayerBlock > 0)
|
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/PlayerPanel/BlockBadge", self.PlayerBlock > 0)
|
||||||
self:SetText("/ui/DefaultGroup/CombatHud/PlayerPanel/BlockBadge/Value", string.format("%d", self.PlayerBlock))
|
self:SetText("/ui/RunUIGroup/CombatHud/PlayerPanel/BlockBadge/Value", string.format("%d", self.PlayerBlock))
|
||||||
local pb = self:BuffsLabel(self.PlayerStr, self.PlayerWeak, self.PlayerVuln, 0)
|
local pb = self:BuffsLabel(self.PlayerStr, self.PlayerWeak, self.PlayerVuln, 0)
|
||||||
if self.PlayerDex ~= nil and self.PlayerDex > 0 then
|
if self.PlayerDex ~= nil and self.PlayerDex > 0 then
|
||||||
if pb ~= "" then pb = pb .. " " end
|
if pb ~= "" then pb = pb .. " " end
|
||||||
@@ -86,10 +85,10 @@ if self.PlayerPowers ~= nil and #self.PlayerPowers > 0 then
|
|||||||
if pb ~= "" then pb = pb .. " · " end
|
if pb ~= "" then pb = pb .. " · " end
|
||||||
pb = pb .. table.concat(names, " ")
|
pb = pb .. table.concat(names, " ")
|
||||||
end
|
end
|
||||||
self:SetText("/ui/DefaultGroup/CombatHud/PlayerPanel/Buffs", pb)
|
self:SetText("/ui/RunUIGroup/CombatHud/PlayerPanel/Buffs", pb)
|
||||||
self:RenderRun()`),
|
self:RenderRun()`),
|
||||||
method('ShowDmgPop', `local slotKey = string.format("%d", math.floor(slot or 0))
|
method('ShowDmgPop', `local slotKey = string.format("%d", math.floor(slot or 0))
|
||||||
local base = "/ui/DefaultGroup/CombatHud/DmgPop" .. slotKey
|
local base = "/ui/RunUIGroup/CombatHud/DmgPop" .. slotKey
|
||||||
local pop = _EntityService:GetEntityByPath(base)
|
local pop = _EntityService:GetEntityByPath(base)
|
||||||
if pop == nil then
|
if pop == nil then
|
||||||
return
|
return
|
||||||
@@ -134,7 +133,7 @@ if m ~= nil and m.entity ~= nil and isvalid(m.entity) and m.entity.TransformComp
|
|||||||
local screen = _UILogic:WorldToScreenPosition(Vector2(wp.x, wp.y + ${HEAD_OFFSET_Y + 0.45}))
|
local screen = _UILogic:WorldToScreenPosition(Vector2(wp.x, wp.y + ${HEAD_OFFSET_Y + 0.45}))
|
||||||
popPos = _UILogic:ScreenToUIPosition(screen)
|
popPos = _UILogic:ScreenToUIPosition(screen)
|
||||||
else
|
else
|
||||||
local slotEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/MonsterSlot" .. slotKey)
|
local slotEntity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/MonsterStatus" .. slotKey)
|
||||||
if slotEntity ~= nil and slotEntity.UITransformComponent ~= nil then
|
if slotEntity ~= nil and slotEntity.UITransformComponent ~= nil then
|
||||||
local sp = slotEntity.UITransformComponent.anchoredPosition
|
local sp = slotEntity.UITransformComponent.anchoredPosition
|
||||||
popPos = Vector2(sp.x, sp.y + 76)
|
popPos = Vector2(sp.x, sp.y + 76)
|
||||||
@@ -169,7 +168,7 @@ end, 0.48)`, [
|
|||||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' },
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' },
|
||||||
]),
|
]),
|
||||||
method('ShowPlayerDmgPop', `local base = "/ui/DefaultGroup/CombatHud/PlayerPanel/DmgPop"
|
method('ShowPlayerDmgPop', `local base = "/ui/RunUIGroup/CombatHud/PlayerPanel/DmgPop"
|
||||||
if amount > 0 then
|
if amount > 0 then
|
||||||
self:SetText(base, "-" .. string.format("%d", amount))
|
self:SetText(base, "-" .. string.format("%d", amount))
|
||||||
else
|
else
|
||||||
@@ -291,7 +290,7 @@ end
|
|||||||
local wp = tr.WorldPosition
|
local wp = tr.WorldPosition
|
||||||
local screen = _UILogic:WorldToScreenPosition(Vector2(wp.x, wp.y + ${HEAD_OFFSET_Y}))
|
local screen = _UILogic:WorldToScreenPosition(Vector2(wp.x, wp.y + ${HEAD_OFFSET_Y}))
|
||||||
local uipos = _UILogic:ScreenToUIPosition(screen)
|
local uipos = _UILogic:ScreenToUIPosition(screen)
|
||||||
local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/MonsterSlot" .. tostring(slot))
|
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/MonsterStatus" .. tostring(slot))
|
||||||
if e ~= nil and e.UITransformComponent ~= nil then
|
if e ~= nil and e.UITransformComponent ~= nil then
|
||||||
e.UITransformComponent.anchoredPosition = uipos
|
e.UITransformComponent.anchoredPosition = uipos
|
||||||
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||||
@@ -303,6 +302,6 @@ end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], N
|
|||||||
if self.AscensionLevel > 0 then
|
if self.AscensionLevel > 0 then
|
||||||
floorText = floorText .. " · 승천" .. string.format("%d", self.AscensionLevel)
|
floorText = floorText .. " · 승천" .. string.format("%d", self.AscensionLevel)
|
||||||
end
|
end
|
||||||
self:SetText("/ui/DefaultGroup/CombatHud/TopBar/Floor", floorText)
|
self:SetText("/ui/RunUIGroup/CombatHud/TopBar/Floor", floorText)
|
||||||
self:SetText("/ui/DefaultGroup/CombatHud/TopBar/Gold", "메소 " .. string.format("%d", self.Gold))`),
|
self:SetText("/ui/RunUIGroup/CombatHud/TopBar/Gold", "메소 " .. string.format("%d", self.Gold))`),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ for id, c in pairs(self.Cards) do
|
|||||||
end
|
end
|
||||||
table.sort(pool)
|
table.sort(pool)
|
||||||
return pool`, [], 0, 'any'),
|
return pool`, [], 0, 'any'),
|
||||||
method('OfferReward', `self:SetEntityEnabled("/ui/DefaultGroup/CardHand", false)
|
method('OfferReward', `self:SetEntityEnabled("/ui/RunUIGroup/CardHand", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/DeckHud", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/DeckHud", false)
|
||||||
local pool = self:CardPool()
|
local pool = self:CardPool()
|
||||||
local byRarity = {}
|
local byRarity = {}
|
||||||
for _, id in ipairs(pool) do
|
for _, id in ipairs(pool) do
|
||||||
@@ -30,11 +30,11 @@ for i = 1, 3 do
|
|||||||
self.RewardChoices[i] = bucket[math.random(1, #bucket)]
|
self.RewardChoices[i] = bucket[math.random(1, #bucket)]
|
||||||
self:ApplyRewardVisual(i, self.RewardChoices[i])
|
self:ApplyRewardVisual(i, self.RewardChoices[i])
|
||||||
end
|
end
|
||||||
local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/RewardHud")
|
local hud = _EntityService:GetEntityByPath("/ui/RunUIGroup/RewardHud")
|
||||||
if hud ~= nil then
|
if hud ~= nil then
|
||||||
hud.Enable = true
|
hud.Enable = true
|
||||||
end`),
|
end`),
|
||||||
method('ApplyRewardVisual', `self:ApplyCardFace("/ui/DefaultGroup/RewardHud/Reward" .. tostring(slot), cardId)`, [
|
method('ApplyRewardVisual', `self:ApplyCardFace("/ui/RunUIGroup/RewardHud/Reward" .. tostring(slot), cardId)`, [
|
||||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
||||||
]),
|
]),
|
||||||
@@ -47,7 +47,7 @@ if slot ~= 0 and self.RewardChoices ~= nil then
|
|||||||
table.insert(self.RunDeck, id)
|
table.insert(self.RunDeck, id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/RewardHud")
|
local hud = _EntityService:GetEntityByPath("/ui/RunUIGroup/RewardHud")
|
||||||
if hud ~= nil then
|
if hud ~= nil then
|
||||||
hud.Enable = false
|
hud.Enable = false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -59,11 +59,11 @@ _TimerService:SetTimerOnce(function()
|
|||||||
end, 0.2)`),
|
end, 0.2)`),
|
||||||
method('StartCombat', `self:ShowState("combat")
|
method('StartCombat', `self:ShowState("combat")
|
||||||
self:KickCombatCamera()
|
self:KickCombatCamera()
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud/Result", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/Result", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud/PotionMenu", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/PotionMenu", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud/TooltipBox", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/TooltipBox", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud/DiscardPrompt", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/DiscardPrompt", false)
|
||||||
self:SetText("/ui/DefaultGroup/CombatHud/PlayerPanel/Name", self:JobLabel())
|
self:SetText("/ui/RunUIGroup/CombatHud/PlayerPanel/Name", self:JobLabel())
|
||||||
self.MaxEnergy = 3
|
self.MaxEnergy = 3
|
||||||
self.Turn = 0
|
self.Turn = 0
|
||||||
self.PlayerBlock = 0
|
self.PlayerBlock = 0
|
||||||
@@ -81,6 +81,7 @@ self.DiscardSelectRemaining = 0
|
|||||||
self.DiscardSelectTotal = 0
|
self.DiscardSelectTotal = 0
|
||||||
self.DiscardPostShiv = 0
|
self.DiscardPostShiv = 0
|
||||||
self.DiscardShivPerPick = 0
|
self.DiscardShivPerPick = 0
|
||||||
|
self.RetainSelectActive = false
|
||||||
self.CombatOver = false
|
self.CombatOver = false
|
||||||
self.DiscardPile = {}
|
self.DiscardPile = {}
|
||||||
self.ExhaustPile = {}
|
self.ExhaustPile = {}
|
||||||
@@ -95,7 +96,19 @@ self:BuildMonsters()
|
|||||||
self:RenderCombat()
|
self:RenderCombat()
|
||||||
self:StartPlayerTurn()
|
self:StartPlayerTurn()
|
||||||
self:ApplyRelics("combatStart")
|
self:ApplyRelics("combatStart")
|
||||||
self:RenderCombat()`),
|
self:RenderCombat()
|
||||||
|
local slotTid = 0
|
||||||
|
slotTid = _TimerService:SetTimerRepeat(function()
|
||||||
|
if self.CombatOver == true or self.Monsters == nil or #self.Monsters == 0 then
|
||||||
|
_TimerService:ClearTimer(slotTid)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for i = 1, #self.Monsters do
|
||||||
|
if self.Monsters[i] ~= nil and self.Monsters[i].alive == true then
|
||||||
|
self:PositionMonsterSlot(i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end, 0.15)`),
|
||||||
method('RegisterMonster', `if self.Registered == nil then
|
method('RegisterMonster', `if self.Registered == nil then
|
||||||
self.Registered = {}
|
self.Registered = {}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ if lp.CurrentMapName == target then
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
_TeleportService:TeleportToMapPosition(lp, Vector3(-6, 0.03, 0), target)`),
|
_TeleportService:TeleportToMapPosition(lp, Vector3(-6, 0.03, 0), target)`),
|
||||||
method('ShowResult', `self:SetText("/ui/DefaultGroup/CombatHud/Result", text)
|
method('ShowResult', `self:SetText("/ui/RunUIGroup/CombatHud/Result", text)
|
||||||
local entity = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/Result")
|
local entity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/Result")
|
||||||
if entity ~= nil then
|
if entity ~= nil then
|
||||||
entity.Enable = true
|
entity.Enable = true
|
||||||
end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'text' }]),
|
end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'text' }]),
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ self.ShopPotion = pkeys[math.random(1, #pkeys)]
|
|||||||
self.ShopPotionBought = false
|
self.ShopPotionBought = false
|
||||||
self:RenderShop()
|
self:RenderShop()
|
||||||
self:ShowState("shop")`),
|
self:ShowState("shop")`),
|
||||||
method('RenderShop', `self:SetText("/ui/DefaultGroup/ShopHud/Gold", "메소 " .. string.format("%d", self.Gold))
|
method('RenderShop', `self:SetText("/ui/RunUIGroup/ShopHud/Gold", "메소 " .. string.format("%d", self.Gold))
|
||||||
for i = 1, 3 do
|
for i = 1, 3 do
|
||||||
local cid = self.ShopChoices[i]
|
local cid = self.ShopChoices[i]
|
||||||
local c = self.Cards[cid]
|
local c = self.Cards[cid]
|
||||||
local base = "/ui/DefaultGroup/ShopHud/Card" .. tostring(i)
|
local base = "/ui/RunUIGroup/ShopHud/Card" .. tostring(i)
|
||||||
if c ~= nil then
|
if c ~= nil then
|
||||||
self:ApplyCardFace(base, cid)
|
self:ApplyCardFace(base, cid)
|
||||||
self:SetText(base .. "/Price", string.format("%d", ${CARD_PRICE}) .. " 메소")
|
self:SetText(base .. "/Price", string.format("%d", ${CARD_PRICE}) .. " 메소")
|
||||||
@@ -38,9 +38,9 @@ for i = 1, 3 do
|
|||||||
end
|
end
|
||||||
local rr = self.Relics[self.ShopRelic]
|
local rr = self.Relics[self.ShopRelic]
|
||||||
if rr ~= nil then
|
if rr ~= nil then
|
||||||
self:SetText("/ui/DefaultGroup/ShopHud/Relic/Label", rr.name .. " — " .. rr.desc)
|
self:SetText("/ui/RunUIGroup/ShopHud/Relic/Label", rr.name .. " — " .. rr.desc)
|
||||||
self:SetText("/ui/DefaultGroup/ShopHud/Relic/Price", string.format("%d", ${RELIC_PRICE}) .. " 메소")
|
self:SetText("/ui/RunUIGroup/ShopHud/Relic/Price", string.format("%d", ${RELIC_PRICE}) .. " 메소")
|
||||||
local re = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud/Relic")
|
local re = _EntityService:GetEntityByPath("/ui/RunUIGroup/ShopHud/Relic")
|
||||||
if re ~= nil and re.SpriteGUIRendererComponent ~= nil then
|
if re ~= nil and re.SpriteGUIRendererComponent ~= nil then
|
||||||
if self.ShopRelicBought == true then
|
if self.ShopRelicBought == true then
|
||||||
re.SpriteGUIRendererComponent.Color = Color(0.2, 0.22, 0.26, 0.6)
|
re.SpriteGUIRendererComponent.Color = Color(0.2, 0.22, 0.26, 0.6)
|
||||||
@@ -51,9 +51,9 @@ if rr ~= nil then
|
|||||||
end
|
end
|
||||||
local pp = self.Potions[self.ShopPotion]
|
local pp = self.Potions[self.ShopPotion]
|
||||||
if pp ~= nil then
|
if pp ~= nil then
|
||||||
self:SetText("/ui/DefaultGroup/ShopHud/Potion/Label", pp.name .. " — " .. pp.desc)
|
self:SetText("/ui/RunUIGroup/ShopHud/Potion/Label", pp.name .. " — " .. pp.desc)
|
||||||
self:SetText("/ui/DefaultGroup/ShopHud/Potion/Price", string.format("%d", ${POTIONS.shopPrice}) .. " 메소")
|
self:SetText("/ui/RunUIGroup/ShopHud/Potion/Price", string.format("%d", ${POTIONS.shopPrice}) .. " 메소")
|
||||||
local pe = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud/Potion")
|
local pe = _EntityService:GetEntityByPath("/ui/RunUIGroup/ShopHud/Potion")
|
||||||
if pe ~= nil and pe.SpriteGUIRendererComponent ~= nil then
|
if pe ~= nil and pe.SpriteGUIRendererComponent ~= nil then
|
||||||
if self.ShopPotionBought == true then
|
if self.ShopPotionBought == true then
|
||||||
pe.SpriteGUIRendererComponent.Color = Color(0.2, 0.22, 0.26, 0.6)
|
pe.SpriteGUIRendererComponent.Color = Color(0.2, 0.22, 0.26, 0.6)
|
||||||
@@ -106,24 +106,24 @@ if self.PlayerHp > self.PlayerMaxHp then
|
|||||||
self.PlayerHp = self.PlayerMaxHp
|
self.PlayerHp = self.PlayerMaxHp
|
||||||
end
|
end
|
||||||
local healed = self.PlayerHp - old
|
local healed = self.PlayerHp - old
|
||||||
self:SetText("/ui/DefaultGroup/RestHud/Info", "HP " .. string.format("%d", old) .. " → " .. string.format("%d", self.PlayerHp) .. " (+" .. string.format("%d", healed) .. ")")
|
self:SetText("/ui/RunUIGroup/RestHud/Info", "HP " .. string.format("%d", old) .. " → " .. string.format("%d", self.PlayerHp) .. " (+" .. string.format("%d", healed) .. ")")
|
||||||
self:RenderCombat()
|
self:RenderCombat()
|
||||||
self:ShowState("rest")`),
|
self:ShowState("rest")`),
|
||||||
method('LeaveNode', `local s = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud")
|
method('LeaveNode', `local s = _EntityService:GetEntityByPath("/ui/RunUIGroup/ShopHud")
|
||||||
if s ~= nil then
|
if s ~= nil then
|
||||||
s.Enable = false
|
s.Enable = false
|
||||||
end
|
end
|
||||||
local r = _EntityService:GetEntityByPath("/ui/DefaultGroup/RestHud")
|
local r = _EntityService:GetEntityByPath("/ui/RunUIGroup/RestHud")
|
||||||
if r ~= nil then
|
if r ~= nil then
|
||||||
r.Enable = false
|
r.Enable = false
|
||||||
end
|
end
|
||||||
local t = _EntityService:GetEntityByPath("/ui/DefaultGroup/TreasureHud")
|
local t = _EntityService:GetEntityByPath("/ui/RunUIGroup/TreasureHud")
|
||||||
if t ~= nil then
|
if t ~= nil then
|
||||||
t.Enable = false
|
t.Enable = false
|
||||||
end
|
end
|
||||||
self:ShowMap()`),
|
self:ShowMap()`),
|
||||||
method('ShowTreasure', `self.ChestOpened = false
|
method('ShowTreasure', `self.ChestOpened = false
|
||||||
local chest = _EntityService:GetEntityByPath("/ui/DefaultGroup/TreasureHud/Chest")
|
local chest = _EntityService:GetEntityByPath("/ui/RunUIGroup/TreasureHud/Chest")
|
||||||
if chest ~= nil then
|
if chest ~= nil then
|
||||||
if chest.SpriteGUIRendererComponent ~= nil then
|
if chest.SpriteGUIRendererComponent ~= nil then
|
||||||
chest.SpriteGUIRendererComponent.ImageRUID = "${CHEST_CLOSED_RUID}"
|
chest.SpriteGUIRendererComponent.ImageRUID = "${CHEST_CLOSED_RUID}"
|
||||||
@@ -132,15 +132,15 @@ if chest ~= nil then
|
|||||||
chest.UITransformComponent.anchoredPosition = Vector2(0, 40)
|
chest.UITransformComponent.anchoredPosition = Vector2(0, 40)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/TreasureHud/Reward", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/TreasureHud/Reward", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/TreasureHud/Hint", true)
|
self:SetEntityEnabled("/ui/RunUIGroup/TreasureHud/Hint", true)
|
||||||
self:ShowState("treasure")`),
|
self:ShowState("treasure")`),
|
||||||
method('OpenChest', `if self.ChestOpened == true then
|
method('OpenChest', `if self.ChestOpened == true then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
self.ChestOpened = true
|
self.ChestOpened = true
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/TreasureHud/Hint", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/TreasureHud/Hint", false)
|
||||||
local chest = _EntityService:GetEntityByPath("/ui/DefaultGroup/TreasureHud/Chest")
|
local chest = _EntityService:GetEntityByPath("/ui/RunUIGroup/TreasureHud/Chest")
|
||||||
local steps = { 10, -10, 8, -8, 5, 0 }
|
local steps = { 10, -10, 8, -8, 5, 0 }
|
||||||
for i = 1, #steps do
|
for i = 1, #steps do
|
||||||
local dx = steps[i]
|
local dx = steps[i]
|
||||||
@@ -167,7 +167,7 @@ _TimerService:SetTimerOnce(function()
|
|||||||
end
|
end
|
||||||
self.Gold = self.Gold + g
|
self.Gold = self.Gold + g
|
||||||
self:RenderRun()
|
self:RenderRun()
|
||||||
self:SetText("/ui/DefaultGroup/TreasureHud/Reward", msg)
|
self:SetText("/ui/RunUIGroup/TreasureHud/Reward", msg)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/TreasureHud/Reward", true)
|
self:SetEntityEnabled("/ui/RunUIGroup/TreasureHud/Reward", true)
|
||||||
end, 0.55)`),
|
end, 0.55)`),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ export const soulMethods = [
|
|||||||
method('ShowSoulShop', `self:RenderSoulLabel()
|
method('ShowSoulShop', `self:RenderSoulLabel()
|
||||||
self:RenderSoulShop()
|
self:RenderSoulShop()
|
||||||
self:BindSoulShopButtons()
|
self:BindSoulShopButtons()
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/SoulShopHud", true)`),
|
self:SetEntityEnabled("/ui/LobbyUIGroup/SoulShopHud", true)`),
|
||||||
method('CloseSoulShop', `self:SetEntityEnabled("/ui/DefaultGroup/SoulShopHud", false)`),
|
method('CloseSoulShop', `self:SetEntityEnabled("/ui/LobbyUIGroup/SoulShopHud", false)`),
|
||||||
method('ReqLoadSouls', `local ds = _DataStorageService:GetUserDataStorage(userId)
|
method('ReqLoadSouls', `local ds = _DataStorageService:GetUserDataStorage(userId)
|
||||||
local e1, pts = ds:GetAndWait("soulPoints")
|
local e1, pts = ds:GetAndWait("soulPoints")
|
||||||
local e2, unl = ds:GetAndWait("soulUnlocks")
|
local e2, unl = ds:GetAndWait("soulUnlocks")
|
||||||
@@ -63,7 +63,7 @@ self:RenderSoulLabel()
|
|||||||
self:RenderSoulShop()`, [{ Type: "number", DefaultValue: null, SyncDirection: 0, Attributes: [], Name: "slot" }]),
|
self:RenderSoulShop()`, [{ Type: "number", DefaultValue: null, SyncDirection: 0, Attributes: [], Name: "slot" }]),
|
||||||
method('RenderSoulShop', `local defs = self.SoulShopDef or {}
|
method('RenderSoulShop', `local defs = self.SoulShopDef or {}
|
||||||
for i = 1, 4 do
|
for i = 1, 4 do
|
||||||
local base = "/ui/DefaultGroup/SoulShopHud/Item" .. tostring(i)
|
local base = "/ui/LobbyUIGroup/SoulShopHud/Item" .. tostring(i)
|
||||||
local d = defs[i]
|
local d = defs[i]
|
||||||
if d == nil then
|
if d == nil then
|
||||||
self:SetEntityEnabled(base, false)
|
self:SetEntityEnabled(base, false)
|
||||||
@@ -87,8 +87,8 @@ end
|
|||||||
self.SoulShopBound = true
|
self.SoulShopBound = true
|
||||||
for i = 1, 4 do
|
for i = 1, 4 do
|
||||||
local idx = i
|
local idx = i
|
||||||
local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/SoulShopHud/Item" .. tostring(i))
|
local e = _EntityService:GetEntityByPath("/ui/LobbyUIGroup/SoulShopHud/Item" .. tostring(i))
|
||||||
if e ~= nil and e.ButtonComponent ~= nil then
|
if e ~= nil and (e.ButtonComponent ~= nil or e:AddComponent("ButtonComponent") ~= nil) then
|
||||||
e:ConnectEvent(ButtonClickEvent, function() self:BuySoulUnlock(idx) end)
|
e:ConnectEvent(ButtonClickEvent, function() self:BuySoulUnlock(idx) end)
|
||||||
end
|
end
|
||||||
end`),
|
end`),
|
||||||
|
|||||||
@@ -6,37 +6,45 @@ export const stateMethods = [
|
|||||||
method('HideGameHud', `self:SetEntityEnabled("/ui/DefaultGroup/Button_Attack", false)
|
method('HideGameHud', `self:SetEntityEnabled("/ui/DefaultGroup/Button_Attack", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/Button_Jump", false)
|
self:SetEntityEnabled("/ui/DefaultGroup/Button_Jump", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/UIJoystick", false)
|
self:SetEntityEnabled("/ui/DefaultGroup/UIJoystick", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/DeckHud", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/DeckHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CardHand", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/CardHand", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/RewardHud", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/RewardHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/MapHud", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/MapHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/ShopHud", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/ShopHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/RestHud", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/RestHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/TreasureHud", false)
|
self:SetEntityEnabled("/ui/RunUIGroup/TreasureHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/JobChoiceHud", false)
|
self:SetEntityEnabled("/ui/SelectUIGroup/JobChoiceHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/JobSelectHud", false)
|
self:SetEntityEnabled("/ui/SelectUIGroup/JobSelectHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/DeckInspectHud", false)
|
self:SetEntityEnabled("/ui/DeckUIGroup/DeckInspectHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/DeckAllHud", false)
|
self:SetEntityEnabled("/ui/DeckUIGroup/DeckAllHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/LobbyHud", false)
|
self:SetEntityEnabled("/ui/LobbyUIGroup/LobbyHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/BoardHud", false)
|
self:SetEntityEnabled("/ui/LobbyUIGroup/BoardHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/SoulShopHud", false)`),
|
self:SetEntityEnabled("/ui/LobbyUIGroup/SoulShopHud", false)`),
|
||||||
|
method('ActivateUIGroups', `local function grp(n)
|
||||||
|
local g = _EntityService:GetEntityByPath("/ui/" .. n)
|
||||||
|
if g ~= nil then g:SetEnable(true) end
|
||||||
|
end
|
||||||
|
grp("SelectUIGroup")
|
||||||
|
grp("LobbyUIGroup")
|
||||||
|
grp("RunUIGroup")
|
||||||
|
grp("DeckUIGroup")`, [], 2),
|
||||||
method('ShowState', `self:HideGameHud()
|
method('ShowState', `self:HideGameHud()
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/MainMenu", state == "menu")
|
self:SetEntityEnabled("/ui/DefaultGroup/MainMenu", state == "menu")
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CharacterSelectHud", state == "charselect")
|
self:SetEntityEnabled("/ui/SelectUIGroup/CharacterSelectHud", state == "charselect")
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/LobbyHud", state == "lobby")
|
self:SetEntityEnabled("/ui/LobbyUIGroup/LobbyHud", state == "lobby")
|
||||||
if state == "map" then
|
if state == "map" then
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/MapHud", true)
|
self:SetEntityEnabled("/ui/RunUIGroup/MapHud", true)
|
||||||
elseif state == "combat" then
|
elseif state == "combat" then
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud", true)
|
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud", true)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/DeckHud", true)
|
self:SetEntityEnabled("/ui/RunUIGroup/DeckHud", true)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/CardHand", true)
|
self:SetEntityEnabled("/ui/RunUIGroup/CardHand", true)
|
||||||
elseif state == "shop" then
|
elseif state == "shop" then
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/ShopHud", true)
|
self:SetEntityEnabled("/ui/RunUIGroup/ShopHud", true)
|
||||||
elseif state == "rest" then
|
elseif state == "rest" then
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/RestHud", true)
|
self:SetEntityEnabled("/ui/RunUIGroup/RestHud", true)
|
||||||
elseif state == "treasure" then
|
elseif state == "treasure" then
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/TreasureHud", true)
|
self:SetEntityEnabled("/ui/RunUIGroup/TreasureHud", true)
|
||||||
end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'state' }]),
|
end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'state' }]),
|
||||||
method('ShowMainMenu', `self.SelectedClass = ""
|
method('ShowMainMenu', `self.SelectedClass = ""
|
||||||
self:RenderAscension()
|
self:RenderAscension()
|
||||||
@@ -46,39 +54,39 @@ self:SetText("/ui/DefaultGroup/MainMenu/Subtitle", "캐릭터를 고르고 덱
|
|||||||
self:SetText("/ui/DefaultGroup/MainMenu/NewGameButton", "새 게임")
|
self:SetText("/ui/DefaultGroup/MainMenu/NewGameButton", "새 게임")
|
||||||
self:BindMenuButtons()`),
|
self:BindMenuButtons()`),
|
||||||
method('BindMenuButtons', `local buttonEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/MainMenu/NewGameButton")
|
method('BindMenuButtons', `local buttonEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/MainMenu/NewGameButton")
|
||||||
if buttonEntity ~= nil and buttonEntity.ButtonComponent ~= nil then
|
if buttonEntity ~= nil and (buttonEntity.ButtonComponent ~= nil or buttonEntity:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.NewGameHandler ~= nil then
|
if self.NewGameHandler ~= nil then
|
||||||
buttonEntity:DisconnectEvent(ButtonClickEvent, self.NewGameHandler)
|
buttonEntity:DisconnectEvent(ButtonClickEvent, self.NewGameHandler)
|
||||||
self.NewGameHandler = nil
|
self.NewGameHandler = nil
|
||||||
end
|
end
|
||||||
self.NewGameHandler = buttonEntity:ConnectEvent(ButtonClickEvent, function() self:ShowCharacterSelect() end)
|
self.NewGameHandler = buttonEntity:ConnectEvent(ButtonClickEvent, function() self:ShowLobby() end)
|
||||||
end
|
end
|
||||||
local warrior = _EntityService:GetEntityByPath("/ui/DefaultGroup/CharacterSelectHud/WarriorButton")
|
local warrior = _EntityService:GetEntityByPath("/ui/SelectUIGroup/CharacterSelectHud/WarriorButton")
|
||||||
if warrior ~= nil and warrior.ButtonComponent ~= nil then
|
if warrior ~= nil and (warrior.ButtonComponent ~= nil or warrior:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.WarriorSelectHandler ~= nil then
|
if self.WarriorSelectHandler ~= nil then
|
||||||
warrior:DisconnectEvent(ButtonClickEvent, self.WarriorSelectHandler)
|
warrior:DisconnectEvent(ButtonClickEvent, self.WarriorSelectHandler)
|
||||||
self.WarriorSelectHandler = nil
|
self.WarriorSelectHandler = nil
|
||||||
end
|
end
|
||||||
self.WarriorSelectHandler = warrior:ConnectEvent(ButtonClickEvent, function() self:SelectClass("warrior") end)
|
self.WarriorSelectHandler = warrior:ConnectEvent(ButtonClickEvent, function() self:SelectClass("warrior") end)
|
||||||
end
|
end
|
||||||
local thief = _EntityService:GetEntityByPath("/ui/DefaultGroup/CharacterSelectHud/ThiefButton")
|
local thief = _EntityService:GetEntityByPath("/ui/SelectUIGroup/CharacterSelectHud/ThiefButton")
|
||||||
if thief ~= nil and thief.ButtonComponent ~= nil then
|
if thief ~= nil and (thief.ButtonComponent ~= nil or thief:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.ThiefSelectHandler ~= nil then
|
if self.ThiefSelectHandler ~= nil then
|
||||||
thief:DisconnectEvent(ButtonClickEvent, self.ThiefSelectHandler)
|
thief:DisconnectEvent(ButtonClickEvent, self.ThiefSelectHandler)
|
||||||
self.ThiefSelectHandler = nil
|
self.ThiefSelectHandler = nil
|
||||||
end
|
end
|
||||||
self.ThiefSelectHandler = thief:ConnectEvent(ButtonClickEvent, function() self:SelectClass("bandit") end)
|
self.ThiefSelectHandler = thief:ConnectEvent(ButtonClickEvent, function() self:SelectClass("bandit") end)
|
||||||
end
|
end
|
||||||
local mage = _EntityService:GetEntityByPath("/ui/DefaultGroup/CharacterSelectHud/MageButton")
|
local mage = _EntityService:GetEntityByPath("/ui/SelectUIGroup/CharacterSelectHud/MageButton")
|
||||||
if mage ~= nil and mage.ButtonComponent ~= nil then
|
if mage ~= nil and (mage.ButtonComponent ~= nil or mage:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.MageSelectHandler ~= nil then
|
if self.MageSelectHandler ~= nil then
|
||||||
mage:DisconnectEvent(ButtonClickEvent, self.MageSelectHandler)
|
mage:DisconnectEvent(ButtonClickEvent, self.MageSelectHandler)
|
||||||
self.MageSelectHandler = nil
|
self.MageSelectHandler = nil
|
||||||
end
|
end
|
||||||
self.MageSelectHandler = mage:ConnectEvent(ButtonClickEvent, function() self:SelectClass("magician") end)
|
self.MageSelectHandler = mage:ConnectEvent(ButtonClickEvent, function() self:SelectClass("magician") end)
|
||||||
end
|
end
|
||||||
local allDeckClose = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckAllHud/Close")
|
local allDeckClose = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Close")
|
||||||
if allDeckClose ~= nil and allDeckClose.ButtonComponent ~= nil then
|
if allDeckClose ~= nil and (allDeckClose.ButtonComponent ~= nil or allDeckClose:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.AllDeckCloseHandler ~= nil then
|
if self.AllDeckCloseHandler ~= nil then
|
||||||
allDeckClose:DisconnectEvent(ButtonClickEvent, self.AllDeckCloseHandler)
|
allDeckClose:DisconnectEvent(ButtonClickEvent, self.AllDeckCloseHandler)
|
||||||
self.AllDeckCloseHandler = nil
|
self.AllDeckCloseHandler = nil
|
||||||
@@ -86,16 +94,16 @@ if allDeckClose ~= nil and allDeckClose.ButtonComponent ~= nil then
|
|||||||
self.AllDeckCloseHandler = allDeckClose:ConnectEvent(ButtonClickEvent, function() self:CloseAllDeck() end)
|
self.AllDeckCloseHandler = allDeckClose:ConnectEvent(ButtonClickEvent, function() self:CloseAllDeck() end)
|
||||||
end
|
end
|
||||||
self:BindClassDeckTabs()
|
self:BindClassDeckTabs()
|
||||||
local start = _EntityService:GetEntityByPath("/ui/DefaultGroup/CharacterSelectHud/StartButton")
|
local start = _EntityService:GetEntityByPath("/ui/SelectUIGroup/CharacterSelectHud/StartButton")
|
||||||
if start ~= nil and start.ButtonComponent ~= nil then
|
if start ~= nil and (start.ButtonComponent ~= nil or start:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.StartGameHandler ~= nil then
|
if self.StartGameHandler ~= nil then
|
||||||
start:DisconnectEvent(ButtonClickEvent, self.StartGameHandler)
|
start:DisconnectEvent(ButtonClickEvent, self.StartGameHandler)
|
||||||
self.StartGameHandler = nil
|
self.StartGameHandler = nil
|
||||||
end
|
end
|
||||||
self.StartGameHandler = start:ConnectEvent(ButtonClickEvent, function() self:StartNewGame() end)
|
self.StartGameHandler = start:ConnectEvent(ButtonClickEvent, function() self:StartNewGame() end)
|
||||||
end
|
end
|
||||||
local charBack = _EntityService:GetEntityByPath("/ui/DefaultGroup/CharacterSelectHud/BackButton")
|
local charBack = _EntityService:GetEntityByPath("/ui/SelectUIGroup/CharacterSelectHud/BackButton")
|
||||||
if charBack ~= nil and charBack.ButtonComponent ~= nil then
|
if charBack ~= nil and (charBack.ButtonComponent ~= nil or charBack:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.CharBackHandler ~= nil then
|
if self.CharBackHandler ~= nil then
|
||||||
charBack:DisconnectEvent(ButtonClickEvent, self.CharBackHandler)
|
charBack:DisconnectEvent(ButtonClickEvent, self.CharBackHandler)
|
||||||
self.CharBackHandler = nil
|
self.CharBackHandler = nil
|
||||||
@@ -103,7 +111,7 @@ if charBack ~= nil and charBack.ButtonComponent ~= nil then
|
|||||||
self.CharBackHandler = charBack:ConnectEvent(ButtonClickEvent, function() self:ShowLobby() end)
|
self.CharBackHandler = charBack:ConnectEvent(ButtonClickEvent, function() self:ShowLobby() end)
|
||||||
end
|
end
|
||||||
local ascMinus = _EntityService:GetEntityByPath("/ui/DefaultGroup/MainMenu/AscMinus")
|
local ascMinus = _EntityService:GetEntityByPath("/ui/DefaultGroup/MainMenu/AscMinus")
|
||||||
if ascMinus ~= nil and ascMinus.ButtonComponent ~= nil then
|
if ascMinus ~= nil and (ascMinus.ButtonComponent ~= nil or ascMinus:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.AscMinusHandler ~= nil then
|
if self.AscMinusHandler ~= nil then
|
||||||
ascMinus:DisconnectEvent(ButtonClickEvent, self.AscMinusHandler)
|
ascMinus:DisconnectEvent(ButtonClickEvent, self.AscMinusHandler)
|
||||||
self.AscMinusHandler = nil
|
self.AscMinusHandler = nil
|
||||||
@@ -111,7 +119,7 @@ if ascMinus ~= nil and ascMinus.ButtonComponent ~= nil then
|
|||||||
self.AscMinusHandler = ascMinus:ConnectEvent(ButtonClickEvent, function() self:AdjustAscension(-1) end)
|
self.AscMinusHandler = ascMinus:ConnectEvent(ButtonClickEvent, function() self:AdjustAscension(-1) end)
|
||||||
end
|
end
|
||||||
local ascPlus = _EntityService:GetEntityByPath("/ui/DefaultGroup/MainMenu/AscPlus")
|
local ascPlus = _EntityService:GetEntityByPath("/ui/DefaultGroup/MainMenu/AscPlus")
|
||||||
if ascPlus ~= nil and ascPlus.ButtonComponent ~= nil then
|
if ascPlus ~= nil and (ascPlus.ButtonComponent ~= nil or ascPlus:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.AscPlusHandler ~= nil then
|
if self.AscPlusHandler ~= nil then
|
||||||
ascPlus:DisconnectEvent(ButtonClickEvent, self.AscPlusHandler)
|
ascPlus:DisconnectEvent(ButtonClickEvent, self.AscPlusHandler)
|
||||||
self.AscPlusHandler = nil
|
self.AscPlusHandler = nil
|
||||||
@@ -122,8 +130,8 @@ end`),
|
|||||||
self:RenderAscension()
|
self:RenderAscension()
|
||||||
self:RenderSoulLabel()
|
self:RenderSoulLabel()
|
||||||
self:ShowState("lobby")
|
self:ShowState("lobby")
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/BoardHud", false)
|
self:SetEntityEnabled("/ui/LobbyUIGroup/BoardHud", false)
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/SoulShopHud", false)
|
self:SetEntityEnabled("/ui/LobbyUIGroup/SoulShopHud", false)
|
||||||
self:BindLobbyButtons()
|
self:BindLobbyButtons()
|
||||||
self:BindMenuButtons()
|
self:BindMenuButtons()
|
||||||
self:GoLobbyMap()`),
|
self:GoLobbyMap()`),
|
||||||
@@ -155,39 +163,39 @@ elseif id == "board" then
|
|||||||
self:ShowBoard()
|
self:ShowBoard()
|
||||||
end`, [{ Type: 'string', DefaultValue: '""', SyncDirection: 0, Attributes: [], Name: 'id' }]),
|
end`, [{ Type: 'string', DefaultValue: '""', SyncDirection: 0, Attributes: [], Name: 'id' }]),
|
||||||
method('RenderSoulLabel', `local s = self.SoulPoints or 0
|
method('RenderSoulLabel', `local s = self.SoulPoints or 0
|
||||||
self:SetText("/ui/DefaultGroup/LobbyHud/SoulLabel", "영혼 " .. string.format("%d", s))
|
self:SetText("/ui/LobbyUIGroup/LobbyHud/SoulLabel", "영혼 " .. string.format("%d", s))
|
||||||
self:SetText("/ui/DefaultGroup/SoulShopHud/Souls", "영혼 " .. string.format("%d", s))`),
|
self:SetText("/ui/LobbyUIGroup/SoulShopHud/Souls", "영혼 " .. string.format("%d", s))`),
|
||||||
method('BindLobbyButtons', `if self.LobbyBound == true then
|
method('BindLobbyButtons', `if self.LobbyBound == true then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
self.LobbyBound = true
|
self.LobbyBound = true
|
||||||
local function bindClick(path, fn)
|
local function bindClick(path, fn)
|
||||||
local e = _EntityService:GetEntityByPath(path)
|
local e = _EntityService:GetEntityByPath(path)
|
||||||
if e ~= nil and e.ButtonComponent ~= nil then
|
if e ~= nil and (e.ButtonComponent ~= nil or e:AddComponent("ButtonComponent") ~= nil) then
|
||||||
e:ConnectEvent(ButtonClickEvent, fn)
|
e:ConnectEvent(ButtonClickEvent, fn)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
bindClick("/ui/DefaultGroup/LobbyHud/AscMinus", function() self:AdjustAscension(-1) end)
|
bindClick("/ui/LobbyUIGroup/LobbyHud/AscMinus", function() self:AdjustAscension(-1) end)
|
||||||
bindClick("/ui/DefaultGroup/LobbyHud/AscPlus", function() self:AdjustAscension(1) end)
|
bindClick("/ui/LobbyUIGroup/LobbyHud/AscPlus", function() self:AdjustAscension(1) end)
|
||||||
bindClick("/ui/DefaultGroup/BoardHud/Close", function() self:CloseBoard() end)
|
bindClick("/ui/LobbyUIGroup/BoardHud/Close", function() self:CloseBoard() end)
|
||||||
bindClick("/ui/DefaultGroup/SoulShopHud/Close", function() self:CloseSoulShop() end)`),
|
bindClick("/ui/LobbyUIGroup/SoulShopHud/Close", function() self:CloseSoulShop() end)`),
|
||||||
method('ShowCodex', `self.CodexMode = true
|
method('ShowCodex', `self.CodexMode = true
|
||||||
self.ClassDeckMode = true
|
self.ClassDeckMode = true
|
||||||
local close = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckAllHud/Close")
|
local close = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Close")
|
||||||
if close ~= nil and close.ButtonComponent ~= nil then
|
if close ~= nil and (close.ButtonComponent ~= nil or close:AddComponent("ButtonComponent") ~= nil) then
|
||||||
if self.AllDeckCloseHandler ~= nil then
|
if self.AllDeckCloseHandler ~= nil then
|
||||||
close:DisconnectEvent(ButtonClickEvent, self.AllDeckCloseHandler)
|
close:DisconnectEvent(ButtonClickEvent, self.AllDeckCloseHandler)
|
||||||
end
|
end
|
||||||
self.AllDeckCloseHandler = close:ConnectEvent(ButtonClickEvent, function() self:CloseAllDeck() end)
|
self.AllDeckCloseHandler = close:ConnectEvent(ButtonClickEvent, function() self:CloseAllDeck() end)
|
||||||
end
|
end
|
||||||
self:BindClassDeckTabs()
|
self:BindClassDeckTabs()
|
||||||
self:SetEntityEnabled("/ui/DefaultGroup/LobbyHud", false)
|
self:SetEntityEnabled("/ui/LobbyUIGroup/LobbyHud", false)
|
||||||
self:SetClassDeckTab("warrior")
|
self:SetClassDeckTab("warrior")
|
||||||
local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckAllHud")
|
local hud = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud")
|
||||||
if hud ~= nil then
|
if hud ~= nil then
|
||||||
hud.Enable = true
|
hud.Enable = true
|
||||||
end
|
end
|
||||||
self:RenderAllDeck()`),
|
self:RenderAllDeck()`),
|
||||||
method('ShowBoard', `self:SetEntityEnabled("/ui/DefaultGroup/BoardHud", true)`),
|
method('ShowBoard', `self:SetEntityEnabled("/ui/LobbyUIGroup/BoardHud", true)`),
|
||||||
method('CloseBoard', `self:SetEntityEnabled("/ui/DefaultGroup/BoardHud", false)`),
|
method('CloseBoard', `self:SetEntityEnabled("/ui/LobbyUIGroup/BoardHud", false)`),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ local cardId = self.Hand[slot]
|
|||||||
if cardId == nil then
|
if cardId == nil then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(slot))
|
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||||
local tx = 0
|
local tx = 0
|
||||||
if e ~= nil and e.UITransformComponent ~= nil then
|
if e ~= nil and e.UITransformComponent ~= nil then
|
||||||
tx = e.UITransformComponent.anchoredPosition.x
|
tx = e.UITransformComponent.anchoredPosition.x
|
||||||
@@ -87,7 +87,7 @@ if c ~= nil then
|
|||||||
self:HideTooltip()
|
self:HideTooltip()
|
||||||
end
|
end
|
||||||
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||||
method('UnhoverCard', `local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(slot))
|
method('UnhoverCard', `local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||||
if e ~= nil and e.UITransformComponent ~= nil then
|
if e ~= nil and e.UITransformComponent ~= nil then
|
||||||
e.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
e.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
||||||
end
|
end
|
||||||
@@ -97,9 +97,9 @@ self:HideTooltip()`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, At
|
|||||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'desc' },
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'desc' },
|
||||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'x' },
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'x' },
|
||||||
]),
|
]),
|
||||||
method('ShowTooltipAt', `self:SetText("/ui/DefaultGroup/CombatHud/TooltipBox/Name", name)
|
method('ShowTooltipAt', `self:SetText("/ui/RunUIGroup/CombatHud/TooltipBox/Name", name)
|
||||||
self:SetText("/ui/DefaultGroup/CombatHud/TooltipBox/Desc", desc)
|
self:SetText("/ui/RunUIGroup/CombatHud/TooltipBox/Desc", desc)
|
||||||
local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/TooltipBox")
|
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/TooltipBox")
|
||||||
if e ~= nil then
|
if e ~= nil then
|
||||||
if e.UITransformComponent ~= nil then
|
if e.UITransformComponent ~= nil then
|
||||||
e.UITransformComponent.anchoredPosition = Vector2(x, y)
|
e.UITransformComponent.anchoredPosition = Vector2(x, y)
|
||||||
@@ -111,5 +111,5 @@ end`, [
|
|||||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'x' },
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'x' },
|
||||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'y' },
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'y' },
|
||||||
]),
|
]),
|
||||||
method('HideTooltip', `self:SetEntityEnabled("/ui/DefaultGroup/CombatHud/TooltipBox", false)`),
|
method('HideTooltip', `self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/TooltipBox", false)`),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { readFileSync, writeFileSync } from 'node:fs';
|
import { readFileSync, writeFileSync } from 'node:fs';
|
||||||
|
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from './lib/data.mjs';
|
import { POTIONS } from './lib/data.mjs';
|
||||||
import { prop, method, codeblock, RUN_LENGTH, GOLD_PER_WIN, CARD_PRICE, REST_HEAL, RELIC_PRICE, ACT_COUNT, ACT_MAPS, LOBBY_MAP, LOBBY_SPAWN } from './lib/codeblock.mjs';
|
import { prop, codeblock, RUN_LENGTH } from './lib/codeblock.mjs';
|
||||||
import { bootMethods } from './cb/boot.mjs';
|
import { bootMethods } from './cb/boot.mjs';
|
||||||
import { stateMethods } from './cb/state.mjs';
|
import { stateMethods } from './cb/state.mjs';
|
||||||
import { soulMethods } from './cb/soul.mjs';
|
import { soulMethods } from './cb/soul.mjs';
|
||||||
@@ -19,241 +19,7 @@ import { itemMethods } from './cb/items.mjs';
|
|||||||
import { tooltipMethods } from './cb/tooltip.mjs';
|
import { tooltipMethods } from './cb/tooltip.mjs';
|
||||||
import { mapMethods } from './cb/map.mjs';
|
import { mapMethods } from './cb/map.mjs';
|
||||||
import { shopMethods } from './cb/shop.mjs';
|
import { shopMethods } from './cb/shop.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';
|
import { COMMON_FILE } from './lib/ui-helpers.mjs';
|
||||||
import { buildDeckHud } from './hud/deckhud.mjs';
|
|
||||||
import { buildDeckInspect } from './hud/deckinspect.mjs';
|
|
||||||
import { buildDeckAll } from './hud/deckall.mjs';
|
|
||||||
import { buildCombat } from './hud/combat.mjs';
|
|
||||||
import { buildReward } from './hud/reward.mjs';
|
|
||||||
import { buildMap } from './hud/map.mjs';
|
|
||||||
import { buildShop } from './hud/shop.mjs';
|
|
||||||
import { buildRest } from './hud/rest.mjs';
|
|
||||||
import { buildTreasure } from './hud/treasure.mjs';
|
|
||||||
import { buildJobChoice } from './hud/jobchoice.mjs';
|
|
||||||
import { buildJobSelect } from './hud/jobselect.mjs';
|
|
||||||
import { buildLobby } from './hud/lobby.mjs';
|
|
||||||
import { buildBoard } from './hud/board.mjs';
|
|
||||||
import { buildSoulShop } from './hud/soulshop.mjs';
|
|
||||||
import { buildMainMenu } from './hud/mainmenu.mjs';
|
|
||||||
|
|
||||||
function upsertUi() {
|
|
||||||
const ui = JSON.parse(readFileSync(UI_FILE, 'utf8'));
|
|
||||||
const E = ui.ContentProto.Entities;
|
|
||||||
// CardHand는 스톡 섹션이라 과거 생성된 단색판(NamePlate/CostPlate)이 잔존 → 프레임 이미지 도입으로 제거
|
|
||||||
const obsoletePlate = /^\/ui\/DefaultGroup\/CardHand\/Card\d+\/(NamePlate|CostPlate)$/;
|
|
||||||
ui.ContentProto.Entities = E.filter((e) => !isGeneratedUiEntity(e) && !obsoletePlate.test(e.path));
|
|
||||||
|
|
||||||
const byPath = new Map(ui.ContentProto.Entities.map((e) => [e.path, e]));
|
|
||||||
const uiSections = new Map();
|
|
||||||
const emit = (section, entities) => {
|
|
||||||
if (uiSections.has(section)) {
|
|
||||||
throw new Error(`[gen-slaydeck] duplicate generated UI section: ${section}`);
|
|
||||||
}
|
|
||||||
uiSections.set(section, entities);
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const path of DISABLED_STOCK_CONTROLS.map((name) => uiPath(name))) {
|
|
||||||
const e = byPath.get(path);
|
|
||||||
if (e != null) {
|
|
||||||
e.jsonString.enable = false;
|
|
||||||
e.jsonString.visible = false;
|
|
||||||
for (const component of e.jsonString['@components'] || []) {
|
|
||||||
component.Enable = false;
|
|
||||||
if (component.RaycastTarget != null) component.RaycastTarget = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 카드 미리보기(초기 정적 표시 — 런타임 RenderHand가 덮어씀): 카드 종류를 순환해 다양성 표시
|
|
||||||
const previewIds = Object.keys(CARDS.cards);
|
|
||||||
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) };
|
|
||||||
});
|
|
||||||
|
|
||||||
// 손패 슬롯 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: 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;
|
|
||||||
sp.RaycastTarget = true;
|
|
||||||
const comps = card.jsonString['@components'];
|
|
||||||
if (!comps.some((c) => c['@type'] === 'MOD.Core.ButtonComponent')) {
|
|
||||||
comps.push(button());
|
|
||||||
}
|
|
||||||
if (!card.componentNames.includes('MOD.Core.ButtonComponent')) {
|
|
||||||
card.componentNames += ',MOD.Core.ButtonComponent';
|
|
||||||
}
|
|
||||||
if (!comps.some((c) => c['@type'] === 'MOD.Core.UITouchReceiveComponent')) {
|
|
||||||
comps.push({ '@type': 'MOD.Core.UITouchReceiveComponent', Enable: true });
|
|
||||||
}
|
|
||||||
if (!card.componentNames.includes('MOD.Core.UITouchReceiveComponent')) {
|
|
||||||
card.componentNames += ',MOD.Core.UITouchReceiveComponent';
|
|
||||||
}
|
|
||||||
card.jsonString.enable = true;
|
|
||||||
card.jsonString.visible = true;
|
|
||||||
|
|
||||||
const handLayout = cardFaceLayout(CARD_W);
|
|
||||||
const previewValues = { Cost: cards[i - 1].cost, Name: cards[i - 1].name, Desc: cards[i - 1].desc };
|
|
||||||
const children = handLayout.texts.map(([suffix, cfg]) => [suffix, { ...cfg, value: previewValues[suffix] }]);
|
|
||||||
for (const [suffix, cfg] of children) {
|
|
||||||
const path = `/ui/DefaultGroup/CardHand/Card${i}/${suffix}`;
|
|
||||||
const dOrder = suffix === 'Cost' ? 7 : suffix === 'Name' ? 6 : 8;
|
|
||||||
let child = byPath.get(path);
|
|
||||||
if (!child) {
|
|
||||||
child = entity({
|
|
||||||
id: guid('dck', i * 10 + children.findIndex(([s]) => s === suffix)),
|
|
||||||
path,
|
|
||||||
modelId: 'uitext',
|
|
||||||
entryId: 'UIText',
|
|
||||||
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent',
|
|
||||||
displayOrder: dOrder,
|
|
||||||
components: [
|
|
||||||
transform({ parentW: CARD_W, parentH: CARD_H, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: cfg.size, pos: cfg.pos }),
|
|
||||||
sprite({ color: TRANSPARENT }),
|
|
||||||
text({ value: cfg.value, fontSize: cfg.fontSize, bold: cfg.bold, color: cfg.color, dropShadow: cfg.dropShadow, outlineWidth: cfg.outlineWidth }),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
ui.ContentProto.Entities.push(child);
|
|
||||||
byPath.set(path, child);
|
|
||||||
} else {
|
|
||||||
child.id = guid('dck', i * 10 + children.findIndex(([s]) => s === suffix));
|
|
||||||
child.jsonString.enable = true;
|
|
||||||
child.jsonString.visible = true;
|
|
||||||
child.jsonString.displayOrder = dOrder;
|
|
||||||
const ctr = child.jsonString['@components'].find((c) => c['@type'] === 'MOD.Core.UITransformComponent');
|
|
||||||
if (ctr) {
|
|
||||||
const pivot = { x: 0.5, y: 0.5 };
|
|
||||||
ctr.RectSize = cfg.size;
|
|
||||||
ctr.anchoredPosition = cfg.pos;
|
|
||||||
ctr.OffsetMin = { x: cfg.pos.x - pivot.x * cfg.size.x, y: cfg.pos.y - pivot.y * cfg.size.y };
|
|
||||||
ctr.OffsetMax = { x: cfg.pos.x + (1 - pivot.x) * cfg.size.x, y: cfg.pos.y + (1 - pivot.y) * cfg.size.y };
|
|
||||||
}
|
|
||||||
child.jsonString['@components'][2].Text = cfg.value;
|
|
||||||
child.jsonString['@components'][2].FontSize = cfg.fontSize;
|
|
||||||
child.jsonString['@components'][2].MaxSize = cfg.fontSize;
|
|
||||||
child.jsonString['@components'][2].FontColor = cfg.color;
|
|
||||||
child.jsonString['@components'][2].Bold = cfg.bold;
|
|
||||||
child.jsonString['@components'][2].DropShadow = cfg.dropShadow === true;
|
|
||||||
child.jsonString['@components'][2].DropShadowDistance = cfg.dropShadow === true ? 18 : 32;
|
|
||||||
child.jsonString['@components'][2].OutlineWidth = cfg.outlineWidth || 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 프레임 이미지가 이름판·코스트판을 내장하므로 Art만 유지 (잔존 NamePlate/CostPlate는 upsertUi 초입에서 제거)
|
|
||||||
const frameKids = [
|
|
||||||
['Art', 5, handLayout.art, WHITE, 0],
|
|
||||||
];
|
|
||||||
for (const [suffix, dOrder, cfg, color, spriteType] of frameKids) {
|
|
||||||
const fPath = `/ui/DefaultGroup/CardHand/Card${i}/${suffix}`;
|
|
||||||
let fe = byPath.get(fPath);
|
|
||||||
if (!fe) {
|
|
||||||
fe = entity({
|
|
||||||
id: guid('dck', 200 + i * 10 + dOrder),
|
|
||||||
path: fPath,
|
|
||||||
modelId: 'uisprite',
|
|
||||||
entryId: 'UISprite',
|
|
||||||
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
|
|
||||||
displayOrder: dOrder,
|
|
||||||
components: [
|
|
||||||
transform({ parentW: CARD_W, parentH: CARD_H, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: cfg.size, pos: cfg.pos }),
|
|
||||||
sprite({ color, type: spriteType, raycast: false }),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
ui.ContentProto.Entities.push(fe);
|
|
||||||
byPath.set(fPath, fe);
|
|
||||||
} else {
|
|
||||||
const ftr = fe.jsonString['@components'].find((c) => c['@type'] === 'MOD.Core.UITransformComponent');
|
|
||||||
if (ftr) {
|
|
||||||
ftr.RectSize = cfg.size;
|
|
||||||
ftr.anchoredPosition = cfg.pos;
|
|
||||||
ftr.OffsetMin = { x: cfg.pos.x - cfg.size.x / 2, y: cfg.pos.y - cfg.size.y / 2 };
|
|
||||||
ftr.OffsetMax = { x: cfg.pos.x + cfg.size.x / 2, y: cfg.pos.y + cfg.size.y / 2 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit('DeckHud', buildDeckHud());
|
|
||||||
|
|
||||||
emit('DeckInspectHud', buildDeckInspect());
|
|
||||||
|
|
||||||
emit('DeckAllHud', buildDeckAll());
|
|
||||||
|
|
||||||
emit('CombatHud', buildCombat());
|
|
||||||
|
|
||||||
emit('RewardHud', buildReward());
|
|
||||||
|
|
||||||
emit('MapHud', buildMap());
|
|
||||||
|
|
||||||
emit('ShopHud', buildShop());
|
|
||||||
|
|
||||||
emit('RestHud', buildRest());
|
|
||||||
|
|
||||||
// 유물 방 — 보물 상자 (P8)
|
|
||||||
emit('TreasureHud', buildTreasure());
|
|
||||||
|
|
||||||
// 전직 선택 (P9) — 보스 보상: 유물 vs 2차 전직
|
|
||||||
emit('JobChoiceHud', buildJobChoice());
|
|
||||||
|
|
||||||
emit('JobSelectHud', buildJobSelect());
|
|
||||||
|
|
||||||
emit('MainMenu', buildMainMenu());
|
|
||||||
|
|
||||||
// ── LobbyHud — 반복 런의 허브. NPC 클릭으로 런시작/도감/영혼상점/게시판 ──
|
|
||||||
emit('LobbyHud', buildLobby());
|
|
||||||
|
|
||||||
// ── BoardHud — 게시판(공지/팁) ──
|
|
||||||
emit('BoardHud', buildBoard());
|
|
||||||
|
|
||||||
// ── SoulShopHud — 영혼 메타 상점 (Phase 9에서 해금 항목·구매 로직 채움) ──
|
|
||||||
emit('SoulShopHud', buildSoulShop());
|
|
||||||
|
|
||||||
for (const section of UI_APPEND_ORDER) {
|
|
||||||
const entities = uiSections.get(section);
|
|
||||||
if (entities == null) {
|
|
||||||
throw new Error(`[gen-slaydeck] missing generated UI section: ${section}`);
|
|
||||||
}
|
|
||||||
appendUiSection(ui, section, entities);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 엔티티 id 유일성 검증 — 같은 id가 다른 path에 재배정되면 메이커 refresh 병합이 꼬임
|
|
||||||
const seenIds = new Map();
|
|
||||||
for (const e of ui.ContentProto.Entities) {
|
|
||||||
const prev = seenIds.get(e.id);
|
|
||||||
if (prev != null) throw new Error(`[gen-slaydeck] 엔티티 id 중복: ${e.id} (${prev} ↔ ${e.path})`);
|
|
||||||
seenIds.set(e.id, e.path);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON.parse(JSON.stringify(ui));
|
|
||||||
writeFileSync(UI_FILE, JSON.stringify(ui, null, 2), 'utf8');
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeCodeblocks() {
|
function writeCodeblocks() {
|
||||||
const combat = codeblock('SlayDeckController', 'SlayDeckController', [
|
const combat = codeblock('SlayDeckController', 'SlayDeckController', [
|
||||||
@@ -296,6 +62,9 @@ function writeCodeblocks() {
|
|||||||
prop('boolean', 'CodexMode', 'false'),
|
prop('boolean', 'CodexMode', 'false'),
|
||||||
prop('any', 'CodexCards'),
|
prop('any', 'CodexCards'),
|
||||||
prop('boolean', 'ClassDeckMode', 'false'),
|
prop('boolean', 'ClassDeckMode', 'false'),
|
||||||
|
prop('boolean', 'DebugCardPickerMode', 'false'),
|
||||||
|
prop('boolean', 'DebugCtrlDown', 'false'),
|
||||||
|
prop('boolean', 'DebugShiftDown', 'false'),
|
||||||
prop('any', 'ClassDeckCards'),
|
prop('any', 'ClassDeckCards'),
|
||||||
prop('string', 'ClassDeckTitle', '""'),
|
prop('string', 'ClassDeckTitle', '""'),
|
||||||
prop('string', 'ClassDeckClass', '""'),
|
prop('string', 'ClassDeckClass', '""'),
|
||||||
@@ -361,6 +130,7 @@ function writeCodeblocks() {
|
|||||||
prop('number', 'DiscardSelectTotal', '0'),
|
prop('number', 'DiscardSelectTotal', '0'),
|
||||||
prop('number', 'DiscardPostShiv', '0'),
|
prop('number', 'DiscardPostShiv', '0'),
|
||||||
prop('number', 'DiscardShivPerPick', '0'),
|
prop('number', 'DiscardShivPerPick', '0'),
|
||||||
|
prop('boolean', 'RetainSelectActive', 'false'),
|
||||||
], [
|
], [
|
||||||
...bootMethods,
|
...bootMethods,
|
||||||
...stateMethods,
|
...stateMethods,
|
||||||
@@ -397,8 +167,7 @@ function patchCommon() {
|
|||||||
writeFileSync(COMMON_FILE, JSON.stringify(common, null, 2), 'utf8');
|
writeFileSync(COMMON_FILE, JSON.stringify(common, null, 2), 'utf8');
|
||||||
}
|
}
|
||||||
|
|
||||||
upsertUi();
|
|
||||||
writeCodeblocks();
|
writeCodeblocks();
|
||||||
patchCommon();
|
patchCommon();
|
||||||
|
|
||||||
console.log('Slay deck UI and combat codeblocks generated.');
|
console.log('SlayDeckController/common 생성 완료 (UI는 메이커 저작 — 생성기 미접근).');
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildBoard() {
|
export function buildBoard() {
|
||||||
const board = [];
|
const board = [];
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildCombat() {
|
export function buildCombat() {
|
||||||
const PANEL_BG = { r: 0.08, g: 0.09, b: 0.11, a: 0.78 };
|
const PANEL_BG = { r: 0.08, g: 0.09, b: 0.11, a: 0.78 };
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildDeckAll() {
|
export function buildDeckAll() {
|
||||||
const allDeck = [];
|
const allDeck = [];
|
||||||
@@ -116,11 +116,12 @@ export function buildDeckAll() {
|
|||||||
path: cardPath,
|
path: cardPath,
|
||||||
modelId: 'uisprite',
|
modelId: 'uisprite',
|
||||||
entryId: 'UISprite',
|
entryId: 'UISprite',
|
||||||
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
|
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent',
|
||||||
displayOrder: i,
|
displayOrder: i,
|
||||||
components: [
|
components: [
|
||||||
transform({ parentW: 980, parentH: 620, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: ALL_DECK_CARD_W, y: ALL_DECK_CARD_H }, pos: { x: 0, y: 0 } }),
|
transform({ parentW: 980, parentH: 620, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: ALL_DECK_CARD_W, y: ALL_DECK_CARD_H }, pos: { x: 0, y: 0 } }),
|
||||||
sprite({ dataId: CARDFRAMES.frames.warrior.normal, color: WHITE, type: 0 }),
|
sprite({ dataId: CARDFRAMES.frames.warrior.normal, color: WHITE, type: 0, raycast: true }),
|
||||||
|
button(),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
card.jsonString.enable = false;
|
card.jsonString.enable = false;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildDeckHud() {
|
export function buildDeckHud() {
|
||||||
const hud = [];
|
const hud = [];
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildDeckInspect() {
|
export function buildDeckInspect() {
|
||||||
const inspect = [];
|
const inspect = [];
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildJobChoice() {
|
export function buildJobChoice() {
|
||||||
const jobChoice = [];
|
const jobChoice = [];
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildJobSelect() {
|
export function buildJobSelect() {
|
||||||
const jobSelect = [];
|
const jobSelect = [];
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildLobby() {
|
export function buildLobby() {
|
||||||
const lobby = [];
|
const lobby = [];
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildMainMenu() {
|
export function buildMainMenu() {
|
||||||
const menu = [];
|
const menu = [];
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildMap() {
|
export function buildMap() {
|
||||||
const TYPE_KO = { combat: '전투', elite: '엘리트', boss: '보스', shop: '상점', rest: '휴식' };
|
const TYPE_KO = { combat: '전투', elite: '엘리트', boss: '보스', shop: '상점', rest: '휴식' };
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildRest() {
|
export function buildRest() {
|
||||||
const rest = [];
|
const rest = [];
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildReward() {
|
export function buildReward() {
|
||||||
const reward = [];
|
const reward = [];
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildShop() {
|
export function buildShop() {
|
||||||
const shop = [];
|
const shop = [];
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildSoulShop() {
|
export function buildSoulShop() {
|
||||||
const soulShop = [];
|
const soulShop = [];
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
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';
|
||||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, luaSoulShopTable, CARDFRAMES, RARITIES, frameRuid, luaFramesTable, luaNodeIconsTable, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, luaRelicsTable, POTIONS, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../../lib/data.mjs';
|
||||||
|
|
||||||
export function buildTreasure() {
|
export function buildTreasure() {
|
||||||
const treasure = [];
|
const treasure = [];
|
||||||
246
tools/deck/legacy/upsert-ui.mjs
Normal file
246
tools/deck/legacy/upsert-ui.mjs
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
import { readFileSync, writeFileSync } from 'node:fs';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import { CARDS, frameRuid } from '../lib/data.mjs';
|
||||||
|
import { UI_FILE, isGeneratedUiEntity, DISABLED_STOCK_CONTROLS, uiPath, guid, entity, transform, sprite, button, text, WHITE, TRANSPARENT, CARD_W, CARD_H, cardFaceLayout, UI_APPEND_ORDER, appendUiSection } from '../lib/ui-helpers.mjs';
|
||||||
|
import { buildDeckHud } from './hud/deckhud.mjs';
|
||||||
|
import { buildDeckInspect } from './hud/deckinspect.mjs';
|
||||||
|
import { buildDeckAll } from './hud/deckall.mjs';
|
||||||
|
import { buildCombat } from './hud/combat.mjs';
|
||||||
|
import { buildReward } from './hud/reward.mjs';
|
||||||
|
import { buildMap } from './hud/map.mjs';
|
||||||
|
import { buildShop } from './hud/shop.mjs';
|
||||||
|
import { buildRest } from './hud/rest.mjs';
|
||||||
|
import { buildTreasure } from './hud/treasure.mjs';
|
||||||
|
import { buildJobChoice } from './hud/jobchoice.mjs';
|
||||||
|
import { buildJobSelect } from './hud/jobselect.mjs';
|
||||||
|
import { buildLobby } from './hud/lobby.mjs';
|
||||||
|
import { buildBoard } from './hud/board.mjs';
|
||||||
|
import { buildSoulShop } from './hud/soulshop.mjs';
|
||||||
|
import { buildMainMenu } from './hud/mainmenu.mjs';
|
||||||
|
|
||||||
|
// ⚠️ 휴면(LEGACY): 메이커 저작 전환 후 생성기는 .ui를 안 만든다. 이 파일은 옛 DefaultGroup.ui
|
||||||
|
// 단일 저작 로직의 롤백/참조용. import는 무해(함수만 정의), 직접 실행할 때만 .ui를 옛 생성본으로 덮어쓴다.
|
||||||
|
|
||||||
|
function upsertUi() {
|
||||||
|
const ui = JSON.parse(readFileSync(UI_FILE, 'utf8'));
|
||||||
|
const E = ui.ContentProto.Entities;
|
||||||
|
// CardHand는 스톡 섹션이라 과거 생성된 단색판(NamePlate/CostPlate)이 잔존 → 프레임 이미지 도입으로 제거
|
||||||
|
const obsoletePlate = /^\/ui\/DefaultGroup\/CardHand\/Card\d+\/(NamePlate|CostPlate)$/;
|
||||||
|
ui.ContentProto.Entities = E.filter((e) => !isGeneratedUiEntity(e) && !obsoletePlate.test(e.path));
|
||||||
|
|
||||||
|
const byPath = new Map(ui.ContentProto.Entities.map((e) => [e.path, e]));
|
||||||
|
const uiSections = new Map();
|
||||||
|
const emit = (section, entities) => {
|
||||||
|
if (uiSections.has(section)) {
|
||||||
|
throw new Error(`[gen-slaydeck] duplicate generated UI section: ${section}`);
|
||||||
|
}
|
||||||
|
uiSections.set(section, entities);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const path of DISABLED_STOCK_CONTROLS.map((name) => uiPath(name))) {
|
||||||
|
const e = byPath.get(path);
|
||||||
|
if (e != null) {
|
||||||
|
e.jsonString.enable = false;
|
||||||
|
e.jsonString.visible = false;
|
||||||
|
for (const component of e.jsonString['@components'] || []) {
|
||||||
|
component.Enable = false;
|
||||||
|
if (component.RaycastTarget != null) component.RaycastTarget = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 카드 미리보기(초기 정적 표시 — 런타임 RenderHand가 덮어씀): 카드 종류를 순환해 다양성 표시
|
||||||
|
const previewIds = Object.keys(CARDS.cards);
|
||||||
|
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) };
|
||||||
|
});
|
||||||
|
|
||||||
|
// 손패 슬롯 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: 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;
|
||||||
|
sp.RaycastTarget = true;
|
||||||
|
const comps = card.jsonString['@components'];
|
||||||
|
if (!comps.some((c) => c['@type'] === 'MOD.Core.ButtonComponent')) {
|
||||||
|
comps.push(button());
|
||||||
|
}
|
||||||
|
if (!card.componentNames.includes('MOD.Core.ButtonComponent')) {
|
||||||
|
card.componentNames += ',MOD.Core.ButtonComponent';
|
||||||
|
}
|
||||||
|
if (!comps.some((c) => c['@type'] === 'MOD.Core.UITouchReceiveComponent')) {
|
||||||
|
comps.push({ '@type': 'MOD.Core.UITouchReceiveComponent', Enable: true });
|
||||||
|
}
|
||||||
|
if (!card.componentNames.includes('MOD.Core.UITouchReceiveComponent')) {
|
||||||
|
card.componentNames += ',MOD.Core.UITouchReceiveComponent';
|
||||||
|
}
|
||||||
|
card.jsonString.enable = true;
|
||||||
|
card.jsonString.visible = true;
|
||||||
|
|
||||||
|
const handLayout = cardFaceLayout(CARD_W);
|
||||||
|
const previewValues = { Cost: cards[i - 1].cost, Name: cards[i - 1].name, Desc: cards[i - 1].desc };
|
||||||
|
const children = handLayout.texts.map(([suffix, cfg]) => [suffix, { ...cfg, value: previewValues[suffix] }]);
|
||||||
|
for (const [suffix, cfg] of children) {
|
||||||
|
const path = `/ui/DefaultGroup/CardHand/Card${i}/${suffix}`;
|
||||||
|
const dOrder = suffix === 'Cost' ? 7 : suffix === 'Name' ? 6 : 8;
|
||||||
|
let child = byPath.get(path);
|
||||||
|
if (!child) {
|
||||||
|
child = entity({
|
||||||
|
id: guid('dck', i * 10 + children.findIndex(([s]) => s === suffix)),
|
||||||
|
path,
|
||||||
|
modelId: 'uitext',
|
||||||
|
entryId: 'UIText',
|
||||||
|
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent',
|
||||||
|
displayOrder: dOrder,
|
||||||
|
components: [
|
||||||
|
transform({ parentW: CARD_W, parentH: CARD_H, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: cfg.size, pos: cfg.pos }),
|
||||||
|
sprite({ color: TRANSPARENT }),
|
||||||
|
text({ value: cfg.value, fontSize: cfg.fontSize, bold: cfg.bold, color: cfg.color, dropShadow: cfg.dropShadow, outlineWidth: cfg.outlineWidth }),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
ui.ContentProto.Entities.push(child);
|
||||||
|
byPath.set(path, child);
|
||||||
|
} else {
|
||||||
|
child.id = guid('dck', i * 10 + children.findIndex(([s]) => s === suffix));
|
||||||
|
child.jsonString.enable = true;
|
||||||
|
child.jsonString.visible = true;
|
||||||
|
child.jsonString.displayOrder = dOrder;
|
||||||
|
const ctr = child.jsonString['@components'].find((c) => c['@type'] === 'MOD.Core.UITransformComponent');
|
||||||
|
if (ctr) {
|
||||||
|
const pivot = { x: 0.5, y: 0.5 };
|
||||||
|
ctr.RectSize = cfg.size;
|
||||||
|
ctr.anchoredPosition = cfg.pos;
|
||||||
|
ctr.OffsetMin = { x: cfg.pos.x - pivot.x * cfg.size.x, y: cfg.pos.y - pivot.y * cfg.size.y };
|
||||||
|
ctr.OffsetMax = { x: cfg.pos.x + (1 - pivot.x) * cfg.size.x, y: cfg.pos.y + (1 - pivot.y) * cfg.size.y };
|
||||||
|
}
|
||||||
|
child.jsonString['@components'][2].Text = cfg.value;
|
||||||
|
child.jsonString['@components'][2].FontSize = cfg.fontSize;
|
||||||
|
child.jsonString['@components'][2].MaxSize = cfg.fontSize;
|
||||||
|
child.jsonString['@components'][2].FontColor = cfg.color;
|
||||||
|
child.jsonString['@components'][2].Bold = cfg.bold;
|
||||||
|
child.jsonString['@components'][2].DropShadow = cfg.dropShadow === true;
|
||||||
|
child.jsonString['@components'][2].DropShadowDistance = cfg.dropShadow === true ? 18 : 32;
|
||||||
|
child.jsonString['@components'][2].OutlineWidth = cfg.outlineWidth || 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 프레임 이미지가 이름판·코스트판을 내장하므로 Art만 유지 (잔존 NamePlate/CostPlate는 upsertUi 초입에서 제거)
|
||||||
|
const frameKids = [
|
||||||
|
['Art', 5, handLayout.art, WHITE, 0],
|
||||||
|
];
|
||||||
|
for (const [suffix, dOrder, cfg, color, spriteType] of frameKids) {
|
||||||
|
const fPath = `/ui/DefaultGroup/CardHand/Card${i}/${suffix}`;
|
||||||
|
let fe = byPath.get(fPath);
|
||||||
|
if (!fe) {
|
||||||
|
fe = entity({
|
||||||
|
id: guid('dck', 200 + i * 10 + dOrder),
|
||||||
|
path: fPath,
|
||||||
|
modelId: 'uisprite',
|
||||||
|
entryId: 'UISprite',
|
||||||
|
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
|
||||||
|
displayOrder: dOrder,
|
||||||
|
components: [
|
||||||
|
transform({ parentW: CARD_W, parentH: CARD_H, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: cfg.size, pos: cfg.pos }),
|
||||||
|
sprite({ color, type: spriteType, raycast: false }),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
ui.ContentProto.Entities.push(fe);
|
||||||
|
byPath.set(fPath, fe);
|
||||||
|
} else {
|
||||||
|
const ftr = fe.jsonString['@components'].find((c) => c['@type'] === 'MOD.Core.UITransformComponent');
|
||||||
|
if (ftr) {
|
||||||
|
ftr.RectSize = cfg.size;
|
||||||
|
ftr.anchoredPosition = cfg.pos;
|
||||||
|
ftr.OffsetMin = { x: cfg.pos.x - cfg.size.x / 2, y: cfg.pos.y - cfg.size.y / 2 };
|
||||||
|
ftr.OffsetMax = { x: cfg.pos.x + cfg.size.x / 2, y: cfg.pos.y + cfg.size.y / 2 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('DeckHud', buildDeckHud());
|
||||||
|
|
||||||
|
emit('DeckInspectHud', buildDeckInspect());
|
||||||
|
|
||||||
|
emit('DeckAllHud', buildDeckAll());
|
||||||
|
|
||||||
|
emit('CombatHud', buildCombat());
|
||||||
|
|
||||||
|
emit('RewardHud', buildReward());
|
||||||
|
|
||||||
|
emit('MapHud', buildMap());
|
||||||
|
|
||||||
|
emit('ShopHud', buildShop());
|
||||||
|
|
||||||
|
emit('RestHud', buildRest());
|
||||||
|
|
||||||
|
// 유물 방 — 보물 상자 (P8)
|
||||||
|
emit('TreasureHud', buildTreasure());
|
||||||
|
|
||||||
|
// 전직 선택 (P9) — 보스 보상: 유물 vs 2차 전직
|
||||||
|
emit('JobChoiceHud', buildJobChoice());
|
||||||
|
|
||||||
|
emit('JobSelectHud', buildJobSelect());
|
||||||
|
|
||||||
|
emit('MainMenu', buildMainMenu());
|
||||||
|
|
||||||
|
// ── LobbyHud — 반복 런의 허브. NPC 클릭으로 런시작/도감/영혼상점/게시판 ──
|
||||||
|
emit('LobbyHud', buildLobby());
|
||||||
|
|
||||||
|
// ── BoardHud — 게시판(공지/팁) ──
|
||||||
|
emit('BoardHud', buildBoard());
|
||||||
|
|
||||||
|
// ── SoulShopHud — 영혼 메타 상점 (Phase 9에서 해금 항목·구매 로직 채움) ──
|
||||||
|
emit('SoulShopHud', buildSoulShop());
|
||||||
|
|
||||||
|
for (const section of UI_APPEND_ORDER) {
|
||||||
|
const entities = uiSections.get(section);
|
||||||
|
if (entities == null) {
|
||||||
|
throw new Error(`[gen-slaydeck] missing generated UI section: ${section}`);
|
||||||
|
}
|
||||||
|
appendUiSection(ui, section, entities);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 엔티티 id 유일성 검증 — 같은 id가 다른 path에 재배정되면 메이커 refresh 병합이 꼬임
|
||||||
|
const seenIds = new Map();
|
||||||
|
for (const e of ui.ContentProto.Entities) {
|
||||||
|
const prev = seenIds.get(e.id);
|
||||||
|
if (prev != null) throw new Error(`[gen-slaydeck] 엔티티 id 중복: ${e.id} (${prev} ↔ ${e.path})`);
|
||||||
|
seenIds.set(e.id, e.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON.parse(JSON.stringify(ui));
|
||||||
|
writeFileSync(UI_FILE, JSON.stringify(ui, null, 2), 'utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 롤백/참조용 직접 실행 시에만 동작 (import 시에는 실행 안 함)
|
||||||
|
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
||||||
|
upsertUi();
|
||||||
|
}
|
||||||
28
tools/deck/reconnect-ui-paths.mjs
Normal file
28
tools/deck/reconnect-ui-paths.mjs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { readFileSync, writeFileSync, readdirSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
// 일회성·멱등 마이그레이션: cb/*.mjs의 UI 경로 리터럴을 메이커 재편 UIGroup으로 재연결.
|
||||||
|
// 이미 이동된 경로는 매치 안 됨(멱등). MainMenu·Button_Attack/Jump·UIJoystick(=DefaultGroup 잔류)은 미변경.
|
||||||
|
// 섹션→UIGroup 매핑은 tools/verify/uimap.mjs 탐색으로 검증된 실제 .ui 분포 기준.
|
||||||
|
const MOVE = {
|
||||||
|
CharacterSelectHud: 'SelectUIGroup', JobChoiceHud: 'SelectUIGroup', JobSelectHud: 'SelectUIGroup',
|
||||||
|
LobbyHud: 'LobbyUIGroup', BoardHud: 'LobbyUIGroup', SoulShopHud: 'LobbyUIGroup',
|
||||||
|
CombatHud: 'RunUIGroup', DeckHud: 'RunUIGroup', CardHand: 'RunUIGroup', MapHud: 'RunUIGroup',
|
||||||
|
RewardHud: 'RunUIGroup', ShopHud: 'RunUIGroup', RestHud: 'RunUIGroup', TreasureHud: 'RunUIGroup',
|
||||||
|
DeckInspectHud: 'DeckUIGroup', DeckAllHud: 'DeckUIGroup',
|
||||||
|
};
|
||||||
|
const CB_DIR = 'tools/deck/cb';
|
||||||
|
let n = 0;
|
||||||
|
for (const f of readdirSync(CB_DIR).filter((x) => x.endsWith('.mjs'))) {
|
||||||
|
const p = join(CB_DIR, f);
|
||||||
|
const before = readFileSync(p, 'utf8');
|
||||||
|
let s = before;
|
||||||
|
// 1) 몬스터 슬롯: 그룹+이름 동시 (CombatHud 일반 remap보다 먼저). 슬롯 5→4는 MAX_MONSTERS(=4)가 이미 반영.
|
||||||
|
s = s.split('/ui/DefaultGroup/CombatHud/MonsterSlot').join('/ui/RunUIGroup/CombatHud/MonsterStatus');
|
||||||
|
// 2) 섹션별 그룹 접두사 remap
|
||||||
|
for (const [section, group] of Object.entries(MOVE)) {
|
||||||
|
s = s.split(`/ui/DefaultGroup/${section}`).join(`/ui/${group}/${section}`);
|
||||||
|
}
|
||||||
|
if (s !== before) { writeFileSync(p, s, 'utf8'); n++; console.log(' remapped', f); }
|
||||||
|
}
|
||||||
|
console.log(`reconnect-ui-paths: ${n} files updated`);
|
||||||
69
tools/verify/cbgap.mjs
Normal file
69
tools/verify/cbgap.mjs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import { readFileSync, readdirSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
// cb 컨트롤러가 참조하는 /ui/DefaultGroup/... 경로를, 사용자가 메이커에서 재편한
|
||||||
|
// 새 UIGroup(.ui) 구조에 대조해 "그대로 옮겨지면 해결(resolved)" vs "이름/구조가 바뀌어
|
||||||
|
// 못 찾음(GAP)"을 분류. GAP = 사용자에게 구→신 매핑을 받아야 할 항목.
|
||||||
|
// 출력은 경로 이름 + EXISTS/GAP boolean 뿐(엔티티 값 본문 미출력 → RULES §2 준수).
|
||||||
|
|
||||||
|
// 섹션(=DefaultGroup 다음 첫 세그먼트) → 이동된 UIGroup (uimap.mjs 탐색 결과 기반)
|
||||||
|
const SECTION_TO_GROUP = {
|
||||||
|
MainMenu: 'DefaultGroup', Button_Attack: 'DefaultGroup', Button_Jump: 'DefaultGroup', UIJoystick: 'DefaultGroup',
|
||||||
|
CharacterSelectHud: 'SelectUIGroup', JobChoiceHud: 'SelectUIGroup', JobSelectHud: 'SelectUIGroup',
|
||||||
|
LobbyHud: 'LobbyUIGroup', BoardHud: 'LobbyUIGroup', SoulShopHud: 'LobbyUIGroup',
|
||||||
|
CombatHud: 'RunUIGroup', DeckHud: 'RunUIGroup', CardHand: 'RunUIGroup', MapHud: 'RunUIGroup',
|
||||||
|
RewardHud: 'RunUIGroup', ShopHud: 'RunUIGroup', RestHud: 'RunUIGroup', TreasureHud: 'RunUIGroup',
|
||||||
|
DeckInspectHud: 'DeckUIGroup', DeckAllHud: 'DeckUIGroup',
|
||||||
|
};
|
||||||
|
|
||||||
|
// 새 .ui 로드
|
||||||
|
const UI_DIR = 'ui';
|
||||||
|
const ui = {};
|
||||||
|
for (const f of readdirSync(UI_DIR).filter((x) => x.endsWith('.ui'))) {
|
||||||
|
ui[f.replace('.ui', '')] = readFileSync(join(UI_DIR, f), 'utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
// cb 소스에서 /ui/DefaultGroup/... 경로 리터럴 추출 (템플릿 ${...} 포함)
|
||||||
|
const CB_DIR = 'tools/deck/cb';
|
||||||
|
const re = /\/ui\/DefaultGroup\/[^"'`\s),]+/g;
|
||||||
|
const paths = new Set();
|
||||||
|
for (const f of readdirSync(CB_DIR).filter((x) => x.endsWith('.mjs'))) {
|
||||||
|
const src = readFileSync(join(CB_DIR, f), 'utf8');
|
||||||
|
for (const m of src.match(re) || []) paths.add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 동적 세그먼트(${...}) 앞 정적 prefix만 취해 존재검사 (e.g. .../Card${i} → .../Card)
|
||||||
|
function staticPrefix(p) {
|
||||||
|
const i = p.indexOf('${');
|
||||||
|
if (i === -1) return { p, dyn: false };
|
||||||
|
// ${...} 직전까지 (마지막 세그먼트의 정적 앞부분 포함)
|
||||||
|
return { p: p.slice(0, i), dyn: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
const bySection = {};
|
||||||
|
for (const p of [...paths].sort()) {
|
||||||
|
const rest = p.slice('/ui/DefaultGroup/'.length); // Section/child/...
|
||||||
|
const section = rest.split('/')[0].split('${')[0];
|
||||||
|
const group = SECTION_TO_GROUP[section] || '??';
|
||||||
|
const newPath = group === '??' ? p : p.replace('/ui/DefaultGroup/', `/ui/${group}/`);
|
||||||
|
const { p: probe } = staticPrefix(newPath);
|
||||||
|
const blob = ui[group] || '';
|
||||||
|
const exists = group !== '??' && blob.includes(probe);
|
||||||
|
(bySection[section] ||= []).push({ old: p, neu: newPath, exists, group });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 보고
|
||||||
|
let totResolved = 0, totGap = 0;
|
||||||
|
for (const section of Object.keys(bySection).sort()) {
|
||||||
|
const rows = bySection[section];
|
||||||
|
const group = rows[0].group;
|
||||||
|
const gaps = rows.filter((r) => !r.exists);
|
||||||
|
const ok = rows.length - gaps.length;
|
||||||
|
totResolved += ok; totGap += gaps.length;
|
||||||
|
console.log(`\n[${section}] → ${group} 해결 ${ok} / GAP ${gaps.length} (총 ${rows.length})`);
|
||||||
|
for (const g of gaps) {
|
||||||
|
// GAP만 상세 출력 (사용자가 신규 이름 채워야 할 대상)
|
||||||
|
console.log(` GAP ${g.old.replace('/ui/DefaultGroup/', '')} →(없음) ${g.neu.replace(`/ui/${group}/`, `${group}: `)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(`\n=== 합계: 자동해결 ${totResolved} / GAP ${totGap} (distinct 경로 ${paths.size}) ===`);
|
||||||
35
tools/verify/uimap.mjs
Normal file
35
tools/verify/uimap.mjs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { readFileSync, readdirSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
// UIGroup(.ui) 매핑 헬퍼 (RULES §2: 내용 출력 금지·카운트만).
|
||||||
|
// 어떤 섹션/엔티티 이름이 어느 .ui 파일에 들어있는지 카운트 매트릭스로 보고.
|
||||||
|
// 산출물 경로를 명령줄에 노출하지 않아(디렉토리 스캔) deny 회피.
|
||||||
|
//
|
||||||
|
// 사용: node tools/verify/uimap.mjs <pattern> [<pattern> ...]
|
||||||
|
// 각 pattern은 정규식. 출력은 "pattern | file=count ..." 형식(본문 미출력).
|
||||||
|
const UI_DIR = 'ui';
|
||||||
|
const files = readdirSync(UI_DIR).filter((f) => f.endsWith('.ui'));
|
||||||
|
const cache = {};
|
||||||
|
for (const f of files) {
|
||||||
|
cache[f] = readFileSync(join(UI_DIR, f), 'utf8');
|
||||||
|
}
|
||||||
|
// 파일별 크기/JSON 유효성 헤더
|
||||||
|
console.log('=== ui/*.ui ===');
|
||||||
|
for (const f of files) {
|
||||||
|
let ok = false;
|
||||||
|
try { JSON.parse(cache[f]); ok = true; } catch { ok = false; }
|
||||||
|
console.log(` ${f} bytes=${cache[f].length} jsonValid=${ok}`);
|
||||||
|
}
|
||||||
|
const pats = process.argv.slice(2);
|
||||||
|
if (pats.length === 0) process.exit(0);
|
||||||
|
console.log('=== matches (file=count, 0 생략) ===');
|
||||||
|
for (const pat of pats) {
|
||||||
|
const re = new RegExp(pat, 'g');
|
||||||
|
const hits = [];
|
||||||
|
for (const f of files) {
|
||||||
|
const m = cache[f].match(re);
|
||||||
|
const n = m ? m.length : 0;
|
||||||
|
if (n > 0) hits.push(`${f}=${n}`);
|
||||||
|
}
|
||||||
|
console.log(` /${pat}/ ${hits.length ? hits.join(' ') : '(none)'}`);
|
||||||
|
}
|
||||||
157957
ui/DeckUIGroup.ui
Normal file
157957
ui/DeckUIGroup.ui
Normal file
File diff suppressed because it is too large
Load Diff
243887
ui/DefaultGroup.ui
243887
ui/DefaultGroup.ui
File diff suppressed because it is too large
Load Diff
5414
ui/LobbyUIGroup.ui
Normal file
5414
ui/LobbyUIGroup.ui
Normal file
File diff suppressed because it is too large
Load Diff
100
ui/PopupGroup.ui
100
ui/PopupGroup.ui
@@ -97,7 +97,7 @@
|
|||||||
{
|
{
|
||||||
"@type": "MOD.Core.UIGroupComponent",
|
"@type": "MOD.Core.UIGroupComponent",
|
||||||
"DefaultShow": false,
|
"DefaultShow": false,
|
||||||
"GroupOrder": 1,
|
"GroupOrder": 2,
|
||||||
"GroupType": 1,
|
"GroupType": 1,
|
||||||
"Enable": true
|
"Enable": true
|
||||||
},
|
},
|
||||||
@@ -585,7 +585,7 @@
|
|||||||
{
|
{
|
||||||
"id": "94a274e4-4111-40f1-924d-c95a3a1f14d5",
|
"id": "94a274e4-4111-40f1-924d-c95a3a1f14d5",
|
||||||
"path": "/ui/PopupGroup/PopupBack/PopupPanel/PopupBtnOK",
|
"path": "/ui/PopupGroup/PopupBack/PopupPanel/PopupBtnOK",
|
||||||
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent,MOD.Core.TextComponent",
|
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent",
|
||||||
"jsonString": {
|
"jsonString": {
|
||||||
"name": "PopupBtnOK",
|
"name": "PopupBtnOK",
|
||||||
"path": "/ui/PopupGroup/PopupBack/PopupPanel/PopupBtnOK",
|
"path": "/ui/PopupGroup/PopupBack/PopupPanel/PopupBtnOK",
|
||||||
@@ -719,53 +719,6 @@
|
|||||||
"Type": 1,
|
"Type": 1,
|
||||||
"Enable": true
|
"Enable": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"@type": "MOD.Core.ButtonComponent",
|
|
||||||
"Colors": {
|
|
||||||
"NormalColor": {
|
|
||||||
"r": 1.0,
|
|
||||||
"g": 1.0,
|
|
||||||
"b": 1.0,
|
|
||||||
"a": 1.0
|
|
||||||
},
|
|
||||||
"HighlightedColor": {
|
|
||||||
"r": 0.9607843,
|
|
||||||
"g": 0.9607843,
|
|
||||||
"b": 0.9607843,
|
|
||||||
"a": 1.0
|
|
||||||
},
|
|
||||||
"PressedColor": {
|
|
||||||
"r": 0.784313738,
|
|
||||||
"g": 0.784313738,
|
|
||||||
"b": 0.784313738,
|
|
||||||
"a": 1.0
|
|
||||||
},
|
|
||||||
"SelectedColor": {
|
|
||||||
"r": 0.9607843,
|
|
||||||
"g": 0.9607843,
|
|
||||||
"b": 0.9607843,
|
|
||||||
"a": 1.0
|
|
||||||
},
|
|
||||||
"DisabledColor": {
|
|
||||||
"r": 0.784313738,
|
|
||||||
"g": 0.784313738,
|
|
||||||
"b": 0.784313738,
|
|
||||||
"a": 0.5019608
|
|
||||||
},
|
|
||||||
"ColorMultiplier": 1.0,
|
|
||||||
"FadeDuration": 0.1
|
|
||||||
},
|
|
||||||
"ImageRUIDs": {
|
|
||||||
"HighlightedSprite": null,
|
|
||||||
"PressedSprite": null,
|
|
||||||
"SelectedSprite": null,
|
|
||||||
"DisabledSprite": null
|
|
||||||
},
|
|
||||||
"KeyCode": 0,
|
|
||||||
"OverrideSorting": false,
|
|
||||||
"Transition": 1,
|
|
||||||
"Enable": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"@type": "MOD.Core.TextComponent",
|
"@type": "MOD.Core.TextComponent",
|
||||||
"Alignment": 4,
|
"Alignment": 4,
|
||||||
@@ -820,7 +773,7 @@
|
|||||||
{
|
{
|
||||||
"id": "0f5de49b-2adc-409a-816d-15aa43df8e0d",
|
"id": "0f5de49b-2adc-409a-816d-15aa43df8e0d",
|
||||||
"path": "/ui/PopupGroup/PopupBack/PopupPanel/PopupBtnCancel",
|
"path": "/ui/PopupGroup/PopupBack/PopupPanel/PopupBtnCancel",
|
||||||
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent,MOD.Core.TextComponent",
|
"componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent",
|
||||||
"jsonString": {
|
"jsonString": {
|
||||||
"name": "PopupBtnCancel",
|
"name": "PopupBtnCancel",
|
||||||
"path": "/ui/PopupGroup/PopupBack/PopupPanel/PopupBtnCancel",
|
"path": "/ui/PopupGroup/PopupBack/PopupPanel/PopupBtnCancel",
|
||||||
@@ -954,53 +907,6 @@
|
|||||||
"Type": 1,
|
"Type": 1,
|
||||||
"Enable": true
|
"Enable": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"@type": "MOD.Core.ButtonComponent",
|
|
||||||
"Colors": {
|
|
||||||
"NormalColor": {
|
|
||||||
"r": 1.0,
|
|
||||||
"g": 1.0,
|
|
||||||
"b": 1.0,
|
|
||||||
"a": 1.0
|
|
||||||
},
|
|
||||||
"HighlightedColor": {
|
|
||||||
"r": 0.9607843,
|
|
||||||
"g": 0.9607843,
|
|
||||||
"b": 0.9607843,
|
|
||||||
"a": 1.0
|
|
||||||
},
|
|
||||||
"PressedColor": {
|
|
||||||
"r": 0.784313738,
|
|
||||||
"g": 0.784313738,
|
|
||||||
"b": 0.784313738,
|
|
||||||
"a": 1.0
|
|
||||||
},
|
|
||||||
"SelectedColor": {
|
|
||||||
"r": 0.9607843,
|
|
||||||
"g": 0.9607843,
|
|
||||||
"b": 0.9607843,
|
|
||||||
"a": 1.0
|
|
||||||
},
|
|
||||||
"DisabledColor": {
|
|
||||||
"r": 0.784313738,
|
|
||||||
"g": 0.784313738,
|
|
||||||
"b": 0.784313738,
|
|
||||||
"a": 0.5019608
|
|
||||||
},
|
|
||||||
"ColorMultiplier": 1.0,
|
|
||||||
"FadeDuration": 0.1
|
|
||||||
},
|
|
||||||
"ImageRUIDs": {
|
|
||||||
"HighlightedSprite": null,
|
|
||||||
"PressedSprite": null,
|
|
||||||
"SelectedSprite": null,
|
|
||||||
"DisabledSprite": null
|
|
||||||
},
|
|
||||||
"KeyCode": 0,
|
|
||||||
"OverrideSorting": false,
|
|
||||||
"Transition": 1,
|
|
||||||
"Enable": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"@type": "MOD.Core.TextComponent",
|
"@type": "MOD.Core.TextComponent",
|
||||||
"Alignment": 4,
|
"Alignment": 4,
|
||||||
|
|||||||
69868
ui/RunUIGroup.ui
Normal file
69868
ui/RunUIGroup.ui
Normal file
File diff suppressed because it is too large
Load Diff
6123
ui/SelectUIGroup.ui
Normal file
6123
ui/SelectUIGroup.ui
Normal file
File diff suppressed because it is too large
Load Diff
@@ -97,7 +97,7 @@
|
|||||||
{
|
{
|
||||||
"@type": "MOD.Core.UIGroupComponent",
|
"@type": "MOD.Core.UIGroupComponent",
|
||||||
"DefaultShow": false,
|
"DefaultShow": false,
|
||||||
"GroupOrder": 2,
|
"GroupOrder": 3,
|
||||||
"GroupType": 1,
|
"GroupType": 1,
|
||||||
"Enable": true
|
"Enable": true
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user