Changes to wolf and images

This commit is contained in:
DazedAnon 2024-09-12 16:58:00 -05:00
parent eee6ec282d
commit 921ea31a4e
3 changed files with 403 additions and 137 deletions

View file

@ -70,9 +70,9 @@ def handleImages(folderName, estimate):
originalList = translatedData[0][1]
dimensionsList = translatedData[0][2]
image = stringToImage(translatedList[i], dimensionsList[i][0], dimensionsList[i][1])
image.save(rf'translated/{folderName}/{originalList[i]}.png', quality=100)
image.save(rf'translated/{folderName}/{translatedList[i]}.png', quality=100)
except Exception as e:
PBAR.write(f'{originalList[i]}: {str(e)}')
PBAR.write(f'{translatedList[i]}: {str(e)}')
#Ignore Error
# Print File
@ -173,7 +173,7 @@ def stringToImage(text, width, height, font_path='fonts/TsunagiGothic.ttf', scal
y = (scaled_height - text_height) // 2
# Draw the text on the image
draw.text((x, y), text, font=font, fill=(0, 0, 0, 255))
draw.text((x, y), text, font=font, fill=(255, 255, 255, 255))
# Resize back to the original dimensions to get a clearer text rendering
image = image.resize((width, height), Image.LANCZOS,)
@ -192,7 +192,7 @@ def getImageDimensions(file_path):
def processImagesDir(directory_path, imageList):
for file_name in os.listdir(directory_path):
# .png and Japanese
if '.png' in file_name and re.search(r'[一-龠ぁ-ゔァ-ヴー]+', file_name):
if '.png' in file_name and re.search(r'[一-龠ぁ-ゔァ-ヴー]+', file_name) and file_name.replace('.png', '') in VOCAB and len(file_name) > 5:
file_path = os.path.join(directory_path, file_name)
if os.path.isfile(file_path):
# Check if the file is an image

View file

@ -35,6 +35,7 @@ BRFLAG = False # If the game uses <br> instead
FIXTEXTWRAP = True # Overwrites textwrap
IGNORETLTEXT = False # Ignores all translated text.
MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
FILENAME = None
BRACKETNAMES = False
# Pricing - Depends on the model https://openai.com/pricing
@ -48,7 +49,7 @@ if 'gpt-3.5' in MODEL:
elif 'gpt-4' in MODEL:
INPUTAPICOST = .005
OUTPUTAPICOST = .015
BATCHSIZE = 20
BATCHSIZE = 40
FREQUENCY_PENALTY = 0.1
#tqdm Globals
@ -64,9 +65,9 @@ CODE102 = False
CODE122 = False
# Other
CODE210 = True
CODE300 = True
CODE250 = False
CODE210 = False
CODE300 = False
CODE250 = True
# Database
NPCFLAG = False
@ -78,8 +79,9 @@ ENEMYFLAG = False
WEAPONFLAG = False
def handleWOLF(filename, estimate):
global ESTIMATE, TOKENS
global ESTIMATE, TOKENS, FILENAME
ESTIMATE = estimate
FILENAME = filename
# Translate
start = time.time()
@ -365,7 +367,7 @@ def searchCodes(events, pbar, jobList, filename):
# # Validate and Set Data
# codeList[i]['stringArgs'][1] = translatedText
if 'stringArgs' in codeList[i] and len(codeList[i]['stringArgs']) > 1:
imageRegex = r'(\\?r?\\?n?_\w+\r\n)|(@-?\d?)(\d?-?\d?[^\r]+?)(\r\n|$)|(_PDC)|(>\r\n)|(^[#])|(\r\n@$)|(/)|(_SS_)|(\r\n[@/]-?\d?\r\n)'
imageRegex = r'(\r?\n?_\w+\r?\n?)|(@-?\d?\r\n)|(@-?\d?[^\r])(\d?-?\d?[^\r]+?)(\r\n|$)|(_PDC)|(>\r\n)|(^[#])|(\r\n@$)|(/)|(_SS_)|(\r\n[@/]-?\d?\r\n)'
fontSize = 24
# Grab String
@ -383,9 +385,9 @@ def searchCodes(events, pbar, jobList, filename):
j = 0
translatedText = ''
while j < len(cleanedList):
if j > 0 and ('@' in cleanedList[j] or '/' in cleanedList[j]) and j < len(cleanedList)-1 and re.search(r'(\r\n[@/]-?\d?\r\n)', cleanedList[j]) is None:
if ('@' in cleanedList[j] or '/' in cleanedList[j]) and j < len(cleanedList)-1 and re.search(r'([@/]-?\d?\r\n)', cleanedList[j]) is None:
# Setup @
if '@' not in cleanedList[j-1] and '/' not in cleanedList[j-1] and '_' not in cleanedList[j-1]:
if j > 0 and '@' not in cleanedList[j-1] and '/' not in cleanedList[j-1] and '_' not in cleanedList[j-1]:
cleanedList[j-1] = cleanedList[j-1] + cleanedList[j+1]
else:
cleanedList.insert(j, cleanedList[j+1])
@ -406,8 +408,14 @@ def searchCodes(events, pbar, jobList, filename):
# Pass 2
else:
if all(x not in str for x in ['_', '@', '>', '/',]) and str != '\r\n':
# Decide Wrap
if codeList[i]['stringArgs'][0] == '[移]サウンドノベル':
width = 40
else:
width = WIDTH
# Add Textwrap and Font
list300[0] = textwrap.fill(list300[0], WIDTH)
list300[0] = textwrap.fill(list300[0], width)
list300[0] = list300[0].replace('\n', f'\r\n\\f[{fontSize}]')
list300[0] = f'\\f[{fontSize}]{list300[0]}\r\n'
translatedText += list300[0]
@ -419,6 +427,8 @@ def searchCodes(events, pbar, jobList, filename):
if setData:
# Formatting Fixes
translatedText = translatedText.replace('*"', '* "')
translatedText = translatedText.replace('\r\n\r\n', '\r\n')
translatedText = re.sub(r'[^\S\r\n]+', ' ', translatedText)
codeList[i]['stringArgs'][1] = translatedText
@ -483,11 +493,11 @@ def searchCodes(events, pbar, jobList, filename):
codeList[i]['stringArgs'][0] = translatedText
### Event Code: 300 Common Events
if codeList[i]['code'] == 300 and CODE300 == True and len(codeList[i]['stringArgs']) > 1:
if codeList[i]['code'] == 122 and CODE300 == True and len(codeList[i]['stringArgs']) > 0:
# Choices
if codeList[i]['stringArgs'][0] == "選択肢/確認":
if codeList[i]['stringArgs'][0] == "m_可変式選択肢":
# Grab String
choiceList = codeList[i]['stringArgs'][1].split(',')
choiceList = codeList[i]['stringArgs'][1].split('\r\n')
# Translate Question
question = codeList[i]['stringArgs'][2]
@ -510,20 +520,28 @@ def searchCodes(events, pbar, jobList, filename):
choiceListTL[j] = choiceListTL[j].replace(', ', '')
# Convert to String and Set
translatedText = ','.join(choiceListTL)
translatedText = '\r\n'.join(choiceListTL)
codeList[i]['stringArgs'][1] = translatedText
# Dialogue
elif codeList[i]['stringArgs'][0] == "Hメッセージ" \
or codeList[i]['stringArgs'][0] == 'Hしらべる' \
or codeList[i]['stringArgs'][0] == '[共]Hメッセージ+' \
or codeList[i]['stringArgs'][0] == '[共]ポップアップ表示' \
or codeList[i]['stringArgs'][0] == 'm_謎冒頭' \
or (codeList[i]['codeStr'] == 'SetString' and '@' in codeList[i]['stringArgs'][0])\
or codeList[i]['stringArgs'][0] == '[移]サウンドノベル':
imageRegex = r'(\r?\n?_\w+\r?\n?)|(@-?\d?\r\n)|(@-?\d?[^\r])(\d?-?\d?[^\r]+?)(\r\n|$)|(_PDC)|(>\r\n)|(^[#])|(\r\n@$)|(/)|(_SS_)|(\r\n[@/]-?\d?\r\n)'
imageRegex = r'(\r?\n?_\w+\r?\n?)|(@-?\d?\r\n)|(@-?\d?[^\r*])(\d?-?\d?[^\r]+?)(\r\n|$)|(_PDC)|(>\r\n)|(^[#])|(\r\n@$)|(/)|(_SS_)|(\r\n[@/]-?\d?\r\n)'
fontSize = 24
# Grab String
jaString = codeList[i]['stringArgs'][1]
if codeList[i]['codeStr'] != 'SetString':
jaString = codeList[i]['stringArgs'][1]
else:
jaString = codeList[i]['stringArgs'][0]
jaString = jaString.replace('\u3000', ' ')
jaString = jaString.replace('#', '')
jaString = re.sub(r'[^\r]\n', '\r\n', jaString)
# Grab and Split
jaStringList = re.split(imageRegex, jaString)
@ -560,12 +578,12 @@ def searchCodes(events, pbar, jobList, filename):
if all(x not in str for x in ['_', '@', '>', '/',]) and str != '\r\n':
# Decide Wrap
if codeList[i]['stringArgs'][0] == '[移]サウンドノベル':
width = 50
width = 40
else:
width = WIDTH
# Add Textwrap and Font
list300[0] = textwrap.fill(list300[0], WIDTH)
list300[0] = textwrap.fill(list300[0], width)
list300[0] = list300[0].replace('\n', f'\r\n\\f[{fontSize}]')
list300[0] = f'\\f[{fontSize}]{list300[0]}\r\n'
translatedText += list300[0]
@ -577,44 +595,49 @@ def searchCodes(events, pbar, jobList, filename):
if setData:
# Formatting Fixes
translatedText = translatedText.replace('*"', '* "')
translatedText = translatedText.replace('\r\n\r\n', '\r\n')
translatedText = re.sub(r'[^\S\r\n]+', ' ', translatedText)
codeList[i]['stringArgs'][1] = translatedText
if codeList[i]['codeStr'] != 'SetString':
codeList[i]['stringArgs'][1] = translatedText
else:
codeList[i]['stringArgs'][0] = translatedText
### Event Code: 250 Common Events
if codeList[i]['code'] == 250 and CODE250 == True:
foundTerm = False
# Validate size
if len(codeList[i]['stringArgs']) > 0:
# Grab String
jaString = codeList[i]['stringArgs'][0]
if len(codeList[i]['stringArgs']) > 2:
if codeList[i]['stringArgs'][1] == "┗所持防具個数" and codeList[i]['stringArgs'][2] != '':
# Grab String
jaString = codeList[i]['stringArgs'][2]
# Catch Vars that may break the TL
varString = ''
matchList = re.findall(r'^[\\_]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
if len(matchList) != 0:
varString = matchList[0]
jaString = jaString.replace(matchList[0], '')
# Catch Vars that may break the TL
varString = ''
matchList = re.findall(r'^[\\_]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
if len(matchList) != 0:
varString = matchList[0]
jaString = jaString.replace(matchList[0], '')
# Check if term already translated
for j in range(len(TERMSLIST)):
if jaString == TERMSLIST[j][0]:
translatedText = TERMSLIST[j][1]
foundTerm = True
# Check if term already translated
for j in range(len(TERMSLIST)):
if jaString == TERMSLIST[j][0]:
translatedText = TERMSLIST[j][1]
foundTerm = True
# Translate
if foundTerm == False:
response = translateGPT(jaString, f'Reply with the {LANGUAGE} translation of the text.', False)
translatedText = response[0]
totalTokens[0] = response[1][0]
totalTokens[1] = response[1][1]
TERMSLIST.append([jaString, translatedText])
# Translate
if foundTerm == False:
response = translateGPT(jaString, f'Reply with the {LANGUAGE} translation of the text.', False)
translatedText = response[0]
totalTokens[0] = response[1][0]
totalTokens[1] = response[1][1]
TERMSLIST.append([jaString, translatedText])
# Add back Potential Variables in String
translatedText = varString + translatedText
# Add back Potential Variables in String
translatedText = varString + translatedText
# Set Data
codeList[i]['stringArgs'][0] = translatedText
# Set Data
codeList[i]['stringArgs'][2] = translatedText
### Iterate
i += 1
@ -697,7 +720,7 @@ def searchDB(events, pbar, jobList, filename):
totalTokens = [0, 0]
initialJAString = ''
tableList = events
font = '\\f[18]'
font = ''
global LOCK
global NAMESLIST
global MISMATCH
@ -726,7 +749,7 @@ def searchDB(events, pbar, jobList, filename):
# Parse
for j in range(len(dataList)):
# Name
if '翔太' in dataList[j].get('name'):
if 'キャラ名' in dataList[j].get('name'):
# Pass 1 (Grab Data)
if setData == False:
if dataList[j].get('value') != '':
@ -818,102 +841,105 @@ def searchDB(events, pbar, jobList, filename):
scenarioList[2].pop(0)
# Grab Items
if table['name'] == '道具' and ITEMFLAG == True:
for item in table['data']:
dataList = item['data']
if table['name'] == '宿泊施設' and ITEMFLAG == True:
with open('translations.txt', 'a') as file:
for item in table['data']:
dataList = item['data']
# Parse
for j in range(len(dataList)):
# Name
if '道具名' in dataList[j].get('name'):
# Pass 1 (Grab Data)
if setData == False:
if dataList[j].get('value') != '':
itemList[0].append(dataList[j].get('value'))
# Parse #
for j in range(len(dataList)):
# Name
if 'NULL' in dataList[j].get('name'):
# Pass 1 (Grab Data)
if setData == False:
if dataList[j].get('value') != '':
itemList[0].append(dataList[j].get('value'))
# Pass 2 (Set Data)
else:
if dataList[j].get('value') != '':
dataList[j].update({'value': itemList[0][0]})
itemList[0].pop(0)
# Description
if 'NULL' in dataList[j].get('name'):
# Pass 1 (Grab Data)
if setData == False:
if dataList[j].get('value') != '':
# Remove Textwrap
jaString = dataList[j].get('value')
jaString = jaString.replace('\n', ' ')
jaString = jaString.replace('\r', '')
jaString = re.sub(r'[\\]+f\[\d+\]', '', jaString)
# Pass 2 (Set Data)
else:
if dataList[j].get('value') != '':
file.write(f'{dataList[j].get('value')} ({itemList[0][0]})\n')
dataList[j].update({'value': itemList[0][0]})
itemList[0].pop(0)
# Description
if dataList[j].get('name') == '選2文字列(夜時非表示':
# Pass 1 (Grab Data)
if setData == False:
if dataList[j].get('value') != '':
# Remove Textwrap
jaString = dataList[j].get('value')
jaString = jaString.replace('\n', ' ')
jaString = jaString.replace('\r', '')
jaString = re.sub(r'[\\]+f\[\d+\]', '', jaString)
# Append Data
itemList[1].append(jaString)
# Append Data
itemList[1].append(jaString)
# Pass 2 (Set Data)
else:
if dataList[j].get('value') != '':
# Textwrap
translatedText = itemList[1][0]
translatedText = textwrap.fill(translatedText, LISTWIDTH)
translatedText = font + translatedText
# Pass 2 (Set Data)
else:
if dataList[j].get('value') != '':
# Textwrap
translatedText = itemList[1][0]
translatedText = textwrap.fill(translatedText, LISTWIDTH)
translatedText = translatedText.replace('\n', '\r\n')
translatedText = font + translatedText
# Set Data
dataList[j].update({'value': translatedText})
itemList[1].pop(0)
# Set Data
dataList[j].update({'value': translatedText})
itemList[1].pop(0)
# Description 2
if '使用後文章[移動]' in dataList[j].get('name'):
# Pass 1 (Grab Data)
if setData == False:
if dataList[j].get('value') != '':
# Remove Textwrap
jaString = dataList[j].get('value')
jaString = jaString.replace('\n', ' ')
jaString = jaString.replace('\r', '')
jaString = re.sub(r'[\\]+f\[\d+\]', '', jaString)
# Description 2
if dataList[j].get('name') == '選3文字列':
# Pass 1 (Grab Data)
if setData == False:
if dataList[j].get('value') != '':
# Remove Textwrap
jaString = dataList[j].get('value')
jaString = jaString.replace('\n', ' ')
jaString = jaString.replace('\r', '')
jaString = re.sub(r'[\\]+f\[\d+\]', '', jaString)
# Append Data
itemList[2].append(jaString)
# Append Data
itemList[2].append(jaString)
# Pass 2 (Set Data)
else:
if dataList[j].get('value') != '':
# Textwrap
translatedText = itemList[2][0]
translatedText = textwrap.fill(translatedText, LISTWIDTH)
translatedText = font + translatedText
# Pass 2 (Set Data)
else:
if dataList[j].get('value') != '':
# Textwrap
translatedText = itemList[2][0]
translatedText = textwrap.fill(translatedText, LISTWIDTH)
translatedText = font + translatedText
# Set Data
dataList[j].update({'value': translatedText})
itemList[2].pop(0)
# Set Data
dataList[j].update({'value': translatedText})
itemList[2].pop(0)
# Description 3
if '使用時文章[戦]' in dataList[j].get('name'):
# Pass 1 (Grab Data)
if setData == False:
if dataList[j].get('value') != '':
# Remove Textwrap
jaString = dataList[j].get('value')
jaString = jaString.replace('\n', ' ')
jaString = jaString.replace('\r', '')
jaString = re.sub(r'[\\]+f\[\d+\]', '', jaString)
# Description 3
if dataList[j].get('name') == '┗セ⑥_昼(になった)':
# Pass 1 (Grab Data)
if setData == False:
if dataList[j].get('value') != '':
# Remove Textwrap
jaString = dataList[j].get('value')
jaString = jaString.replace('\n', ' ')
jaString = jaString.replace('\r', '')
jaString = re.sub(r'[\\]+f\[\d+\]', '', jaString)
# Append Data
itemList[3].append(jaString)
# Append Data
itemList[3].append(jaString)
# Pass 2 (Set Data)
else:
if dataList[j].get('value') != '':
# Textwrap
translatedText = itemList[3][0]
translatedText = textwrap.fill(translatedText, LISTWIDTH)
translatedText = font + translatedText
# Pass 2 (Set Data)
else:
if dataList[j].get('value') != '':
# Textwrap
translatedText = itemList[3][0]
translatedText = textwrap.fill(translatedText, LISTWIDTH)
translatedText = font + translatedText
# Set Data
dataList[j].update({'value': translatedText})
itemList[3].pop(0)
# Set Data
dataList[j].update({'value': translatedText})
itemList[3].pop(0)
# Grab Armors
if table['name'] == '防具' and ARMORFLAG == True:
@ -1160,7 +1186,7 @@ def searchDB(events, pbar, jobList, filename):
pbar.refresh()
# Name
response = translateGPT(NPCList[0], 'Reply with only the '+ LANGUAGE +' translation of the RPG item name', True)
response = translateGPT(NPCList[0], 'Reply with only the '+ LANGUAGE +' translation of the RPG enemy name', True)
nameListTL = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
@ -1229,7 +1255,7 @@ def searchDB(events, pbar, jobList, filename):
translate = True
# ITEMS
if len(itemList[0]) > 0:
if len(itemList[0]) > 0 or len(itemList[1]) > 0:
# Progress Bar
total = 0
for itemArray in itemList:
@ -1238,7 +1264,7 @@ def searchDB(events, pbar, jobList, filename):
pbar.refresh()
# Name
response = translateGPT(itemList[0], 'Reply with only the '+ LANGUAGE +' translation of the RPG item name', True)
response = translateGPT(itemList[0], 'Reply with only the '+ LANGUAGE +' translation', True)
nameListTL = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
@ -1377,7 +1403,7 @@ def searchDB(events, pbar, jobList, filename):
pbar.refresh()
# Name
response = translateGPT(collectionList[0], '', True)
response = translateGPT(collectionList[0], 'reply with only the gender neutral '+ LANGUAGE +' translation of the action log. Always start the sentence with Taro. For example, Translate \'Taroを倒した\' as \'Taro was defeated!\'', True)
nameListTL = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
@ -1555,6 +1581,7 @@ def createContext(fullPromptFlag, subbedT):
ハッサン (Hassan) - Male\n\
アロマ (Aroma) - Female\n\
ピッケ (Pikke) - Female\n\
ドラオ (Dorao) - Male\n\
'
system = PROMPT + VOCAB if fullPromptFlag else \
@ -1685,7 +1712,7 @@ def combineList(tlist, text):
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
global PBAR
global PBAR, MISMATCH, FILENAME
mismatch = False
totalTokens = [0, 0]
@ -1754,6 +1781,8 @@ def translateGPT(text, history, fullPromptFlag):
else:
history = text[-10:]
mismatch = False
if FILENAME not in MISMATCH:
MISMATCH.append(FILENAME)
# Update Loading Bar
with LOCK:

237
vocab.txt
View file

@ -66,4 +66,241 @@ ME 音量 (ME Volume)
ギャンデッド (Ganded)
リーロランド (Liloland)
ローバー (Roper)
# Armors
アマカラ靴1 (Amakara Shoes 1)
お鍋のフタ (Pot Lid)
ライトシールド (Light Shield)
キトンシールド (Kiton Shield)
こうらの盾 (Shell Shield)
プラチナシールド (Platinum Shield)
魔法の盾 (Magic Shield)
シルバートレイ (Silver Tray)
皮の盾 (Leather Shield)
青銅の盾 (Bronze Shield)
ホワイトシールド (White Shield)
力の盾 (Power Shield)
水鏡の盾 (Water Mirror Shield)
ダークシールド (Dark Shield)
精霊の盾 (Spirit Shield)
スチヌラの盾 (Stinura Shield)
輪廻の盾 (Reincarnation Shield)
はぐれスチルの盾 (Stray Steel Shield)
破滅の盾 (Shield of Ruin)
鉄の盾 (Iron Shield)
鋼の盾 (Steel Shield)
氷の盾 (Ice Shield)
炎の盾 (Flame Shield)
玉鋼の盾 (Jewel Steel Shield)
ドラゴンシールド (Dragon Shield)
風神の盾 (Wind God Shield)
オーガシールド (Ogre Shield)
幻魔の盾 (Phantom Demon Shield)
女神の盾 (Goddess Shield)
シャハルの鏡 (Shahar's Mirror)
エンデの盾 (Ende's Shield)
スチルキングの盾 (Steel King Shield)
天空の盾 (Sky Shield)
ロトの盾 (Roto's Shield)
光の盾 (Light Shield)
皮の鎧 (Leather Armor)
くさりかたびら (Chain Mail)
鉄の胸当て (Iron Breastplate)
鋼の胸当て (Steel Breastplate)
プラチナメイル (Platinum Mail)
こうらの鎧 (Shell Armor)
ドラゴンスケイル (Dragon Scale)
シルバーメイル (Silver Mail)
ダンシングメイル (Dancing Mail)
魔法の鎧 (Magic Armor)
精霊の鎧 (Spirit Armor)
神秘の鎧 (Mystic Armor)
スチヌラ鎧 (Stenura Armor)
エンデの鎧 (Ende's Armor)
はぐれスチル鎧 (Stray Steel Armor)
勝利の鎧 (Victory Armor)
鉄の鎧 (Iron Armor)
鋼の鎧 (Steel Armor)
戦士の鎧 (Warrior's Armor)
ドラゴンメイル (Dragon Mail)
大地の鎧 (Earth Armor)
玉鋼の鎧 (Jewel Steel Armor)
氷の鎧 (Ice Armor)
炎の鎧 (Flame Armor)
魔神の鎧 (Demon Armor)
ミスリルアーマー (Mithril Armor)
ギガントアーマー (Gigant Armor)
幻魔の鎧 (Phantom Demon Armor)
女神の鎧 (Goddess Armor)
悪魔の鎧 (Devil Armor)
スチルキング鎧 (Steel King Armor)
布の服 (Cloth Garb)
旅人の服 (Traveler's Clothes)
貴族の服 (Noble's Clothes)
毛皮のコート (Fur Coat)
みかわしの服 (Evasion Clothes)
拳法着 (Martial Arts Wear)
かくれみの服 (Cloak of Invisibility)
竜の道着 (Dragon's Gi)
闇の衣 (Dark Robe)
レザーマント (Leather Mantle)
紅蓮のローブ (Crimson Robe)
やすらぎのローブ (Tranquil Robe)
魔法の法衣 (Magic Vestment)
神官のエプロン (Priest's Apron)
賢者のローブ (Sage's Robe)
天使のローブ (Angel's Robe)
不思議なボレロ (Mysterious Bolero)
精霊の法衣 (Spirit's Garb)
神秘のローブ (Mystic Robe)
ドラゴンローブ (Dragon Robe)
皮のドレス (Leather Dress)
絹のローブ (Silk Robe)
マジカルスカート (Magical Skirt)
シルクのビスチェ (Silk Bustier)
水の羽衣 (Water Robe)
光のドレス (Dress of Light)
プリンセスローブ (Princess Robe)
踊り子の服 (Dancer's Outfit)
バニースーツ (Bunny Suit)
あぶない水着 (Dangerous Swimsuit)
天使のレオタード (Angel's Leotard)
魔法のビキニ (Magic Bikini)
神秘のビスチェ (Mystic Bustier)
清き衣 (Pure Garment)
エッチな下着 (Sexy Underwear)
天空の鎧 (Sky Armor)
王者のマント (King's Mantle)
ロトの鎧 (Roto's Armor)
皮の帽子 (Leather Hat)
サークレット (Circlet)
毛皮のフード (Fur Hood)
神官の帽子 (Priest's Hat)
知識の帽子 (Hat of Knowledge)
ファントムマスク (Phantom Mask)
マジカルハット (Magical Hat)
般若の面 (Hannya Mask)
幸せの帽子 (Hat of Happiness)
不思議な帽子 (Mysterious Hat)
山彦の帽子 (Echo Hat)
うさみみバンド (Bunny Ears Band)
銀の髪飾り (Silver Hair Ornament)
ウィッチハット (Witch Hat)
黄金のティアラ (Golden Tiara)
スチールヘッドギア (Steel Headgear)
プラチナメット (Platinum Helmet)
サタンヘルム (Satan Helm)
武王のはちがね (War King's Headband)
ミスリルフード (Mithril Hood)
スチヌラヘルム (Stenura Helm)
不幸の兜 (Helmet of Misfortune)
はぐれスチルヘルム (Stray Steel Helm)
慈愛の兜 (Helmet of Compassion)
チェインフード (Chain Hood)
鉄兜 (Iron Helmet)
鉄仮面 (Iron Mask)
戦士の兜 (Warrior's Helmet)
猛牛ヘルム (Bull Helm)
玉鋼の兜 (Tamahagane Helmet)
グレートヘルム (Great Helm)
ミスリルヘルム (Mithril Helm)
幻魔の兜 (Phantom Demon Helmet)
女神の兜 (Goddess Helmet)
オルテガの兜 (Ortega's Helmet)
エンデの兜 (Ende's Helmet)
スチルキングヘルム (Steel King Helm)
天空の兜 (Heavenly Helmet)
太陽の冠 (Crown of the Sun)
ロトの兜 (Roto's Helmet)
竜のお守り (Dragon Amulet)
結界の指輪 (Ring of Protection)
護りのルビー (Ruby of Protection)
力のルビー (Ruby of Power)
怒りのタトゥー (Tattoo of Rage)
豪傑の腕輪 (Brave's Bracelet)
はやてのリング (Swift Ring)
疾風のバンダナ (Gale Bandana)
星降る腕輪 (Starfall Bracelet)
インテリめがね (Intelligent Glasses)
博識リング (Knowledge Ring)
知力の腕輪 (Bracelet of Wisdom)
大地の指輪 (Earth Ring)
命の指輪 (Ring of Life)
妖精の腕輪 (Fairy Bracelet)
女神の指輪 (Goddess Ring)
幸運のお守り (Lucky Charm)
ラッキーペンダント (Lucky Pendant)
魔除けの聖印 (Talisman of Protection)
破毒のリング (Antidote Ring)
めざましリング (Awakening Ring)
音溢れの指輪 (Sound Overflow Ring)
理性のリング (Ring of Reason)
エルフのお守り (Elf Charm)
癒しの腕輪 (Healing Bracelet)
祈りの腕輪 (Prayer Bracelet)
静寂の玉 (Orb of Silence)
うさぎのしっぽ (Rabbit's Tail)
銀の指輪 (Silver Ring)
炎のリング (Ring of Fire)
水のリング (Ring of Water)
アバンのしるし (Avan's Emblem)
太陽の指輪 (Ring of the Sun)
月の指輪 (Ring of the Moon)
業師の手袋 (Artisan's Gloves)
達人の手袋 (Master's Gloves)
神業の手袋 (Divine Gloves)
革の靴 (Leather Shoes)
盗賊のブーツ (Thief's Boots)
黄金の靴 (Golden Shoes)
速足のブーツ (Swift Boots)
フェザーシューズ (Feather Shoes)
魔法の靴 (Magic Shoes)
ステルスシューズ (Stealth Shoes)
ヌライムピアス (Nuraim Earrings)
翼のブローチ (Winged Brooch)
世界樹の皮 (World Tree Bark)
ちいさな虫かご (Small Bug Cage)
匂い袋 (Scent Bag)
名人のルアー (Master's Lure)
怪しげなコイン (Suspicious Coin)
謎の鉱物 (Mysterious Mineral)
精霊の腕輪 (Spirit Bracelet)
魔導ユニット (Magic Unit)
竜の角のペンダント (Dragon Horn Pendant)
千里眼の眼鏡 (Clairvoyant Glasses)
幸運の帽子 (Lucky Hat)
修験者の杖 (Ascetic's Staff)
業師の腕輪 (Artisan's Bracelet)
魔物使いの心得 (Beast Tamer's Knowledge)
カイトバックラー (Kite Buckler)
ミスリルシールド (Mithril Shield)
ドルフィンシールド (Dolphin Shield)
聖騎士の盾 (Holy Knight's Shield)
戦士の大盾 (Warrior's Great Shield)
スケイルメイル (Scale Mail)
ホーリーチェイン (Holy Chain)
ルーンスケイル (Rune Scale)
マスターチェイン (Master Chain)
厚手の鎧 (Thick Armor)
ヘヴィアーマー (Heavy Armor)
毛皮のポンチョ (Fur Poncho)
ノーブルマント (Noble Mantle)
ブラックマント (Black Mantle)
マジカルマント (Magical Mantle)
ミラクルマント (Miracle Mantle)
聖者の法衣 (Saint's Robe)
とんがりぼうし (Pointed Hat)
風の帽子 (Wind Hat)
星のサークレット (Star Circlet)
闇夜の帽子 (Dark Night Hat)
アイアンヘッドギア (Iron Headgear)
銀仮面 (Silver Mask)
くろがねのはちがね (Iron Headband)
知力の兜 (Intellect Helm)
ヘヴィヘルム (Heavy Helm)
竜の指輪 (Dragon Ring)
光の指輪 (Light Ring)
闇の指輪 (Dark Ring)
精霊の指輪 (Spirit Ring)
```