2025-11-10 18:04:15 +08:00
|
|
|
|
import os
|
|
|
|
|
|
import csv
|
|
|
|
|
|
from io import StringIO
|
2025-11-13 21:33:51 +08:00
|
|
|
|
import re
|
2025-11-18 14:37:23 +08:00
|
|
|
|
import shutil
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
2025-11-20 16:56:06 +08:00
|
|
|
|
g_ai_cfg_dict = []
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
|
|
|
|
|
# function: read_text_file
|
2025-11-12 19:42:32 +08:00
|
|
|
|
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 编码
|
2025-11-10 18:04:15 +08:00
|
|
|
|
try:
|
2025-11-12 19:42:32 +08:00
|
|
|
|
with open(file_path, read_mode, encoding='gbk') as f:
|
|
|
|
|
|
return f.read()
|
2025-11-10 18:04:15 +08:00
|
|
|
|
except UnicodeDecodeError:
|
2025-11-12 19:42:32 +08:00
|
|
|
|
# 两种编码都失败,抛出异常
|
|
|
|
|
|
raise Exception(f"文件 {file_path} 不支持 UTF-8 和 GBK 编码")
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 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:
|
2025-11-18 14:37:23 +08:00
|
|
|
|
if has_content(row) and is_row_empty(row) == False:
|
2025-11-12 19:42:32 +08:00
|
|
|
|
data.append(dict(row)) # 转换为普通字典
|
2025-11-10 18:04:15 +08:00
|
|
|
|
return data
|
|
|
|
|
|
|
2025-11-18 14:37:23 +08:00
|
|
|
|
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
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
|
|
|
|
|
def has_content(s):
|
|
|
|
|
|
return s is not None and len(s) > 0
|
|
|
|
|
|
|
2025-11-18 14:37:23 +08:00
|
|
|
|
def is_row_empty(row):
|
|
|
|
|
|
is_empty = True
|
|
|
|
|
|
for key, value in row.items():
|
|
|
|
|
|
if value != '':
|
|
|
|
|
|
is_empty = False
|
|
|
|
|
|
break
|
|
|
|
|
|
return is_empty
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
|
|
|
|
|
# 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]
|
2025-11-18 14:37:23 +08:00
|
|
|
|
story_type = start_csv_line['剧情分类']
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
|
|
|
|
|
story_data = {
|
|
|
|
|
|
'id': start_csv_line['ID'],
|
2025-11-18 14:37:23 +08:00
|
|
|
|
'map_level': start_csv_line['关卡'],
|
2025-11-25 09:24:09 +08:00
|
|
|
|
'task_title': start_csv_line['任务标题'],
|
2025-11-18 14:37:23 +08:00
|
|
|
|
'story_type': story_type,
|
2025-12-29 14:58:24 +08:00
|
|
|
|
'story_intro': [],
|
2025-11-18 14:37:23 +08:00
|
|
|
|
#'B1_add_heart': start_csv_line['分支1好感度'],
|
|
|
|
|
|
#'B1_reward': start_csv_line['分支1奖励'],
|
2025-11-10 18:04:15 +08:00
|
|
|
|
'B1_scripts': [],
|
2025-11-18 14:37:23 +08:00
|
|
|
|
#'B2_add_heart': start_csv_line['分支2好感度'],
|
|
|
|
|
|
#'B2_reward': start_csv_line['分支2奖励'],
|
2025-11-10 18:04:15 +08:00
|
|
|
|
'B2_scripts': [],
|
2025-11-18 14:37:23 +08:00
|
|
|
|
#'B3_add_heart': start_csv_line['分支3好感度'],
|
|
|
|
|
|
#'B3_reward': start_csv_line['分支3奖励'],
|
2025-11-10 18:04:15 +08:00
|
|
|
|
'B3_scripts': [],
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-29 14:58:24 +08:00
|
|
|
|
story_intro = []
|
2025-11-10 18:04:15 +08:00
|
|
|
|
idx = 0
|
|
|
|
|
|
for i in range(start_idx, end_idx):
|
|
|
|
|
|
csv_line = csv_data[i]
|
2025-12-29 14:58:24 +08:00
|
|
|
|
|
|
|
|
|
|
if has_content(csv_line['聊天前要']):
|
|
|
|
|
|
story_intro.append(csv_line['聊天前要'])
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
|
|
|
|
|
# 分支1
|
2026-01-17 17:16:52 +08:00
|
|
|
|
story_data['B1_scripts'].append({'idx': idx, 'name': csv_line['分支1角色'], 'script': csv_line['分支1台词'], 'story_intro':csv_line['聊天前要']})
|
2025-11-10 18:04:15 +08:00
|
|
|
|
# if csv_line['分支1角色'] != '' and csv_line['分支1台词'] != '':
|
|
|
|
|
|
# story_data['B1_scripts'].append({'idx': idx, 'name': csv_line['分支1角色'], 'script': csv_line['分支1台词']})
|
|
|
|
|
|
|
|
|
|
|
|
# 分支2
|
2026-01-17 17:16:52 +08:00
|
|
|
|
story_data['B2_scripts'].append({'idx': idx, 'name': csv_line['分支2角色'], 'script': csv_line['分支2台词'], 'story_intro':csv_line['聊天前要']})
|
2025-11-10 18:04:15 +08:00
|
|
|
|
# if csv_line['分支2角色'] != '' and csv_line['分支2台词'] != '':
|
|
|
|
|
|
# story_data['B2_scripts'].append({'idx': idx, 'name': csv_line['分支2角色'], 'script': csv_line['分支2台词']})
|
|
|
|
|
|
|
|
|
|
|
|
# 分支3
|
2026-01-17 17:16:52 +08:00
|
|
|
|
story_data['B3_scripts'].append({'idx': idx, 'name': csv_line['分支3角色'], 'script': csv_line['分支3台词'], 'story_intro':csv_line['聊天前要']})
|
2025-11-10 18:04:15 +08:00
|
|
|
|
# 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
|
2025-12-29 14:58:24 +08:00
|
|
|
|
|
|
|
|
|
|
story_data['story_intro'] = story_intro
|
2025-11-10 18:04:15 +08:00
|
|
|
|
return story_data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# functino: make_language_key
|
|
|
|
|
|
g_language_strs = {}
|
|
|
|
|
|
def make_language_key(idx, str):
|
2025-11-25 09:24:09 +08:00
|
|
|
|
if str == '':
|
|
|
|
|
|
return ''
|
2025-11-10 18:04:15 +08:00
|
|
|
|
key = "ST%s"%(idx)
|
2025-11-20 16:56:06 +08:00
|
|
|
|
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):
|
2025-11-25 09:24:09 +08:00
|
|
|
|
if str == '':
|
|
|
|
|
|
return ''
|
2025-11-20 16:56:06 +08:00
|
|
|
|
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()
|
2025-11-18 14:37:23 +08:00
|
|
|
|
if has_content(str):
|
|
|
|
|
|
g_language_strs[key] = str
|
2025-11-10 18:04:15 +08:00
|
|
|
|
return key
|
|
|
|
|
|
|
2025-11-25 09:24:09 +08:00
|
|
|
|
def make_language_story_intro_key(idx, str):
|
2026-01-17 17:16:52 +08:00
|
|
|
|
# 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
|
2025-11-25 09:24:09 +08:00
|
|
|
|
|
2025-12-29 14:58:24 +08:00
|
|
|
|
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
|
|
|
|
|
|
|
2025-11-18 14:37:23 +08:00
|
|
|
|
def make_language_key2(key, str):
|
2025-11-25 09:24:09 +08:00
|
|
|
|
if str == '':
|
|
|
|
|
|
return ''
|
2025-11-18 14:37:23 +08:00
|
|
|
|
if has_content(str):
|
|
|
|
|
|
g_language_strs[key] = str
|
|
|
|
|
|
return key
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
|
|
|
|
|
# functino: get_language_name_key
|
2025-11-18 14:37:23 +08:00
|
|
|
|
# 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 = []
|
2025-11-10 18:04:15 +08:00
|
|
|
|
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
|
|
|
|
|
|
|
2025-11-18 14:37:23 +08:00
|
|
|
|
g_StoryRewardCfg = []
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
|
|
|
|
|
# functino: create_story_cfg
|
2025-12-29 14:58:24 +08:00
|
|
|
|
def create_story_cfg(story_id, task_title, story_type, story_npc_id, map_level, story_intro, story_selection_texts, story_selection_next,
|
2025-11-18 14:37:23 +08:00
|
|
|
|
story_force_guide_group, story_condition):
|
2025-12-29 14:58:24 +08:00
|
|
|
|
task_title_key = make_language_story_title_key(story_id, task_title)
|
2025-11-10 18:04:15 +08:00
|
|
|
|
return {
|
|
|
|
|
|
'Id': int(story_id),
|
|
|
|
|
|
'StoryId': int(story_id),
|
2025-12-29 14:58:24 +08:00
|
|
|
|
'TaskTitle': task_title_key,
|
2025-11-10 18:04:15 +08:00
|
|
|
|
'Type': int(story_type),
|
2025-11-18 14:37:23 +08:00
|
|
|
|
'StoryNpcId': int(story_npc_id),
|
|
|
|
|
|
'MapLevel': int(map_level),
|
2025-11-25 09:24:09 +08:00
|
|
|
|
'StoryIntro': story_intro,
|
2025-11-10 18:04:15 +08:00
|
|
|
|
'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
|
2025-12-29 14:58:24 +08:00
|
|
|
|
type_idx = 0
|
2025-11-10 18:04:15 +08:00
|
|
|
|
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
|
2025-11-20 16:56:06 +08:00
|
|
|
|
story_perform_id = str(int(story_id)*100 + idx)
|
2025-11-10 18:04:15 +08:00
|
|
|
|
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'])
|
|
|
|
|
|
|
2025-12-29 14:58:24 +08:00
|
|
|
|
if has_content(script_info['story_intro']):
|
|
|
|
|
|
type_idx += 1
|
|
|
|
|
|
print(script_info['story_intro'])
|
|
|
|
|
|
|
2025-11-11 15:09:52 +08:00
|
|
|
|
if actor_info == None:
|
|
|
|
|
|
print("ERR: not find actor name, story_id=" + story_id)
|
2025-11-25 09:24:09 +08:00
|
|
|
|
|
2025-11-10 18:04:15 +08:00
|
|
|
|
if actor_info['NameKey'] == 'player':
|
2025-11-25 09:24:09 +08:00
|
|
|
|
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 = ''
|
2025-11-12 19:42:32 +08:00
|
|
|
|
else:
|
2025-11-25 09:24:09 +08:00
|
|
|
|
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'
|
2025-11-10 18:04:15 +08:00
|
|
|
|
else:
|
2025-11-25 09:24:09 +08:00
|
|
|
|
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 = ''
|
2025-11-12 19:42:32 +08:00
|
|
|
|
else:
|
2025-11-25 09:24:09 +08:00
|
|
|
|
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'
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
|
|
|
|
|
cfgs.append({
|
2025-12-29 14:58:24 +08:00
|
|
|
|
'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,
|
2026-01-17 17:16:52 +08:00
|
|
|
|
'WordTime': 10, 'Camp': '', 'CfgId': '', 'Dir': '', 'DirStartTime': '',
|
2025-12-29 14:58:24 +08:00
|
|
|
|
'AniName': '', 'AniStartTime': '', 'Eff': '', 'EffStartTime': '', 'OverTime': 0
|
2025-11-10 18:04:15 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
# 如果是对话框对话,就要在首尾添加入场配置和退场配置
|
2025-12-29 14:58:24 +08:00
|
|
|
|
''' 这个是以前的RO对话剧情,必须在首位添加配置,现在暂时屏蔽了,用漫画剧情
|
2025-11-10 18:04:15 +08:00
|
|
|
|
if story_type == 0:
|
2025-11-20 16:56:06 +08:00
|
|
|
|
story_perform_id = str(int(story_id)*100 + 0)
|
2025-11-10 18:04:15 +08:00
|
|
|
|
LeftName = cfgs[0]['LeftName']
|
|
|
|
|
|
LeftImg = cfgs[0]['LeftImg']
|
|
|
|
|
|
RightName = cfgs[0]['RightName']
|
|
|
|
|
|
RightImg = cfgs[0]['RightImg']
|
2025-11-25 09:24:09 +08:00
|
|
|
|
LeftAct = ""
|
|
|
|
|
|
RightAct = ""
|
|
|
|
|
|
if LeftName != "":
|
|
|
|
|
|
LeftAct = "RoleMovein"
|
|
|
|
|
|
if RightName != "":
|
|
|
|
|
|
RightAct = "RoleMovein"
|
2025-11-10 18:04:15 +08:00
|
|
|
|
cfgs.insert(0, {
|
2025-11-25 09:24:09 +08:00
|
|
|
|
'Id': story_perform_id, 'StoryId': story_id, 'Type': 0, 'LeftAct': LeftAct, 'LeftActBgTime': 0,
|
|
|
|
|
|
'RightAct': RightAct, 'RightActBgTime': 0, 'LeftName': LeftName, 'LeftNameColour': 'title02', 'LeftImg': LeftImg,
|
2025-11-10 18:04:15 +08:00
|
|
|
|
'RightName': RightName, 'RightNameColour': 'title01', 'RightImg': RightImg, 'SpeakSite': 0, 'SpeakId': '', 'SpeakTime': 0,
|
2025-11-25 09:24:09 +08:00
|
|
|
|
'WordTime': 0, 'Camp': '', 'CfgId': '', 'Dir': '', 'DirStartTime': '',
|
2025-11-10 18:04:15 +08:00
|
|
|
|
'AniName': '', 'AniStartTime': '', 'Eff': '', 'EffStartTime': '', 'OverTime': 0
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2025-11-20 16:56:06 +08:00
|
|
|
|
story_perform_id = str(int(story_id)*100 + len(cfgs))
|
2025-11-10 18:04:15 +08:00
|
|
|
|
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,
|
2025-11-25 09:24:09 +08:00
|
|
|
|
'WordTime': 0, 'Camp': '', 'CfgId': '', 'Dir': '', 'DirStartTime': '',
|
2025-11-10 18:04:15 +08:00
|
|
|
|
'AniName': '', 'AniStartTime': '', 'Eff': '', 'EffStartTime': '', 'OverTime': 0
|
|
|
|
|
|
})
|
2025-12-29 14:58:24 +08:00
|
|
|
|
'''
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
2025-11-11 15:09:52 +08:00
|
|
|
|
for i, cfg_item in enumerate(cfgs):
|
|
|
|
|
|
if cfg_item == None:
|
|
|
|
|
|
print("----cfg_item is None-----")
|
2025-11-13 21:33:51 +08:00
|
|
|
|
#print(cfg_item)
|
2025-11-11 15:09:52 +08:00
|
|
|
|
|
2025-11-10 18:04:15 +08:00
|
|
|
|
return cfgs
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-11-13 21:33:51 +08:00
|
|
|
|
# function: make_story_cfg
|
2025-11-10 18:04:15 +08:00
|
|
|
|
def make_story_cfg(story_cfgs, stroyPerformCfgV2_cfgs, story_data):
|
|
|
|
|
|
ID = story_data['id']
|
2025-11-18 14:37:23 +08:00
|
|
|
|
level = story_data['map_level']
|
2025-12-29 14:58:24 +08:00
|
|
|
|
task_title = story_data['task_title']
|
2025-11-10 18:04:15 +08:00
|
|
|
|
story_type = 0
|
2025-11-18 14:37:23 +08:00
|
|
|
|
story_npc_id = 0
|
|
|
|
|
|
if '对话' in story_data['story_type']:
|
2025-11-10 18:04:15 +08:00
|
|
|
|
story_type = 0
|
2025-11-18 14:37:23 +08:00
|
|
|
|
elif '聊天' in story_data['story_type']:
|
2025-11-10 18:04:15 +08:00
|
|
|
|
story_type = 1
|
2025-11-18 14:37:23 +08:00
|
|
|
|
|
|
|
|
|
|
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'])
|
|
|
|
|
|
|
2025-11-10 18:04:15 +08:00
|
|
|
|
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']):
|
2025-11-20 16:56:06 +08:00
|
|
|
|
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'])
|
2025-12-29 14:58:24 +08:00
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
2025-11-10 18:04:15 +08:00
|
|
|
|
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)
|
2025-12-29 14:58:24 +08:00
|
|
|
|
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, ''))
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
2026-01-17 17:16:52 +08:00
|
|
|
|
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))
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-11-10 18:04:15 +08:00
|
|
|
|
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:
|
2025-11-20 16:56:06 +08:00
|
|
|
|
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'])
|
2025-12-29 14:58:24 +08:00
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
2025-11-10 18:04:15 +08:00
|
|
|
|
story1_selection_texts = "%s;%s" % (story1_opt_1, story1_opt_2)
|
|
|
|
|
|
story1_selection_next = "%s;%s" % (story1_id, story2_id)
|
2025-12-29 14:58:24 +08:00
|
|
|
|
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, ''))
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
2026-01-17 17:16:52 +08:00
|
|
|
|
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))
|
|
|
|
|
|
|
2025-11-10 18:04:15 +08:00
|
|
|
|
has_multi_options = True
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
if has_multi_options == False:
|
2025-11-20 16:56:06 +08:00
|
|
|
|
story_id = "%s0" % (ID)
|
2025-12-29 14:58:24 +08:00
|
|
|
|
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))
|
2026-01-17 17:16:52 +08:00
|
|
|
|
|
|
|
|
|
|
if story_type == 1:
|
|
|
|
|
|
stroyPerformCfgV2_cfgs.extend(create_stroyPerformCfg(story_data['B1_scripts'], story_id, story_type, 0, len(story_data['B1_scripts'])-1))
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-11-18 14:37:23 +08:00
|
|
|
|
# function: generate_StoryCfgV2
|
2025-11-10 18:04:15 +08:00
|
|
|
|
def generate_StoryCfgV2(out_path, data):
|
2025-11-11 15:09:52 +08:00
|
|
|
|
with open(out_path+'/StoryCfgV2.csv', 'w', newline='', encoding='utf-8') as file:
|
2025-12-29 14:58:24 +08:00
|
|
|
|
fieldnames = ['序列ID', '触发剧情ID', '剧情标题', '剧情类型(0是对话,其他ChatNpcId)', '剧情NpcId', '关卡', '剧情介绍',
|
2025-11-10 18:04:15 +08:00
|
|
|
|
'选项显示', '继续下一个剧情', '是否底图', '是否隐藏UI',
|
|
|
|
|
|
'是否转场', '转场类型', '是否可跳过', '剧情播放间隔时间(s)',
|
|
|
|
|
|
'是否需要程序驱动', '是否存盘', '强制引导', '触发条件', '同组', '数据判断']
|
2025-12-29 14:58:24 +08:00
|
|
|
|
row1 = ['Id', 'StoryId', 'StoryTitle', 'Type', 'StoryNpcId', 'MapLevel', "StoryIntro",
|
2025-11-10 18:04:15 +08:00
|
|
|
|
'SelectionTexts', 'SelectionNext', 'NeedBg', 'HideUi',
|
|
|
|
|
|
'Transition', 'TransitionType', 'Skip', 'PlayInterval',
|
|
|
|
|
|
'ProgramControl', 'NeedSave', 'ForceGuideGroup', 'Condition', 'Group', 'DataCheck']
|
2025-12-29 14:58:24 +08:00
|
|
|
|
row2 = ['int', 'int', 'string', 'int', 'int', 'int', 'list',
|
2025-11-18 14:37:23 +08:00
|
|
|
|
'list', 'list', 'bool', 'bool',
|
|
|
|
|
|
'bool', 'int', 'bool', 'int',
|
2025-11-10 18:04:15 +08:00
|
|
|
|
'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)
|
2025-11-11 15:09:52 +08:00
|
|
|
|
#print("\n--- StoryCfgV2.csv ---")
|
|
|
|
|
|
#print(csv_data)
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-11-13 21:33:51 +08:00
|
|
|
|
# function: generate_StroyPerformCfgV2
|
2025-11-10 18:04:15 +08:00
|
|
|
|
def generate_StroyPerformCfgV2(out_path, data):
|
2025-11-11 15:09:52 +08:00
|
|
|
|
with open(out_path+'/StroyPerformCfgV2.csv', 'w', newline='', encoding='utf-8') as file:
|
2025-11-10 18:04:15 +08:00
|
|
|
|
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)
|
2025-11-11 15:09:52 +08:00
|
|
|
|
print("\n--- StroyPerformCfgV2.csv ---")
|
2025-11-10 18:04:15 +08:00
|
|
|
|
for i, data_item in enumerate(data):
|
2025-11-11 15:09:52 +08:00
|
|
|
|
if data_item == None:
|
|
|
|
|
|
print("data_item: None " + str(i))
|
2025-11-10 18:04:15 +08:00
|
|
|
|
csv_data.append(data_item.values())
|
|
|
|
|
|
writer = csv.writer(file)
|
|
|
|
|
|
writer.writerows(csv_data)
|
2025-11-13 21:33:51 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-11-18 14:37:23 +08:00
|
|
|
|
# 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']
|
2025-11-13 21:33:51 +08:00
|
|
|
|
csv_data = []
|
|
|
|
|
|
csv_data.append(fieldnames)
|
|
|
|
|
|
csv_data.append(row1)
|
|
|
|
|
|
csv_data.append(row2)
|
2025-11-18 14:37:23 +08:00
|
|
|
|
print("\n--- StoryNpcCfgV2.csv ---")
|
|
|
|
|
|
for i, data_item in enumerate(storyNpcCfg):
|
|
|
|
|
|
if data_item == None:
|
|
|
|
|
|
print("data_item: None " + str(i))
|
2025-11-25 09:24:09 +08:00
|
|
|
|
data_item['Location'] = data_item['Location']
|
|
|
|
|
|
data_item['Nation'] = data_item['Nation']
|
|
|
|
|
|
data_item['Marry'] = data_item['Marry']
|
2025-11-18 14:37:23 +08:00
|
|
|
|
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())
|
2025-11-13 21:33:51 +08:00
|
|
|
|
writer = csv.writer(file)
|
|
|
|
|
|
writer.writerows(csv_data)
|
2025-11-18 14:37:23 +08:00
|
|
|
|
|
|
|
|
|
|
# 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)
|
|
|
|
|
|
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
2025-11-13 21:33:51 +08:00
|
|
|
|
# function: generate_LanguagePackageV2_cn
|
2025-11-10 18:04:15 +08:00
|
|
|
|
def generate_LanguagePackageV2_cn(out_path, data):
|
2025-11-11 15:09:52 +08:00
|
|
|
|
with open(out_path+'/../../../Assets/Content/Config/LanguagePackageV2_cn.csv', 'w', newline='', encoding='utf-8') as file:
|
2025-11-10 18:04:15 +08:00
|
|
|
|
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 ---")
|
2025-11-11 15:09:52 +08:00
|
|
|
|
#print(csv_data)
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
2025-11-20 16:56:06 +08:00
|
|
|
|
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)
|
2025-11-25 09:24:09 +08:00
|
|
|
|
writer.writerows(csv_data)
|
2025-11-20 16:56:06 +08:00
|
|
|
|
|
2026-03-02 14:28:34 +08:00
|
|
|
|
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)
|
|
|
|
|
|
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
2025-11-13 21:33:51 +08:00
|
|
|
|
# function: generate_config
|
2025-11-10 18:04:15 +08:00
|
|
|
|
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)
|
|
|
|
|
|
|
2025-11-20 16:56:06 +08:00
|
|
|
|
generate_StoryAICfgV2(out_path, g_ai_cfg_dict)
|
2025-11-18 14:37:23 +08:00
|
|
|
|
generate_StoryNpcCfgV2(out_path, g_actor_info_dict)
|
2025-11-10 18:04:15 +08:00
|
|
|
|
generate_StoryCfgV2(out_path, StoryCfgV2_lines)
|
2025-11-18 14:37:23 +08:00
|
|
|
|
#generate_StoryRewards(out_path, StoryCfgV2_lines)
|
2026-03-02 14:28:34 +08:00
|
|
|
|
generate_StoryTaskV2(out_path, StoryCfgV2_lines, g_actor_info_dict)
|
|
|
|
|
|
|
2025-11-10 18:04:15 +08:00
|
|
|
|
generate_StroyPerformCfgV2(out_path, StroyPerformCfgV2_lines)
|
|
|
|
|
|
generate_LanguagePackageV2_cn(out_path, g_language_strs)
|
2025-11-18 14:37:23 +08:00
|
|
|
|
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
2026-03-02 14:28:34 +08:00
|
|
|
|
|
2025-11-10 18:04:15 +08:00
|
|
|
|
# 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')
|
2025-11-11 15:09:52 +08:00
|
|
|
|
g_input_dir = g_input_dir.replace('\\', '/')
|
|
|
|
|
|
g_out_dir = g_out_dir.replace('\\', '/')
|
2025-11-10 18:04:15 +08:00
|
|
|
|
print('g_input_dir: ' + g_input_dir)
|
|
|
|
|
|
print('g_out_dir: ' + g_out_dir)
|
|
|
|
|
|
g_story_data_list = []
|
|
|
|
|
|
|
2025-11-18 14:37:23 +08:00
|
|
|
|
# 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)
|
2025-11-20 16:56:06 +08:00
|
|
|
|
|
|
|
|
|
|
# 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)
|
2025-11-18 14:37:23 +08:00
|
|
|
|
|
2025-11-20 16:56:06 +08:00
|
|
|
|
# 3. Read StoryRewardCfg.csv
|
2025-11-18 14:37:23 +08:00
|
|
|
|
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)
|
2025-11-25 09:24:09 +08:00
|
|
|
|
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)
|
2025-11-18 14:37:23 +08:00
|
|
|
|
|
2025-11-20 16:56:06 +08:00
|
|
|
|
# 4. Read StoryText.csv
|
2025-11-18 14:37:23 +08:00
|
|
|
|
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)
|
|
|
|
|
|
'''
|
2025-11-10 18:04:15 +08:00
|
|
|
|
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)
|
2025-11-12 19:42:32 +08:00
|
|
|
|
#print("--- story_data ---")
|
|
|
|
|
|
#print(story_data)
|
|
|
|
|
|
#print()
|
2025-11-11 15:09:52 +08:00
|
|
|
|
|
2025-11-10 18:04:15 +08:00
|
|
|
|
# 根据story_data_list生成配置文件
|
|
|
|
|
|
generate_config(g_story_data_list, g_out_dir)
|
|
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
print(f"无法读取文件: {filename}")
|
|
|
|
|
|
|
2025-11-18 14:37:23 +08:00
|
|
|
|
'''
|
2025-11-10 18:04:15 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|