![]() |
發佈時間: 2025-7-15 13:53
正文摘要:.copy {border: 3px dotted #0000FF;padding-right: 10px;} 本文轉貼來源&作者 (Copying Published Source) https://forum.gamer.com.tw/C.php?bsn=79354&snA=5740&tnum=5 《Artale楓之谷世界》造型解包懶人包 📂 看到別人超炫的造型,絕版了買不到好想要?這篇教你當個數位考古學家! 🎯 核心目標: 把你在遊戲裡看過的任何玩家造型,從電腦的暫存檔裡「挖」出來,變成一張張的 PNG 圖檔!🗺️ 神秘路徑: 造型都藏在 C:\Users\你的使用者名稱\AppData\LocalLow\nexon\MapleStory Worlds\resource_cache\ugc\ 這個資料夾裡。⚙️ 解包神器: 提供兩種自動化腳本(BAT 或 Python),選一個你喜歡的,一鍵就能把 .mod 檔案解成圖片。💡 效率神技: 檔案太多像大海撈針?先把 ugc 資料夾清空,再去人多的地圖或組隊頻逛一圈,想要的熱門造型就自動下載到你家啦! 想把自己在《Artale楓之谷世界》中看過的酷炫造型保存下來嗎?或是想研究一下其他玩家的造型是怎麼搭配的?其實,遊戲為了讀取速度,會把你看到的所有素材(包括地圖、玩家造型)都暫存在你的電腦裡。這篇攻略將帶你一步一步學習如何從這些暫存檔中,將喜歡的造型解包出來,變成可以收藏的 PNG 圖片! 接著,你可以選擇使用下面提供的其中一種自動化腳本來處理這些檔案。此外,社群上也有流傳一些現成的工具,例如: CopyPng.exe 下載連結: https://pixeldrain.com/u/541GeuWV 造型解包腳本教學 (二選一) 這裡提供兩種不同的自動化腳本,一種是簡單的批次檔(.bat),另一種是需要 Python 環境的腳本(.py)。兩種都能達到一樣的效果,可以根據自己的情況選擇。 操作前的重要提醒: 建議先把整個 ugc 資料夾完整複製到一個新的、乾淨的資料夾(例如桌面上的「楓谷造型解包」資料夾),然後在那個新資料夾裡進行以下操作,避免動到原始快取。檔案數量可能非常龐大,解包會需要一些時間,建議在電腦空閒時執行。部分防毒軟體可能會誤判腳本,如果執行失敗,可以嘗試暫時關閉防毒軟體或將其設定為信任。 方法一:使用 BAT 批次檔 (適合無程式背景玩家) 在你剛剛建立的新資料夾(裡面已經放了複製過來的 ugc 資料夾內容)中,按右鍵新增一個「文字文件」。打開這個文字文件,將底下框框中的所有程式碼完整複製並貼上。[url=home.php?mod=space&uid=503431]@Echo[/url] off chcp 65001 setlocal enabledelayedexpansion :: 建立主資料夾 set "base_output=%~dp0extracted_pngs" if not exist "%base_output%" ( mkdir "%base_output%" ) :: 處理所有 .win.mod 檔案 for /r %%f in (*.win.mod) do ( set "filepath=%%f" set "filename=%%~nxf" set "nameonly=%%~nf" set "temp_folder=%base_output%\__temp_extract__" if not exist "!temp_folder!" ( mkdir "!temp_folder!" ) echo 正在掃描:!filename! powershell -nologo -noprofile -command ^ "$bytes = [System.IO.File]::ReadAllBytes('%%f');" ^ "$sig = [byte[]](0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A);" ^ "$offset = 0; $count = 0; $pngs = @();" ^ "while ($offset -lt $bytes.Length) {" ^ "$start = [Array]::IndexOf($bytes, $sig[0], $offset);" ^ "if ($start -eq -1) { break }" ^ "$isMatch = $true;" ^ "for ($i = 0; $i -lt $sig.Length; $i++) { if ($bytes[$start + $i] -ne $sig[$i]) { $isMatch = $false; break } }" ^ "if (-not $isMatch) { $offset = $start + 1; continue }" ^ "$iendStr = [System.Text.Encoding]::ASCII.GetBytes('IEND');" ^ "$iendPos = [Array]::IndexOf($bytes, $iendStr[0], $start);" ^ "while ($iendPos -ne -1) {" ^ "$isIEND = $true;" ^ "for ($j = 0; $j -lt 4; $j++) { if ($bytes[$iendPos + $j] -ne $iendStr[$j]) { $isIEND = $false; break } }" ^ "if ($isIEND) { break }" ^ "$iendPos = [Array]::IndexOf($bytes, $iendStr[0], $iendPos + 1);" ^ "}" ^ "if ($iendPos -eq -1) { break }" ^ "$end = $iendPos + 8;" ^ "if ($end -gt $bytes.Length) { break }" ^ "$png = $bytes[$start..($end - 1)];" ^ "$pngs += ,$png;" ^ "$offset = $end;" ^ "}" ^ "if ($pngs.Count -gt 1) {" ^ "$folder = '%base_output%\%%~nf.images'; if (-not (Test-Path $folder)) { New-Item -ItemType Directory -Path $folder | Out-Null };" ^ "for ($k = 0; $k -lt $pngs.Count; $k++) {" ^ "$ts = Get-Date -Format 'yyyyMMdd_HHmmss_fff';" ^ "$outFile = Join-Path $folder ($ts + '_image' + $k + '.png');" ^ "[System.IO.File]::WriteAllBytes($outFile, $pngs[$k]);" ^ "}" ^ "echo → 已儲存 !filename! 共 $($pngs.Count) 張圖片。" ^ "} else {" ^ "echo → 略過 !filename!(只有一張圖片)" ^ "}" ) echo 所有符合條件的檔案已處理完畢。 pause複製代碼存檔後,將這個文字文件的副檔名從「.txt」改成「.bat」(例如:解包.bat)。如果看不到副檔名,請到資料夾選項中開啟顯示副檔名。直接點兩下執行這個 .bat 檔案,它就會開始自動掃描並解包了!完成後,圖片會被存放在一個名為「extracted_pngs」的新資料夾中。 方法二:使用 Python 腳本 (需有 Python 環境) 如果你對程式稍有了解,且電腦已安裝 Python 環境,也可以使用這個更有效率的腳本。 同樣,在放滿 .mod 檔的新資料夾中,建立一個新檔案。將底下框框中的 Python 程式碼完整複製並貼上。import os from pathlib import Path from datetime import datetime from PIL import Image from io import BytesIO # 設定根目錄 base_dir = Path(__file__).resolve().parent output_multi_root = base_dir / "extracted_pngs" output_multi_root.mkdir(exist_ok=True) # PNG 標記 PNG_SIGNATURE = b"\x89PNG\r\n\x1a\n" IEND_SIGNATURE = b"IEND" SIZE_LIMIT = 512 def extract_pngs_from_file(file_path): with open(file_path, "rb") as f: data = f.read() pngs = [] offset = 0 while offset < len(data): start = data.find(PNG_SIGNATURE, offset) if start == -1: break end = data.find(IEND_SIGNATURE, start) if end == -1: break end += 8 # 'IEND' (4 bytes) + CRC (4 bytes) if end > len(data): break png_data = data[start:end] pngs.append(png_data) offset = end return pngs # 掃描所有 .win.mod 檔 for mod_file in base_dir.rglob("*.win.mod"): pngs = extract_pngs_from_file(mod_file) if len(pngs) > 1: out_folder = output_multi_root / (mod_file.stem + ".images") out_folder.mkdir(parents=True, exist_ok=True) for i, png in enumerate(pngs): ts = datetime.now().strftime("%Y%m%d_%H%M%S_%f") out_file = out_folder / f"{ts}_image{i}.png" with open(out_file, "wb") as f: f.write(png) print(f"✔ 多圖:{mod_file.name} -> {len(pngs)} 張") elif len(pngs) == 1: try: img = Image.open(BytesIO(pngs[0])) width, height = img.size if width == 512 and height == 512: # 特例:裝備圖或素材圖也當作多圖處理 out_folder = output_multi_root / (mod_file.stem + ".images") out_folder.mkdir(parents=True, exist_ok=True) ts = datetime.now().strftime("%Y%m%d_%H%M%S_%f") out_file = out_folder / f"{ts}_image0.png" with open(out_file, "wb") as f: f.write(pngs[0]) print(f" 例外處理:{mod_file.name}(512x512)") else: print(f"→ 單圖:{mod_file.name},已略過") except Exception as e: print(f" 無法判斷尺寸,略過:{mod_file.name},錯誤:{e}") continue print(" 所有可提取檔案已處理完成")複製代碼將檔案儲存,並命名為副檔名是「.py」的檔案(例如:解包.py)。執行這個 Python 腳本,它就會開始處理檔案,解出的圖片同樣會放在「extracted_pngs」資料夾。 進階技巧與解說 如何快速找到想要的造型? 快取資料夾玩久了會變得非常肥大,幾千個檔案撈起來很痛苦。有個聰明的方法:先把 ugc 資料夾裡的舊檔案全部移走或刪除(等於淨空快取),然後上線去人多的地圖(如自由市場、組隊頻道)逛一逛,或是在創作者商店點開你想找的造型。這時遊戲會重新下載你看到的造型,你的 ugc 資料夾裡就會出現最新的熱門造型檔案,省去大海撈針的麻煩!關於解包後的圖片拼接 (Atlas Spritesheet) 有些玩家會發現解出來的圖檔是一塊一塊的,沒辦法直接用。這是因為遊戲採用了「Atlas Spritesheet」技術,把一個完整動作(例如走路)拆成很多小圖,再拼成一張大圖集以節省空間。要還原成可用的動圖,需要: 1. 讀取每張小圖的裁切座標資料。 2. 讀取每張小圖的對位點(origin)座標。 3. 將小圖按照座標精準地對齊。 這個過程用手動對齊會非常耗時耗力,而且對不準的話,人物就會看起來在抖動或浮空。這需要更專業的圖像處理知識。 以下廣告滑動後還有帖子內容var custom_call_MIR = function (params) {if ( params === null || params.hasAd === false ) {var divRowSide;for (let index = 0; index < ONEADs.length; index++) {if (ONEADs[index].pub.player_mode === "mobile-inread") {divRowSide = ONEADs[index].pub.slotobj;}}var ins = document.createElement('ins');ins.className = 'clickforceads';ins.setAttribute('style', 'display:inline-block;');ins.setAttribute('data-ad-zone', '18264');divRowSide.appendChild(ins);var js = document.createElement('script');js.async = true;js.type = 'text/javascript';js.setAttribute('src', '//cdn.holmesmind.com/js/init.js');js.onload = function(){console.log('[ONEAD MIR] ClickForce Loaded');};divRowSide.appendChild(js);}};var _ONEAD = {};_ONEAD.pub = {};_ONEAD.pub.slotobj = document.getElementById("oneadMIRDFPTag");_ONEAD.pub.slots = ["div-onead-ad"];_ONEAD.pub.uid = "1000509";_ONEAD.pub.external_url = "https://onead.onevision.com.tw/";_ONEAD.pub.scopes = ["spotbuy", "speed"];_ONEAD.pub.player_mode_div = "div-onead-ad";_ONEAD.pub.player_mode = "mobile-inread";_ONEAD.pub.queryAdCallback = custom_call_MIR;var ONEAD_pubs = ONEAD_pubs || [];ONEAD_pubs.push(_ONEAD);var truvidScript = document.createElement('script'); truvidScript.async = true; truvidScript.setAttribute('data-cfasync','false'); truvidScript.type = 'text/javascript'; truvidScript.src = '//stg.truvidplayer.com/index.php?sub_user_id=597&widget_id=3309&playlist_id=2381&m=a&cb=' + (Math.random() * 10000000000000000); var currentScript = document.currentScript || document.scripts[document.scripts.length - 1]; currentScript.parentNode.insertBefore(truvidScript, currentScript.nextSibling); 楓之谷世界造型解包_常見問題Q&A Q:為什麼我解出來的造型圖片不完整,只有部分動作的圖? A:這可能是因為你看到的角色當下只做了那幾個動作,所以遊戲快取也只存了那幾個動作的圖檔。另一個可能是該造型採用了 Atlas Spritesheet 技術,完整的動作被分散在不同的小圖中,需要進一步拼接。 Q:腳本為什麼會「略過只有一張圖片」的檔案? A:這個腳本的設計初衷是為了提取「角色造型」,而角色造型通常由多個動作圖檔組成。單張圖片的檔案很大部分是遊戲的介面圖示(ICON)、單張的特效圖、背景物件或是一些素材拼圖,這些通常不是玩家想找的造型本體,所以腳本會自動過濾掉以節省時間和空間。 Q:公布這個方法會傷害到原創繪師嗎? A:根據原文討論區的玩家看法,多數人認為在官方缺乏有效防盜機制的情況下,這類工具對「利用資訊不對稱來轉賣盜版圖檔的商人」傷害最大。讓提取方法透明化,反而能減少這些中盤商的獲利空間。但無論如何,我們都應該尊重每一位繪師的心血,有能力的話請務必支持正版創作。 Q:解包出來的圖檔要怎麼「摳圖」或編輯成自己想要的樣子? A:這需要使用圖像處理軟體,例如 Photoshop 或一些免費的替代軟體(如 GIMP、Photopea)。關鍵是要學會「圖層」和「剪貼」等基本概念。你可以在 YouTube 上搜尋「Photoshop 基礎教學」等關鍵字找到很多入門資源。 Q:如何找到特定作者的造型?或是用ID搜尋? A:目前的解包方式是基於你「看到過」的造型快取,無法直接透過作者ID或名稱去搜尋。所有檔案都是以亂碼命名,需要玩家自行在解出的圖片中辨識。 參考資料 原文討論來源: https://forum.gamer.com.tw/C.php?bsn=79354&snA=5740&tnum=5 |