extends Node #存档路径 var save_file_path:String="user://save.data" #加载的存档数据 var save_data:Array=[] func load_save_data(): var f= FileAccess.open(save_file_path,FileAccess.READ) if f!=null: save_data=f.get_var() else: f=FileAccess.open(save_file_path,FileAccess.WRITE) f.store_var(save_data) #将所有存档数据保存到硬盘 func save_save_data(): var f=FileAccess.open(save_file_path,FileAccess.WRITE) f.store_var(save_data) #将当前的游戏数据以存档名n的名字添加到存储队列 func add_now_game_to_save(n:String): var new_save=now_game_data.duplicate(true) new_save["name"]=n save_data.append(new_save) save_save_data() #将当前的游戏数据以存档原名覆盖到第ind个存档上 func cover_now_game_to_save(ind:int): var n:String=save_data[ind]["name"] var new_save=now_game_data.duplicate(true) new_save["name"]=n save_data[ind]=new_save save_save_data() #获取当前存档队列 func get_all_save(): return save_data.duplicate(true) #加载第ind个存档 func load_save(ind:int): now_game_data=save_data[ind].duplicate() SceneManager.change_scene_to("res://scene/game_flow.tscn") pass #删除第ind个存档 func delete_save(ind:int): save_data.pop_at(ind) save_save_data() var system_config_data_path:String="user://config.data" #加载配置文件 func load_config(): var f=FileAccess.open(system_config_data_path,FileAccess.READ) if f!=null: system_config_data=f.get_var() else: f=FileAccess.open(system_config_data_path,FileAccess.WRITE) f.store_var(system_config_data) Bgm.set_BGM_volume(system_config_data["BGM_volume"]) Bgm.set_effect_volume(system_config_data["effect_volume"]) #存储配置文件 func save_config(): var f=FileAccess.open(system_config_data_path,FileAccess.WRITE) f.store_var(system_config_data) #更改BGM音量 func change_BGM_volume(value:float): Bgm.set_BGM_volume(value) system_config_data["BGM_volume"]=value save_config() pass #更改音效音量 func change_effect_volume(value:float): Bgm.set_effect_volume(value) system_config_data["effect_volume"]=value save_config() pass func get_BGM_volume(): return system_config_data["BGM_volume"] pass func get_effect_volume(): return system_config_data["effect_volume"] var system_config_data:Dictionary={ #BGM音量 "BGM_volume":0.7, #音效音量 "effect_volume":0.7, } #局外游戏数据文件目录 var system_game_data_path:String="user://system_game.data" #局外游戏数据 var system_game_data:Dictionary={ "unlock_character":["test_character_01","test_character_02"], #全局物品 "item":[], "jifen":100, "jinqian":100, "zuanshi":100, "tili":100, } #获取系统全局物品 func get_all_item_system_data(): pass #货币变更信号 signal system_currency_changed #获取货币,0积分,1金钱,2钻石,3体力 func get_currency_system(ind:int): match ind: 0: return system_game_data["jifen"] 1: return system_game_data["jinqian"] 2: return system_game_data["zuanshi"] 3: return system_game_data["tili"] #更改货币数据 func set_currency_system(ind:int,value): match ind: 0: system_game_data["jifen"]=value 1: system_game_data["jinqian"]=value 2: system_game_data["zuanshi"]=value 3: system_game_data["tili"]=value system_currency_changed.emit() save_system_game_data() pass #加载局外游戏数据文件 func load_system_game_data(): var f=FileAccess.open(system_game_data_path,FileAccess.READ) if f!=null: system_game_data=f.get_var() else: f=FileAccess.open(system_game_data_path,FileAccess.WRITE) f.store_var(system_game_data) #存储局外游戏数据 func save_system_game_data(): var f=FileAccess.open(system_game_data_path,FileAccess.WRITE) f.store_var(system_game_data) #获取当前游戏内所有物品 func get_all_item_game_data()->Array: return now_game_data["item"].duplicate(true) #根据type获取当前物品 func get_type_item_game_data(type:int)->Array: var item:Array=now_game_data["item"].duplicate(true) var res:Array=[] for i in item: if i.has("type") and int(i["type"])==type: res.append(i) return res func get_now_character_equip_page(page:int): return CharacterTool.get_character_equip_page(get_now_character_data(),page) func get_now_character_equip_use(): return CharacterTool.get_character_equip_now(get_now_character_data()) func replace_equip_with_data(page:int,pos:int,item_data): var left=CharacterTool.replace_character_equip(now_game_data["character_data"],page,pos,item_data) if left!=null: add_item_to_bag(left) pass #向背包中添加item,会根据allow merger属性决定是否自动合并,并创建num属性 func add_item_to_bag(item_data:Dictionary): var item:Array=now_game_data["item"] if item_data["allow_merge"]: for i in item_data.size(): if item_data[i]["id"]==item_data["id"]: if item_data[i].has("num"): item_data[i]["num"]+=1 else: item_data[i]["num"]=2 pass pass else: item.append(item_data) #根据在背包的排序减少对应物品的数量 func decrease_item_num_index(ind:int,num:int=1): var item:Array=now_game_data["item"] if indbool: var item:Array=now_game_data["item"] var item_data:Dictionary var ind:int for i in item.size(): if item[i]["id"]==id: item_data=item[i] ind=i break if item_data==null: return false else: if not item_data.has("num"): item_data["num"]=1 var item_num:int=item_data["num"] if item_num>num: item_data["num"]-=num return true elif item_num==num: item.pop_at(ind) return true else: return false #通过id获取当前背包数量(如果是不允许合并的物品则返回1(有)或者0(没有)) func get_item_by_id(id:String)->int: var item:Array=now_game_data["item"] var item_data:Dictionary var ind:int for i in item.size(): if item[i]["id"]==id: item_data=item[i] ind=i break if item_data!=null: if item_data.has("num"): return item_data["num"] else: return 1 else: return 0 pass #返回一个长度为2的数组,第一个数组存储的item中装备的index,另一个是对应的item_data func get_all_equip_index_and_data_in_bag()->Array: var item:Array=now_game_data["item"].duplicate(true) var res:Array=[] var ind_arr:Array=[] var data_arr:Array=[] for i in item.size(): if is_item_a_equip(item[i]): ind_arr.append(i) data_arr.append(item[i]) res=[ind_arr,data_arr] return res #返回一个长度为2的数组,第一个数组存储的item中技能的index,另一个是对应的item_data func get_all_skill_index_and_data_in_bag()->Array: var item:Array=now_game_data["item"].duplicate(true) var res:Array=[] var ind_arr:Array=[] var data_arr:Array=[] for i in item.size(): if is_item_a_skill(item[i]): ind_arr.append(i) data_arr.append(item[i]) res=[ind_arr,data_arr] return res #判断item是否为一个装备(暂时将武器除外) func is_item_a_equip(item_data:Dictionary)->bool: if not item_data.has("type"): return false var type:int=item_data["type"] if type in [0,1,2,3]: return true else: return false #判断item是否为一个技能 func is_item_a_skill(item_data:Dictionary): if not item_data.has("type"): return false var type:int=item_data["type"] if type ==6: return true else: return false #改变当前角色使用的装备页 func change_character_equip_now_use(page:int): print(page) CharacterTool.change_character_equip_now_use(now_game_data["character_data"],page) #获取当前使用装备页数 func get_character_page_now_use()->int: return CharacterTool.get_character_equip_now_use_page(now_game_data["character_data"]) #将角色第ind个技能卡移除,放入背包 func remove_skill_card_ind_to_bag(ind:int): var now_character_data:Dictionary=now_game_data["character_data"] var left=CharacterTool.remove_skill_index(now_character_data,ind) if left!=null: add_item_to_bag(left) #将背包中序列为ind的技能卡装备到角色 func add_sill_card_from_bag_to_character(ind:int): var item_data=now_game_data["item"][ind] if is_item_a_skill(item_data): var res=CharacterTool.add_skill_card(now_game_data["character_data"],item_data) if res: decrease_item_num_index(ind) #获取当前角色的所有技能 func get_now_character_skill(): var character_data=now_game_data["character_data"] return CharacterTool.get_character_skill_all(character_data) ##当前局内数据 var now_game_data:Dictionary={ "character_data":{ }, "script_data":{ }, #游戏内物品 "item":[], #存储的NPC数据(仅包含遇到的NPC,用于存储NPC的背包,在申请NPCdata时进行写入 "NPC_data":{}, "now_scene":"", "difficulty":0, "gold":1000, "health":100, "spirit":999, "map":"map_01", "move_ability":1, "time_unix":0, "card_in_bag":["card_03","card_03","card_02","card_02","card_01","card_01","card_01","card_01"], "condition_triger_randi_dic":{ } } #获取当前局内NPC数据 func get_now_game_npc_data(NPC_id:String): var now_npc_data:Dictionary=now_game_data["NPC_data"] if now_npc_data.has(NPC_id): #这里不进行duplicate副本的原因是trade交易场景要对数据进行操作 return now_npc_data[NPC_id] else: #填入npc数据,并实例出售卖的道具()可以通过在get item data上施加影响来实现随机 var n_data=Database.get_npc_data(NPC_id) for i in n_data["sold_item"].size(): n_data["sold_item"][i]=Database.get_item_data(n_data["sold_item"][i]) now_game_data["NPC_data"][NPC_id]=n_data return now_npc_data[NPC_id] #获取当前角色与NPC的好感度 func get_now_game_npc_favor(npc_id): return CharacterTool.get_character_with_npc_favor(now_game_data["character_data"],npc_id) #展示和NPC id对应的交易界面 func show_trade(npc_id:String): now_game_flow.show_trade(npc_id) #游戏内货币改变信号 signal game_currency_changed #获取游戏内的“货币”,0:生命,1金钱,2精神 func get_currency_game(ind:int): match ind: 0: return now_game_data["health"] 1: return now_game_data["gold"] 2: return now_game_data["spirit"] func set_currency_game(ind:int,value): match ind: 0: now_game_data["health"]=value 1: now_game_data["gold"]=value 2: now_game_data["spirit"]=value game_currency_changed.emit() #更改 func change_currency_game(ind:int,change): set_currency_game(ind,get_currency_game(ind)+change) #当前战斗场景 var now_fight_scene:FightScene #向卡组中添加卡牌 func add_card(card_id:String): now_game_data["card_in_bag"].append(card_id) #从卡组中删除卡牌 func delete_card(card_id:String)->bool: var now_arr:Array= now_game_data["card_in_bag"] var ind=now_arr.find(card_id) if ind==-1: return false else: now_game_data["card_in_bag"].pop_at(ind) return true var now_fight_enermy_data:Array=[] var now_fight_friend_data:Array=[] func fight(data:Dictionary): if data.has("friend"): now_fight_friend_data=data["friend"] now_fight_enermy_data SceneManager.change_scene_to("res://scene/fight.tscn") pass #使用卡牌,character为使用者,target为目标,card_data为使用的卡牌数据 func use_card(card_data:Dictionary,user=null,target=null): print("执行了卡牌:\n"+str(card_data)+"\n目标"+str(target)) if card_data.has("triger"): for funcitem in card_data["triger"]: var _func=Callable(self,funcitem.func) var value:Array=funcitem.value.duplicate() for i in value.size(): if value[i] is String and value[i]=="user": value[i]=user elif value[i] is String and value[i]=="target": value[i]=target _func.callv(value) ##下面是例子 ##打击单位 func hit(target,value): if target is FightCharacterCard ||target is FightEnermyCard: target.HP-=value #打击全部单位 func hit_all(value): var all_character=now_fight_scene.get_all_unit() for i in all_character: i.HP-=value #回血 func recover(target,value): if target is FightCharacterCard ||target is FightEnermyCard: target.HP+=value func get_all_card()->Array: return now_game_data["card_in_bag"].duplicate() func get_move_ability(): return now_game_data["move_ability"] func get_time_dictionary(): var time_unix=int(now_game_data["time_unix"]) return Time.get_datetime_dict_from_unix_time(time_unix) func get_time_unix(): return now_game_data["time_unix"] #year、month、day、weekday、hour、minute 和 second func flow_time(data:Dictionary): var date=get_time_dictionary() var change_unix:float=0 if data.has("day"): var day=data["year"] change_unix+=day*86400 if data.has("hour"): var hour=data["hour"] change_unix+=3600*hour if data.has("minute"): var minute=data["minute"] change_unix+=minute*60 now_game_data["time_unix"]+=change_unix time_changed.emit() #时间改变的信号 signal time_changed #事件触发器列表 var triger:Dictionary={ "change_event":func (data):now_game_flow.show_event(data), "change_texture": func (data):now_game_flow.event_panel.change_texture(data), "change_text":func(data):now_game_flow.event_panel.change_text(data), "change_choice":func(data):now_game_flow.event_panel.change_choice(data), "increase_health":func (data):now_game_data.health-=data, "end_event":func(data):now_game_flow.event_panel.hide(), "flow_time":func (data):flow_time(data), "fight":func (data):fight(data), "add_currency":func (data):change_currency_game(data["ind"],data["value"]), "trade":func(data): show_trade(data), "show_identifaction":func(data):show_identification(data) } #使用事件触发器 func call_triger(triger_type:String,data): if triger.has(triger_type): return triger[triger_type].call(data) else: return null #条件触发器(用于返回是否的条件判定结果) var condition_triger:Dictionary={ "date_limit":func (data:Dictionary):return TimeTool.is_in_date(data,get_time_dictionary()), "time_limit":func (data:Dictionary):return TimeTool.is_in_time(data,get_time_dictionary()), "rand":func (data:Dictionary):return get_rand(data["scene_id"],data["touch_id"],data["index"],data["condition"]), "currency_more_than": func (data:Dictionary) :return get_currency_game(data["ind"])>=data["value"] } #使用条件触发器 func call_condition_triger(triger_type:String,data): if condition_triger.has(triger_type): return condition_triger[triger_type].call(data) else: return false #记录随机的场景上一次结果,如果时间不变则直接取上一次结果 #记录在游戏存档内,保证加载数据不改变 func get_rand(scene_id:String,touch_name:String,index:String,condition:float)->bool: if now_game_data["condition_triger_randi_dic"].has(scene_id): var scene_data=now_game_data["condition_triger_randi_dic"][scene_id] if scene_data.has(touch_name): var touch_data=scene_data[touch_name] if touch_data.has(index): var triger_data=touch_data[index] var last_time_triger=triger_data["last_time_triger"] if last_time_triger==get_time_unix(): return triger_data["last_rand_result"] else: var dic=recreate_rand_dic(condition) now_game_data["condition_triger_randi_dic"][scene_id][touch_name][index]=dic return dic["last_rand_result"] pass else: var dic=recreate_rand_dic(condition) now_game_data["condition_triger_randi_dic"][scene_id][touch_name][index]=dic return dic["last_rand_result"] else: var dic=recreate_rand_dic(condition) now_game_data["condition_triger_randi_dic"][scene_id][touch_name]={ index:dic } return dic["last_rand_result"] pass else: var dic=recreate_rand_dic(condition) now_game_data["condition_triger_randi_dic"][scene_id]={ touch_name:{ index:dic } } return dic["last_rand_result"] #显示鉴定界面(用于触发器) func show_identification(data:String): if now_game_flow!=null: now_game_flow.show_identification(data) pass #为随机创建一个新的随机字典 func recreate_rand_dic(condition:float)->Dictionary: var new_rand_result:bool=(randf()bool: print(choice) return true pass #用来获取鉴定每轮显示的难易度 var indetification_difficulty_get_triger:Dictionary={ "fish":fish_get_difficulty } func call_difficulty_triger(triger_type:String,character_data:Dictionary,round_dic:Dictionary): if indetification_difficulty_get_triger.has(triger_type): return indetification_difficulty_get_triger[triger_type].call(character_data,round_dic) else: return null func fish_get_difficulty(character_data:Dictionary,round_dic:Dictionary): pass #用来判断鉴定是否结束的函数 var identification_is_finish_triger:Dictionary={ "normal":normal_is_finish, } func call_is_finish_triger(triger_type:String,character_data:Dictionary,round_dic:Dictionary): if identification_is_finish_triger.has(triger_type): return identification_is_finish_triger[triger_type].call(character_data,round_dic) else: return null func normal_is_finish(character_data:Dictionary,round_dic:Dictionary)->bool: if round_dic["left_cost"]==0 ||round_dic["left_total"]==round_dic["left_total_max"] || round_dic["right_cost"]==0: return true else: return false #鉴定结束触发的函数(用于获得奖励一类的) var identification_finish_triger:Dictionary={ "fish":fish_finish, } func call_finish_triger(triger_type:String,character_data:Dictionary,round_dic:Dictionary): if identification_finish_triger.has(triger_type): return identification_finish_triger[triger_type].call(character_data,round_dic) else: return null func fish_finish(character_data:Dictionary,round_data:Dictionary): pass #移动场景,前者是scene的ID,后者是距离当前场景的距离 func move_scene(scene_id:String,distance): if scene_id==get_now_scene(): return false flow_time({ "minute":distance/get_move_ability() }) now_game_flow.change_scene(scene_id,distance) set_now_scene(scene_id) return true pass #获取当前场景ID func get_now_scene(): return now_game_data["now_scene"] #设置当前场景,只用于开局重置位置 func set_now_scene(scene_id:String): now_game_data["now_scene"]=scene_id #当前的游戏流程场景 var now_game_flow:GameFlow #获取当前角色数据的拷贝 func get_now_character_data(): return now_game_data["character_data"].duplicate() #设置当前角色(游戏内) func set_now_character(id:String): now_game_data["character_data"]=Database.get_character_data(id) func _ready() -> void: load_config() load_system_game_data() load_save_data()