全站通知:
模块:GiftTastesNPC/data/doc
刷
历
编
< 模块:GiftTastesNPC | data
跳到导航
跳到搜索
当前页面的数据通过以下 Python 代码生成,后续如果游戏版本更新,可重新执行脚本,导出最新的数据。
本 Python 脚本部分内容与 MediaWiki 解析发生冲突,原脚本:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
星露谷物语 NPCGiftTastes.zh-CN.json 转 Lua 数据转换器
此脚本将 NPCGiftTastes.zh-CN.json 文件转换为 Lua 数据格式。
NPCGiftTastes数据格式说明:
1. Universal_* 键: 通用喜好,对所有村民有效
- 值为用空格分隔的ID数组
- 正数表示物品ID,负数表示类别ID
2. NPC名称键: 个人喜好,格式为用"/"分隔的字符串
结构: 最爱对话/最爱物品ID/喜欢对话/喜欢物品ID/不喜欢对话/不喜欢物品ID/讨厌对话/讨厌物品ID/一般对话/一般物品ID
"""
import json
import os
import re
from typing import Dict, List, Any, Union
class NPCGiftTastesConverter:
def __init__(self, input_file: str, output_file: str = None):
"""
初始化转换器
Args:
input_file (str): 输入的JSON文件路径
output_file (str): 输出的Lua文件路径,如果为None则自动生成
"""
self.input_file = input_file
self.output_file = output_file or self._generate_output_filename()
# 通用喜好级别映射
self.universal_levels = [
'Universal_Love',
'Universal_Like',
'Universal_Neutral',
'Universal_Dislike',
'Universal_Hate'
]
# 个人喜好级别映射(索引对应NPC数据中的位置)
self.personal_levels = [
'love', # 0,1 最爱
'like', # 2,3 喜欢
'dislike', # 4,5 不喜欢
'hate', # 6,7 讨厌
'neutral' # 8,9 一般
]
def _generate_output_filename(self) -> str:
"""生成输出文件名"""
base_name = os.path.splitext(self.input_file)[0]
return f"{base_name}.lua"
def _escape_lua_string(self, text: str) -> str:
"""转义Lua字符串中的特殊字符"""
if not text:
return '""'
# 转义特殊字符
text = text.replace('\\', '\\\\')
text = text.replace('"', '\\"')
text = text.replace('\n', '\\n')
text = text.replace('\r', '\\r')
text = text.replace('\t', '\\t')
return f'"{text}"'
def _parse_id_list(self, id_string: str) -> List[Union[int, str]]:
"""解析空格分隔的ID列表,可以是数字或字符串"""
if not id_string or id_string.strip() == '':
return []
ids = []
for id_str in id_string.strip().split():
try:
# 尝试将ID转换为整数
ids.append(int(id_str))
except ValueError:
# 如果不是数字,可能是特殊标识符 (例如物品的英文名),作为字符串保留
ids.append(id_str)
return ids
def _parse_npc_data(self, npc_data: str) -> Dict[str, Any]:
"""
解析NPC个人喜好数据
格式: 最爱对话/最爱物品/喜欢对话/喜欢物品/不喜欢对话/不喜欢物品/讨厌对话/讨厌物品/一般对话/一般物品
"""
parts = npc_data.split('/')
# 确保有足够的部分(至少10个部分)
while len(parts) < 10:
parts.append('')
result = {}
for i, level in enumerate(self.personal_levels):
dialogue_index = i * 2
items_index = i * 2 + 1
dialogue = parts[dialogue_index] if dialogue_index < len(parts) else ''
items_str = parts[items_index] if items_index < len(parts) else ''
result[level] = {
'dialogue': dialogue.strip(),
'items': self._parse_id_list(items_str)
}
return result
def _convert_to_lua_table(self, data: Any, indent: int = 0) -> str:
"""将数据转换为Lua表格式"""
indent_str = ' ' * indent
if isinstance(data, dict):
if not data:
return '{}'
lines = ['{']
for key, value in data.items():
# 确保键名是有效的Lua标识符或使用方括号语法
if isinstance(key, str) and re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', key):
key_str = key
else:
key_str = f'[{self._escape_lua_string(str(key))}]'
value_str = self._convert_to_lua_table(value, indent + 1)
lines.append(f'{indent_str} {key_str} = {value_str},')
lines.append(f'{indent_str}}}')
return '\n'.join(lines)
elif isinstance(data, list):
if not data:
return '{}'
# 如果是纯数字数组,使用紧凑格式
if all(isinstance(x, (int, float)) for x in data):
return '{' + ', '.join(str(x) for x in data) + '}'
# 否则,使用多行格式以提高可读性
else:
lines = ['{']
for item in data:
item_str = self._convert_to_lua_table(item, indent + 1)
lines.append(f'{indent_str} {item_str},')
lines.append(f'{indent_str}}}')
return '\n'.join(lines)
elif isinstance(data, str):
return self._escape_lua_string(data)
elif isinstance(data, (int, float)):
return str(data)
elif isinstance(data, bool):
return 'true' if data else 'false'
elif data is None:
return 'nil'
else:
return self._escape_lua_string(str(data))
def convert(self) -> None:
"""执行转换"""
print(f"开始转换: {self.input_file}")
# 读取JSON文件
try:
with open(self.input_file, 'r', encoding='utf-8') as f:
json_data = json.load(f)
except FileNotFoundError:
print(f"错误: 找不到文件 {self.input_file}")
return
except json.JSONDecodeError as e:
print(f"错误: JSON解析失败 - {e}")
return
except Exception as e:
print(f"错误: 读取文件失败 - {e}")
return
# 准备Lua数据结构
lua_data = {
'universal': {},
'npcs': {}
}
# 处理通用喜好
for level in self.universal_levels:
if level in json_data:
level_name = level.replace('Universal_', '').lower()
lua_data['universal'][level_name] = self._parse_id_list(json_data[level])
# 处理NPC个人喜好
for key, value in json_data.items():
if not key.startswith('Universal_'):
lua_data['npcs'][key] = self._parse_npc_data(value)
# 生成Lua文件内容
lua_content = self._generate_lua_file(lua_data)
# 写入Lua文件
try:
with open(self.output_file, 'w', encoding='utf-8') as f:
f.write(lua_content)
print(f"转换完成: {self.output_file}")
print(f"- 通用喜好级别: {len(lua_data['universal'])}")
print(f"- NPC数量: {len(lua_data['npcs'])}")
except Exception as e:
print(f"错误: 写入文件失败 - {e}")
def _generate_lua_file(self, data: Dict[str, Any]) -> str:
"""生成完整的Lua文件内容"""
header = '''--[[
星露谷物语 NPC礼物喜好数据 (中文版)
由脚本自动生成
数据结构说明:
- universal: 通用喜好,对所有NPC有效
- love/like/neutral/dislike/hate: 各级别喜好的物品/类别ID数组
- npcs: 各NPC的个人喜好
- [NPC名称]: NPC的个人喜好数据
- love/like/neutral/dislike/hate: 各级别的对话和物品数据
- dialogue: 对应级别的对话文本
- items: 对应级别的物品/类别ID数组
注意:
- 正数ID表示物品ID,负数ID表示类别ID
- 物品ID也可能是字符串形式(例如英文原名)
- 个人喜好会覆盖通用喜好
--]]
'''
lua_table = self._convert_to_lua_table(data)
return f'{header}local NPCGiftTastes = {lua_table}\n\nreturn NPCGiftTastes\n'
def main():
"""主函数"""
# 请确保此路径是您系统中正确的路径
input_file = r"C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley\Content (unpacked)\Data\NPCGiftTastes.zh-CN.json"
# 检查输入文件是否存在
if not os.path.exists(input_file):
print(f"错误: 输入文件不存在: {input_file}")
print("请检查 main() 函数中的 input_file 路径是否正确。")
return
# 创建转换器并执行转换
converter = NPCGiftTastesConverter(input_file)
converter.convert()
print("\n脚本执行完毕!")
if __name__ == '__main__':
main()