diff --git a/공유/PD_지시_트래킹/개발팀_PD_지시_로그.md b/공유/PD_지시_트래킹/개발팀_PD_지시_로그.md index d31f57c..6fde04a 100644 --- a/공유/PD_지시_트래킹/개발팀_PD_지시_로그.md +++ b/공유/PD_지시_트래킹/개발팀_PD_지시_로그.md @@ -33,6 +33,7 @@ C3·C13 위반에 해당. **즉시 자진 보고 후 소급 등록**. | # | 일시 | 지시 요지 | 처리 상태 | 산출물 경로 | 중단 사유 | 사후 조치 | |---|------|----------|----------|-----------|----------|----------| +| BT49-FirstRising | 2026-10-02 | **장비 아이콘 생성 체계 구축 (ComfyUI · 투명 배경) — 원하는 장비 아이콘을 자유롭게 생성할 수 있을 때까지 생성 · 검토 · 학습을 자율 반복** + (10-03) **원색 계열만 써서 저급해 보인다 → 색감 개선** (원문은 대화로그) | **보류(10-03 PD "이 세션의 작업은 여기서 마무리하고, 추후 다시 진행")** — 회차 a1~a28 · 자체 LoRA v1~v6. 되는 방식 = 윤곽 길잡이 + 부위별 재질 · 작은 강조색 묘사(검토 평가: 길잡이 방식 6.5~7/10 · 레퍼런스 색감 대비 6/10 · 글자만 4.5/10). 정식 경로 = 글자 → SDXL 초벌 → 눈으로 고른 윤곽 길잡이 → 본 생성(`icon_make.py`). 리소스 후보: 색 개선 최상급 32장(21종) `moba_anfg/best_color/` · 예전 색 최상급 46장 · 합격본 166장 · 데이터셋 462장. 결정 대기: 색 개선 방향 확인 · FR 반입 · SDXL 전환(GPU 업그레이드 뒤). 미해결: 뿔피리 · 석궁류 · 손그림 질감. FR 반입 없음. 문서 `공유/기획/FirstRising/아이템/아이콘_생성_체계.md` · 인수인계 `공유/대화로그/FirstRising/2026-10-03_세션인수인계.md` | | BT48-FirstRising | 2026-10-01 | **아이템 드랍 · 아이템 · 능력치 시스템 구현 (디아블로식 파밍) — 몬스터 처치 시 드롭, 인벤토리에서 옵션 확인, 완료까지 중단 없이 자율 반복** (BT47 초안 v1 확정 기준 · 원문은 대화로그) | **완료 · FR `bt/work` `dc45353d72` push(10-01 22:59)** — 후속 3건 반영(드롭률 10% · 예전 등급 옵션 표시/적용 제거 + 기존 장비 변환 · 활 기본 투사체 수 1) · 3차 검증 Play 오류 0 · — 처치 → 드롭(등급 색 기둥 + 한글 이름표) → 습득 → 인벤토리 · 정보 창(고정1 · 옵션) → 8부위 장착 → 능력치 엔티티 반영(방어 v2 · 신성 · 관통 · 고정 피해 · 저항 · 회피 · 막기). 보류: 공격 속도 · 사거리 · 투사체 수 · 범위 피해 · 스킬 레벨 · 상태이상 · 흡혈 · 획득량 · 조건부 옵션(스킬 시스템 수정 필요) | FR `Assets/BurningTimes/Visual/Scripts/TV{ItemData,GlobalValue,ItemDatabase,ItemGenerator,LootDrops,ItemStats,ItemStatSync,ItemText}.cs` · `Resources/BT/*.asset` · 원본 9곳 · 인계서 `공유/대화로그/FirstRising/2026-10-01_세션인수인계.md` · 검증 `몬스터보스/tools/unity_eval/bt_evals_1001/` | — | — | | BT47-FirstRising | 2026-10-01 | **아이템 드랍 시스템 초안 설계** — 등급 10 · 부위 8 · 고정 스텟 + 랜덤 옵션 · 몬스터 레벨→드랍 범위 · 획득 찬스→상위 등급. 능력치 시스템 변경 규모 병렬 점검(원문은 대화로그) | **초안 v0 + PPT 21장 제출(10-01) · PD 결정 대기 8건(Q14~Q21)** — 판정 [실측]: 대대적 개편 아님, 중간 규모 확장. PD 확정 13건(신성 = 방어 무시 순수 피해 · 공격 속도 = 무기 스킬 쿨타임 · 관통/고정 피해/막기 정의 · 보조 장비 8종 · 반지 1/목걸이 1 · 등급 = 성능만) 반영. 방어력 공식 v2(로그형 단일 곡선, 상한 80% 하나) PD "우선 이대로" | `공유/기획/FirstRising/시스템기획/2026-10-01_FR_아이템드랍시스템_초안_v0.md` · `…_초안_v0.pptx` · `tools/build_item_drop_v0.py` | — | — | | BT46-Org | 2026-09-30 09:40 | **Claude 윈도우 앱이 쓰지 않는 동안 트레이에서 사라짐 — 원인 확인 · 조치** (원문은 대화로그) | **원인 확정 · 조치 준비 완료(09-30 10:00) · PD 실행 대기** — 원인 [실측 · 앱 로그 + 윈도우 이벤트 로그]: 앱이 업데이트를 받아 둔 채 10분쯤 쉬면 창 · 트레이를 내리고 윈도우에 강제 종료 + 새 버전 등록을 요청하는데, 09-23 02:56 부터 앱이 자기 프로세스를 작업 묶음에 넣으면서(`[windows-app-job] joined`) 윈도우가 앱을 닫지 못한다(AppXDeploymentServer 419 · 404 — 0x800700E9 / 0x8007001F). 그 전 18회는 2~40초 만에 재시작, 그 뒤 6회는 전부 실패. 실패하면 앱은 창 · 트레이 없이 숨어서 남고 아이콘을 눌러도 뜨지 않는다. 앱 내부 결함이라 직접 고칠 수 없음 → 감시 스크립트 작성 · 시험 모드 4가지 상황 통과. 작업 스케줄러 등록은 시스템 설정이라 PD 가 명령 1개로 실행 | `%LOCALAPPDATA%/ClaudeTrayWatchdog/`(watchdog.ps1 · run-hidden.vbs) · `공유/대화로그/조직운영/2026-09-30_Claude앱_트레이.md` | — | 등록 뒤 첫 실제 발생 때 동작 확인 필요(실제 끄고 켜기는 시험하지 않음 — 이 세션이 그 앱 안에서 돈다) · 근본 수정은 Anthropic 앱 업데이트 | diff --git a/공유/기획/FirstRising/아이템/comfy_alt_ckpt.py b/공유/기획/FirstRising/아이템/comfy_alt_ckpt.py new file mode 100644 index 0000000..d0203d3 --- /dev/null +++ b/공유/기획/FirstRising/아이템/comfy_alt_ckpt.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +# 2026-10-01 PD 지시 — "내가 원하는 스타일이 아니야. 다른 체크포인트로 제작을 시도해보자." +# 보유한 다른 체크포인트로 같은 대상 6종을 시험 생성해 한 장으로 모은다(풍 비교용). +# python comfy_alt_ckpt.py <출력폴더> +import io, json, os, sys, time, uuid, urllib.request, urllib.parse +from PIL import Image, ImageDraw + +HOST = "http://127.0.0.1:8000" +SUBJECTS = [("sword", "a sword"), ("armor", "a breastplate armor"), ("gloves", "a pair of gauntlets"), ("ring", "a ring with a gemstone"), ("shield", "a shield"), ("bow", "a bow")] +# 목표 풍(PD 가 처음 고른 사이트 예시의 특징): 굵고 양식화된 손그림풍 MMO 아이콘 · 진한 채도 · 두꺼운 형태 · 발광 · 검은 배경 +STYLE = "stylized fantasy MMORPG game item icon, hand-painted, bold thick chunky shapes, vibrant saturated colors, glowing magical accents, ornate, three-quarter view, centered single object, plain black background" + +PRESETS = { + "flux": dict(ckpt="flux1CheckpointEasyTo_v10.safetensors", flux=True, size=768, steps=20, cfg=1.0, sampler="euler", scheduler="simple", neg="", prefix="", lora=None), + "noob": dict(ckpt="noobaiXLNAIXL_epsilonPred05Version.safetensors", flux=False, size=1024, steps=26, cfg=6.0, sampler="euler_ancestral", scheduler="normal", + neg="worst quality, low quality, blurry, text, watermark, person, 1girl, hands, photo", prefix="masterpiece, best quality, no humans, ", lora=None), + "noob2": dict(ckpt="catTowerNoobaiXL_chenkinnoobV11.safetensors", flux=False, size=1024, steps=26, cfg=6.0, sampler="euler_ancestral", scheduler="normal", + neg="worst quality, low quality, blurry, text, watermark, person, 1girl, hands, photo", prefix="masterpiece, best quality, no humans, ", lora=None), + "sd15rpg": dict(ckpt="difconsistencyCheckpoint_v10.safetensors", flux=False, size=512, steps=28, cfg=7.0, sampler="dpmpp_2m", scheduler="karras", + neg="worst quality, low quality, blurry, text, watermark, person, hands, photo, realistic", prefix="", lora=("GameItemUI_sd15.safetensors", 0.8)), +} + + +def post(path, data): + req = urllib.request.Request(HOST + path, data=json.dumps(data).encode("utf-8"), headers={"Content-Type": "application/json"}) + return json.loads(urllib.request.urlopen(req, timeout=60).read()) + + +def get(path): + return urllib.request.urlopen(HOST + path, timeout=300).read() + + +def workflow(p, prompt, seed): + wf = {"1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": p["ckpt"]}}} + model, clip = ["1", 0], ["1", 1] + if p["lora"]: + wf["2"] = {"class_type": "LoraLoader", "inputs": {"model": model, "clip": clip, "lora_name": p["lora"][0], "strength_model": p["lora"][1], "strength_clip": p["lora"][1]}} + model, clip = ["2", 0], ["2", 1] + wf["4"] = {"class_type": "CLIPTextEncode", "inputs": {"clip": clip, "text": prompt}} + wf["5"] = {"class_type": "CLIPTextEncode", "inputs": {"clip": clip, "text": p["neg"]}} + pos = ["4", 0] + if p["flux"]: + wf["13"] = {"class_type": "FluxGuidance", "inputs": {"conditioning": ["4", 0], "guidance": 3.5}} + pos = ["13", 0] + wf["6"] = {"class_type": "EmptyLatentImage", "inputs": {"width": p["size"], "height": p["size"], "batch_size": 1}} + wf["7"] = {"class_type": "KSampler", "inputs": {"model": model, "positive": pos, "negative": ["5", 0], "latent_image": ["6", 0], "seed": seed, "steps": p["steps"], "cfg": p["cfg"], "sampler_name": p["sampler"], "scheduler": p["scheduler"], "denoise": 1.0}} + wf["8"] = {"class_type": "VAEDecode", "inputs": {"samples": ["7", 0], "vae": ["1", 2]}} + wf["9"] = {"class_type": "SaveImage", "inputs": {"images": ["8", 0], "filename_prefix": "alt_ckpt"}} + return wf + + +def run(p, prompt, seed): + pid = post("/prompt", {"prompt": workflow(p, prompt, seed), "client_id": str(uuid.uuid4())})["prompt_id"] + t0 = time.time() + while time.time() - t0 < 1500: + hist = json.loads(get("/history/" + pid)) + if pid in hist: + st = hist[pid].get("status", {}) + if st.get("status_str") == "error": + raise RuntimeError(json.dumps(st)[:900]) + for node in hist[pid].get("outputs", {}).values(): + for im in node.get("images", []): + q = urllib.parse.urlencode({"filename": im["filename"], "subfolder": im.get("subfolder", ""), "type": im.get("type", "output")}) + return Image.open(io.BytesIO(get("/view?" + q))).convert("RGB") + time.sleep(2) + raise TimeoutError("comfy timeout") + + +def main(): + out, name = sys.argv[1], sys.argv[2] + p = PRESETS[name] + os.makedirs(out, exist_ok=True) + cell, pad, label = 256, 6, 18 + sheet = Image.new("RGB", (len(SUBJECTS) * (cell + pad) + pad, cell + pad * 2 + label), (40, 40, 40)) + draw = ImageDraw.Draw(sheet) + for i, (sname, body) in enumerate(SUBJECTS): + prompt = "%s%s, %s" % (p["prefix"], body, STYLE) + t0 = time.time() + im = run(p, prompt, 7000 + i * 19) + print("%s %s %.1f초" % (name, sname, time.time() - t0)); sys.stdout.flush() + im.save(os.path.join(out, "%s_%s.png" % (name, sname))) + sheet.paste(im.resize((cell, cell), Image.LANCZOS), (pad + i * (cell + pad), label + pad)) + draw.text((pad + i * (cell + pad) + 4, 3), "%s / %s" % (name, sname), fill=(240, 220, 160)) + path = os.path.join(out, "%s_sheet.png" % name) + sheet.save(path) + print("sheet", path) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/comfy_anfg_train.py b/공유/기획/FirstRising/아이템/comfy_anfg_train.py new file mode 100644 index 0000000..e936177 --- /dev/null +++ b/공유/기획/FirstRising/아이템/comfy_anfg_train.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지시(자율 반복) — 합격본(dataset.json)으로 FR 전용 아이콘 LoRA 를 학습한다. 학습을 거듭할수록 합격본이 늘고, 글자만으로 원하는 풍이 나오게 하는 것이 목표. +# python comfy_anfg_train.py <버전 이름 예: v1> [steps=800] [PD 합격본 반복 배수=2] +# 구성: 기반 mobaGameEquipment_v10 위에 ANFG LoRA(0.8)를 얹은 모델을 학습 대상으로 넣는다 → 새 LoRA 는 "ANFG 풍에서 FR 합격본 쪽으로의 차이"만 배운다. +# (쓸 때도 ANFG LoRA 와 함께 건다.) 캡션 = "fricon, game icon institute, game icon, ahfg, <묘사>, black background". +# 학습 노드 구성 · 입력 이름은 comfy_moba_lora_train.py(2026-10-02) · comfy_lora_train.py(2026-09-25 실측)와 같다. +import io, json, os, shutil, sys, time, uuid, glob, urllib.request +from PIL import Image, ImageOps +import icon_dataset + +HOST = "http://127.0.0.1:8000" +VER = sys.argv[1] +STEPS = int(sys.argv[2]) if len(sys.argv) > 2 else 800 +PD_REPEAT = int(sys.argv[3]) if len(sys.argv) > 3 else 2 +NAME = "FR_anfg_%s" % VER +DS_NAME = "fr_anfg_%s" % VER +DS = os.path.join(r"C:\Comfyui\input", DS_NAME) +LORA_OUT = r"C:\Comfyui\output\loras" +LORA_DST = os.path.join(r"C:\Comfyui\models\loras", NAME + ".safetensors") +CKPT = "mobaGameEquipment_v10.safetensors" +BASE_LORA, BASE_LORA_STRENGTH = "giI_anfg_v3_000018.safetensors", 0.8 +TRIGGER = "fricon, game icon institute, game icon, ahfg" +RES = 512 +LR, RANK, BATCH, SEED = 2e-4, 16, 2, 11 + + +# a11 검토(v3): 글자만 생성이 "화면 가득한 금속 원반"으로 무너졌다. 원인으로 본 것 — ① 학습 그림이 캔버스의 82% 를 채워 여백을 못 배웠다 +# ② 갑옷 · 목걸이 · 장화가 많아 둥근 덩어리로 쏠렸다 ③ PD 합격본 윤곽에서 나온 복제(genpd)가 섞였다 ④ 캡션에 구도 낱말이 없었다. +# v4 부터: 그림을 줄여 여백을 넣고(MARGIN) · 종류당 장수를 제한하고(CAP) · genpd 유래를 빼고 · 캡션 앞에 생성 때와 같은 구도 낱말을 붙인다. +MARGIN = float(os.environ.get("ANFG_TRAIN_MARGIN", "0.84")) # 82% 로 맞춘 그림을 다시 이 비율로 줄인다 → 물체가 캔버스의 약 69% +CAP = int(os.environ.get("ANFG_TRAIN_CAP", "8")) # 종류당 최대 장수(PD 합격본은 제한 밖) +COMPOSE = "single item, centered, full object in frame, wide margin" + + +def kind_of(src): + """원본 파일 이름(<회차>_<대상>_s..)에서 종류를 읽는다 — 대상이 '종류-길잡이' 꼴이면 앞부분""" + import re + m = re.match(r"^[a-z0-9]+_(.+)_s\d+_\d+\.png$", src) + return m.group(1).split("-")[0] if m else "?" + + +def select(data): + """학습에 쓸 항목: PD 합격본 전부 + 나머지는 genpd 유래를 빼고 종류당 CAP 장(뒤 회차일수록 설정이 다듬어졌으므로 뒤에서부터 고른다)""" + # 2026-10-03 PD 지적("원색 계열만 … 저급해 보인다") 뒤: 예전 합격본(금 + 적/청)으로 학습한 v4 가 원색으로 끌어당긴다. + # ANFG_TRAIN_TAGS="a26,a27" 처럼 회차를 주면 그 회차(재질색 + 작은 강조색)의 합격본만으로 학습한다 — PD 가 예전에 고른 14장(원색 세트)도 뺀다. + tags = [x for x in os.environ.get("ANFG_TRAIN_TAGS", "").split(",") if x] + if tags: + data = [e for e in data if e["src"].split("_")[0] in tags] + picked = [e for e in data if e["source"] == "pd"] + count = {} + for e in reversed([e for e in data if e["source"] != "pd"]): + if "-genpd" in e["src"]: + continue + k = kind_of(e["src"]) + if count.get(k, 0) >= CAP: + continue + count[k] = count.get(k, 0) + 1 + picked.append(e) + print("학습 선택 %d / %d · 종류별 %s" % (len(picked), len(data), sorted(count.items(), key=lambda x: -x[1])), flush=True) + return picked + + +def build_dataset(): + data = select(icon_dataset.load()) + os.makedirs(DS, exist_ok=True) + n = 0 + for e in data: + im = Image.open(os.path.join(icon_dataset.DS_DIR, e["file"])).convert("RGBA") + side = max(1, int(RES * MARGIN)) + small = im.resize((side, side), Image.LANCZOS) + im = Image.new("RGBA", (RES, RES), (0, 0, 0, 0)); im.paste(small, ((RES - side) // 2, (RES - side) // 2), small) + base = os.path.splitext(e["file"])[0] + # PD 가 직접 고른 그림은 여러 번 넣어 비중을 높인다 + # 검토에서 "최상급"으로 뽑힌 그림(best_*.json → dataset.json 의 best 표시)은 두 번 넣는다(장식 밀도 · 붓결이 좋은 쪽으로 끌기 위해) + reps = PD_REPEAT if e["source"] == "pd" else (2 if e.get("best") else 1) + for r in range(reps): + for tag, v in (("a", im), ("b", ImageOps.mirror(im))): + bg = Image.new("RGB", (RES, RES), (0, 0, 0)); bg.paste(v, (0, 0), v) + stem = "%s_%d%s" % (base, r, tag) + bg.save(os.path.join(DS, stem + ".png")) + with io.open(os.path.join(DS, stem + ".txt"), "w", encoding="utf-8") as f: + f.write("%s, %s, %s, black background" % (TRIGGER, COMPOSE, e["caption"])) + n += 1 + print("dataset %s: %d images (원본 %d)" % (DS, n, len(data)), flush=True) + return n + + +def get(path): + return json.load(urllib.request.urlopen(HOST + path, timeout=120)) + + +def train(): + wf = { + "1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": CKPT}}, + "10": {"class_type": "LoraLoader", "inputs": {"model": ["1", 0], "clip": ["1", 1], "lora_name": BASE_LORA, "strength_model": BASE_LORA_STRENGTH, "strength_clip": BASE_LORA_STRENGTH}}, + "2": {"class_type": "LoadImageTextDataSetFromFolder", "inputs": {"folder": DS_NAME}}, + "3": {"class_type": "MakeTrainingDataset", "inputs": {"images": ["2", 0], "vae": ["1", 2], "clip": ["10", 1], "texts": ["2", 1]}}, + "4": {"class_type": "TrainLoraNode", "inputs": { + "model": ["10", 0], "latents": ["3", 0], "positive": ["3", 1], + "batch_size": BATCH, "grad_accumulation_steps": 1, "steps": STEPS, "learning_rate": LR, "rank": RANK, + "optimizer": "AdamW", "loss_function": "MSE", "seed": SEED, "training_dtype": "bf16", "lora_dtype": "bf16", + "quantized_backward": False, "algorithm": "LoRA", "gradient_checkpointing": True, "checkpoint_depth": 1, + "offloading": False, "existing_lora": "[None]", "bucket_mode": False, "bypass_mode": False}}, + "5": {"class_type": "SaveLoRA", "inputs": {"lora": ["4", 0], "prefix": "loras/" + NAME, "steps": ["4", 2]}}, + "6": {"class_type": "LossGraphNode", "inputs": {"loss": ["4", 1], "filename_prefix": NAME + "_loss"}}, + } + req = urllib.request.Request(HOST + "/prompt", data=json.dumps({"prompt": wf, "client_id": str(uuid.uuid4())}).encode(), headers={"Content-Type": "application/json"}) + try: + r = json.load(urllib.request.urlopen(req, timeout=60)) + except urllib.error.HTTPError as e: + print("PROMPT REJECTED:", e.read().decode(errors="replace")[:2000]); return None + if r.get("node_errors"): + print("NODE ERRORS:", json.dumps(r["node_errors"], ensure_ascii=False)[:2000]); return None + pid = r["prompt_id"] + print("queued %s · steps %d · batch %d · lr %s · rank %d" % (pid, STEPS, BATCH, LR, RANK), flush=True) + t0 = time.time() + while time.time() - t0 < 7200: + time.sleep(20) + h = get("/history/" + pid) + if pid in h: + st = h[pid].get("status", {}) + if st.get("status_str") == "error": + for m in st.get("messages", []): + if m[0] == "execution_error": + print("TRAIN ERROR:", m[1].get("node_type"), m[1].get("exception_message", "")[:1500]) + print("\n".join(m[1].get("traceback", [])[-6:])[:2000]) + return None + print("done in %.0fs" % (time.time() - t0), flush=True) + return h[pid]["outputs"] + print("TIMEOUT"); return None + + +if __name__ == "__main__": + if os.path.isdir(DS) and os.listdir(DS): + print("데이터셋 폴더가 이미 있다(버전 이름을 바꿔 다시 실행):", DS); sys.exit(1) + build_dataset() + if train() is None: + sys.exit(1) + files = sorted(glob.glob(os.path.join(LORA_OUT, NAME + "*.safetensors")), key=os.path.getmtime) + if not files: + print("no lora file in", LORA_OUT); sys.exit(1) + shutil.copy2(files[-1], LORA_DST) + print("LORA: %s -> %s (%.1f MB)" % (files[-1], LORA_DST, os.path.getsize(LORA_DST) / 2**20)) diff --git a/공유/기획/FirstRising/아이템/comfy_gii_style.py b/공유/기획/FirstRising/아이템/comfy_gii_style.py new file mode 100644 index 0000000..df46291 --- /dev/null +++ b/공유/기획/FirstRising/아이템/comfy_gii_style.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- +# 2026-10-01 PD 지시 — "game Icon Institute_anfg_v3-000018 로라를 적용해서 다시" · 트리거 "game icon institute, game icon, ahfg". +# 사이트 예시(직접 확인): 굵고 양식화된 손그림풍 MMO 아이콘 · 진한 채도 · 두꺼운 형태 · 발광 · 검은 배경. +# 앞선 결과가 얇고 사실적으로 나온 원인 = 기반 모델(제작자 권장 "游戏图标研究所 3.0" SD1.5 가 이 PC 에 없어 사실풍 difconsistency 로 대체). +# 여기서는 같은 기반에서 LoRA 를 더 세게 걸고(변형별 강도), 사실풍을 부정어로 누르고, 2배 다시 그리기를 빼서 LoRA 의 그림체를 최대한 살린다. +# python comfy_gii_style.py <출력폴더> [rembg 0|1] [시드 수] +import io, json, os, sys, time, uuid, urllib.request, urllib.parse +from PIL import Image, ImageDraw + +HOST = "http://127.0.0.1:8000" +CKPT = "difconsistencyCheckpoint_v10.safetensors" +LORA = "game Icon Institute_anfg_v3-000018.safetensors" # PD 가 loras 폴더에 넣어 둔 원래 이름의 파일 +TRIGGER = "game icon institute, game icon, ahfg" +# 페이지의 부정어 "(easynegative:0.8), black, dark, Low resolution" + 사실풍 누르기 +NEG = "black, dark, low resolution, worst quality, low quality, blurry, photo, photorealistic, realistic, 3d render, thin, text, watermark, signature, cropped, person, hands" + +SUBJECTS = [ + ("sword", "sword"), + ("blunt", "hammer, mace"), + ("bow", "bow"), + ("dagger", "dagger"), + ("staff", "staff, gem"), + ("magic_dagger", "dagger, glowing, gem"), + ("armor", "armor"), + ("belt", "belt"), + ("gloves", "gloves, gauntlets"), + ("boots", "boots"), + ("ring", "ring, gem"), + ("necklace", "necklace, gem"), + ("shield", "shield"), + ("quiver", "quiver, arrows"), + ("spellbook", "book"), + ("throwing", "shuriken"), + ("orb", "orb, crystal, glowing"), + ("offhand_sword", "short sword"), +] + + +def post(path, data): + req = urllib.request.Request(HOST + path, data=json.dumps(data).encode("utf-8"), headers={"Content-Type": "application/json"}) + return json.loads(urllib.request.urlopen(req, timeout=60).read()) + + +def get(path): + return urllib.request.urlopen(HOST + path, timeout=180).read() + + +def workflow(prompt, seed, strength, clip_skip, rembg): + wf = { + "1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": CKPT}}, + "2": {"class_type": "LoraLoader", "inputs": {"model": ["1", 0], "clip": ["1", 1], "lora_name": LORA, "strength_model": strength, "strength_clip": strength}}, + "3": {"class_type": "CLIPSetLastLayer", "inputs": {"clip": ["2", 1], "stop_at_clip_layer": clip_skip}}, + "4": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": prompt}}, + "5": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": NEG}}, + "6": {"class_type": "EmptyLatentImage", "inputs": {"width": 512, "height": 512, "batch_size": 1}}, + "7": {"class_type": "KSampler", "inputs": {"model": ["2", 0], "positive": ["4", 0], "negative": ["5", 0], "latent_image": ["6", 0], "seed": seed, "steps": 28, "cfg": 7.0, "sampler_name": "euler_ancestral", "scheduler": "normal", "denoise": 1.0}}, + "8": {"class_type": "VAEDecode", "inputs": {"samples": ["7", 0], "vae": ["1", 2]}}, + } + if rembg: + wf["12"] = {"class_type": "InspyrenetRembg", "inputs": {"image": ["8", 0], "torchscript_jit": "default"}} + wf["9"] = {"class_type": "SaveImage", "inputs": {"images": ["12", 0], "filename_prefix": "gii_style"}} + else: + wf["9"] = {"class_type": "SaveImage", "inputs": {"images": ["8", 0], "filename_prefix": "gii_style"}} + return wf + + +def run(prompt, seed, strength, clip_skip, rembg): + cid = str(uuid.uuid4()) + pid = post("/prompt", {"prompt": workflow(prompt, seed, strength, clip_skip, rembg), "client_id": cid})["prompt_id"] + t0 = time.time() + while time.time() - t0 < 900: + hist = json.loads(get("/history/" + pid)) + if pid in hist: + st = hist[pid].get("status", {}) + if st.get("status_str") == "error": + raise RuntimeError(json.dumps(st)[:800]) + outs = hist[pid].get("outputs", {}) + if outs: + for node in outs.values(): + for im in node.get("images", []): + q = urllib.parse.urlencode({"filename": im["filename"], "subfolder": im.get("subfolder", ""), "type": im.get("type", "output")}) + return Image.open(io.BytesIO(get("/view?" + q))).convert("RGBA") + time.sleep(1.2) + raise TimeoutError("comfy timeout") + + +def checker(size, n=16): + im = Image.new("RGB", (size, size), (58, 58, 58)) + d = ImageDraw.Draw(im) + for y in range(0, size, n): + for x in range(0, size, n): + if (x // n + y // n) % 2: + d.rectangle([x, y, x + n - 1, y + n - 1], fill=(74, 74, 74)) + return im + + +def main(): + out, tag = sys.argv[1], sys.argv[2] + strength, clip_skip = float(sys.argv[3]), int(sys.argv[4]) + rembg = int(sys.argv[5]) if len(sys.argv) > 5 else 0 + seeds = int(sys.argv[6]) if len(sys.argv) > 6 else 2 + lo = int(sys.argv[7]) if len(sys.argv) > 7 else 0 + hi = int(sys.argv[8]) if len(sys.argv) > 8 else len(SUBJECTS) + os.makedirs(out, exist_ok=True) + subs = SUBJECTS[lo:hi] + cell, pad, label = 200, 4, 16 + cols = 9 + rows = (len(subs) + cols - 1) // cols + sheet = Image.new("RGB", (cols * (cell + pad) + pad, rows * (seeds * (cell + pad) + label) + pad), (40, 40, 40)) + draw = ImageDraw.Draw(sheet) + for i, (name, body) in enumerate(subs): + prompt = "%s, %s, still life, black background" % (TRIGGER, body) + cx = pad + (i % cols) * (cell + pad) + cy = pad + (i // cols) * (seeds * (cell + pad) + label) + draw.text((cx + 3, cy + 2), name, fill=(240, 220, 160)) + for j in range(seeds): + t0 = time.time() + im = run(prompt, 5000 + (lo + i) * 17 + j * 307, strength, clip_skip, rembg) + print("%s %s #%d %.1f초" % (tag, name, j, time.time() - t0)); sys.stdout.flush() + im.save(os.path.join(out, "%s_%s_%d.png" % (tag, name, j))) + bg = checker(cell) if rembg else Image.new("RGB", (cell, cell), (0, 0, 0)) + small = im.resize((cell, cell), Image.LANCZOS) + bg.paste(small, (0, 0), small) + sheet.paste(bg, (cx, cy + label + j * (cell + pad))) + path = os.path.join(out, "%s_sheet.png" % tag) + sheet.save(path) + print("sheet", path) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/comfy_moba.py b/공유/기획/FirstRising/아이템/comfy_moba.py new file mode 100644 index 0000000..e10432b --- /dev/null +++ b/공유/기획/FirstRising/아이템/comfy_moba.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +# 2026-10-01 PD 지시 — 체크포인트 mobaGameEquipment_v10 으로 civitai 88908 "Moba game equipment icon" 풍의 아이콘을 만든다. 배경은 투명. +# 페이지 예시 그림의 설정(직접 확인): 프롬프트 "(masterpiece:1.2), (best quality:1.2), moba game icon, …" · 부정어 "lowres, bad anatomy, bad hands, text, error, …" · +# DPM++ 2M Karras · 30 steps · CFG 7 · clip skip 2 · 권장 해상도 512 / 768. 트리거 = moba game icon. +# python comfy_moba.py <출력폴더> [크기=768] [시드 수=2] [시작] [끝] [rembg=1] +import io, json, os, sys, time, uuid, urllib.request, urllib.parse +from PIL import Image, ImageDraw + +HOST = "http://127.0.0.1:8000" +CKPT = "mobaGameEquipment_v10.safetensors" +PREFIX = "(masterpiece:1.2), (best quality:1.2), moba game icon" +# 2차: 1차(768)에서 지팡이 · 목걸이 · 부츠 · 벨트가 인물로 나와 인물 부정어를 더했다 +NEG = "lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, 1girl, 1boy, person, human, character, face, hair, breasts, body, wearing" + +# FR 장비 전 부위(무기 6 · 방어구 4 · 장신구 2 · 보조 장비 6) +SUBJECTS = [ + ("sword", "sword"), + ("blunt", "war hammer, mace"), + ("bow", "bow"), + ("dagger", "dagger"), + ("staff", "magic staff"), + ("magic_dagger", "magic dagger, glowing blade"), + ("armor", "armor, breastplate"), + ("belt", "belt"), + ("gloves", "gauntlets, gloves"), + ("boots", "boots"), + ("ring", "ring"), + ("necklace", "necklace, pendant"), + ("shield", "shield"), + ("quiver", "quiver with arrows"), + ("spellbook", "spellbook, magic book"), + ("throwing", "shuriken, throwing blade"), + ("orb", "magic orb, crystal ball"), + ("offhand_sword", "short sword"), +] + + +def post(path, data): + req = urllib.request.Request(HOST + path, data=json.dumps(data).encode("utf-8"), headers={"Content-Type": "application/json"}) + return json.loads(urllib.request.urlopen(req, timeout=60).read()) + + +def get(path): + return urllib.request.urlopen(HOST + path, timeout=300).read() + + +def workflow(prompt, seed, size, rembg): + wf = { + "1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": CKPT}}, + "3": {"class_type": "CLIPSetLastLayer", "inputs": {"clip": ["1", 1], "stop_at_clip_layer": -2}}, + "4": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": prompt}}, + "5": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": NEG}}, + "6": {"class_type": "EmptyLatentImage", "inputs": {"width": size, "height": size, "batch_size": 1}}, + "7": {"class_type": "KSampler", "inputs": {"model": ["1", 0], "positive": ["4", 0], "negative": ["5", 0], "latent_image": ["6", 0], "seed": seed, "steps": 30, "cfg": 7.0, "sampler_name": "dpmpp_2m", "scheduler": "karras", "denoise": 1.0}}, + "8": {"class_type": "VAEDecode", "inputs": {"samples": ["7", 0], "vae": ["1", 2]}}, + } + if rembg: + wf["12"] = {"class_type": "InspyrenetRembg", "inputs": {"image": ["8", 0], "torchscript_jit": "default"}} + wf["9"] = {"class_type": "SaveImage", "inputs": {"images": ["12", 0], "filename_prefix": "moba"}} + else: + wf["9"] = {"class_type": "SaveImage", "inputs": {"images": ["8", 0], "filename_prefix": "moba"}} + return wf + + +def run(prompt, seed, size, rembg): + pid = post("/prompt", {"prompt": workflow(prompt, seed, size, rembg), "client_id": str(uuid.uuid4())})["prompt_id"] + t0 = time.time() + while time.time() - t0 < 900: + hist = json.loads(get("/history/" + pid)) + if pid in hist: + st = hist[pid].get("status", {}) + if st.get("status_str") == "error": + raise RuntimeError(json.dumps(st)[:900]) + for node in hist[pid].get("outputs", {}).values(): + for im in node.get("images", []): + q = urllib.parse.urlencode({"filename": im["filename"], "subfolder": im.get("subfolder", ""), "type": im.get("type", "output")}) + return Image.open(io.BytesIO(get("/view?" + q))).convert("RGBA") + time.sleep(1.2) + raise TimeoutError("comfy timeout") + + +def checker(size, n=16): + im = Image.new("RGB", (size, size), (58, 58, 58)) + d = ImageDraw.Draw(im) + for y in range(0, size, n): + for x in range(0, size, n): + if (x // n + y // n) % 2: + d.rectangle([x, y, x + n - 1, y + n - 1], fill=(74, 74, 74)) + return im + + +def main(): + out, tag = sys.argv[1], sys.argv[2] + size = int(sys.argv[3]) if len(sys.argv) > 3 else 768 + seeds = int(sys.argv[4]) if len(sys.argv) > 4 else 2 + lo = int(sys.argv[5]) if len(sys.argv) > 5 else 0 + hi = int(sys.argv[6]) if len(sys.argv) > 6 else len(SUBJECTS) + rembg = int(sys.argv[7]) if len(sys.argv) > 7 else 1 + os.makedirs(out, exist_ok=True) + subs = SUBJECTS[lo:hi] + cell, pad, label, cols = 200, 4, 16, 9 + rows = (len(subs) + cols - 1) // cols + sheet = Image.new("RGB", (cols * (cell + pad) + pad, rows * (seeds * (cell + pad) + label) + pad), (40, 40, 40)) + draw = ImageDraw.Draw(sheet) + for i, (name, body) in enumerate(subs): + # 2차: 대상이 장식에 묻혀 가중치를 주고, 물건 하나만 가운데 오게 적는다 + prompt = "%s, (%s:1.35), no humans, single item, centered, still life" % (PREFIX, body) + cx = pad + (i % cols) * (cell + pad) + cy = pad + (i // cols) * (seeds * (cell + pad) + label) + draw.text((cx + 3, cy + 2), name, fill=(240, 220, 160)) + for j in range(seeds): + t0 = time.time() + im = run(prompt, 9000 + (lo + i) * 23 + j * 401, size, rembg) + print("%s %s #%d %.1f초" % (tag, name, j, time.time() - t0)); sys.stdout.flush() + im.save(os.path.join(out, "%s_%s_%d.png" % (tag, name, j))) + bg = checker(cell) + small = im.resize((cell, cell), Image.LANCZOS) + bg.paste(small, (0, 0), small) + sheet.paste(bg, (cx, cy + label + j * (cell + pad))) + path = os.path.join(out, "%s_sheet.png" % tag) + sheet.save(path) + print("sheet", path) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/comfy_moba_anfg.py b/공유/기획/FirstRising/아이템/comfy_moba_anfg.py new file mode 100644 index 0000000..5f2ebbe --- /dev/null +++ b/공유/기획/FirstRising/아이템/comfy_moba_anfg.py @@ -0,0 +1,451 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지시 — "내가 원하는 아트풍은 첨부한 아트풍(Game Icon Research Institute LoRA-ANFG_V3 예시)인데, 우리 프로젝트의 원본 에셋이 너무 실사풍이라…" +# → 원본 에셋을 따라 칠하는 방식(comfy_moba_repaint*.py)은 실사풍을 그대로 끌고 오므로 방향이 틀렸다. +# 여기서는 원본 에셋을 쓰지 않고, 양식화된 게임 아이콘 기반 모델(mobaGameEquipment_v10) 위에 ANFG v3 LoRA 를 얹어 글자만으로 뽑는다. +# (10-01 시도는 기반이 실사풍 difconsistency 였다 — 얇고 사실적으로 나와 PD 가 반려. 이 조합은 처음이다.) +# python comfy_moba_anfg.py <출력폴더> [LoRA 강도들 "0.7,1.0"] [시드 수=2] [크기=512] [다듬기 0|1] +import io, json, os, sys, time, uuid, urllib.parse +from PIL import Image, ImageDraw +import comfy_moba_repaint as base # 통신 · 바둑판 바탕은 앞선 스크립트의 것을 쓴다 + +CKPT = "mobaGameEquipment_v10.safetensors" +LORA = "giI_anfg_v3_000018.safetensors" +TRIGGER = "game icon institute, game icon, ahfg" # PD 가 알려 준 트리거 +NEG = ("(worst quality, low quality:1.3), lowres, text, watermark, signature, blurry, photo, realistic, photorealistic, 3d render, thin, " + "1girl, 1boy, person, human, face, body, multiple objects, duplicate, frame, border, circle background") +UPSCALER = "4x-UltraSharp.pth" +# 2026-10-02 PD 지적 — a2 선별본(final_sheet)이 "너무 캐주얼한 느낌". 예시는 어두운 금속 · 정교한 장식 · 깊은 명암의 MMORPG 풍인데 +# a2 는 묘사가 단순하고(금 반지 + 붉은 보석) 다듬기(0.35)가 면을 매끈하게 밀어 만화풍이 됐다. +# 분위기 사전 설정(환경변수 ANFG_TONE): 프롬프트 뒤에 붙는 낱말 · 부정어에 더하는 낱말. 다듬기 세기는 ANFG_REFINE(기본 0.35). +TONES = { + "": ("", ""), + "epic": (", epic fantasy mmorpg equipment, ornate, intricate engraved details, dark metal, painterly shading, dramatic lighting, deep shadows, glowing accents", + ", cartoon, casual, cute, chibi, toy, flat color, simple design, cel shading, thick outline"), + # a4(epic) 검토: 명암 · 질감은 목표에 가까워졌으나 형태가 녹고(반지 → 가면, 벨트 → 칼날) 빛 번짐 · 잘림이 늘었다. LoRA 1.0 은 형태가 더 녹는다. + # refined: PD 가 고른 것의 공통점(실제 장비 비례 · 얇은 외곽선 · 면 안의 명암 단계 · 금 + 한 색)을 낱말로 옮기고, 발광 · 원색 · 굵은 외곽선을 부정어로 누른다. + "refined": (", realistic proportions, clean sharp edges, crisp silhouette, polished metal, subtle painterly shading, thin outline, soft studio light", + ", cartoon, casual, cute, chibi, toy, flat color, thick black outline, neon colors, oversized gem, glow, bloom, smoke, flame, motion blur, cropped, cut off"), + # a9 검토: 형태는 길잡이로 풀렸고 남은 걸림돌은 "단순함"(도형에 색만 입힌 수준 · 명암 단계가 적어 플라스틱 느낌 · 정면 평면 구도). + # rich: 장식 밀도와 명암을 올린다. 길잡이 ControlNet 은 일찍 풀어(끝 0.35) 모델이 장식을 덧붙일 여지를 준다. + # a10 검토: 단검 · 방패는 장식 · 명암이 PD 합격본 수준에 근접. 다만 ControlNet 끝 0.35 는 24장 중 약 10장이 길잡이를 벗어났고(활 → 덩어리, 반지 → 메달), + # "embedded gemstones" 는 망치 머리 · 반지 안을 통보석으로 만들었고, "three-quarter view" 는 효과가 약했다 → 두 낱말을 빼고 끝을 0.5 로(가는 종류는 0.6). ANFG 는 0.7 고정(0.9 는 형태가 녹는다). + "rich": (", ornate fantasy design, engraved filigree, layered metal plates, crisp silhouette, clean sharp edges, " + "detailed painterly shading, painterly brush strokes, strong highlights and deep shadows, dark ambient occlusion", + ", cartoon, casual, cute, chibi, toy, plastic, glossy plastic, plain, simple design, flat color, flat front view, thick black outline, neon colors, glow, bloom, smoke, flame, motion blur, cropped, cut off, " + "round medallion, coin, disc, close-up"), + # a14 검토: 배색 · 외곽선 · 밝기는 PD 합격본과 한 세트. 남은 차이 = 손그림 붓결과 깊은 그림자(깨끗한 그라데이션 + 흰 하이라이트 띠가 지배적). + # paint: 붓결 · 무광 · 어두운 바탕색 쪽 낱말로 바꾸고, 매끈함 · 광택을 부정어로 누른다(다듬기 방식 비교와 함께 a16 에서 시험). + "paint": (", ornate fantasy design, engraved filigree, layered metal plates, crisp silhouette, hand painted texture, visible painterly brush strokes, " + "matte dark metal, deep shadows, dark ambient occlusion, rich muted colors, strong rim light, specular highlights, high contrast", + ", cartoon, casual, cute, chibi, toy, plastic, glossy plastic, plain, simple design, flat color, flat front view, thick black outline, neon colors, glow, bloom, smoke, flame, motion blur, cropped, cut off, " + "round medallion, coin, disc, close-up, smooth gradient, airbrushed, shiny, white highlight band, 3d render, purple, magenta, pink"), +} +# 구도 낱말(맨 앞) — 분위기 설정이 있을 때만 붙인다(a1 · a2 재현을 깨지 않게) +COMPOSE = "single item, centered, full object in frame, wide margin, " +TONE = os.environ.get("ANFG_TONE", "") +REFINE = float(os.environ.get("ANFG_REFINE", "0.35")) +# 자체 학습 LoRA(comfy_anfg_train.py 가 만든 FR_anfg_<버전>)를 ANFG LoRA 위에 함께 건다 — 환경변수 ANFG_LORA2 = "파일이름:강도". 걸면 트리거 fricon 을 앞에 붙인다. +LORA2 = os.environ.get("ANFG_LORA2", "") +# 1024 로 키우는 방식: model = 4x-UltraSharp(선명하지만 면을 매끈하게 민다) · lanczos = 단순 확대 뒤 다듬기에서 모델이 다시 칠하게 둔다(붓결을 살리려는 시험) +UPSCALE = os.environ.get("ANFG_UPSCALE", "model") + +# PD 가 보여 준 예시와 같은 종류(반지 · 투구 · 장갑 · 갑옷 · 목걸이) + FR 부위(검 · 부츠 · 벨트) +SUBJECTS = [ + ("ring", "a blue dragon head ring, silver scales, glowing cyan"), + ("helmet", "a red and gold horned helmet"), + ("gloves", "a single armored gauntlet, dark steel with gold trim and purple gem"), + ("armor", "a red and gold chest armor with shoulder plates"), + ("necklace", "a red gem pendant necklace with gold wings"), + ("sword", "a broad sword, blue glowing blade, gold hilt"), + ("boots", "a pair of armored boots, blue and gold"), + ("belt", "a leather belt with large gold buckle and red gem"), +] + + +# FR 장비 전 부위(무기 6 · 방어구 4 · 장신구 2 · 보조 장비 8) — a1 에서 형태가 약했던 벨트 · 검 · 장갑은 낱말을 구체적으로 바꿨다 +SUBJECTS_FR = [ + ("sword", "a single longsword, steel blade, gold crossguard, blue gem, full weapon in frame"), + ("blunt", "a single war hammer, heavy steel head with gold trim, full weapon in frame"), + ("bow", "a single recurve bow, wooden with gold tips and green gem, full weapon in frame"), + ("dagger", "a single dagger, curved steel blade, red gem pommel, full weapon in frame"), + ("staff", "a single magic staff, gold top holding a purple crystal, full weapon in frame"), + ("magic_dagger", "a single magic dagger, glowing green crystal blade, gold hilt, full weapon in frame"), + ("armor", "a red and gold chest armor with shoulder plates"), + ("belt", "a waist belt, wide brown leather strap loop, large round gold buckle with red gem"), + ("gloves", "a pair of armored gloves, steel fingers, gold trim, purple gem"), + ("boots", "a pair of armored boots, blue and gold"), + ("ring", "a gold ring with a large red gemstone"), + ("necklace", "a blue gem pendant necklace with gold chain"), + ("shield", "a kite shield, blue steel with gold rim and lion emblem"), + ("quiver", "a leather quiver full of arrows, gold trim"), + ("spellbook", "a closed thick spellbook, purple cover, gold corners, glowing gem"), + ("throwing", "a four pointed steel shuriken with gold center"), + ("orb", "a glowing cyan crystal orb held in a gold claw stand"), + ("offhand_sword", "a single short sword, wide blade, gold hilt, full weapon in frame"), + ("totem", "a carved wooden totem with glowing green runes and feathers"), + ("horn", "a gold trimmed war horn"), +] + + +# a2 검토(직접 봄): 풍은 일정하나 긴 무기(둔기 · 활 · 지팡이 · 화살통)가 전부 검 모양으로 쏠리고, 장식 테두리 · 화면 밖 잘림이 섞였다. +# a3: FR 원본 아이콘에서 "윤곽선만" 빌려 형태를 잡는다(색 · 질감은 가져오지 않으므로 실사풍이 따라오지 않는다). (이름, 묘사, 윤곽을 빌릴 원본 번호) +SUBJECTS_SHAPE = [ + ("blunt", "a war hammer, heavy steel head with gold trim and blue gem, brown handle", 1015), + ("mace", "a flanged mace, gold and steel head with red gem, dark handle", 1057), + ("bow", "a recurve bow, green and gold limbs, thin bowstring", 1029), + ("dagger", "a dagger, steel blade, gold guard, red gem", 1043), + ("sword", "a short sword, blue steel blade, gold crossguard", 1435), + ("belt1", "a leather belt, brown strap, gold buckle with red gem", 1337), + ("belt2", "a leather belt, dark strap, gold skull buckle, cyan gems", 1351), + ("belt3", "a leather belt with gold plates and hanging chains, cyan gems", 1309), + ("gloves1", "a pair of armored gloves, purple leather, gold trim, glowing runes", 1169), + ("gloves2", "a pair of steel gauntlets, gold trim, red gems", 1211), + ("boots1", "a pair of armored boots, blue and gold", 1393), + ("boots2", "a pair of high plate boots, red and gold", 1421), + ("armor1", "a chest armor, red and gold plates, shoulder pauldrons", 1253), + ("armor2", "a chest armor, blue steel and gold, fur collar, cyan gem", 1239), + ("necklace1", "a round amulet, gold rim, glowing cyan gem", 1099), + ("necklace2", "a shield shaped pendant, silver and gold, blue gem", 1113), +] +# a5 검토(에이전트가 직접 봄): 글자만으로는 검 · 단검 · 갑옷 · 장화만 안정. 둔기 · 활 · 지팡이 · 화살통 · 뿔피리 등은 칼날 모양으로 쏠리고, 벨트 · 투척 · 방패는 원형 바탕이 붙는다. +# SUBJECTS_ALL: (이름, 묘사, 윤곽 원본 번호 또는 None, 종류별 부정어). 묘사 · 부정어는 a5 검토의 수정안을 반영했다. +SUBJECTS_ALL = [ + ("sword", "a single longsword, steel blade, gold crossguard, blue gem, full weapon in frame", None, "two blades"), + ("blunt", "a one-handed flanged mace, heavy spiked steel head with gold trim on a short handle", 1057, "sword, blade"), + ("hammer", "a war hammer, heavy block steel head with gold trim and blue gem, brown wooden handle", 1015, "sword, blade"), + ("bow", "a recurve bow, curved wooden limbs with gold tips, thin taut bowstring, side view", 1029, "sword, blade, shield, arrow, harp, panel, banner, sail"), + ("dagger", "a single dagger, curved steel blade, red gem pommel, full weapon in frame", None, "two blades"), + ("staff", "a long wooden wizard staff, full length visible, purple crystal on top, diagonal", None, "sword, blade, scepter"), + ("magic_dagger", "a single magic dagger, green crystal blade, gold hilt, full weapon in frame", None, "two blades, floating orbs"), + ("armor", "a red and gold chest armor with shoulder plates", None, ""), + ("belt", "a leather waist belt laid flat as a horizontal strap, large gold buckle in the center, red leather", 1337, "ring, circle, pants, torso, round frame"), + ("gloves", "a single armored gauntlet, five fingers, steel plate glove with gold trim, wrist cuff", None, "boot, bare hand"), + ("boots", "a pair of armored boots, blue and gold", None, ""), + ("ring", "a gold ring with a large red gemstone, closed circular finger ring band", None, "ribbon, broken ring"), + ("necklace", "a pendant necklace, short closed chain loop fully visible, blue gem pendant with gold setting", None, "bottle, wings, cropped chain"), + ("shield", "a kite shield, plain blue field with gold rim and central boss, three-quarter view, small in frame", None, "lion, animal, face, crest, round frame"), + ("quiver", "a leather quiver full of arrows, feathered arrow shafts sticking out of the top, shoulder strap", None, "sword, blade"), + ("spellbook", "a closed thick spellbook, purple cover, gold corner clasps, gem on the front cover, three-quarter view", None, "open book, scroll"), + ("throwing", "a single steel throwing knife, kunai, small leaf shaped blade with ring pommel", None, "shuriken, star, disc, wheel, round frame"), + ("orb", "a crystal ball, deep blue glass sphere on a small gold stand", None, "cyan, teal, horns"), + ("offhand_sword", "a short parrying dagger, main-gauche, wide curved gold handguard, whole weapon in frame", None, "two blades"), + ("totem", "a small carved wooden idol statue, tribal face, gold bands, red gem eyes", None, "green glow, neon, pillar, column, round frame"), + ("horn", "a curved ivory war horn, blowing horn, gold rim bands, leather strap", None, "axe, blade, trumpet, all gold"), +] +# 초안 방식(draft): 물건을 정확히 아는 실사풍 모델로 먼저 "형태 초안"을 그리고, 그 초안의 윤곽선만 ControlNet 으로 넘겨 ANFG 풍으로 새로 그린다. +# 색 · 질감은 넘어가지 않으므로 실사풍이 따라오지 않고, 글자만으로는 못 잡던 형태(활 · 화살통 · 뿔피리 등)를 잡는다 — 어떤 장비든 글자로 뽑기 위한 방법. +DRAFT_CKPT = "difconsistencyCheckpoint_v10.safetensors" +DRAFT_NEG = "person, human, hand, character, multiple objects, text, watermark, frame, border, cropped, cut off, blurry, lowres" + + +def add_draft(wf, desc, seed, cn_strength, cn_end): + """형태 초안(d*) → 굵은 선화 → ControlNet 을 글자 조건(4 · 5)에 걸어 샘플러(7)에 물린다.""" + wf["d1"] = {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": DRAFT_CKPT}} + wf["d4"] = {"class_type": "CLIPTextEncode", "inputs": {"clip": ["d1", 1], "text": "%s, single object, centered, whole object visible, wide margin, game item concept art, plain dark background" % desc}} + wf["d5"] = {"class_type": "CLIPTextEncode", "inputs": {"clip": ["d1", 1], "text": DRAFT_NEG}} + wf["d6"] = {"class_type": "EmptyLatentImage", "inputs": {"width": 512, "height": 512, "batch_size": 1}} + wf["d7"] = {"class_type": "KSampler", "inputs": {"model": ["d1", 0], "positive": ["d4", 0], "negative": ["d5", 0], "latent_image": ["d6", 0], "seed": seed + 7, + "steps": 24, "cfg": 7.0, "sampler_name": "dpmpp_2m", "scheduler": "karras", "denoise": 1.0}} + wf["d8"] = {"class_type": "VAEDecode", "inputs": {"samples": ["d7", 0], "vae": ["d1", 2]}} + wf["d9"] = {"class_type": "SaveImage", "inputs": {"images": ["d8", 0], "filename_prefix": "moba_anfg_draft"}} + wf["30"] = {"class_type": "ControlNetLoader", "inputs": {"control_net_name": CN_LINEART}} + wf["31"] = {"class_type": "LineArtPreprocessor", "inputs": {"image": ["d8", 0], "coarse": "enable", "resolution": 512}} + wf["32"] = {"class_type": "ControlNetApplyAdvanced", "inputs": {"positive": ["4", 0], "negative": ["5", 0], "control_net": ["30", 0], "image": ["31", 0], + "strength": cn_strength, "start_percent": 0.0, "end_percent": cn_end, "vae": ["1", 2]}} + wf["7"]["inputs"]["positive"] = ["32", 0]; wf["7"]["inputs"]["negative"] = ["32", 1] + return wf + + +# 길잡이 모음 방식(lib): icon_shapes.py 가 만든 moba_anfg/shapes/<종류>__<출처>.png 의 윤곽선으로 형태를 잡는다(a6 검토에서 가장 정확했던 방식). +# 종류별 묘사의 {pal} 자리에 색 조합을 돌려 넣어, 같은 형태라도 다른 디자인이 나오게 한다(학습 데이터가 한 색으로 쏠리지 않게). +TYPE_DESC = { + "sword": "a longsword, ornate engraved steel blade with a fuller, dark steel shading, ornate crossguard, {pal}", + "dagger": "a dagger, engraved steel blade with a fuller, dark steel shading, ornate hilt and crossguard, {pal}", + "blunt": "a flanged mace, heavy spiked metal head on a short handle, {pal}", + "hammer": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, {pal}", + "axe": "a single-bladed battle axe, solid broad axe head attached to the shaft, engraved steel blade, dark steel shading, wooden shaft with metal fittings, {pal}", + "bow": "an ornate recurve bow, carved limbs with gold filigree fittings, gem at the wrapped grip, thin bowstring, {pal}", + "staff": "a wizard staff, long shaft, glowing crystal head ornament, {pal}", + "armor": "a chest armor, layered plates, shoulder pauldrons, {pal}", + "helmet": "a knight helmet, visor, crest, {pal}", + "belt": "a waist belt, leather strap, large ornate buckle, {pal}", + "gloves": "a pair of armored gauntlets, plated fingers, wrist cuffs, {pal}", + "boots": "a pair of armored boots, plated shins, {pal}", + "ring": "a finger ring, large faceted gemstone, engraved band, {pal}", + "necklace": "a pendant amulet, faceted gem in an ornate setting, {pal}", + "shield": "a shield, metal rim, central emblem boss, {pal}", + "quiver": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, {pal}", + "spellbook": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, {pal}", + "throwing": "a throwing blade, kunai, sharp steel, {pal}", + "orb": "a crystal orb, glass sphere on an ornate stand, {pal}", + "totem": "a carved wooden totem, stacked tribal faces, small wings, {pal}", + "horn": "a curved war horn, ivory body, metal rim bands, {pal}", +} +# PD 가 고른 것 = 금 + 적 또는 금 + 청 + 은빛 금속. 그 둘을 앞에 두고 나머지로 폭을 넓힌다. +# a7 검토: 여섯 색을 돌리니 청록 · 보라 · 초록 단색 칠이 40% 쯤 나와 불합격이 늘었다 → 금을 늘 넣고 한 색만 더한다. 은 단색은 세트에서 차갑게 떠서 뺐다. +PALETTES = ["gold and crimson red with silver steel", "gold and royal blue with silver steel", "gold trim on dark steel with red gems", "gold trim on silver steel with blue gems"] +# a21 뒤 최상급 점검(검토): 세트로는 묶이지만 목표 풍과 다른 점 = 원색 파랑이 전면(30장 중 약 20장) · 목표는 어둡고 채도 낮은 바탕에 포인트만 빛난다. +# ANFG_PAL=dark 이면 어두운 바탕색 + 작은 강조색 조합을 쓴다(PD 에게 방향 비교로 보여 줄 시험용 — PD 가 고른 합격본은 금 + 적/청의 밝은 쪽이다). +if os.environ.get("ANFG_PAL", "") == "dark": + PALETTES = ["dark steel with antique gold trim and a small glowing blue gem accent", "dark iron and antique gold with deep crimson accents", + "blackened steel with bronze trim and a small glowing red gem accent", "dark silver and antique gold with deep blue enamel accents"] +# 2026-10-03 PD 지적 — "붉은색 · 푸른색 같은 원색 계열만 쓰고 있어서 색감이 풍부하지 않고 저급해 보인다" + 레퍼런스(핀터레스트 → ArtStation "RPG Weapon Icons 02", Olekzandr Zahorulko). +# 레퍼런스에서 본 것: 색이 "칠"이 아니라 "재질"에서 나온다(강철 회색 · 나무 갈색 · 가죽 · 뼈 · 청동 · 녹슨 쇠). 원색은 물건 전체가 아니라 작은 강조(감은 끈 · 보석 · 마법 빛)에만, +# 그 강조색이 물건마다 다르다(청록 · 보라 · 초록 · 주황 · 분홍 · 하늘). 어두운 바탕 위에서 명암 폭이 넓다. +# 우리 문제: 색 조합이 "금 + 적 / 금 + 청" 넷뿐이고 물건 전체를 그 색 에나멜로 칠한다 · 자체 LoRA v4 가 그 배색으로 학습돼 더 끌어당긴다. +# ANFG_PAL=material: 재질 조합(몸체) × 강조색(작은 부분)을 따로 돌린다 → 조합 수가 많아 물건마다 색이 달라진다. +MATERIALS = ["weathered steel and dark walnut wood", "dark iron and worn brown leather", "aged bronze and bone ivory", "blackened steel and antique brass", + "pale silver and deep burgundy leather", "tarnished copper and dark oak wood", "gunmetal grey steel and tan leather wraps", "antique gold and dark slate grey steel"] +ACCENTS = ["a small emerald green gem accent", "a small amethyst purple gem accent", "a small teal cyan glowing accent", "a small amber orange gem accent", + "a small ruby red gem accent", "a small sapphire blue gem accent", "a small jade green inlay accent", "a small rose pink crystal accent", + "a small turquoise inlay accent", "a small pale moonstone white gem accent"] +if os.environ.get("ANFG_PAL", "") == "material": + # a25(PM 이 비교 시트를 직접 봄): 반지 · 벨트 · 방패 · 목걸이 · 망치 · 검은 재질색 + 작은 강조로 잘 나왔으나, 갑옷 · 장화 · 투구는 강조색이 몸체 전체를 덮었다(보라 갑옷 · 초록 투구). + # → 재질에 가중치를 주고 "몸체는 재질색, 강조는 작은 보석 하나"임을 낱말로 못박는다. + PALETTES = ["(body made of %s:1.25), natural material colors, %s only" % (m, ACCENTS[(k * 3 + j) % len(ACCENTS)]) for j in range(5) for k, m in enumerate(MATERIALS)] +# a26 검토(에이전트 + PM 이 최상급 24장 직접 확인): 원색 문제는 약 70% 에서 풀리고 세트가 확실히 풍부해졌다. 남은 문제 — +# ① 재질 낱말이 엉뚱한 부위에 붙는다(나무 칼날 · 나무 투구 · 뼈 벨트) ② 장식 밀도가 줄어 민무늬 면이 늘었다 ③ 갈색 쪽으로 쏠려 차가운 재질이 적다 ④ 일부는 여전히 한 색이 몸체를 덮는다. +# ANFG_PAL=parts: 재질을 "부위"에 묶는다. TYPE_PARTS 의 묘사에 {metal}(주 금속) · {metal2}(장식 금속) · {soft}(가죽/나무/천) · {accent}(작은 강조색) 자리를 두고 따로 돌린다. +METALS = ["weathered steel", "blued steel", "dark iron", "aged bronze", "verdigris bronze", "pale silver", "blackened steel", "antique gold", "tarnished copper", "gunmetal grey steel"] +METALS2 = ["antique brass trim", "silver trim", "antique gold trim", "dark iron rivets and trim", "bronze trim"] +SOFTS = ["dark walnut wood", "worn brown leather", "deep burgundy leather", "tan leather wraps", "dark oak wood", "teal leather wrap", "black leather", "bone ivory"] +ACCENTS2 = ["a small emerald green gem", "a small amethyst purple gem", "a small turquoise inlay", "a small amber orange gem", "a small ruby red gem", + "a small sapphire blue gem", "a small jade green inlay", "a small moonstone white gem", "a small topaz yellow gem", "a small garnet dark red gem"] +ORNATE = "engraved filigree, etched runes, rivets, worn edges, fine scratches" +TYPE_PARTS = { + "sword": "a longsword, {metal} blade with a fuller, {metal2} crossguard, {soft} wrapped grip, {accent} in the pommel", + "dagger": "a dagger, {metal} blade with a fuller, {metal2} crossguard, {soft} wrapped grip, {accent} in the pommel", + "axe": "a single-bladed battle axe, solid broad {metal} axe head attached to the shaft, {soft} shaft with {metal2}, {accent} on the axe head", + "blunt": "a flanged mace, heavy spiked {metal} head, {soft} wrapped handle with {metal2}, {accent} on the head", + "hammer": "a war hammer, heavy block {metal} head with banded ends, {soft} wrapped handle with {metal2}, {accent} on the head", + "bow": "an ornate recurve bow, carved {soft} limbs with {metal} fittings, wrapped grip, thin bowstring, {accent} at the grip", + "staff": "a wizard staff, long {soft} shaft with {metal} fittings, crystal head ornament, {accent} glowing softly", + "armor": "a chest armor, layered {metal} plates with {metal2}, {soft} straps, shoulder pauldrons, {accent} on the chest", + "helmet": "a knight helmet, {metal} plates with {metal2}, visor, crest, {accent} on the brow", + "belt": "a waist belt, {soft} strap, large ornate {metal} buckle with {metal2}, {accent} in the buckle", + "gloves": "a pair of armored gauntlets, {metal} plated fingers with {metal2}, {soft} cuffs, {accent} on the back of the hand", + "boots": "a pair of armored boots, {metal} plated shins with {metal2}, {soft} boot, {accent} on the shin", + "ring": "a finger ring, engraved {metal} band with {metal2}, {accent} in an ornate setting", + "necklace": "a pendant amulet, {metal} ornate setting with {metal2}, {accent} in the center", + "shield": "a shield, {metal} rim with {metal2}, {soft} covered face, central emblem boss, {accent} on the boss", + "quiver": "a quiver full of arrows, {soft} body with {metal} fittings, feathered arrows sticking out, shoulder strap, {accent} on the fitting", + "spellbook": "a closed spellbook, thick tome, {soft} cover, {metal} corner clasps, {accent} on the cover", + "throwing": "a throwing blade, kunai, sharp {metal} blade, {soft} wrapped grip, {accent} on the ring pommel", + "orb": "a crystal orb, glass sphere on an ornate {metal} stand with {metal2}, {accent} glow inside the sphere", + "totem": "a carved totem, {soft} body with stacked tribal faces, {metal} bands, small wings, {accent} eyes", + "horn": "a curved war horn, bone ivory body, {metal} rim bands with {metal2}, {soft} strap, {accent} on the band", +} +PARTS = os.environ.get("ANFG_PAL", "") == "parts" + + +def parts_desc(kind, n): + """종류 kind 의 n 번째 색 조합 묘사 — 금속 · 장식 금속 · 부드러운 재질 · 강조색을 서로 다른 걸음으로 돌려 겹치지 않게 한다""" + return TYPE_PARTS[kind].format(metal=METALS[n % len(METALS)], metal2=METALS2[(n // 2) % len(METALS2)], + soft=SOFTS[(n * 3 + 1) % len(SOFTS)], accent=ACCENTS2[(n * 7 + 2) % len(ACCENTS2)]) + ", " + ORNATE + + +# 색을 누르는 부정어(재질 조합일 때만 붙인다) +MATERIAL_NEG = ", saturated primary colors, blue enamel, red enamel, fully blue, fully red, all gold, monochrome gold, two-tone color scheme, candy colors, fully purple, fully green, fully teal, colored metal plates, painted armor, colored enamel body, red armor, magenta, wooden blade, circular background, glow outline, halo" +SHAPES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "moba_anfg", "shapes") +# icon_make.py 가 적는 종류별 묘사(새 종류 · 묘사 고침)를 표에 합친다 +_DESC_JSON = os.path.join(os.path.dirname(os.path.abspath(__file__)), "moba_anfg", "type_desc.json") +if os.path.exists(_DESC_JSON): + TYPE_DESC.update(json.load(io.open(_DESC_JSON, encoding="utf-8"))) + + +def lib_subjects(): + """길잡이 모음의 그림마다 대상 한 줄: (이름 = 종류-출처, 묘사, 길잡이 경로, 부정어, 종류)""" + import glob + neg = dict((x[0], x[3]) for x in SUBJECTS_ALL) + subs = [] + act = os.path.join(SHAPES_DIR, "active.txt") # icon_shapes.py 가 적는 "지금 쓰는 길잡이" 목록 + names = io.open(act, encoding="utf-8").read().split() if os.path.exists(act) else [os.path.basename(f) for f in sorted(glob.glob(os.path.join(SHAPES_DIR, "*__*.png")))] + for k, path in enumerate(os.path.join(SHAPES_DIR, n) for n in names): + kind, label = os.path.basename(path)[:-4].split("__", 1) + if kind in TYPE_DESC: + subs.append((kind + "-" + label.replace("_", ""), TYPE_DESC[kind], path, neg.get(kind, ""), kind)) + return subs + + +SRC = base.SRC +CN_LINEART = "control_v11p_sd15_lineart_fp16.safetensors" +FRAME_NEG = ", ornate frame, picture frame, card, corner ornaments, vignette, ring shaped background, out of frame" + + +def shape_image(gid, fit=0.72): + """원본 아이콘을 1024 캔버스 가운데에 여백을 넉넉히 두고 놓는다(윤곽 추출용 · 여백이 곧 완성본의 여백)""" + im = Image.open(os.path.join(SRC, "%d.png" % gid)).convert("RGBA") + box = im.getchannel("A").getbbox() + if box: + im = im.crop(box) + scale = 1024 * fit / float(max(im.size)) + im = im.resize((max(1, int(im.width * scale)), max(1, int(im.height * scale))), Image.LANCZOS) + rgb = Image.new("RGB", (1024, 1024), base.BG) + rgb.paste(im, ((1024 - im.width) // 2, (1024 - im.height) // 2), im) + return rgb + + +def add_shape(wf, image_name, cn_strength, cn_end): + """글자 조건(4 · 5)에 윤곽 ControlNet 을 걸어 샘플러(7 · 44)에 물린다. 굵은 선(coarse)만 써서 세부는 모델이 새로 그리게 둔다.""" + wf["22"] = {"class_type": "LoadImage", "inputs": {"image": image_name}} + wf["30"] = {"class_type": "ControlNetLoader", "inputs": {"control_net_name": CN_LINEART}} + wf["31"] = {"class_type": "LineArtPreprocessor", "inputs": {"image": ["22", 0], "coarse": "enable", "resolution": 768}} + wf["32"] = {"class_type": "ControlNetApplyAdvanced", "inputs": {"positive": ["4", 0], "negative": ["5", 0], "control_net": ["30", 0], "image": ["31", 0], + "strength": cn_strength, "start_percent": 0.0, "end_percent": cn_end, "vae": ["1", 2]}} + wf["7"]["inputs"]["positive"] = ["32", 0]; wf["7"]["inputs"]["negative"] = ["32", 1] + return wf + + +def workflow(prompt, seed, strength, size, refine, extra_neg=""): + wf = { + "1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": CKPT}}, + "2": {"class_type": "LoraLoader", "inputs": {"model": ["1", 0], "clip": ["1", 1], "lora_name": LORA, "strength_model": strength, "strength_clip": strength}}, + "3": {"class_type": "CLIPSetLastLayer", "inputs": {"clip": ["2", 1], "stop_at_clip_layer": -2}}, + "4": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": prompt}}, + "5": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": NEG + FRAME_NEG + (TONES[TONE][1].replace(", purple, magenta, pink", "") if os.environ.get("ANFG_PAL", "") in ("material", "parts") else TONES[TONE][1]) + (MATERIAL_NEG if os.environ.get("ANFG_PAL", "") in ("material", "parts") else "") + ((", " + extra_neg) if extra_neg else "")}}, + "6": {"class_type": "EmptyLatentImage", "inputs": {"width": size, "height": size, "batch_size": 1}}, + "7": {"class_type": "KSampler", "inputs": {"model": ["2", 0], "positive": ["4", 0], "negative": ["5", 0], "latent_image": ["6", 0], "seed": seed, + "steps": 30, "cfg": 7.0, "sampler_name": "dpmpp_2m", "scheduler": "karras", "denoise": 1.0}}, + "8": {"class_type": "VAEDecode", "inputs": {"samples": ["7", 0], "vae": ["1", 2]}}, + } + model = ["2", 0] + if LORA2: + name2, strength2 = LORA2.rsplit(":", 1) + wf["2b"] = {"class_type": "LoraLoaderModelOnly", "inputs": {"model": ["2", 0], "lora_name": name2, "strength_model": float(strength2)}} + model = ["2b", 0] + wf["7"]["inputs"]["model"] = model + last = "8" + if refine: + # 4배 확대 → 1024 → 약하게 다듬기(세부 선명도) + wf["40"] = {"class_type": "UpscaleModelLoader", "inputs": {"model_name": UPSCALER}} + wf["41"] = {"class_type": "ImageUpscaleWithModel", "inputs": {"upscale_model": ["40", 0], "image": ["8", 0]}} + wf["42"] = {"class_type": "ImageScale", "inputs": {"image": ["41", 0] if UPSCALE == "model" else ["8", 0], "upscale_method": "lanczos", "width": 1024, "height": 1024, "crop": "disabled"}} + if UPSCALE != "model": + del wf["40"]; del wf["41"] + wf["43"] = {"class_type": "VAEEncode", "inputs": {"pixels": ["42", 0], "vae": ["1", 2]}} + wf["44"] = {"class_type": "KSampler", "inputs": {"model": model, "positive": ["4", 0], "negative": ["5", 0], "latent_image": ["43", 0], "seed": seed + 1, + "steps": 24, "cfg": 7.0, "sampler_name": "dpmpp_2m", "scheduler": "karras", "denoise": REFINE}} + wf["45"] = {"class_type": "VAEDecode", "inputs": {"samples": ["44", 0], "vae": ["1", 2]}} + last = "45" + wf["12"] = {"class_type": "InspyrenetRembg", "inputs": {"image": [last, 0], "torchscript_jit": "default"}} + wf["9"] = {"class_type": "SaveImage", "inputs": {"images": ["12", 0], "filename_prefix": "moba_anfg"}} + return wf + + +def run(wf, want="9"): + pid = base.post("/prompt", {"prompt": wf, "client_id": str(uuid.uuid4())})["prompt_id"] + t0 = time.time() + while time.time() - t0 < 900: + hist = json.loads(base.get("/history/" + pid)) + if pid in hist: + st = hist[pid].get("status", {}) + if st.get("status_str") == "error": + raise RuntimeError(json.dumps(st)[:1500]) + for nid, node in hist[pid].get("outputs", {}).items(): + if nid != want: + continue + for im in node.get("images", []): + q = urllib.parse.urlencode({"filename": im["filename"], "subfolder": im.get("subfolder", ""), "type": im.get("type", "output")}) + return Image.open(io.BytesIO(base.get("/view?" + q))).convert("RGBA") + time.sleep(1.0) + raise TimeoutError("comfy timeout") + + +# a12 검토: 가는 무기(검 · 단검 · 도끼 · 활 · 지팡이 …)는 512 에서 날이 흰 납작면으로 뭉개진다 → 768 로 그리고(모델 권장 크기), 길잡이를 끝까지 더 오래 잡는다(끝 0.7). +THIN = ("sword", "dagger", "axe", "bow", "staff", "throwing", "blunt", "hammer", "magic_dagger", "offhand_sword") +THIN_SIZE = int(os.environ.get("ANFG_THIN_SIZE", "768")) +SEED_BASE = int(os.environ.get("ANFG_SEED", "0")) # 회차마다 다른 시드를 쓰려면 바꾼다 + + +def hash_name(name): + """종류 이름으로 시드를 흩는다(표의 순서가 바뀌어도 같은 종류는 같은 시드)""" + return sum(ord(c) * (k + 3) for k, c in enumerate(name)) % 9973 + + +def main(): + out, tag = sys.argv[1], sys.argv[2] + strengths = [float(v) for v in (sys.argv[3] if len(sys.argv) > 3 else "0.7,1.0").split(",")] + seeds = int(sys.argv[4]) if len(sys.argv) > 4 else 2 + size = int(sys.argv[5]) if len(sys.argv) > 5 else 512 + refine = int(sys.argv[6]) if len(sys.argv) > 6 else 0 + global SUBJECTS + mode = sys.argv[7] if len(sys.argv) > 7 else "" + cn_strength = float(sys.argv[8]) if len(sys.argv) > 8 else 0.6 + cn_end = float(sys.argv[9]) if len(sys.argv) > 9 else 0.6 + if mode == "fr": + SUBJECTS = SUBJECTS_FR + elif mode == "shape": + SUBJECTS = SUBJECTS_SHAPE + elif mode in ("all", "draft", "allshape"): + SUBJECTS = SUBJECTS_ALL + elif mode == "lib": + SUBJECTS = lib_subjects() + only = os.environ.get("ANFG_ONLY", "") # 쉼표로 적은 종류만 돌린다 + if only: + SUBJECTS = [x for x in SUBJECTS if x[0].split("-")[0] in only.split(",")] + skip = os.environ.get("ANFG_SKIP", "") # 행 이름에 이 글자가 들어 있으면 뺀다(예: genpd — PD 합격본 윤곽 길잡이는 복제를 만든다) + if skip: + SUBJECTS = [x for x in SUBJECTS if not any(k in x[0] for k in skip.split(","))] + rows = os.environ.get("ANFG_ROWS", "") # 쉼표로 적은 행 이름(종류-길잡이)만 돌린다 + if rows: + SUBJECTS = [x for x in SUBJECTS if x[0] in rows.split(",")] + os.makedirs(out, exist_ok=True) + cols = len(strengths) * seeds + cell, pad, left = 220, 4, 80 + sheet = Image.new("RGB", (left + cols * (cell + pad) + pad, len(SUBJECTS) * (cell + pad) + pad), (24, 24, 28)) + draw = ImageDraw.Draw(sheet) + for i, sub in enumerate(SUBJECTS): + name, desc = sub[0], sub[1] + extra_neg = sub[3] if len(sub) > 3 else "" + use_shape = len(sub) > 2 and sub[2] and mode in ("shape", "allshape") + shape = base.upload(shape_image(sub[2]), "bt_anfg_shape_%d.png" % sub[2]) if use_shape else None + if mode == "lib": + guide = Image.open(sub[2]).convert("RGB") + if "-genpd" in name: + # a11 검토: PD 합격본의 윤곽을 그대로 넘기면 색만 바뀐 복제가 나온다 → 좌우를 뒤집어 넘긴다 + guide = guide.transpose(Image.FLIP_LEFT_RIGHT) + shape = base.upload(guide, "bt_anfg_lib_%s.png" % name) + y = pad + i * (cell + pad) + draw.text((pad, y + 4), name, fill=(240, 220, 160)) + col = 0 + for s in strengths: + for j in range(seeds): + fn = "%s_%s_s%02d_%d.png" % (tag, name, int(s * 10), j) + # 길잡이 모음 방식은 그림마다 색 조합을 돌린다(종류 안 순번 + 시드 순번 + 회차 시드) + d1 = desc.format(pal=PALETTES[(i * 7 + j * 3 + SEED_BASE) % len(PALETTES)]) if "{pal}" in desc else desc + if PARTS and name.split("-")[0] in TYPE_PARTS: + d1 = parts_desc(name.split("-")[0], i * 7 + j * 3 + SEED_BASE) + prompt = "%s, %s%s, simple background, black background, no humans" % (("fricon, " if LORA2 else "") + TRIGGER, (COMPOSE if TONE else "") + d1, TONES[TONE][0]) + # 이미 만든 그림은 다시 만들지 않는다(끊겨도 이어서 돌린다) + if os.path.exists(os.path.join(out, fn)): + im = Image.open(os.path.join(out, fn)).convert("RGBA") + else: + # 종류 표가 정해진 예전 회차(a1 · a2)는 순번 시드를 그대로 쓴다(재현). 새 표는 이름으로 흩는다. + seed = (50000 + i * 37 + j * 733) if mode in ("", "fr", "shape") else (50000 + SEED_BASE + hash_name(name) + j * 733) + kind = name.split("-")[0] + wf = workflow(prompt, seed, s, THIN_SIZE if kind in THIN else size, refine, extra_neg) + if shape: + # Layer Lab 길잡이는 캐주얼한 세부가 새므로 약하게 걸어 큰 윤곽만 잡는다 + weak = mode == "lib" and "-ll" in name + # 가는 형태(반지 · 활 · 지팡이 · 투척)는 ControlNet 을 일찍 풀면 다른 물건이 된다 — 끝을 0.6 아래로 내리지 않는다 + end = max(cn_end, 0.7) if kind in THIN else (max(cn_end, 0.6) if kind == "ring" else cn_end) + add_shape(wf, shape, 0.4 if weak else cn_strength, 0.4 if weak else end) + elif mode == "draft": + add_draft(wf, d1, seed, cn_strength, cn_end) + im = run(wf) + im.save(os.path.join(out, fn)) + # 학습 캡션으로 쓸 묘사를 곁파일로 남긴다(icon_dataset.py 가 읽는다) + with io.open(os.path.join(out, fn[:-4] + ".txt"), "w", encoding="utf-8") as f: + f.write(d1) + # 예시와 견주기 쉽게 어두운 바탕에 올린다 + bg = Image.new("RGB", (cell, cell), (12, 12, 14)); small = im.resize((cell, cell), Image.LANCZOS); bg.paste(small, (0, 0), small) + sheet.paste(bg, (left + col * (cell + pad), y)) + draw.text((left + col * (cell + pad) + 3, y + 2), "LoRA %.1f #%d" % (s, j), fill=(200, 200, 200)) + col += 1 + print("%s %s" % (tag, name)); sys.stdout.flush() + sheet.save(os.path.join(out, "%s_sheet.png" % tag)) + print("sheet", os.path.join(out, "%s_sheet.png" % tag)) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/comfy_moba_batch.py b/공유/기획/FirstRising/아이템/comfy_moba_batch.py new file mode 100644 index 0000000..c0a22b2 --- /dev/null +++ b/공유/기획/FirstRising/아이템/comfy_moba_batch.py @@ -0,0 +1,164 @@ +# -*- coding: utf-8 -*- +# 2026-10-01 PD 지시 — mobaGameEquipment_v10 결과 36장 중 "쓸 만한 것"은 3장(초록 마법 단검 · 은색 갑옷 · 갈색 부츠)뿐. +# 합격 기준(PD 가 고른 3장의 공통점): 물건 하나가 따로 떨어져 있다 · 원형 바탕/후광/딸린 조각이 없다 · 전체가 여백 안에 들어온다. +# 방법: 대상마다 여러 장을 뽑고(장당 약 7초), 투명도(알파)로 자동 채점해 기준에 맞는 것만 추린다 → 추린 것을 사람이 본다. +# python comfy_moba_batch.py <출력폴더> <대상당 장수> [시작] [끝] +# 자동 채점(배경 제거 뒤 알파 기준): +# · 불투명 비율 6~42% (원형 바탕이 붙으면 50% 를 넘는다) · 가장자리 닿음 1.5% 이하(잘림) · 가장 큰 덩어리가 불투명의 88% 이상(딸린 조각 없음) +import io, json, os, sys, time, uuid, urllib.request, urllib.parse +from collections import deque +from PIL import Image, ImageDraw + +HOST = "http://127.0.0.1:8000" +CKPT = "mobaGameEquipment_v10.safetensors" +PREFIX = "(masterpiece:1.2), (best quality:1.2), moba game icon" +NEG = ("lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, " + "1girl, 1boy, person, human, character, face, hair, breasts, body, wearing, mannequin, bust, " + "circle, round frame, border, badge, emblem, aura, halo, light rays, glowing background, explosion, fire background, " + "multiple objects, two weapons, crossed weapons, duplicate, out of frame") + +# 1 · 2차에서 형태가 약했던 대상은 낱말을 구체적으로 바꿨다(활 · 벨트 · 목걸이 · 화살통 · 반지 · 둔기 · 투척) +SUBJECTS = [ + ("sword", "longsword"), + ("blunt", "one-handed war hammer"), + ("bow", "longbow, wooden bow with bowstring"), + ("dagger", "dagger"), + ("staff", "magic staff with crystal"), + ("magic_dagger", "magic dagger, glowing blade"), + ("armor", "plate armor, breastplate"), + ("belt", "leather belt with metal buckle"), + ("gloves", "gauntlets"), + ("boots", "leather boots"), + ("ring", "gold ring with gemstone"), + ("necklace", "amulet, pendant with gem on chain"), + ("shield", "shield"), + ("quiver", "arrow quiver, leather tube holding arrows"), + ("spellbook", "closed spellbook, thick book"), + ("throwing", "throwing knife"), + ("orb", "crystal orb"), + ("offhand_sword", "short sword"), +] + + +def post(path, data): + req = urllib.request.Request(HOST + path, data=json.dumps(data).encode("utf-8"), headers={"Content-Type": "application/json"}) + return json.loads(urllib.request.urlopen(req, timeout=60).read()) + + +def get(path): + return urllib.request.urlopen(HOST + path, timeout=300).read() + + +def workflow(prompt, seed): + return { + "1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": CKPT}}, + "3": {"class_type": "CLIPSetLastLayer", "inputs": {"clip": ["1", 1], "stop_at_clip_layer": -2}}, + "4": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": prompt}}, + "5": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": NEG}}, + "6": {"class_type": "EmptyLatentImage", "inputs": {"width": 512, "height": 512, "batch_size": 1}}, + "7": {"class_type": "KSampler", "inputs": {"model": ["1", 0], "positive": ["4", 0], "negative": ["5", 0], "latent_image": ["6", 0], "seed": seed, "steps": 30, "cfg": 7.0, "sampler_name": "dpmpp_2m", "scheduler": "karras", "denoise": 1.0}}, + "8": {"class_type": "VAEDecode", "inputs": {"samples": ["7", 0], "vae": ["1", 2]}}, + "12": {"class_type": "InspyrenetRembg", "inputs": {"image": ["8", 0], "torchscript_jit": "default"}}, + "9": {"class_type": "SaveImage", "inputs": {"images": ["12", 0], "filename_prefix": "moba_batch"}}, + } + + +def run(prompt, seed): + pid = post("/prompt", {"prompt": workflow(prompt, seed), "client_id": str(uuid.uuid4())})["prompt_id"] + t0 = time.time() + while time.time() - t0 < 600: + hist = json.loads(get("/history/" + pid)) + if pid in hist: + st = hist[pid].get("status", {}) + if st.get("status_str") == "error": + raise RuntimeError(json.dumps(st)[:900]) + for node in hist[pid].get("outputs", {}).values(): + for im in node.get("images", []): + q = urllib.parse.urlencode({"filename": im["filename"], "subfolder": im.get("subfolder", ""), "type": im.get("type", "output")}) + return Image.open(io.BytesIO(get("/view?" + q))).convert("RGBA") + time.sleep(1.0) + raise TimeoutError("comfy timeout") + + +def score(im): + """알파로 채점 — (합격 여부, 불투명 비율, 가장자리 닿음 비율, 가장 큰 덩어리 비율)""" + n = 96 + a = im.getchannel("A").resize((n, n), Image.BILINEAR) + px = a.load() + solid = [[px[x, y] > 40 for x in range(n)] for y in range(n)] + total = sum(sum(1 for v in row if v) for row in solid) + if total == 0: + return False, 0.0, 0.0, 0.0 + opaque = total / float(n * n) + edge = sum(1 for i in range(n) if solid[0][i]) + sum(1 for i in range(n) if solid[n - 1][i]) + sum(1 for i in range(n) if solid[i][0]) + sum(1 for i in range(n) if solid[i][n - 1]) + edge_ratio = edge / float(4 * n) + seen = [[False] * n for _ in range(n)] + best = 0 + for y in range(n): + for x in range(n): + if solid[y][x] and not seen[y][x]: + q = deque([(x, y)]); seen[y][x] = True; size = 0 + while q: + cx, cy = q.popleft(); size += 1 + for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)): + nx, ny = cx + dx, cy + dy + if 0 <= nx < n and 0 <= ny < n and solid[ny][nx] and not seen[ny][nx]: + seen[ny][nx] = True; q.append((nx, ny)) + best = max(best, size) + main = best / float(total) + ok = 0.06 <= opaque <= 0.42 and edge_ratio <= 0.015 and main >= 0.88 + return ok, opaque, edge_ratio, main + + +def checker(size, n=16): + im = Image.new("RGB", (size, size), (58, 58, 58)) + d = ImageDraw.Draw(im) + for y in range(0, size, n): + for x in range(0, size, n): + if (x // n + y // n) % 2: + d.rectangle([x, y, x + n - 1, y + n - 1], fill=(74, 74, 74)) + return im + + +def main(): + out, tag, count = sys.argv[1], sys.argv[2], int(sys.argv[3]) + lo = int(sys.argv[4]) if len(sys.argv) > 4 else 0 + hi = int(sys.argv[5]) if len(sys.argv) > 5 else len(SUBJECTS) + os.makedirs(out, exist_ok=True) + subs = SUBJECTS[lo:hi] + show = 6 + cell, pad, label = 170, 4, 16 + sheet = Image.new("RGB", (pad + 110 + show * (cell + pad), len(subs) * (cell + pad) + pad), (40, 40, 40)) + draw = ImageDraw.Draw(sheet) + report = [] + for i, (name, body) in enumerate(subs): + prompt = "%s, (%s:1.35), no humans, single item, isolated, centered, full object in frame, simple background, still life" % (PREFIX, body) + passed = [] + t0 = time.time() + for j in range(count): + im = run(prompt, 12000 + (lo + i) * 29 + j * 503) + ok, opaque, edge, mainc = score(im) + fn = "%s_%s_%02d%s.png" % (tag, name, j, "" if ok else "_x") + im.save(os.path.join(out, fn)) + if ok: + passed.append((mainc - abs(opaque - 0.24), fn, im)) + passed.sort(key=lambda t: -t[0]) + report.append((name, len(passed), count)) + print("%s %s 합격 %d/%d (%.0f초)" % (tag, name, len(passed), count, time.time() - t0)); sys.stdout.flush() + y = pad + i * (cell + pad) + draw.text((pad, y + 4), name, fill=(240, 220, 160)) + draw.text((pad, y + 22), "%d/%d" % (len(passed), count), fill=(200, 200, 200)) + for k, (_, fn, im) in enumerate(passed[:show]): + bg = checker(cell) + small = im.resize((cell, cell), Image.LANCZOS) + bg.paste(small, (0, 0), small) + sheet.paste(bg, (pad + 110 + k * (cell + pad), y)) + draw.text((pad + 112 + k * (cell + pad), y + 2), fn[len(tag) + len(name) + 2:len(tag) + len(name) + 4], fill=(255, 255, 255)) + path = os.path.join(out, "%s_pass_sheet_%d_%d.png" % (tag, lo, hi)) + sheet.save(path) + print("sheet", path) + print("요약", ", ".join("%s %d/%d" % r for r in report)) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/comfy_moba_lora_test.py b/공유/기획/FirstRising/아이템/comfy_moba_lora_test.py new file mode 100644 index 0000000..b9bade1 --- /dev/null +++ b/공유/기획/FirstRising/아이템/comfy_moba_lora_test.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지시 — 학습한 FR_moba_v1 LoRA 검증. 학습에 없던 대상(반지 · 방패 · 화살통 · 오브 · 마법책 · 지팡이 · 활 · 표창 등)을 글자만으로 뽑아 +# 통일된 풍 · 물건 하나 · 투명 배경으로 나오는지 본다. +# python comfy_moba_lora_test.py <출력폴더> [LoRA 강도=1.0] [시드 수=2] +import io, json, os, sys, time, uuid, urllib.request, urllib.parse +from PIL import Image, ImageDraw + +HOST = "http://127.0.0.1:8000" +CKPT = "mobaGameEquipment_v10.safetensors" +LORA = "FR_moba_v1.safetensors" +TRIGGER = "frmoba, moba game icon" +NEG = ("lowres, text, error, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, " + "1girl, 1boy, person, human, character, face, circle, round frame, border, badge, emblem, aura, halo, light rays, glowing background, multiple objects, duplicate") + +# 앞 8 = 학습에 없던 새 대상(보조 장비 · 반지 등), 뒤 4 = 학습에 있던 부위의 새 디자인 +SUBJECTS = [ + ("ring", "a dark iron ring with an orange glowing gem"), + ("shield", "a dark steel kite shield with gold trim"), + ("quiver", "a brown leather quiver full of arrows"), + ("spellbook", "a closed dark leather spellbook with gold corners and a cyan gem"), + ("orb", "a cyan glowing crystal orb held in a dark iron claw"), + ("throwing", "a dark steel throwing knife with a ring pommel"), + ("staff", "a dark wooden magic staff with a cyan crystal on top"), + ("offhand_sword", "a short sword with a gold hilt"), + ("sword", "a dark steel longsword with an orange gem in the guard"), + ("bow", "a dark wooden recurve bow with gold tips"), + ("armor", "a dark plate armor with gold trim and an orange gem"), + ("boots", "a pair of dark plate boots with gold trim"), +] + + +def post(path, data): + req = urllib.request.Request(HOST + path, data=json.dumps(data).encode("utf-8"), headers={"Content-Type": "application/json"}) + return json.loads(urllib.request.urlopen(req, timeout=60).read()) + + +def get(path): + return urllib.request.urlopen(HOST + path, timeout=300).read() + + +def workflow(prompt, seed, strength): + return { + "1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": CKPT}}, + "2": {"class_type": "LoraLoaderModelOnly", "inputs": {"model": ["1", 0], "lora_name": LORA, "strength_model": strength}}, + "3": {"class_type": "CLIPSetLastLayer", "inputs": {"clip": ["1", 1], "stop_at_clip_layer": -2}}, + "4": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": prompt}}, + "5": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": NEG}}, + "6": {"class_type": "EmptyLatentImage", "inputs": {"width": 512, "height": 512, "batch_size": 1}}, + "7": {"class_type": "KSampler", "inputs": {"model": ["2", 0], "positive": ["4", 0], "negative": ["5", 0], "latent_image": ["6", 0], "seed": seed, "steps": 30, "cfg": 7.0, "sampler_name": "dpmpp_2m", "scheduler": "karras", "denoise": 1.0}}, + "8": {"class_type": "VAEDecode", "inputs": {"samples": ["7", 0], "vae": ["1", 2]}}, + "12": {"class_type": "InspyrenetRembg", "inputs": {"image": ["8", 0], "torchscript_jit": "default"}}, + "9": {"class_type": "SaveImage", "inputs": {"images": ["12", 0], "filename_prefix": "moba_lora_test"}}, + } + + +def run(prompt, seed, strength): + pid = post("/prompt", {"prompt": workflow(prompt, seed, strength), "client_id": str(uuid.uuid4())})["prompt_id"] + t0 = time.time() + while time.time() - t0 < 600: + hist = json.loads(get("/history/" + pid)) + if pid in hist: + st = hist[pid].get("status", {}) + if st.get("status_str") == "error": + raise RuntimeError(json.dumps(st)[:900]) + for node in hist[pid].get("outputs", {}).values(): + for im in node.get("images", []): + q = urllib.parse.urlencode({"filename": im["filename"], "subfolder": im.get("subfolder", ""), "type": im.get("type", "output")}) + return Image.open(io.BytesIO(get("/view?" + q))).convert("RGBA") + time.sleep(1.0) + raise TimeoutError("comfy timeout") + + +def checker(size, n=16): + im = Image.new("RGB", (size, size), (58, 58, 58)) + d = ImageDraw.Draw(im) + for y in range(0, size, n): + for x in range(0, size, n): + if (x // n + y // n) % 2: + d.rectangle([x, y, x + n - 1, y + n - 1], fill=(74, 74, 74)) + return im + + +def main(): + out, tag = sys.argv[1], sys.argv[2] + strength = float(sys.argv[3]) if len(sys.argv) > 3 else 1.0 + seeds = int(sys.argv[4]) if len(sys.argv) > 4 else 2 + os.makedirs(out, exist_ok=True) + cell, pad, label = 160, 4, 16 + sheet = Image.new("RGB", (len(SUBJECTS) * (cell + pad) + pad, seeds * (cell + pad) + label + pad), (40, 40, 40)) + draw = ImageDraw.Draw(sheet) + for i, (name, desc) in enumerate(SUBJECTS): + prompt = "%s, %s, black background" % (TRIGGER, desc) + draw.text((pad + i * (cell + pad) + 3, 2), name, fill=(240, 220, 160)) + for j in range(seeds): + im = run(prompt, 30000 + i * 31 + j * 607, strength) + im.save(os.path.join(out, "%s_%s_%d.png" % (tag, name, j))) + bg = checker(cell); small = im.resize((cell, cell), Image.LANCZOS); bg.paste(small, (0, 0), small) + sheet.paste(bg, (pad + i * (cell + pad), label + j * (cell + pad))) + print("%s %s" % (tag, name)); sys.stdout.flush() + path = os.path.join(out, "%s_sheet.png" % tag) + sheet.save(path) + print("sheet", path) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/comfy_moba_lora_train.py b/공유/기획/FirstRising/아이템/comfy_moba_lora_train.py new file mode 100644 index 0000000..46a2da4 --- /dev/null +++ b/공유/기획/FirstRising/아이템/comfy_moba_lora_train.py @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지시 — "…합격 기준에 드는 것들을 통일감 있게 만들어. 그리고 나서 최종 결과물을 학습시켜." +# FR 장비 아이콘을 MOBA 풍으로 다시 칠해 고른 그림(comfy_moba_repaint.py → picked/)으로 스타일 LoRA 를 학습한다. +# 1) 데이터셋: 고른 그림(아이콘당 2장)을 검정 바탕 512² 로 합성, 원본 · 좌우 반전 2벌 + 캡션 .txt → C:\Comfyui\input\fr_moba_v1 +# 2) 학습: mobaGameEquipment_v10 · LoRA rank 16 · lr 4e-4 · batch 2 · N step(기본 600) → output/loras → models/loras/FR_moba_v1.safetensors +# python comfy_moba_lora_train.py [steps] +# 학습 노드 구성 · 입력 이름은 앞선 FR_icons_v1 학습(comfy_lora_train.py · 2026-09-25 실측)과 같다. +import io, json, os, re, shutil, sys, time, uuid, glob, urllib.request +from PIL import Image, ImageOps + +HOST = "http://127.0.0.1:8000" +PICKED = sys.argv[1] +STEPS = int(sys.argv[2]) if len(sys.argv) > 2 else 600 +DS_NAME = "fr_moba_v1" +DS = os.path.join(r"C:\Comfyui\input", DS_NAME) +LORA_OUT = r"C:\Comfyui\output\loras" +LORA_DST = os.path.join(r"C:\Comfyui\models\loras", "FR_moba_v1.safetensors") +CKPT = "mobaGameEquipment_v10.safetensors" +TRIGGER = "frmoba" # 화풍을 묶는 트리거 낱말 +RES = 512 +LR, RANK, BATCH, SEED = 4e-4, 16, 2, 11 + + +def load_captions(): + """아이콘 번호 → 내용 설명 표는 comfy_lora_train.py 의 CAP 을 그대로 읽는다(표를 두 벌로 두지 않는다).""" + text = io.open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "comfy_lora_train.py"), encoding="utf-8").read() + m = re.search(r"CAP = \{(.*?)\n\}", text, re.S) + return eval("{" + m.group(1) + "}") + + +def build_dataset(): + cap = load_captions() + if os.path.isdir(DS): + # 같은 이름의 예전 데이터셋은 통째로 바꾼다(학습 입력은 다시 만들 수 있는 파생물) + for f in os.listdir(DS): + os.remove(os.path.join(DS, f)) + os.makedirs(DS, exist_ok=True) + n = 0 + for path in sorted(glob.glob(os.path.join(PICKED, "*.png"))): + base = os.path.splitext(os.path.basename(path))[0] # "<번호>_<순번>" + gid = int(base.split("_")[0]) + if gid not in cap: + continue + im = Image.open(path).convert("RGBA").resize((RES, RES), Image.LANCZOS) + for tag, v in (("a", im), ("b", ImageOps.mirror(im))): + bg = Image.new("RGB", (RES, RES), (0, 0, 0)); bg.paste(v, (0, 0), v) + bg.save(os.path.join(DS, "%s_%s.png" % (base, tag))) + with io.open(os.path.join(DS, "%s_%s.txt" % (base, tag)), "w", encoding="utf-8") as f: + f.write("%s, moba game icon, %s, black background" % (TRIGGER, cap[gid])) + n += 1 + print("dataset %s: %d images" % (DS, n), flush=True) + return n + + +def get(path): + return json.load(urllib.request.urlopen(HOST + path, timeout=120)) + + +def train(): + wf = { + "1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": CKPT}}, + "2": {"class_type": "LoadImageTextDataSetFromFolder", "inputs": {"folder": DS_NAME}}, + "3": {"class_type": "MakeTrainingDataset", "inputs": {"images": ["2", 0], "vae": ["1", 2], "clip": ["1", 1], "texts": ["2", 1]}}, + "4": {"class_type": "TrainLoraNode", "inputs": { + "model": ["1", 0], "latents": ["3", 0], "positive": ["3", 1], + "batch_size": BATCH, "grad_accumulation_steps": 1, "steps": STEPS, "learning_rate": LR, "rank": RANK, + "optimizer": "AdamW", "loss_function": "MSE", "seed": SEED, "training_dtype": "bf16", "lora_dtype": "bf16", + "quantized_backward": False, "algorithm": "LoRA", "gradient_checkpointing": True, "checkpoint_depth": 1, + "offloading": False, "existing_lora": "[None]", "bucket_mode": False, "bypass_mode": False}}, + "5": {"class_type": "SaveLoRA", "inputs": {"lora": ["4", 0], "prefix": "loras/FR_moba_v1", "steps": ["4", 2]}}, + "6": {"class_type": "LossGraphNode", "inputs": {"loss": ["4", 1], "filename_prefix": "FR_moba_v1_loss"}}, + } + req = urllib.request.Request(HOST + "/prompt", data=json.dumps({"prompt": wf, "client_id": str(uuid.uuid4())}).encode(), headers={"Content-Type": "application/json"}) + try: + r = json.load(urllib.request.urlopen(req, timeout=60)) + except urllib.error.HTTPError as e: + print("PROMPT REJECTED:", e.read().decode(errors="replace")[:1500]); return None + if r.get("node_errors"): + print("NODE ERRORS:", json.dumps(r["node_errors"], ensure_ascii=False)[:1500]); return None + pid = r["prompt_id"] + print("queued %s · steps %d · batch %d · lr %s · rank %d" % (pid, STEPS, BATCH, LR, RANK), flush=True) + t0 = time.time() + while time.time() - t0 < 5400: + time.sleep(20) + h = get("/history/" + pid) + if pid in h: + st = h[pid].get("status", {}) + if st.get("status_str") == "error": + for m in st.get("messages", []): + if m[0] == "execution_error": + print("TRAIN ERROR:", m[1].get("node_type"), m[1].get("exception_message", "")[:1500]) + print("\n".join(m[1].get("traceback", [])[-6:])[:2000]) + return None + print("done in %.0fs" % (time.time() - t0), flush=True) + return h[pid]["outputs"] + print("TIMEOUT"); return None + + +if __name__ == "__main__": + build_dataset() + out = train() + if out is None: + sys.exit(1) + files = sorted(glob.glob(os.path.join(LORA_OUT, "FR_moba_v1*.safetensors")), key=os.path.getmtime) + if not files: + print("no lora file in", LORA_OUT); sys.exit(1) + shutil.copy2(files[-1], LORA_DST) + print("LORA: %s -> %s (%.1f MB)" % (files[-1], LORA_DST, os.path.getsize(LORA_DST) / 2**20)) diff --git a/공유/기획/FirstRising/아이템/comfy_moba_repaint.py b/공유/기획/FirstRising/아이템/comfy_moba_repaint.py new file mode 100644 index 0000000..f24f6ea --- /dev/null +++ b/공유/기획/FirstRising/아이템/comfy_moba_repaint.py @@ -0,0 +1,193 @@ +# -*- coding: utf-8 -*- +# 2026-10-01 PD 지시 — "우리 게임의 장비 아이콘 리소스를 기준으로 moba풍으로 다시 칠하도록 … 로라로 학습 가능한 수준으로 이미지를 뽑아내고 +# 합격 기준에 드는 것들을 통일감 있게 만들어. 그리고 나서 최종 결과물을 학습시켜." +# 1단계(이 스크립트): FR 장비 아이콘 원본(형태)을 입력으로 넣고 mobaGameEquipment_v10 이 그 위에 MOBA 풍을 다시 칠한다(이미지 투 이미지). +# 형태는 원본이 정하므로 글자 프롬프트만 쓸 때의 형태 실패가 없다. 다시 칠하는 세기(denoise) 2종 × 시드 3 = 아이콘당 6 후보. +# 배경 제거 뒤 자동 채점: 원본 실루엣과의 겹침(IoU) · 덩어리 하나 · 가장자리 안 닿음. 아이콘마다 점수순으로 한 줄(원본 | 후보)을 만든다. +# python comfy_moba_repaint.py <출력폴더> [시작] [끝] [세기들 "0.5,0.65"] [시드 수=3] +import io, json, os, re, sys, time, uuid, urllib.request, urllib.parse +from collections import deque +from PIL import Image, ImageDraw + +HOST = "http://127.0.0.1:8000" +CKPT = "mobaGameEquipment_v10.safetensors" +SRC = r"C:\BurningTimes\FirstRising\Assets\GameAssets\UI\EquipmentItemIcon" # FR 장비 아이콘 원본(1024 · 투명 배경) +PREFIX = "(masterpiece:1.2), (best quality:1.2), moba game icon" +NEG = ("lowres, text, error, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, " + "1girl, 1boy, person, human, character, face, " + "circle, round frame, border, badge, emblem, aura, halo, light rays, glowing background, explosion, multiple objects, duplicate") +RES = 512 +BG = (16, 16, 20) # 입력 바탕 — 어두운 단색(배경 제거가 깔끔하고, 모델이 원형 바탕을 덜 만든다) +FIT = 0.80 # 캔버스에서 아이콘이 차지하는 비율(여백 확보 — 합격 기준 "전체가 여백 안에") + + +def load_captions(): + """앞선 학습 스크립트(comfy_lora_train.py)의 CAP 표(아이콘 번호 → 내용 설명)를 그대로 읽는다 — 표를 두 벌로 두지 않는다.""" + text = io.open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "comfy_lora_train.py"), encoding="utf-8").read() + m = re.search(r"CAP = \{(.*?)\n\}", text, re.S) + return eval("{" + m.group(1) + "}") + + +def post(path, data): + req = urllib.request.Request(HOST + path, data=json.dumps(data).encode("utf-8"), headers={"Content-Type": "application/json"}) + return json.loads(urllib.request.urlopen(req, timeout=60).read()) + + +def get(path): + return urllib.request.urlopen(HOST + path, timeout=300).read() + + +def upload(image, name): + """ComfyUI 입력 폴더로 그림을 올린다(multipart) — LoadImage 가 이 이름으로 읽는다.""" + buf = io.BytesIO(); image.save(buf, "PNG"); data = buf.getvalue() + boundary = "----bt" + uuid.uuid4().hex + body = b"".join([ + ("--%s\r\nContent-Disposition: form-data; name=\"image\"; filename=\"%s\"\r\nContent-Type: image/png\r\n\r\n" % (boundary, name)).encode(), data, b"\r\n", + ("--%s\r\nContent-Disposition: form-data; name=\"overwrite\"\r\n\r\ntrue\r\n" % boundary).encode(), + ("--%s--\r\n" % boundary).encode()]) + req = urllib.request.Request(HOST + "/upload/image", data=body, headers={"Content-Type": "multipart/form-data; boundary=" + boundary}) + return json.loads(urllib.request.urlopen(req, timeout=60).read())["name"] + + +def workflow(image_name, prompt, seed, denoise): + return { + "1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": CKPT}}, + "3": {"class_type": "CLIPSetLastLayer", "inputs": {"clip": ["1", 1], "stop_at_clip_layer": -2}}, + "4": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": prompt}}, + "5": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": NEG}}, + "20": {"class_type": "LoadImage", "inputs": {"image": image_name}}, + "21": {"class_type": "VAEEncode", "inputs": {"pixels": ["20", 0], "vae": ["1", 2]}}, + "7": {"class_type": "KSampler", "inputs": {"model": ["1", 0], "positive": ["4", 0], "negative": ["5", 0], "latent_image": ["21", 0], "seed": seed, "steps": 30, "cfg": 7.0, "sampler_name": "dpmpp_2m", "scheduler": "karras", "denoise": denoise}}, + "8": {"class_type": "VAEDecode", "inputs": {"samples": ["7", 0], "vae": ["1", 2]}}, + "12": {"class_type": "InspyrenetRembg", "inputs": {"image": ["8", 0], "torchscript_jit": "default"}}, + "9": {"class_type": "SaveImage", "inputs": {"images": ["12", 0], "filename_prefix": "moba_repaint"}}, + } + + +def run(image_name, prompt, seed, denoise): + pid = post("/prompt", {"prompt": workflow(image_name, prompt, seed, denoise), "client_id": str(uuid.uuid4())})["prompt_id"] + t0 = time.time() + while time.time() - t0 < 600: + hist = json.loads(get("/history/" + pid)) + if pid in hist: + st = hist[pid].get("status", {}) + if st.get("status_str") == "error": + raise RuntimeError(json.dumps(st)[:900]) + for node in hist[pid].get("outputs", {}).values(): + for im in node.get("images", []): + q = urllib.parse.urlencode({"filename": im["filename"], "subfolder": im.get("subfolder", ""), "type": im.get("type", "output")}) + return Image.open(io.BytesIO(get("/view?" + q))).convert("RGBA") + time.sleep(1.0) + raise TimeoutError("comfy timeout") + + +def prepare(path): + """원본 아이콘을 캔버스 가운데에 여백을 두고 놓는다 — (어두운 바탕에 합성한 RGB, 같은 자리의 RGBA)""" + im = Image.open(path).convert("RGBA") + box = im.getchannel("A").getbbox() + if box: + im = im.crop(box) + scale = RES * FIT / float(max(im.size)) + im = im.resize((max(1, int(im.width * scale)), max(1, int(im.height * scale))), Image.LANCZOS) + rgba = Image.new("RGBA", (RES, RES), (0, 0, 0, 0)) + rgba.paste(im, ((RES - im.width) // 2, (RES - im.height) // 2), im) + rgb = Image.new("RGB", (RES, RES), BG) + rgb.paste(rgba, (0, 0), rgba) + return rgb, rgba + + +def mask(im, n=96, th=40): + a = im.getchannel("A").resize((n, n), Image.BILINEAR) + px = a.load() + return [[px[x, y] > th for x in range(n)] for y in range(n)] + + +def score(result, source_mask): + """(점수, 겹침 IoU, 가장 큰 덩어리 비율, 가장자리 닿음) — 점수가 높을수록 원본 형태를 지킨 깔끔한 한 덩어리""" + n = len(source_mask) + m = mask(result, n) + inter = union = total = 0 + for y in range(n): + for x in range(n): + a, b = m[y][x], source_mask[y][x] + if a: total += 1 + if a and b: inter += 1 + if a or b: union += 1 + if total == 0 or union == 0: + return 0.0, 0.0, 0.0, 1.0 + iou = inter / float(union) + edge = (sum(1 for i in range(n) if m[0][i]) + sum(1 for i in range(n) if m[n - 1][i]) + sum(1 for i in range(n) if m[i][0]) + sum(1 for i in range(n) if m[i][n - 1])) / float(4 * n) + seen = [[False] * n for _ in range(n)] + best = 0 + for y in range(n): + for x in range(n): + if m[y][x] and not seen[y][x]: + q = deque([(x, y)]); seen[y][x] = True; size = 0 + while q: + cx, cy = q.popleft(); size += 1 + for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)): + nx, ny = cx + dx, cy + dy + if 0 <= nx < n and 0 <= ny < n and m[ny][nx] and not seen[ny][nx]: + seen[ny][nx] = True; q.append((nx, ny)) + best = max(best, size) + main = best / float(total) + s = iou * 0.7 + main * 0.3 - edge * 2.0 + return s, iou, main, edge + + +def checker(size, n=16): + im = Image.new("RGB", (size, size), (58, 58, 58)) + d = ImageDraw.Draw(im) + for y in range(0, size, n): + for x in range(0, size, n): + if (x // n + y // n) % 2: + d.rectangle([x, y, x + n - 1, y + n - 1], fill=(74, 74, 74)) + return im + + +def main(): + out, tag = sys.argv[1], sys.argv[2] + lo = int(sys.argv[3]) if len(sys.argv) > 3 else 0 + hi = int(sys.argv[4]) if len(sys.argv) > 4 else 999 + denoises = [float(v) for v in (sys.argv[5] if len(sys.argv) > 5 else "0.5,0.65").split(",")] + seeds = int(sys.argv[6]) if len(sys.argv) > 6 else 3 + os.makedirs(out, exist_ok=True) + cap = load_captions() + ids = sorted(cap.keys())[lo:hi] + show = len(denoises) * seeds + cell, pad = 150, 4 + sheet = Image.new("RGB", (pad + (show + 1) * (cell + pad), len(ids) * (cell + pad) + pad), (40, 40, 40)) + draw = ImageDraw.Draw(sheet) + scores = {} + for i, gid in enumerate(ids): + rgb, rgba = prepare(os.path.join(SRC, "%d.png" % gid)) + name = upload(rgb, "bt_moba_src_%d.png" % gid) + src_mask = mask(rgba) + prompt = "%s, (%s:1.2), no humans, single item, isolated, dark background" % (PREFIX, cap[gid]) + results = [] + t0 = time.time() + for d in denoises: + for j in range(seeds): + im = run(name, prompt, 20000 + gid * 7 + j * 911 + int(d * 100), d) + s, iou, mainc, edge = score(im, src_mask) + fn = "%s_%d_d%02d_%d.png" % (tag, gid, int(d * 100), j) + im.save(os.path.join(out, fn)) + results.append((s, fn, im, iou, mainc, edge, d)) + results.sort(key=lambda t: -t[0]) + scores[gid] = [dict(file=r[1], score=round(r[0], 3), iou=round(r[3], 3), main=round(r[4], 3), edge=round(r[5], 3), denoise=r[6]) for r in results] + print("%s %d 최고 IoU %.2f(세기 %.2f) · %.0f초" % (tag, gid, results[0][3], results[0][6], time.time() - t0)); sys.stdout.flush() + y = pad + i * (cell + pad) + bg = checker(cell); small = rgba.resize((cell, cell), Image.LANCZOS); bg.paste(small, (0, 0), small); sheet.paste(bg, (pad, y)) + draw.text((pad + 3, y + 2), "%d 원본" % gid, fill=(255, 255, 255)) + for k, r in enumerate(results[:show]): + bg = checker(cell); small = r[2].resize((cell, cell), Image.LANCZOS); bg.paste(small, (0, 0), small) + sheet.paste(bg, (pad + (k + 1) * (cell + pad), y)) + draw.text((pad + (k + 1) * (cell + pad) + 3, y + 2), "d%.2f #%s IoU%.2f" % (r[6], r[1][-5], r[3]), fill=(255, 255, 255)) + json.dump(scores, io.open(os.path.join(out, "%s_scores_%d_%d.json" % (tag, lo, hi)), "w", encoding="utf-8"), ensure_ascii=False, indent=1) + path = os.path.join(out, "%s_sheet_%d_%d.png" % (tag, lo, hi)) + sheet.save(path) + print("sheet", path) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/comfy_moba_repaint_hq.py b/공유/기획/FirstRising/아이템/comfy_moba_repaint_hq.py new file mode 100644 index 0000000..47819e3 --- /dev/null +++ b/공유/기획/FirstRising/아이템/comfy_moba_repaint_hq.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지적 — 1차 다시 칠하기(comfy_moba_repaint.py · 512) 결과에 "퀄리티 좀 아쉬운데?". +# 원인(직접 본 것): 512 로 줄여 칠해 1024 원본의 세부가 뭉개졌고, 세기를 낮춰(0.5~0.65) MOBA 풍의 질감이 덜 올라왔다. +# 고품질 방식(이 스크립트): +# 1) 원본에서 윤곽선을 뽑아 ControlNet(선화 또는 캐니)으로 형태를 붙잡는다 → 세기를 높여(0.75~0.9) 질감 · 빛을 MOBA 풍으로 새로 칠해도 형태가 남는다. +# 2) 768(모델 권장 최대)에서 칠한 뒤 4x-UltraSharp 로 키우고 1024 로 맞춰, 약한 세기(0.3)로 한 번 더 다듬는다(세부 선명도). +# 3) 배경 제거(Inspyrenet) → 1024 투명 PNG. 채점은 1차와 같다(원본 실루엣 겹침 · 한 덩어리 · 가장자리). +# python comfy_moba_repaint_hq.py <출력폴더> <번호들 "1015,1253" 또는 all> [윤곽 "lineart,canny"] [세기 "0.75,0.9"] [시드 수=1] [윤곽 강도=0.8] +import io, json, os, sys, time, uuid, urllib.parse +from PIL import Image, ImageDraw +import comfy_moba_repaint as base # 올리기 · 채점 · 캡션 표는 1차 스크립트의 것을 그대로 쓴다 + +CKPT = base.CKPT +PREFIX = "(masterpiece:1.2), (best quality:1.2), moba game icon" +STYLE = "highly detailed, intricate details, sharp focus, polished metal, strong specular highlights, rim light, rich colors, hand painted game equipment icon" +# 시험(h1)에서 갑옷에 소매 · 팔이 덧붙어 몸 관련 낱말을 더했다 +NEG = base.NEG + ", flat color, sketch, monochrome, washed out, sleeves, arms, torso, body, mannequin" +RES1, RES2 = 768, 1024 # 1차로 칠하는 크기 · 최종 크기 +CN = {"lineart": "control_v11p_sd15_lineart_fp16.safetensors", "canny": "control_v11p_sd15_canny_fp16.safetensors"} +UPSCALER = "4x-UltraSharp.pth" +REFINE = 0.30 # 2차 다듬기 세기 + + +def prepare(path, res): + """원본 아이콘을 res 캔버스 가운데에 여백을 두고 놓는다 — (어두운 바탕 RGB, 투명 RGBA)""" + im = Image.open(path).convert("RGBA") + box = im.getchannel("A").getbbox() + if box: + im = im.crop(box) + scale = res * base.FIT / float(max(im.size)) + im = im.resize((max(1, int(im.width * scale)), max(1, int(im.height * scale))), Image.LANCZOS) + rgba = Image.new("RGBA", (res, res), (0, 0, 0, 0)) + rgba.paste(im, ((res - im.width) // 2, (res - im.height) // 2), im) + rgb = Image.new("RGB", (res, res), base.BG) + rgb.paste(rgba, (0, 0), rgba) + return rgb, rgba + + +def workflow(src768, src1024, prompt, seed, denoise, kind, cn_strength): + """768 칠하기(ControlNet) → 4배 확대 → 1024 → 약하게 다듬기(ControlNet) → 배경 제거""" + wf = { + "1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": CKPT}}, + "3": {"class_type": "CLIPSetLastLayer", "inputs": {"clip": ["1", 1], "stop_at_clip_layer": -2}}, + "4": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": prompt}}, + "5": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": NEG}}, + "20": {"class_type": "LoadImage", "inputs": {"image": src768}}, + "22": {"class_type": "LoadImage", "inputs": {"image": src1024}}, + "30": {"class_type": "ControlNetLoader", "inputs": {"control_net_name": CN[kind]}}, + # 윤곽은 1024 원본에서 뽑는다(가는 선까지 남긴다) + "31": ({"class_type": "LineArtPreprocessor", "inputs": {"image": ["22", 0], "coarse": "disable", "resolution": 1024}} if kind == "lineart" + else {"class_type": "Canny", "inputs": {"image": ["22", 0], "low_threshold": 0.15, "high_threshold": 0.45}}), + "32": {"class_type": "ControlNetApplyAdvanced", "inputs": {"positive": ["4", 0], "negative": ["5", 0], "control_net": ["30", 0], "image": ["31", 0], + "strength": cn_strength, "start_percent": 0.0, "end_percent": 0.85, "vae": ["1", 2]}}, + "21": {"class_type": "VAEEncode", "inputs": {"pixels": ["20", 0], "vae": ["1", 2]}}, + "7": {"class_type": "KSampler", "inputs": {"model": ["1", 0], "positive": ["32", 0], "negative": ["32", 1], "latent_image": ["21", 0], "seed": seed, + "steps": 30, "cfg": 7.0, "sampler_name": "dpmpp_2m", "scheduler": "karras", "denoise": denoise}}, + "8": {"class_type": "VAEDecode", "inputs": {"samples": ["7", 0], "vae": ["1", 2]}}, + "40": {"class_type": "UpscaleModelLoader", "inputs": {"model_name": UPSCALER}}, + "41": {"class_type": "ImageUpscaleWithModel", "inputs": {"upscale_model": ["40", 0], "image": ["8", 0]}}, + "42": {"class_type": "ImageScale", "inputs": {"image": ["41", 0], "upscale_method": "lanczos", "width": RES2, "height": RES2, "crop": "disabled"}}, + "43": {"class_type": "VAEEncode", "inputs": {"pixels": ["42", 0], "vae": ["1", 2]}}, + "44": {"class_type": "KSampler", "inputs": {"model": ["1", 0], "positive": ["32", 0], "negative": ["32", 1], "latent_image": ["43", 0], "seed": seed + 1, + "steps": 24, "cfg": 7.0, "sampler_name": "dpmpp_2m", "scheduler": "karras", "denoise": REFINE}}, + "45": {"class_type": "VAEDecode", "inputs": {"samples": ["44", 0], "vae": ["1", 2]}}, + "12": {"class_type": "InspyrenetRembg", "inputs": {"image": ["45", 0], "torchscript_jit": "default"}}, + "9": {"class_type": "SaveImage", "inputs": {"images": ["12", 0], "filename_prefix": "moba_hq"}}, + } + return wf + + +def run(wf): + pid = base.post("/prompt", {"prompt": wf, "client_id": str(uuid.uuid4())})["prompt_id"] + t0 = time.time() + while time.time() - t0 < 900: + hist = json.loads(base.get("/history/" + pid)) + if pid in hist: + st = hist[pid].get("status", {}) + if st.get("status_str") == "error": + raise RuntimeError(json.dumps(st)[:1500]) + for node in hist[pid].get("outputs", {}).values(): + for im in node.get("images", []): + q = urllib.parse.urlencode({"filename": im["filename"], "subfolder": im.get("subfolder", ""), "type": im.get("type", "output")}) + return Image.open(io.BytesIO(base.get("/view?" + q))).convert("RGBA") + time.sleep(1.0) + raise TimeoutError("comfy timeout") + + +def main(): + out, tag = sys.argv[1], sys.argv[2] + cap = base.load_captions() + ids = sorted(cap.keys()) if sys.argv[3] == "all" else [int(v) for v in sys.argv[3].split(",")] + kinds = (sys.argv[4] if len(sys.argv) > 4 else "lineart,canny").split(",") + denoises = [float(v) for v in (sys.argv[5] if len(sys.argv) > 5 else "0.75,0.9").split(",")] + seeds = int(sys.argv[6]) if len(sys.argv) > 6 else 1 + cn_strength = float(sys.argv[7]) if len(sys.argv) > 7 else 0.8 + old_dir = sys.argv[8] if len(sys.argv) > 8 else "" # 1차 결과(고른 것) 폴더 — 있으면 비교 칸으로 넣는다 + os.makedirs(out, exist_ok=True) + show = len(kinds) * len(denoises) * seeds + extra = 2 if old_dir else 1 + cell, pad = 256, 4 + sheet = Image.new("RGB", (pad + (show + extra) * (cell + pad), len(ids) * (cell + pad) + pad), (40, 40, 40)) + draw = ImageDraw.Draw(sheet) + scores = {} + + def put(im, col, y, text): + bg = base.checker(cell); small = im.resize((cell, cell), Image.LANCZOS); bg.paste(small, (0, 0), small) + sheet.paste(bg, (pad + col * (cell + pad), y)) + draw.text((pad + col * (cell + pad) + 3, y + 2), text, fill=(255, 255, 255)) + + for i, gid in enumerate(ids): + path = os.path.join(base.SRC, "%d.png" % gid) + rgb1, _ = prepare(path, RES1) + rgb2, rgba2 = prepare(path, RES2) + n1 = base.upload(rgb1, "bt_moba_hq768_%d.png" % gid) + n2 = base.upload(rgb2, "bt_moba_hq1024_%d.png" % gid) + src_mask = base.mask(rgba2) + prompt = "%s, (%s:1.2), %s, no humans, single item, isolated, dark background" % (PREFIX, cap[gid], STYLE) + y = pad + i * (cell + pad) + put(rgba2, 0, y, "%d 원본" % gid) + col = 1 + if old_dir: + old = os.path.join(old_dir, "%d_0.png" % gid) + if os.path.exists(old): + put(Image.open(old).convert("RGBA"), 1, y, "1차(512)") + col = 2 + results = [] + t0 = time.time() + for kind in kinds: + for d in denoises: + for j in range(seeds): + fn = "%s_%d_%s_d%02d_%d.png" % (tag, gid, kind, int(d * 100), j) + # 이미 만든 그림은 다시 만들지 않는다(긴 작업이 끊겨도 이어서 돌린다) + if os.path.exists(os.path.join(out, fn)): + im = Image.open(os.path.join(out, fn)).convert("RGBA") + else: + im = run(workflow(n1, n2, prompt, 40000 + gid * 7 + j * 911 + int(d * 100), d, kind, cn_strength)) + im.save(os.path.join(out, fn)) + s, iou, mainc, edge = base.score(im, src_mask) + results.append(dict(file=fn, score=round(s, 3), iou=round(iou, 3), main=round(mainc, 3), edge=round(edge, 3), denoise=d, kind=kind)) + put(im, col, y, "%s d%.2f #%d IoU%.2f" % (kind, d, j, iou)); col += 1 + scores[gid] = results + print("%s %d · %d장 · %.0f초" % (tag, gid, len(results), time.time() - t0)); sys.stdout.flush() + sheet.save(os.path.join(out, "%s_sheet.png" % tag)) + json.dump(scores, io.open(os.path.join(out, "%s_scores.json" % tag), "w", encoding="utf-8"), ensure_ascii=False, indent=1) + print("sheet", os.path.join(out, "%s_sheet.png" % tag)) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/icon_approved_sheet.py b/공유/기획/FirstRising/아이템/icon_approved_sheet.py new file mode 100644 index 0000000..53d93ee --- /dev/null +++ b/공유/기획/FirstRising/아이템/icon_approved_sheet.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지시(자율 반복) — PD 가 직접 동그라미 친 그림만 모아 "합격 기준 시트"를 만든다. 검토 담당(사람 · 에이전트)이 새 그림을 고를 때 이 시트를 기준으로 삼는다. +# python icon_approved_sheet.py +# 목록은 PD 가 고른 그대로다(1차 = a1 시트의 동그라미 7장 · 2차 = final_sheet 의 동그라미 8장). PD 가 새로 고르면 여기에 더한다. +import os +from PIL import Image, ImageDraw + +HERE = os.path.dirname(os.path.abspath(__file__)) +A1 = r"C:\Users\sw\AppData\Local\Temp\claude\E--BurningTimes\87b07a14-ef05-46d9-b47a-a879d51eee93\scratchpad\moba_anfg" +OUT = os.path.join(HERE, "moba_anfg", "approved") +PICKS = [ + # (출력 이름, 원본 경로) + ("pd1_ring", os.path.join(A1, "a1_ring_s10_0.png")), + ("pd1_helmet", os.path.join(A1, "a1_helmet_s07_0.png")), + ("pd1_gloves_a", os.path.join(A1, "a1_gloves_s07_1.png")), + ("pd1_gloves_b", os.path.join(A1, "a1_gloves_s10_0.png")), + ("pd1_armor", os.path.join(A1, "a1_armor_s07_1.png")), + ("pd1_necklace", os.path.join(A1, "a1_necklace_s07_0.png")), + ("pd1_boots", os.path.join(A1, "a1_boots_s10_0.png")), + ("pd2_armor", os.path.join(HERE, "moba_anfg", "final", "armor_a.png")), + ("pd2_boots", os.path.join(HERE, "moba_anfg", "final", "boots_a.png")), + ("pd2_dagger", os.path.join(HERE, "moba_anfg", "final", "dagger_c.png")), + ("pd2_magicdagger", os.path.join(HERE, "moba_anfg", "final", "magicdagger_b.png")), + ("pd2_necklace", os.path.join(HERE, "moba_anfg", "final", "necklace_a.png")), + ("pd2_ring", os.path.join(HERE, "moba_anfg", "final", "ring_c.png")), + ("pd2_shield", os.path.join(HERE, "moba_anfg", "final", "shield_b.png")), + ("pd2_sword", os.path.join(HERE, "moba_anfg", "final", "sword_a.png")), +] + + +def main(): + os.makedirs(OUT, exist_ok=True) + cell, pad, cols = 256, 4, 5 + rows = (len(PICKS) + cols - 1) // cols + sheet = Image.new("RGB", (cols * (cell + pad) + pad, rows * (cell + pad) + pad), (24, 24, 28)) + draw = ImageDraw.Draw(sheet) + for i, (name, path) in enumerate(PICKS): + im = Image.open(path).convert("RGBA") + im.save(os.path.join(OUT, name + ".png")) # 원본을 합격본 폴더에 사본으로 모아 둔다(scratchpad 는 사라질 수 있다) + bg = Image.new("RGB", (cell, cell), (40, 40, 46)); small = im.resize((cell, cell), Image.LANCZOS); bg.paste(small, (0, 0), small) + x, y = pad + (i % cols) * (cell + pad), pad + (i // cols) * (cell + pad) + sheet.paste(bg, (x, y)); draw.text((x + 3, y + 2), name, fill=(220, 220, 220)) + sheet.save(os.path.join(OUT, "approved_sheet.png")) + print("approved %d -> %s" % (len(PICKS), OUT)) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/icon_compare_sheet.py b/공유/기획/FirstRising/아이템/icon_compare_sheet.py new file mode 100644 index 0000000..178cd35 --- /dev/null +++ b/공유/기획/FirstRising/아이템/icon_compare_sheet.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지시(자율 반복) — 같은 길잡이의 "지금 색 조합(밝은 금 + 적/청)"과 "어두운 색 조합(a22)"을 나란히 놓은 비교 시트(PD 방향 결정용). +# python icon_compare_sheet.py +# 열: 지금(앞 회차의 같은 행 #0) | 어두운 조합 ANFG 0.7 #0 · #1 | ANFG 0.8 #0 · #1 +import os +from PIL import Image, ImageDraw + +ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "moba_anfg") +ROWS = [("armor-fr1267", "a17"), ("boots-fr1379", "a17"), ("gloves-fr1183", "a17"), ("necklace-fr1099", "a17"), ("belt-fr1351", "a17"), + ("helmet-genmoba0", "a17"), ("blunt-fr1057", "a17"), ("shield-genxl1", "a19"), ("sword-genxl1", "a19"), ("staff-genxlb0", "a20")] +HEAD = ["now (bright)", "dark 0.7 #0", "dark 0.7 #1", "dark 0.8 #0", "dark 0.8 #1"] + + +def main(): + cell, pad, top = 200, 4, 18 + sheet = Image.new("RGB", (len(HEAD) * (cell + pad) + pad, top + len(ROWS) * (cell + pad) + pad), (24, 24, 28)) + d = ImageDraw.Draw(sheet) + for c, h in enumerate(HEAD): + d.text((pad + c * (cell + pad) + 4, 3), h, fill=(240, 220, 160)) + for r, (row, old) in enumerate(ROWS): + files = ["%s_%s_s07_0.png" % (old, row), "a22_%s_s07_0.png" % row, "a22_%s_s07_1.png" % row, "a22_%s_s08_0.png" % row, "a22_%s_s08_1.png" % row] + for c, fn in enumerate(files): + path = os.path.join(ROOT, fn) + if not os.path.exists(path): + continue + im = Image.open(path).convert("RGBA") + # 게임 칸과 비슷한 어두운 바탕 + bg = Image.new("RGB", (cell, cell), (40, 40, 46)); small = im.resize((cell, cell), Image.LANCZOS); bg.paste(small, (0, 0), small) + sheet.paste(bg, (pad + c * (cell + pad), top + r * (cell + pad))) + out = os.path.join(ROOT, "a22_compare.png") + sheet.save(out); print(out) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/icon_dataset.py b/공유/기획/FirstRising/아이템/icon_dataset.py new file mode 100644 index 0000000..e38e7c2 --- /dev/null +++ b/공유/기획/FirstRising/아이템/icon_dataset.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지시(자율 반복) — "완성 된 이미지를 모아 학습을 거듭해 … 체계를 구축". 합격본을 학습 데이터셋 목록(dataset.json)에 쌓는다. +# python icon_dataset.py add <고른 목록 json> <그림 폴더> <출처: pd|auto> 고른 그림을 목록에 더한다(같은 파일은 한 번만) +# python icon_dataset.py list 목록 요약 +# 고른 목록 json: {"<이름>": "<파일 이름>", …}. 파일 이름 규칙 _<대상>_s<강도>_<순번>.png 에서 대상을 읽어 묘사(캡션)를 찾는다. +# 그림은 moba_anfg/dataset/ 로 사본을 모은다(1024 투명 · 여백 통일 = icon_finalize.finalize). +import io, json, os, re, sys +import comfy_moba_anfg as gen +from icon_finalize import finalize + +HERE = os.path.dirname(os.path.abspath(__file__)) +ROOT = os.path.join(HERE, "moba_anfg") +DS_DIR = os.path.join(ROOT, "dataset") +DS_JSON = os.path.join(ROOT, "dataset.json") + + +def table_for(tag): + """회차 이름 → 그 회차가 쓴 대상 표. 같은 이름(ring 등)이라도 회차마다 묘사가 다르므로 회차로 표를 고른다. + (2026-10-02 수정: 처음에는 표를 합쳐 찾아 a2 그림에 a1 묘사가 붙었다 — v1 학습은 그 잘못된 캡션으로 돌았다.)""" + if tag in ("a1", "a4"): + table = gen.SUBJECTS + elif tag in ("a2", "a5n", "a5v"): + table = gen.SUBJECTS_FR + elif tag == "a3": + table = gen.SUBJECTS_SHAPE + else: + table = gen.SUBJECTS_ALL + return dict((x[0], x[1]) for x in table) + + +def load(): + return json.load(io.open(DS_JSON, encoding="utf-8")) if os.path.exists(DS_JSON) else [] + + +def add(picks_path, folder, source): + picks = json.load(io.open(picks_path, encoding="utf-8")) + data = load() + have = set(e["src"] for e in data) + os.makedirs(DS_DIR, exist_ok=True) + n = 0 + for name, fn in sorted(picks.items()): + if fn in have: + continue + m = re.match(r"^([a-z0-9]+)_(.+)_s\d+_\d+\.png$", fn) + if not m: + print("이름 규칙이 아니라 건너뜀:", fn); continue + tag, subject = m.group(1), m.group(2) + # 생성 때 남긴 곁파일(<그림>.txt)이 있으면 그 묘사를 쓴다. 없으면(예전 회차) 회차의 대상 표에서 찾는다. + side = os.path.join(folder, fn[:-4] + ".txt") + caption = io.open(side, encoding="utf-8").read().strip() if os.path.exists(side) else table_for(tag).get(subject) + if not caption: + print("묘사를 못 찾아 건너뜀:", fn); continue + out_name = "%s_%s.png" % (tag, fn[len(tag) + 1:-4]) + finalize(os.path.join(folder, fn)).save(os.path.join(DS_DIR, out_name)) + data.append({"file": out_name, "src": fn, "caption": caption, "source": source}) + n += 1 + json.dump(data, io.open(DS_JSON, "w", encoding="utf-8"), ensure_ascii=False, indent=1) + print("추가 %d · 전체 %d (pd %d)" % (n, len(data), sum(1 for e in data if e["source"] == "pd"))) + + +if __name__ == "__main__": + if sys.argv[1] == "add": + add(sys.argv[2], sys.argv[3], sys.argv[4]) + else: + data = load() + print("전체 %d · pd %d" % (len(data), sum(1 for e in data if e["source"] == "pd"))) diff --git a/공유/기획/FirstRising/아이템/icon_finalize.py b/공유/기획/FirstRising/아이템/icon_finalize.py new file mode 100644 index 0000000..0f7591b --- /dev/null +++ b/공유/기획/FirstRising/아이템/icon_finalize.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지시 — "기준에 맞는지 검토해서 배경을 투명하게 … 리소스화 할 수 있도록 제작". +# 검토에서 고른 그림을 게임 리소스 규격으로 다듬는다: 옅은 잔여 알파 제거 → 물체 테두리로 잘라 → 캔버스(1024) 가운데에 같은 여백(물체 긴 변 = 캔버스의 82%)으로 놓는다. +# python icon_finalize.py <원본 폴더> <고른 목록 json> <출력 폴더> +# 목록 json: {"<출력 이름>": "<원본 파일 이름>", …}. 끝에 고른 것 전체를 한 장(final_sheet.png)으로 묶는다. +import io, json, os, sys +from PIL import Image, ImageDraw + +SIZE, FIT = 1024, 0.82 # FR 원본 아이콘과 같은 1024 · 여백 통일 +ALPHA_FLOOR = 24 # 이보다 옅은 알파(배경 제거가 남긴 안개)는 지운다 + + +def finalize(path): + im = Image.open(path).convert("RGBA") + a = im.getchannel("A").point(lambda v: 0 if v < ALPHA_FLOOR else v) + im.putalpha(a) + box = a.getbbox() + if box: + im = im.crop(box) + scale = SIZE * FIT / float(max(im.size)) + im = im.resize((max(1, int(round(im.width * scale))), max(1, int(round(im.height * scale)))), Image.LANCZOS) + canvas = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0)) + canvas.paste(im, ((SIZE - im.width) // 2, (SIZE - im.height) // 2), im) + return canvas + + +def main(): + src, picks_path, out = sys.argv[1], sys.argv[2], sys.argv[3] + picks = json.load(io.open(picks_path, encoding="utf-8")) + os.makedirs(out, exist_ok=True) + names = sorted(picks.keys()) + cell, pad, cols = 200, 4, 8 + rows = (len(names) + cols - 1) // cols + sheet = Image.new("RGB", (cols * (cell + pad) + pad, rows * (cell + pad) + pad), (24, 24, 28)) + draw = ImageDraw.Draw(sheet) + for i, name in enumerate(names): + im = finalize(os.path.join(src, picks[name])) + im.save(os.path.join(out, name + ".png")) + # 게임 칸과 비슷한 어두운 바탕에 올려 본다 + bg = Image.new("RGB", (cell, cell), (40, 40, 46)); small = im.resize((cell, cell), Image.LANCZOS); bg.paste(small, (0, 0), small) + x, y = pad + (i % cols) * (cell + pad), pad + (i // cols) * (cell + pad) + sheet.paste(bg, (x, y)); draw.text((x + 3, y + 2), name, fill=(220, 220, 220)) + sheet.save(os.path.join(out, "final_sheet.png")) + print("%d icons -> %s" % (len(names), out)) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/icon_guide_bootstrap.py b/공유/기획/FirstRising/아이템/icon_guide_bootstrap.py new file mode 100644 index 0000000..a74ab00 --- /dev/null +++ b/공유/기획/FirstRising/아이템/icon_guide_bootstrap.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지시(자율 반복) — 길잡이가 없는(또는 직접 그린 도형으로는 안 되는) 종류의 길잡이를 자동으로 마련한다. +# a15 검토: 도끼는 도형을 네 번 고쳐도 "속 빈 초승달"(선화가 면을 고리로 읽는다). 투구 · 반지 · 뿔피리 · 구슬도 단순 도형에서는 매끈하게만 나온다. +# → 기반 모델(mobaGameEquipment_v10 · LoRA 없음)이 글자로 그린 그림 가운데 "물건 하나 · 여백 안 · 한 덩어리"인 것을 골라 그 윤곽을 길잡이로 쓴다. +# 안쪽 선이 풍부해 모델이 채울 근거가 생긴다. 색 · 질감은 넘어가지 않는다(윤곽선만 쓴다). +# python icon_guide_bootstrap.py <종류> "<묘사>" [장수=10] [고를 수=2] ["부정어"] +# 결과: moba_anfg/shapes/<종류>__genmoba.png (active.txt 에 등록) · 후보 전체는 moba_anfg/bootstrap/ 에 남긴다. +import io, json, os, sys, time, uuid, urllib.parse +from PIL import Image +import comfy_moba_batch as mb +import icon_shapes + +# a17 · a18 검토: 기반 모델(SD1.5)의 초벌은 단검이 두 자루로, 반지 · 뿔피리가 다른 물건으로 나와 길잡이로 쓸 수 없었다. +# → 환경변수 BOOT_MODEL=xl 이면 글자를 더 잘 알아듣는 SDXL 아이콘 모델(gameIconInstitute_v4XL)로 초벌을 그린다. 풍은 상관없다(윤곽만 쓴다). 등록 이름은 genxl. +XL = os.environ.get("BOOT_MODEL", "") == "xl" +XL_CKPT = "gameIconInstitute_v4XL.safetensors" +XL_NEG = "worst quality, low quality, lowres, blurry, cropped, cut off, text, watermark, signature, person, hands, multiple objects, duplicate, frame, border, round background" + + +def run_xl(desc, seed): + """SDXL 초벌 한 장(1024 · 배경 제거)""" + wf = { + "1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": XL_CKPT}}, + "3": {"class_type": "CLIPSetLastLayer", "inputs": {"clip": ["1", 1], "stop_at_clip_layer": -2}}, + "4": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": "gmic_\\(3dicon\\), game icon, %s, single object, centered, whole object visible, wide margin, simple dark background" % desc}}, + "5": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["3", 0], "text": XL_NEG}}, + "6": {"class_type": "EmptyLatentImage", "inputs": {"width": 1024, "height": 1024, "batch_size": 1}}, + "7": {"class_type": "KSampler", "inputs": {"model": ["1", 0], "positive": ["4", 0], "negative": ["5", 0], "latent_image": ["6", 0], "seed": seed, "steps": 20, "cfg": 7.0, "sampler_name": "dpmpp_2m", "scheduler": "karras", "denoise": 1.0}}, + "8": {"class_type": "VAEDecode", "inputs": {"samples": ["7", 0], "vae": ["1", 2]}}, + "12": {"class_type": "InspyrenetRembg", "inputs": {"image": ["8", 0], "torchscript_jit": "default"}}, + "9": {"class_type": "SaveImage", "inputs": {"images": ["12", 0], "filename_prefix": "boot_xl"}}, + } + pid = mb.post("/prompt", {"prompt": wf, "client_id": str(uuid.uuid4())})["prompt_id"] + t0 = time.time() + while time.time() - t0 < 900: + hist = json.loads(mb.get("/history/" + pid)) + if pid in hist: + st = hist[pid].get("status", {}) + if st.get("status_str") == "error": + raise RuntimeError(json.dumps(st)[:1200]) + for node in hist[pid].get("outputs", {}).values(): + for im in node.get("images", []): + q = urllib.parse.urlencode({"filename": im["filename"], "subfolder": im.get("subfolder", ""), "type": im.get("type", "output")}) + return Image.open(io.BytesIO(mb.get("/view?" + q))).convert("RGBA") + time.sleep(1.5) + raise TimeoutError("comfy timeout") + +HERE = os.path.dirname(os.path.abspath(__file__)) +OUT = os.path.join(HERE, "moba_anfg", "bootstrap") + + +def main(): + kind, desc = sys.argv[1], sys.argv[2] + count = int(sys.argv[3]) if len(sys.argv) > 3 else 10 + keep = int(sys.argv[4]) if len(sys.argv) > 4 else 2 + extra_neg = sys.argv[5] if len(sys.argv) > 5 else "" + os.makedirs(OUT, exist_ok=True) + global XL_NEG + if extra_neg: + mb.NEG = mb.NEG + ", " + extra_neg + XL_NEG = XL_NEG + ", " + extra_neg + prompt = "%s, (%s:1.35), no humans, single item, isolated, centered, full object in frame, simple background, still life" % (mb.PREFIX, desc) + passed = [] + for j in range(count): + seed = 77000 + sum(ord(c) for c in kind) * 13 + j * 503 + im = run_xl(desc, seed) if XL else mb.run(prompt, seed) + ok, opaque, edge, mainc = mb.score(im) + fn = "%s%s_%02d%s.png" % ("xl_" if XL else "", kind, j, "" if ok else "_x") + im.save(os.path.join(OUT, fn)) + if ok: + # 한 덩어리이고 적당한 크기일수록 앞에 둔다 + passed.append((mainc - abs(opaque - 0.24), fn)) + passed.sort(reverse=True) + # a19 검토: 자동 채점은 "두 자루 · 칼집 딸림 · 다른 물건(뿔피리 → 확성기)"을 못 거른다 → 초벌 전체를 한 장으로 묶어 두고, + # 고를 수(keep)를 0 으로 주면 등록하지 않는다. 그때는 초벌 시트를 보고(사람 · 검토 에이전트) 고른 것을 `python icon_shapes.py add <종류> <파일> <이름>` 으로 등록한다. + prefix = ("xl_" if XL else "") + kind + "_" + names = sorted(f for f in os.listdir(OUT) if f.startswith(prefix) and f.endswith(".png") and "sheet" not in f) + cell, pad, cols = 256, 4, 6 + rows = (len(names) + cols - 1) // cols + from PIL import ImageDraw + sheet = Image.new("RGB", (cols * (cell + pad) + pad, rows * (cell + pad) + pad), (24, 24, 28)) + d = ImageDraw.Draw(sheet) + for i, fn in enumerate(names): + im = Image.open(os.path.join(OUT, fn)).convert("RGBA") + bg = Image.new("RGB", (cell, cell), (52, 52, 58)); small = im.resize((cell, cell), Image.LANCZOS); bg.paste(small, (0, 0), small) + x, y = pad + (i % cols) * (cell + pad), pad + (i // cols) * (cell + pad) + sheet.paste(bg, (x, y)); d.text((x + 3, y + 2), fn[:-4], fill=(255, 120, 120) if fn.endswith("_x.png") else (120, 255, 120)) + sheet.save(os.path.join(OUT, prefix + "sheet.png")) + # 이미 등록된 genmoba 번호 뒤에 잇는다 + label = "genxl" if XL else "genmoba" + have = len([f for f in os.listdir(icon_shapes.OUT) if f.startswith(kind + "__" + label)]) + for k, (_, fn) in enumerate(passed[:keep]): + icon_shapes.add_from(kind, os.path.join(OUT, fn), "%s%d" % (label, have + k)) + print("%s: 통과 %d/%d · 길잡이 등록 %d (%s)" % (kind, len(passed), count, min(keep, len(passed)), ", ".join(fn for _, fn in passed[:keep]))) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/icon_guides_register.py b/공유/기획/FirstRising/아이템/icon_guides_register.py new file mode 100644 index 0000000..746aa6a --- /dev/null +++ b/공유/기획/FirstRising/아이템/icon_guides_register.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지시(자율 반복) — 검토에서 고른 초벌을 길잡이로 등록한다. +# python icon_guides_register.py <이름표(예: xlb)> +# guides json: {"<종류>": ["xl_axe_01.png", …], …} (moba_anfg/ 아래 · 초벌은 moba_anfg/bootstrap/ 에 있다) +# 등록 이름 = <종류>__gen<이름표><순번>.png. 마지막 줄에 본 생성에 넘길 행 이름(ANFG_ROWS)을 찍는다. +import io, json, os, sys +import icon_shapes + +HERE = os.path.dirname(os.path.abspath(__file__)) +ROOT = os.path.join(HERE, "moba_anfg") + + +def main(): + guides = json.load(io.open(os.path.join(ROOT, sys.argv[1]), encoding="utf-8")) + label = sys.argv[2] + rows = [] + for kind, files in sorted(guides.items()): + for k, fn in enumerate(files): + name = "gen%s%d" % (label, k) + icon_shapes.add_from(kind, os.path.join(ROOT, "bootstrap", fn), name) + rows.append("%s-%s" % (kind, name)) + print(",".join(rows)) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/icon_make.py b/공유/기획/FirstRising/아이템/icon_make.py new file mode 100644 index 0000000..ce9d1fd --- /dev/null +++ b/공유/기획/FirstRising/아이템/icon_make.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지시(자율 반복) — "원하는 장비 아이콘을 자유롭게 생성할 수 있는 … 체계". 새 종류든 기존 종류든 한 줄로 뽑는 명령. +# a18 결론: 글자만으로는 형태가 안정되지 않는다 → 정식 경로를 "글자 → 자동 길잡이 → 본 생성" 2단으로 묶는다. +# python icon_make.py <종류> "<초벌 묘사(영어)>" "<본 묘사(영어 · {pal} 자리에 색 조합이 들어간다)>" [초벌 장수=6] [길잡이 수=2] [길잡이당 장수=3] +# 예: python icon_make.py crossbow "a single crossbow, wooden stock, steel limbs" "a crossbow, carved wooden stock, steel limbs with ornate fittings, {pal}" +# 하는 일: +# 1) SDXL 아이콘 모델로 초벌을 그려 자동 채점(물건 하나 · 여백 안 · 한 덩어리)을 통과한 것의 윤곽을 길잡이로 등록(shapes/<종류>__genxl.png) +# 2) 본 묘사를 종류 표(moba_anfg/type_desc.json)에 적는다 — 생성 스크립트가 읽는다 +# 3) 그 길잡이로 본 생성(기본 설정 = v4 0.6 · paint · UltraSharp · 다듬기 0.45) → moba_anfg/mk<종류>_*.png + 검토 시트 +# 결과는 검토(사람 또는 검토 에이전트)를 거쳐 icon_dataset.py · icon_pack.py 로 넘긴다. 자동 채점은 "그 종류로 읽히는가"를 보지 못한다. +import io, json, os, re, subprocess, sys + +HERE = os.path.dirname(os.path.abspath(__file__)) +ROOT = os.path.join(HERE, "moba_anfg") +DESC_JSON = os.path.join(ROOT, "type_desc.json") + + +def main(): + kind, draft_desc, final_desc = sys.argv[1], sys.argv[2], sys.argv[3] + n_draft = sys.argv[4] if len(sys.argv) > 4 else "6" + n_guide = sys.argv[5] if len(sys.argv) > 5 else "2" + n_out = sys.argv[6] if len(sys.argv) > 6 else "3" + if not re.match(r"^[a-z_]+$", kind): + print("종류 이름은 영어 소문자와 _ 만"); sys.exit(1) + # 2) 본 묘사 등록 + table = json.load(io.open(DESC_JSON, encoding="utf-8")) if os.path.exists(DESC_JSON) else {} + table[kind] = final_desc + json.dump(table, io.open(DESC_JSON, "w", encoding="utf-8"), ensure_ascii=False, indent=1) + env = dict(os.environ, PYTHONIOENCODING="utf-8") + # 1) 초벌 → 길잡이 + r = subprocess.run([sys.executable, os.path.join(HERE, "icon_guide_bootstrap.py"), kind, draft_desc, n_draft, n_guide], env=dict(env, BOOT_MODEL="xl"), cwd=HERE) + if r.returncode != 0: + sys.exit(r.returncode) + # 3) 본 생성(이 종류의 SDXL 초벌 길잡이만) + tag = "mk" + kind.replace("_", "") + genv = dict(env, ANFG_TONE="paint", ANFG_UPSCALE="model", ANFG_REFINE="0.45", ANFG_LORA2="FR_anfg_v4.safetensors:0.6", + ANFG_ONLY=kind, ANFG_SKIP="genpd,genmoba,draw,-fr,-ll", ANFG_ROWS="", ANFG_SEED=os.environ.get("ANFG_SEED", "41")) + r = subprocess.run([sys.executable, os.path.join(HERE, "comfy_moba_anfg.py"), ROOT, tag, "0.7", n_out, "512", "1", "lib", "0.6", "0.5"], env=genv, cwd=HERE) + if r.returncode != 0: + sys.exit(r.returncode) + subprocess.run([sys.executable, os.path.join(HERE, "icon_review_sheet.py"), ROOT, tag, "8"], env=env, cwd=HERE) + print("끝: %s\\%s_review_0.png 를 검토한 뒤 picks_%s.json → icon_dataset.py add · icon_pack.py" % (ROOT, tag, tag)) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/icon_pack.py b/공유/기획/FirstRising/아이템/icon_pack.py new file mode 100644 index 0000000..f430d3f --- /dev/null +++ b/공유/기획/FirstRising/아이템/icon_pack.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지시(자율 반복) — 검토를 통과한 그림을 리소스 묶음으로 만든다. +# python icon_pack.py <출력 폴더 이름> [시트 칸 수=10] +# 예: python icon_pack.py final_v4 picks_a13.json,picks_a14.json,picks_a17.json +# 결과: moba_anfg/<출력 폴더>/<종류>_<번호>.png (1024 투명 · 여백 통일) + final_sheet.png(종류 순서로 정렬) +import io, json, os, re, sys +from PIL import Image, ImageDraw +from icon_finalize import finalize + +HERE = os.path.dirname(os.path.abspath(__file__)) +ROOT = os.path.join(HERE, "moba_anfg") +# 시트에 놓는 순서: 무기 → 방어구 → 장신구 → 보조 장비 +ORDER = ["sword", "dagger", "magic_dagger", "offhand_sword", "axe", "blunt", "hammer", "bow", "staff", "armor", "helmet", "gloves", "belt", "boots", + "ring", "necklace", "shield", "quiver", "spellbook", "throwing", "orb", "totem", "horn"] + + +def kind_of(fn): + m = re.match(r"^[a-z0-9]+_(.+)_s\d+_\d+\.png$", fn) + return m.group(1).split("-")[0] if m else "etc" + + +def main(): + out = os.path.join(ROOT, sys.argv[1]) + cols = int(sys.argv[3]) if len(sys.argv) > 3 else 10 + files = [] + for name in sys.argv[2].split(","): + files += list(json.load(io.open(os.path.join(ROOT, name), encoding="utf-8")).values()) + files = sorted(set(files), key=lambda f: (ORDER.index(kind_of(f)) if kind_of(f) in ORDER else 99, f)) + os.makedirs(out, exist_ok=True) + cell, pad = 180, 4 + rows = (len(files) + cols - 1) // cols + sheet = Image.new("RGB", (cols * (cell + pad) + pad, rows * (cell + pad) + pad), (24, 24, 28)) + draw = ImageDraw.Draw(sheet) + count, index = {}, [] + for i, fn in enumerate(files): + k = kind_of(fn) + count[k] = count.get(k, 0) + 1 + name = "%s_%02d" % (k, count[k]) + im = finalize(os.path.join(ROOT, fn)) + im.save(os.path.join(out, name + ".png")) + index.append({"icon": name + ".png", "source": fn}) + bg = Image.new("RGB", (cell, cell), (40, 40, 46)); small = im.resize((cell, cell), Image.LANCZOS); bg.paste(small, (0, 0), small) + x, y = pad + (i % cols) * (cell + pad), pad + (i // cols) * (cell + pad) + sheet.paste(bg, (x, y)); draw.text((x + 3, y + 2), name, fill=(220, 220, 220)) + sheet.save(os.path.join(out, "final_sheet.png")) + json.dump(index, io.open(os.path.join(out, "index.json"), "w", encoding="utf-8"), ensure_ascii=False, indent=1) + print("%d icons -> %s · 종류별 %s" % (len(files), out, sorted(count.items(), key=lambda x: -x[1]))) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/icon_review_sheet.py b/공유/기획/FirstRising/아이템/icon_review_sheet.py new file mode 100644 index 0000000..d1a04a7 --- /dev/null +++ b/공유/기획/FirstRising/아이템/icon_review_sheet.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지시 — "피드백 해준 기준에 맞는지 검토해서 배경을 투명하게 … 리소스화". 생성한 아이콘 폴더를 채점해 검토용 시트로 묶는다. +# python icon_review_sheet.py <폴더> [한 시트의 줄 수=10] +# 파일 이름 규칙: _<대상>_s<강도>_<순번>.png. 채점은 comfy_moba_batch.score(불투명 비율 · 가장자리 닿음 · 한 덩어리). +import glob, os, sys +from PIL import Image, ImageDraw +from comfy_moba_batch import score + + +def main(): + folder, tag = sys.argv[1], sys.argv[2] + rows_per = int(sys.argv[3]) if len(sys.argv) > 3 else 10 + groups, order = {}, [] + for path in sorted(glob.glob(os.path.join(folder, tag + "_*_s*_*.png")), key=os.path.getmtime): + name = os.path.basename(path)[len(tag) + 1:].rsplit("_s", 1)[0] + if name not in groups: + groups[name] = []; order.append(name) + groups[name].append(path) + cell, pad, left = 240, 4, 90 + cols = max(len(v) for v in groups.values()) + for page in range(0, len(order), rows_per): + names = order[page:page + rows_per] + sheet = Image.new("RGB", (left + cols * (cell + pad) + pad, len(names) * (cell + pad) + pad), (24, 24, 28)) + draw = ImageDraw.Draw(sheet) + for i, name in enumerate(names): + y = pad + i * (cell + pad) + draw.text((pad, y + 4), name, fill=(240, 220, 160)) + for k, path in enumerate(sorted(groups[name])): + im = Image.open(path).convert("RGBA") + ok, opaque, edge, mainc = score(im) + # 투명 배경 확인용으로 중간 회색 바탕에 올린다 + bg = Image.new("RGB", (cell, cell), (52, 52, 58)); small = im.resize((cell, cell), Image.LANCZOS); bg.paste(small, (0, 0), small) + x = left + k * (cell + pad) + sheet.paste(bg, (x, y)) + draw.text((x + 3, y + 2), "#%d %s op%.2f ed%.2f mn%.2f" % (k, "OK" if ok else "X", opaque, edge, mainc), fill=(120, 255, 120) if ok else (255, 120, 120)) + out = os.path.join(folder, "%s_review_%d.png" % (tag, page // rows_per)) + sheet.save(out); print(out) + + +if __name__ == "__main__": + main() diff --git a/공유/기획/FirstRising/아이템/icon_shapes.py b/공유/기획/FirstRising/아이템/icon_shapes.py new file mode 100644 index 0000000..dffaaff --- /dev/null +++ b/공유/기획/FirstRising/아이템/icon_shapes.py @@ -0,0 +1,529 @@ +# -*- coding: utf-8 -*- +# 2026-10-02 PD 지시(자율 반복) — 형태 길잡이 모음을 만든다. +# a6 검토(에이전트가 직접 봄): 글자만(T)은 21종 중 4종만 합격, 실사풍 초안(D)은 물건 여러 개 · 인물이 섞임, "깨끗한 윤곽을 빌린 것(S)"은 8장 모두 형태가 읽히고 여백도 맞았다. +# → 종류마다 깨끗한 윤곽(물건 하나 · 투명 배경)을 모아 두고, 그 윤곽선만 ControlNet 으로 넘겨 목표 풍으로 새로 그린다. 색 · 질감은 넘어가지 않는다. +# 길잡이의 출처 셋: ① FR 장비 아이콘 원본 ② Layer Lab GUI Pro-FantasyRPG 아이콘(PD 보유 에셋) ③ 이 스크립트가 직접 그리는 단순 도형(원본이 없는 종류: 지팡이 · 화살통 · 뿔피리 · 오브 · 토템 · 투척 · 활) +# 합격한 생성물도 다시 길잡이로 쓸 수 있다(add_from). +# python icon_shapes.py → moba_anfg/shapes/<종류>__<출처>.png (1024 · 어두운 바탕 · 여백 통일) + shapes_sheet.png +import glob, io, math, os, sys +from PIL import Image, ImageDraw + +HERE = os.path.dirname(os.path.abspath(__file__)) +OUT = os.path.join(HERE, "moba_anfg", "shapes") +FR = r"C:\BurningTimes\FirstRising\Assets\GameAssets\UI\EquipmentItemIcon" +LL = r"C:\Users\sw\Downloads\Layer Lab\GUI Pro-FantasyRPG\ResourcesData\Sprites\Component" +LL_ITEM = os.path.join(LL, "Icon_ItemIcons", "NoShadow", "Original") +SIZE, FIT, BG = 1024, 0.70, (16, 16, 20) + +# a7 검토(에이전트가 직접 봄) 반영: +# · Layer Lab 길잡이는 뭉툭한 비례 · 굵은 외곽선이 결과에 남아 "캐주얼"이 샌다 → 투구 · 책 · 사슬 목걸이만 남기고 뺀다. +# · 벨트는 fr1351(정면 띠 + 버클)만 허리띠로 읽혔다. 단검은 화면 끝에서 잘렸다 → 가는 무기는 더 작게 놓는다. +# · 직접 그린 도형은 밋밋했다(활 · 뿔 · 오브 · 화살통 · 토템) → 장식 선을 더해 다시 그렸다(draw*2). 도끼 · 반지 · 방패 도형을 새로 그렸다. +# 종류 → FR 원본 번호 +FR_IDS = { + # a8 검토: fr1015(망치)는 가시 철퇴로, fr1043 · fr1071(단검)은 너무 작거나 삼지창으로, fr1029(활)는 0장 → 뺐다(직접 그린 도형으로 대신한다) + "blunt": [1057], # a12: fr1435(검)는 0/3(흰 납작면 · 잘림) → 직접 그린 검으로 대신 + "necklace": [1099, 1113, 1127, 1141], "gloves": [1169, 1183, 1197, 1211], "armor": [1239, 1253, 1267, 1281], + "belt": [1351], "boots": [1379, 1393, 1407, 1421], +} +# 종류 → Layer Lab 아이템 아이콘 이름(…icon_<이름>.png) +LL_NAMES = { + # a8 검토: Layer Lab 투구 · 목걸이 · book_0 은 0장(캐주얼 윤곽 · 책이 판으로 나옴) → book_1 만 남긴다 + "spellbook": ["book_1"], +} +# 가는 무기는 대각선으로 놓여 화면 끝에 닿기 쉽다 — 종류별로 더 작게 놓는다(기본 0.70) +FIT_BY_KIND = {"dagger": 0.74, "sword": 0.76, "staff": 0.74, "bow": 0.72, "throwing": 0.68, "blunt": 0.72, "hammer": 0.72, "axe": 0.74} +FG, LINE = (150, 150, 158), (70, 70, 78) # 도형의 면 · 안쪽 선(선화 추출이 테두리와 안쪽 선을 잡는다) + + +def place(im, fit=FIT): + """투명 그림을 물체 테두리로 잘라 1024 어두운 바탕 가운데에 같은 여백으로 놓는다""" + im = im.convert("RGBA") + box = im.getchannel("A").getbbox() + if box: + im = im.crop(box) + scale = SIZE * fit / float(max(im.size)) + im = im.resize((max(1, int(im.width * scale)), max(1, int(im.height * scale))), Image.LANCZOS) + rgb = Image.new("RGB", (SIZE, SIZE), BG) + rgb.paste(im, ((SIZE - im.width) // 2, (SIZE - im.height) // 2), im) + return rgb + + +def canvas(): + im = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0)) + return im, ImageDraw.Draw(im) + + +def draw_staff(kind): + """지팡이: 긴 자루 + 머리 장식(0 = 마름모 수정 · 1 = 둥근 보석을 감싼 갈고리)""" + im, d = canvas() + d.rounded_rectangle([490, 250, 534, 1000], 14, fill=FG, outline=LINE, width=6) + for y in (420, 760, 940): + d.rectangle([482, y, 542, y + 22], fill=FG, outline=LINE, width=5) + if kind == 0: + d.polygon([(512, 20), (600, 150), (512, 280), (424, 150)], fill=FG, outline=LINE) + d.line([(512, 20), (512, 280)], fill=LINE, width=6); d.line([(424, 150), (600, 150)], fill=LINE, width=6) + d.polygon([(430, 250), (512, 300), (594, 250), (560, 330), (464, 330)], fill=FG, outline=LINE) + else: + d.ellipse([432, 60, 592, 220], fill=FG, outline=LINE, width=8) + d.arc([380, 10, 644, 300], 110, 250, fill=FG, width=34); d.arc([380, 10, 644, 300], 290, 70, fill=FG, width=34) + d.polygon([(450, 250), (574, 250), (540, 320), (484, 320)], fill=FG, outline=LINE) + return im.rotate(-35, resample=Image.BICUBIC, expand=True) + + +def draw_quiver(): + """화살통: 원통 + 위로 나온 화살 깃 + 어깨끈""" + im, d = canvas() + for k, x in enumerate((400, 470, 540, 610)): + top = 120 + (k % 2) * 50 + d.rectangle([x - 7, top, x + 7, 420], fill=FG, outline=LINE, width=3) + d.polygon([(x - 34, top + 10), (x, top - 40), (x + 34, top + 10), (x + 34, top + 130), (x, top + 90), (x - 34, top + 130)], fill=FG, outline=LINE) + d.rounded_rectangle([340, 380, 680, 980], 60, fill=FG, outline=LINE, width=8) + d.rectangle([330, 380, 690, 450], fill=FG, outline=LINE, width=8) + d.rectangle([340, 820, 680, 870], fill=FG, outline=LINE, width=6) + d.arc([180, 300, 560, 900], 100, 260, fill=FG, width=30) + return im.rotate(-22, resample=Image.BICUBIC, expand=True) + + +def draw_horn(): + """뿔피리: 굽으면서 가늘어지는 뿔 + 테 둘""" + im, d = canvas() + cx, cy, R = 380, 300, 520 + outer, inner = [], [] + for k in range(0, 41): + t = k / 40.0 + a = math.radians(5 + 100 * t) + w = 150 * (1 - t) + 14 # 입구 쪽이 굵고 끝이 가늘다 + outer.append((cx + (R + w / 2) * math.cos(a), cy + (R + w / 2) * math.sin(a))) + inner.append((cx + (R - w / 2) * math.cos(a), cy + (R - w / 2) * math.sin(a))) + d.polygon(outer + inner[::-1], fill=FG, outline=LINE) + for t in (0.06, 0.45): + a = math.radians(5 + 100 * t); w = 150 * (1 - t) + 40 + d.line([(cx + (R + w / 2) * math.cos(a), cy + (R + w / 2) * math.sin(a)), (cx + (R - w / 2) * math.cos(a), cy + (R - w / 2) * math.sin(a))], fill=LINE, width=26) + return im + + +def draw_orb(): + """오브: 구슬 + 받침""" + im, d = canvas() + d.polygon([(400, 640), (624, 640), (580, 800), (444, 800)], fill=FG, outline=LINE) + d.rounded_rectangle([340, 800, 684, 880], 24, fill=FG, outline=LINE, width=8) + d.arc([300, 380, 724, 760], 20, 160, fill=FG, width=40) + d.ellipse([292, 140, 732, 580], fill=FG, outline=LINE, width=10) + d.arc([350, 190, 600, 440], 180, 270, fill=LINE, width=8) + return im + + +def draw_totem(): + """토템: 층층이 쌓은 나무 기둥 + 옆 날개 + 받침""" + im, d = canvas() + d.polygon([(250, 300), (400, 250), (400, 380)], fill=FG, outline=LINE); d.polygon([(774, 300), (624, 250), (624, 380)], fill=FG, outline=LINE) + for k, y in enumerate((100, 330, 560)): + d.rounded_rectangle([390, y, 634, y + 220], 26, fill=FG, outline=LINE, width=8) + d.ellipse([440, y + 60, 500, y + 120], outline=LINE, width=8); d.ellipse([524, y + 60, 584, y + 120], outline=LINE, width=8) + d.rectangle([470, y + 150, 554, y + 180], outline=LINE, width=8) + d.rounded_rectangle([340, 780, 684, 880], 20, fill=FG, outline=LINE, width=8) + return im + + +def draw_throwing(kind): + """투척: 0 = 쿠나이(잎 모양 날 + 자루 + 고리) · 1 = 네 날 표창""" + im, d = canvas() + if kind == 0: + d.polygon([(512, 60), (640, 420), (512, 560), (384, 420)], fill=FG, outline=LINE) + d.line([(512, 60), (512, 560)], fill=LINE, width=6) + d.rectangle([486, 560, 538, 800], fill=FG, outline=LINE, width=6) + d.ellipse([442, 790, 582, 930], outline=FG, width=34) + return im.rotate(-40, resample=Image.BICUBIC, expand=True) + for a in (0, 90, 180, 270): + r = math.radians(a) + tip = (512 + 420 * math.cos(r), 512 + 420 * math.sin(r)) + l = (512 + 120 * math.cos(r + 1.0), 512 + 120 * math.sin(r + 1.0)); rr = (512 + 120 * math.cos(r - 1.0), 512 + 120 * math.sin(r - 1.0)) + d.polygon([tip, l, rr], fill=FG, outline=LINE) + d.ellipse([412, 412, 612, 612], fill=FG, outline=LINE, width=10); d.ellipse([472, 472, 552, 552], fill=(0, 0, 0, 0), outline=LINE, width=8) + return im.rotate(20, resample=Image.BICUBIC, expand=True) + + +def draw_bow(): + """활: 굽은 몸체 + 곧은 시위 + 가운데 손잡이""" + im, d = canvas() + d.arc([200, 80, 900, 944], 100, 260, fill=FG, width=46) + top = (550 + 350 * math.cos(math.radians(260)), 512 + 432 * math.sin(math.radians(260))) + bot = (550 + 350 * math.cos(math.radians(100)), 512 + 432 * math.sin(math.radians(100))) + d.line([top, bot], fill=FG, width=8) + d.rounded_rectangle([170, 440, 250, 584], 20, fill=FG, outline=LINE, width=8) + return im.rotate(-30, resample=Image.BICUBIC, expand=True) + + +def arc_points(cx, cy, rx, ry, a0, a1, n=40): + """타원 호 위의 점들(도형의 굽은 변을 만들 때 쓴다)""" + return [(cx + rx * math.cos(math.radians(a0 + (a1 - a0) * k / float(n))), cy + ry * math.sin(math.radians(a0 + (a1 - a0) * k / float(n)))) for k in range(n + 1)] + + +def draw_axe(): + """도끼: 자루가 날을 관통 + 속이 찬 부채꼴 날(바깥이 넓은 호) + 반대쪽 작은 뿔 + 자루 끝 마개. + (a9 검토: 처음 도형은 날 안쪽이 파여 낫으로 읽혔고 날과 자루가 한 점으로만 닿았다 → 날을 자루에 넓게 붙였다.)""" + im, d = canvas() + blade = [(520, 150)] + arc_points(520, 320, 330, 290, -62, 62) + [(520, 490)] + d.polygon(blade, fill=FG, outline=LINE) + d.line(arc_points(520, 320, 270, 235, -55, 55), fill=LINE, width=7) # 날 안쪽의 연마선 + d.polygon([(500, 230), (360, 260), (330, 320), (360, 380), (500, 410)], fill=FG, outline=LINE) # 반대쪽 뿔 + d.rounded_rectangle([482, 90, 542, 990], 16, fill=FG, outline=LINE, width=6) + d.rounded_rectangle([466, 200, 558, 440], 14, outline=LINE, width=8) # 날을 무는 쇠테 + d.polygon([(482, 90), (512, 30), (542, 90)], fill=FG, outline=LINE) + for y in (640, 720, 800): + d.line([(482, y), (542, y)], fill=LINE, width=6) + d.rounded_rectangle([470, 930, 554, 1000], 14, fill=FG, outline=LINE, width=6) + return im.rotate(-35, resample=Image.BICUBIC, expand=True) + + +def draw_bow2(): + """활(다시): 굵은 리커브 몸체(끝이 바깥으로 말림) + 손잡이 + 끝 장식 + 시위""" + im, d = canvas() + outer = arc_points(620, 512, 400, 430, 115, 245) + inner = arc_points(650, 512, 370, 400, 245, 115) + d.polygon(outer + inner, fill=FG, outline=LINE) + d.line(arc_points(635, 512, 385, 415, 120, 240), fill=LINE, width=5) + top, bot = outer[-1], outer[0] + d.polygon([top, (top[0] + 90, top[1] - 40), (top[0] + 60, top[1] + 30)], fill=FG, outline=LINE) + d.polygon([bot, (bot[0] + 90, bot[1] + 40), (bot[0] + 60, bot[1] - 30)], fill=FG, outline=LINE) + d.line([(top[0] + 70, top[1] - 10), (bot[0] + 70, bot[1] + 10)], fill=FG, width=9) + d.rounded_rectangle([208, 420, 290, 604], 22, fill=FG, outline=LINE, width=8) + for y in (450, 512, 574): + d.line([(208, y), (290, y)], fill=LINE, width=6) + return im.rotate(-25, resample=Image.BICUBIC, expand=True) + + +def draw_horn2(): + """뿔피리(다시): 넓은 나팔 입구 + 테 둘 + 끈""" + im, d = canvas() + cx, cy, R = 300, 250, 520 + outer, inner = [], [] + for k in range(0, 41): + t = k / 40.0 + a = math.radians(0 + 95 * t) + w = 260 * (1 - t) ** 1.3 + 26 + outer.append((cx + (R + w / 2) * math.cos(a), cy + (R + w / 2) * math.sin(a))) + inner.append((cx + (R - w / 2) * math.cos(a), cy + (R - w / 2) * math.sin(a))) + d.polygon(outer + inner[::-1], fill=FG, outline=LINE) + d.ellipse([cx + R - 150, cy - 46, cx + R + 150, cy + 46], fill=FG, outline=LINE, width=9) # 나팔 입구 + for t in (0.14, 0.52, 0.8): + a = math.radians(95 * t); w = 260 * (1 - t) ** 1.3 + 50 + d.line([(cx + (R + w / 2) * math.cos(a), cy + (R + w / 2) * math.sin(a)), (cx + (R - w / 2) * math.cos(a), cy + (R - w / 2) * math.sin(a))], fill=LINE, width=30) + d.arc([330, 330, 760, 900], 190, 300, fill=FG, width=12) + return im + + +def draw_orb2(): + """오브(다시): 구슬 + 비스듬히 두른 금속 테 + 아래 작은 받침 발톱(받침대 기둥은 뺐다 — 트로피로 읽혔다)""" + im, d = canvas() + d.ellipse([232, 190, 792, 750], fill=FG, outline=LINE, width=12) + d.arc([300, 250, 560, 510], 180, 280, fill=LINE, width=9) + d.arc([170, 380, 854, 620], 0, 180, fill=LINE, width=34) + d.arc([170, 380, 854, 620], 0, 180, fill=FG, width=20) + for x in (360, 512, 664): + d.polygon([(x - 46, 730), (x + 46, 730), (x, 860)], fill=FG, outline=LINE) + return im + + +def draw_quiver2(): + """화살통(다시): 세운 원통 + 위로 나온 화살 셋(깃이 또렷) + 띠 + 어깨끈""" + im, d = canvas() + for k, x in enumerate((430, 512, 594)): + top = 90 + (k % 2) * 60 + d.rectangle([x - 8, top + 60, x + 8, 430], fill=FG, outline=LINE, width=3) + d.polygon([(x - 44, top + 40), (x - 8, top), (x - 8, top + 190), (x - 44, top + 230)], fill=FG, outline=LINE) + d.polygon([(x + 44, top + 40), (x + 8, top), (x + 8, top + 190), (x + 44, top + 230)], fill=FG, outline=LINE) + d.polygon([(360, 400), (664, 400), (630, 960), (394, 960)], fill=FG, outline=LINE) + d.ellipse([350, 370, 674, 440], fill=FG, outline=LINE, width=8) + d.line([(372, 560), (652, 560)], fill=LINE, width=22); d.line([(386, 820), (638, 820)], fill=LINE, width=22) + d.ellipse([462, 640, 562, 740], outline=LINE, width=8) + d.arc([560, 380, 860, 940], 270, 90, fill=FG, width=26) + return im.rotate(-15, resample=Image.BICUBIC, expand=True) + + +def draw_ring(): + """반지: 얇은 고리(비스듬히 본 타원) + 위쪽 보석과 물림쇠""" + im, d = canvas() + d.ellipse([222, 330, 802, 910], outline=FG, width=64) + d.ellipse([222, 330, 802, 910], outline=LINE, width=6); d.ellipse([286, 394, 738, 846], outline=LINE, width=6) + d.polygon([(400, 330), (624, 330), (580, 420), (444, 420)], fill=FG, outline=LINE) + d.polygon([(512, 110), (640, 240), (580, 350), (444, 350), (384, 240)], fill=FG, outline=LINE) + d.line([(384, 240), (640, 240)], fill=LINE, width=6); d.line([(512, 110), (444, 350)], fill=LINE, width=5); d.line([(512, 110), (580, 350)], fill=LINE, width=5) + return im.rotate(-18, resample=Image.BICUBIC, expand=True) + + +def draw_totem2(): + """토템(다시): 세 단으로 쌓은 기둥의 외곽 + 단마다 띠 + 꼭대기 뿔 + 받침(얼굴 구멍은 뺐다 — 만화 얼굴로 읽혔다)""" + im, d = canvas() + d.polygon([(420, 110), (360, 20), (470, 80)], fill=FG, outline=LINE); d.polygon([(604, 110), (664, 20), (554, 80)], fill=FG, outline=LINE) + for k, (y, w) in enumerate(((90, 250), (330, 290), (590, 250))): + d.rounded_rectangle([512 - w // 2, y, 512 + w // 2, y + 230], 30, fill=FG, outline=LINE, width=8) + d.line([(512 - w // 2 + 10, y + 180), (512 + w // 2 - 10, y + 180)], fill=LINE, width=14) + d.polygon([(512, y + 40), (560, y + 100), (512, y + 160), (464, y + 100)], outline=LINE) + d.polygon([(367, 400), (240, 360), (367, 500)], fill=FG, outline=LINE); d.polygon([(657, 400), (784, 360), (657, 500)], fill=FG, outline=LINE) + d.rounded_rectangle([350, 820, 674, 910], 20, fill=FG, outline=LINE, width=8) + return im + + +def draw_shield(): + """방패: 연 모양 몸체 + 안쪽 테 + 가운데 돌기 + 세로 · 가로 띠""" + im, d = canvas() + body = [(512, 80), (800, 170), (780, 560), (512, 950), (244, 560), (224, 170)] + d.polygon(body, fill=FG, outline=LINE) + inner = [(512, 150), (735, 220), (718, 540), (512, 850), (306, 540), (289, 220)] + d.line(inner + [inner[0]], fill=LINE, width=10) + d.line([(512, 150), (512, 850)], fill=LINE, width=8); d.line([(295, 400), (729, 400)], fill=LINE, width=8) + d.ellipse([432, 320, 592, 480], fill=FG, outline=LINE, width=10) + return im.rotate(-12, resample=Image.BICUBIC, expand=True) + + +def draw_dagger(): + """단검: 짧고 넓은 날 + 가로 날밑 + 짧은 손잡이 + 자루 끝 구슬""" + im, d = canvas() + d.polygon([(512, 60), (590, 220), (575, 600), (449, 600), (434, 220)], fill=FG, outline=LINE) + d.line([(512, 60), (512, 600)], fill=LINE, width=6) + d.polygon([(330, 590), (694, 590), (720, 630), (694, 670), (330, 670), (304, 630)], fill=FG, outline=LINE) + d.rounded_rectangle([474, 670, 550, 880], 14, fill=FG, outline=LINE, width=6) + for y in (720, 770, 820): + d.line([(474, y), (550, y)], fill=LINE, width=6) + d.ellipse([456, 866, 568, 978], fill=FG, outline=LINE, width=8) + return im.rotate(-40, resample=Image.BICUBIC, expand=True) + + +def draw_hammer(): + """망치: 직사각 덩어리 머리(양쪽 테) + 곧은 자루 + 자루 끝 마개 — 가시가 없어 철퇴와 구분된다""" + im, d = canvas() + d.rounded_rectangle([484, 300, 540, 990], 16, fill=FG, outline=LINE, width=6) + d.rounded_rectangle([250, 80, 774, 360], 30, fill=FG, outline=LINE, width=10) + d.rectangle([250, 80, 330, 360], outline=LINE, width=10); d.rectangle([694, 80, 774, 360], outline=LINE, width=10) + d.ellipse([452, 160, 572, 280], outline=LINE, width=9) + d.rounded_rectangle([462, 350, 562, 430], 12, fill=FG, outline=LINE, width=7) + for y in (620, 700, 780): + d.line([(484, y), (540, y)], fill=LINE, width=6) + d.rounded_rectangle([470, 930, 554, 1000], 14, fill=FG, outline=LINE, width=6) + return im.rotate(-35, resample=Image.BICUBIC, expand=True) + + +def draw_totem3(): + """토템(셋째): 통나무 기둥 하나에 새긴 얼굴 둘(눈 · 입 윤곽) + 머리 깃 + 옆 날개 + 받침 — 블록 쌓기로 읽히지 않게 기둥을 한 덩어리로 그린다""" + im, d = canvas() + d.polygon([(380, 330), (220, 250), (250, 400), (380, 430)], fill=FG, outline=LINE) + d.polygon([(644, 330), (804, 250), (774, 400), (644, 430)], fill=FG, outline=LINE) + for x in (440, 512, 584): + d.polygon([(x - 30, 130), (x, 20 if x == 512 else 50), (x + 30, 130)], fill=FG, outline=LINE) + d.rounded_rectangle([380, 120, 644, 860], 40, fill=FG, outline=LINE, width=10) + for y in (170, 510): + d.polygon([(420, y + 40), (490, y + 60), (480, y + 110), (420, y + 100)], outline=LINE) # 왼눈 + d.polygon([(604, y + 40), (534, y + 60), (544, y + 110), (604, y + 100)], outline=LINE) # 오른눈 + d.polygon([(512, y + 100), (540, y + 190), (484, y + 190)], outline=LINE) # 코 + d.rounded_rectangle([430, y + 220, 594, y + 280], 12, outline=LINE, width=8) # 입 + for x in (470, 512, 554): + d.line([(x, y + 220), (x, y + 280)], fill=LINE, width=6) + d.line([(380, 490), (644, 490)], fill=LINE, width=16) + d.rounded_rectangle([330, 850, 694, 940], 22, fill=FG, outline=LINE, width=8) + return im + + +def draw_helmet(kind): + """투구: 둥근 머리 + 얼굴 가리개(눈 틈) + 목 보호대. 0 = 꼭대기 볏 · 1 = 양옆 뿔""" + im, d = canvas() + if kind == 1: + # 뿔: 투구 옆면(밑동이 본체 안으로 겹친다)에서 솟아 위로 휘며 뾰족해진다 + d.polygon([(330, 420), (280, 540), (150, 430), (110, 250), (150, 90), (200, 250), (260, 360)], fill=FG, outline=LINE) + d.polygon([(694, 420), (744, 540), (874, 430), (914, 250), (874, 90), (824, 250), (764, 360)], fill=FG, outline=LINE) + d.polygon(arc_points(512, 470, 270, 330, 180, 360) + [(782, 760), (680, 900), (344, 900), (242, 760)], fill=FG, outline=LINE) + d.line(arc_points(512, 470, 270, 330, 180, 360), fill=LINE, width=10) + d.polygon([(300, 470), (724, 470), (700, 560), (540, 560), (512, 620), (484, 560), (324, 560)], fill=(0, 0, 0, 0), outline=LINE) # 눈 틈 + d.line([(512, 150), (512, 470)], fill=LINE, width=10) + d.line([(512, 620), (512, 900)], fill=LINE, width=8) + d.line([(242, 760), (782, 760)], fill=LINE, width=8) + if kind == 0: + d.polygon(arc_points(512, 300, 60, 260, 180, 360) + [(572, 300), (452, 300)], fill=FG, outline=LINE) + return im + + +def draw_sword2(): + """검(직접 그림): 넓은 날 + 가운데 홈(풀러) + 날개형 날밑 + 감은 손잡이 + 마름모 자루 끝. + (a12 검토: fr1435 윤곽은 너무 가늘어 흰 납작면 · 잘림이 났다 → 날을 넓히고 안쪽 선을 넣어 명암을 올릴 자리를 만든다.)""" + im, d = canvas() + d.polygon([(512, 30), (578, 170), (570, 640), (454, 640), (446, 170)], fill=FG, outline=LINE) + d.line([(512, 60), (512, 640)], fill=LINE, width=7) + d.line([(486, 190), (486, 640)], fill=LINE, width=4); d.line([(538, 190), (538, 640)], fill=LINE, width=4) + d.polygon([(290, 650), (350, 600), (454, 626), (570, 626), (674, 600), (734, 650), (700, 712), (600, 694), (424, 694), (324, 712)], fill=FG, outline=LINE) + d.ellipse([478, 630, 546, 698], outline=LINE, width=7) + d.rounded_rectangle([480, 694, 544, 880], 12, fill=FG, outline=LINE, width=6) + for y in (730, 770, 810, 850): + d.line([(480, y), (544, y - 18)], fill=LINE, width=5) + d.polygon([(512, 840), (576, 916), (512, 992), (448, 916)], fill=FG, outline=LINE) # 자루 끝(손잡이와 겹친다 — a13: 떨어져 보였다) + return im.rotate(-40, resample=Image.BICUBIC, expand=True) + + +def draw_dagger2(): + """단검(다시): 잎 모양의 짧은 날 + 홈 + 굽은 작은 날밑 + 손잡이 + 둥근 자루 끝. + (a12 검토: 처음 도형은 날밑이 날만큼 넓어 '뭉툭한 십자 덩어리'가 됐다 → 날을 길게, 날밑을 좁게.)""" + im, d = canvas() + d.polygon([(512, 90), (592, 300), (566, 640), (458, 640), (432, 300)], fill=FG, outline=LINE) + d.line([(512, 120), (512, 640)], fill=LINE, width=7) + d.line([(478, 320), (486, 640)], fill=LINE, width=4); d.line([(546, 320), (538, 640)], fill=LINE, width=4) + d.polygon([(370, 610), (420, 640), (604, 640), (654, 610), (650, 690), (590, 700), (434, 700), (374, 690)], fill=FG, outline=LINE) + d.rounded_rectangle([478, 700, 546, 870], 12, fill=FG, outline=LINE, width=6) + for y in (735, 775, 815): + d.line([(478, y), (546, y)], fill=LINE, width=5) + d.ellipse([458, 856, 566, 964], fill=FG, outline=LINE, width=8) + return im.rotate(-40, resample=Image.BICUBIC, expand=True) + + +def draw_axe3(): + """도끼(셋째): 자루에 넓게 붙은 속 찬 수염 도끼 머리(각진 다각형 + 안쪽 연마선) + 반대쪽 뿔 + 꼭대기 창끝. + (a12 검토: 부채꼴 호가 초승달 조각으로 떨어져 나왔다 → 호를 쓰지 않고 자루와 면으로 맞닿는 각진 머리로 그린다.)""" + im, d = canvas() + d.rounded_rectangle([480, 110, 544, 990], 16, fill=FG, outline=LINE, width=6) + d.polygon([(544, 170), (700, 110), (830, 210), (870, 350), (830, 500), (720, 600), (640, 470), (544, 450)], fill=FG, outline=LINE) + d.line([(690, 160), (790, 240), (822, 350), (790, 470), (716, 540)], fill=LINE, width=7) + d.polygon([(480, 240), (360, 300), (480, 380)], fill=FG, outline=LINE) + d.rounded_rectangle([462, 160, 562, 460], 14, outline=LINE, width=8) + d.polygon([(480, 110), (512, 30), (544, 110)], fill=FG, outline=LINE) + for y in (640, 720, 800): + d.line([(480, y), (544, y)], fill=LINE, width=6) + d.rounded_rectangle([468, 930, 556, 1000], 14, fill=FG, outline=LINE, width=6) + return im.rotate(-35, resample=Image.BICUBIC, expand=True) + + +def draw_axe4(): + """도끼(넷째): 속이 찬 반달 날 한 덩어리가 자루와 넓게 겹친다. 안쪽 윤곽은 날 끝 쪽의 연마선 한 줄뿐. + (a13 검토: 셋째 도형도 안쪽 윤곽이 고리로 읽혀 '속 빈 초승달'이 됐다 → 쇠테 · 겹선을 모두 없앴다.)""" + im, d = canvas() + d.rounded_rectangle([478, 110, 546, 990], 16, fill=FG, outline=LINE, width=6) + blade = [(500, 150)] + arc_points(500, 330, 360, 250, -80, 80, 30) + [(500, 510)] + d.polygon(blade, fill=FG, outline=LINE) + d.line(arc_points(500, 330, 315, 210, -62, 62, 30), fill=LINE, width=6) + d.polygon([(478, 250), (380, 330), (478, 410)], fill=FG, outline=LINE) + d.polygon([(478, 110), (512, 30), (546, 110)], fill=FG, outline=LINE) + for y in (660, 740, 820): + d.line([(478, y), (546, y)], fill=LINE, width=6) + d.rounded_rectangle([466, 930, 558, 1000], 14, fill=FG, outline=LINE, width=6) + return im.rotate(-35, resample=Image.BICUBIC, expand=True) + + +def draw_dagger3(): + """단검(셋째): 넓고 짧은 날(길이:폭 약 3:1) + 날 길이의 60% 에서 닫히는 가는 홈 + 작은 날밑 + 손잡이 + 자루 끝(손잡이와 겹침). + (a13 검토: 둘째 도형은 끝까지 그은 중심선이 날을 둘로 가르는 경계로 읽혀 두 갈래 날이 됐다.)""" + im, d = canvas() + d.polygon([(512, 110), (606, 330), (586, 650), (438, 650), (418, 330)], fill=FG, outline=LINE) + d.ellipse([498, 330, 526, 640], outline=LINE, width=5) + d.polygon([(360, 630), (438, 650), (586, 650), (664, 630), (650, 706), (374, 706)], fill=FG, outline=LINE) + d.rounded_rectangle([476, 700, 548, 880], 12, fill=FG, outline=LINE, width=6) + for y in (740, 785, 830): + d.line([(476, y), (548, y)], fill=LINE, width=5) + d.ellipse([454, 850, 570, 966], fill=FG, outline=LINE, width=8) + return im.rotate(-40, resample=Image.BICUBIC, expand=True) + + +def draw_bow3(): + """활(셋째): 가운데가 굵고 양 끝으로 가늘어지는 활대 + 바깥으로 젖힌 끝 고리 + 감은 손잡이 + 손잡이 위아래 마름모 장식 + 가는 시위 한 줄. + (a13 검토: 형태는 처음으로 온전했으나 굵기가 일정한 '매끈한 관'이라 밋밋했다. 시위가 굵으면 막대로 그려진다.)""" + im, d = canvas() + outer, inner = [], [] + for k in range(0, 61): + t = k / 60.0 + ang = math.radians(118 + 124 * t) # 활대의 중심선(왼쪽으로 볼록한 호) + w = 22 + 46 * (1 - abs(2 * t - 1)) ** 0.8 # 가운데 68 → 끝 22 + cx, cy = 640 + 400 * math.cos(ang), 512 + 440 * math.sin(ang) + nx, ny = math.cos(ang), math.sin(ang) + outer.append((cx + nx * w / 2, cy + ny * w / 2)); inner.append((cx - nx * w / 2, cy - ny * w / 2)) + d.polygon(outer + inner[::-1], fill=FG, outline=LINE) + top = (640 + 400 * math.cos(math.radians(242)), 512 + 440 * math.sin(math.radians(242))) + bot = (640 + 400 * math.cos(math.radians(118)), 512 + 440 * math.sin(math.radians(118))) + for (x, y), sgn in ((top, -1), (bot, 1)): + d.polygon([(x - 20, y), (x + 70, y + sgn * 70), (x + 96, y + sgn * 40), (x + 30, y - sgn * 24)], fill=FG, outline=LINE) # 젖힌 끝 + d.line([(top[0] + 78, top[1] - 52), (bot[0] + 78, bot[1] + 52)], fill=FG, width=5) # 시위 + d.rounded_rectangle([198, 430, 290, 594], 20, fill=FG, outline=LINE, width=7) + for y in (462, 496, 530, 564): + d.line([(198, y), (290, y - 14)], fill=LINE, width=5) + for y in (360, 664): + d.polygon([(250, y - 46), (292, y), (250, y + 46), (208, y)], fill=FG, outline=LINE) + return im.rotate(-25, resample=Image.BICUBIC, expand=True) + + +def draw_hammer2(): + """망치(다시): 직사각 머리 + 양 끝의 두꺼운 띠와 모서리 장식 + 가운데 문장 + 자루 목의 쇠테 + 감은 자루. + (a13 검토: 처음 도형은 '단순한 상자 머리'로 장식이 부족했다.)""" + im, d = canvas() + d.rounded_rectangle([482, 300, 542, 990], 16, fill=FG, outline=LINE, width=6) + d.rounded_rectangle([250, 90, 774, 360], 26, fill=FG, outline=LINE, width=10) + for x0, x1 in ((230, 330), (694, 794)): + d.rounded_rectangle([x0, 70, x1, 380], 18, fill=FG, outline=LINE, width=9) + d.line([(x0 + 50, 70), (x0 + 50, 380)], fill=LINE, width=5) + d.polygon([(512, 140), (590, 225), (512, 310), (434, 225)], outline=LINE) + d.line([(512, 140), (512, 310)], fill=LINE, width=5); d.line([(434, 225), (590, 225)], fill=LINE, width=5) + d.polygon([(482, 90), (512, 36), (542, 90)], fill=FG, outline=LINE) + d.rounded_rectangle([458, 350, 566, 440], 12, fill=FG, outline=LINE, width=7) + for y in (560, 610, 660, 710, 760, 810): + d.line([(482, y), (542, y - 18)], fill=LINE, width=5) + d.rounded_rectangle([466, 920, 558, 1000], 14, fill=FG, outline=LINE, width=6) + return im.rotate(-35, resample=Image.BICUBIC, expand=True) + + +DRAWN = { + "staff": [("draw0", lambda: draw_staff(0)), ("draw1", lambda: draw_staff(1))], + "quiver": [("draw2", draw_quiver2)], "horn": [("draw2", draw_horn2)], "orb": [("draw2", draw_orb2)], "totem": [("draw3", draw_totem3)], + "throwing": [("draw0", lambda: draw_throwing(0)), ("draw1", lambda: draw_throwing(1))], "bow": [("draw3", draw_bow3)], + "axe": [("draw4", draw_axe4)], "ring": [("draw0", draw_ring)], "shield": [("draw0", draw_shield)], + "dagger": [("draw3", draw_dagger3)], "hammer": [("draw2", draw_hammer2)], "helmet": [("draw0", lambda: draw_helmet(0)), ("draw1", lambda: draw_helmet(1))], + "sword": [("draw2", draw_sword2)], +} + + +def add_from(kind, path, label): + """합격한 생성물(투명 PNG)을 길잡이 모음에 더한다 — 다른 색 · 장식으로 다시 그릴 때의 형태가 된다. active.txt 에도 올린다.""" + os.makedirs(OUT, exist_ok=True) + name = "%s__%s.png" % (kind, label) + place(Image.open(path), FIT_BY_KIND.get(kind, FIT)).save(os.path.join(OUT, name)) + act = os.path.join(OUT, "active.txt") + have = io.open(act, encoding="utf-8").read().split() if os.path.exists(act) else [] + if name not in have: + io.open(act, "a", encoding="utf-8").write(name + "\n") + + +def main(): + os.makedirs(OUT, exist_ok=True) + active = [] # 이번 정의로 쓰는 길잡이(예전 정의로 만든 파일은 지우지 않고 폴더에 남긴다 — 생성 스크립트는 active.txt 만 본다) + for kind, ids in FR_IDS.items(): + for gid in ids: + name = "%s__fr%d.png" % (kind, gid) + place(Image.open(os.path.join(FR, "%d.png" % gid)), FIT_BY_KIND.get(kind, FIT)).save(os.path.join(OUT, name)); active.append(name) + for kind, names in LL_NAMES.items(): + for nm in names: + hits = glob.glob(os.path.join(LL_ITEM, "*icon_%s.png" % nm)) + if not hits: + print("Layer Lab 에 없음:", nm); continue + name = "%s__ll_%s.png" % (kind, nm) + place(Image.open(hits[0]), FIT_BY_KIND.get(kind, FIT)).save(os.path.join(OUT, name)); active.append(name) + for kind, items in DRAWN.items(): + for label, fn in items: + name = "%s__%s.png" % (kind, label) + place(fn(), FIT_BY_KIND.get(kind, FIT)).save(os.path.join(OUT, name)); active.append(name) + # add_from 으로 더한 합격본 길잡이(gen*)는 계속 쓴다 + active += [os.path.basename(f) for f in glob.glob(os.path.join(OUT, "*__gen*.png"))] + active = sorted(set(active)) + io.open(os.path.join(OUT, "active.txt"), "w", encoding="utf-8").write("\n".join(active) + "\n") + cell, pad, cols = 160, 4, 10 + rows = (len(active) + cols - 1) // cols + sheet = Image.new("RGB", (cols * (cell + pad) + pad, rows * (cell + pad) + pad), (40, 40, 44)) + d = ImageDraw.Draw(sheet) + for i, name in enumerate(active): + x, y = pad + (i % cols) * (cell + pad), pad + (i // cols) * (cell + pad) + sheet.paste(Image.open(os.path.join(OUT, name)).resize((cell, cell), Image.LANCZOS), (x, y)) + d.text((x + 3, y + 2), name[:-4], fill=(240, 220, 160)) + sheet.save(os.path.join(OUT, "shapes_sheet.png")) + print("shapes %d (%d 종류) -> %s" % (len(active), len(set(n.split("__")[0] for n in active)), OUT)) + + +if __name__ == "__main__": + # python icon_shapes.py → 길잡이 모음을 다시 만든다 + # python icon_shapes.py add <종류> <투명 PNG 경로> <이름> → 그림 한 장의 윤곽을 길잡이로 등록(이름은 gen 으로 시작해야 다시 만들 때 남는다) + if len(sys.argv) > 4 and sys.argv[1] == "add": + add_from(sys.argv[2], sys.argv[3], sys.argv[4]); print("등록", sys.argv[2], sys.argv[4]) + else: + main() diff --git a/공유/기획/FirstRising/아이템/moba_anfg/a22_compare.png b/공유/기획/FirstRising/아이템/moba_anfg/a22_compare.png new file mode 100644 index 0000000..1a5f3b9 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/a22_compare.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/a25_compare.png b/공유/기획/FirstRising/아이템/moba_anfg/a25_compare.png new file mode 100644 index 0000000..e3e4dbd Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/a25_compare.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/a28_compare.png b/공유/기획/FirstRising/아이템/moba_anfg/a28_compare.png new file mode 100644 index 0000000..95f78bc Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/a28_compare.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/approved_sheet.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/approved_sheet.png new file mode 100644 index 0000000..27bdfcb Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/approved_sheet.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_armor.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_armor.png new file mode 100644 index 0000000..f95f535 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_armor.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_boots.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_boots.png new file mode 100644 index 0000000..1c1f962 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_boots.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_gloves_a.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_gloves_a.png new file mode 100644 index 0000000..49431b1 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_gloves_a.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_gloves_b.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_gloves_b.png new file mode 100644 index 0000000..9da3239 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_gloves_b.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_helmet.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_helmet.png new file mode 100644 index 0000000..ddb41d9 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_helmet.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_necklace.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_necklace.png new file mode 100644 index 0000000..a1a6e16 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_necklace.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_ring.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_ring.png new file mode 100644 index 0000000..8e90d1b Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd1_ring.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_armor.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_armor.png new file mode 100644 index 0000000..009d038 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_armor.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_boots.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_boots.png new file mode 100644 index 0000000..054940f Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_boots.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_dagger.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_dagger.png new file mode 100644 index 0000000..69fa032 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_dagger.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_magicdagger.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_magicdagger.png new file mode 100644 index 0000000..ae367c1 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_magicdagger.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_necklace.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_necklace.png new file mode 100644 index 0000000..9e6b990 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_necklace.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_ring.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_ring.png new file mode 100644 index 0000000..8304149 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_ring.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_shield.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_shield.png new file mode 100644 index 0000000..deb794c Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_shield.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_sword.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_sword.png new file mode 100644 index 0000000..4a48038 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd2_sword.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd_target_reference.png b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd_target_reference.png new file mode 100644 index 0000000..7829e52 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd_target_reference.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/approved/pd_target_reference.webp b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd_target_reference.webp new file mode 100644 index 0000000..4bcc2cb Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/approved/pd_target_reference.webp differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_a14.json b/공유/기획/FirstRising/아이템/moba_anfg/best_a14.json new file mode 100644 index 0000000..59595e7 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_a14.json @@ -0,0 +1,10 @@ +{ + "a14_armor-fr1267_1": "a14_armor-fr1267_s07_1.png", + "a14_belt-fr1351_0": "a14_belt-fr1351_s07_0.png", + "a14_boots-fr1379_1": "a14_boots-fr1379_s07_1.png", + "a14_gloves-fr1169_1": "a14_gloves-fr1169_s07_1.png", + "a14_necklace-fr1099_0": "a14_necklace-fr1099_s07_0.png", + "a14_shield-draw0_0": "a14_shield-draw0_s07_0.png", + "a14_spellbook-llbook1_0": "a14_spellbook-llbook1_s07_0.png", + "a14_totem-draw3_1": "a14_totem-draw3_s07_1.png" +} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_a17.json b/공유/기획/FirstRising/아이템/moba_anfg/best_a17.json new file mode 100644 index 0000000..d41890c --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_a17.json @@ -0,0 +1,15 @@ +{ + "a17_armor-fr1253_1": "a17_armor-fr1253_s07_1.png", + "a17_armor-fr1267_1": "a17_armor-fr1267_s07_1.png", + "a17_boots-fr1393_0": "a17_boots-fr1393_s07_0.png", + "a17_gloves-fr1183_0": "a17_gloves-fr1183_s07_0.png", + "a17_necklace-fr1127_0": "a17_necklace-fr1127_s07_0.png", + "a17_orb-genmoba1_0": "a17_orb-genmoba1_s07_0.png", + "a17_helmet-genmoba0_0": "a17_helmet-genmoba0_s07_0.png", + "a17_staff-draw1_1": "a17_staff-draw1_s07_1.png", + "a17_blunt-fr1057_1": "a17_blunt-fr1057_s07_1.png", + "a17_totem-draw3_1": "a17_totem-draw3_s07_1.png", + "a17_spellbook-llbook1_1": "a17_spellbook-llbook1_s07_1.png", + "a17_belt-fr1351_1": "a17_belt-fr1351_s07_1.png", + "a17_throwing-draw0_0": "a17_throwing-draw0_s07_0.png" +} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_a19.json b/공유/기획/FirstRising/아이템/moba_anfg/best_a19.json new file mode 100644 index 0000000..141db7c --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_a19.json @@ -0,0 +1,7 @@ +{ + "a19_sword-genxl1_1": "a19_sword-genxl1_s07_1.png", + "a19_ring-genxl0_1": "a19_ring-genxl0_s07_1.png", + "a19_quiver-genxl1_0": "a19_quiver-genxl1_s07_0.png", + "a19_shield-genxl1_0": "a19_shield-genxl1_s07_0.png", + "a19_helmet-genxl1_0": "a19_helmet-genxl1_s07_0.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_a20.json b/공유/기획/FirstRising/아이템/moba_anfg/best_a20.json new file mode 100644 index 0000000..a41f012 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_a20.json @@ -0,0 +1,6 @@ +{ + "a20_dagger-genxlb0_1": "a20_dagger-genxlb0_s07_1.png", + "a20_bow-genxlb0_1": "a20_bow-genxlb0_s07_1.png", + "a20_belt-genxlb0_1": "a20_belt-genxlb0_s07_1.png", + "a20_staff-genxlb0_2": "a20_staff-genxlb0_s07_2.png" +} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_a21.json b/공유/기획/FirstRising/아이템/moba_anfg/best_a21.json new file mode 100644 index 0000000..4c7bc5e --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_a21.json @@ -0,0 +1,4 @@ +{ + "a21_necklace-genxlc0_2": "a21_necklace-genxlc0_s07_2.png", + "a21_spellbook-genxlc0_0": "a21_spellbook-genxlc0_s07_0.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_a23.json b/공유/기획/FirstRising/아이템/moba_anfg/best_a23.json new file mode 100644 index 0000000..d4a9095 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_a23.json @@ -0,0 +1,10 @@ +{ + "a23_axe-genxld1_1": "a23_axe-genxld1_s07_1.png", + "a23_hammer-genxld1_2": "a23_hammer-genxld1_s07_2.png", + "a23_helmet-genxld2_1": "a23_helmet-genxld2_s07_1.png", + "a23_helmet-genxld3_2": "a23_helmet-genxld3_s07_2.png", + "a23_quiver-genxld2_0": "a23_quiver-genxld2_s07_0.png", + "a23_ring-genxld1_0": "a23_ring-genxld1_s07_0.png", + "a23_ring-genxld3_0": "a23_ring-genxld3_s07_0.png", + "a23_shield-genxld3_0": "a23_shield-genxld3_s07_0.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_a24.json b/공유/기획/FirstRising/아이템/moba_anfg/best_a24.json new file mode 100644 index 0000000..2bac07d --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_a24.json @@ -0,0 +1,15 @@ +{ + "a24_axe-genxld1_0": "a24_axe-genxld1_s07_0.png", + "a24_dagger-genxlb0_3": "a24_dagger-genxlb0_s07_3.png", + "a24_dagger-genxlb0_2": "a24_dagger-genxlb0_s07_2.png", + "a24_hammer-genxld0_3": "a24_hammer-genxld0_s07_3.png", + "a24_hammer-genxld1_3": "a24_hammer-genxld1_s07_3.png", + "a24_horn-draw2_0": "a24_horn-draw2_s07_0.png", + "a24_horn-draw2_2": "a24_horn-draw2_s07_2.png", + "a24_orb-genmoba1_1": "a24_orb-genmoba1_s07_1.png", + "a24_orb-genmoba1_0": "a24_orb-genmoba1_s07_0.png", + "a24_spellbook-genxlc0_0": "a24_spellbook-genxlc0_s07_0.png", + "a24_spellbook-genxlc0_3": "a24_spellbook-genxlc0_s07_3.png", + "a24_sword-genxl1_1": "a24_sword-genxl1_s07_1.png", + "a24_sword-genxl1_0": "a24_sword-genxl1_s07_0.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_a26.json b/공유/기획/FirstRising/아이템/moba_anfg/best_a26.json new file mode 100644 index 0000000..d97fcb7 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_a26.json @@ -0,0 +1,26 @@ +{ + "a26_armor-fr1253_0": "a26_armor-fr1253_s07_0.png", + "a26_armor-fr1281_2": "a26_armor-fr1281_s07_2.png", + "a26_belt-fr1351_0": "a26_belt-fr1351_s07_0.png", + "a26_belt-genxlb0_2": "a26_belt-genxlb0_s07_2.png", + "a26_blunt-fr1057_0": "a26_blunt-fr1057_s07_0.png", + "a26_boots-fr1393_2": "a26_boots-fr1393_s07_2.png", + "a26_gloves-fr1183_0": "a26_gloves-fr1183_s07_0.png", + "a26_gloves-fr1197_1": "a26_gloves-fr1197_s07_1.png", + "a26_helmet-genmoba0_1": "a26_helmet-genmoba0_s07_1.png", + "a26_horn-draw2_0": "a26_horn-draw2_s07_0.png", + "a26_necklace-fr1099_0": "a26_necklace-fr1099_s07_0.png", + "a26_necklace-fr1127_1": "a26_necklace-fr1127_s07_1.png", + "a26_shield-draw0_0": "a26_shield-draw0_s07_0.png", + "a26_staff-genxlb0_1": "a26_staff-genxlb0_s07_1.png", + "a26_throwing-draw0_1": "a26_throwing-draw0_s07_1.png", + "a26_totem-draw3_0": "a26_totem-draw3_s07_0.png", + "a26_dagger-genxlb0_2": "a26_dagger-genxlb0_s07_2.png", + "a26_bow-genxlb0_1": "a26_bow-genxlb0_s07_1.png", + "a26_spellbook-genxlc0_0": "a26_spellbook-genxlc0_s07_0.png", + "a26_axe-genxld1_2": "a26_axe-genxld1_s07_2.png", + "a26_hammer-genxld0_1": "a26_hammer-genxld0_s07_1.png", + "a26_hammer-genxld1_1": "a26_hammer-genxld1_s07_1.png", + "a26_ring-genxld2_2": "a26_ring-genxld2_s07_2.png", + "a26_ring-genxld3_1": "a26_ring-genxld3_s07_1.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color.json b/공유/기획/FirstRising/아이템/moba_anfg/best_color.json new file mode 100644 index 0000000..bd772a5 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_color.json @@ -0,0 +1,34 @@ +{ + "a27_sword-genxl1_1": "a27_sword-genxl1_s07_1.png", + "a27_dagger-genxlb0_1": "a27_dagger-genxlb0_s07_1.png", + "a27_axe-genxld1_0": "a27_axe-genxld1_s07_0.png", + "a26_blunt-fr1057_0": "a26_blunt-fr1057_s07_0.png", + "a27_hammer-genxld1_1": "a27_hammer-genxld1_s07_1.png", + "a27_hammer-genxld0_1": "a27_hammer-genxld0_s07_1.png", + "a26_bow-genxlb0_1": "a26_bow-genxlb0_s07_1.png", + "a26_staff-genxlb0_1": "a26_staff-genxlb0_s07_1.png", + "a27_staff-draw1_0": "a27_staff-draw1_s07_0.png", + "a26_throwing-draw0_1": "a26_throwing-draw0_s07_1.png", + "a27_orb-genmoba1_0": "a27_orb-genmoba1_s07_0.png", + "a26_spellbook-genxlc0_0": "a26_spellbook-genxlc0_s07_0.png", + "a27_totem-draw3_1": "a27_totem-draw3_s07_1.png", + "a26_horn-draw2_0": "a26_horn-draw2_s07_0.png", + "a27_quiver-genxld2_0": "a27_quiver-genxld2_s07_0.png", + "a27_shield-draw0_1": "a27_shield-draw0_s07_1.png", + "a27_shield-genxld3_1": "a27_shield-genxld3_s07_1.png", + "a27_armor-fr1253_1": "a27_armor-fr1253_s07_1.png", + "a27_armor-fr1267_1": "a27_armor-fr1267_s07_1.png", + "a26_armor-fr1281_2": "a26_armor-fr1281_s07_2.png", + "a27_helmet-genxld3_0": "a27_helmet-genxld3_s07_0.png", + "a26_gloves-fr1197_1": "a26_gloves-fr1197_s07_1.png", + "a27_gloves-fr1197_1": "a27_gloves-fr1197_s07_1.png", + "a27_boots-fr1379_1": "a27_boots-fr1379_s07_1.png", + "a27_boots-fr1407_0": "a27_boots-fr1407_s07_0.png", + "a26_belt-genxlb0_2": "a26_belt-genxlb0_s07_2.png", + "a27_belt-fr1351_0": "a27_belt-fr1351_s07_0.png", + "a27_ring-genxld2_0": "a27_ring-genxld2_s07_0.png", + "a27_ring-genxld3_0": "a27_ring-genxld3_s07_0.png", + "a26_ring-genxld3_1": "a26_ring-genxld3_s07_1.png", + "a27_necklace-fr1113_0": "a27_necklace-fr1113_s07_0.png", + "a27_necklace-genxlc0_1": "a27_necklace-genxlc0_s07_1.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/armor_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/armor_01.png new file mode 100644 index 0000000..98395da Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/armor_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/armor_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/armor_02.png new file mode 100644 index 0000000..d8533de Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/armor_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/armor_03.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/armor_03.png new file mode 100644 index 0000000..067fd12 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/armor_03.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/axe_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/axe_01.png new file mode 100644 index 0000000..c6dda7b Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/axe_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/belt_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/belt_01.png new file mode 100644 index 0000000..c1c0bba Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/belt_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/belt_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/belt_02.png new file mode 100644 index 0000000..c3c2c26 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/belt_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/blunt_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/blunt_01.png new file mode 100644 index 0000000..667996c Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/blunt_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/boots_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/boots_01.png new file mode 100644 index 0000000..d4c2435 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/boots_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/boots_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/boots_02.png new file mode 100644 index 0000000..3d773a8 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/boots_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/bow_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/bow_01.png new file mode 100644 index 0000000..8bc0ee1 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/bow_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/dagger_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/dagger_01.png new file mode 100644 index 0000000..84488ec Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/dagger_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/final_sheet.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/final_sheet.png new file mode 100644 index 0000000..7538a51 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/final_sheet.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/gloves_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/gloves_01.png new file mode 100644 index 0000000..3dba532 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/gloves_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/gloves_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/gloves_02.png new file mode 100644 index 0000000..d19c0b6 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/gloves_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/hammer_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/hammer_01.png new file mode 100644 index 0000000..97673c8 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/hammer_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/hammer_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/hammer_02.png new file mode 100644 index 0000000..e18c9d0 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/hammer_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/helmet_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/helmet_01.png new file mode 100644 index 0000000..50ec79c Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/helmet_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/horn_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/horn_01.png new file mode 100644 index 0000000..fb717d0 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/horn_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/index.json b/공유/기획/FirstRising/아이템/moba_anfg/best_color/index.json new file mode 100644 index 0000000..95041b7 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_color/index.json @@ -0,0 +1,130 @@ +[ + { + "icon": "sword_01.png", + "source": "a27_sword-genxl1_s07_1.png" + }, + { + "icon": "dagger_01.png", + "source": "a27_dagger-genxlb0_s07_1.png" + }, + { + "icon": "axe_01.png", + "source": "a27_axe-genxld1_s07_0.png" + }, + { + "icon": "blunt_01.png", + "source": "a26_blunt-fr1057_s07_0.png" + }, + { + "icon": "hammer_01.png", + "source": "a27_hammer-genxld0_s07_1.png" + }, + { + "icon": "hammer_02.png", + "source": "a27_hammer-genxld1_s07_1.png" + }, + { + "icon": "bow_01.png", + "source": "a26_bow-genxlb0_s07_1.png" + }, + { + "icon": "staff_01.png", + "source": "a26_staff-genxlb0_s07_1.png" + }, + { + "icon": "staff_02.png", + "source": "a27_staff-draw1_s07_0.png" + }, + { + "icon": "armor_01.png", + "source": "a26_armor-fr1281_s07_2.png" + }, + { + "icon": "armor_02.png", + "source": "a27_armor-fr1253_s07_1.png" + }, + { + "icon": "armor_03.png", + "source": "a27_armor-fr1267_s07_1.png" + }, + { + "icon": "helmet_01.png", + "source": "a27_helmet-genxld3_s07_0.png" + }, + { + "icon": "gloves_01.png", + "source": "a26_gloves-fr1197_s07_1.png" + }, + { + "icon": "gloves_02.png", + "source": "a27_gloves-fr1197_s07_1.png" + }, + { + "icon": "belt_01.png", + "source": "a26_belt-genxlb0_s07_2.png" + }, + { + "icon": "belt_02.png", + "source": "a27_belt-fr1351_s07_0.png" + }, + { + "icon": "boots_01.png", + "source": "a27_boots-fr1379_s07_1.png" + }, + { + "icon": "boots_02.png", + "source": "a27_boots-fr1407_s07_0.png" + }, + { + "icon": "ring_01.png", + "source": "a26_ring-genxld3_s07_1.png" + }, + { + "icon": "ring_02.png", + "source": "a27_ring-genxld2_s07_0.png" + }, + { + "icon": "ring_03.png", + "source": "a27_ring-genxld3_s07_0.png" + }, + { + "icon": "necklace_01.png", + "source": "a27_necklace-fr1113_s07_0.png" + }, + { + "icon": "necklace_02.png", + "source": "a27_necklace-genxlc0_s07_1.png" + }, + { + "icon": "shield_01.png", + "source": "a27_shield-draw0_s07_1.png" + }, + { + "icon": "shield_02.png", + "source": "a27_shield-genxld3_s07_1.png" + }, + { + "icon": "quiver_01.png", + "source": "a27_quiver-genxld2_s07_0.png" + }, + { + "icon": "spellbook_01.png", + "source": "a26_spellbook-genxlc0_s07_0.png" + }, + { + "icon": "throwing_01.png", + "source": "a26_throwing-draw0_s07_1.png" + }, + { + "icon": "orb_01.png", + "source": "a27_orb-genmoba1_s07_0.png" + }, + { + "icon": "totem_01.png", + "source": "a27_totem-draw3_s07_1.png" + }, + { + "icon": "horn_01.png", + "source": "a26_horn-draw2_s07_0.png" + } +] \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/necklace_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/necklace_01.png new file mode 100644 index 0000000..133246a Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/necklace_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/necklace_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/necklace_02.png new file mode 100644 index 0000000..897ce47 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/necklace_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/orb_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/orb_01.png new file mode 100644 index 0000000..f639022 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/orb_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/quiver_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/quiver_01.png new file mode 100644 index 0000000..938d47c Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/quiver_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/ring_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/ring_01.png new file mode 100644 index 0000000..57fb710 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/ring_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/ring_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/ring_02.png new file mode 100644 index 0000000..1972416 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/ring_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/ring_03.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/ring_03.png new file mode 100644 index 0000000..a98d911 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/ring_03.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/shield_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/shield_01.png new file mode 100644 index 0000000..bd595cc Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/shield_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/shield_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/shield_02.png new file mode 100644 index 0000000..fe9afe2 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/shield_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/spellbook_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/spellbook_01.png new file mode 100644 index 0000000..3dd5318 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/spellbook_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/staff_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/staff_01.png new file mode 100644 index 0000000..15c6bb7 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/staff_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/staff_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/staff_02.png new file mode 100644 index 0000000..c0f98ce Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/staff_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/sword_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/sword_01.png new file mode 100644 index 0000000..e6c0ea1 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/sword_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/throwing_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/throwing_01.png new file mode 100644 index 0000000..4ba7a30 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/throwing_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_color/totem_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_color/totem_01.png new file mode 100644 index 0000000..da23f01 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_color/totem_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_final.json b/공유/기획/FirstRising/아이템/moba_anfg/best_final.json new file mode 100644 index 0000000..a717f60 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_final.json @@ -0,0 +1,27 @@ +{ + "a14_armor-fr1267_1": "a14_armor-fr1267_s07_1.png", + "a14_belt-fr1351_0": "a14_belt-fr1351_s07_0.png", + "a14_boots-fr1379_1": "a14_boots-fr1379_s07_1.png", + "a14_gloves-fr1169_1": "a14_gloves-fr1169_s07_1.png", + "a14_necklace-fr1099_0": "a14_necklace-fr1099_s07_0.png", + "a14_shield-draw0_0": "a14_shield-draw0_s07_0.png", + "a14_totem-draw3_1": "a14_totem-draw3_s07_1.png", + "a17_armor-fr1253_1": "a17_armor-fr1253_s07_1.png", + "a17_armor-fr1267_1": "a17_armor-fr1267_s07_1.png", + "a17_boots-fr1393_0": "a17_boots-fr1393_s07_0.png", + "a17_gloves-fr1183_0": "a17_gloves-fr1183_s07_0.png", + "a17_necklace-fr1127_0": "a17_necklace-fr1127_s07_0.png", + "a17_orb-genmoba1_0": "a17_orb-genmoba1_s07_0.png", + "a17_helmet-genmoba0_0": "a17_helmet-genmoba0_s07_0.png", + "a17_staff-draw1_1": "a17_staff-draw1_s07_1.png", + "a17_blunt-fr1057_1": "a17_blunt-fr1057_s07_1.png", + "a17_totem-draw3_1": "a17_totem-draw3_s07_1.png", + "a17_belt-fr1351_1": "a17_belt-fr1351_s07_1.png", + "a19_sword-genxl1_1": "a19_sword-genxl1_s07_1.png", + "a19_ring-genxl0_1": "a19_ring-genxl0_s07_1.png", + "a19_quiver-genxl1_0": "a19_quiver-genxl1_s07_0.png", + "a19_shield-genxl1_0": "a19_shield-genxl1_s07_0.png", + "a20_belt-genxlb0_1": "a20_belt-genxlb0_s07_1.png", + "a21_necklace-genxlc0_2": "a21_necklace-genxlc0_s07_2.png", + "a21_spellbook-genxlc0_0": "a21_spellbook-genxlc0_s07_0.png" +} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_final2.json b/공유/기획/FirstRising/아이템/moba_anfg/best_final2.json new file mode 100644 index 0000000..0941dde --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_final2.json @@ -0,0 +1,35 @@ +{ + "a14_armor-fr1267_1": "a14_armor-fr1267_s07_1.png", + "a14_belt-fr1351_0": "a14_belt-fr1351_s07_0.png", + "a14_boots-fr1379_1": "a14_boots-fr1379_s07_1.png", + "a14_gloves-fr1169_1": "a14_gloves-fr1169_s07_1.png", + "a14_necklace-fr1099_0": "a14_necklace-fr1099_s07_0.png", + "a14_shield-draw0_0": "a14_shield-draw0_s07_0.png", + "a14_totem-draw3_1": "a14_totem-draw3_s07_1.png", + "a17_armor-fr1253_1": "a17_armor-fr1253_s07_1.png", + "a17_armor-fr1267_1": "a17_armor-fr1267_s07_1.png", + "a17_boots-fr1393_0": "a17_boots-fr1393_s07_0.png", + "a17_gloves-fr1183_0": "a17_gloves-fr1183_s07_0.png", + "a17_necklace-fr1127_0": "a17_necklace-fr1127_s07_0.png", + "a17_orb-genmoba1_0": "a17_orb-genmoba1_s07_0.png", + "a17_helmet-genmoba0_0": "a17_helmet-genmoba0_s07_0.png", + "a17_staff-draw1_1": "a17_staff-draw1_s07_1.png", + "a17_blunt-fr1057_1": "a17_blunt-fr1057_s07_1.png", + "a17_totem-draw3_1": "a17_totem-draw3_s07_1.png", + "a17_belt-fr1351_1": "a17_belt-fr1351_s07_1.png", + "a19_sword-genxl1_1": "a19_sword-genxl1_s07_1.png", + "a19_ring-genxl0_1": "a19_ring-genxl0_s07_1.png", + "a19_quiver-genxl1_0": "a19_quiver-genxl1_s07_0.png", + "a19_shield-genxl1_0": "a19_shield-genxl1_s07_0.png", + "a20_belt-genxlb0_1": "a20_belt-genxlb0_s07_1.png", + "a21_necklace-genxlc0_2": "a21_necklace-genxlc0_s07_2.png", + "a21_spellbook-genxlc0_0": "a21_spellbook-genxlc0_s07_0.png", + "a23_axe-genxld1_1": "a23_axe-genxld1_s07_1.png", + "a23_hammer-genxld1_2": "a23_hammer-genxld1_s07_2.png", + "a23_helmet-genxld2_1": "a23_helmet-genxld2_s07_1.png", + "a23_helmet-genxld3_2": "a23_helmet-genxld3_s07_2.png", + "a23_quiver-genxld2_0": "a23_quiver-genxld2_s07_0.png", + "a23_ring-genxld1_0": "a23_ring-genxld1_s07_0.png", + "a23_ring-genxld3_0": "a23_ring-genxld3_s07_0.png", + "a23_shield-genxld3_0": "a23_shield-genxld3_s07_0.png" +} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_final3.json b/공유/기획/FirstRising/아이템/moba_anfg/best_final3.json new file mode 100644 index 0000000..8ff7f5e --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_final3.json @@ -0,0 +1,48 @@ +{ + "a14_armor-fr1267_1": "a14_armor-fr1267_s07_1.png", + "a14_belt-fr1351_0": "a14_belt-fr1351_s07_0.png", + "a14_boots-fr1379_1": "a14_boots-fr1379_s07_1.png", + "a14_gloves-fr1169_1": "a14_gloves-fr1169_s07_1.png", + "a14_necklace-fr1099_0": "a14_necklace-fr1099_s07_0.png", + "a14_shield-draw0_0": "a14_shield-draw0_s07_0.png", + "a14_totem-draw3_1": "a14_totem-draw3_s07_1.png", + "a17_armor-fr1253_1": "a17_armor-fr1253_s07_1.png", + "a17_armor-fr1267_1": "a17_armor-fr1267_s07_1.png", + "a17_boots-fr1393_0": "a17_boots-fr1393_s07_0.png", + "a17_gloves-fr1183_0": "a17_gloves-fr1183_s07_0.png", + "a17_necklace-fr1127_0": "a17_necklace-fr1127_s07_0.png", + "a17_orb-genmoba1_0": "a17_orb-genmoba1_s07_0.png", + "a17_helmet-genmoba0_0": "a17_helmet-genmoba0_s07_0.png", + "a17_staff-draw1_1": "a17_staff-draw1_s07_1.png", + "a17_blunt-fr1057_1": "a17_blunt-fr1057_s07_1.png", + "a17_totem-draw3_1": "a17_totem-draw3_s07_1.png", + "a17_belt-fr1351_1": "a17_belt-fr1351_s07_1.png", + "a19_sword-genxl1_1": "a19_sword-genxl1_s07_1.png", + "a19_ring-genxl0_1": "a19_ring-genxl0_s07_1.png", + "a19_quiver-genxl1_0": "a19_quiver-genxl1_s07_0.png", + "a19_shield-genxl1_0": "a19_shield-genxl1_s07_0.png", + "a20_belt-genxlb0_1": "a20_belt-genxlb0_s07_1.png", + "a21_necklace-genxlc0_2": "a21_necklace-genxlc0_s07_2.png", + "a21_spellbook-genxlc0_0": "a21_spellbook-genxlc0_s07_0.png", + "a23_axe-genxld1_1": "a23_axe-genxld1_s07_1.png", + "a23_hammer-genxld1_2": "a23_hammer-genxld1_s07_2.png", + "a23_helmet-genxld2_1": "a23_helmet-genxld2_s07_1.png", + "a23_helmet-genxld3_2": "a23_helmet-genxld3_s07_2.png", + "a23_quiver-genxld2_0": "a23_quiver-genxld2_s07_0.png", + "a23_ring-genxld1_0": "a23_ring-genxld1_s07_0.png", + "a23_ring-genxld3_0": "a23_ring-genxld3_s07_0.png", + "a23_shield-genxld3_0": "a23_shield-genxld3_s07_0.png", + "a24_axe-genxld1_0": "a24_axe-genxld1_s07_0.png", + "a24_dagger-genxlb0_3": "a24_dagger-genxlb0_s07_3.png", + "a24_dagger-genxlb0_2": "a24_dagger-genxlb0_s07_2.png", + "a24_hammer-genxld0_3": "a24_hammer-genxld0_s07_3.png", + "a24_hammer-genxld1_3": "a24_hammer-genxld1_s07_3.png", + "a24_horn-draw2_0": "a24_horn-draw2_s07_0.png", + "a24_horn-draw2_2": "a24_horn-draw2_s07_2.png", + "a24_orb-genmoba1_1": "a24_orb-genmoba1_s07_1.png", + "a24_orb-genmoba1_0": "a24_orb-genmoba1_s07_0.png", + "a24_spellbook-genxlc0_0": "a24_spellbook-genxlc0_s07_0.png", + "a24_spellbook-genxlc0_3": "a24_spellbook-genxlc0_s07_3.png", + "a24_sword-genxl1_1": "a24_sword-genxl1_s07_1.png", + "a24_sword-genxl1_0": "a24_sword-genxl1_s07_0.png" +} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4b_reject.json b/공유/기획/FirstRising/아이템/moba_anfg/best_v4b_reject.json new file mode 100644 index 0000000..906d21e --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_v4b_reject.json @@ -0,0 +1 @@ +["spellbook_01", "spellbook_02", "helmet_02", "dagger_01", "throwing_01", "bow_01", "staff_02"] diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/armor_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/armor_01.png new file mode 100644 index 0000000..0c2ad21 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/armor_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/armor_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/armor_02.png new file mode 100644 index 0000000..98e4c06 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/armor_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/armor_03.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/armor_03.png new file mode 100644 index 0000000..a7ebcd8 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/armor_03.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/axe_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/axe_01.png new file mode 100644 index 0000000..7488454 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/axe_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/axe_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/axe_02.png new file mode 100644 index 0000000..3aa5b4e Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/axe_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/belt_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/belt_01.png new file mode 100644 index 0000000..02cecb6 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/belt_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/belt_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/belt_02.png new file mode 100644 index 0000000..a34d17e Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/belt_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/belt_03.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/belt_03.png new file mode 100644 index 0000000..1bebea1 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/belt_03.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/blunt_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/blunt_01.png new file mode 100644 index 0000000..59cf14d Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/blunt_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/boots_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/boots_01.png new file mode 100644 index 0000000..34f9367 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/boots_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/boots_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/boots_02.png new file mode 100644 index 0000000..bf8013b Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/boots_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/dagger_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/dagger_01.png new file mode 100644 index 0000000..b091144 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/dagger_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/dagger_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/dagger_02.png new file mode 100644 index 0000000..5fba464 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/dagger_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/final_sheet.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/final_sheet.png new file mode 100644 index 0000000..50f0f81 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/final_sheet.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/gloves_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/gloves_01.png new file mode 100644 index 0000000..1e77d85 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/gloves_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/gloves_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/gloves_02.png new file mode 100644 index 0000000..70b69a9 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/gloves_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/hammer_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/hammer_01.png new file mode 100644 index 0000000..9987a8d Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/hammer_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/hammer_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/hammer_02.png new file mode 100644 index 0000000..59f6611 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/hammer_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/hammer_03.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/hammer_03.png new file mode 100644 index 0000000..610f45e Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/hammer_03.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/helmet_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/helmet_01.png new file mode 100644 index 0000000..4a3faca Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/helmet_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/helmet_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/helmet_02.png new file mode 100644 index 0000000..2911406 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/helmet_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/helmet_03.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/helmet_03.png new file mode 100644 index 0000000..45dfd3b Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/helmet_03.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/horn_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/horn_01.png new file mode 100644 index 0000000..170a274 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/horn_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/horn_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/horn_02.png new file mode 100644 index 0000000..ecffb3a Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/horn_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/index.json b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/index.json new file mode 100644 index 0000000..1841f73 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/index.json @@ -0,0 +1,186 @@ +[ + { + "icon": "sword_01.png", + "source": "a19_sword-genxl1_s07_1.png" + }, + { + "icon": "sword_02.png", + "source": "a24_sword-genxl1_s07_0.png" + }, + { + "icon": "sword_03.png", + "source": "a24_sword-genxl1_s07_1.png" + }, + { + "icon": "dagger_01.png", + "source": "a24_dagger-genxlb0_s07_2.png" + }, + { + "icon": "dagger_02.png", + "source": "a24_dagger-genxlb0_s07_3.png" + }, + { + "icon": "axe_01.png", + "source": "a23_axe-genxld1_s07_1.png" + }, + { + "icon": "axe_02.png", + "source": "a24_axe-genxld1_s07_0.png" + }, + { + "icon": "blunt_01.png", + "source": "a17_blunt-fr1057_s07_1.png" + }, + { + "icon": "hammer_01.png", + "source": "a23_hammer-genxld1_s07_2.png" + }, + { + "icon": "hammer_02.png", + "source": "a24_hammer-genxld0_s07_3.png" + }, + { + "icon": "hammer_03.png", + "source": "a24_hammer-genxld1_s07_3.png" + }, + { + "icon": "staff_01.png", + "source": "a17_staff-draw1_s07_1.png" + }, + { + "icon": "armor_01.png", + "source": "a14_armor-fr1267_s07_1.png" + }, + { + "icon": "armor_02.png", + "source": "a17_armor-fr1253_s07_1.png" + }, + { + "icon": "armor_03.png", + "source": "a17_armor-fr1267_s07_1.png" + }, + { + "icon": "helmet_01.png", + "source": "a17_helmet-genmoba0_s07_0.png" + }, + { + "icon": "helmet_02.png", + "source": "a23_helmet-genxld2_s07_1.png" + }, + { + "icon": "helmet_03.png", + "source": "a23_helmet-genxld3_s07_2.png" + }, + { + "icon": "gloves_01.png", + "source": "a14_gloves-fr1169_s07_1.png" + }, + { + "icon": "gloves_02.png", + "source": "a17_gloves-fr1183_s07_0.png" + }, + { + "icon": "belt_01.png", + "source": "a14_belt-fr1351_s07_0.png" + }, + { + "icon": "belt_02.png", + "source": "a17_belt-fr1351_s07_1.png" + }, + { + "icon": "belt_03.png", + "source": "a20_belt-genxlb0_s07_1.png" + }, + { + "icon": "boots_01.png", + "source": "a14_boots-fr1379_s07_1.png" + }, + { + "icon": "boots_02.png", + "source": "a17_boots-fr1393_s07_0.png" + }, + { + "icon": "ring_01.png", + "source": "a19_ring-genxl0_s07_1.png" + }, + { + "icon": "ring_02.png", + "source": "a23_ring-genxld1_s07_0.png" + }, + { + "icon": "ring_03.png", + "source": "a23_ring-genxld3_s07_0.png" + }, + { + "icon": "necklace_01.png", + "source": "a14_necklace-fr1099_s07_0.png" + }, + { + "icon": "necklace_02.png", + "source": "a17_necklace-fr1127_s07_0.png" + }, + { + "icon": "necklace_03.png", + "source": "a21_necklace-genxlc0_s07_2.png" + }, + { + "icon": "shield_01.png", + "source": "a14_shield-draw0_s07_0.png" + }, + { + "icon": "shield_02.png", + "source": "a19_shield-genxl1_s07_0.png" + }, + { + "icon": "shield_03.png", + "source": "a23_shield-genxld3_s07_0.png" + }, + { + "icon": "quiver_01.png", + "source": "a19_quiver-genxl1_s07_0.png" + }, + { + "icon": "quiver_02.png", + "source": "a23_quiver-genxld2_s07_0.png" + }, + { + "icon": "spellbook_01.png", + "source": "a21_spellbook-genxlc0_s07_0.png" + }, + { + "icon": "spellbook_02.png", + "source": "a24_spellbook-genxlc0_s07_0.png" + }, + { + "icon": "spellbook_03.png", + "source": "a24_spellbook-genxlc0_s07_3.png" + }, + { + "icon": "orb_01.png", + "source": "a17_orb-genmoba1_s07_0.png" + }, + { + "icon": "orb_02.png", + "source": "a24_orb-genmoba1_s07_0.png" + }, + { + "icon": "orb_03.png", + "source": "a24_orb-genmoba1_s07_1.png" + }, + { + "icon": "totem_01.png", + "source": "a14_totem-draw3_s07_1.png" + }, + { + "icon": "totem_02.png", + "source": "a17_totem-draw3_s07_1.png" + }, + { + "icon": "horn_01.png", + "source": "a24_horn-draw2_s07_0.png" + }, + { + "icon": "horn_02.png", + "source": "a24_horn-draw2_s07_2.png" + } +] \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/necklace_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/necklace_01.png new file mode 100644 index 0000000..613a760 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/necklace_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/necklace_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/necklace_02.png new file mode 100644 index 0000000..d30ab1c Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/necklace_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/necklace_03.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/necklace_03.png new file mode 100644 index 0000000..2fd427d Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/necklace_03.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/orb_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/orb_01.png new file mode 100644 index 0000000..c981874 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/orb_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/orb_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/orb_02.png new file mode 100644 index 0000000..28ad5bb Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/orb_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/orb_03.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/orb_03.png new file mode 100644 index 0000000..339ae21 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/orb_03.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/quiver_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/quiver_01.png new file mode 100644 index 0000000..a204da2 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/quiver_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/quiver_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/quiver_02.png new file mode 100644 index 0000000..575bde5 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/quiver_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/ring_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/ring_01.png new file mode 100644 index 0000000..0edeb80 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/ring_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/ring_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/ring_02.png new file mode 100644 index 0000000..2587d08 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/ring_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/ring_03.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/ring_03.png new file mode 100644 index 0000000..084580a Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/ring_03.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/shield_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/shield_01.png new file mode 100644 index 0000000..cbdb866 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/shield_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/shield_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/shield_02.png new file mode 100644 index 0000000..2363181 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/shield_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/shield_03.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/shield_03.png new file mode 100644 index 0000000..ecd5a97 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/shield_03.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/spellbook_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/spellbook_01.png new file mode 100644 index 0000000..2e31e34 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/spellbook_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/spellbook_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/spellbook_02.png new file mode 100644 index 0000000..859b6e2 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/spellbook_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/spellbook_03.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/spellbook_03.png new file mode 100644 index 0000000..bddf487 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/spellbook_03.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/staff_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/staff_01.png new file mode 100644 index 0000000..1500846 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/staff_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/sword_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/sword_01.png new file mode 100644 index 0000000..22bf2b0 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/sword_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/sword_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/sword_02.png new file mode 100644 index 0000000..8de5b81 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/sword_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/sword_03.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/sword_03.png new file mode 100644 index 0000000..25bbae0 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/sword_03.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/totem_01.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/totem_01.png new file mode 100644 index 0000000..0f3eed6 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/totem_01.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/totem_02.png b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/totem_02.png new file mode 100644 index 0000000..6ce0f80 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/best_v4e/totem_02.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/dataset.json b/공유/기획/FirstRising/아이템/moba_anfg/dataset.json new file mode 100644 index 0000000..72d32e9 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/dataset.json @@ -0,0 +1,2795 @@ +[ + { + "file": "a1_armor_s07_1.png", + "src": "a1_armor_s07_1.png", + "caption": "a red and gold chest armor with shoulder plates", + "source": "pd" + }, + { + "file": "a1_boots_s10_0.png", + "src": "a1_boots_s10_0.png", + "caption": "a pair of armored boots, blue and gold", + "source": "pd" + }, + { + "file": "a1_gloves_s07_1.png", + "src": "a1_gloves_s07_1.png", + "caption": "a single armored gauntlet, dark steel with gold trim and purple gem", + "source": "pd" + }, + { + "file": "a1_helmet_s07_0.png", + "src": "a1_helmet_s07_0.png", + "caption": "a red and gold horned helmet", + "source": "pd" + }, + { + "file": "a1_necklace_s07_0.png", + "src": "a1_necklace_s07_0.png", + "caption": "a red gem pendant necklace with gold wings", + "source": "pd" + }, + { + "file": "a1_ring_s10_0.png", + "src": "a1_ring_s10_0.png", + "caption": "a blue dragon head ring, silver scales, glowing cyan", + "source": "pd" + }, + { + "file": "a2_armor_s07_1.png", + "src": "a2_armor_s07_1.png", + "caption": "a red and gold chest armor with shoulder plates", + "source": "pd" + }, + { + "file": "a2_boots_s07_0.png", + "src": "a2_boots_s07_0.png", + "caption": "a pair of armored boots, blue and gold", + "source": "pd" + }, + { + "file": "a2_dagger_s07_3.png", + "src": "a2_dagger_s07_3.png", + "caption": "a single dagger, curved steel blade, red gem pommel, full weapon in frame", + "source": "pd" + }, + { + "file": "a2_magic_dagger_s07_3.png", + "src": "a2_magic_dagger_s07_3.png", + "caption": "a single magic dagger, glowing green crystal blade, gold hilt, full weapon in frame", + "source": "pd" + }, + { + "file": "a2_necklace_s07_2.png", + "src": "a2_necklace_s07_2.png", + "caption": "a blue gem pendant necklace with gold chain", + "source": "pd" + }, + { + "file": "a2_ring_s07_2.png", + "src": "a2_ring_s07_2.png", + "caption": "a gold ring with a large red gemstone", + "source": "pd" + }, + { + "file": "a2_shield_s07_1.png", + "src": "a2_shield_s07_1.png", + "caption": "a kite shield, blue steel with gold rim and lion emblem", + "source": "pd" + }, + { + "file": "a2_sword_s07_0.png", + "src": "a2_sword_s07_0.png", + "caption": "a single longsword, steel blade, gold crossguard, blue gem, full weapon in frame", + "source": "pd" + }, + { + "file": "a5n_armor_s07_0.png", + "src": "a5n_armor_s07_0.png", + "caption": "a red and gold chest armor with shoulder plates", + "source": "auto" + }, + { + "file": "a5n_armor_s07_1.png", + "src": "a5n_armor_s07_1.png", + "caption": "a red and gold chest armor with shoulder plates", + "source": "auto" + }, + { + "file": "a5n_boots_s07_1.png", + "src": "a5n_boots_s07_1.png", + "caption": "a pair of armored boots, blue and gold", + "source": "auto" + }, + { + "file": "a5n_dagger_s07_1.png", + "src": "a5n_dagger_s07_1.png", + "caption": "a single dagger, curved steel blade, red gem pommel, full weapon in frame", + "source": "auto" + }, + { + "file": "a5n_ring_s07_0.png", + "src": "a5n_ring_s07_0.png", + "caption": "a gold ring with a large red gemstone", + "source": "auto" + }, + { + "file": "a5n_sword_s07_1.png", + "src": "a5n_sword_s07_1.png", + "caption": "a single longsword, steel blade, gold crossguard, blue gem, full weapon in frame", + "source": "auto" + }, + { + "file": "a5v_armor_s07_0.png", + "src": "a5v_armor_s07_0.png", + "caption": "a red and gold chest armor with shoulder plates", + "source": "auto" + }, + { + "file": "a5v_boots_s07_1.png", + "src": "a5v_boots_s07_1.png", + "caption": "a pair of armored boots, blue and gold", + "source": "auto" + }, + { + "file": "a5v_dagger_s07_1.png", + "src": "a5v_dagger_s07_1.png", + "caption": "a single dagger, curved steel blade, red gem pommel, full weapon in frame", + "source": "auto" + }, + { + "file": "a5v_magic_dagger_s07_1.png", + "src": "a5v_magic_dagger_s07_1.png", + "caption": "a single magic dagger, glowing green crystal blade, gold hilt, full weapon in frame", + "source": "auto" + }, + { + "file": "a5v_sword_s07_0.png", + "src": "a5v_sword_s07_0.png", + "caption": "a single longsword, steel blade, gold crossguard, blue gem, full weapon in frame", + "source": "auto" + }, + { + "file": "a5v_sword_s07_1.png", + "src": "a5v_sword_s07_1.png", + "caption": "a single longsword, steel blade, gold crossguard, blue gem, full weapon in frame", + "source": "auto" + }, + { + "file": "a4_armor_s10_0.png", + "src": "a4_armor_s10_0.png", + "caption": "a red and gold chest armor with shoulder plates", + "source": "auto" + }, + { + "file": "a4_helmet_s08_0.png", + "src": "a4_helmet_s08_0.png", + "caption": "a red and gold horned helmet", + "source": "auto" + }, + { + "file": "a6d_gloves_s07_0.png", + "src": "a6d_gloves_s07_0.png", + "caption": "a single armored gauntlet, five fingers, steel plate glove with gold trim, wrist cuff", + "source": "auto" + }, + { + "file": "a6d_offhand_sword_s07_0.png", + "src": "a6d_offhand_sword_s07_0.png", + "caption": "a short parrying dagger, main-gauche, wide curved gold handguard, whole weapon in frame", + "source": "auto" + }, + { + "file": "a6d_ring_s07_1.png", + "src": "a6d_ring_s07_1.png", + "caption": "a gold ring with a large red gemstone, closed circular finger ring band", + "source": "auto" + }, + { + "file": "a6d_shield_s07_0.png", + "src": "a6d_shield_s07_0.png", + "caption": "a kite shield, plain blue field with gold rim and central boss, three-quarter view, small in frame", + "source": "auto" + }, + { + "file": "a6d_shield_s07_1.png", + "src": "a6d_shield_s07_1.png", + "caption": "a kite shield, plain blue field with gold rim and central boss, three-quarter view, small in frame", + "source": "auto" + }, + { + "file": "a6s_belt_s07_0.png", + "src": "a6s_belt_s07_0.png", + "caption": "a leather waist belt laid flat as a horizontal strap, large gold buckle in the center, red leather", + "source": "auto" + }, + { + "file": "a6s_belt_s07_1.png", + "src": "a6s_belt_s07_1.png", + "caption": "a leather waist belt laid flat as a horizontal strap, large gold buckle in the center, red leather", + "source": "auto" + }, + { + "file": "a6s_blunt_s07_0.png", + "src": "a6s_blunt_s07_0.png", + "caption": "a one-handed flanged mace, heavy spiked steel head with gold trim on a short handle", + "source": "auto" + }, + { + "file": "a6s_bow_s07_0.png", + "src": "a6s_bow_s07_0.png", + "caption": "a recurve bow, curved wooden limbs with gold tips, thin taut bowstring, side view", + "source": "auto" + }, + { + "file": "a6s_hammer_s07_0.png", + "src": "a6s_hammer_s07_0.png", + "caption": "a war hammer, heavy block steel head with gold trim and blue gem, brown wooden handle", + "source": "auto" + }, + { + "file": "a6t_boots_s07_0.png", + "src": "a6t_boots_s07_0.png", + "caption": "a pair of armored boots, blue and gold", + "source": "auto" + }, + { + "file": "a6t_orb_s07_1.png", + "src": "a6t_orb_s07_1.png", + "caption": "a crystal ball, deep blue glass sphere on a small gold stand", + "source": "auto" + }, + { + "file": "a6t_ring_s07_0.png", + "src": "a6t_ring_s07_0.png", + "caption": "a gold ring with a large red gemstone, closed circular finger ring band", + "source": "auto" + }, + { + "file": "a6t_sword_s07_0.png", + "src": "a6t_sword_s07_0.png", + "caption": "a single longsword, steel blade, gold crossguard, blue gem, full weapon in frame", + "source": "auto" + }, + { + "file": "a7_armor-fr1239_s07_0.png", + "src": "a7_armor-fr1239_s07_0.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold and crimson red", + "source": "auto" + }, + { + "file": "a7_armor-fr1253_s07_0.png", + "src": "a7_armor-fr1253_s07_0.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold and royal blue", + "source": "auto" + }, + { + "file": "a7_armor-fr1281_s07_1.png", + "src": "a7_armor-fr1281_s07_1.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, white silver and ice blue", + "source": "auto" + }, + { + "file": "a7_belt-fr1351_s07_1.png", + "src": "a7_belt-fr1351_s07_1.png", + "caption": "a waist belt, leather strap, large ornate buckle, white silver and ice blue", + "source": "auto" + }, + { + "file": "a7_blunt-fr1057_s07_1.png", + "src": "a7_blunt-fr1057_s07_1.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, gold and crimson red", + "source": "auto" + }, + { + "file": "a7_boots-fr1379_s07_0.png", + "src": "a7_boots-fr1379_s07_0.png", + "caption": "a pair of armored boots, plated shins, white silver and ice blue", + "source": "auto" + }, + { + "file": "a7_boots-fr1379_s07_1.png", + "src": "a7_boots-fr1379_s07_1.png", + "caption": "a pair of armored boots, plated shins, gold and royal blue", + "source": "auto" + }, + { + "file": "a7_boots-fr1407_s07_0.png", + "src": "a7_boots-fr1407_s07_0.png", + "caption": "a pair of armored boots, plated shins, gold and royal blue", + "source": "auto" + }, + { + "file": "a7_gloves-fr1183_s07_1.png", + "src": "a7_gloves-fr1183_s07_1.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, white silver and ice blue", + "source": "auto" + }, + { + "file": "a7_gloves-fr1197_s07_1.png", + "src": "a7_gloves-fr1197_s07_1.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, gold and crimson red", + "source": "auto" + }, + { + "file": "a7_gloves-fr1211_s07_1.png", + "src": "a7_gloves-fr1211_s07_1.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, gold and royal blue", + "source": "auto" + }, + { + "file": "a7_helmet-llequiphelmet0_s07_1.png", + "src": "a7_helmet-llequiphelmet0_s07_1.png", + "caption": "a knight helmet, visor, crest, white silver and ice blue", + "source": "auto" + }, + { + "file": "a7_helmet-llequiphelmet1_s07_1.png", + "src": "a7_helmet-llequiphelmet1_s07_1.png", + "caption": "a knight helmet, visor, crest, gold and crimson red", + "source": "auto" + }, + { + "file": "a7_necklace-fr1099_s07_0.png", + "src": "a7_necklace-fr1099_s07_0.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold and crimson red", + "source": "auto" + }, + { + "file": "a7_necklace-fr1113_s07_0.png", + "src": "a7_necklace-fr1113_s07_0.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold and royal blue", + "source": "auto" + }, + { + "file": "a7_necklace-llaccessoriesnecklace_s07_1.png", + "src": "a7_necklace-llaccessoriesnecklace_s07_1.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold and crimson red", + "source": "auto" + }, + { + "file": "a7_spellbook-llbook1_s07_1.png", + "src": "a7_spellbook-llbook1_s07_1.png", + "caption": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, gold and crimson red", + "source": "auto" + }, + { + "file": "a7_staff-draw0_s07_0.png", + "src": "a7_staff-draw0_s07_0.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, white silver and ice blue", + "source": "auto" + }, + { + "file": "a7_staff-draw0_s07_1.png", + "src": "a7_staff-draw0_s07_1.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold and royal blue", + "source": "auto" + }, + { + "file": "a7_sword-fr1435_s07_0.png", + "src": "a7_sword-fr1435_s07_0.png", + "caption": "a longsword, polished steel blade, ornate crossguard, gold and royal blue", + "source": "auto" + }, + { + "file": "a7_throwing-draw0_s07_1.png", + "src": "a7_throwing-draw0_s07_1.png", + "caption": "a throwing blade, kunai, sharp steel, white silver and ice blue", + "source": "auto" + }, + { + "file": "a8l_armor-fr1253_s07_0.png", + "src": "a8l_armor-fr1253_s07_0.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a8l_armor-fr1267_s07_1.png", + "src": "a8l_armor-fr1267_s07_1.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a8l_armor-fr1281_s07_0.png", + "src": "a8l_armor-fr1281_s07_0.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a8l_axe-draw0_s07_0.png", + "src": "a8l_axe-draw0_s07_0.png", + "caption": "a battle axe, broad curved blade, sturdy handle, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a8l_belt-fr1351_s07_0.png", + "src": "a8l_belt-fr1351_s07_0.png", + "caption": "a waist belt, leather strap, large ornate buckle, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a8l_blunt-fr1057_s07_0.png", + "src": "a8l_blunt-fr1057_s07_0.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a8l_boots-fr1379_s07_0.png", + "src": "a8l_boots-fr1379_s07_0.png", + "caption": "a pair of armored boots, plated shins, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a8l_boots-fr1393_s07_0.png", + "src": "a8l_boots-fr1393_s07_0.png", + "caption": "a pair of armored boots, plated shins, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a8l_boots-fr1421_s07_1.png", + "src": "a8l_boots-fr1421_s07_1.png", + "caption": "a pair of armored boots, plated shins, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a8l_bow-draw2_s07_0.png", + "src": "a8l_bow-draw2_s07_0.png", + "caption": "a recurve bow, curved limbs with metal tips, thin bowstring, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a8l_gloves-fr1183_s07_0.png", + "src": "a8l_gloves-fr1183_s07_0.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a8l_horn-draw2_s07_0.png", + "src": "a8l_horn-draw2_s07_0.png", + "caption": "a curved war horn, ivory body, metal rim bands, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a8l_horn-draw2_s07_1.png", + "src": "a8l_horn-draw2_s07_1.png", + "caption": "a curved war horn, ivory body, metal rim bands, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a8l_necklace-fr1099_s07_0.png", + "src": "a8l_necklace-fr1099_s07_0.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a8l_necklace-fr1113_s07_0.png", + "src": "a8l_necklace-fr1113_s07_0.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a8l_necklace-fr1127_s07_0.png", + "src": "a8l_necklace-fr1127_s07_0.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a8l_orb-draw2_s07_0.png", + "src": "a8l_orb-draw2_s07_0.png", + "caption": "a crystal orb, glass sphere on an ornate stand, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a8l_quiver-draw2_s07_0.png", + "src": "a8l_quiver-draw2_s07_0.png", + "caption": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a8l_ring-draw0_s07_1.png", + "src": "a8l_ring-draw0_s07_1.png", + "caption": "a finger ring, large faceted gemstone, engraved band, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a8l_shield-draw0_s07_0.png", + "src": "a8l_shield-draw0_s07_0.png", + "caption": "a shield, metal rim, central emblem boss, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a8l_shield-draw0_s07_1.png", + "src": "a8l_shield-draw0_s07_1.png", + "caption": "a shield, metal rim, central emblem boss, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a8l_spellbook-llbook1_s07_0.png", + "src": "a8l_spellbook-llbook1_s07_0.png", + "caption": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a8l_staff-draw1_s07_0.png", + "src": "a8l_staff-draw1_s07_0.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a8l_staff-draw1_s07_1.png", + "src": "a8l_staff-draw1_s07_1.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a8l_sword-fr1435_s07_1.png", + "src": "a8l_sword-fr1435_s07_1.png", + "caption": "a longsword, polished steel blade, ornate crossguard, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a8l_throwing-draw0_s07_0.png", + "src": "a8l_throwing-draw0_s07_0.png", + "caption": "a throwing blade, kunai, sharp steel, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a8l_throwing-draw1_s07_0.png", + "src": "a8l_throwing-draw1_s07_0.png", + "caption": "a throwing blade, kunai, sharp steel, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a8t_armor_s07_1.png", + "src": "a8t_armor_s07_1.png", + "caption": "a red and gold chest armor with shoulder plates", + "source": "auto" + }, + { + "file": "a8t_offhand_sword_s07_1.png", + "src": "a8t_offhand_sword_s07_1.png", + "caption": "a short parrying dagger, main-gauche, wide curved gold handguard, whole weapon in frame", + "source": "auto" + }, + { + "file": "a8t_orb_s07_0.png", + "src": "a8t_orb_s07_0.png", + "caption": "a crystal ball, deep blue glass sphere on a small gold stand", + "source": "auto" + }, + { + "file": "a8t_orb_s07_1.png", + "src": "a8t_orb_s07_1.png", + "caption": "a crystal ball, deep blue glass sphere on a small gold stand", + "source": "auto" + }, + { + "file": "a8t_shield_s07_1.png", + "src": "a8t_shield_s07_1.png", + "caption": "a kite shield, plain blue field with gold rim and central boss, three-quarter view, small in frame", + "source": "auto" + }, + { + "file": "a8t_sword_s07_0.png", + "src": "a8t_sword_s07_0.png", + "caption": "a single longsword, steel blade, gold crossguard, blue gem, full weapon in frame", + "source": "auto" + }, + { + "file": "a9_belt-fr1351_s07_1.png", + "src": "a9_belt-fr1351_s07_1.png", + "caption": "a waist belt, leather strap, large ornate buckle, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a9_belt-fr1351_s07_3.png", + "src": "a9_belt-fr1351_s07_3.png", + "caption": "a waist belt, leather strap, large ornate buckle, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a9_blunt-fr1057_s07_1.png", + "src": "a9_blunt-fr1057_s07_1.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a9_blunt-fr1057_s07_3.png", + "src": "a9_blunt-fr1057_s07_3.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a9_bow-draw2_s07_1.png", + "src": "a9_bow-draw2_s07_1.png", + "caption": "a recurve bow, curved limbs with metal tips, thin bowstring, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a9_bow-draw2_s07_2.png", + "src": "a9_bow-draw2_s07_2.png", + "caption": "a recurve bow, curved limbs with metal tips, thin bowstring, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a9_dagger-draw0_s07_0.png", + "src": "a9_dagger-draw0_s07_0.png", + "caption": "a dagger, sharp steel blade, ornate hilt, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a9_hammer-draw0_s07_0.png", + "src": "a9_hammer-draw0_s07_0.png", + "caption": "a war hammer, heavy block metal head, sturdy handle, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a9_hammer-draw0_s07_2.png", + "src": "a9_hammer-draw0_s07_2.png", + "caption": "a war hammer, heavy block metal head, sturdy handle, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a9_helmet-draw0_s07_0.png", + "src": "a9_helmet-draw0_s07_0.png", + "caption": "a knight helmet, visor, crest, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a9_helmet-draw0_s07_2.png", + "src": "a9_helmet-draw0_s07_2.png", + "caption": "a knight helmet, visor, crest, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a9_horn-draw2_s07_0.png", + "src": "a9_horn-draw2_s07_0.png", + "caption": "a curved war horn, ivory body, metal rim bands, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a9_horn-draw2_s07_2.png", + "src": "a9_horn-draw2_s07_2.png", + "caption": "a curved war horn, ivory body, metal rim bands, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a9_orb-draw2_s07_0.png", + "src": "a9_orb-draw2_s07_0.png", + "caption": "a crystal orb, glass sphere on an ornate stand, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a9_quiver-draw2_s07_2.png", + "src": "a9_quiver-draw2_s07_2.png", + "caption": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a9_ring-draw0_s07_1.png", + "src": "a9_ring-draw0_s07_1.png", + "caption": "a finger ring, large faceted gemstone, engraved band, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a9_ring-draw0_s07_3.png", + "src": "a9_ring-draw0_s07_3.png", + "caption": "a finger ring, large faceted gemstone, engraved band, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a9_shield-draw0_s07_0.png", + "src": "a9_shield-draw0_s07_0.png", + "caption": "a shield, metal rim, central emblem boss, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a9_shield-draw0_s07_2.png", + "src": "a9_shield-draw0_s07_2.png", + "caption": "a shield, metal rim, central emblem boss, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a9_spellbook-llbook1_s07_1.png", + "src": "a9_spellbook-llbook1_s07_1.png", + "caption": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a9_staff-draw0_s07_1.png", + "src": "a9_staff-draw0_s07_1.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a9_staff-draw1_s07_2.png", + "src": "a9_staff-draw1_s07_2.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a9_staff-draw1_s07_3.png", + "src": "a9_staff-draw1_s07_3.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a9_throwing-draw0_s07_2.png", + "src": "a9_throwing-draw0_s07_2.png", + "caption": "a throwing blade, kunai, sharp steel, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a9_throwing-draw1_s07_1.png", + "src": "a9_throwing-draw1_s07_1.png", + "caption": "a throwing blade, kunai, sharp steel, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a9_totem-draw3_s07_0.png", + "src": "a9_totem-draw3_s07_0.png", + "caption": "a carved wooden totem, stacked tribal faces, small wings, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a9_totem-draw3_s07_1.png", + "src": "a9_totem-draw3_s07_1.png", + "caption": "a carved wooden totem, stacked tribal faces, small wings, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a10_bow-draw2_s07_1.png", + "src": "a10_bow-draw2_s07_1.png", + "caption": "a recurve bow, curved limbs with metal tips, thin bowstring, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a10_dagger-draw0_s07_1.png", + "src": "a10_dagger-draw0_s07_1.png", + "caption": "a dagger, sharp steel blade, ornate hilt, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a10_hammer-draw0_s07_0.png", + "src": "a10_hammer-draw0_s07_0.png", + "caption": "a war hammer, heavy block metal head, sturdy handle, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a10_horn-draw2_s07_0.png", + "src": "a10_horn-draw2_s07_0.png", + "caption": "a curved war horn, ivory body, metal rim bands, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a10_ring-draw0_s07_1.png", + "src": "a10_ring-draw0_s07_1.png", + "caption": "a finger ring, large faceted gemstone, engraved band, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a10_shield-draw0_s07_1.png", + "src": "a10_shield-draw0_s07_1.png", + "caption": "a shield, metal rim, central emblem boss, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a11l_armor-fr1253_s07_0.png", + "src": "a11l_armor-fr1253_s07_0.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a11l_armor-fr1253_s07_1.png", + "src": "a11l_armor-fr1253_s07_1.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a11l_armor-fr1267_s07_1.png", + "src": "a11l_armor-fr1267_s07_1.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a11l_armor-fr1281_s07_1.png", + "src": "a11l_armor-fr1281_s07_1.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a11l_belt-fr1351_s07_0.png", + "src": "a11l_belt-fr1351_s07_0.png", + "caption": "a waist belt, leather strap, large ornate buckle, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a11l_blunt-fr1057_s07_1.png", + "src": "a11l_blunt-fr1057_s07_1.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a11l_boots-fr1393_s07_0.png", + "src": "a11l_boots-fr1393_s07_0.png", + "caption": "a pair of armored boots, plated shins, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a11l_boots-fr1407_s07_1.png", + "src": "a11l_boots-fr1407_s07_1.png", + "caption": "a pair of armored boots, plated shins, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a11l_boots-fr1421_s07_1.png", + "src": "a11l_boots-fr1421_s07_1.png", + "caption": "a pair of armored boots, plated shins, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a11l_gloves-fr1183_s07_0.png", + "src": "a11l_gloves-fr1183_s07_0.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a11l_gloves-fr1211_s07_0.png", + "src": "a11l_gloves-fr1211_s07_0.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a11l_hammer-draw0_s07_0.png", + "src": "a11l_hammer-draw0_s07_0.png", + "caption": "a war hammer, heavy block metal head, sturdy handle, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a11l_helmet-draw0_s07_0.png", + "src": "a11l_helmet-draw0_s07_0.png", + "caption": "a knight helmet, visor, crest, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a11l_helmet-draw0_s07_1.png", + "src": "a11l_helmet-draw0_s07_1.png", + "caption": "a knight helmet, visor, crest, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a11l_helmet-draw1_s07_1.png", + "src": "a11l_helmet-draw1_s07_1.png", + "caption": "a knight helmet, visor, crest, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a11l_horn-draw2_s07_1.png", + "src": "a11l_horn-draw2_s07_1.png", + "caption": "a curved war horn, ivory body, metal rim bands, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a11l_necklace-fr1099_s07_1.png", + "src": "a11l_necklace-fr1099_s07_1.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a11l_necklace-fr1113_s07_1.png", + "src": "a11l_necklace-fr1113_s07_1.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a11l_necklace-fr1127_s07_0.png", + "src": "a11l_necklace-fr1127_s07_0.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a11l_necklace-fr1127_s07_1.png", + "src": "a11l_necklace-fr1127_s07_1.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a11l_necklace-fr1141_s07_1.png", + "src": "a11l_necklace-fr1141_s07_1.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a11l_orb-draw2_s07_1.png", + "src": "a11l_orb-draw2_s07_1.png", + "caption": "a crystal orb, glass sphere on an ornate stand, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a11l_quiver-draw2_s07_1.png", + "src": "a11l_quiver-draw2_s07_1.png", + "caption": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a11l_ring-genpd1ring_s07_1.png", + "src": "a11l_ring-genpd1ring_s07_1.png", + "caption": "a finger ring, large faceted gemstone, engraved band, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a11l_shield-genpd2shield_s07_1.png", + "src": "a11l_shield-genpd2shield_s07_1.png", + "caption": "a shield, metal rim, central emblem boss, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a11l_spellbook-llbook1_s07_1.png", + "src": "a11l_spellbook-llbook1_s07_1.png", + "caption": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a11l_staff-draw1_s07_0.png", + "src": "a11l_staff-draw1_s07_0.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a11l_sword-genpd2sword_s07_1.png", + "src": "a11l_sword-genpd2sword_s07_1.png", + "caption": "a longsword, polished steel blade, ornate crossguard, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a11l_throwing-draw1_s07_1.png", + "src": "a11l_throwing-draw1_s07_1.png", + "caption": "a throwing blade, kunai, sharp steel, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a11l_totem-draw3_s07_0.png", + "src": "a11l_totem-draw3_s07_0.png", + "caption": "a carved wooden totem, stacked tribal faces, small wings, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a11l_totem-draw3_s07_1.png", + "src": "a11l_totem-draw3_s07_1.png", + "caption": "a carved wooden totem, stacked tribal faces, small wings, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a12l_blunt-fr1057_s07_0.png", + "src": "a12l_blunt-fr1057_s07_0.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a12l_blunt-fr1057_s07_2.png", + "src": "a12l_blunt-fr1057_s07_2.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a12l_dagger-genpd2dagger_s07_1.png", + "src": "a12l_dagger-genpd2dagger_s07_1.png", + "caption": "a dagger, engraved steel blade with a fuller, dark steel shading, ornate hilt and crossguard, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a12l_dagger-genpd2magicdagger_s07_2.png", + "src": "a12l_dagger-genpd2magicdagger_s07_2.png", + "caption": "a dagger, engraved steel blade with a fuller, dark steel shading, ornate hilt and crossguard, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a12l_hammer-draw0_s07_0.png", + "src": "a12l_hammer-draw0_s07_0.png", + "caption": "a war hammer, heavy block metal head, sturdy handle, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a12l_hammer-draw0_s07_1.png", + "src": "a12l_hammer-draw0_s07_1.png", + "caption": "a war hammer, heavy block metal head, sturdy handle, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a12l_horn-draw2_s07_1.png", + "src": "a12l_horn-draw2_s07_1.png", + "caption": "a curved war horn, ivory body, metal rim bands, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a12l_quiver-draw2_s07_1.png", + "src": "a12l_quiver-draw2_s07_1.png", + "caption": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a12l_ring-genpd1ring_s07_0.png", + "src": "a12l_ring-genpd1ring_s07_0.png", + "caption": "a finger ring, large faceted gemstone, engraved band, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a12l_shield-draw0_s07_0.png", + "src": "a12l_shield-draw0_s07_0.png", + "caption": "a shield, metal rim, central emblem boss, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a12l_shield-genpd2shield_s07_0.png", + "src": "a12l_shield-genpd2shield_s07_0.png", + "caption": "a shield, metal rim, central emblem boss, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a12l_spellbook-llbook1_s07_1.png", + "src": "a12l_spellbook-llbook1_s07_1.png", + "caption": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a12l_staff-draw1_s07_0.png", + "src": "a12l_staff-draw1_s07_0.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a12l_staff-draw1_s07_2.png", + "src": "a12l_staff-draw1_s07_2.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a12l_sword-genpd2sword_s07_0.png", + "src": "a12l_sword-genpd2sword_s07_0.png", + "caption": "a longsword, ornate engraved steel blade with a fuller, dark steel shading, ornate crossguard, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a12l_throwing-draw0_s07_0.png", + "src": "a12l_throwing-draw0_s07_0.png", + "caption": "a throwing blade, kunai, sharp steel, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a12l_throwing-draw1_s07_0.png", + "src": "a12l_throwing-draw1_s07_0.png", + "caption": "a throwing blade, kunai, sharp steel, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a12l_throwing-draw1_s07_1.png", + "src": "a12l_throwing-draw1_s07_1.png", + "caption": "a throwing blade, kunai, sharp steel, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a12t_armor_s07_1.png", + "src": "a12t_armor_s07_1.png", + "caption": "a red and gold chest armor with shoulder plates", + "source": "auto" + }, + { + "file": "a12t_boots_s07_0.png", + "src": "a12t_boots_s07_0.png", + "caption": "a pair of armored boots, blue and gold", + "source": "auto" + }, + { + "file": "a12t_dagger_s07_0.png", + "src": "a12t_dagger_s07_0.png", + "caption": "a single dagger, curved steel blade, red gem pommel, full weapon in frame", + "source": "auto" + }, + { + "file": "a12t_gloves_s07_0.png", + "src": "a12t_gloves_s07_0.png", + "caption": "a single armored gauntlet, five fingers, steel plate glove with gold trim, wrist cuff", + "source": "auto" + }, + { + "file": "a12t_gloves_s07_1.png", + "src": "a12t_gloves_s07_1.png", + "caption": "a single armored gauntlet, five fingers, steel plate glove with gold trim, wrist cuff", + "source": "auto" + }, + { + "file": "a12t_orb_s07_1.png", + "src": "a12t_orb_s07_1.png", + "caption": "a crystal ball, deep blue glass sphere on a small gold stand", + "source": "auto" + }, + { + "file": "a12t_shield_s07_0.png", + "src": "a12t_shield_s07_0.png", + "caption": "a kite shield, plain blue field with gold rim and central boss, three-quarter view, small in frame", + "source": "auto" + }, + { + "file": "a12t_throwing_s07_0.png", + "src": "a12t_throwing_s07_0.png", + "caption": "a single steel throwing knife, kunai, small leaf shaped blade with ring pommel", + "source": "auto" + }, + { + "file": "a13l_blunt-fr1057_s07_0.png", + "src": "a13l_blunt-fr1057_s07_0.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a13l_blunt-fr1057_s07_1.png", + "src": "a13l_blunt-fr1057_s07_1.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a13l_bow-draw2_s07_1.png", + "src": "a13l_bow-draw2_s07_1.png", + "caption": "a recurve bow, carved wooden limbs with ornate metal fittings, wrapped grip, thin bowstring, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a13l_hammer-draw0_s07_0.png", + "src": "a13l_hammer-draw0_s07_0.png", + "caption": "a war hammer, heavy block metal head, sturdy handle, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a13l_staff-draw0_s07_0.png", + "src": "a13l_staff-draw0_s07_0.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a13l_staff-draw0_s07_1.png", + "src": "a13l_staff-draw0_s07_1.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a13l_staff-draw1_s07_1.png", + "src": "a13l_staff-draw1_s07_1.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a13l_staff-draw1_s07_2.png", + "src": "a13l_staff-draw1_s07_2.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a13l_sword-draw2_s07_1.png", + "src": "a13l_sword-draw2_s07_1.png", + "caption": "a longsword, ornate engraved steel blade with a fuller, dark steel shading, ornate crossguard, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a13l_sword-genpd2sword_s07_1.png", + "src": "a13l_sword-genpd2sword_s07_1.png", + "caption": "a longsword, ornate engraved steel blade with a fuller, dark steel shading, ornate crossguard, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a13l_throwing-draw0_s07_0.png", + "src": "a13l_throwing-draw0_s07_0.png", + "caption": "a throwing blade, kunai, sharp steel, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a13l_throwing-draw0_s07_1.png", + "src": "a13l_throwing-draw0_s07_1.png", + "caption": "a throwing blade, kunai, sharp steel, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a13l_throwing-draw1_s07_1.png", + "src": "a13l_throwing-draw1_s07_1.png", + "caption": "a throwing blade, kunai, sharp steel, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a13l_throwing-draw1_s07_2.png", + "src": "a13l_throwing-draw1_s07_2.png", + "caption": "a throwing blade, kunai, sharp steel, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a13t_armor_s07_0.png", + "src": "a13t_armor_s07_0.png", + "caption": "a red and gold chest armor with shoulder plates", + "source": "auto" + }, + { + "file": "a13t_boots_s07_1.png", + "src": "a13t_boots_s07_1.png", + "caption": "a pair of armored boots, blue and gold", + "source": "auto" + }, + { + "file": "a13t_orb_s07_0.png", + "src": "a13t_orb_s07_0.png", + "caption": "a crystal ball, deep blue glass sphere on a small gold stand", + "source": "auto" + }, + { + "file": "a13t_orb_s07_1.png", + "src": "a13t_orb_s07_1.png", + "caption": "a crystal ball, deep blue glass sphere on a small gold stand", + "source": "auto" + }, + { + "file": "a14_armor-fr1253_s07_1.png", + "src": "a14_armor-fr1253_s07_1.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a14_armor-fr1267_s07_0.png", + "src": "a14_armor-fr1267_s07_0.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a14_armor-fr1267_s07_1.png", + "src": "a14_armor-fr1267_s07_1.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold and crimson red with silver steel", + "source": "auto", + "best": true + }, + { + "file": "a14_armor-fr1281_s07_0.png", + "src": "a14_armor-fr1281_s07_0.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a14_armor-fr1281_s07_1.png", + "src": "a14_armor-fr1281_s07_1.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a14_belt-fr1351_s07_0.png", + "src": "a14_belt-fr1351_s07_0.png", + "caption": "a waist belt, leather strap, large ornate buckle, gold trim on silver steel with blue gems", + "source": "auto", + "best": true + }, + { + "file": "a14_belt-fr1351_s07_1.png", + "src": "a14_belt-fr1351_s07_1.png", + "caption": "a waist belt, leather strap, large ornate buckle, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a14_boots-fr1379_s07_0.png", + "src": "a14_boots-fr1379_s07_0.png", + "caption": "a pair of armored boots, plated shins, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a14_boots-fr1379_s07_1.png", + "src": "a14_boots-fr1379_s07_1.png", + "caption": "a pair of armored boots, plated shins, gold and royal blue with silver steel", + "source": "auto", + "best": true + }, + { + "file": "a14_boots-fr1393_s07_0.png", + "src": "a14_boots-fr1393_s07_0.png", + "caption": "a pair of armored boots, plated shins, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a14_boots-fr1407_s07_0.png", + "src": "a14_boots-fr1407_s07_0.png", + "caption": "a pair of armored boots, plated shins, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a14_boots-fr1421_s07_0.png", + "src": "a14_boots-fr1421_s07_0.png", + "caption": "a pair of armored boots, plated shins, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a14_gloves-fr1169_s07_1.png", + "src": "a14_gloves-fr1169_s07_1.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, gold trim on silver steel with blue gems", + "source": "auto", + "best": true + }, + { + "file": "a14_gloves-fr1197_s07_1.png", + "src": "a14_gloves-fr1197_s07_1.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a14_necklace-fr1099_s07_0.png", + "src": "a14_necklace-fr1099_s07_0.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold trim on silver steel with blue gems", + "source": "auto", + "best": true + }, + { + "file": "a14_necklace-fr1099_s07_1.png", + "src": "a14_necklace-fr1099_s07_1.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a14_necklace-fr1113_s07_1.png", + "src": "a14_necklace-fr1113_s07_1.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a14_necklace-fr1127_s07_0.png", + "src": "a14_necklace-fr1127_s07_0.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a14_necklace-fr1141_s07_0.png", + "src": "a14_necklace-fr1141_s07_0.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a14_quiver-draw2_s07_1.png", + "src": "a14_quiver-draw2_s07_1.png", + "caption": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a14_shield-draw0_s07_0.png", + "src": "a14_shield-draw0_s07_0.png", + "caption": "a shield, metal rim, central emblem boss, gold trim on dark steel with red gems", + "source": "auto", + "best": true + }, + { + "file": "a14_shield-genpd2shield_s07_1.png", + "src": "a14_shield-genpd2shield_s07_1.png", + "caption": "a shield, metal rim, central emblem boss, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a14_spellbook-llbook1_s07_0.png", + "src": "a14_spellbook-llbook1_s07_0.png", + "caption": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, gold and crimson red with silver steel", + "source": "auto", + "best": true + }, + { + "file": "a14_totem-draw3_s07_1.png", + "src": "a14_totem-draw3_s07_1.png", + "caption": "a carved wooden totem, stacked tribal faces, small wings, gold trim on dark steel with red gems", + "source": "auto", + "best": true + }, + { + "file": "a15_bow-draw3_s07_3.png", + "src": "a15_bow-draw3_s07_3.png", + "caption": "an ornate recurve bow, carved limbs with gold filigree fittings, gem at the wrapped grip, thin bowstring, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a15_dagger-draw3_s07_1.png", + "src": "a15_dagger-draw3_s07_1.png", + "caption": "a dagger, engraved steel blade with a fuller, dark steel shading, ornate hilt and crossguard, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a15_hammer-draw2_s07_2.png", + "src": "a15_hammer-draw2_s07_2.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a15_hammer-draw2_s07_3.png", + "src": "a15_hammer-draw2_s07_3.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a15_sword-draw2_s07_2.png", + "src": "a15_sword-draw2_s07_2.png", + "caption": "a longsword, ornate engraved steel blade with a fuller, dark steel shading, ornate crossguard, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a16b_armor-fr1267_s07_1.png", + "src": "a16b_armor-fr1267_s07_1.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a16b_blunt-fr1057_s07_1.png", + "src": "a16b_blunt-fr1057_s07_1.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a16b_necklace-fr1099_s07_0.png", + "src": "a16b_necklace-fr1099_s07_0.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a16b_staff-draw1_s07_0.png", + "src": "a16b_staff-draw1_s07_0.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a16d_blunt-fr1057_s08_0.png", + "src": "a16d_blunt-fr1057_s08_0.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a16d_boots-fr1379_s08_0.png", + "src": "a16d_boots-fr1379_s08_0.png", + "caption": "a pair of armored boots, plated shins, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a16d_boots-fr1379_s08_1.png", + "src": "a16d_boots-fr1379_s08_1.png", + "caption": "a pair of armored boots, plated shins, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a16d_shield-draw0_s08_1.png", + "src": "a16d_shield-draw0_s08_1.png", + "caption": "a shield, metal rim, central emblem boss, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a17_armor-fr1253_s07_0.png", + "src": "a17_armor-fr1253_s07_0.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a17_armor-fr1253_s07_1.png", + "src": "a17_armor-fr1253_s07_1.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold trim on silver steel with blue gems", + "source": "auto", + "best": true + }, + { + "file": "a17_armor-fr1267_s07_0.png", + "src": "a17_armor-fr1267_s07_0.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a17_armor-fr1267_s07_1.png", + "src": "a17_armor-fr1267_s07_1.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold and crimson red with silver steel", + "source": "auto", + "best": true + }, + { + "file": "a17_armor-fr1281_s07_0.png", + "src": "a17_armor-fr1281_s07_0.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a17_armor-fr1281_s07_1.png", + "src": "a17_armor-fr1281_s07_1.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a17_axe-genmoba0_s07_0.png", + "src": "a17_axe-genmoba0_s07_0.png", + "caption": "a single-bladed battle axe, solid broad axe head attached to the shaft, engraved steel blade, dark steel shading, wooden shaft with metal fittings, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a17_belt-fr1351_s07_1.png", + "src": "a17_belt-fr1351_s07_1.png", + "caption": "a waist belt, leather strap, large ornate buckle, gold and royal blue with silver steel", + "source": "auto", + "best": true + }, + { + "file": "a17_blunt-fr1057_s07_0.png", + "src": "a17_blunt-fr1057_s07_0.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a17_blunt-fr1057_s07_1.png", + "src": "a17_blunt-fr1057_s07_1.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, gold trim on dark steel with red gems", + "source": "auto", + "best": true + }, + { + "file": "a17_boots-fr1379_s07_0.png", + "src": "a17_boots-fr1379_s07_0.png", + "caption": "a pair of armored boots, plated shins, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a17_boots-fr1379_s07_1.png", + "src": "a17_boots-fr1379_s07_1.png", + "caption": "a pair of armored boots, plated shins, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a17_boots-fr1393_s07_0.png", + "src": "a17_boots-fr1393_s07_0.png", + "caption": "a pair of armored boots, plated shins, gold trim on silver steel with blue gems", + "source": "auto", + "best": true + }, + { + "file": "a17_boots-fr1407_s07_1.png", + "src": "a17_boots-fr1407_s07_1.png", + "caption": "a pair of armored boots, plated shins, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a17_boots-fr1421_s07_0.png", + "src": "a17_boots-fr1421_s07_0.png", + "caption": "a pair of armored boots, plated shins, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a17_bow-draw3_s07_1.png", + "src": "a17_bow-draw3_s07_1.png", + "caption": "an ornate recurve bow, carved limbs with gold filigree fittings, gem at the wrapped grip, thin bowstring, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a17_gloves-fr1183_s07_0.png", + "src": "a17_gloves-fr1183_s07_0.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, gold trim on silver steel with blue gems", + "source": "auto", + "best": true + }, + { + "file": "a17_gloves-fr1183_s07_1.png", + "src": "a17_gloves-fr1183_s07_1.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a17_gloves-fr1197_s07_0.png", + "src": "a17_gloves-fr1197_s07_0.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a17_gloves-fr1211_s07_0.png", + "src": "a17_gloves-fr1211_s07_0.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a17_gloves-fr1211_s07_1.png", + "src": "a17_gloves-fr1211_s07_1.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a17_hammer-draw2_s07_1.png", + "src": "a17_hammer-draw2_s07_1.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a17_helmet-genmoba0_s07_0.png", + "src": "a17_helmet-genmoba0_s07_0.png", + "caption": "a knight helmet, visor, crest, gold and royal blue with silver steel", + "source": "auto", + "best": true + }, + { + "file": "a17_horn-draw2_s07_1.png", + "src": "a17_horn-draw2_s07_1.png", + "caption": "a curved war horn, ivory body, metal rim bands, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a17_necklace-fr1099_s07_0.png", + "src": "a17_necklace-fr1099_s07_0.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a17_necklace-fr1113_s07_1.png", + "src": "a17_necklace-fr1113_s07_1.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a17_necklace-fr1127_s07_0.png", + "src": "a17_necklace-fr1127_s07_0.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold trim on silver steel with blue gems", + "source": "auto", + "best": true + }, + { + "file": "a17_necklace-fr1127_s07_1.png", + "src": "a17_necklace-fr1127_s07_1.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a17_orb-genmoba1_s07_0.png", + "src": "a17_orb-genmoba1_s07_0.png", + "caption": "a crystal orb, glass sphere on an ornate stand, gold trim on silver steel with blue gems", + "source": "auto", + "best": true + }, + { + "file": "a17_orb-genmoba1_s07_1.png", + "src": "a17_orb-genmoba1_s07_1.png", + "caption": "a crystal orb, glass sphere on an ornate stand, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a17_spellbook-llbook1_s07_1.png", + "src": "a17_spellbook-llbook1_s07_1.png", + "caption": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, gold and royal blue with silver steel", + "source": "auto", + "best": true + }, + { + "file": "a17_staff-draw0_s07_0.png", + "src": "a17_staff-draw0_s07_0.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a17_staff-draw1_s07_0.png", + "src": "a17_staff-draw1_s07_0.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a17_staff-draw1_s07_1.png", + "src": "a17_staff-draw1_s07_1.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold trim on silver steel with blue gems", + "source": "auto", + "best": true + }, + { + "file": "a17_throwing-draw0_s07_0.png", + "src": "a17_throwing-draw0_s07_0.png", + "caption": "a throwing blade, kunai, sharp steel, gold and crimson red with silver steel", + "source": "auto", + "best": true + }, + { + "file": "a17_throwing-draw1_s07_0.png", + "src": "a17_throwing-draw1_s07_0.png", + "caption": "a throwing blade, kunai, sharp steel, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a17_totem-draw3_s07_0.png", + "src": "a17_totem-draw3_s07_0.png", + "caption": "a carved wooden totem, stacked tribal faces, small wings, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a17_totem-draw3_s07_1.png", + "src": "a17_totem-draw3_s07_1.png", + "caption": "a carved wooden totem, stacked tribal faces, small wings, gold trim on silver steel with blue gems", + "source": "auto", + "best": true + }, + { + "file": "a18l_belt-fr1351_s07_0.png", + "src": "a18l_belt-fr1351_s07_0.png", + "caption": "a waist belt, leather strap, large ornate buckle, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a18l_belt-fr1351_s07_1.png", + "src": "a18l_belt-fr1351_s07_1.png", + "caption": "a waist belt, leather strap, large ornate buckle, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a18l_bow-draw3_s07_0.png", + "src": "a18l_bow-draw3_s07_0.png", + "caption": "an ornate recurve bow, carved limbs with gold filigree fittings, gem at the wrapped grip, thin bowstring, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a18l_hammer-draw2_s07_0.png", + "src": "a18l_hammer-draw2_s07_0.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a18l_hammer-draw2_s07_1.png", + "src": "a18l_hammer-draw2_s07_1.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a18l_helmet-draw0_s07_1.png", + "src": "a18l_helmet-draw0_s07_1.png", + "caption": "a knight helmet, visor, crest, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a18l_horn-draw2_s07_0.png", + "src": "a18l_horn-draw2_s07_0.png", + "caption": "a curved war horn, ivory body, metal rim bands, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a18l_quiver-draw2_s07_0.png", + "src": "a18l_quiver-draw2_s07_0.png", + "caption": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a18l_quiver-draw2_s07_1.png", + "src": "a18l_quiver-draw2_s07_1.png", + "caption": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a18l_shield-draw0_s07_1.png", + "src": "a18l_shield-draw0_s07_1.png", + "caption": "a shield, metal rim, central emblem boss, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a18l_spellbook-llbook1_s07_0.png", + "src": "a18l_spellbook-llbook1_s07_0.png", + "caption": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a19_helmet-genxl1_s07_0.png", + "src": "a19_helmet-genxl1_s07_0.png", + "caption": "a knight helmet, visor, crest, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a19_quiver-genxl1_s07_0.png", + "src": "a19_quiver-genxl1_s07_0.png", + "caption": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a19_quiver-genxl1_s07_1.png", + "src": "a19_quiver-genxl1_s07_1.png", + "caption": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a19_ring-genxl0_s07_1.png", + "src": "a19_ring-genxl0_s07_1.png", + "caption": "a finger ring, large faceted gemstone, engraved band, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a19_ring-genxl1_s07_0.png", + "src": "a19_ring-genxl1_s07_0.png", + "caption": "a finger ring, large faceted gemstone, engraved band, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a19_shield-genxl1_s07_0.png", + "src": "a19_shield-genxl1_s07_0.png", + "caption": "a shield, metal rim, central emblem boss, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a19_shield-genxl1_s07_1.png", + "src": "a19_shield-genxl1_s07_1.png", + "caption": "a shield, metal rim, central emblem boss, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a19_sword-genxl1_s07_0.png", + "src": "a19_sword-genxl1_s07_0.png", + "caption": "a longsword, ornate engraved steel blade with a fuller, dark steel shading, ornate crossguard, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a19_sword-genxl1_s07_1.png", + "src": "a19_sword-genxl1_s07_1.png", + "caption": "a longsword, ornate engraved steel blade with a fuller, dark steel shading, ornate crossguard, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a20_belt-genxlb0_s07_1.png", + "src": "a20_belt-genxlb0_s07_1.png", + "caption": "a waist belt, leather strap, large ornate buckle, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a20_belt-genxlb1_s07_0.png", + "src": "a20_belt-genxlb1_s07_0.png", + "caption": "a waist belt, leather strap, large ornate buckle, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a20_belt-genxlb1_s07_2.png", + "src": "a20_belt-genxlb1_s07_2.png", + "caption": "a waist belt, leather strap, large ornate buckle, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a20_bow-genxlb0_s07_1.png", + "src": "a20_bow-genxlb0_s07_1.png", + "caption": "an ornate recurve bow, carved limbs with gold filigree fittings, gem at the wrapped grip, thin bowstring, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a20_dagger-genxlb0_s07_0.png", + "src": "a20_dagger-genxlb0_s07_0.png", + "caption": "a dagger, engraved steel blade with a fuller, dark steel shading, ornate hilt and crossguard, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a20_dagger-genxlb0_s07_1.png", + "src": "a20_dagger-genxlb0_s07_1.png", + "caption": "a dagger, engraved steel blade with a fuller, dark steel shading, ornate hilt and crossguard, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a20_staff-genxlb0_s07_0.png", + "src": "a20_staff-genxlb0_s07_0.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a20_staff-genxlb0_s07_1.png", + "src": "a20_staff-genxlb0_s07_1.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a20_staff-genxlb0_s07_2.png", + "src": "a20_staff-genxlb0_s07_2.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a20_staff-genxlb1_s07_2.png", + "src": "a20_staff-genxlb1_s07_2.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a21_necklace-genxlc0_s07_0.png", + "src": "a21_necklace-genxlc0_s07_0.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a21_necklace-genxlc0_s07_1.png", + "src": "a21_necklace-genxlc0_s07_1.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a21_necklace-genxlc0_s07_2.png", + "src": "a21_necklace-genxlc0_s07_2.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a21_spellbook-genxlc0_s07_0.png", + "src": "a21_spellbook-genxlc0_s07_0.png", + "caption": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a21_spellbook-genxlc0_s07_2.png", + "src": "a21_spellbook-genxlc0_s07_2.png", + "caption": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a23_axe-genxld1_s07_1.png", + "src": "a23_axe-genxld1_s07_1.png", + "caption": "a single-bladed battle axe, solid broad axe head attached to the shaft, engraved steel blade, dark steel shading, wooden shaft with metal fittings, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a23_hammer-genxld0_s07_1.png", + "src": "a23_hammer-genxld0_s07_1.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a23_hammer-genxld0_s07_2.png", + "src": "a23_hammer-genxld0_s07_2.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a23_hammer-genxld1_s07_2.png", + "src": "a23_hammer-genxld1_s07_2.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a23_helmet-genxld2_s07_0.png", + "src": "a23_helmet-genxld2_s07_0.png", + "caption": "a knight helmet, visor, crest, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a23_helmet-genxld2_s07_1.png", + "src": "a23_helmet-genxld2_s07_1.png", + "caption": "a knight helmet, visor, crest, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a23_helmet-genxld3_s07_2.png", + "src": "a23_helmet-genxld3_s07_2.png", + "caption": "a knight helmet, visor, crest, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a23_quiver-genxld1_s07_0.png", + "src": "a23_quiver-genxld1_s07_0.png", + "caption": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a23_quiver-genxld2_s07_0.png", + "src": "a23_quiver-genxld2_s07_0.png", + "caption": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a23_quiver-genxld2_s07_2.png", + "src": "a23_quiver-genxld2_s07_2.png", + "caption": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a23_ring-genxld0_s07_0.png", + "src": "a23_ring-genxld0_s07_0.png", + "caption": "a finger ring, large faceted gemstone, engraved band, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a23_ring-genxld0_s07_1.png", + "src": "a23_ring-genxld0_s07_1.png", + "caption": "a finger ring, large faceted gemstone, engraved band, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a23_ring-genxld1_s07_0.png", + "src": "a23_ring-genxld1_s07_0.png", + "caption": "a finger ring, large faceted gemstone, engraved band, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a23_ring-genxld2_s07_0.png", + "src": "a23_ring-genxld2_s07_0.png", + "caption": "a finger ring, large faceted gemstone, engraved band, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a23_ring-genxld3_s07_0.png", + "src": "a23_ring-genxld3_s07_0.png", + "caption": "a finger ring, large faceted gemstone, engraved band, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a23_ring-genxld3_s07_1.png", + "src": "a23_ring-genxld3_s07_1.png", + "caption": "a finger ring, large faceted gemstone, engraved band, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a23_shield-genxld0_s07_2.png", + "src": "a23_shield-genxld0_s07_2.png", + "caption": "a shield, metal rim, central emblem boss, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a23_shield-genxld3_s07_0.png", + "src": "a23_shield-genxld3_s07_0.png", + "caption": "a shield, metal rim, central emblem boss, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a23_shield-genxld3_s07_2.png", + "src": "a23_shield-genxld3_s07_2.png", + "caption": "a shield, metal rim, central emblem boss, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a23_sword-genxld0_s07_1.png", + "src": "a23_sword-genxld0_s07_1.png", + "caption": "a longsword, ornate engraved steel blade with a fuller, dark steel shading, ornate crossguard, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a24_axe-genxld1_s07_0.png", + "src": "a24_axe-genxld1_s07_0.png", + "caption": "a single-bladed battle axe, solid broad axe head attached to the shaft, engraved steel blade, dark steel shading, wooden shaft with metal fittings, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a24_axe-genxld1_s07_3.png", + "src": "a24_axe-genxld1_s07_3.png", + "caption": "a single-bladed battle axe, solid broad axe head attached to the shaft, engraved steel blade, dark steel shading, wooden shaft with metal fittings, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a24_bow-genxlb0_s07_1.png", + "src": "a24_bow-genxlb0_s07_1.png", + "caption": "an ornate recurve bow, carved limbs with gold filigree fittings, gem at the wrapped grip, thin bowstring, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a24_dagger-genxlb0_s07_2.png", + "src": "a24_dagger-genxlb0_s07_2.png", + "caption": "a dagger, engraved steel blade with a fuller, dark steel shading, ornate hilt and crossguard, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a24_dagger-genxlb0_s07_3.png", + "src": "a24_dagger-genxlb0_s07_3.png", + "caption": "a dagger, engraved steel blade with a fuller, dark steel shading, ornate hilt and crossguard, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a24_hammer-genxld0_s07_1.png", + "src": "a24_hammer-genxld0_s07_1.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a24_hammer-genxld0_s07_3.png", + "src": "a24_hammer-genxld0_s07_3.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a24_hammer-genxld1_s07_0.png", + "src": "a24_hammer-genxld1_s07_0.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a24_hammer-genxld1_s07_3.png", + "src": "a24_hammer-genxld1_s07_3.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a24_helmet-genxld2_s07_0.png", + "src": "a24_helmet-genxld2_s07_0.png", + "caption": "a knight helmet, visor, crest, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a24_helmet-genxld2_s07_1.png", + "src": "a24_helmet-genxld2_s07_1.png", + "caption": "a knight helmet, visor, crest, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a24_helmet-genxld2_s07_3.png", + "src": "a24_helmet-genxld2_s07_3.png", + "caption": "a knight helmet, visor, crest, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a24_helmet-genxld3_s07_0.png", + "src": "a24_helmet-genxld3_s07_0.png", + "caption": "a knight helmet, visor, crest, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a24_helmet-genxld3_s07_1.png", + "src": "a24_helmet-genxld3_s07_1.png", + "caption": "a knight helmet, visor, crest, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a24_horn-draw2_s07_0.png", + "src": "a24_horn-draw2_s07_0.png", + "caption": "a curved war horn, ivory body, metal rim bands, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a24_horn-draw2_s07_2.png", + "src": "a24_horn-draw2_s07_2.png", + "caption": "a curved war horn, ivory body, metal rim bands, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a24_orb-genmoba1_s07_0.png", + "src": "a24_orb-genmoba1_s07_0.png", + "caption": "a crystal orb, glass sphere on an ornate stand, gold trim on dark steel with red gems", + "source": "auto" + }, + { + "file": "a24_orb-genmoba1_s07_1.png", + "src": "a24_orb-genmoba1_s07_1.png", + "caption": "a crystal orb, glass sphere on an ornate stand, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a24_quiver-genxld2_s07_2.png", + "src": "a24_quiver-genxld2_s07_2.png", + "caption": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a24_shield-genxl1_s07_2.png", + "src": "a24_shield-genxl1_s07_2.png", + "caption": "a shield, metal rim, central emblem boss, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a24_shield-genxld3_s07_0.png", + "src": "a24_shield-genxld3_s07_0.png", + "caption": "a shield, metal rim, central emblem boss, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a24_shield-genxld3_s07_1.png", + "src": "a24_shield-genxld3_s07_1.png", + "caption": "a shield, metal rim, central emblem boss, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a24_shield-genxld3_s07_2.png", + "src": "a24_shield-genxld3_s07_2.png", + "caption": "a shield, metal rim, central emblem boss, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a24_spellbook-genxlc0_s07_0.png", + "src": "a24_spellbook-genxlc0_s07_0.png", + "caption": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a24_spellbook-genxlc0_s07_3.png", + "src": "a24_spellbook-genxlc0_s07_3.png", + "caption": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a24_sword-genxl1_s07_0.png", + "src": "a24_sword-genxl1_s07_0.png", + "caption": "a longsword, ornate engraved steel blade with a fuller, dark steel shading, ornate crossguard, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a24_sword-genxl1_s07_1.png", + "src": "a24_sword-genxl1_s07_1.png", + "caption": "a longsword, ornate engraved steel blade with a fuller, dark steel shading, ornate crossguard, gold and royal blue with silver steel", + "source": "auto" + }, + { + "file": "a24_totem-draw3_s07_0.png", + "src": "a24_totem-draw3_s07_0.png", + "caption": "a carved wooden totem, stacked tribal faces, small wings, gold trim on silver steel with blue gems", + "source": "auto" + }, + { + "file": "a24_totem-draw3_s07_1.png", + "src": "a24_totem-draw3_s07_1.png", + "caption": "a carved wooden totem, stacked tribal faces, small wings, gold and crimson red with silver steel", + "source": "auto" + }, + { + "file": "a26_armor-fr1253_s07_0.png", + "src": "a26_armor-fr1253_s07_0.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, (body made of antique gold and dark slate grey steel:1.25), natural material colors, a small ruby red gem accent only", + "source": "auto" + }, + { + "file": "a26_armor-fr1253_s07_1.png", + "src": "a26_armor-fr1253_s07_1.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, (body made of aged bronze and bone ivory:1.25), natural material colors, a small emerald green gem accent only", + "source": "auto" + }, + { + "file": "a26_armor-fr1267_s07_1.png", + "src": "a26_armor-fr1267_s07_1.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, (body made of dark iron and worn brown leather:1.25), natural material colors, a small amber orange gem accent only", + "source": "auto" + }, + { + "file": "a26_armor-fr1281_s07_2.png", + "src": "a26_armor-fr1281_s07_2.png", + "caption": "a chest armor, layered plates, shoulder pauldrons, (body made of blackened steel and antique brass:1.25), natural material colors, a small emerald green gem accent only", + "source": "auto" + }, + { + "file": "a26_axe-genxld1_s07_0.png", + "src": "a26_axe-genxld1_s07_0.png", + "caption": "a single-bladed battle axe, solid broad axe head attached to the shaft, engraved steel blade, dark steel shading, wooden shaft with metal fittings, (body made of dark iron and worn brown leather:1.25), natural material colors, a small amber orange gem accent only", + "source": "auto" + }, + { + "file": "a26_axe-genxld1_s07_2.png", + "src": "a26_axe-genxld1_s07_2.png", + "caption": "a single-bladed battle axe, solid broad axe head attached to the shaft, engraved steel blade, dark steel shading, wooden shaft with metal fittings, (body made of antique gold and dark slate grey steel:1.25), natural material colors, a small amethyst purple gem accent only", + "source": "auto" + }, + { + "file": "a26_belt-fr1351_s07_0.png", + "src": "a26_belt-fr1351_s07_0.png", + "caption": "a waist belt, leather strap, large ornate buckle, (body made of pale silver and deep burgundy leather:1.25), natural material colors, a small amber orange gem accent only", + "source": "auto" + }, + { + "file": "a26_belt-fr1351_s07_1.png", + "src": "a26_belt-fr1351_s07_1.png", + "caption": "a waist belt, leather strap, large ornate buckle, (body made of antique gold and dark slate grey steel:1.25), natural material colors, a small teal cyan glowing accent only", + "source": "auto" + }, + { + "file": "a26_belt-genxlb0_s07_1.png", + "src": "a26_belt-genxlb0_s07_1.png", + "caption": "a waist belt, leather strap, large ornate buckle, (body made of blackened steel and antique brass:1.25), natural material colors, a small amber orange gem accent only", + "source": "auto" + }, + { + "file": "a26_belt-genxlb0_s07_2.png", + "src": "a26_belt-genxlb0_s07_2.png", + "caption": "a waist belt, leather strap, large ornate buckle, (body made of gunmetal grey steel and tan leather wraps:1.25), natural material colors, a small teal cyan glowing accent only", + "source": "auto" + }, + { + "file": "a26_blunt-fr1057_s07_0.png", + "src": "a26_blunt-fr1057_s07_0.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, (body made of blackened steel and antique brass:1.25), natural material colors, a small amethyst purple gem accent only", + "source": "auto" + }, + { + "file": "a26_blunt-fr1057_s07_2.png", + "src": "a26_blunt-fr1057_s07_2.png", + "caption": "a flanged mace, heavy spiked metal head on a short handle, (body made of dark iron and worn brown leather:1.25), natural material colors, a small jade green inlay accent only", + "source": "auto" + }, + { + "file": "a26_boots-fr1393_s07_0.png", + "src": "a26_boots-fr1393_s07_0.png", + "caption": "a pair of armored boots, plated shins, (body made of dark iron and worn brown leather:1.25), natural material colors, a small rose pink crystal accent only", + "source": "auto" + }, + { + "file": "a26_boots-fr1393_s07_2.png", + "src": "a26_boots-fr1393_s07_2.png", + "caption": "a pair of armored boots, plated shins, (body made of antique gold and dark slate grey steel:1.25), natural material colors, a small sapphire blue gem accent only", + "source": "auto" + }, + { + "file": "a26_boots-fr1407_s07_1.png", + "src": "a26_boots-fr1407_s07_1.png", + "caption": "a pair of armored boots, plated shins, (body made of blackened steel and antique brass:1.25), natural material colors, a small pale moonstone white gem accent only", + "source": "auto" + }, + { + "file": "a26_boots-fr1407_s07_2.png", + "src": "a26_boots-fr1407_s07_2.png", + "caption": "a pair of armored boots, plated shins, (body made of gunmetal grey steel and tan leather wraps:1.25), natural material colors, a small turquoise inlay accent only", + "source": "auto" + }, + { + "file": "a26_bow-genxlb0_s07_1.png", + "src": "a26_bow-genxlb0_s07_1.png", + "caption": "an ornate recurve bow, carved limbs with gold filigree fittings, gem at the wrapped grip, thin bowstring, (body made of dark iron and worn brown leather:1.25), natural material colors, a small ruby red gem accent only", + "source": "auto" + }, + { + "file": "a26_bow-genxlb0_s07_2.png", + "src": "a26_bow-genxlb0_s07_2.png", + "caption": "an ornate recurve bow, carved limbs with gold filigree fittings, gem at the wrapped grip, thin bowstring, (body made of pale silver and deep burgundy leather:1.25), natural material colors, a small amber orange gem accent only", + "source": "auto" + }, + { + "file": "a26_dagger-genxlb0_s07_2.png", + "src": "a26_dagger-genxlb0_s07_2.png", + "caption": "a dagger, engraved steel blade with a fuller, dark steel shading, ornate hilt and crossguard, (body made of blackened steel and antique brass:1.25), natural material colors, a small amethyst purple gem accent only", + "source": "auto" + }, + { + "file": "a26_gloves-fr1183_s07_0.png", + "src": "a26_gloves-fr1183_s07_0.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, (body made of antique gold and dark slate grey steel:1.25), natural material colors, a small amethyst purple gem accent only", + "source": "auto" + }, + { + "file": "a26_gloves-fr1197_s07_0.png", + "src": "a26_gloves-fr1197_s07_0.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, (body made of gunmetal grey steel and tan leather wraps:1.25), natural material colors, a small pale moonstone white gem accent only", + "source": "auto" + }, + { + "file": "a26_gloves-fr1197_s07_1.png", + "src": "a26_gloves-fr1197_s07_1.png", + "caption": "a pair of armored gauntlets, plated fingers, wrist cuffs, (body made of dark iron and worn brown leather:1.25), natural material colors, a small sapphire blue gem accent only", + "source": "auto" + }, + { + "file": "a26_hammer-genxld0_s07_1.png", + "src": "a26_hammer-genxld0_s07_1.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, (body made of blackened steel and antique brass:1.25), natural material colors, a small emerald green gem accent only", + "source": "auto" + }, + { + "file": "a26_hammer-genxld0_s07_2.png", + "src": "a26_hammer-genxld0_s07_2.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, (body made of gunmetal grey steel and tan leather wraps:1.25), natural material colors, a small pale moonstone white gem accent only", + "source": "auto" + }, + { + "file": "a26_hammer-genxld1_s07_0.png", + "src": "a26_hammer-genxld1_s07_0.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, (body made of antique gold and dark slate grey steel:1.25), natural material colors, a small teal cyan glowing accent only", + "source": "auto" + }, + { + "file": "a26_hammer-genxld1_s07_1.png", + "src": "a26_hammer-genxld1_s07_1.png", + "caption": "a war hammer, heavy block metal head with ornate banded ends and an engraved emblem, wrapped handle, (body made of aged bronze and bone ivory:1.25), natural material colors, a small turquoise inlay accent only", + "source": "auto" + }, + { + "file": "a26_helmet-genmoba0_s07_1.png", + "src": "a26_helmet-genmoba0_s07_1.png", + "caption": "a knight helmet, visor, crest, (body made of antique gold and dark slate grey steel:1.25), natural material colors, a small ruby red gem accent only", + "source": "auto" + }, + { + "file": "a26_helmet-genxld3_s07_2.png", + "src": "a26_helmet-genxld3_s07_2.png", + "caption": "a knight helmet, visor, crest, (body made of blackened steel and antique brass:1.25), natural material colors, a small amber orange gem accent only", + "source": "auto" + }, + { + "file": "a26_horn-draw2_s07_0.png", + "src": "a26_horn-draw2_s07_0.png", + "caption": "a curved war horn, ivory body, metal rim bands, (body made of blackened steel and antique brass:1.25), natural material colors, a small amber orange gem accent only", + "source": "auto" + }, + { + "file": "a26_horn-draw2_s07_2.png", + "src": "a26_horn-draw2_s07_2.png", + "caption": "a curved war horn, ivory body, metal rim bands, (body made of dark iron and worn brown leather:1.25), natural material colors, a small amber orange gem accent only", + "source": "auto" + }, + { + "file": "a26_necklace-fr1099_s07_0.png", + "src": "a26_necklace-fr1099_s07_0.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, (body made of aged bronze and bone ivory:1.25), natural material colors, a small jade green inlay accent only", + "source": "auto" + }, + { + "file": "a26_necklace-fr1113_s07_1.png", + "src": "a26_necklace-fr1113_s07_1.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, (body made of pale silver and deep burgundy leather:1.25), natural material colors, a small amber orange gem accent only", + "source": "auto" + }, + { + "file": "a26_necklace-fr1127_s07_1.png", + "src": "a26_necklace-fr1127_s07_1.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, (body made of blackened steel and antique brass:1.25), natural material colors, a small amethyst purple gem accent only", + "source": "auto" + }, + { + "file": "a26_necklace-fr1127_s07_2.png", + "src": "a26_necklace-fr1127_s07_2.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, (body made of gunmetal grey steel and tan leather wraps:1.25), natural material colors, a small emerald green gem accent only", + "source": "auto" + }, + { + "file": "a26_necklace-genxlc0_s07_1.png", + "src": "a26_necklace-genxlc0_s07_1.png", + "caption": "a pendant amulet, faceted gem in an ornate setting, (body made of gunmetal grey steel and tan leather wraps:1.25), natural material colors, a small amethyst purple gem accent only", + "source": "auto" + }, + { + "file": "a26_quiver-genxld2_s07_1.png", + "src": "a26_quiver-genxld2_s07_1.png", + "caption": "a leather quiver full of arrows, feathered arrows sticking out, shoulder strap, (body made of antique gold and dark slate grey steel:1.25), natural material colors, a small sapphire blue gem accent only", + "source": "auto" + }, + { + "file": "a26_ring-genxld0_s07_0.png", + "src": "a26_ring-genxld0_s07_0.png", + "caption": "a finger ring, large faceted gemstone, engraved band, (body made of blackened steel and antique brass:1.25), natural material colors, a small pale moonstone white gem accent only", + "source": "auto" + }, + { + "file": "a26_ring-genxld0_s07_1.png", + "src": "a26_ring-genxld0_s07_1.png", + "caption": "a finger ring, large faceted gemstone, engraved band, (body made of gunmetal grey steel and tan leather wraps:1.25), natural material colors, a small turquoise inlay accent only", + "source": "auto" + }, + { + "file": "a26_ring-genxld0_s07_2.png", + "src": "a26_ring-genxld0_s07_2.png", + "caption": "a finger ring, large faceted gemstone, engraved band, (body made of dark iron and worn brown leather:1.25), natural material colors, a small ruby red gem accent only", + "source": "auto" + }, + { + "file": "a26_ring-genxld2_s07_0.png", + "src": "a26_ring-genxld2_s07_0.png", + "caption": "a finger ring, large faceted gemstone, engraved band, (body made of dark iron and worn brown leather:1.25), natural material colors, a small sapphire blue gem accent only", + "source": "auto" + }, + { + "file": "a26_ring-genxld2_s07_2.png", + "src": "a26_ring-genxld2_s07_2.png", + "caption": "a finger ring, large faceted gemstone, engraved band, (body made of antique gold and dark slate grey steel:1.25), natural material colors, a small amber orange gem accent only", + "source": "auto" + }, + { + "file": "a26_ring-genxld3_s07_1.png", + "src": "a26_ring-genxld3_s07_1.png", + "caption": "a finger ring, large faceted gemstone, engraved band, (body made of blackened steel and antique brass:1.25), natural material colors, a small teal cyan glowing accent only", + "source": "auto" + }, + { + "file": "a26_shield-draw0_s07_0.png", + "src": "a26_shield-draw0_s07_0.png", + "caption": "a shield, metal rim, central emblem boss, (body made of gunmetal grey steel and tan leather wraps:1.25), natural material colors, a small amethyst purple gem accent only", + "source": "auto" + }, + { + "file": "a26_shield-genxl1_s07_2.png", + "src": "a26_shield-genxl1_s07_2.png", + "caption": "a shield, metal rim, central emblem boss, (body made of antique gold and dark slate grey steel:1.25), natural material colors, a small ruby red gem accent only", + "source": "auto" + }, + { + "file": "a26_shield-genxld3_s07_0.png", + "src": "a26_shield-genxld3_s07_0.png", + "caption": "a shield, metal rim, central emblem boss, (body made of antique gold and dark slate grey steel:1.25), natural material colors, a small ruby red gem accent only", + "source": "auto" + }, + { + "file": "a26_shield-genxld3_s07_1.png", + "src": "a26_shield-genxld3_s07_1.png", + "caption": "a shield, metal rim, central emblem boss, (body made of aged bronze and bone ivory:1.25), natural material colors, a small emerald green gem accent only", + "source": "auto" + }, + { + "file": "a26_spellbook-genxlc0_s07_0.png", + "src": "a26_spellbook-genxlc0_s07_0.png", + "caption": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, (body made of aged bronze and bone ivory:1.25), natural material colors, a small emerald green gem accent only", + "source": "auto" + }, + { + "file": "a26_spellbook-genxlc0_s07_2.png", + "src": "a26_spellbook-genxlc0_s07_2.png", + "caption": "a closed spellbook, thick tome, metal corner clasps, gem on the cover, (body made of weathered steel and dark walnut wood:1.25), natural material colors, a small emerald green gem accent only", + "source": "auto" + }, + { + "file": "a26_staff-draw1_s07_2.png", + "src": "a26_staff-draw1_s07_2.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, (body made of blackened steel and antique brass:1.25), natural material colors, a small pale moonstone white gem accent only", + "source": "auto" + }, + { + "file": "a26_staff-genxlb0_s07_0.png", + "src": "a26_staff-genxlb0_s07_0.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, (body made of pale silver and deep burgundy leather:1.25), natural material colors, a small ruby red gem accent only", + "source": "auto" + }, + { + "file": "a26_staff-genxlb0_s07_1.png", + "src": "a26_staff-genxlb0_s07_1.png", + "caption": "a wizard staff, long shaft, glowing crystal head ornament, (body made of antique gold and dark slate grey steel:1.25), natural material colors, a small amber orange gem accent only", + "source": "auto" + }, + { + "file": "a26_throwing-draw0_s07_1.png", + "src": "a26_throwing-draw0_s07_1.png", + "caption": "a throwing blade, kunai, sharp steel, (body made of antique gold and dark slate grey steel:1.25), natural material colors, a small amethyst purple gem accent only", + "source": "auto" + }, + { + "file": "a26_totem-draw3_s07_0.png", + "src": "a26_totem-draw3_s07_0.png", + "caption": "a carved wooden totem, stacked tribal faces, small wings, (body made of blackened steel and antique brass:1.25), natural material colors, a small emerald green gem accent only", + "source": "auto" + }, + { + "file": "a27_armor-fr1253_s07_1.png", + "src": "a27_armor-fr1253_s07_1.png", + "caption": "a chest armor, layered blackened steel plates with dark iron rivets and trim, teal leather wrap straps, shoulder pauldrons, a small ruby red gem on the chest, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_armor-fr1267_s07_0.png", + "src": "a27_armor-fr1267_s07_0.png", + "caption": "a chest armor, layered weathered steel plates with antique brass trim, worn brown leather straps, shoulder pauldrons, a small turquoise inlay on the chest, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_armor-fr1267_s07_1.png", + "src": "a27_armor-fr1267_s07_1.png", + "caption": "a chest armor, layered aged bronze plates with silver trim, deep burgundy leather straps, shoulder pauldrons, a small amber orange gem on the chest, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_armor-fr1281_s07_0.png", + "src": "a27_armor-fr1281_s07_0.png", + "caption": "a chest armor, layered antique gold plates with dark iron rivets and trim, black leather straps, shoulder pauldrons, a small amethyst purple gem on the chest, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_armor-fr1281_s07_1.png", + "src": "a27_armor-fr1281_s07_1.png", + "caption": "a chest armor, layered weathered steel plates with antique brass trim, bone ivory straps, shoulder pauldrons, a small turquoise inlay on the chest, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_axe-genxld1_s07_0.png", + "src": "a27_axe-genxld1_s07_0.png", + "caption": "a single-bladed battle axe, solid broad aged bronze axe head attached to the shaft, deep burgundy leather shaft with silver trim, a small amber orange gem on the axe head, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_belt-fr1351_s07_0.png", + "src": "a27_belt-fr1351_s07_0.png", + "caption": "a waist belt, tan leather wraps strap, large ornate verdigris bronze buckle with antique gold trim, a small emerald green gem in the buckle, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_belt-genxlb1_s07_0.png", + "src": "a27_belt-genxlb1_s07_0.png", + "caption": "a waist belt, dark oak wood strap, large ornate blued steel buckle with antique brass trim, a small garnet dark red gem in the buckle, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_blunt-fr1057_s07_0.png", + "src": "a27_blunt-fr1057_s07_0.png", + "caption": "a flanged mace, heavy spiked blued steel head, dark walnut wood wrapped handle with antique brass trim, a small garnet dark red gem on the head, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_boots-fr1379_s07_1.png", + "src": "a27_boots-fr1379_s07_1.png", + "caption": "a pair of armored boots, blued steel plated shins with antique brass trim, black leather boot, a small garnet dark red gem on the shin, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_boots-fr1393_s07_0.png", + "src": "a27_boots-fr1393_s07_0.png", + "caption": "a pair of armored boots, pale silver plated shins with antique gold trim, deep burgundy leather boot, a small moonstone white gem on the shin, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_boots-fr1393_s07_1.png", + "src": "a27_boots-fr1393_s07_1.png", + "caption": "a pair of armored boots, tarnished copper plated shins with bronze trim, tan leather wraps boot, a small topaz yellow gem on the shin, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_boots-fr1407_s07_0.png", + "src": "a27_boots-fr1407_s07_0.png", + "caption": "a pair of armored boots, dark iron plated shins with silver trim, bone ivory boot, a small jade green inlay on the shin, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_boots-fr1407_s07_1.png", + "src": "a27_boots-fr1407_s07_1.png", + "caption": "a pair of armored boots, pale silver plated shins with antique gold trim, dark walnut wood boot, a small moonstone white gem on the shin, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_bow-genxlb0_s07_0.png", + "src": "a27_bow-genxlb0_s07_0.png", + "caption": "an ornate recurve bow, carved worn brown leather limbs with tarnished copper fittings, wrapped grip, thin bowstring, a small topaz yellow gem at the grip, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_bow-genxlb0_s07_1.png", + "src": "a27_bow-genxlb0_s07_1.png", + "caption": "an ornate recurve bow, carved deep burgundy leather limbs with blued steel fittings, wrapped grip, thin bowstring, a small garnet dark red gem at the grip, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_dagger-genxlb0_s07_0.png", + "src": "a27_dagger-genxlb0_s07_0.png", + "caption": "a dagger, pale silver blade with a fuller, antique gold trim crossguard, black leather wrapped grip, a small moonstone white gem in the pommel, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_dagger-genxlb0_s07_1.png", + "src": "a27_dagger-genxlb0_s07_1.png", + "caption": "a dagger, tarnished copper blade with a fuller, bronze trim crossguard, bone ivory wrapped grip, a small topaz yellow gem in the pommel, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_gloves-fr1197_s07_1.png", + "src": "a27_gloves-fr1197_s07_1.png", + "caption": "a pair of armored gauntlets, gunmetal grey steel plated fingers with bronze trim, deep burgundy leather cuffs, a small sapphire blue gem on the back of the hand, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_hammer-genxld0_s07_1.png", + "src": "a27_hammer-genxld0_s07_1.png", + "caption": "a war hammer, heavy block aged bronze head with banded ends, dark walnut wood wrapped handle with silver trim, a small amber orange gem on the head, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_hammer-genxld1_s07_0.png", + "src": "a27_hammer-genxld1_s07_0.png", + "caption": "a war hammer, heavy block antique gold head with banded ends, dark oak wood wrapped handle with dark iron rivets and trim, a small amethyst purple gem on the head, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_hammer-genxld1_s07_1.png", + "src": "a27_hammer-genxld1_s07_1.png", + "caption": "a war hammer, heavy block weathered steel head with banded ends, teal leather wrap wrapped handle with antique brass trim, a small turquoise inlay on the head, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_helmet-genxld3_s07_0.png", + "src": "a27_helmet-genxld3_s07_0.png", + "caption": "a knight helmet, blued steel plates with antique brass trim, visor, crest, a small garnet dark red gem on the brow, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_horn-draw2_s07_0.png", + "src": "a27_horn-draw2_s07_0.png", + "caption": "a curved war horn, bone ivory body, antique gold rim bands with dark iron rivets and trim, dark walnut wood strap, a small amethyst purple gem on the band, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_necklace-fr1099_s07_0.png", + "src": "a27_necklace-fr1099_s07_0.png", + "caption": "a pendant amulet, verdigris bronze ornate setting with antique gold trim, a small emerald green gem in the center, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_necklace-fr1113_s07_0.png", + "src": "a27_necklace-fr1113_s07_0.png", + "caption": "a pendant amulet, blued steel ornate setting with antique brass trim, a small garnet dark red gem in the center, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_necklace-fr1113_s07_1.png", + "src": "a27_necklace-fr1113_s07_1.png", + "caption": "a pendant amulet, verdigris bronze ornate setting with antique gold trim, a small emerald green gem in the center, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_necklace-fr1127_s07_1.png", + "src": "a27_necklace-fr1127_s07_1.png", + "caption": "a pendant amulet, blued steel ornate setting with antique brass trim, a small garnet dark red gem in the center, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_necklace-genxlc0_s07_1.png", + "src": "a27_necklace-genxlc0_s07_1.png", + "caption": "a pendant amulet, dark iron ornate setting with silver trim, a small jade green inlay in the center, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_orb-genmoba1_s07_0.png", + "src": "a27_orb-genmoba1_s07_0.png", + "caption": "a crystal orb, glass sphere on an ornate pale silver stand with antique gold trim, a small moonstone white gem glow inside the sphere, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_quiver-genxld2_s07_0.png", + "src": "a27_quiver-genxld2_s07_0.png", + "caption": "a quiver full of arrows, tan leather wraps body with tarnished copper fittings, feathered arrows sticking out, shoulder strap, a small topaz yellow gem on the fitting, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_ring-genxld0_s07_0.png", + "src": "a27_ring-genxld0_s07_0.png", + "caption": "a finger ring, engraved pale silver band with antique gold trim, a small moonstone white gem in an ornate setting, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_ring-genxld1_s07_1.png", + "src": "a27_ring-genxld1_s07_1.png", + "caption": "a finger ring, engraved pale silver band with antique gold trim, a small moonstone white gem in an ornate setting, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_ring-genxld2_s07_0.png", + "src": "a27_ring-genxld2_s07_0.png", + "caption": "a finger ring, engraved gunmetal grey steel band with bronze trim, a small sapphire blue gem in an ornate setting, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_ring-genxld2_s07_1.png", + "src": "a27_ring-genxld2_s07_1.png", + "caption": "a finger ring, engraved dark iron band with silver trim, a small jade green inlay in an ornate setting, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_ring-genxld3_s07_0.png", + "src": "a27_ring-genxld3_s07_0.png", + "caption": "a finger ring, engraved blackened steel band with dark iron rivets and trim, a small ruby red gem in an ornate setting, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_ring-genxld3_s07_1.png", + "src": "a27_ring-genxld3_s07_1.png", + "caption": "a finger ring, engraved gunmetal grey steel band with bronze trim, a small sapphire blue gem in an ornate setting, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_shield-draw0_s07_1.png", + "src": "a27_shield-draw0_s07_1.png", + "caption": "a shield, pale silver rim with antique gold trim, deep burgundy leather covered face, central emblem boss, a small moonstone white gem on the boss, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_shield-genxld3_s07_0.png", + "src": "a27_shield-genxld3_s07_0.png", + "caption": "a shield, aged bronze rim with silver trim, dark oak wood covered face, central emblem boss, a small amber orange gem on the boss, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_shield-genxld3_s07_1.png", + "src": "a27_shield-genxld3_s07_1.png", + "caption": "a shield, blackened steel rim with dark iron rivets and trim, teal leather wrap covered face, central emblem boss, a small ruby red gem on the boss, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_spellbook-genxlc0_s07_0.png", + "src": "a27_spellbook-genxlc0_s07_0.png", + "caption": "a closed spellbook, thick tome, teal leather wrap cover, blackened steel corner clasps, a small ruby red gem on the cover, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_staff-draw1_s07_0.png", + "src": "a27_staff-draw1_s07_0.png", + "caption": "a wizard staff, long black leather shaft with gunmetal grey steel fittings, crystal head ornament, a small sapphire blue gem glowing softly, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_sword-genxl1_s07_1.png", + "src": "a27_sword-genxl1_s07_1.png", + "caption": "a longsword, aged bronze blade with a fuller, silver trim crossguard, black leather wrapped grip, a small amber orange gem in the pommel, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_throwing-draw0_s07_0.png", + "src": "a27_throwing-draw0_s07_0.png", + "caption": "a throwing blade, kunai, sharp blackened steel blade, tan leather wraps wrapped grip, a small ruby red gem on the ring pommel, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_totem-draw3_s07_0.png", + "src": "a27_totem-draw3_s07_0.png", + "caption": "a carved totem, dark walnut wood body with stacked tribal faces, aged bronze bands, small wings, a small amber orange gem eyes, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + }, + { + "file": "a27_totem-draw3_s07_1.png", + "src": "a27_totem-draw3_s07_1.png", + "caption": "a carved totem, worn brown leather body with stacked tribal faces, blackened steel bands, small wings, a small ruby red gem eyes, engraved filigree, etched runes, rivets, worn edges, fine scratches", + "source": "auto" + } +] \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/edge_check.png b/공유/기획/FirstRising/아이템/moba_anfg/edge_check.png new file mode 100644 index 0000000..dd057ce Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/edge_check.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/final_v4e/final_sheet.png b/공유/기획/FirstRising/아이템/moba_anfg/final_v4e/final_sheet.png new file mode 100644 index 0000000..880f89d Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/final_v4e/final_sheet.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/final_v4e/index.json b/공유/기획/FirstRising/아이템/moba_anfg/final_v4e/index.json new file mode 100644 index 0000000..70f4e75 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/final_v4e/index.json @@ -0,0 +1,666 @@ +[ + { + "icon": "sword_01.png", + "source": "a13l_sword-draw2_s07_1.png" + }, + { + "icon": "sword_02.png", + "source": "a13l_sword-genpd2sword_s07_1.png" + }, + { + "icon": "sword_03.png", + "source": "a15_sword-draw2_s07_2.png" + }, + { + "icon": "sword_04.png", + "source": "a19_sword-genxl1_s07_0.png" + }, + { + "icon": "sword_05.png", + "source": "a19_sword-genxl1_s07_1.png" + }, + { + "icon": "sword_06.png", + "source": "a23_sword-genxld0_s07_1.png" + }, + { + "icon": "sword_07.png", + "source": "a24_sword-genxl1_s07_0.png" + }, + { + "icon": "sword_08.png", + "source": "a24_sword-genxl1_s07_1.png" + }, + { + "icon": "dagger_01.png", + "source": "a15_dagger-draw3_s07_1.png" + }, + { + "icon": "dagger_02.png", + "source": "a20_dagger-genxlb0_s07_0.png" + }, + { + "icon": "dagger_03.png", + "source": "a20_dagger-genxlb0_s07_1.png" + }, + { + "icon": "dagger_04.png", + "source": "a24_dagger-genxlb0_s07_2.png" + }, + { + "icon": "dagger_05.png", + "source": "a24_dagger-genxlb0_s07_3.png" + }, + { + "icon": "axe_01.png", + "source": "a17_axe-genmoba0_s07_0.png" + }, + { + "icon": "axe_02.png", + "source": "a23_axe-genxld1_s07_1.png" + }, + { + "icon": "axe_03.png", + "source": "a24_axe-genxld1_s07_0.png" + }, + { + "icon": "axe_04.png", + "source": "a24_axe-genxld1_s07_3.png" + }, + { + "icon": "blunt_01.png", + "source": "a13l_blunt-fr1057_s07_0.png" + }, + { + "icon": "blunt_02.png", + "source": "a13l_blunt-fr1057_s07_1.png" + }, + { + "icon": "blunt_03.png", + "source": "a16b_blunt-fr1057_s07_1.png" + }, + { + "icon": "blunt_04.png", + "source": "a16d_blunt-fr1057_s08_0.png" + }, + { + "icon": "blunt_05.png", + "source": "a17_blunt-fr1057_s07_0.png" + }, + { + "icon": "blunt_06.png", + "source": "a17_blunt-fr1057_s07_1.png" + }, + { + "icon": "hammer_01.png", + "source": "a13l_hammer-draw0_s07_0.png" + }, + { + "icon": "hammer_02.png", + "source": "a15_hammer-draw2_s07_2.png" + }, + { + "icon": "hammer_03.png", + "source": "a15_hammer-draw2_s07_3.png" + }, + { + "icon": "hammer_04.png", + "source": "a17_hammer-draw2_s07_1.png" + }, + { + "icon": "hammer_05.png", + "source": "a23_hammer-genxld0_s07_1.png" + }, + { + "icon": "hammer_06.png", + "source": "a23_hammer-genxld0_s07_2.png" + }, + { + "icon": "hammer_07.png", + "source": "a23_hammer-genxld1_s07_2.png" + }, + { + "icon": "hammer_08.png", + "source": "a24_hammer-genxld0_s07_1.png" + }, + { + "icon": "hammer_09.png", + "source": "a24_hammer-genxld0_s07_3.png" + }, + { + "icon": "hammer_10.png", + "source": "a24_hammer-genxld1_s07_0.png" + }, + { + "icon": "hammer_11.png", + "source": "a24_hammer-genxld1_s07_3.png" + }, + { + "icon": "bow_01.png", + "source": "a13l_bow-draw2_s07_1.png" + }, + { + "icon": "bow_02.png", + "source": "a15_bow-draw3_s07_3.png" + }, + { + "icon": "bow_03.png", + "source": "a17_bow-draw3_s07_1.png" + }, + { + "icon": "bow_04.png", + "source": "a20_bow-genxlb0_s07_1.png" + }, + { + "icon": "bow_05.png", + "source": "a24_bow-genxlb0_s07_1.png" + }, + { + "icon": "staff_01.png", + "source": "a13l_staff-draw0_s07_0.png" + }, + { + "icon": "staff_02.png", + "source": "a13l_staff-draw0_s07_1.png" + }, + { + "icon": "staff_03.png", + "source": "a13l_staff-draw1_s07_1.png" + }, + { + "icon": "staff_04.png", + "source": "a13l_staff-draw1_s07_2.png" + }, + { + "icon": "staff_05.png", + "source": "a16b_staff-draw1_s07_0.png" + }, + { + "icon": "staff_06.png", + "source": "a17_staff-draw0_s07_0.png" + }, + { + "icon": "staff_07.png", + "source": "a17_staff-draw1_s07_0.png" + }, + { + "icon": "staff_08.png", + "source": "a17_staff-draw1_s07_1.png" + }, + { + "icon": "staff_09.png", + "source": "a20_staff-genxlb0_s07_0.png" + }, + { + "icon": "staff_10.png", + "source": "a20_staff-genxlb0_s07_1.png" + }, + { + "icon": "staff_11.png", + "source": "a20_staff-genxlb0_s07_2.png" + }, + { + "icon": "staff_12.png", + "source": "a20_staff-genxlb1_s07_2.png" + }, + { + "icon": "armor_01.png", + "source": "a13t_armor_s07_0.png" + }, + { + "icon": "armor_02.png", + "source": "a14_armor-fr1253_s07_1.png" + }, + { + "icon": "armor_03.png", + "source": "a14_armor-fr1267_s07_0.png" + }, + { + "icon": "armor_04.png", + "source": "a14_armor-fr1267_s07_1.png" + }, + { + "icon": "armor_05.png", + "source": "a14_armor-fr1281_s07_0.png" + }, + { + "icon": "armor_06.png", + "source": "a14_armor-fr1281_s07_1.png" + }, + { + "icon": "armor_07.png", + "source": "a16b_armor-fr1267_s07_1.png" + }, + { + "icon": "armor_08.png", + "source": "a17_armor-fr1253_s07_0.png" + }, + { + "icon": "armor_09.png", + "source": "a17_armor-fr1253_s07_1.png" + }, + { + "icon": "armor_10.png", + "source": "a17_armor-fr1267_s07_0.png" + }, + { + "icon": "armor_11.png", + "source": "a17_armor-fr1267_s07_1.png" + }, + { + "icon": "armor_12.png", + "source": "a17_armor-fr1281_s07_0.png" + }, + { + "icon": "armor_13.png", + "source": "a17_armor-fr1281_s07_1.png" + }, + { + "icon": "helmet_01.png", + "source": "a17_helmet-genmoba0_s07_0.png" + }, + { + "icon": "helmet_02.png", + "source": "a19_helmet-genxl1_s07_0.png" + }, + { + "icon": "helmet_03.png", + "source": "a23_helmet-genxld2_s07_0.png" + }, + { + "icon": "helmet_04.png", + "source": "a23_helmet-genxld2_s07_1.png" + }, + { + "icon": "helmet_05.png", + "source": "a23_helmet-genxld3_s07_2.png" + }, + { + "icon": "helmet_06.png", + "source": "a24_helmet-genxld2_s07_0.png" + }, + { + "icon": "helmet_07.png", + "source": "a24_helmet-genxld2_s07_1.png" + }, + { + "icon": "helmet_08.png", + "source": "a24_helmet-genxld2_s07_3.png" + }, + { + "icon": "helmet_09.png", + "source": "a24_helmet-genxld3_s07_0.png" + }, + { + "icon": "helmet_10.png", + "source": "a24_helmet-genxld3_s07_1.png" + }, + { + "icon": "gloves_01.png", + "source": "a14_gloves-fr1169_s07_1.png" + }, + { + "icon": "gloves_02.png", + "source": "a14_gloves-fr1197_s07_1.png" + }, + { + "icon": "gloves_03.png", + "source": "a17_gloves-fr1183_s07_0.png" + }, + { + "icon": "gloves_04.png", + "source": "a17_gloves-fr1183_s07_1.png" + }, + { + "icon": "gloves_05.png", + "source": "a17_gloves-fr1197_s07_0.png" + }, + { + "icon": "gloves_06.png", + "source": "a17_gloves-fr1211_s07_0.png" + }, + { + "icon": "gloves_07.png", + "source": "a17_gloves-fr1211_s07_1.png" + }, + { + "icon": "belt_01.png", + "source": "a14_belt-fr1351_s07_0.png" + }, + { + "icon": "belt_02.png", + "source": "a14_belt-fr1351_s07_1.png" + }, + { + "icon": "belt_03.png", + "source": "a17_belt-fr1351_s07_1.png" + }, + { + "icon": "belt_04.png", + "source": "a20_belt-genxlb0_s07_1.png" + }, + { + "icon": "belt_05.png", + "source": "a20_belt-genxlb1_s07_0.png" + }, + { + "icon": "belt_06.png", + "source": "a20_belt-genxlb1_s07_2.png" + }, + { + "icon": "boots_01.png", + "source": "a13t_boots_s07_1.png" + }, + { + "icon": "boots_02.png", + "source": "a14_boots-fr1379_s07_0.png" + }, + { + "icon": "boots_03.png", + "source": "a14_boots-fr1379_s07_1.png" + }, + { + "icon": "boots_04.png", + "source": "a14_boots-fr1393_s07_0.png" + }, + { + "icon": "boots_05.png", + "source": "a14_boots-fr1407_s07_0.png" + }, + { + "icon": "boots_06.png", + "source": "a14_boots-fr1421_s07_0.png" + }, + { + "icon": "boots_07.png", + "source": "a16d_boots-fr1379_s08_0.png" + }, + { + "icon": "boots_08.png", + "source": "a16d_boots-fr1379_s08_1.png" + }, + { + "icon": "boots_09.png", + "source": "a17_boots-fr1379_s07_0.png" + }, + { + "icon": "boots_10.png", + "source": "a17_boots-fr1379_s07_1.png" + }, + { + "icon": "boots_11.png", + "source": "a17_boots-fr1393_s07_0.png" + }, + { + "icon": "boots_12.png", + "source": "a17_boots-fr1407_s07_1.png" + }, + { + "icon": "boots_13.png", + "source": "a17_boots-fr1421_s07_0.png" + }, + { + "icon": "ring_01.png", + "source": "a19_ring-genxl0_s07_1.png" + }, + { + "icon": "ring_02.png", + "source": "a19_ring-genxl1_s07_0.png" + }, + { + "icon": "ring_03.png", + "source": "a23_ring-genxld0_s07_0.png" + }, + { + "icon": "ring_04.png", + "source": "a23_ring-genxld0_s07_1.png" + }, + { + "icon": "ring_05.png", + "source": "a23_ring-genxld1_s07_0.png" + }, + { + "icon": "ring_06.png", + "source": "a23_ring-genxld2_s07_0.png" + }, + { + "icon": "ring_07.png", + "source": "a23_ring-genxld3_s07_0.png" + }, + { + "icon": "ring_08.png", + "source": "a23_ring-genxld3_s07_1.png" + }, + { + "icon": "necklace_01.png", + "source": "a14_necklace-fr1099_s07_0.png" + }, + { + "icon": "necklace_02.png", + "source": "a14_necklace-fr1099_s07_1.png" + }, + { + "icon": "necklace_03.png", + "source": "a14_necklace-fr1113_s07_1.png" + }, + { + "icon": "necklace_04.png", + "source": "a14_necklace-fr1127_s07_0.png" + }, + { + "icon": "necklace_05.png", + "source": "a14_necklace-fr1141_s07_0.png" + }, + { + "icon": "necklace_06.png", + "source": "a16b_necklace-fr1099_s07_0.png" + }, + { + "icon": "necklace_07.png", + "source": "a17_necklace-fr1099_s07_0.png" + }, + { + "icon": "necklace_08.png", + "source": "a17_necklace-fr1113_s07_1.png" + }, + { + "icon": "necklace_09.png", + "source": "a17_necklace-fr1127_s07_0.png" + }, + { + "icon": "necklace_10.png", + "source": "a17_necklace-fr1127_s07_1.png" + }, + { + "icon": "necklace_11.png", + "source": "a21_necklace-genxlc0_s07_0.png" + }, + { + "icon": "necklace_12.png", + "source": "a21_necklace-genxlc0_s07_1.png" + }, + { + "icon": "necklace_13.png", + "source": "a21_necklace-genxlc0_s07_2.png" + }, + { + "icon": "shield_01.png", + "source": "a14_shield-draw0_s07_0.png" + }, + { + "icon": "shield_02.png", + "source": "a14_shield-genpd2shield_s07_1.png" + }, + { + "icon": "shield_03.png", + "source": "a16d_shield-draw0_s08_1.png" + }, + { + "icon": "shield_04.png", + "source": "a19_shield-genxl1_s07_0.png" + }, + { + "icon": "shield_05.png", + "source": "a19_shield-genxl1_s07_1.png" + }, + { + "icon": "shield_06.png", + "source": "a23_shield-genxld0_s07_2.png" + }, + { + "icon": "shield_07.png", + "source": "a23_shield-genxld3_s07_0.png" + }, + { + "icon": "shield_08.png", + "source": "a23_shield-genxld3_s07_2.png" + }, + { + "icon": "shield_09.png", + "source": "a24_shield-genxl1_s07_2.png" + }, + { + "icon": "shield_10.png", + "source": "a24_shield-genxld3_s07_0.png" + }, + { + "icon": "shield_11.png", + "source": "a24_shield-genxld3_s07_1.png" + }, + { + "icon": "shield_12.png", + "source": "a24_shield-genxld3_s07_2.png" + }, + { + "icon": "quiver_01.png", + "source": "a14_quiver-draw2_s07_1.png" + }, + { + "icon": "quiver_02.png", + "source": "a19_quiver-genxl1_s07_0.png" + }, + { + "icon": "quiver_03.png", + "source": "a19_quiver-genxl1_s07_1.png" + }, + { + "icon": "quiver_04.png", + "source": "a23_quiver-genxld1_s07_0.png" + }, + { + "icon": "quiver_05.png", + "source": "a23_quiver-genxld2_s07_0.png" + }, + { + "icon": "quiver_06.png", + "source": "a23_quiver-genxld2_s07_2.png" + }, + { + "icon": "quiver_07.png", + "source": "a24_quiver-genxld2_s07_2.png" + }, + { + "icon": "spellbook_01.png", + "source": "a14_spellbook-llbook1_s07_0.png" + }, + { + "icon": "spellbook_02.png", + "source": "a17_spellbook-llbook1_s07_1.png" + }, + { + "icon": "spellbook_03.png", + "source": "a21_spellbook-genxlc0_s07_0.png" + }, + { + "icon": "spellbook_04.png", + "source": "a21_spellbook-genxlc0_s07_2.png" + }, + { + "icon": "spellbook_05.png", + "source": "a24_spellbook-genxlc0_s07_0.png" + }, + { + "icon": "spellbook_06.png", + "source": "a24_spellbook-genxlc0_s07_3.png" + }, + { + "icon": "throwing_01.png", + "source": "a13l_throwing-draw0_s07_0.png" + }, + { + "icon": "throwing_02.png", + "source": "a13l_throwing-draw0_s07_1.png" + }, + { + "icon": "throwing_03.png", + "source": "a13l_throwing-draw1_s07_1.png" + }, + { + "icon": "throwing_04.png", + "source": "a13l_throwing-draw1_s07_2.png" + }, + { + "icon": "throwing_05.png", + "source": "a17_throwing-draw0_s07_0.png" + }, + { + "icon": "throwing_06.png", + "source": "a17_throwing-draw1_s07_0.png" + }, + { + "icon": "orb_01.png", + "source": "a13t_orb_s07_0.png" + }, + { + "icon": "orb_02.png", + "source": "a13t_orb_s07_1.png" + }, + { + "icon": "orb_03.png", + "source": "a17_orb-genmoba1_s07_0.png" + }, + { + "icon": "orb_04.png", + "source": "a17_orb-genmoba1_s07_1.png" + }, + { + "icon": "orb_05.png", + "source": "a24_orb-genmoba1_s07_0.png" + }, + { + "icon": "orb_06.png", + "source": "a24_orb-genmoba1_s07_1.png" + }, + { + "icon": "totem_01.png", + "source": "a14_totem-draw3_s07_1.png" + }, + { + "icon": "totem_02.png", + "source": "a17_totem-draw3_s07_0.png" + }, + { + "icon": "totem_03.png", + "source": "a17_totem-draw3_s07_1.png" + }, + { + "icon": "totem_04.png", + "source": "a24_totem-draw3_s07_0.png" + }, + { + "icon": "totem_05.png", + "source": "a24_totem-draw3_s07_1.png" + }, + { + "icon": "horn_01.png", + "source": "a17_horn-draw2_s07_1.png" + }, + { + "icon": "horn_02.png", + "source": "a24_horn-draw2_s07_0.png" + }, + { + "icon": "horn_03.png", + "source": "a24_horn-draw2_s07_2.png" + } +] \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/guides_a20.json b/공유/기획/FirstRising/아이템/moba_anfg/guides_a20.json new file mode 100644 index 0000000..acb8daf --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/guides_a20.json @@ -0,0 +1,10 @@ +{ + "axe": ["xl_axe_01.png", "xl_axe_10.png"], + "dagger": ["xl_dagger_04.png"], + "horn": ["xl_horn_02.png"], + "bow": ["xl_bow_01_x.png", "xl_bow_05_x.png", "xl_bow_11_x.png"], + "staff": ["xl_staff_04.png", "xl_staff_05.png", "xl_staff_03_x.png"], + "hammer": ["xl_hammer_03.png", "xl_hammer_07.png"], + "belt": ["xl_belt_07.png", "xl_belt_05.png", "xl_belt_02.png"], + "gloves": [] +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/guides_a21.json b/공유/기획/FirstRising/아이템/moba_anfg/guides_a21.json new file mode 100644 index 0000000..eee6cde --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/guides_a21.json @@ -0,0 +1,24 @@ +{ + "gloves": [ + "xl_gloves_08.png" + ], + "horn": [ + "xl_horn_08.png", + "xl_horn_05.png" + ], + "dagger": [ + "xl_dagger_04.png" + ], + "spellbook": [ + "xl_spellbook_01.png", + "xl_spellbook_04.png", + "xl_spellbook_07_x.png" + ], + "totem": [ + "xl_totem_03.png", + "xl_totem_00.png" + ], + "necklace": [ + "xl_necklace_07.png" + ] +} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/guides_a21_use.json b/공유/기획/FirstRising/아이템/moba_anfg/guides_a21_use.json new file mode 100644 index 0000000..26a88cc --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/guides_a21_use.json @@ -0,0 +1 @@ +{"gloves": [], "horn": ["xl_horn_08.png", "xl_horn_05.png"], "dagger": ["xl_dagger_04.png"], "spellbook": ["xl_spellbook_01.png", "xl_spellbook_04.png", "xl_spellbook_07_x.png"], "totem": ["xl_totem_03.png", "xl_totem_00.png"], "necklace": ["xl_necklace_07.png"]} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/guides_a23.json b/공유/기획/FirstRising/아이템/moba_anfg/guides_a23.json new file mode 100644 index 0000000..45bb4ce --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/guides_a23.json @@ -0,0 +1,9 @@ +{ + "ring": ["xl_ring_01.png", "xl_ring_03.png", "xl_ring_06.png", "xl_ring_08.png"], + "helmet": ["xl_helmet_00.png", "xl_helmet_02.png", "xl_helmet_04.png", "xl_helmet_06.png"], + "sword": ["xl_sword_06.png", "xl_sword_08.png"], + "shield": ["xl_shield_00.png", "xl_shield_05.png", "xl_shield_07.png", "xl_shield_08.png"], + "quiver": ["xl_quiver_03.png", "xl_quiver_04.png", "xl_quiver_05.png", "xl_quiver_06.png"], + "axe": ["xl_axe_11.png", "xl_axe_05.png", "xl_axe_02.png"], + "hammer": ["xl_hammer_03.png", "xl_hammer_05.png", "xl_hammer_06.png", "xl_hammer_07.png"] +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a10.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a10.json new file mode 100644 index 0000000..3365c84 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a10.json @@ -0,0 +1,8 @@ +{ + "a10_bow-draw2_s07_1": "a10_bow-draw2_s07_1.png", + "a10_dagger-draw0_s07_1": "a10_dagger-draw0_s07_1.png", + "a10_hammer-draw0_s07_0": "a10_hammer-draw0_s07_0.png", + "a10_horn-draw2_s07_0": "a10_horn-draw2_s07_0.png", + "a10_ring-draw0_s07_1": "a10_ring-draw0_s07_1.png", + "a10_shield-draw0_s07_1": "a10_shield-draw0_s07_1.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a11.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a11.json new file mode 100644 index 0000000..3c59520 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a11.json @@ -0,0 +1,33 @@ +{ + "a11l_armor-fr1253_0": "a11l_armor-fr1253_s07_0.png", + "a11l_armor-fr1253_1": "a11l_armor-fr1253_s07_1.png", + "a11l_armor-fr1281_1": "a11l_armor-fr1281_s07_1.png", + "a11l_armor-fr1267_1": "a11l_armor-fr1267_s07_1.png", + "a11l_belt-fr1351_0": "a11l_belt-fr1351_s07_0.png", + "a11l_blunt-fr1057_1": "a11l_blunt-fr1057_s07_1.png", + "a11l_boots-fr1393_0": "a11l_boots-fr1393_s07_0.png", + "a11l_boots-fr1407_1": "a11l_boots-fr1407_s07_1.png", + "a11l_boots-fr1421_1": "a11l_boots-fr1421_s07_1.png", + "a11l_gloves-fr1183_0": "a11l_gloves-fr1183_s07_0.png", + "a11l_gloves-fr1211_0": "a11l_gloves-fr1211_s07_0.png", + "a11l_hammer-draw0_0": "a11l_hammer-draw0_s07_0.png", + "a11l_helmet-draw0_0": "a11l_helmet-draw0_s07_0.png", + "a11l_helmet-draw0_1": "a11l_helmet-draw0_s07_1.png", + "a11l_helmet-draw1_1": "a11l_helmet-draw1_s07_1.png", + "a11l_horn-draw2_1": "a11l_horn-draw2_s07_1.png", + "a11l_necklace-fr1099_1": "a11l_necklace-fr1099_s07_1.png", + "a11l_necklace-fr1113_1": "a11l_necklace-fr1113_s07_1.png", + "a11l_necklace-fr1127_0": "a11l_necklace-fr1127_s07_0.png", + "a11l_necklace-fr1127_1": "a11l_necklace-fr1127_s07_1.png", + "a11l_necklace-fr1141_1": "a11l_necklace-fr1141_s07_1.png", + "a11l_orb-draw2_1": "a11l_orb-draw2_s07_1.png", + "a11l_quiver-draw2_1": "a11l_quiver-draw2_s07_1.png", + "a11l_ring-genpd1ring_1": "a11l_ring-genpd1ring_s07_1.png", + "a11l_shield-genpd2shield_1": "a11l_shield-genpd2shield_s07_1.png", + "a11l_spellbook-llbook1_1": "a11l_spellbook-llbook1_s07_1.png", + "a11l_staff-draw1_0": "a11l_staff-draw1_s07_0.png", + "a11l_sword-genpd2sword_1": "a11l_sword-genpd2sword_s07_1.png", + "a11l_throwing-draw1_1": "a11l_throwing-draw1_s07_1.png", + "a11l_totem-draw3_0": "a11l_totem-draw3_s07_0.png", + "a11l_totem-draw3_1": "a11l_totem-draw3_s07_1.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a12.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a12.json new file mode 100644 index 0000000..cf13c70 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a12.json @@ -0,0 +1,28 @@ +{ + "a12t_dagger_0": "a12t_dagger_s07_0.png", + "a12t_armor_1": "a12t_armor_s07_1.png", + "a12t_gloves_0": "a12t_gloves_s07_0.png", + "a12t_gloves_1": "a12t_gloves_s07_1.png", + "a12t_boots_0": "a12t_boots_s07_0.png", + "a12t_shield_0": "a12t_shield_s07_0.png", + "a12t_orb_1": "a12t_orb_s07_1.png", + "a12t_throwing_0": "a12t_throwing_s07_0.png", + "a12l_blunt-fr1057_0": "a12l_blunt-fr1057_s07_0.png", + "a12l_blunt-fr1057_2": "a12l_blunt-fr1057_s07_2.png", + "a12l_dagger-genpd2dagger_1": "a12l_dagger-genpd2dagger_s07_1.png", + "a12l_dagger-genpd2magicdagger_2": "a12l_dagger-genpd2magicdagger_s07_2.png", + "a12l_hammer-draw0_0": "a12l_hammer-draw0_s07_0.png", + "a12l_hammer-draw0_1": "a12l_hammer-draw0_s07_1.png", + "a12l_horn-draw2_1": "a12l_horn-draw2_s07_1.png", + "a12l_quiver-draw2_1": "a12l_quiver-draw2_s07_1.png", + "a12l_ring-genpd1ring_0": "a12l_ring-genpd1ring_s07_0.png", + "a12l_shield-draw0_0": "a12l_shield-draw0_s07_0.png", + "a12l_shield-genpd2shield_0": "a12l_shield-genpd2shield_s07_0.png", + "a12l_spellbook-llbook1_1": "a12l_spellbook-llbook1_s07_1.png", + "a12l_staff-draw1_0": "a12l_staff-draw1_s07_0.png", + "a12l_staff-draw1_2": "a12l_staff-draw1_s07_2.png", + "a12l_sword-genpd2sword_0": "a12l_sword-genpd2sword_s07_0.png", + "a12l_throwing-draw0_0": "a12l_throwing-draw0_s07_0.png", + "a12l_throwing-draw1_0": "a12l_throwing-draw1_s07_0.png", + "a12l_throwing-draw1_1": "a12l_throwing-draw1_s07_1.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a13.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a13.json new file mode 100644 index 0000000..6ad6ec1 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a13.json @@ -0,0 +1,20 @@ +{ + "a13l_blunt-fr1057_0": "a13l_blunt-fr1057_s07_0.png", + "a13l_blunt-fr1057_1": "a13l_blunt-fr1057_s07_1.png", + "a13l_bow-draw2_1": "a13l_bow-draw2_s07_1.png", + "a13l_hammer-draw0_0": "a13l_hammer-draw0_s07_0.png", + "a13l_staff-draw0_0": "a13l_staff-draw0_s07_0.png", + "a13l_staff-draw0_1": "a13l_staff-draw0_s07_1.png", + "a13l_staff-draw1_1": "a13l_staff-draw1_s07_1.png", + "a13l_staff-draw1_2": "a13l_staff-draw1_s07_2.png", + "a13l_sword-draw2_1": "a13l_sword-draw2_s07_1.png", + "a13l_sword-genpd2sword_1": "a13l_sword-genpd2sword_s07_1.png", + "a13l_throwing-draw0_0": "a13l_throwing-draw0_s07_0.png", + "a13l_throwing-draw0_1": "a13l_throwing-draw0_s07_1.png", + "a13l_throwing-draw1_1": "a13l_throwing-draw1_s07_1.png", + "a13l_throwing-draw1_2": "a13l_throwing-draw1_s07_2.png", + "a13t_armor_0": "a13t_armor_s07_0.png", + "a13t_boots_1": "a13t_boots_s07_1.png", + "a13t_orb_0": "a13t_orb_s07_0.png", + "a13t_orb_1": "a13t_orb_s07_1.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a14.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a14.json new file mode 100644 index 0000000..082c2f3 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a14.json @@ -0,0 +1,26 @@ +{ + "a14_armor-fr1253_1": "a14_armor-fr1253_s07_1.png", + "a14_armor-fr1267_0": "a14_armor-fr1267_s07_0.png", + "a14_armor-fr1267_1": "a14_armor-fr1267_s07_1.png", + "a14_armor-fr1281_0": "a14_armor-fr1281_s07_0.png", + "a14_armor-fr1281_1": "a14_armor-fr1281_s07_1.png", + "a14_belt-fr1351_0": "a14_belt-fr1351_s07_0.png", + "a14_belt-fr1351_1": "a14_belt-fr1351_s07_1.png", + "a14_boots-fr1379_0": "a14_boots-fr1379_s07_0.png", + "a14_boots-fr1379_1": "a14_boots-fr1379_s07_1.png", + "a14_boots-fr1393_0": "a14_boots-fr1393_s07_0.png", + "a14_boots-fr1407_0": "a14_boots-fr1407_s07_0.png", + "a14_boots-fr1421_0": "a14_boots-fr1421_s07_0.png", + "a14_gloves-fr1169_1": "a14_gloves-fr1169_s07_1.png", + "a14_gloves-fr1197_1": "a14_gloves-fr1197_s07_1.png", + "a14_necklace-fr1099_0": "a14_necklace-fr1099_s07_0.png", + "a14_necklace-fr1099_1": "a14_necklace-fr1099_s07_1.png", + "a14_necklace-fr1113_1": "a14_necklace-fr1113_s07_1.png", + "a14_necklace-fr1127_0": "a14_necklace-fr1127_s07_0.png", + "a14_necklace-fr1141_0": "a14_necklace-fr1141_s07_0.png", + "a14_quiver-draw2_1": "a14_quiver-draw2_s07_1.png", + "a14_shield-draw0_0": "a14_shield-draw0_s07_0.png", + "a14_shield-genpd2shield_1": "a14_shield-genpd2shield_s07_1.png", + "a14_spellbook-llbook1_0": "a14_spellbook-llbook1_s07_0.png", + "a14_totem-draw3_1": "a14_totem-draw3_s07_1.png" +} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a15.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a15.json new file mode 100644 index 0000000..d1502a0 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a15.json @@ -0,0 +1,7 @@ +{ + "a15_hammer-draw2_2": "a15_hammer-draw2_s07_2.png", + "a15_hammer-draw2_3": "a15_hammer-draw2_s07_3.png", + "a15_bow-draw3_3": "a15_bow-draw3_s07_3.png", + "a15_dagger-draw3_1": "a15_dagger-draw3_s07_1.png", + "a15_sword-draw2_2": "a15_sword-draw2_s07_2.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a16.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a16.json new file mode 100644 index 0000000..d64ac60 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a16.json @@ -0,0 +1,10 @@ +{ + "a16b_armor-fr1267_1": "a16b_armor-fr1267_s07_1.png", + "a16d_blunt-fr1057_0": "a16d_blunt-fr1057_s08_0.png", + "a16b_blunt-fr1057_1": "a16b_blunt-fr1057_s07_1.png", + "a16d_boots-fr1379_0": "a16d_boots-fr1379_s08_0.png", + "a16d_boots-fr1379_1": "a16d_boots-fr1379_s08_1.png", + "a16b_necklace-fr1099_0": "a16b_necklace-fr1099_s07_0.png", + "a16d_shield-draw0_1": "a16d_shield-draw0_s08_1.png", + "a16b_staff-draw1_0": "a16b_staff-draw1_s07_0.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a17.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a17.json new file mode 100644 index 0000000..5d3df1a --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a17.json @@ -0,0 +1,40 @@ +{ + "a17_armor-fr1253_0": "a17_armor-fr1253_s07_0.png", + "a17_armor-fr1253_1": "a17_armor-fr1253_s07_1.png", + "a17_armor-fr1267_0": "a17_armor-fr1267_s07_0.png", + "a17_armor-fr1267_1": "a17_armor-fr1267_s07_1.png", + "a17_armor-fr1281_0": "a17_armor-fr1281_s07_0.png", + "a17_armor-fr1281_1": "a17_armor-fr1281_s07_1.png", + "a17_axe-genmoba0_0": "a17_axe-genmoba0_s07_0.png", + "a17_belt-fr1351_1": "a17_belt-fr1351_s07_1.png", + "a17_blunt-fr1057_0": "a17_blunt-fr1057_s07_0.png", + "a17_blunt-fr1057_1": "a17_blunt-fr1057_s07_1.png", + "a17_boots-fr1379_0": "a17_boots-fr1379_s07_0.png", + "a17_boots-fr1379_1": "a17_boots-fr1379_s07_1.png", + "a17_boots-fr1393_0": "a17_boots-fr1393_s07_0.png", + "a17_boots-fr1407_1": "a17_boots-fr1407_s07_1.png", + "a17_boots-fr1421_0": "a17_boots-fr1421_s07_0.png", + "a17_bow-draw3_1": "a17_bow-draw3_s07_1.png", + "a17_gloves-fr1183_0": "a17_gloves-fr1183_s07_0.png", + "a17_gloves-fr1183_1": "a17_gloves-fr1183_s07_1.png", + "a17_gloves-fr1197_0": "a17_gloves-fr1197_s07_0.png", + "a17_gloves-fr1211_0": "a17_gloves-fr1211_s07_0.png", + "a17_gloves-fr1211_1": "a17_gloves-fr1211_s07_1.png", + "a17_hammer-draw2_1": "a17_hammer-draw2_s07_1.png", + "a17_helmet-genmoba0_0": "a17_helmet-genmoba0_s07_0.png", + "a17_horn-draw2_1": "a17_horn-draw2_s07_1.png", + "a17_necklace-fr1099_0": "a17_necklace-fr1099_s07_0.png", + "a17_necklace-fr1113_1": "a17_necklace-fr1113_s07_1.png", + "a17_necklace-fr1127_0": "a17_necklace-fr1127_s07_0.png", + "a17_necklace-fr1127_1": "a17_necklace-fr1127_s07_1.png", + "a17_orb-genmoba1_0": "a17_orb-genmoba1_s07_0.png", + "a17_orb-genmoba1_1": "a17_orb-genmoba1_s07_1.png", + "a17_spellbook-llbook1_1": "a17_spellbook-llbook1_s07_1.png", + "a17_staff-draw0_0": "a17_staff-draw0_s07_0.png", + "a17_staff-draw1_0": "a17_staff-draw1_s07_0.png", + "a17_staff-draw1_1": "a17_staff-draw1_s07_1.png", + "a17_throwing-draw0_0": "a17_throwing-draw0_s07_0.png", + "a17_throwing-draw1_0": "a17_throwing-draw1_s07_0.png", + "a17_totem-draw3_0": "a17_totem-draw3_s07_0.png", + "a17_totem-draw3_1": "a17_totem-draw3_s07_1.png" +} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a18.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a18.json new file mode 100644 index 0000000..681d446 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a18.json @@ -0,0 +1,13 @@ +{ + "a18l_belt-fr1351_0": "a18l_belt-fr1351_s07_0.png", + "a18l_belt-fr1351_1": "a18l_belt-fr1351_s07_1.png", + "a18l_bow-draw3_0": "a18l_bow-draw3_s07_0.png", + "a18l_hammer-draw2_0": "a18l_hammer-draw2_s07_0.png", + "a18l_hammer-draw2_1": "a18l_hammer-draw2_s07_1.png", + "a18l_helmet-draw0_1": "a18l_helmet-draw0_s07_1.png", + "a18l_horn-draw2_0": "a18l_horn-draw2_s07_0.png", + "a18l_quiver-draw2_0": "a18l_quiver-draw2_s07_0.png", + "a18l_quiver-draw2_1": "a18l_quiver-draw2_s07_1.png", + "a18l_shield-draw0_1": "a18l_shield-draw0_s07_1.png", + "a18l_spellbook-llbook1_0": "a18l_spellbook-llbook1_s07_0.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a19.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a19.json new file mode 100644 index 0000000..ac51edc --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a19.json @@ -0,0 +1,11 @@ +{ + "a19_sword-genxl1_0": "a19_sword-genxl1_s07_0.png", + "a19_sword-genxl1_1": "a19_sword-genxl1_s07_1.png", + "a19_ring-genxl0_1": "a19_ring-genxl0_s07_1.png", + "a19_ring-genxl1_0": "a19_ring-genxl1_s07_0.png", + "a19_quiver-genxl1_0": "a19_quiver-genxl1_s07_0.png", + "a19_quiver-genxl1_1": "a19_quiver-genxl1_s07_1.png", + "a19_shield-genxl1_0": "a19_shield-genxl1_s07_0.png", + "a19_shield-genxl1_1": "a19_shield-genxl1_s07_1.png", + "a19_helmet-genxl1_0": "a19_helmet-genxl1_s07_0.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a2.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a2.json new file mode 100644 index 0000000..e176817 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a2.json @@ -0,0 +1,33 @@ +{ + "sword_a": "a2_sword_s07_0.png", + "sword_b": "a2_sword_s07_1.png", + "sword_c": "a2_sword_s07_3.png", + "dagger_a": "a2_dagger_s07_0.png", + "dagger_b": "a2_dagger_s07_1.png", + "dagger_c": "a2_dagger_s07_3.png", + "magicdagger_a": "a2_magic_dagger_s07_1.png", + "magicdagger_b": "a2_magic_dagger_s07_3.png", + "staff_a": "a2_staff_s07_2.png", + "armor_a": "a2_armor_s07_1.png", + "armor_b": "a2_armor_s07_3.png", + "belt_a": "a2_belt_s07_3.png", + "gloves_a": "a2_gloves_s07_1.png", + "gloves_b": "a2_gloves_s07_2.png", + "boots_a": "a2_boots_s07_0.png", + "boots_b": "a2_boots_s07_2.png", + "boots_c": "a2_boots_s07_3.png", + "ring_a": "a2_ring_s07_0.png", + "ring_b": "a2_ring_s07_1.png", + "ring_c": "a2_ring_s07_2.png", + "necklace_a": "a2_necklace_s07_2.png", + "shield_a": "a2_shield_s07_0.png", + "shield_b": "a2_shield_s07_1.png", + "throwing_a": "a2_throwing_s07_3.png", + "orb_a": "a2_orb_s07_0.png", + "orb_b": "a2_orb_s07_2.png", + "orb_c": "a2_orb_s07_3.png", + "totem_a": "a2_totem_s07_0.png", + "totem_b": "a2_totem_s07_2.png", + "horn_a": "a2_horn_s07_0.png", + "horn_b": "a2_horn_s07_3.png" +} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a20.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a20.json new file mode 100644 index 0000000..d188f01 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a20.json @@ -0,0 +1,12 @@ +{ + "a20_dagger-genxlb0_0": "a20_dagger-genxlb0_s07_0.png", + "a20_dagger-genxlb0_1": "a20_dagger-genxlb0_s07_1.png", + "a20_bow-genxlb0_1": "a20_bow-genxlb0_s07_1.png", + "a20_belt-genxlb0_1": "a20_belt-genxlb0_s07_1.png", + "a20_belt-genxlb1_0": "a20_belt-genxlb1_s07_0.png", + "a20_belt-genxlb1_2": "a20_belt-genxlb1_s07_2.png", + "a20_staff-genxlb0_0": "a20_staff-genxlb0_s07_0.png", + "a20_staff-genxlb0_1": "a20_staff-genxlb0_s07_1.png", + "a20_staff-genxlb0_2": "a20_staff-genxlb0_s07_2.png", + "a20_staff-genxlb1_2": "a20_staff-genxlb1_s07_2.png" +} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a21.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a21.json new file mode 100644 index 0000000..8f57ea4 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a21.json @@ -0,0 +1,7 @@ +{ + "a21_necklace-genxlc0_0": "a21_necklace-genxlc0_s07_0.png", + "a21_necklace-genxlc0_1": "a21_necklace-genxlc0_s07_1.png", + "a21_necklace-genxlc0_2": "a21_necklace-genxlc0_s07_2.png", + "a21_spellbook-genxlc0_0": "a21_spellbook-genxlc0_s07_0.png", + "a21_spellbook-genxlc0_2": "a21_spellbook-genxlc0_s07_2.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a23.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a23.json new file mode 100644 index 0000000..ecbe259 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a23.json @@ -0,0 +1,22 @@ +{ + "a23_axe-genxld1_1": "a23_axe-genxld1_s07_1.png", + "a23_hammer-genxld0_1": "a23_hammer-genxld0_s07_1.png", + "a23_hammer-genxld0_2": "a23_hammer-genxld0_s07_2.png", + "a23_hammer-genxld1_2": "a23_hammer-genxld1_s07_2.png", + "a23_helmet-genxld2_0": "a23_helmet-genxld2_s07_0.png", + "a23_helmet-genxld2_1": "a23_helmet-genxld2_s07_1.png", + "a23_helmet-genxld3_2": "a23_helmet-genxld3_s07_2.png", + "a23_quiver-genxld1_0": "a23_quiver-genxld1_s07_0.png", + "a23_quiver-genxld2_0": "a23_quiver-genxld2_s07_0.png", + "a23_quiver-genxld2_2": "a23_quiver-genxld2_s07_2.png", + "a23_ring-genxld0_0": "a23_ring-genxld0_s07_0.png", + "a23_ring-genxld0_1": "a23_ring-genxld0_s07_1.png", + "a23_ring-genxld1_0": "a23_ring-genxld1_s07_0.png", + "a23_ring-genxld2_0": "a23_ring-genxld2_s07_0.png", + "a23_ring-genxld3_0": "a23_ring-genxld3_s07_0.png", + "a23_ring-genxld3_1": "a23_ring-genxld3_s07_1.png", + "a23_shield-genxld0_2": "a23_shield-genxld0_s07_2.png", + "a23_shield-genxld3_0": "a23_shield-genxld3_s07_0.png", + "a23_shield-genxld3_2": "a23_shield-genxld3_s07_2.png", + "a23_sword-genxld0_1": "a23_sword-genxld0_s07_1.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a24.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a24.json new file mode 100644 index 0000000..7bc07c7 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a24.json @@ -0,0 +1,31 @@ +{ + "a24_axe-genxld1_0": "a24_axe-genxld1_s07_0.png", + "a24_axe-genxld1_3": "a24_axe-genxld1_s07_3.png", + "a24_bow-genxlb0_1": "a24_bow-genxlb0_s07_1.png", + "a24_dagger-genxlb0_2": "a24_dagger-genxlb0_s07_2.png", + "a24_dagger-genxlb0_3": "a24_dagger-genxlb0_s07_3.png", + "a24_hammer-genxld0_1": "a24_hammer-genxld0_s07_1.png", + "a24_hammer-genxld0_3": "a24_hammer-genxld0_s07_3.png", + "a24_hammer-genxld1_0": "a24_hammer-genxld1_s07_0.png", + "a24_hammer-genxld1_3": "a24_hammer-genxld1_s07_3.png", + "a24_helmet-genxld2_0": "a24_helmet-genxld2_s07_0.png", + "a24_helmet-genxld2_1": "a24_helmet-genxld2_s07_1.png", + "a24_helmet-genxld2_3": "a24_helmet-genxld2_s07_3.png", + "a24_helmet-genxld3_0": "a24_helmet-genxld3_s07_0.png", + "a24_helmet-genxld3_1": "a24_helmet-genxld3_s07_1.png", + "a24_horn-draw2_0": "a24_horn-draw2_s07_0.png", + "a24_horn-draw2_2": "a24_horn-draw2_s07_2.png", + "a24_orb-genmoba1_0": "a24_orb-genmoba1_s07_0.png", + "a24_orb-genmoba1_1": "a24_orb-genmoba1_s07_1.png", + "a24_quiver-genxld2_2": "a24_quiver-genxld2_s07_2.png", + "a24_shield-genxl1_2": "a24_shield-genxl1_s07_2.png", + "a24_shield-genxld3_0": "a24_shield-genxld3_s07_0.png", + "a24_shield-genxld3_1": "a24_shield-genxld3_s07_1.png", + "a24_shield-genxld3_2": "a24_shield-genxld3_s07_2.png", + "a24_spellbook-genxlc0_0": "a24_spellbook-genxlc0_s07_0.png", + "a24_spellbook-genxlc0_3": "a24_spellbook-genxlc0_s07_3.png", + "a24_sword-genxl1_0": "a24_sword-genxl1_s07_0.png", + "a24_sword-genxl1_1": "a24_sword-genxl1_s07_1.png", + "a24_totem-draw3_0": "a24_totem-draw3_s07_0.png", + "a24_totem-draw3_1": "a24_totem-draw3_s07_1.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a26.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a26.json new file mode 100644 index 0000000..3c7d10f --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a26.json @@ -0,0 +1,55 @@ +{ + "a26_armor-fr1253_0": "a26_armor-fr1253_s07_0.png", + "a26_armor-fr1253_1": "a26_armor-fr1253_s07_1.png", + "a26_armor-fr1267_1": "a26_armor-fr1267_s07_1.png", + "a26_armor-fr1281_2": "a26_armor-fr1281_s07_2.png", + "a26_belt-fr1351_0": "a26_belt-fr1351_s07_0.png", + "a26_belt-fr1351_1": "a26_belt-fr1351_s07_1.png", + "a26_belt-genxlb0_1": "a26_belt-genxlb0_s07_1.png", + "a26_belt-genxlb0_2": "a26_belt-genxlb0_s07_2.png", + "a26_blunt-fr1057_0": "a26_blunt-fr1057_s07_0.png", + "a26_blunt-fr1057_2": "a26_blunt-fr1057_s07_2.png", + "a26_boots-fr1393_0": "a26_boots-fr1393_s07_0.png", + "a26_boots-fr1393_2": "a26_boots-fr1393_s07_2.png", + "a26_boots-fr1407_1": "a26_boots-fr1407_s07_1.png", + "a26_boots-fr1407_2": "a26_boots-fr1407_s07_2.png", + "a26_gloves-fr1183_0": "a26_gloves-fr1183_s07_0.png", + "a26_gloves-fr1197_0": "a26_gloves-fr1197_s07_0.png", + "a26_gloves-fr1197_1": "a26_gloves-fr1197_s07_1.png", + "a26_helmet-genmoba0_1": "a26_helmet-genmoba0_s07_1.png", + "a26_helmet-genxld3_2": "a26_helmet-genxld3_s07_2.png", + "a26_horn-draw2_0": "a26_horn-draw2_s07_0.png", + "a26_horn-draw2_2": "a26_horn-draw2_s07_2.png", + "a26_necklace-fr1099_0": "a26_necklace-fr1099_s07_0.png", + "a26_necklace-fr1113_1": "a26_necklace-fr1113_s07_1.png", + "a26_necklace-fr1127_1": "a26_necklace-fr1127_s07_1.png", + "a26_necklace-fr1127_2": "a26_necklace-fr1127_s07_2.png", + "a26_necklace-genxlc0_1": "a26_necklace-genxlc0_s07_1.png", + "a26_shield-draw0_0": "a26_shield-draw0_s07_0.png", + "a26_shield-genxl1_2": "a26_shield-genxl1_s07_2.png", + "a26_shield-genxld3_0": "a26_shield-genxld3_s07_0.png", + "a26_shield-genxld3_1": "a26_shield-genxld3_s07_1.png", + "a26_staff-draw1_2": "a26_staff-draw1_s07_2.png", + "a26_staff-genxlb0_0": "a26_staff-genxlb0_s07_0.png", + "a26_staff-genxlb0_1": "a26_staff-genxlb0_s07_1.png", + "a26_throwing-draw0_1": "a26_throwing-draw0_s07_1.png", + "a26_totem-draw3_0": "a26_totem-draw3_s07_0.png", + "a26_dagger-genxlb0_2": "a26_dagger-genxlb0_s07_2.png", + "a26_bow-genxlb0_1": "a26_bow-genxlb0_s07_1.png", + "a26_bow-genxlb0_2": "a26_bow-genxlb0_s07_2.png", + "a26_spellbook-genxlc0_0": "a26_spellbook-genxlc0_s07_0.png", + "a26_spellbook-genxlc0_2": "a26_spellbook-genxlc0_s07_2.png", + "a26_axe-genxld1_0": "a26_axe-genxld1_s07_0.png", + "a26_axe-genxld1_2": "a26_axe-genxld1_s07_2.png", + "a26_hammer-genxld0_1": "a26_hammer-genxld0_s07_1.png", + "a26_hammer-genxld0_2": "a26_hammer-genxld0_s07_2.png", + "a26_hammer-genxld1_0": "a26_hammer-genxld1_s07_0.png", + "a26_hammer-genxld1_1": "a26_hammer-genxld1_s07_1.png", + "a26_quiver-genxld2_1": "a26_quiver-genxld2_s07_1.png", + "a26_ring-genxld0_0": "a26_ring-genxld0_s07_0.png", + "a26_ring-genxld0_1": "a26_ring-genxld0_s07_1.png", + "a26_ring-genxld0_2": "a26_ring-genxld0_s07_2.png", + "a26_ring-genxld2_0": "a26_ring-genxld2_s07_0.png", + "a26_ring-genxld2_2": "a26_ring-genxld2_s07_2.png", + "a26_ring-genxld3_1": "a26_ring-genxld3_s07_1.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a27.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a27.json new file mode 100644 index 0000000..d4c2316 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a27.json @@ -0,0 +1,48 @@ +{ + "a27_armor-fr1253_1": "a27_armor-fr1253_s07_1.png", + "a27_armor-fr1267_0": "a27_armor-fr1267_s07_0.png", + "a27_armor-fr1267_1": "a27_armor-fr1267_s07_1.png", + "a27_armor-fr1281_0": "a27_armor-fr1281_s07_0.png", + "a27_armor-fr1281_1": "a27_armor-fr1281_s07_1.png", + "a27_belt-fr1351_0": "a27_belt-fr1351_s07_0.png", + "a27_blunt-fr1057_0": "a27_blunt-fr1057_s07_0.png", + "a27_boots-fr1379_1": "a27_boots-fr1379_s07_1.png", + "a27_boots-fr1393_0": "a27_boots-fr1393_s07_0.png", + "a27_boots-fr1393_1": "a27_boots-fr1393_s07_1.png", + "a27_boots-fr1407_0": "a27_boots-fr1407_s07_0.png", + "a27_boots-fr1407_1": "a27_boots-fr1407_s07_1.png", + "a27_gloves-fr1197_1": "a27_gloves-fr1197_s07_1.png", + "a27_horn-draw2_0": "a27_horn-draw2_s07_0.png", + "a27_necklace-fr1099_0": "a27_necklace-fr1099_s07_0.png", + "a27_necklace-fr1113_0": "a27_necklace-fr1113_s07_0.png", + "a27_necklace-fr1113_1": "a27_necklace-fr1113_s07_1.png", + "a27_necklace-fr1127_1": "a27_necklace-fr1127_s07_1.png", + "a27_orb-genmoba1_0": "a27_orb-genmoba1_s07_0.png", + "a27_shield-draw0_1": "a27_shield-draw0_s07_1.png", + "a27_staff-draw1_0": "a27_staff-draw1_s07_0.png", + "a27_throwing-draw0_0": "a27_throwing-draw0_s07_0.png", + "a27_totem-draw3_0": "a27_totem-draw3_s07_0.png", + "a27_totem-draw3_1": "a27_totem-draw3_s07_1.png", + "a27_sword-genxl1_1": "a27_sword-genxl1_s07_1.png", + "a27_belt-genxlb1_0": "a27_belt-genxlb1_s07_0.png", + "a27_bow-genxlb0_0": "a27_bow-genxlb0_s07_0.png", + "a27_bow-genxlb0_1": "a27_bow-genxlb0_s07_1.png", + "a27_dagger-genxlb0_0": "a27_dagger-genxlb0_s07_0.png", + "a27_dagger-genxlb0_1": "a27_dagger-genxlb0_s07_1.png", + "a27_necklace-genxlc0_1": "a27_necklace-genxlc0_s07_1.png", + "a27_spellbook-genxlc0_0": "a27_spellbook-genxlc0_s07_0.png", + "a27_axe-genxld1_0": "a27_axe-genxld1_s07_0.png", + "a27_hammer-genxld0_1": "a27_hammer-genxld0_s07_1.png", + "a27_hammer-genxld1_0": "a27_hammer-genxld1_s07_0.png", + "a27_hammer-genxld1_1": "a27_hammer-genxld1_s07_1.png", + "a27_helmet-genxld3_0": "a27_helmet-genxld3_s07_0.png", + "a27_quiver-genxld2_0": "a27_quiver-genxld2_s07_0.png", + "a27_ring-genxld0_0": "a27_ring-genxld0_s07_0.png", + "a27_ring-genxld1_1": "a27_ring-genxld1_s07_1.png", + "a27_ring-genxld2_0": "a27_ring-genxld2_s07_0.png", + "a27_ring-genxld2_1": "a27_ring-genxld2_s07_1.png", + "a27_ring-genxld3_0": "a27_ring-genxld3_s07_0.png", + "a27_ring-genxld3_1": "a27_ring-genxld3_s07_1.png", + "a27_shield-genxld3_0": "a27_shield-genxld3_s07_0.png", + "a27_shield-genxld3_1": "a27_shield-genxld3_s07_1.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a4.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a4.json new file mode 100644 index 0000000..15540b9 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a4.json @@ -0,0 +1 @@ +{"a4_helmet_x":"a4_helmet_s08_0.png","a4_armor_x":"a4_armor_s10_0.png"} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a5.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a5.json new file mode 100644 index 0000000..a329c3a --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a5.json @@ -0,0 +1,14 @@ +{ + "a5n_sword_1": "a5n_sword_s07_1.png", + "a5n_dagger_1": "a5n_dagger_s07_1.png", + "a5n_armor_0": "a5n_armor_s07_0.png", + "a5n_armor_1": "a5n_armor_s07_1.png", + "a5n_ring_0": "a5n_ring_s07_0.png", + "a5n_boots_1": "a5n_boots_s07_1.png", + "a5v_sword_0": "a5v_sword_s07_0.png", + "a5v_sword_1": "a5v_sword_s07_1.png", + "a5v_dagger_1": "a5v_dagger_s07_1.png", + "a5v_magic_dagger_1": "a5v_magic_dagger_s07_1.png", + "a5v_armor_0": "a5v_armor_s07_0.png", + "a5v_boots_1": "a5v_boots_s07_1.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a6.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a6.json new file mode 100644 index 0000000..ef164bb --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a6.json @@ -0,0 +1 @@ +{"a6s_blunt_0":"a6s_blunt_s07_0.png","a6s_hammer_0":"a6s_hammer_s07_0.png","a6s_bow_0":"a6s_bow_s07_0.png","a6s_belt_0":"a6s_belt_s07_0.png","a6s_belt_1":"a6s_belt_s07_1.png","a6d_gloves_0":"a6d_gloves_s07_0.png","a6d_ring_1":"a6d_ring_s07_1.png","a6d_shield_0":"a6d_shield_s07_0.png","a6d_shield_1":"a6d_shield_s07_1.png","a6d_offhand_sword_0":"a6d_offhand_sword_s07_0.png","a6t_sword_0":"a6t_sword_s07_0.png","a6t_boots_0":"a6t_boots_s07_0.png","a6t_ring_0":"a6t_ring_s07_0.png","a6t_orb_1":"a6t_orb_s07_1.png"} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a7.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a7.json new file mode 100644 index 0000000..68ac06f --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a7.json @@ -0,0 +1,23 @@ +{ + "a7_armor-fr1239_0": "a7_armor-fr1239_s07_0.png", + "a7_armor-fr1253_0": "a7_armor-fr1253_s07_0.png", + "a7_armor-fr1281_1": "a7_armor-fr1281_s07_1.png", + "a7_belt-fr1351_1": "a7_belt-fr1351_s07_1.png", + "a7_blunt-fr1057_1": "a7_blunt-fr1057_s07_1.png", + "a7_boots-fr1379_0": "a7_boots-fr1379_s07_0.png", + "a7_boots-fr1379_1": "a7_boots-fr1379_s07_1.png", + "a7_boots-fr1407_0": "a7_boots-fr1407_s07_0.png", + "a7_gloves-fr1183_1": "a7_gloves-fr1183_s07_1.png", + "a7_gloves-fr1197_1": "a7_gloves-fr1197_s07_1.png", + "a7_gloves-fr1211_1": "a7_gloves-fr1211_s07_1.png", + "a7_helmet-llequiphelmet0_1": "a7_helmet-llequiphelmet0_s07_1.png", + "a7_helmet-llequiphelmet1_1": "a7_helmet-llequiphelmet1_s07_1.png", + "a7_necklace-fr1099_0": "a7_necklace-fr1099_s07_0.png", + "a7_necklace-fr1113_0": "a7_necklace-fr1113_s07_0.png", + "a7_necklace-llaccessoriesnecklace_1": "a7_necklace-llaccessoriesnecklace_s07_1.png", + "a7_spellbook-llbook1_1": "a7_spellbook-llbook1_s07_1.png", + "a7_staff-draw0_0": "a7_staff-draw0_s07_0.png", + "a7_staff-draw0_1": "a7_staff-draw0_s07_1.png", + "a7_sword-fr1435_0": "a7_sword-fr1435_s07_0.png", + "a7_throwing-draw0_1": "a7_throwing-draw0_s07_1.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a8.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a8.json new file mode 100644 index 0000000..095ae30 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a8.json @@ -0,0 +1,35 @@ +{ + "a8l_armor-fr1253_0": "a8l_armor-fr1253_s07_0.png", + "a8l_armor-fr1281_0": "a8l_armor-fr1281_s07_0.png", + "a8l_armor-fr1267_1": "a8l_armor-fr1267_s07_1.png", + "a8l_axe-draw0_0": "a8l_axe-draw0_s07_0.png", + "a8l_belt-fr1351_0": "a8l_belt-fr1351_s07_0.png", + "a8l_blunt-fr1057_0": "a8l_blunt-fr1057_s07_0.png", + "a8l_boots-fr1379_0": "a8l_boots-fr1379_s07_0.png", + "a8l_boots-fr1393_0": "a8l_boots-fr1393_s07_0.png", + "a8l_boots-fr1421_1": "a8l_boots-fr1421_s07_1.png", + "a8l_bow-draw2_0": "a8l_bow-draw2_s07_0.png", + "a8l_gloves-fr1183_0": "a8l_gloves-fr1183_s07_0.png", + "a8l_horn-draw2_0": "a8l_horn-draw2_s07_0.png", + "a8l_horn-draw2_1": "a8l_horn-draw2_s07_1.png", + "a8l_necklace-fr1099_0": "a8l_necklace-fr1099_s07_0.png", + "a8l_necklace-fr1113_0": "a8l_necklace-fr1113_s07_0.png", + "a8l_necklace-fr1127_0": "a8l_necklace-fr1127_s07_0.png", + "a8l_orb-draw2_0": "a8l_orb-draw2_s07_0.png", + "a8l_quiver-draw2_0": "a8l_quiver-draw2_s07_0.png", + "a8l_ring-draw0_1": "a8l_ring-draw0_s07_1.png", + "a8l_shield-draw0_0": "a8l_shield-draw0_s07_0.png", + "a8l_shield-draw0_1": "a8l_shield-draw0_s07_1.png", + "a8l_spellbook-llbook1_0": "a8l_spellbook-llbook1_s07_0.png", + "a8l_staff-draw1_0": "a8l_staff-draw1_s07_0.png", + "a8l_staff-draw1_1": "a8l_staff-draw1_s07_1.png", + "a8l_sword-fr1435_1": "a8l_sword-fr1435_s07_1.png", + "a8l_throwing-draw0_0": "a8l_throwing-draw0_s07_0.png", + "a8l_throwing-draw1_0": "a8l_throwing-draw1_s07_0.png", + "a8t_sword_0": "a8t_sword_s07_0.png", + "a8t_armor_1": "a8t_armor_s07_1.png", + "a8t_shield_1": "a8t_shield_s07_1.png", + "a8t_orb_0": "a8t_orb_s07_0.png", + "a8t_orb_1": "a8t_orb_s07_1.png", + "a8t_offhand_sword_1": "a8t_offhand_sword_s07_1.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_a9.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_a9.json new file mode 100644 index 0000000..af55e1b --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_a9.json @@ -0,0 +1,29 @@ +{ + "a9_belt-fr1351_1": "a9_belt-fr1351_s07_1.png", + "a9_belt-fr1351_3": "a9_belt-fr1351_s07_3.png", + "a9_blunt-fr1057_1": "a9_blunt-fr1057_s07_1.png", + "a9_blunt-fr1057_3": "a9_blunt-fr1057_s07_3.png", + "a9_bow-draw2_1": "a9_bow-draw2_s07_1.png", + "a9_bow-draw2_2": "a9_bow-draw2_s07_2.png", + "a9_dagger-draw0_0": "a9_dagger-draw0_s07_0.png", + "a9_hammer-draw0_0": "a9_hammer-draw0_s07_0.png", + "a9_hammer-draw0_2": "a9_hammer-draw0_s07_2.png", + "a9_helmet-draw0_0": "a9_helmet-draw0_s07_0.png", + "a9_helmet-draw0_2": "a9_helmet-draw0_s07_2.png", + "a9_horn-draw2_0": "a9_horn-draw2_s07_0.png", + "a9_horn-draw2_2": "a9_horn-draw2_s07_2.png", + "a9_orb-draw2_0": "a9_orb-draw2_s07_0.png", + "a9_quiver-draw2_2": "a9_quiver-draw2_s07_2.png", + "a9_ring-draw0_1": "a9_ring-draw0_s07_1.png", + "a9_ring-draw0_3": "a9_ring-draw0_s07_3.png", + "a9_shield-draw0_0": "a9_shield-draw0_s07_0.png", + "a9_shield-draw0_2": "a9_shield-draw0_s07_2.png", + "a9_spellbook-llbook1_1": "a9_spellbook-llbook1_s07_1.png", + "a9_staff-draw0_1": "a9_staff-draw0_s07_1.png", + "a9_staff-draw1_2": "a9_staff-draw1_s07_2.png", + "a9_staff-draw1_3": "a9_staff-draw1_s07_3.png", + "a9_throwing-draw0_2": "a9_throwing-draw0_s07_2.png", + "a9_throwing-draw1_1": "a9_throwing-draw1_s07_1.png", + "a9_totem-draw3_0": "a9_totem-draw3_s07_0.png", + "a9_totem-draw3_1": "a9_totem-draw3_s07_1.png" +} diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_pd1.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_pd1.json new file mode 100644 index 0000000..1156a72 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_pd1.json @@ -0,0 +1 @@ +{"pd1_ring":"a1_ring_s10_0.png","pd1_helmet":"a1_helmet_s07_0.png","pd1_gloves_a":"a1_gloves_s07_1.png","pd1_armor":"a1_armor_s07_1.png","pd1_necklace":"a1_necklace_s07_0.png","pd1_boots":"a1_boots_s10_0.png"} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/picks_pd2.json b/공유/기획/FirstRising/아이템/moba_anfg/picks_pd2.json new file mode 100644 index 0000000..0d2fdbb --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/picks_pd2.json @@ -0,0 +1 @@ +{"pd2_armor":"a2_armor_s07_1.png","pd2_boots":"a2_boots_s07_0.png","pd2_dagger":"a2_dagger_s07_3.png","pd2_magicdagger":"a2_magic_dagger_s07_3.png","pd2_necklace":"a2_necklace_s07_2.png","pd2_ring":"a2_ring_s07_2.png","pd2_shield":"a2_shield_s07_1.png","pd2_sword":"a2_sword_s07_0.png"} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/moba_anfg/shapes/active.txt b/공유/기획/FirstRising/아이템/moba_anfg/shapes/active.txt new file mode 100644 index 0000000..69d905c --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/shapes/active.txt @@ -0,0 +1,130 @@ +armor__fr1239.png +armor__fr1253.png +armor__fr1267.png +armor__fr1281.png +armor__genpd1armor.png +armor__genpd2armor.png +axe__draw4.png +axe__genmoba0.png +axe__genmoba1.png +belt__fr1351.png +blunt__fr1057.png +boots__fr1379.png +boots__fr1393.png +boots__fr1407.png +boots__fr1421.png +boots__genpd1boots.png +boots__genpd2boots.png +bow__draw3.png +dagger__draw3.png +dagger__genmoba0.png +dagger__genmoba1.png +dagger__genpd2dagger.png +dagger__genpd2magicdagger.png +gloves__fr1169.png +gloves__fr1183.png +gloves__fr1197.png +gloves__fr1211.png +gloves__genpd1glovesa.png +hammer__draw2.png +helmet__draw0.png +helmet__draw1.png +helmet__genmoba0.png +helmet__genpd1helmet.png +horn__draw2.png +horn__genmoba0.png +horn__genmoba1.png +necklace__fr1099.png +necklace__fr1113.png +necklace__fr1127.png +necklace__fr1141.png +necklace__genpd1necklace.png +necklace__genpd2necklace.png +orb__draw2.png +orb__genmoba0.png +orb__genmoba1.png +quiver__draw2.png +ring__draw0.png +ring__genmoba0.png +ring__genpd1ring.png +ring__genpd2ring.png +shield__draw0.png +shield__genpd2shield.png +spellbook__ll_book_1.png +staff__draw0.png +staff__draw1.png +sword__draw2.png +sword__genpd2sword.png +throwing__draw0.png +throwing__draw1.png +totem__draw3.png +axe__genxl0.png +axe__genxl1.png +dagger__genxl0.png +dagger__genxl1.png +sword__genxl0.png +sword__genxl1.png +ring__genxl0.png +ring__genxl1.png +horn__genxl0.png +horn__genxl1.png +bow__genxl0.png +quiver__genxl0.png +quiver__genxl1.png +shield__genxl0.png +shield__genxl1.png +helmet__genxl0.png +helmet__genxl1.png +axe__genxlb0.png +axe__genxlb1.png +belt__genxlb0.png +belt__genxlb1.png +belt__genxlb2.png +bow__genxlb0.png +bow__genxlb1.png +bow__genxlb2.png +dagger__genxlb0.png +hammer__genxlb0.png +hammer__genxlb1.png +horn__genxlb0.png +staff__genxlb0.png +staff__genxlb1.png +staff__genxlb2.png +dagger__genxlc0.png +horn__genxlc0.png +horn__genxlc1.png +necklace__genxlc0.png +spellbook__genxlc0.png +spellbook__genxlc1.png +spellbook__genxlc2.png +totem__genxlc0.png +totem__genxlc1.png +crossbow__genxl0.png +crossbow__genxl1.png +bracelet__genxl0.png +bracelet__genxl1.png +axe__genxld0.png +axe__genxld1.png +axe__genxld2.png +hammer__genxld0.png +hammer__genxld1.png +hammer__genxld2.png +hammer__genxld3.png +helmet__genxld0.png +helmet__genxld1.png +helmet__genxld2.png +helmet__genxld3.png +quiver__genxld0.png +quiver__genxld1.png +quiver__genxld2.png +quiver__genxld3.png +ring__genxld0.png +ring__genxld1.png +ring__genxld2.png +ring__genxld3.png +shield__genxld0.png +shield__genxld1.png +shield__genxld2.png +shield__genxld3.png +sword__genxld0.png +sword__genxld1.png diff --git a/공유/기획/FirstRising/아이템/moba_anfg/shapes/shapes_sheet.png b/공유/기획/FirstRising/아이템/moba_anfg/shapes/shapes_sheet.png new file mode 100644 index 0000000..419fae0 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/shapes/shapes_sheet.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/showcase_12.png b/공유/기획/FirstRising/아이템/moba_anfg/showcase_12.png new file mode 100644 index 0000000..3926298 Binary files /dev/null and b/공유/기획/FirstRising/아이템/moba_anfg/showcase_12.png differ diff --git a/공유/기획/FirstRising/아이템/moba_anfg/type_desc.json b/공유/기획/FirstRising/아이템/moba_anfg/type_desc.json new file mode 100644 index 0000000..0da11d9 --- /dev/null +++ b/공유/기획/FirstRising/아이템/moba_anfg/type_desc.json @@ -0,0 +1,4 @@ +{ + "crossbow": "a crossbow, carved wooden stock, steel limbs with ornate fittings, {pal}", + "bracelet": "an armored bracelet, engraved metal band with a faceted gem, {pal}" +} \ No newline at end of file diff --git a/공유/기획/FirstRising/아이템/run_a26.ps1 b/공유/기획/FirstRising/아이템/run_a26.ps1 new file mode 100644 index 0000000..3b1cd34 --- /dev/null +++ b/공유/기획/FirstRising/아이템/run_a26.ps1 @@ -0,0 +1,11 @@ +# 2026-10-03 a26 생산 회차(재질 조합 색) — 백그라운드 시간 제한으로 끊겨 따로 띄우는 프로세스로 이어 돌린다. 이미 만든 그림은 건너뛴다. +Set-Location "E:\BurningTimes\공유\기획\FirstRising\아이템" +$env:PYTHONIOENCODING='utf-8' +$o="E:\BurningTimes\공유\기획\FirstRising\아이템\moba_anfg" +$env:ANFG_SEED='71'; $env:ANFG_ONLY=''; $env:ANFG_SKIP='' +$env:ANFG_ROWS='armor-fr1267,armor-fr1253,armor-fr1281,boots-fr1379,boots-fr1393,boots-fr1407,gloves-fr1183,gloves-fr1197,gloves-fr1211,necklace-fr1099,necklace-fr1113,necklace-fr1127,necklace-genxlc0,belt-fr1351,belt-genxlb0,belt-genxlb1,helmet-genxld2,helmet-genxld3,helmet-genmoba0,shield-genxld3,shield-genxl1,shield-draw0,ring-genxld0,ring-genxld1,ring-genxld2,ring-genxld3,sword-genxl1,dagger-genxlb0,axe-genxld1,hammer-genxld0,hammer-genxld1,staff-genxlb0,staff-draw1,blunt-fr1057,bow-genxlb0,quiver-genxld2,spellbook-genxlc0,orb-genmoba1,totem-draw3,throwing-draw0,horn-draw2' +$env:ANFG_TONE='paint'; $env:ANFG_UPSCALE='model'; $env:ANFG_REFINE='0.45'; $env:ANFG_PAL='material'; $env:ANFG_LORA2='FR_anfg_v4.safetensors:0.3' +python comfy_moba_anfg.py $o a26 "0.7" 3 512 1 lib 0.6 0.5 *> "$o\a26_run.log" +$env:ANFG_PAL='' +python icon_review_sheet.py $o a26 9 *>> "$o\a26_run.log" +"A26 DONE" | Out-File -Append -Encoding utf8 "$o\a26_run.log" diff --git a/공유/기획/FirstRising/아이템/아이콘_생성_체계.md b/공유/기획/FirstRising/아이템/아이콘_생성_체계.md new file mode 100644 index 0000000..cab4ebb --- /dev/null +++ b/공유/기획/FirstRising/아이템/아이콘_생성_체계.md @@ -0,0 +1,142 @@ +# FR 장비 아이콘 생성 체계 (2026-10-02 착수 · 자율 반복 중) + +> PD 지시(2026-10-02): "원하는 장비 아이콘을 자유롭게 생성할 수 있는 수준에 도달할 때까지 이미지를 반복해서 생성하고, 완성된 이미지를 모아 학습을 거듭해 우리 프로젝트에 유용한 자원을 생산할 수 있는 체계를 구축." · 승인을 구하려 멈추지 말 것 · 방법은 스스로 고안. +> 세션이 끊기면 이 문서 하나로 이어 간다. 회차 기록은 맨 아래 표에 한 줄씩 더한다. + +## 1. 목표 풍과 합격 기준 +- 목표 풍: civitai 143301 "Game Icon Research Institute LoRA-ANFG_V3" 예시 → `moba_anfg/approved/pd_target_reference.png` +- PD 합격본: `moba_anfg/approved/approved_sheet.png` (15장 · `icon_approved_sheet.py` 가 만든다) +- 합격 기준(PD 가 고른 것의 공통점 · 검토 에이전트 분석 포함) + - 물건 하나 · 여백 안 · 테두리/원형 바탕/잘림 없음 · 다른 물건과 섞이지 않음 · 무슨 장비인지 분명 + - 실제 장비 비례에 가까운 단순한 실루엣 · 얇은 외곽선 · 면 안에 명암 단계 · 금 + 한 색(적 또는 청) + 은빛 금속 + - 불합격 경향: 굵은 검은 외곽선 + 납작한 색면("캐주얼") · 장난감 같은 덩어리 · 원색 청록/형광 초록/자홍 · 빛 번짐 +- FR 원본 장비 아이콘은 PD 가 "너무 실사풍"이라 판단 → 색 · 질감은 쓰지 않는다(윤곽선만 빌리는 것은 가능). + +## 2. 반복 순서 (한 회차) +1. **생성** `comfy_moba_anfg.py <출력폴더> <회차> <시드 수> 512 1 ` — 환경변수 `ANFG_TONE`(분위기) · `ANFG_REFINE`(다듬기 세기) · `ANFG_LORA2`("FR_anfg_vN.safetensors:강도") + - 기반 `mobaGameEquipment_v10` + LoRA `giI_anfg_v3_000018`(0.7~0.8, 1.0 은 형태가 녹음) · 512 → 4x-UltraSharp → 1024 다듬기 → InspyrenetRembg(투명) · 장당 약 30초(RTX 3060) +2. **채점 시트** `icon_review_sheet.py <폴더> <회차> <줄 수>` — 알파 기준 자동 채점(OK/X)과 함께 `<회차>_review_N.png` +3. **검토** 검토 에이전트(그림을 직접 보는 하위 에이전트)가 합격 기준 시트와 견주어 고른다 → `moba_anfg/picks_<회차>.json` (엄격 · 애매하면 뺀다). PM 세션은 그림을 직접 읽지 않는다(세션 기록이 커져 끊긴다). +4. **데이터셋 등록** `icon_dataset.py add <폴더> ` → `moba_anfg/dataset/` · `dataset.json` +5. **학습** `comfy_anfg_train.py <버전> [steps] [PD 합격본 배수]` → `C:\Comfyui\models\loras\FR_anfg_<버전>.safetensors` (ANFG LoRA 를 얹은 모델 위에서 차이만 학습 · 트리거 `fricon`) +6. **검증** 새 LoRA 를 `ANFG_LORA2` 로 걸고 전 부위를 글자만으로 생성 → 2~3 단계 → 합격률 비교 → 합격본을 데이터셋에 더해 다음 버전 학습 +7. **리소스화** `icon_finalize.py <폴더> <출력폴더>` → 1024 투명 · 여백 통일(긴 변 82%) + +## 3. 지켜야 할 것 +- 생성물은 조직 레포 검토 폴더에만 둔다. FR 프로젝트 반입 · 커밋 · push 는 PD 지시 시만. 파일 삭제 금지. +- ComfyUI = Comfy Desktop(`C:\Comfyui\Comfy Desktop\Comfy Desktop.exe`) · `http://127.0.0.1:8000`. 꺼져 있으면 실행하고 1분쯤 기다린다. 생성 스크립트는 이미 만든 파일을 건너뛰므로 같은 명령을 다시 돌리면 이어진다. +- 그래픽 카드는 하나 — 생성과 학습을 동시에 돌리지 않는다. + +## 4. 회차 기록 +| 회차 | 설정 | 결과(실측) | 다음 조치 | +|---|---|---|---| +| a1 | ANFG 0.7/1.0 · 512 · 다듬기 없음 · 8종 | PD 7장 선택 "이전보다 좋아졌어" · 벨트/검/장갑 형태 실패 | 묘사 구체화 | +| a2 | ANFG 0.7 · 다듬기 0.35 · FR 20종×4 | 31장 선별 → PD 8장 선택 · "너무 캐주얼" · "퀄리티 들쭉날쭉 · 풍 안 맞음" · 긴 무기가 검으로 쏠림 | 분위기 조정 · 학습 | +| a3 | shape(원본 윤곽 ControlNet) | 2장만 만들고 중단(분위기 조정이 먼저) | 분위기 확정 뒤 재개 | +| a4 | tone=epic · ANFG 0.8/1.0 · 다듬기 0.25 · 8종 | 검토: 명암은 가까워졌으나 형태가 녹음 · 잘림 · 빛 번짐 · 32장 중 2장 | tone=refined 신설 | +| v1 | PD 합격본 14장 · 800 스텝 · lr 2e-4 · rank 16 | 학습 완료. 단 캡션 3건이 다른 회차 묘사로 잘못 붙어 있었다(고침) | a5 에서 v1 유무 비교 | +| a5 | tone=refined · FR 20종×2 · v1 없음(N) / v1 0.8(V) | 검토: 풍은 V 가 조금 낫고 형태는 N 이 낫다. v1 은 방패 사자를 베끼고 검 쏠림을 키움. 엄격 합격 12/80(검 · 단검 · 갑옷 · 장화 · 반지) | v1 은 쓰지 않음 · 종류 넓힌 뒤 v2 | +| a6 | 글자만(T) / 실사풍 초안(D) / 원본 윤곽(S) 비교 · 21종×2 | 검토: T 는 4종만 합격 · D 는 물건 여러 개 · 인물 섞임 · S 는 8장 모두 형태 읽힘. 합격 14. 수준 4/10 · 걸림돌 = 형태 지식 · 구도 통제 | 길잡이 모음(icon_shapes.py) | +| a7 | lib 방식: 길잡이 48개(FR 원본 · Layer Lab · 직접 그린 도형) × 2 · 색 조합 6 순환 | 검토: 합격 21/96 · 10종 0장. FR 윤곽은 좋음 · Layer Lab 은 캐주얼이 샘 · 도형은 밋밋 · 청록/보라/초록 단색이 40%. 수준 5/10 | 도형 다시 그림 · 색 4조합(금 중심) | +| v2 | 데이터셋 63장(PD 14 ×2 배수) · 1200 스텝 | 학습 완료 | a8 | +| a8 | v2 0.6 · 글자만 21종×2(a8t) + 길잡이 40개×2(a8l) | 검토: 풍이 PD 합격본 쪽으로 뚜렷이 감 · 통일감 높음. 길잡이 약 41/80(저장 27) — a7 의 0장 10종 중 7종이 합격. 글자만은 5종/21종(제자리). 수준 = 글자만 4.5 · 길잡이 6.5 | 단검 · 망치 · 토템 · 투구 도형 추가 · 드문 종류 집중 | +| a9 | v2 0.6 · 드문 16종 길잡이 × 4장 | 검토: 합격 27/76(17행) · 새 도형 중 토템 · 투구(볏) · 망치는 통함, 도끼 · 뿔 투구 0장. 남은 걸림돌 = 단순함(장식 밀도 · 명암 단계 · 정면 구도) · 같은 길잡이는 같은 그림 | 도끼 · 뿔 투구 도형 수정 · PD 합격본 윤곽 14개를 길잡이에 추가(50개) · tone=rich | +| a10 | tone=rich · ControlNet 끝 0.35 · ANFG 0.7/0.9 · 6종×2 | 검토: 단검 · 방패는 장식 · 명암이 PD 합격본에 근접. 끝 0.35 는 약 40% 가 길잡이 이탈 · 0.9 는 전 행에서 0.7 보다 나쁨. 합격 6/24 | 끝 0.5(가는 종류 0.6) · "gemstones" · "three-quarter view" 삭제 · ANFG 0.7 고정 | +| v3 | 데이터셋 123장(PD 14 ×3 배수) · 1500 스텝 | 학습 완료 | a11 | +| a11 | v3 · tone=rich · 글자만 21종×2(v3 0.8) + 길잡이 50개×2(v3 0.6 · 끝 0.5) | 검토: 길잡이 약 46/100(저장 31) — 갑옷 · 목걸이 · 장화 · 장갑 · 투구는 PD 합격본 수준. **글자만은 후퇴(21종 중 1종)** — 거의 전부 "화면 가득한 금속 원반". genpd 길잡이는 색만 바뀐 복제. 가는 무기는 날이 흰 납작면. 수준 = 글자만 2 · 길잡이 7 | 학습 방식 수정(v4) | +| v4 | 여백을 넣은 그림(약 69%) · 종류당 8장 제한 · genpd 유래 제외 · 캡션에 구도 낱말 · 1200 스텝 · PD ×3 (선택 143/160) | 학습 완료(32분) | a12 | +| a12 | v4 0.6 · 글자만 21종×2 + 무기 중심 길잡이 ×3(날 묘사 보강 · genpd 길잡이는 좌우 반전) | 검토: **글자만의 원반 붕괴가 풀림**(7종 · 8/42 — 지금까지 최고). 길잡이 약 34/63(저장 18). 도끼 · 활 · 직접 그린 단검 · fr1435 검은 0장. 풍은 PD 합격본과 배색 · 밝기 일치, 장식 밀도 · 붓결은 목표 풍보다 부족. 수준 = 글자만 4.5 · 길잡이 7 | 가는 무기 768 · 도형 다시 그림 | +| a13 | v4 · 가는 무기 길잡이(768 · 끝 0.7 · 검/단검/도끼 새 도형) ×3 + 글자만 v4 0.8 비교 | 검토: 가는 무기 약 26/39(저장 14) — "흰 납작면" 대부분 풀림 · 잘림 0. 지팡이 · 둔기 · 투척은 리소스 수준. 도끼(속 빈 초승달) · 직접 그린 단검(두 갈래 날) 0장. 글자만 v4 0.8 은 3종(0.6 보다 나쁨) | 도끼 · 단검 · 활 · 망치 도형 다시 그림 · v4 는 0.6 고정 | +| a14 | v4 0.6 · 방어구/장신구/보조 장비 길잡이 37행×2 | 검토: 저장 24/74 · 최상급 8(`best_a14.json`). 배색 · 외곽선 · 밝기는 PD 합격본과 한 세트. genpd 행은 대부분 복제 · 투구/반지/뿔피리/구슬 0장(단순 도형은 매끈해짐). 남은 차이 = 손그림 붓결 · 깊은 그림자 | 붓결 시험(a16) | +| a15 | v4 0.6 · 도끼/단검/활/망치/검 새 도형 ×4(768) | 검토: 저장 5/32. 망치는 풀림(쓸 만함) · 검/단검/활은 조건부(4장에 1장) · **도끼는 도형을 네 번 고쳐도 "속 빈 초승달"** | 길잡이 자동 마련(icon_guide_bootstrap.py) | +| a16 | 붓결 시험 6행×2: a=paint+UltraSharp 0.3 · b=paint+단순 확대 0.5 · c=rich+단순 확대 0.5 · d=b 에 ANFG 0.85 | 검토: 목표 풍과의 거리 d > b > a > c. 붓결을 만드는 것은 확대 방식보다 **paint 낱말과 ANFG 강도**. d 는 형태 · 색 이탈, b 는 약간 흐림, a 는 가장 선명하나 잔티 · 굵은 외곽선. 그림자 깊이는 넷 다 부족(학습 데이터 쪽 과제로 추정) | 기본 = paint + UltraSharp + 다듬기 0.45 · ANFG 0.7 (b 의 면 정리 + a 의 선명도를 노린 혼합 — a17 에서 확인) | +| a17 | 생산 회차: 전 길잡이(genpd 제외 · 자동 마련 길잡이 포함) × 2 · v4 0.6 · paint + UltraSharp + 0.45 | 검토: 저장 38/92 · 최상급 13(`best_a17.json`). 붓결은 a14 보다 나아짐 · 보라/자홍 이탈 없음 · 그림자 깊이는 여전히 얕음. 방어구 · 장신구는 PD 합격본과 한 세트, 직접 그린 도형의 무기는 반 단계 떨어짐. 자동 마련 길잡이는 도끼(1장 · 처음으로 속 찬 날) · 투구 · 구슬에서 도형보다 나음, 단검 · 반지 · 뿔피리는 실패. 수준 6.5/10 | v5(최상급 2배 · 종류당 10장) | +| v5 | 데이터셋 279장 중 선택 · PD ×3 · 최상급 ×2 · 1300 스텝 | 학습 완료(35분) | a18 | +| a18 | v5 0.6 · 글자만 21종×2(최종 측정) + 약한 12종 길잡이 ×2 | 검토: **글자만 후퇴(2종 · 3/42)** — 원반 · "같은 물건 다발" 붕괴. 길잡이는 v4 와 동급(약 16/42), 새김 장식만 소폭 늘음. **판정 = v4 유지, v5 는 기본으로 쓰지 않는다.** 글자만 합격 추세 v2→v5 = 6 · 1종 · 8 · 3장(추세 없음) — 합격본이 길잡이로 만든 그림이라 "글자 ↔ 형태"를 못 가르치는 것으로 추정 | 정식 경로를 "글자 → 자동 길잡이 → 본 생성" 2단으로 | +| a19 | SDXL 초벌 길잡이(genxl · 도끼/단검/검/반지/뿔피리/활/화살통/방패/투구) × 3 · v4 0.6 | 초벌 자동 채점 통과: 검 · 뿔피리 · 화살통 · 방패 · 투구 6/6 · 단검 · 반지 5/6 · 활 1/6. 검토: 엄격 합격 10/51(저장 9) — **검(3/3) · 반지 · 방패 · 화살통이 처음으로 풀림**. 도끼 · 단검 · 활 · 뿔피리 0장 — 원인은 본 생성이 아니라 초벌(두 자루 · 칼집 딸림 · 갈고리 · 뿔피리가 확성기). 풍은 우리 세트와 한 세트(SDXL 풍은 안 넘어옴). 방식 수준 6/10 | 초벌을 눈으로 고른다(초벌 시트 → 검토 → `icon_shapes.py add`) · 초벌 묘사 보강 | +| a20 | 도끼 · 단검 · 뿔피리 · 활 · 지팡이 · 망치 · 벨트 · 장갑의 SDXL 초벌을 묘사를 고쳐 8~12장씩 → 검토 에이전트가 길잡이 15장을 고름(`guides_a20.json` · 장갑 0) → 본 생성 ×3 | 검토: 엄격 합격 10/45 — **단검(2) · 활(1)이 처음 풀림**, 지팡이 4 · 벨트 3. 도끼(도끼 + 칼 혼합 · 곡괭이형) · 뿔피리(굽은 배관) · 망치(상자 덩어리) 0장. 구성 오류(두 자루 · 칼집)는 거의 사라지고 실패 원인이 "초벌 형태 자체"로 바뀜. 방식 수준 6/10 | 뿔피리 · 단검 · 마법서 · 토템 · 목걸이 초벌 선별(`guides_a21.json`) | +| a21 | 눈으로 고른 SDXL 초벌 길잡이(뿔피리 2 · 단검 1 · 마법서 3 · 토템 2 · 목걸이 1) × 3 | 검토: 합격 5/27(목걸이 3/3 · 마법서 2). 뿔피리(부는 구멍 · 벌어진 입이 없어 엄니/통) · 토템 · 단검 0장 | 최상급 점검 | +| 점검 | `best_v4b`(30장) 최종 점검 | 검토가 7장을 제외(`best_v4b_reject.json`) → `best_v4c` 25장. 판정: 세트로는 묶임 · "캐주얼"은 대부분 줄음 · "들쭉날쭉"은 부분 해소. 목표 풍과 다른 점 = 원색 파랑이 전면 · 매끈한 색면 · 단순한 실루엣 · 방어구(고채도 광택)와 무기/소품(옅은 색 · 얇은 선)이 두 무리 | 색 방향 비교(a22) | +| a22 | ANFG_PAL=dark(어두운 바탕색 + 작은 강조색) · 10행 × 2 × ANFG 0.7/0.8 | PM 이 비교 시트(`a22_compare.png`)를 직접 봄: 벨트 · 방패 · 둔기 · 투구는 채도가 내려가고 금속이 어두워짐, 갑옷 · 장갑 · 장화 · 목걸이는 거의 그대로(v4 가 밝은 금 + 적/청으로 끌어당긴다). ANFG 0.8 은 0.7 과 거의 같음. 지팡이 1장에 군더더기(해골 · 가시) | PD 에게 방향 확인 요청(밝은 쪽 유지 / 어두운 쪽) — 답 전까지는 밝은 쪽 유지 | +| make | `icon_make.py` 실증: 표에 없던 종류 2개 | PM 이 직접 봄: **팔찌 6/6 이 팔찌로 읽히고 풍도 세트와 맞음**(자동 길잡이만으로). **석궁 0/6** — 가늘고 복잡한 형태는 초벌도 본 생성도 무너짐 | 결론 갱신 | +| a23 | 장수가 적은 종류(반지 · 투구 · 검 · 방패 · 화살통 · 도끼 · 망치) SDXL 초벌 10~12장 → 눈 선별 25장(`guides_a23.json`) → 본 생성 ×3 | 검토: 저장 20/75 · 대표 8. **망치 · 반지가 풀림**(반지는 12장 중 10장쯤 합격 수준). 도끼는 길잡이 1개(genxld1)에서만 1장. 투구는 기사형 길잡이만. 검 초벌은 12장 중 10장이 칼집 딸림 | 검증된 길잡이로 보충(a24) | +| a24 | 검증된 길잡이 15행 × 4(도끼 genxld1 · 망치 · 화살통 · 검 · 단검 · 활 · 투구 · 방패 · 마법서 · 뿔피리 · 토템 · 구슬) | 검토: **저장 29/60(48%) · 최상급 후보 13.** 형태는 15행 모두 4/4 로 재현. 떨어진 사유는 대부분 색(금 단색 · 무채색 · 적/청 혼용). 활은 길잡이가 가늘어 1/4 | 묶음 갱신(`best_v4e` 46 · `final_v4e` 166) | + +### 최신 묶음 (a24 뒤) +- `moba_anfg/best_v4e/` 최상급 46장 · `moba_anfg/final_v4e/` 합격본 166장 · 데이터셋 363장. +- 투명 가장자리: PM 이 6장을 흰 바탕 · 어두운 바탕에 올려 직접 확인(`edge_check.png`) — 테 · 번짐 없음. +- **검증된 길잡이를 다시 쓰면 형태는 그대로 재현되고 합격률은 약 절반** → 등급별 색 변형(같은 형태 · 다른 색)을 뽑는 용도로 바로 쓸 수 있다. 색을 프롬프트로 고정하면 합격률이 더 오를 것으로 추정(미검증). + +## 7. 색 개선 (2026-10-03 · PD 지적 뒤) +> PD: "디자인 형태나 퀄리티 자체는 그럭저럭 나오는 것 같은데, 너무 붉은색, 푸른색과 같이 원색 계열만 쓰고 있어서 색감이 풍부하지 않고 퀄리티가 저급해보여." + 레퍼런스 `https://kr.pinterest.com/pin/20336635810523957/` (= ArtStation "RPG Weapon Icons 02", Olekzandr Zahorulko) +- 레퍼런스에서 본 것: 색이 "칠"이 아니라 "재질"에서 나온다(강철 · 나무 · 가죽 · 뼈 · 청동). 원색은 작은 강조(보석 · 감은 끈 · 마법 빛)에만, 강조색이 물건마다 다르다. 명암 폭이 넓다. +- 원인: 색 조합을 금 + 적/청 넷으로 좁혔고(a7 뒤 합격률을 올리려던 조치) 물건 전체를 그 색으로 칠하게 묘사했으며, v4 LoRA 가 그 배색으로 학습됐다. **1절의 "금 + 한 색(적 또는 청)" 기준과 PD 합격 15장의 배색은 이제 기준이 아니다(형태 · 구도 기준만 유효).** + +| 회차 | 설정 | 결과(실측) | 다음 조치 | +|---|---|---|---| +| a25 | `ANFG_PAL=material`(재질 8 × 강조색 10) · v4 없음 / 0.3 · 12행×2 | PM 이 비교 시트를 직접 봄: 반지 · 벨트 · 방패 · 목걸이 · 망치 · 검은 재질색 + 작은 강조로 바뀜. 갑옷 · 장화 · 투구는 강조색이 몸체를 덮음. v4 없음과 0.3 은 거의 같음 | 재질 가중 · "강조는 작은 보석만" | +| a26 | material · v4 0.3 · 41행×3 | 검토: 약 70% 가 재질색 + 작은 강조. 저장 53. 남은 문제 = 재질이 엉뚱한 부위(나무 칼날) · 장식 밀도 감소 · 갈색 쏠림 · 일부 한 색 덮음 · 검/구슬 0장 | 부위별 재질 | +| a27 | `ANFG_PAL=parts`(종류별 묘사에 {metal} · {metal2} · {soft} · {accent} 자리 · 장식 낱말 · 차가운 재질 · 명암 낱말) · 41행×2 | 검토: 부위 문제 크게 개선 · 갈색 쏠림 해소 · 검/구슬 해소. 저장 46. 새 부작용 = 강조 없는 무채색 · 금 단색 + 빛 번짐 · 원형 바탕 3장. 레퍼런스 대비 6/10 | 색이 풍부한 합격본으로 v6 학습 | +| v6 | a26 · a27 합격본만(99장 중 종류당 8) · 1000 스텝 · 예전 PD 합격본 제외 | 학습 완료 | a28 에서 v4 0.3 과 비교 | +| a28 | v6 0.6 · parts · 14행×2(a27 과 같은 시드 · 같은 묘사) | PM 이 비교 시트(`a28_compare.png`)를 직접 봄: 색 방향은 둘 다 재질색 + 작은 강조로 같다. v6 는 반지 세공 · 갑옷의 천 안감 · 장화 장식이 조금 더 풍부, 대신 군더더기 2장(망치 옆 파편 · 지팡이 주변 해골 조각)과 초록이 덮은 장갑 1장. v4 0.3 도 지팡이 1장에 별 조각 · 벨트 1장에 원형 테. **차이는 작다 — 결정적 개선 아님.** | 기본은 v6 0.5 로 두고(군더더기를 줄이려 0.6 → 0.5 · 미검증) 질감 · 강조 다양성은 낱말 쪽에서 계속 | + +- 최상급: `moba_anfg/best_color/`(32장 · 21종 · PM 이 시트 직접 확인) · 데이터셋 462장. +- 레퍼런스와 남은 차이(검토): ① 재질 질감(흠집 · 나뭇결 · 바느질 같은 손그림 질감) ② 한 물건 안의 재질 수와 강조 종류(끈 · 천 · 깃털 · 룬 빛) ③ 형태 설계(망치 · 도끼 · 지팡이가 단순 · 검 날밑 위치 · 장갑 발톱) +- 운영 메모: 백그라운드 명령은 약 1시간에서 끊긴다 → 한 회차를 40장 안팎으로 나눈다(생성 스크립트는 이어 돌리면 건너뛴다). `run_a26.ps1` 은 실행되지 않은 채 남은 파일(쓰이지 않음). + +### 다음에 할 일 (PD 결정 뒤) +1. 색 방향: 밝은 금 + 적/청(지금) 유지 / 어두운 쪽(목표 예시) — 어두운 쪽이면 어두운 합격본을 모아 LoRA 를 다시 학습해야 한다(낱말만으로는 갑옷 · 장갑 · 장화가 안 움직였다 · a22). +2. FR 등급 10단계에 맞춘 색 변형 세트(같은 길잡이 · 등급별 색) — 팔레트를 한 조합으로 고정하는 환경변수를 추가하면 된다. +3. 가늘고 복잡한 형태(뿔피리 · 석궁 · 도끼 다양화)와 목표 예시 수준의 붓질 재질감은 SDXL 계열로 옮겨 풍 LoRA 를 새로 학습하는 것이 후보(GPU 업그레이드 뒤). +4. FR 프로젝트 반입(아이콘 번호 · 크기 규격 맞추기)은 PD 승인 뒤. + +### 리소스 묶음 (a23 뒤 · 최신) +- `moba_anfg/best_v4d/` — 최상급 33장(PM 이 시트를 직접 확인: 한 세트로 보임 · 파랑이 많음) · `moba_anfg/final_v4d/` — 합격본 137장. +- 종류별(137장): 목걸이 13 · 장화 13 · 갑옷 13 · 지팡이 12 · 반지 8 · 방패 8 · 망치 7 · 장갑 7 · 투척 6 · 화살통 6 · 벨트 6 · 둔기 6 · 검 6 · 투구 5 · 마법서 4 · 활 4 · 구슬 4 · 단검 3 · 토템 3 · 도끼 2 · 뿔피리 1 +- 종류별 상태(a23 검토): 쓸 만함 = 갑옷 · 장화 · 장갑 · 목걸이 · 벨트 · 반지 · 투구(기사형) · 방패 · 구슬 · 지팡이 · 둔기 · 투척 · 토템 / 조건부(눈으로 고른 길잡이 · 3~4장에 1장) = 망치 · 화살통 · 검 · 마법서 · 단검 · 활 · 도끼 / 아직 아님 = 뿔피리 · 석궁 같은 가늘고 복잡한 형태 +- 검증된 길잡이(행 이름): axe-genxld1 · hammer-genxld0/1 · quiver-genxld2 · sword-genxl1 · dagger-genxlb0 · bow-genxlb0 · helmet-genxld2/3 · shield-genxld3 · shield-genxl1 · spellbook-genxlc0 · ring-genxld0~3 · staff-genxlb0 · belt-genxlb0/1 · necklace-genxlc0 + FR 원본 윤곽(갑옷 · 장화 · 장갑 · 목걸이 · 벨트 · 둔기) + +### 결론 갱신 (2026-10-02 16시) +- **덩어리형 장비(방어구 · 장신구 · 방패 · 책 · 구슬 · 팔찌 등)**: 글자 한 줄(`icon_make.py`)로 새 종류까지 뽑힌다. 세트 풍 유지. +- **가늘고 복잡한 장비(도끼 · 석궁 · 뿔피리 · 망치 · 활 일부)**: 초벌 모델도 형태를 틀려 아직 안 된다. 검 · 단검 · 지팡이 · 둔기 · 투척은 길잡이를 눈으로 고르면 된다. +- **풍**: PD 합격본(밝은 금 + 적/청)과는 한 세트. 목표 예시(어둡고 채도 낮은 바탕 · 붓질 재질감 · 복잡한 실루엣)와는 아직 거리가 있다 — 설정으로는 조금만 움직였고(paint · dark), SD1.5 기반 + 지금 데이터의 한계로 본다. 더 가려면 SDXL 계열로 옮겨 풍 LoRA 를 새로 학습하는 것이 후보(GPU 업그레이드 뒤). + +### 리소스 묶음 갱신 (a20 뒤) +- `moba_anfg/best_v4b/` — 최상급 30장(18종) · `moba_anfg/final_v4b/` — 합격본 112장(21종). +- 여전히 약한 종류: 도끼 1 · 뿔피리 1 · 반지 2 · 투구 2 · 마법서 2. 장갑 초벌은 SDXL 도 손가락을 6~7개로 그린다(FR 원본 윤곽 길잡이가 더 낫다). + +### 한 줄 명령 (a19 뒤 추가) +- `icon_make.py <종류> "<초벌 묘사>" "<본 묘사 · {pal}>" [초벌 장수] [길잡이 수] [길잡이당 장수]` — SDXL 초벌 → 자동 채점 통과분을 길잡이로 등록 → 본 생성 → 검토 시트. 본 묘사는 `moba_anfg/type_desc.json` 에 쌓인다. +- 자동 채점은 "물건 하나 · 여백 안"만 본다. **종류가 맞는지 · 두 자루인지는 못 본다** → 품질이 중요하면 길잡이 수를 0 으로 주고 `bootstrap/xl_<종류>_sheet.png` 를 눈으로 본 뒤 `python icon_shapes.py add <종류> <파일> gen<이름>` 으로 고른 것만 등록한다. + +### 결론(2026-10-02 a18 기준): "글자만 자유 생성"에 대한 판단 +- 자기 합격본으로 LoRA 를 다시 학습하는 것만으로는 글자만 생성이 좋아지지 않는다(v2~v5 실측). SD1.5 계열은 가는 무기 · 드문 종류의 형태를 글자로 안정되게 못 그린다. +- 현실적인 정식 경로 = **글자 → 자동 길잡이 → 본 생성** 2단. 길잡이 초벌은 글자를 잘 알아듣는 모델이 그리고(풍은 상관없음), 본 생성이 그 윤곽 위에 우리 풍을 입힌다. 쓰는 사람에게는 글자만 넣는 것과 같다. +- 초벌 모델: `BOOT_MODEL=xl` → `gameIconInstitute_v4XL`(SDXL · 1024 · 장당 약 40초). 2026-10-02 도끼 3/3 자동 채점 통과(SD1.5 초벌은 3/10). + +## 6. 리소스 묶음 (2026-10-02 12시 기준) +- `icon_pack.py <폴더> ` → 1024 투명 · 여백 통일 · 종류 순 시트 · `index.json`(원본 추적) +- `moba_anfg/best_v4/` — 최상급 21장(PM 이 시트를 직접 확인: 금 + 적/청 + 은 배색으로 한 세트, 캐주얼하지 않음) +- `moba_anfg/final_v4/` — v4 회차(a13~a17) 합격본 93장. 종류별: 갑옷 13 · 장화 13 · 목걸이 10 · 지팡이 8 · 장갑 7 · 둔기 6 · 투척 6 · 망치 4 · 구슬 4 · 검 3 · 활 3 · 벨트 3 · 방패 3 · 토템 3 · 마법서 2 · 단검 1 · 도끼 1 · 투구 1 · 화살통 1 · 뿔피리 1 +- 아직 비어 있는 것: 반지 · 단검 · 도끼 · 검 · 방패 · 화살통(가는 날붙이와 고리 형태). FR 프로젝트 반입은 PD 승인 뒤. + +### 길잡이 자동 마련 (a15 뒤 추가) +- `icon_guide_bootstrap.py <종류> "<묘사>" [장수] [고를 수] ["부정어"]` — 기반 모델(LoRA 없음)이 글자로 그린 그림 중 자동 채점(물건 하나 · 여백 안 · 한 덩어리)을 통과한 것의 윤곽을 `shapes/<종류>__genmoba.png` 로 등록한다. 후보는 `moba_anfg/bootstrap/`. +- 2026-10-02 실측 통과: 도끼 3/10 · 투구 1/10 · 반지 1/10 · 뿔피리 4/10 · 구슬 5/10 · 활 0/10. (통과 = 자동 채점 기준일 뿐, 그 종류로 읽히는지는 생성 결과 검토에서 확인한다.) +- **새 종류를 뽑는 절차**: ① bootstrap 으로 길잡이 확보(안 되면 도형을 그리거나 아무 투명 PNG 를 `icon_shapes.add_from`) ② `TYPE_DESC` 에 묘사 한 줄 ③ lib 모드 생성 ④ 검토 → 합격본 등록. + +### 생성 설정 요약 (환경변수) +- `ANFG_TONE` = refined / rich / paint · `ANFG_REFINE` = 다듬기 세기 · `ANFG_UPSCALE` = model(4x-UltraSharp) / lanczos +- `ANFG_LORA2` = "FR_anfg_v4.safetensors:0.6" (0.8 은 글자만에서 나빠짐) · `ANFG_SEED` = 회차 시드 · `ANFG_ONLY` = 종류 · `ANFG_ROWS` = 행(종류-길잡이) +- 가는 무기(검 · 단검 · 도끼 · 활 · 지팡이 · 투척 · 둔기 · 망치)는 768 로 그리고 ControlNet 끝 0.7 (자동) + +### 게임 리소스로 쓸 만한 종류 (a11 검토 기준) +- 쓸 만함: 갑옷 · 목걸이 · 장화 · 장갑 · 투구 · 벨트 · 토템 · 마법서 · 구슬 · 반지 +- 조건부(장수 부족): 방패 · 뿔피리 · 화살통 · 둔기 · 망치 · 투척 +- 아직 아님: 검 · 단검 · 마법 단검 · 도끼 · 활 · 지팡이 · 보조 검(가는 무기) + +## 5. 형태 길잡이 모음 (a6 뒤 추가) +- `icon_shapes.py` → `moba_anfg/shapes/<종류>__<출처>.png` · 한눈에 보기 `shapes_sheet.png` +- 생성: `comfy_moba_anfg.py <폴더> <회차> 0.7 <시드 수> 512 1 lib 0.6 0.6` (굵은 선화 ControlNet 강도 0.6 · 끝 0.6). `ANFG_ONLY=staff,horn` 으로 종류를 고른다. `ANFG_SEED` 로 회차마다 시드 · 색 조합을 바꾼다. +- 새 종류를 뽑으려면: ① 길잡이 그림(투명 PNG 한 장 · 어디서 온 것이든 윤곽만 쓴다)을 `icon_shapes.add_from` 으로 더하거나 도형 함수를 추가 ② `TYPE_DESC` 에 묘사 한 줄. +- 목표: 종류별 합격본이 쌓이면 LoRA 가 형태를 배워 글자만으로도 나오게 한다(검증 = all 모드 합격률). diff --git a/공유/대화로그/FirstRising/2026-10-02.md b/공유/대화로그/FirstRising/2026-10-02.md new file mode 100644 index 0000000..ea8610f --- /dev/null +++ b/공유/대화로그/FirstRising/2026-10-02.md @@ -0,0 +1,43 @@ +# FirstRising 대화로그 — 2026-10-02 ~ 10-03 (BT49 장비 아이콘 생성 체계) + +## PD 지시 원문 (시간순 · 요지 그대로) +1. "우선 우리 게임의 장비 아이콘 리소스를 기준으로 moba풍으로 다시 칠하도록 해 … 합격 기준에 드는 것들을 통일감 있게 만들어. 그리고 나서 최종 결과물을 학습시켜" → 결과에 "퀄리티 좀 아쉬운데?" +2. "우선 아이템 시스템 구현한 내용 프로젝트 레포에 추가되어 있는지 확인해보고 푸시하도록 해." → 이미 `dc45353d72` 로 올라가 있음(로컬 = 원격). 새로 올린 것 없음. +3. (ANFG v3 예시 이미지) "내가 원하는 아트풍은 첨부한 아트풍인데, 우리 프로젝트의 원본 에셋이 너무 실사풍이라 마음에 들지 않는 것 같아" +4. "gameIconInstitute_v4XL.safetensors는 휴지통에 있을거야. 필요하면 다시 복원해도 돼" +5. (a1 시트에 동그라미 7장) "일부 이미지가 혼용된 것들이 있긴하지만 대체로 이전보다 좋아졌어. 이 방향으로 자율적으로 계속 디벨롭하고, 퀄리티를 높일 수 있도록 반복해줘." +6. "원하는 아이콘을 자유롭게 생성할 수 있을 때까지 아이콘 이미지 고도화 작업을 착수해줘. 필요할 경우 전담 세션을 새로 만들어서 … 에이전트를 구성하는 것도 고려" · "묻지말고 … 기준에 맞는지 검토해서 배경을 투명하게 … 리소스화" · "성과가 보일 경우, 나는 GPU를 업그레이드할 예정" +7. "최적의 결과물을 얻기 위한 적절한 프로세스나 방법은 네가 스스로 고안하고 … 목표는 원하는 장비 아이콘을 자유롭게 생성할 수 있는 수준에 도달할 때까지 이미지를 반복해서 생성하고, 완성 된 이미지를 모아 학습을 거듭해 우리 프로젝트에 유용한 자원을 생산할 수 있는 체계를 구축하는 것" +8. (a2 선별 시트) "이번에는 너무 캐주얼한 느낌이야." · (동그라미 8장) "일부 아이템은 아주 좋으나 여전히 퀄리티가 들쭉날쭉하고, 아트풍도 아직 맞춰지지 않은 느낌" +9. "이제부터 나는 10시간 동안 부재중 … 승인을 요구하기 위해 작업을 임의로 중단하지 말 것 · 자율적으로 목표에 도달할 때까지 멈추지 말고" +10. (10-03) "아이콘 리소스 제작 된 결과물 보여줘. 잘된것 몇가지만 추려서" +11. (10-03) "디자인 형태나 퀄리티 자체는 그럭저럭 나오는 것 같은데, 너무 붉은색, 푸른색과 같이 원색 계열만 쓰고 있어서 색감이 풍부하지 않고 퀄리티가 저급해보여. 개선할 방법이 없겠어? 아래 링크등에서 레퍼런스 이미지들을 찾아봐." (핀터레스트 → ArtStation "RPG Weapon Icons 02") +12. (10-03) "이 세션의 작업은 여기서 마무리하고, 추후 다시 진행하는걸로 하자. 우선 현재까지 작업 된 내용을 세션 공유해." + +## 결정 · 방법 (PM 이 고안 · 실측으로 채택/기각) +- 원본 에셋을 따라 칠하는 방식 폐기(실사풍이 따라옴) → `mobaGameEquipment_v10` + ANFG LoRA 0.7 조합. +- 글자만 생성은 형태가 안 잡힘 → **윤곽 길잡이**(굵은 선화 ControlNet). 길잡이 출처 = FR 원본 윤곽 · 직접 그린 도형 · 초벌 그림. +- 합격본으로 자체 LoRA 재학습 v1~v6. v4 채택(길잡이 6.5~7/10 · 글자만 4.5/10), v5 기각(글자만 후퇴). 재학습만으로는 글자만 생성이 좋아지지 않음(추세 없음). +- 정식 경로 = **글자 → SDXL 아이콘 모델 초벌 → 초벌을 눈으로 골라 길잡이 등록 → 본 생성**. 한 줄 명령 `icon_make.py`. 팔찌(새 종류) 6/6 · 석궁 0/6. +- 검토는 그림을 직접 보는 하위 에이전트(회차마다 1회)가 `picks_*.json` 을 쓰고, PM 은 묶음 시트만 직접 확인. +- 10-03 색 개선: 색 조합(금 + 적/청)을 버리고 **부위별 재질 + 작은 강조색**(`ANFG_PAL=parts`). 원색 문제를 푼 것은 LoRA 가 아니라 이 묘사 방식. v6(재질색 합격본만 학습)는 v4 대비 차이가 작음. + +## 결과 (2026-10-03 세션 종료 시점) +- 회차 a1~a28 · 자체 LoRA v1~v6 · 데이터셋 462장(`moba_anfg/dataset.json`). +- 리소스 후보: **색 개선 최상급 32장(21종)** `moba_anfg/best_color/` · 예전 색(금 + 적/청) 최상급 46장 `best_v4e/` · 합격본 166장 `final_v4e/`(로컬). 모두 투명 배경 1024 · 여백 통일. +- 종류별 상태: 쓸 만함 13종 / 조건부 7종(망치 · 화살통 · 검 · 마법서 · 단검 · 활 · 도끼) / 아직 아님(뿔피리 · 석궁류). +- FR 프로젝트 반입 없음. FR 레포 변경 없음. + +## PM 실수 · 바로잡은 것 +- v1 학습 캡션 3건이 다른 회차 묘사로 붙음 → 회차별 표로 고침. +- v3: 화면을 꽉 채운 학습 그림 탓에 글자만 생성이 "금속 원반"으로 무너짐 → 여백 · 종류 상한 · 구도 캡션(v4~). +- a7 뒤 합격률을 올리려 색 조합을 금 + 적/청 넷으로 좁힘 → PD 가 "원색만 · 저급" 지적(10-03). 재질 방식으로 바꿈. +- 최상급 30종 시트를 직접 확인하지 않고 보냄 → 검토가 7장을 "부끄러운 수준"으로 제외. 이후 묶음 시트는 PM 이 직접 확인 후 보냄. +- a26 을 별도 프로세스로 띄웠다고 보고했으나 실제로는 실행되지 않음(스크립트의 한글 경로 깨짐) → 10분 공백 뒤 정정 보고. + +## 남은 이슈 · 결정 대기 +1. **색 개선 방향 확인**(`best_color/final_sheet.png`) — PD 답 없음. 다음 세션은 이 방향으로 이어가되 PD 확인을 먼저 받는다. +2. 레퍼런스와 남은 차이(검토 6/10): 손그림 질감(흠집 · 나뭇결 · 바느질) · 한 물건 안의 재질 수와 강조 종류(끈 · 천 · 깃털 · 룬 빛) · 형태 설계(망치/도끼/지팡이 단순 · 검 날밑 위치 · 장갑 발톱). +3. v6 를 0.5 로 쓰는 것은 미검증. 가늘고 복잡한 형태(뿔피리 · 석궁)는 미해결 — SDXL 계열 전환이 후보(GPU 업그레이드 뒤). +4. FR 반입(아이콘 번호 · 크기 규격) · 등급 10단계 색 변형 세트는 PD 지시 뒤. +5. 쓰이지 않게 된 것(삭제는 PD 지시 시): `아이템/run_a26.ps1` · 예전 방식 스크립트(`comfy_moba_repaint*.py` · `comfy_moba_lora_*.py`) · LoRA `FR_moba_v1` 데이터셋 폴더 · `C:\Comfyui\_removed_models\giI_anfg_v3_000018.safetensors`(같은 파일이 loras 폴더에 복사돼 쓰이는 중). diff --git a/공유/대화로그/FirstRising/2026-10-03_세션인수인계.md b/공유/대화로그/FirstRising/2026-10-03_세션인수인계.md new file mode 100644 index 0000000..c053098 --- /dev/null +++ b/공유/대화로그/FirstRising/2026-10-03_세션인수인계.md @@ -0,0 +1,38 @@ +# 세션 인수인계 — 2026-10-03 (BT49 장비 아이콘 생성 체계) + +## 다음 세션 첫 프롬프트 (그대로 붙여 넣기) +``` +FR 장비 아이콘 생성 작업(BT49)을 이어서 진행한다. +먼저 읽을 문서: 공유/기획/FirstRising/아이템/아이콘_생성_체계.md (특히 "7. 색 개선"과 "결론" 절) +그다음: 공유/대화로그/FirstRising/2026-10-03_세션인수인계.md +지킬 것: 커밋 · push 는 PD 지시 시만 / 생성물은 조직 레포 검토 폴더에만(FR 반입은 PD 승인 뒤) / 파일 삭제는 PD 지시 시만 / +그림 검토는 하위 에이전트에 맡기고 PM 은 묶음 시트만 직접 확인 / 백그라운드 명령은 약 1시간에서 끊기므로 한 회차 40장 안팎 / +허위 · 추정 단정 금지(본 것 · 검토 판정 · 미검증을 구분). +먼저 PD 에게 색 개선 최상급 시트(moba_anfg/best_color/final_sheet.png)의 방향 확인을 받고 시작한다. +``` + +## 이번에 열 문서 (이것만) +| 문서 | 볼 곳 | +|---|---| +| `공유/기획/FirstRising/아이템/아이콘_생성_체계.md` | 1(합격 기준 — 색 기준은 7절로 대체) · 2(반복 순서) · 7(색 개선) · 결론 · 설정 요약 | +| `공유/대화로그/FirstRising/2026-10-02.md` | PD 지시 원문 · PM 실수 · 남은 이슈 | + +## 현재 상태 +- **되는 방식**: `mobaGameEquipment_v10` + ANFG LoRA 0.7 + 자체 LoRA(v6 0.6 또는 v4 0.3 — 차이 작음) + 윤곽 길잡이 + `ANFG_PAL=parts`(부위별 재질 + 작은 강조색) + `ANFG_TONE=paint` + UltraSharp + 다듬기 0.45. +- **한 회차 명령 예**(PowerShell · 작업 폴더 `공유/기획/FirstRising/아이템`): + `$env:ANFG_TONE='paint'; $env:ANFG_UPSCALE='model'; $env:ANFG_REFINE='0.45'; $env:ANFG_PAL='parts'; $env:ANFG_LORA2='FR_anfg_v6.safetensors:0.6'; $env:ANFG_SEED='<새 숫자>'; $env:ANFG_ROWS='<행들>'; python comfy_moba_anfg.py <회차> "0.7" 2 512 1 lib 0.6 0.5; python icon_review_sheet.py <회차> 10` + → 검토 에이전트 → `icon_dataset.py add` → `icon_pack.py` +- **검증된 길잡이(행 이름)**: 체계 문서 "리소스 묶음 (a23 뒤)" 항목의 목록 + a26/a27 에서 쓴 41행(`a27_review_*.png` 왼쪽 이름). +- **결과물**: `moba_anfg/best_color/`(색 개선 최상급 32장 · 커밋됨) · `best_v4e/`(예전 색 46장 · 커밋됨) · 나머지 생성 원본 · 데이터셋 그림 · 초벌 · 길잡이 그림(약 2.1 GB)은 **이 PC 의 `E:\BurningTimes\공유\기획\FirstRising\아이템\moba_anfg\` 에만 있다(용량 때문에 커밋하지 않음)**. +- **이 PC 에만 있는 것**: ComfyUI(`C:\Comfyui` · Comfy Desktop · 127.0.0.1:8000) · 체크포인트 `mobaGameEquipment_v10` · `gameIconInstitute_v4XL` · LoRA `giI_anfg_v3_000018` · `FR_anfg_v1~v6` · ControlNet lineart · `4x-UltraSharp`. 다른 PC 에서는 이어 갈 수 없다. + +## 미검증 · 결정 대기 +1. PD 의 색 방향 확인(best_color 시트) — 답 없음. +2. v6 0.5(군더더기 줄이기) 미검증. 질감 · 강조 다양성 낱말 보강 회차 미착수. +3. FR 반입 · 등급 10단계 색 변형 · SDXL 전환(GPU 업그레이드 뒤)은 PD 지시 대기. +4. BT47/48(아이템 드랍 시스템)의 보류 항목은 `2026-10-01_세션인수인계.md` 그대로(이번 세션에서 변경 없음 · FR `bt/work` = `dc45353d72`). + +## 쓰이지 않게 된 파일 (삭제는 PD 지시 시) +- `공유/기획/FirstRising/아이템/run_a26.ps1`(실행되지 않은 스크립트) +- `comfy_moba_repaint.py` · `comfy_moba_repaint_hq.py` · `comfy_moba_lora_train.py` · `comfy_moba_lora_test.py`(원본을 따라 칠하는 폐기된 방식 — 단 `comfy_moba_repaint.py` 는 생성 스크립트가 통신 함수를 빌려 쓰므로 지우면 안 된다) +- `C:\Comfyui\_removed_models\giI_anfg_v3_000018.safetensors`(loras 폴더에 사본이 쓰이는 중) · `C:\Comfyui\input\fr_moba_v1`, `fr_anfg_v1~v6`(학습 입력 사본)