2026-03-02 14:28:34 +08:00

827 lines
37 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import csv
from io import StringIO
import re
import shutil
g_ai_cfg_dict = []
# function: read_text_file
def read_text_file(file_path, read_mode='r'):
"""
兼容 UTF-8 和 GBK 编码的文件读取函数
:param file_path: 文件路径
:param read_mode: 读取模式(默认 'r',文本模式)
:return: 文件内容(字符串)
"""
# 先尝试 UTF-8 编码
try:
with open(file_path, read_mode, encoding='utf-8-sig') as f:
return f.read()
except UnicodeDecodeError:
# UTF-8 失败,尝试 GBK 编码
try:
with open(file_path, read_mode, encoding='gbk') as f:
return f.read()
except UnicodeDecodeError:
# 两种编码都失败,抛出异常
raise Exception(f"文件 {file_path} 不支持 UTF-8 和 GBK 编码")
# function: parse_csv_to_dict
def parse_csv_to_dict(csv_str):
"""将CSV字符串解析为字典列表"""
string_io = StringIO(csv_str)
csv_reader = csv.DictReader(string_io)
data = []
for row in csv_reader:
if has_content(row) and is_row_empty(row) == False:
data.append(dict(row)) # 转换为普通字典
return data
def remove_first_line_find(text):
"""
使用 find 方法找到第一个换行符并切片
"""
first_newline = text.find('\n')
if first_newline == -1:
return "" # 没有换行符,说明只有一行
return text[first_newline + 1:]
# function: parse_csv_to_dict2
def parse_csv_to_dict2(csv_str):
"""将CSV字符串解析为字典列表"""
csv_str = remove_first_line_find(csv_str)
string_io = StringIO(csv_str)
csv_reader = csv.DictReader(string_io)
data = []
idx = 0
for row in csv_reader:
if idx > 0 and has_content(row) and is_row_empty(row) == False:
data.append(dict(row)) # 转换为普通字典
idx = idx + 1
return data
def has_content(s):
return s is not None and len(s) > 0
def is_row_empty(row):
is_empty = True
for key, value in row.items():
if value != '':
is_empty = False
break
return is_empty
# function: calc_story_end_idx
def calc_story_range_list(csv_data):
story_ranges = []
for i, item_data in enumerate(csv_data):
if has_content(item_data['关卡']):
story_ranges.append(i)
story_ranges.append(len(csv_data))
story_range_list = []
for i in range(len(story_ranges)-1):
story_range_list.append({'start': story_ranges[i], 'end': story_ranges[i+1]})
return story_range_list
# functino: make_story_data
def make_story_data(csv_data, start_idx, end_idx):
start_csv_line = csv_data[start_idx]
story_type = start_csv_line['剧情分类']
story_data = {
'id': start_csv_line['ID'],
'map_level': start_csv_line['关卡'],
'task_title': start_csv_line['任务标题'],
'story_type': story_type,
'story_intro': [],
#'B1_add_heart': start_csv_line['分支1好感度'],
#'B1_reward': start_csv_line['分支1奖励'],
'B1_scripts': [],
#'B2_add_heart': start_csv_line['分支2好感度'],
#'B2_reward': start_csv_line['分支2奖励'],
'B2_scripts': [],
#'B3_add_heart': start_csv_line['分支3好感度'],
#'B3_reward': start_csv_line['分支3奖励'],
'B3_scripts': [],
}
story_intro = []
idx = 0
for i in range(start_idx, end_idx):
csv_line = csv_data[i]
if has_content(csv_line['聊天前要']):
story_intro.append(csv_line['聊天前要'])
# 分支1
story_data['B1_scripts'].append({'idx': idx, 'name': csv_line['分支1角色'], 'script': csv_line['分支1台词'], 'story_intro':csv_line['聊天前要']})
# if csv_line['分支1角色'] != '' and csv_line['分支1台词'] != '':
# story_data['B1_scripts'].append({'idx': idx, 'name': csv_line['分支1角色'], 'script': csv_line['分支1台词']})
# 分支2
story_data['B2_scripts'].append({'idx': idx, 'name': csv_line['分支2角色'], 'script': csv_line['分支2台词'], 'story_intro':csv_line['聊天前要']})
# if csv_line['分支2角色'] != '' and csv_line['分支2台词'] != '':
# story_data['B2_scripts'].append({'idx': idx, 'name': csv_line['分支2角色'], 'script': csv_line['分支2台词']})
# 分支3
story_data['B3_scripts'].append({'idx': idx, 'name': csv_line['分支3角色'], 'script': csv_line['分支3台词'], 'story_intro':csv_line['聊天前要']})
# if csv_line['分支3角色'] != '' and csv_line['分支3台词'] != '':
# story_data['B3_scripts'].append({'idx': idx, 'name': csv_line['分支3角色'], 'script': csv_line['分支3台词']})
idx = idx + 1
story_data['story_intro'] = story_intro
return story_data
# functino: make_language_key
g_language_strs = {}
def make_language_key(idx, str):
if str == '':
return ''
key = "ST%s"%(idx)
if key in g_language_strs:
print("ERR: in g_language_strs key %s:%s:%s exist!!!!"%(key,g_language_strs[key], str))
exit()
if has_content(str):
g_language_strs[key] = str
return key
def make_language_story_opt_key(idx, str):
if str == '':
return ''
key = "SOPT%s"%(idx)
if key in g_language_strs:
print("ERR: in g_language_strs key %s:%s:%s exist!!!!"%(key,g_language_strs[key], str))
exit()
if has_content(str):
g_language_strs[key] = str
return key
def make_language_story_intro_key(idx, str):
# if str == '':
# return ''
# key = "SINTRO%s"%(idx)
# if key in g_language_strs:
# print("ERR: in g_language_strs key %s:%s:%s exist!!!!"%(key,g_language_strs[key], str))
# exit()
# if has_content(str):
# g_language_strs[key] = str
# return key
return str
def make_language_story_title_key(idx, str):
if str == '':
return ''
key = "STITLE%s"%(idx)
if key in g_language_strs:
print("ERR: in g_language_strs key %s:%s:%s exist!!!!"%(key,g_language_strs[key], str))
exit()
if has_content(str):
g_language_strs[key] = str
return key
def make_language_key2(key, str):
if str == '':
return ''
if has_content(str):
g_language_strs[key] = str
return key
# functino: get_language_name_key
# g_actor_info_dict = [
# {'StoryNpcId': 20000, 'NameKey': 'system', 'Name': '系统', 'Img': 'system', 'Head': 'PlayerHeads/player_head_1'},
# {'StoryNpcId': 20001, 'NameKey': 'player', 'Name': '玩家', 'Img': 'player', 'Head': 'PlayerHeads/player_head_1'},
# {'StoryNpcId': 20002, 'NameKey': 'actor_nvshen', 'Name': '女神', 'Img': 'HeroDraw/Npc_01', 'Head': 'PlayerHeads/player_head_nvshen'},
# {'StoryNpcId': 20003, 'NameKey': 'actor_weier', 'Name': '薇儿', 'Img': 'HeroDraw/Npc_02', 'Head': 'PlayerHeads/player_head_weier'},
# {'StoryNpcId': 20004, 'NameKey': 'actor_xifu', 'Name': '希芙', 'Img': 'HeroDraw/Npc_03', 'Head': 'PlayerHeads/player_head_xifu'},
# {'StoryNpcId': 20005, 'NameKey': 'actor_furuiya', 'Name': '芙蕾雅', 'Img': 'HeroDraw/Npc_04', 'Head': 'PlayerHeads/player_head_furuiya'},
# {'StoryNpcId': 20006, 'NameKey': 'actor_yideng', 'Name': '伊登', 'Img': 'HeroDraw/Npc_05', 'Head': 'PlayerHeads/player_head_yideng'},
# {'StoryNpcId': 20007, 'NameKey': 'actor_haila', 'Name': '海拉', 'Img': 'HeroDraw/Npc_06', 'Head': 'PlayerHeads/player_head_haila'},
# {'StoryNpcId': 20008, 'NameKey': 'actor_waerjili', 'Name': '瓦尔基里', 'Img': 'HeroDraw/Npc_07', 'Head': 'PlayerHeads/player_head_waerjili'}
# ]
g_actor_info_dict = []
def get_actor_info(name):
for value in g_actor_info_dict:
if value['Name'] == name:
return value
print("[get_actor_info] no find actor info name: " + name)
return None
g_StoryRewardCfg = []
# functino: create_story_cfg
def create_story_cfg(story_id, task_title, story_type, story_npc_id, map_level, story_intro, story_selection_texts, story_selection_next,
story_force_guide_group, story_condition):
task_title_key = make_language_story_title_key(story_id, task_title)
return {
'Id': int(story_id),
'StoryId': int(story_id),
'TaskTitle': task_title_key,
'Type': int(story_type),
'StoryNpcId': int(story_npc_id),
'MapLevel': int(map_level),
'StoryIntro': story_intro,
'SelectionTexts': story_selection_texts,
'SelectionNext': story_selection_next,
'NeedBg': False,
'HideUi': False,
'Transition': False,
'TransitionType': 3,
'Skip': False,
'PlayInterval': 5,
'ProgramControl': True,
'NeedSave': len(story_selection_texts) > 0,
'ForceGuideGroup': story_force_guide_group,
'Condition': story_condition,
'Group': '',
'DataCheck': ''
}
# function: create_stroyPerformCfg, act_type: 'RoleMovein', 'RoleSpeaking', 'RoleMoveout'
def create_stroyPerformCfg(script_info_list, story_id, story_type, start_idx, end_idx):
cfgs = []
idx = 0
type_idx = 0
if start_idx <= end_idx:
for script_info in script_info_list[start_idx:end_idx+1]:
if has_content(script_info['script']):
idx += 1
story_perform_id = str(int(story_id)*100 + idx)
SpeakSite = 1
SpeakId = make_language_key(story_perform_id, script_info['script'])
LeftName = ''
LeftImg = ''
LeftAct = ''
RightName = ''
RightImg = ''
RightAct = ''
actor_info = get_actor_info(script_info['name'])
if has_content(script_info['story_intro']):
type_idx += 1
print(script_info['story_intro'])
if actor_info == None:
print("ERR: not find actor name, story_id=" + story_id)
if actor_info['NameKey'] == 'player':
if idx == 1:
SpeakSite = 2
LeftName = ''
LeftImg = ''
LeftAct = ''
RightImg = actor_info['Img']
RightName = actor_info['NameKey']
if story_type == 0:
RightImg = actor_info['Img']
else:
RightImg = actor_info['Head']
RightAct = ''
else:
SpeakSite = 2
LeftName = ''
LeftImg = ''
LeftAct = 'RoleMoveout'
RightImg = actor_info['Img']
RightName = actor_info['NameKey']
if story_type == 0:
RightImg = actor_info['Img']
else:
RightImg = actor_info['Head']
RightAct = 'RoleMovein'
else:
if idx == 1:
SpeakSite = 1
LeftName = actor_info['NameKey']
LeftImg = actor_info['Img']
if story_type == 0:
LeftImg = actor_info['Img']
else:
LeftImg = actor_info['Head']
LeftAct = ''
RightName = ''
RightImg = ''
RightAct = ''
else:
SpeakSite = 1
LeftName = actor_info['NameKey']
LeftImg = actor_info['Img']
if story_type == 0:
LeftImg = actor_info['Img']
else:
LeftImg = actor_info['Head']
LeftAct = 'RoleMovein'
RightName = ''
RightImg = ''
RightAct = 'RoleMoveout'
cfgs.append({
'Id': story_perform_id, 'StoryId': story_id, 'Type': type_idx, 'LeftAct': LeftAct, 'LeftActBgTime': 0,
'RightAct': RightAct, 'RightActBgTime': 0, 'LeftName': LeftName, 'LeftNameColour': 'title02', 'LeftImg': LeftImg,
'RightName': RightName, 'RightNameColour': 'title01', 'RightImg': RightImg, 'SpeakSite': SpeakSite, 'SpeakId': SpeakId, 'SpeakTime': 0,
'WordTime': 10, 'Camp': '', 'CfgId': '', 'Dir': '', 'DirStartTime': '',
'AniName': '', 'AniStartTime': '', 'Eff': '', 'EffStartTime': '', 'OverTime': 0
})
# 如果是对话框对话,就要在首尾添加入场配置和退场配置
''' 这个是以前的RO对话剧情必须在首位添加配置现在暂时屏蔽了用漫画剧情
if story_type == 0:
story_perform_id = str(int(story_id)*100 + 0)
LeftName = cfgs[0]['LeftName']
LeftImg = cfgs[0]['LeftImg']
RightName = cfgs[0]['RightName']
RightImg = cfgs[0]['RightImg']
LeftAct = ""
RightAct = ""
if LeftName != "":
LeftAct = "RoleMovein"
if RightName != "":
RightAct = "RoleMovein"
cfgs.insert(0, {
'Id': story_perform_id, 'StoryId': story_id, 'Type': 0, 'LeftAct': LeftAct, 'LeftActBgTime': 0,
'RightAct': RightAct, 'RightActBgTime': 0, 'LeftName': LeftName, 'LeftNameColour': 'title02', 'LeftImg': LeftImg,
'RightName': RightName, 'RightNameColour': 'title01', 'RightImg': RightImg, 'SpeakSite': 0, 'SpeakId': '', 'SpeakTime': 0,
'WordTime': 0, 'Camp': '', 'CfgId': '', 'Dir': '', 'DirStartTime': '',
'AniName': '', 'AniStartTime': '', 'Eff': '', 'EffStartTime': '', 'OverTime': 0
})
story_perform_id = str(int(story_id)*100 + len(cfgs))
LeftName = cfgs[-1]['LeftName']
LeftImg = cfgs[-1]['LeftImg']
RightName = cfgs[-1]['RightName']
RightImg = cfgs[-1]['RightImg']
cfgs.append({
'Id': story_perform_id, 'StoryId': story_id, 'Type': 0, 'LeftAct': 'RoleMoveout', 'LeftActBgTime': 0,
'RightAct': 'RoleMoveout', 'RightActBgTime': 0, 'LeftName': LeftName, 'LeftNameColour': 'title02', 'LeftImg': LeftImg,
'RightName': RightName, 'RightNameColour': 'title01', 'RightImg': RightImg, 'SpeakSite': 0, 'SpeakId': '', 'SpeakTime': 0,
'WordTime': 0, 'Camp': '', 'CfgId': '', 'Dir': '', 'DirStartTime': '',
'AniName': '', 'AniStartTime': '', 'Eff': '', 'EffStartTime': '', 'OverTime': 0
})
'''
for i, cfg_item in enumerate(cfgs):
if cfg_item == None:
print("----cfg_item is None-----")
#print(cfg_item)
return cfgs
# function: make_story_cfg
def make_story_cfg(story_cfgs, stroyPerformCfgV2_cfgs, story_data):
ID = story_data['id']
level = story_data['map_level']
task_title = story_data['task_title']
story_type = 0
story_npc_id = 0
if '对话' in story_data['story_type']:
story_type = 0
elif '聊天' in story_data['story_type']:
story_type = 1
strs = story_data['story_type'].split(':')
if len(strs) == 2:
story_type = 0
if strs[0] == '对话':
story_type = 0
elif strs[0] == '聊天':
story_type = 1
actor_info = get_actor_info(strs[1])
story_npc_id = int(actor_info['StoryNpcId'])
story_force_guide_group = 0
story_condition = ''
has_multi_options = False
for i in range(len(story_data['B1_scripts'])):
if has_content(story_data['B1_scripts'][i]['script']) and has_content(story_data['B2_scripts'][i]['script']) and has_content(story_data['B3_scripts'][i]['script']):
story_id = "%s0" % (ID)
story1_id = "%s1" % (ID)
story2_id = "%s2" % (ID)
story3_id = "%s3" % (ID)
story1_opt_1 = make_language_story_opt_key(story1_id, story_data['B1_scripts'][i]['script'])
story1_opt_2 = make_language_story_opt_key(story2_id, story_data['B2_scripts'][i]['script'])
story1_opt_3 = make_language_story_opt_key(story3_id, story_data['B3_scripts'][i]['script'])
story_intro_keys = []
for story_intro_i in range(len(story_data['story_intro'])):
story_intro_keys.append(make_language_story_intro_key(int(story_id)*100+story_intro_i, story_data['story_intro'][story_intro_i]))
story_intro_str = ';'.join(story_intro_keys)
story1_selection_texts = "%s;%s;%s" % (story1_opt_1, story1_opt_2, story1_opt_3)
story1_selection_next = "%s;%s;%s" % (story1_id, story2_id, story3_id)
story_cfgs.append(create_story_cfg(story_id, task_title, story_type, story_npc_id, level, story_intro_str, story1_selection_texts, story1_selection_next, story_force_guide_group, story_condition))
story_cfgs.append(create_story_cfg(story1_id, task_title, story_type, story_npc_id, level, '', '', '', 0, ''))
story_cfgs.append(create_story_cfg(story2_id, task_title, story_type, story_npc_id, level, '', '', '', 0, ''))
story_cfgs.append(create_story_cfg(story3_id, task_title, story_type, story_npc_id, level, '', '', '', 0, ''))
if story_type == 1:
stroyPerformCfgV2_cfgs.extend(create_stroyPerformCfg(story_data['B1_scripts'], story_id, story_type, 0, i-1))
stroyPerformCfgV2_cfgs.extend(create_stroyPerformCfg(story_data['B1_scripts'], story1_id, story_type, i+1, len(story_data['B1_scripts'])-1))
stroyPerformCfgV2_cfgs.extend(create_stroyPerformCfg(story_data['B2_scripts'], story2_id, story_type, i+1, len(story_data['B2_scripts'])-1))
stroyPerformCfgV2_cfgs.extend(create_stroyPerformCfg(story_data['B3_scripts'], story3_id, story_type, i+1, len(story_data['B3_scripts'])-1))
has_multi_options = True
break
if has_content(story_data['B1_scripts'][i]['script']) and has_content(story_data['B2_scripts'][i]['script']) and has_content(story_data['B3_scripts'][i]['script']) == False:
story_id = "%s0" % (ID)
story1_id = "%s1" % (ID)
story2_id = "%s2" % (ID)
story1_opt_1 = make_language_story_opt_key(story1_id, story_data['B1_scripts'][i]['script'])
story1_opt_2 = make_language_story_opt_key(story2_id, story_data['B2_scripts'][i]['script'])
story_intro_keys = []
for story_intro_i in range(len(story_data['story_intro'])):
story_intro_keys.append(make_language_story_intro_key(int(story_id)*100+story_intro_i, story_data['story_intro'][story_intro_i]))
story_intro_str = ';'.join(story_intro_keys)
story1_selection_texts = "%s;%s" % (story1_opt_1, story1_opt_2)
story1_selection_next = "%s;%s" % (story1_id, story2_id)
story_cfgs.append(create_story_cfg(story_id, task_title, story_type, story_npc_id, level, story_intro_str, story1_selection_texts, story1_selection_next, story_force_guide_group, story_condition))
story_cfgs.append(create_story_cfg(story1_id, task_title, story_type, story_npc_id, level, '', '', '', 0, ''))
story_cfgs.append(create_story_cfg(story2_id, task_title, story_type, story_npc_id, level, '', '', '', 0, ''))
if story_type == 1:
stroyPerformCfgV2_cfgs.extend(create_stroyPerformCfg(story_data['B1_scripts'], story_id, story_type, 0, i-1))
stroyPerformCfgV2_cfgs.extend(create_stroyPerformCfg(story_data['B1_scripts'], story1_id, story_type, i+1, len(story_data['B1_scripts'])-1))
stroyPerformCfgV2_cfgs.extend(create_stroyPerformCfg(story_data['B2_scripts'], story2_id, story_type, i+1, len(story_data['B2_scripts'])-1))
has_multi_options = True
break
if has_multi_options == False:
story_id = "%s0" % (ID)
story_intro_keys = []
for story_intro_i in range(len(story_data['story_intro'])):
story_intro_keys.append(make_language_story_intro_key(int(story_id)*100+story_intro_i, story_data['story_intro'][story_intro_i]))
story_intro_str = ';'.join(story_intro_keys)
story_cfgs.append(create_story_cfg(story_id, task_title, story_type, story_npc_id, level, story_intro_str, '', '', story_force_guide_group, story_condition))
if story_type == 1:
stroyPerformCfgV2_cfgs.extend(create_stroyPerformCfg(story_data['B1_scripts'], story_id, story_type, 0, len(story_data['B1_scripts'])-1))
# function: generate_StoryCfgV2
def generate_StoryCfgV2(out_path, data):
with open(out_path+'/StoryCfgV2.csv', 'w', newline='', encoding='utf-8') as file:
fieldnames = ['序列ID', '触发剧情ID', '剧情标题', '剧情类型0是对话其他ChatNpcId', '剧情NpcId', '关卡', '剧情介绍',
'选项显示', '继续下一个剧情', '是否底图', '是否隐藏UI',
'是否转场', '转场类型', '是否可跳过', '剧情播放间隔时间s',
'是否需要程序驱动', '是否存盘', '强制引导', '触发条件', '同组', '数据判断']
row1 = ['Id', 'StoryId', 'StoryTitle', 'Type', 'StoryNpcId', 'MapLevel', "StoryIntro",
'SelectionTexts', 'SelectionNext', 'NeedBg', 'HideUi',
'Transition', 'TransitionType', 'Skip', 'PlayInterval',
'ProgramControl', 'NeedSave', 'ForceGuideGroup', 'Condition', 'Group', 'DataCheck']
row2 = ['int', 'int', 'string', 'int', 'int', 'int', 'list',
'list', 'list', 'bool', 'bool',
'bool', 'int', 'bool', 'int',
'bool', 'bool', 'int', 'list', 'list', 'list']
csv_data = []
csv_data.append(fieldnames)
csv_data.append(row1)
csv_data.append(row2)
for i, data_item in enumerate(data):
csv_data.append(data_item.values())
writer = csv.writer(file)
writer.writerows(csv_data)
#print("\n--- StoryCfgV2.csv ---")
#print(csv_data)
# function: generate_StroyPerformCfgV2
def generate_StroyPerformCfgV2(out_path, data):
with open(out_path+'/StroyPerformCfgV2.csv', 'w', newline='', encoding='utf-8') as file:
fieldnames = ['序列ID', '剧情ID', '类型', '左侧行为',
'左侧行为开始时间', '右侧行为', '右侧行为时间', '左侧姓名',
'左侧姓名颜色', '左侧半身像', '右侧姓名', '右侧姓名颜色',
'阵营', '配置ID', '面向', '面向开始时间',
'动作名字', '动作开始时间', '特效ID', '特效开始时间', '结束时间']
row1 = ['Id', 'StoryId', 'Type', 'LeftAct',
'LeftActBgTime', 'RightAct', 'RightActBgTime', 'LeftName',
'LeftNameColour', 'LeftImg', 'RightName', 'RightNameColour',
'RightImg', 'SpeakSite', 'SpeakId', 'SpeakTime',
'WordTime', 'Camp', 'CfgId', 'Dir',
'DirStartTime', 'AniName', 'AniStartTime', 'Eff', 'EffStartTime', 'OverTime']
row2 = ['int', 'int', 'int', 'string',
'int', 'string', 'int', 'string',
'string', 'string', 'string', 'string',
'string', 'int', 'string', 'int',
'int', 'list', 'list', 'list',
'list', 'list', 'list', 'list', 'list', 'int']
csv_data = []
csv_data.append(fieldnames)
csv_data.append(row1)
csv_data.append(row2)
print("\n--- StroyPerformCfgV2.csv ---")
for i, data_item in enumerate(data):
if data_item == None:
print("data_item: None " + str(i))
csv_data.append(data_item.values())
writer = csv.writer(file)
writer.writerows(csv_data)
# function: generate_StoryNpcCfgV2
def generate_StoryNpcCfgV2(out_path, storyNpcCfg):
with open(out_path+'/StoryNpcCfgV2.csv', 'w', newline='', encoding='utf-8') as file:
fieldnames = ['序列ID', 'Story NPC ID', '类型(1妻子2情人3陌生人,4群聊0其他)', '昵称Key', '昵称',
'头像', '对话框半身像', '地点', '年龄',
'民族', '婚姻状况', '签名', '发现动态内容',
'发现动态图片', '发现动态点赞数', '发现动态评论数', '关卡解锁',
'主角等级解锁', '爬塔层数解锁', '撩一撩剧情']
row1 = ['Id', 'StoryNpcId', 'Type', 'NameKey', 'Name',
'Head', 'Img', 'Location', 'Age',
'Nation', 'Marry', 'Sign', 'Post',
'Photos', 'Upvote', 'Comment', 'MapLevel',
'PlayerLevel', 'TowerLevel', 'StoryId']
row2 = ['int', 'int', 'int', 'string', 'string',
'string', 'string', 'string', 'int',
'string', 'string', 'string', 'string',
'list', 'int', 'int', 'int',
'int', 'int', 'int']
csv_data = []
csv_data.append(fieldnames)
csv_data.append(row1)
csv_data.append(row2)
print("\n--- StoryNpcCfgV2.csv ---")
for i, data_item in enumerate(storyNpcCfg):
if data_item == None:
print("data_item: None " + str(i))
data_item['Location'] = data_item['Location']
data_item['Nation'] = data_item['Nation']
data_item['Marry'] = data_item['Marry']
data_item['Sign'] = make_language_key2("NPCSign%s"%(data_item['Id']), data_item['Sign'])
data_item['Post'] = make_language_key2("NPCPost%s"%(data_item['Id']), data_item['Post'])
csv_data.append(data_item.values())
#print(data_item.values())
writer = csv.writer(file)
writer.writerows(csv_data)
# function: generate_StoryRewards, data is storyData
# def generate_StoryRewards(out_path, data):
# with open(out_path+'/StoryRewards.csv', 'w', newline='', encoding='utf-8') as file:
# fieldnames = ['剧情Id', '关卡条件', '增加好感度NPC', '增加好感度', '剧情奖励1', '剧情奖励2', '剧情奖励3',
# '剧情奖励4', '剧情奖励5', '剧情奖励6', '剧情奖励7', '剧情奖励8']
# row1 = ['StoryId', 'MapLevel', 'AddHeartNpc', 'AddHeart', 'Reward1', 'Reward2', 'Reward3', 'Reward4',
# 'Reward5', 'Reward6', 'Reward7', 'Reward8']
# row2 = ['int', 'int', 'int', 'int', 'list', 'list', 'list', 'list',
# 'list', 'list', 'list', 'list']
# csv_data = []
# csv_data.append(fieldnames)
# csv_data.append(row1)
# csv_data.append(row2)
# for i, data_item in enumerate(data):
# story_id = data_item['StoryId']
# map_level = data_item['MapLevel']
# reward_text = data_item['Reward']
# pattern = r'\{([^}]+)\}'
# matches = re.findall(pattern, reward_text)
# row = {'StoryId': story_id, 'MapLevel': map_level, 'AddHeartNpc': data_item['StoryNpcId'], 'AddHeart': data_item['AddHeart']}
# for i in range(8):
# row[f"Reward{i+1}"] = ''
# for i in range(len(matches)):
# row[f"Reward{i+1}"] = matches[i]
# csv_data.append(row.values())
# writer = csv.writer(file)
# writer.writerows(csv_data)
# function: generate_LanguagePackageV2_cn
def generate_LanguagePackageV2_cn(out_path, data):
with open(out_path+'/../../../Assets/Content/Config/LanguagePackageV2_cn.csv', 'w', newline='', encoding='utf-8') as file:
fieldnames = ['key', '内容']
row1 = ['key', 'Language']
row2 = ['string', 'string']
csv_data = []
csv_data.append(fieldnames)
csv_data.append(row1)
csv_data.append(row2)
for actor_info in g_actor_info_dict:
csv_data.append([actor_info['NameKey'], actor_info['Name']])
for key, value in data.items():
csv_data.append([key, value])
writer = csv.writer(file)
writer.writerows(csv_data)
print("\n--- LanguagePackageV2_cn.csv ---")
#print(csv_data)
def generate_StoryAICfgV2(out_path, storyAICfg):
with open(out_path+'/StoryAICfgV2.csv', 'w', newline='', encoding='utf-8') as file:
fieldnames =['序号', '剧情NPC', '剧情ID', '类型1-发送2-响应)', '消息']
row1 = ['Id', 'StoryNpcId', 'StoryId', 'Type', 'Message']
row2 = ['int', 'int', 'int', 'int', 'string']
csv_data = []
csv_data.append(fieldnames)
csv_data.append(row1)
csv_data.append(row2)
print("\n--- StoryAICfgV2.csv ---")
for i, data_item in enumerate(storyAICfg):
if data_item == None:
print("data_item: None " + str(i))
data_item['Message'] = make_language_key2("AIT%s"%(data_item['Id']), data_item['Message'])
csv_data.append(data_item.values())
writer = csv.writer(file)
writer.writerows(csv_data)
def calc_level_range(start_level, end_level):
levels = []
curr_level = start_level
while True:
levels.append(curr_level)
curr_level = curr_level + 1
bigMapId = int(curr_level / 10000)
smallMapId = curr_level % 10000
if bigMapId == 1 and smallMapId > 30:
curr_level = (bigMapId+1)*10000 + 1
elif bigMapId == 2 and smallMapId > 35:
curr_level = (bigMapId+1)*10000 + 1
elif bigMapId == 3 and smallMapId > 40:
curr_level = (bigMapId+1)*10000 + 1
elif bigMapId == 4 and smallMapId > 45:
curr_level = (bigMapId+1)*10000 + 1
elif bigMapId == 5 and smallMapId > 50:
curr_level = (bigMapId+1)*10000 + 1
elif bigMapId == 6 and smallMapId > 50:
curr_level = (bigMapId+1)*10000 + 1
elif bigMapId == 7 and smallMapId > 50:
curr_level = (bigMapId+1)*10000 + 1
elif bigMapId == 8 and smallMapId > 50:
curr_level = (bigMapId+1)*10000 + 1
elif bigMapId == 9 and smallMapId > 50:
curr_level = (bigMapId+1)*10000 + 1
elif bigMapId == 10 and smallMapId > 60:
curr_level = (bigMapId+1)*10000 + 1
elif bigMapId == 11 and smallMapId > 70:
curr_level = (bigMapId+1)*10000 + 1
elif bigMapId == 12 and smallMapId > 80:
curr_level = (bigMapId+1)*10000 + 1
elif bigMapId == 13 and smallMapId > 90:
curr_level = (bigMapId+1)*10000 + 1
elif bigMapId > 13 and smallMapId > 100:
curr_level = (bigMapId+1)*10000 + 1
if curr_level >= end_level:
break
str = ""
for level in levels:
str = str + f"1:{level};"
return str
def generate_StoryTaskV2(out_path, StoryCfgV2_lines, storyNpcCfg):
csv_data = []
csv_data.append(['主任务ID', '剧情ID', '子任务列表(1:关卡;2:炼之塔层数;3:撩一撩StoryNpcId;4:女神消息StoryId;5:玩家等级)'])
csv_data.append(['Id', 'StoryId', 'SubTasks'])
csv_data.append(['int', 'int', 'list'])
csv_data.append([1, 10, '1:10001;'])
npcRecord = {}
for i in range(1, len(StoryCfgV2_lines)):
data_item = StoryCfgV2_lines[i]
last_data_item = StoryCfgV2_lines[i-1]
Id = i
StoryId = data_item['StoryId']
SubTasks = ''
if last_data_item['Type'] == 1 and last_data_item['StoryNpcId'] > 0:
if npcRecord.get(last_data_item['StoryNpcId']):
SubTasks += f"4:{last_data_item['StoryNpcId']};"
else:
npcRecord[last_data_item['StoryNpcId']] = True
SubTasks += f"3:{last_data_item['StoryNpcId']};"
SubTasks = SubTasks + calc_level_range(last_data_item['MapLevel'], data_item['MapLevel'])
csv_data.append([Id, StoryId, SubTasks])
with open(out_path+'/StoryTaskCfgV2.csv', 'w', newline='', encoding='utf-8') as file:
writer = csv.writer(file)
writer.writerows(csv_data)
# function: generate_config
def generate_config(story_data_list, out_path):
StoryCfgV2_lines = []
StroyPerformCfgV2_lines = []
LanguagePackage_cn_lines = []
for i, story_data in enumerate(story_data_list):
make_story_cfg(StoryCfgV2_lines, StroyPerformCfgV2_lines, story_data)
generate_StoryAICfgV2(out_path, g_ai_cfg_dict)
generate_StoryNpcCfgV2(out_path, g_actor_info_dict)
generate_StoryCfgV2(out_path, StoryCfgV2_lines)
#generate_StoryRewards(out_path, StoryCfgV2_lines)
generate_StoryTaskV2(out_path, StoryCfgV2_lines, g_actor_info_dict)
generate_StroyPerformCfgV2(out_path, StroyPerformCfgV2_lines)
generate_LanguagePackageV2_cn(out_path, g_language_strs)
# main入口
if __name__ == "__main__":
g_script_dir = os.path.dirname(os.path.abspath(__file__))
g_input_dir = os.path.join(g_script_dir, 'input')
g_out_dir = os.path.join(g_script_dir, 'output')
g_input_dir = g_input_dir.replace('\\', '/')
g_out_dir = g_out_dir.replace('\\', '/')
print('g_input_dir: ' + g_input_dir)
print('g_out_dir: ' + g_out_dir)
g_story_data_list = []
# 1. Read StoryNpcCfg.csv
file_path = os.path.join(g_input_dir, 'StoryNpcCfg.csv')
file_content = read_text_file(file_path)
g_actor_info_dict = parse_csv_to_dict2(file_content)
#shutil.copy(file_path, g_out_dir)
# 2. Read StoryAICfg.csv
file_path = os.path.join(g_input_dir, 'StoryAICfg.csv')
file_content = read_text_file(file_path)
g_ai_cfg_dict = parse_csv_to_dict2(file_content)
#shutil.copy(file_path, g_out_dir)
# 3. Read StoryRewardCfg.csv
file_path = os.path.join(g_input_dir, 'StoryRewardCfg.csv')
file_content = read_text_file(file_path)
g_StoryRewardCfg = parse_csv_to_dict2(file_content)
shutil.copy(file_path, g_out_dir)
file_path = os.path.join(g_input_dir, 'StoryItemCfg.csv')
file_content = read_text_file(file_path)
g_StoryRewardCfg = parse_csv_to_dict2(file_content)
shutil.copy(file_path, g_out_dir)
# 4. Read StoryText.csv
file_path = os.path.join(g_input_dir, 'StoryText.csv')
file_content = read_text_file(file_path)
if file_content is not None:
# 解析csv数据为Dict
csv_data = parse_csv_to_dict(file_content)
# 把csv数据分隔为一段段剧情并生成剧情数据列表story_data_list
story_range_list = calc_story_range_list(csv_data)
for i, story_range in enumerate(story_range_list):
story_data = make_story_data(csv_data, story_range['start'], story_range['end'])
g_story_data_list.append(story_data)
# 根据story_data_list生成配置文件
generate_config(g_story_data_list, g_out_dir)
'''
for filename in os.listdir(g_input_dir):
if filename.endswith('.csv'):
file_path = os.path.join(g_input_dir, filename)
file_content = read_text_file(file_path)
if file_content is not None:
print(f"=== {filename} ===")
# 解析csv数据为Dict
csv_data = parse_csv_to_dict(file_content)
# 把csv数据分隔为一段段剧情并生成剧情数据列表story_data_list
story_range_list = calc_story_range_list(csv_data)
for i, story_range in enumerate(story_range_list):
story_data = make_story_data(csv_data, story_range['start'], story_range['end'])
g_story_data_list.append(story_data)
#print("--- story_data ---")
#print(story_data)
#print()
# 根据story_data_list生成配置文件
generate_config(g_story_data_list, g_out_dir)
else:
print(f"无法读取文件: {filename}")
'''