diff --git a/www/js/plugins.js b/www/js/plugins.js index 2cd636a..1379e95 100644 --- a/www/js/plugins.js +++ b/www/js/plugins.js @@ -634,5 +634,5 @@ var $plugins = [ { name: "JsScript35Set", status: true, description: "", parameters: {} }, { name: "JsScript1Set", status: false, description: "", parameters: {} }, { name: "JsScript146Set", status: true, description: "", parameters: {} }, - { name: "DazedDataReload", status: true, description: "[Dazed] F5 hot-reload PSData/RDData/GameSetting + refresh mail cache", parameters: {} }, + { name: "DazedDataReload", status: true, description: "[Dazed] F9 hot-reload data + refresh mail/addresses in saves", parameters: {} }, ]; diff --git a/www/js/plugins/DazedDataReload.js b/www/js/plugins/DazedDataReload.js index 0fc273d..ea243b3 100644 --- a/www/js/plugins/DazedDataReload.js +++ b/www/js/plugins/DazedDataReload.js @@ -1,5 +1,5 @@ /*: - * @plugindesc [Dazed Translations] Hot-reload PSData/RDData/GameSetting JSON and refresh cached save data. Press F5 in-game. + * @plugindesc [Dazed Translations] Hot-reload data files and refresh cached save data. Press F9 in-game. * @author DazedTranslations * * @help @@ -7,7 +7,12 @@ * 1. Reload Nupu_PSData.json, RdData.json, and Nupu_GameSetting.json from disk * 2. Refresh all mail text in $gameSystem.AllMailList from updated PSData * 3. Reset the MemoryDatas cache so it rebuilds from updated PSData - * 4. Show a confirmation message on screen + * 4. Scan all Map/CommonEvent data for AddAddress calls and update saved addresses + * 5. Show a confirmation message on screen + * + * Console utilities (open dev console with F12): + * DazedClearComments() - Clears old comments from save (they'll re-add in English as you play) + * DazedClearBBS() - Clears old BBS posts from save * * This allows translation changes to take effect on existing saves * without starting a new game or restarting the application. @@ -51,12 +56,9 @@ for (var j = 0; j < $Nupu_PSData.MailDatas.length; j++) { var srcMail = $Nupu_PSData.MailDatas[j]; if (srcMail.No === savedMail.ToolNo) { - // Update translatable text fields savedMail.ChrStr = srcMail.Name; savedMail.MTitle = srcMail.Title; savedMail.MNaiyo = srcMail.MailText; - - // Update picture descriptions if present if (srcMail.PicDatas && savedMail.PicData) { for (var k = 0; k < srcMail.PicDatas.length && k < savedMail.PicData.length; k++) { savedMail.PicData[k].PicDesc = srcMail.PicDatas[k].PicDesc; @@ -74,27 +76,192 @@ // 3. Reset MemoryDatas cache so it rebuilds from fresh PSData // ========================================================================= function resetMemoryCache() { - // MemoryDatas is a module-level var in JsScript122Set.js - // Setting it to null forces SetMemoryDatas() to rebuild it if (typeof MemoryDatas !== 'undefined') { MemoryDatas = null; } } // ========================================================================= - // 4. Show on-screen notification + // 4. Scan event data for AddAddress calls and refresh saved addresses // ========================================================================= - function showReloadNotification(mailCount) { - var msg = '[DazedTranslations] Data reloaded!'; - if (mailCount > 0) { - msg += ' Updated ' + mailCount + ' mail(s) in save.'; + function padZero(n, digits) { + var s = String(n); + while (s.length < digits) s = '0' + s; + return s; + } + + function loadFileTextSync(url) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.overrideMimeType('application/json'); + try { + xhr.send(); + if (xhr.status < 400) return xhr.responseText; + } catch (e) {} + return null; + } + + // Extract script blocks from event command lists (code 355 starts, 655 continues) + function getScriptBlocks(list) { + var blocks = []; + var current = null; + for (var i = 0; i < list.length; i++) { + var cmd = list[i]; + if (cmd.code === 355) { + if (current !== null) blocks.push(current); + current = cmd.parameters[0]; + } else if (cmd.code === 655 && current !== null) { + current += '\n' + cmd.parameters[0]; + } else { + if (current !== null) blocks.push(current); + current = null; + } } - // Use the map's display message if available - if (typeof SceneManager._scene !== 'undefined' && SceneManager._scene._mapNameWindow) { - // Fallback: just use console + a brief window text + if (current !== null) blocks.push(current); + return blocks; + } + + // Extract AddAddress calls from script blocks + function extractAddressFromScripts(scripts, addressMap) { + for (var i = 0; i < scripts.length; i++) { + var match = scripts[i].match(/AddAddress\(\s*(\d+)\s*,\s*"([^"]+)"\s*,\s*"([^"]+)"/); + if (match) { + var viewNo = parseInt(match[1]); + var name = match[2]; + var picName = match[3]; + // Key by viewNo + picName to handle slot reuse for different characters + var key = viewNo + '|' + picName; + addressMap[key] = { viewNo: viewNo, name: name, picName: picName }; + } } + } + + // Scan a single event list + function scanEventCommands(list, addressMap) { + if (!list) return; + var scripts = getScriptBlocks(list); + extractAddressFromScripts(scripts, addressMap); + } + + // Scan all events in a parsed map + function scanMapData(mapData, addressMap) { + if (!mapData || !mapData.events) return; + for (var i = 0; i < mapData.events.length; i++) { + var ev = mapData.events[i]; + if (!ev || !ev.pages) continue; + for (var j = 0; j < ev.pages.length; j++) { + if (ev.pages[j] && ev.pages[j].list) { + scanEventCommands(ev.pages[j].list, addressMap); + } + } + } + } + + // Scan CommonEvents + function scanCommonEvents(ceData, addressMap) { + if (!ceData) return; + for (var i = 0; i < ceData.length; i++) { + if (ceData[i] && ceData[i].list) { + scanEventCommands(ceData[i].list, addressMap); + } + } + } + + // Main scan: load all map files + CommonEvents and extract AddAddress calls + function scanAllAddressCalls() { + var addressMap = {}; + console.log('[DazedTranslations] Scanning event data for AddAddress calls...'); + + // Scan CommonEvents (already loaded in memory, but reload fresh from disk) + var ceText = loadFileTextSync('data/CommonEvents.json'); + if (ceText) { + // Quick check before expensive parse + if (ceText.indexOf('AddAddress') !== -1) { + var ceData = JSON.parse(ceText); + scanCommonEvents(ceData, addressMap); + } + } + + // Scan all maps + if ($dataMapInfos) { + for (var i = 1; i < $dataMapInfos.length; i++) { + if (!$dataMapInfos[i]) continue; + var filename = 'data/Map' + padZero(i, 3) + '.json'; + var mapText = loadFileTextSync(filename); + if (mapText && mapText.indexOf('AddAddress') !== -1) { + try { + var mapData = JSON.parse(mapText); + scanMapData(mapData, addressMap); + } catch (e) { + console.log('[DazedTranslations] Failed to parse ' + filename); + } + } + } + } + + var count = Object.keys(addressMap).length; + console.log('[DazedTranslations] Found ' + count + ' unique AddAddress entries'); + return addressMap; + } + + // Apply address updates to saved data + function refreshAddresses(addressMap) { + if (!$gameSystem || !$gameSystem.AddressList) return 0; + var updated = 0; + for (var i = 0; i < $gameSystem.AddressList.length; i++) { + var addr = $gameSystem.AddressList[i]; + var key = addr._ViewNo + '|' + addr._PicName; + if (addressMap[key]) { + var newName = addressMap[key].name; + if (addr._Name !== newName) { + console.log('[DazedTranslations] Address: "' + addr._Name + '" -> "' + newName + '"'); + addr._Name = newName; + updated++; + } + } + } + return updated; + } + + // ========================================================================= + // 5. Console utilities for comments/BBS (can't auto-match without IDs) + // ========================================================================= + window.DazedClearComments = function() { + if (!$gameSystem || !$gameSystem.SComeArr) { + console.log('[DazedTranslations] No save loaded.'); + return; + } + var count = $gameSystem.SComeArr.length; + $gameSystem.SComeArr = []; + console.log('[DazedTranslations] Cleared ' + count + ' comments from save.'); + console.log('[DazedTranslations] New comments will appear in English as you play.'); + }; + + window.DazedClearBBS = function() { + if (!$gameSystem || !$gameSystem.SBbsArr) { + console.log('[DazedTranslations] No save loaded.'); + return; + } + var count = $gameSystem.SBbsArr.length; + $gameSystem.SBbsArr = []; + console.log('[DazedTranslations] Cleared ' + count + ' BBS posts from save.'); + }; + + // ========================================================================= + // 6. Show on-screen notification + // ========================================================================= + function showReloadNotification(stats) { + var lines = ['[DazedTranslations] Data reloaded!']; + if (stats.mail > 0) lines.push('Mail: ' + stats.mail + ' updated'); + if (stats.addresses > 0) lines.push('Addresses: ' + stats.addresses + ' updated'); + var msg = lines.join(' | '); + console.log(msg); - // Show a brief HUD message using a sprite + if ($gameSystem && $gameSystem.SComeArr && $gameSystem.SComeArr.length > 0) { + console.log('[DazedTranslations] Note: ' + $gameSystem.SComeArr.length + + ' comments in save cannot be auto-updated. Use DazedClearComments() in console to clear them.'); + } + var scene = SceneManager._scene; if (scene) { var sprite = new Sprite(new Bitmap(Graphics.width, 40)); @@ -107,11 +274,10 @@ sprite.opacity = 255; scene.addChild(sprite); - // Fade out after 3 seconds var frames = 0; var fadeInterval = setInterval(function() { frames++; - if (frames > 180) { // 3 seconds at 60fps + if (frames > 180) { sprite.opacity -= 5; if (sprite.opacity <= 0) { scene.removeChild(sprite); @@ -123,29 +289,33 @@ } // ========================================================================= - // 5. Main reload function + // 7. Main reload function // ========================================================================= function performDataReload() { - console.log('[DazedTranslations] Reloading data files...'); + console.log('[DazedTranslations] === Starting full data reload ==='); - // Reload all three data files + // Reload JSON data files var ok1 = reloadDataFile('$Nupu_PSData', 'Nupu_PSData.json'); var ok2 = reloadDataFile('$RDData', 'RdData.json'); var ok3 = reloadDataFile('$Nupu_GameSetting', 'Nupu_GameSetting.json'); - console.log('[DazedTranslations] PSData: ' + (ok1 ? 'OK' : 'FAIL') + ', RDData: ' + (ok2 ? 'OK' : 'FAIL') + ', GameSetting: ' + (ok3 ? 'OK' : 'FAIL')); - // Refresh cached data in save + // Refresh cached data var mailCount = refreshMailData(); resetMemoryCache(); - showReloadNotification(mailCount); + // Scan and refresh addresses + var addressMap = scanAllAddressCalls(); + var addrCount = refreshAddresses(addressMap); + + showReloadNotification({ mail: mailCount, addresses: addrCount }); + console.log('[DazedTranslations] === Reload complete ==='); } // ========================================================================= - // 6. Hook into the key input system + // 8. Hook into the key input system // ========================================================================= var _SceneManager_onKeyDown = SceneManager.onKeyDown; SceneManager.onKeyDown = function(event) {