diff --git a/modules/csv.py b/modules/csv.py index 2f1b8bb..4108bba 100644 --- a/modules/csv.py +++ b/modules/csv.py @@ -43,6 +43,7 @@ BRFLAG = False # If the game uses
instead FIXTEXTWRAP = True # Overwrites textwrap IGNORETLTEXT = True # Ignores all translated text. MISMATCH = [] # Lists files that thdata a mismatch error (Length of GPT list response is wrong) +FILENAME = None BRACKETNAMES = False # Regex - Need to change this if you want to translate from/to other languages. Default is Japanese Regex @@ -93,8 +94,9 @@ TRANSLATION_CONFIG = TranslationConfig( LEAVE = False def handleCSV(filename, estimate): - global ESTIMATE, TOKENS + global ESTIMATE, TOKENS, FILENAME ESTIMATE = estimate + FILENAME = filename if not ESTIMATE: with open("translated/" + filename, "w+t", newline="", encoding=ENCODING, errors="xmlcharrefreplace") as writeFile: @@ -201,11 +203,11 @@ def parseCSV(readFile, writeFile, filename): totalLines = len(readFile.readlines()) readFile.seek(0) - reader = csv.reader(readFile, delimiter="\t") + reader = csv.reader(readFile, delimiter=",") if not ESTIMATE: writer = csv.writer( writeFile, - delimiter="\t", + delimiter=",", ) else: writer = "" @@ -307,7 +309,7 @@ def translateCSV(data, pbar, writer, filename, translatedList, format): # In Place Format case "3": # Set columns to translate. Leave empty to translate all. - targetColumns = [0] + targetColumns = [1] # False - Place translation in source column # True - Place translation in next column @@ -322,13 +324,48 @@ def translateCSV(data, pbar, writer, filename, translatedList, format): if j in targetColumns and data[i][j]: # Check if Translated jaString = data[i][j] + speaker = "" + vo = "" + + if ':name' in jaString: + match = re.search(r":name\[([^\]]+?)\]\n([\w\W]*)", jaString) + if match: + # TL Speaker + response = getSpeaker(match.group(1)) + speaker = response[0] + totalTokens[0] += response[1][0] + totalTokens[1] += response[1][1] + data[i][j] = data[i][j].replace(match.group(1), speaker) + + # TL Text + jaString = match.group(2) + voMatch = re.search(r"\\[vfF]+\[.+]", jaString) + if voMatch: + vo = voMatch.group(0) + jaString = jaString.replace(vo, "") + jaString = jaString.replace(vo, "") + elif '\\M' in jaString: + match = re.search(r"\\M.+\n([\w\W]*)", jaString) + if match: + jaString = match.group(1) + voMatch = re.search(r"\\[vfF]+\[.+]", jaString) + if voMatch: + vo = voMatch.group(0) + jaString = jaString.replace(vo, "") + elif 'comment' in data[i][0]: + # Skip comments + continue # Remove Textwrap + ojaString = jaString jaString = jaString.replace("\n", " ") # Pass 1 if not translatedList: - stringList.append(jaString) + if speaker: + stringList.append(f"[{speaker}]: {jaString}") + else: + stringList.append(jaString) # Pass 2 else: @@ -336,14 +373,18 @@ def translateCSV(data, pbar, writer, filename, translatedList, format): translatedText = translatedList[0] translatedList.pop(0) + # Remove speaker + if speaker: + translatedText = re.sub(r"^\[?(.+?)\]?\s?[|:]\s?", "", translatedText) + # Add Wordwrap translatedText = dazedwrap.wrapText(translatedText, WIDTH) # Set Data if targetNextRow: - data[i][j + 1] = translatedText + data[i][j + 1] = data[i][j + 1].replace(ojaString, f"{translatedText}") else: - data[i][j] = translatedText + data[i][j] = data[i][j].replace(ojaString, f"{translatedText}") # Iterate i += 1 @@ -388,10 +429,6 @@ def translateCSV(data, pbar, writer, filename, translatedList, format): translatedText = translatedList[0] translatedList.pop(0) - # Remove speaker - if speaker: - translatedText = re.sub(r"^\[?(.+?)\]?\s?[|:]\s?", "", translatedText) - # Add Wordwrap translatedText = dazedwrap.wrapText(translatedText, WIDTH) translatedText = translatedText.replace("\n", "\\n") @@ -464,6 +501,9 @@ def getSpeaker(speaker): for i in range(len(NAMESLIST)): if speaker == NAMESLIST[i][0]: return [NAMESLIST[i][1], [0, 0]] + + if speaker == "???": + return ["???", [0, 0]] # Translate and Store Speaker response = translateAI( diff --git a/modules/rpgmakermvmz.py b/modules/rpgmakermvmz.py index 9875345..57b606c 100644 --- a/modules/rpgmakermvmz.py +++ b/modules/rpgmakermvmz.py @@ -7,6 +7,7 @@ import threading import time import traceback import openai +import copy from concurrent.futures import ThreadPoolExecutor, as_completed from pathlib import Path from colorama import Fore @@ -1058,7 +1059,7 @@ def searchCodes(page, pbar, jobList, filename): # Join Up 401's into single string if len(codeList) > i + 1: - while codeList[i + 1]["code"] in [401, 405, -1] and len(codeList[i]["parameters"]) > 0 and not re.match(r"^(\s*[\\]+[aAbBdDeEfFgGhHjJlLmMoOpPqQrRsStTuUwWxXyYzZ]+\[[\w\d\[\]\\]+\])", codeList[i+1]["parameters"][0]): + while codeList[i + 1]["code"] in [401, 405, -1] and len(codeList[i]["parameters"]) > 0 and len(codeList[i + 1]["parameters"]) > 0 and not re.match(r"^(\s*[\\]+[aAbBdDeEfFgGhHjJlLmMoOpPqQrRsStTuUwWxXyYzZ]+\[[\w\d\[\]\\]+\])", codeList[i+1]["parameters"][0]): if not setData: codeList[i]["parameters"] = [] codeList[i]["code"] = -1 @@ -1138,6 +1139,7 @@ def searchCodes(page, pbar, jobList, filename): if "\\CL" in finalJAString or "\\ac" in finalJAString or "\\#" in finalJAString: finalJAString = finalJAString.replace("\\CL", "") finalJAString = finalJAString.replace("\\ac", "") + finalJAString = finalJAString.replace("\\# ", "") finalJAString = finalJAString.replace("\\#", "") CLFlag = True @@ -1148,7 +1150,7 @@ def searchCodes(page, pbar, jobList, filename): # Check if Empty if finalJAString == "": - if nametag: + if nametag and match: codeList[j]["parameters"][0] = codeList[j]["parameters"][0].replace(match.group(2), tledSpeaker) i += 1 continue @@ -1221,9 +1223,8 @@ def searchCodes(page, pbar, jobList, filename): ### Add Var Strings # CL Flag if CLFlag: - translatedText = "\\#" + translatedText - translatedText = translatedText.replace("\n", "\n\\#") - translatedText = re.sub(r"[\\]+?#\s+", r"\\#", translatedText) + translatedText = "\\# " + translatedText + translatedText = translatedText.replace("\n", "\n\\# ") CLFlag = False # Add Nametag Back In @@ -1590,14 +1591,15 @@ def searchCodes(page, pbar, jobList, filename): jaString = codeList[i]["parameters"][0] patterns = { - "テキスト-": (r"テキスト-(.+)") + # "テキスト-": (r"テキスト-(.+)") + "=": (r'=\s?(.*)",'), # "var text": (r"var\stext\d+\s=\s\"(.+)\""), # "logtxt = ": (r"logtxt\s=\s'(.+)'" # ".setNickname": (r'.setNickname\(\\?"(.+?)\\?"\)' # "_subject=": (r'_subject=(.+?)_' # "text =": (r"text\s*=\s*'(.+[^\\])'"), # "ex_a_name": (r'ex_a_name\(\d+,"(.+)"\)'), - # "gameVariables.setValue": (r":\$gameVariables.setValue\(\d+,'(.+)'\)"), + # "gameVariables.setValue": (r"\$gameVariables.setValue\(\d+,\s?'(.+)'\)"), # "BattleManager._logWindow.push('addText'": (r"BattleManager._logWindow.push\('addText',\s'(.+)'\)"), } @@ -1605,6 +1607,10 @@ def searchCodes(page, pbar, jobList, filename): if key in jaString: match = re.search(regex, jaString) if match: + # Check if the match contains actual text (not just numbers/special chars) + if not re.search(r'[a-zA-Z一-龠ぁ-ゔァ-ヴーa-zA-Z0-9\uFF61-\uFF9F]', match.group(1)): + continue + # Pass 1 if setData: list355655.append(match.group(1)) @@ -1633,24 +1639,33 @@ def searchCodes(page, pbar, jobList, filename): ## Event Code: 408 (Script) if "code" in codeList[i] and (codeList[i]["code"] == 408) and CODE408 is True: - # Remove Textwrap jaString = codeList[i]["parameters"][0] - # jaString = jaString.replace("\n", " ") + match = re.search(r"(.+)", jaString) + if match: + # Remove Textwrap + jaString = codeList[i]["parameters"][0] + ojaString = jaString + jaString = jaString.replace("\n", " ") - # Pass 1 - if setData: - list408.append(jaString) - - # Pass 2 - else: - translatedText = list408[0] - list408.pop(0) + # If there isn't any Japanese in the text just skip + if not re.search(LANGREGEX, jaString): + i += 1 + continue - # Textwrap - translatedText = dazedwrap.wrapText(translatedText, width=1000) + # Pass 1 + if setData: + list408.append(jaString) + + # Pass 2 + else: + translatedText = list408[0] + list408.pop(0) - # Set Data - codeList[i]["parameters"][0] = f"{translatedText}" + # Textwrap + translatedText = dazedwrap.wrapText(translatedText, width=LISTWIDTH) + + # Set Data + codeList[i]["parameters"][0] = codeList[i]["parameters"][0].replace(ojaString, translatedText) ## Event Code: 108 (Script) if "code" in codeList[i] and (codeList[i]["code"] == 108) and CODE108 is True: @@ -1670,6 +1685,8 @@ def searchCodes(page, pbar, jobList, filename): regex = r"event_text\s*:\s*(.*)" elif "Menu Name" in jaString: regex = r"Menu\sName\s*:\s*(.*)>" + elif "text_indicator" in jaString: + regex = r"text_indicator\s?:\s?(.+)" else: i += 1 continue @@ -1742,7 +1759,7 @@ def searchCodes(page, pbar, jobList, filename): # Want to translate this script if "D_TEXT " in jaString: - regex = r"D_TEXT\s([^\s]+)\s?\d*" + regex = r"D_TEXT\s*([^\s]+)\s?\d*" elif "ShowInfo" in jaString: regex = r"ShowInfo\s(.*)" elif "PushGab" in jaString: @@ -1750,7 +1767,7 @@ def searchCodes(page, pbar, jobList, filename): elif "addLog" in jaString: regex = r"addLog\s(.*)" elif "DW_" in jaString: - regex = r"DW_.*?\s(.*)" + regex = r"DW_.*\s\d+\s(.+)" elif "CommonPopup" in jaString: regex = r"CommonPopup\sadd\stext:(.*?)[\\]+}" elif "AddCustomChoice" in jaString: @@ -1906,12 +1923,15 @@ def searchCodes(page, pbar, jobList, filename): if "code" in codeList[i] and codeList[i]["code"] == 102 and CODE102 is True: choiceList = [] varList = [] + choiceIndexMap = [] # Track which original indices we're processing + + # Process each string in the parameters list for choice in range(len(codeList[i]["parameters"][0])): jaString = codeList[i]["parameters"][0][choice] jaString = jaString.replace(" 。", ".") # Avoid Empty Strings - if jaString == "": + if not jaString.strip(): continue # If and En Statements @@ -1921,50 +1941,43 @@ def searchCodes(page, pbar, jobList, filename): for var in ifList: jaString = jaString.replace(var, "") ifVar += var + + # Store the formatting and cleaned string varList.append(ifVar) - - # Append to List choiceList.append(jaString) + choiceIndexMap.append(choice) - # Translate - if len(textHistory) > 0: - response = translateAI( - choiceList, - f"Reply with the English translation of the dialogue choice.\n\nPrevious text for context: {str(textHistory)}\n", - True, - ) - translatedTextList = response[0] - totalTokens[0] += response[1][0] - totalTokens[1] += response[1][1] - else: - response = translateAI(choiceList, "Reply with the English translation of the dialogue choice.", True) + # Translate the list + if len(choiceList) > 0: + if len(textHistory) > 0: + response = translateAI( + choiceList, + f"Reply with the English translation of the dialogue choice.\n\nPrevious text for context: {str(textHistory)}\n", + True, + ) + else: + response = translateAI(choiceList, "Reply with the English translation of the dialogue choice.", True) + translatedTextList = response[0] totalTokens[0] += response[1][0] totalTokens[1] += response[1][1] - # Check Mismatch - if len(translatedTextList) == len(choiceList): - for choice in range(len(codeList[i]["parameters"][0])): - jaString = codeList[i]["parameters"][0][choice] - jaString = jaString.replace(" 。", ".") - - # Avoid Empty Strings - if jaString == "": - continue - - translatedText = translatedTextList[choice] - - # Set Data - totalTokens[0] += response[1][0] - totalTokens[1] += response[1][1] - if translatedText != "": - translatedText = varList[choice] + translatedText[0].upper() + translatedText[1:] - else: - translatedText = varList[choice] + translatedText - codeList[i]["parameters"][0][choice] = translatedText - else: - if filename not in MISMATCH: - MISMATCH.append(filename) + # Check Mismatch and set translations + if len(translatedTextList) == len(choiceList): + for idx, translatedText in enumerate(translatedTextList): + originalIndex = choiceIndexMap[idx] + + # Apply formatting + if translatedText != "": + translatedText = varList[idx] + translatedText[0].upper() + translatedText[1:] + else: + translatedText = varList[idx] + translatedText + + # Set the translation back to the original position + codeList[i]["parameters"][0][originalIndex] = translatedText + else: + if filename not in MISMATCH: + MISMATCH.append(filename) ### Event Code: 111 Script if "code" in codeList[i] and codeList[i]["code"] == 111 and CODE111 is True: @@ -2086,7 +2099,7 @@ def searchCodes(page, pbar, jobList, filename): # 108 if len(list108) > 0: - response = translateAI(list108, textHistory, True) + response = translateAI(list108, "This text is a label. Use title capitalization and keep it brief.", True) list108TL = response[0] totalTokens[0] += response[1][0] totalTokens[1] += response[1][1] diff --git a/modules/wolf.py b/modules/wolf.py index 5e9b9ac..223b86a 100644 --- a/modules/wolf.py +++ b/modules/wolf.py @@ -82,30 +82,30 @@ PBAR = None FILENAME = None # Dialogue / Choices -CODE101 = False -CODE102 = False +CODE101 = True +CODE102 = True # Set String (Fragile but necessary) CODE122 = True -CODE150 = False +CODE150 = True # Other -CODE210 = False -CODE300 = False -CODE250 = False +CODE210 = True +CODE300 = True +CODE250 = True # Database -SCENARIOFLAG = False -OPTIONSFLAG = False -NPCFLAG = False -DBNAMEFLAG = False -DBVALUEFLAG = False +SCENARIOFLAG = True +OPTIONSFLAG = True +NPCFLAG = True +DBNAMEFLAG = True +DBVALUEFLAG = True ITEMFLAG = True -STATEFLAG = False -ENEMYFLAG = False -ARMORFLAG = False -WEAPONFLAG = False -SKILLFLAG = False +STATEFLAG = True +ENEMYFLAG = True +ARMORFLAG = True +WEAPONFLAG = True +SKILLFLAG = True # Initialize Translation Config TRANSLATION_CONFIG = TranslationConfig( diff --git a/vocab.txt b/vocab.txt index 1d65432..f5a311e 100644 --- a/vocab.txt +++ b/vocab.txt @@ -1,8 +1,8 @@ Here are some vocabulary and terms so that you know the proper spelling and translation. # Game Characters -イルヴィナ (Ilvina) - Female -ゾフィー (Zophie) - Female +イルヴィナ (Illvina) - Female +ゾフィー (Sophie) - Female クリュエル (Cruel) - Male アンナ (Anna) - Female エララ (Elala) - Female @@ -11,6 +11,8 @@ Here are some vocabulary and terms so that you know the proper spelling and tran マホ (Maho) - Female オリヴィア (Olivia) - Female プリンシア (Princia) - Female +ベルナ (Berna) - Female +リップ (Ripp) - Female # Lewd Terms マンコ (pussy) @@ -228,4 +230,158 @@ w (lol) エッチ水着 (Lewd Swimsuit) エッチな水着 (Lewd Swimsuit) 服屋内 (Clothing Shop Interior) -衣装保管 (Costume Storage) \ No newline at end of file +衣装保管 (Costume Storage) +template (template) +■本マップ (■Main Map) +▼ユーティリティマップ (▼Utility Map) +世界地図 (World Map) +ギャラリーモード (Gallery Mode) +フィールド (Field) +最初の遺跡 1F (First Ruins 1F) +最初の遺跡 B1F-1 (First Ruins B1F-1) +✨最初の遺跡 B1F-2 (✨First Ruins B1F-2) +最初の遺跡 B1F-3 (First Ruins B1F-3) +最初の遺跡 B1F-4 (First Ruins B1F-4) +最初の遺跡 祭壇 (First Ruins Altar) +⛏砂原隧道 1F (⛏Sandplain Tunnel 1F) +砂原隧道 2F (Sandplain Tunnel 2F) +_王都 (_Royal Capital) +王都 (Royal Capital) +_bak_王都 (_bak_Royal Capital) +ヴェダナ神教本部 (Vedana Church Headquarters) +⛏断崖の空洞 1F (⛏Cliffside Cavern 1F) +断崖の空洞 2F (Cliffside Cavern 2F) +断崖の空洞 3F (Cliffside Cavern 3F) +断崖の遺跡 1F (Cliffside Ruins 1F) +断崖の遺跡 2F (Cliffside Ruins 2F) +ギミックテスト用1 (Gimmick Test 1) +ギミックテスト用2 (Gimmick Test 2) +ギミックテスト用3 (Gimmick Test 3) +ギミックテスト用4-エレベーター (Gimmick Test 4 -Elevator) +ギミックテスト用5 (Gimmick Test 5) +エレベーターシャフト画像用 (For Elevator Shaft Image) +ギミックテスト用6 (Gimmick Test 6) +断崖の遺跡 BF-2 (Cliffside Ruins BF-2) +断崖の遺跡 3F (Cliffside Ruins 3F) +断崖の遺跡 BF (Cliffside Ruins BF) +断崖の遺跡 BF-3 (Cliffside Ruins BF-3) +断崖の遺跡 最深部 (Cliffside Ruins Deepest Area) +断崖の遺跡 BOSS (Cliffside Ruins BOSS) +断崖の遺跡 祭壇 (Cliffside Ruins Altar) +森 (Forest) +森 (Forest) +湖の遺跡 1F (Lake Ruins 1F) +湖の遺跡 エレベーター (Lake Ruins Elevator) +湖の遺跡 B1 (Lake Ruins B1) +湖の遺跡 B2 (Lake Ruins B2) +湖の遺跡 B3 (Lake Ruins B3) +湖の遺跡 スイッチ部屋 (Lake Ruins Switch Room) +湖の遺跡 MB2 (Lake Ruins MB2) +湖の遺跡 最深部 (Lake Ruins Deepest Area) +湖の遺跡 BOSS (Lake Ruins BOSS) +湖の遺跡 祭壇 (Lake Ruins Altar) +クレジット (Credits) +リトライ用 (For Retry) +⛏砂原南の洞窟 (Southern Sand Cave) +砂原南の洞窟 B1 (Southern Sand Cave B1) +⛏アーラヴァ山中路 (Aarava Mountain Path) +砂原の遺跡 1F (Sand Ruins 1F) +砂原の遺跡 B1 (Sand Ruins B1) +砂原の遺跡 B2 (Sand Ruins B2) +砂原の遺跡 B3 (Sand Ruins B3) +_宝部屋 (_Treasury) +_砂原の遺跡 最深部 (_Sand Ruins Deepest Area) +砂原の遺跡 BOSS ( Sand Ruins BOSS) +半島の遺跡 B1 ( Peninsula Ruins B1) +半島の遺跡 宝部屋 ( Peninsula Ruins Treasure Room) +半島の遺跡 BOSS ( Peninsula Ruins BOSS) +砂原の遺跡 祭壇 ( Sand Ruins Altar) +半島の遺跡 最深部 ( Peninsula Ruins Deepest Area) +半島の遺跡 1F ( Peninsula Ruins 1F) +エレベーター ( Elevator) +半島の遺跡 B2 ( Peninsula Ruins B2) +半島の遺跡 B4 ( Peninsula Ruins B4) +_半島の遺跡 B4 通路 (_ Peninsula Ruins B4 Passage) +_半島の遺跡 B4 (_ Peninsula Ruins B4) +半島の遺跡 B3 ( Peninsula Ruins B3) +半島の遺跡 B5 ( Peninsula Ruins B5) +半島の遺跡 祭壇 ( Peninsula Ruins Altar) +ヴェダナ神教本部 奥の部屋 ( Vedana Church Headquarters Back Room) +ヴェダナ神教本部 裏手口 ( Vedana Church Headquarters Rear Entrance) +⛩導きの塔 1F ( Tower of Guidance 1F) +導きの塔 エレベーター ( Tower of Guidance Elevator) +導きの塔 上階 ( Tower of Guidance Upper Floor) +⛏山岳への道 王都側 ( Mountain Path Royal Capital Side) +山岳への道 山岳側 ( Mountain Path Mountain Side) +山岳への道 3F ( Mountain Path 3F) +神域の山 1F西 ( Sacred Mountain 1F West) +神域の山 1F東 ( Sacred Mountain 1F East) +神域の山 2F ( Sacred Mountain 2F) +神域の山 3F ( Sacred Mountain 3F) +⛏水路洞窟 1F ( Waterway Cave 1F) +水路洞窟 2F ( Waterway Cave 2F) +水路洞窟 B1 ( Waterway Cave B1) +水路洞窟 盗賊のアジト (Waterway Cave -Thieves' Hideout) +山岳の遺跡 1F表 (Mountain Ruins 1F Front) +山岳の遺跡 2F表 (Mountain Ruins 2F Front) +山岳の遺跡 外回廊 (Mountain Ruins Outer Corridor) +山岳の遺跡 2F裏 (Mountain Ruins 2F Back) +山岳の遺跡 3F表 (Mountain Ruins 3F Front) +山岳の遺跡 1F裏 (Mountain Ruins 1F Back) +山岳の遺跡 3F裏 (Mountain Ruins 3F Back) +山岳の遺跡 尖塔 (Mountain Ruins Spire) +山岳の遺跡 祭壇 (Mountain Ruins Altar) +山岳の遺跡 boss (Mountain Ruins Boss) +湿地の遺跡 南棟1F (Wetlands Ruins South Wing 1F) +湿地の遺跡 南棟B1 (Wetlands Ruins South Wing B1) +湿地の遺跡 南棟B2 (Wetlands Ruins South Wing B2) +湿地の遺跡 中庭 (Wetlands Ruins Courtyard) +湿地の遺跡 回廊 (Wetlands Ruins Corridor) +湿地の遺跡 北棟B1 (Wetlands Ruins North Wing B1) +湿地の遺跡 北棟1F (Wetlands Ruins North Wing 1F) +湿地の遺跡 バルコニー (Wetlands Ruins Balcony) +湿地の遺跡 boss (Wetlands Ruins Boss) +湿地の遺跡 祭壇 (Wetlands Ruins Altar) +⛏神殿への道 入口 (Path to the Temple Entrance) +神殿への道 エレベーター (Path to the Temple Elevator) +神殿への道 B1 (Path to the Temple B1) +神殿への道 B3 (Path to the Temple B3) +神殿への道 B2 (Path to the Temple B2) +セブネスの神殿 入口 (Sebnes Temple Entrance) +セブネスの神殿 1Fメインホール (Sebnes Temple 1F Main Hall) +セブネスの神殿 1F南西 (Sebnes Temple 1F Southwest) +スイッチ部屋 (Switch Room) +セブネスの神殿 1F南東 (Sevnes Temple 1F Southeast) +セブネスの神殿 1F北西 (Sevnes Temple 1F Northwest) +セブネスの神殿 1F北東 (Sevnes Temple 1F Northeast) +セブネスの神殿 2F (Sevnes Temple 2F) +セブネスの神殿 1F階段部屋 (Sevnes Temple 1F Stair Room) +セブネスの神殿 2F外 (Sevnes Temple 2F Outside) +セブネスの神殿 エレベーター (Sevnes Temple Elevator) +大祭殿 (Grand Sanctuary) +大祭殿大広間 (Grand Sanctuary Great Hall) +大祭殿 BOSS (Grand Sanctuary BOSS) +大祭殿 儀式の間 (Grand Sanctuary Ritual Chamber) +⛩礼拝堂(大河の大洲) (Chapel (Great River Isle)) +礼拝堂(森の集落北) (Chapel (North Forest Settlement)) +礼拝堂(砂原東) (Chapel (East Sandplain)) +礼拝堂(アーラヴァ山) (Chapel (Arava Mountain)) +礼拝堂(山岳西) (Chapel (West Mountains)) +礼拝堂(霊峰の頂) (Chapel (Sacred Peak Summit)) +⛩バールルの奉詠塔 (Barlul's Hymn Tower) +レグラの奉詠塔 (Regra's Hymn Tower) +セブネスの奉詠塔 (Sevnes's Hymn Tower) +⛏川沿いの洞窟 (Riverside Cave) +⛏巣穴の洞窟 (Nest Cave) +巣穴の洞窟 深部 (Nest Cave Depths) +水路洞窟 西1F (Aqueduct Cave West 1F) +水路洞窟 西2F (Aqueduct Cave West 2F) +アラビア部屋2 (Arabia Room 2) +騎士団詰所 (Knights' Station) +山小屋 (Mountain Cabin) +砂原南の洞窟 潜伏先 (South Sandplain Cave Hideout) +_半島の遺跡 BOSS (_Peninsula Ruins BOSS) +大祭殿 BOSS2 ( Grand Sanctuary BOSS2) +⚔バトルテストゾーン (⚔ Battle Test Zone) +☘テンプレ (☘ Template) +難度選択 ( Difficulty Selection) \ No newline at end of file