|  |  |  | extends Node3D | 
					
						
							|  |  |  | class_name LevelManager | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var target: int | 
					
						
							|  |  |  | var level: Level | 
					
						
							|  |  |  | var cur_level_instance: LevelInstance | 
					
						
							|  |  |  | var level_instance_dict: Dictionary = {} | 
					
						
							|  |  |  | var level_loading_rate: float | 
					
						
							|  |  |  | var level_active_spots: Array[Node] | 
					
						
							|  |  |  | var level_character_born_spots: Array[LevelInstance.ChacacterBornSpot] | 
					
						
							|  |  |  | var level_enemy_cfgs: Array[CharacterCfg] | 
					
						
							|  |  |  | var level_doors: Array[LevelDoor] | 
					
						
							|  |  |  | var is_level_active: bool | 
					
						
							|  |  |  | var enemy_count: int #由关卡生成的怪物数量 | 
					
						
							|  |  |  | var current_enmey: Array[int] #当前存活怪物id | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func _ready(): | 
					
						
							|  |  |  | 	Global.level_mgr = self | 
					
						
							|  |  |  | 	SignalManager.character_create.connect(on_character_create) | 
					
						
							|  |  |  | 	SignalManager.character_pos_changed.connect(on_character_pos_changed) | 
					
						
							|  |  |  | 	SignalManager.character_die.connect(on_character_die) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init(): | 
					
						
							|  |  |  | 	var level_scene: PackedScene = load("res://scene/level/level.tscn") | 
					
						
							|  |  |  | 	level = level_scene.instantiate() as Level | 
					
						
							|  |  |  | 	add_child(level) | 
					
						
							|  |  |  | 	var level_instance_list: Array[LevelInstance] = level.get_level_instance_list() | 
					
						
							|  |  |  | 	for level_instance in level_instance_list: | 
					
						
							|  |  |  | 		var level_id_list: Array[Vector3i] = get_level_id_list(level_instance.get_global_position(), level_instance.size) | 
					
						
							|  |  |  | 		for level_id in level_id_list: | 
					
						
							|  |  |  | 			if level_id in level_instance_dict: | 
					
						
							|  |  |  | 				print("关卡id重复", level_id) | 
					
						
							|  |  |  | 			level_instance_dict[level_id] = level_instance | 
					
						
							|  |  |  | 	level.init() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func _process(delta) -> void: | 
					
						
							|  |  |  | 	if not level: | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	if level_loading_rate < 1: | 
					
						
							|  |  |  | 		level_loading_rate += delta *2 | 
					
						
							|  |  |  | 		if level_loading_rate > 1: | 
					
						
							|  |  |  | 			level_loading_rate = 1 | 
					
						
							|  |  |  | 		level.set_level_loading_rate(level_loading_rate) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func get_born_pos() -> Vector3: | 
					
						
							|  |  |  | 	return level.get_born_pos() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func on_character_create(id: int, type: int, pos: Vector3): | 
					
						
							|  |  |  | 	if type == Enum.ECharacterType.Player: | 
					
						
							|  |  |  | 		target = id | 
					
						
							|  |  |  | 		on_character_pos_changed(id, pos) | 
					
						
							|  |  |  | 	elif type == Enum.ECharacterType.Monster: | 
					
						
							|  |  |  | 		current_enmey.append(id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func on_character_pos_changed(id: int, pos: Vector3): | 
					
						
							|  |  |  | 	if id == target: | 
					
						
							|  |  |  | 		set_player_position(pos) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func on_character_die(id: int): | 
					
						
							|  |  |  | 	if id in current_enmey: | 
					
						
							|  |  |  | 		current_enmey.remove_at(current_enmey.find(id)) | 
					
						
							|  |  |  | 		#强制战斗关卡通关 | 
					
						
							|  |  |  | 		if not cur_level_instance.is_force_battle: | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		if enemy_born(1): | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		if current_enmey.size() > 0: | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		for level_door: LevelDoor in level_doors: | 
					
						
							|  |  |  | 			level_door.set_open(true) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func set_player_position(pos: Vector3) -> void: | 
					
						
							|  |  |  | 	level.set_player_position(pos) | 
					
						
							|  |  |  | 	var new_id: Vector3i                  = Util.get_level_id(pos) | 
					
						
							|  |  |  | 	var new_level_instance: LevelInstance = level_instance_dict.get(new_id) | 
					
						
							|  |  |  | 	if not new_level_instance: | 
					
						
							|  |  |  | 		return #todo 不存在的关卡 主角直接死亡 | 
					
						
							|  |  |  | 	if cur_level_instance: | 
					
						
							|  |  |  | 		if new_level_instance == cur_level_instance: | 
					
						
							|  |  |  | 			check_level_active(pos) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		cur_level_instance.set_focus_from(true) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	new_level_instance.set_focus_to(true) | 
					
						
							|  |  |  | 	cur_level_instance = new_level_instance | 
					
						
							|  |  |  | 	enter_level() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func enter_level() -> void: | 
					
						
							|  |  |  | 	SignalManager.level_loading_start.emit() | 
					
						
							|  |  |  | 	is_level_active = false | 
					
						
							|  |  |  | 	level_active_spots = [] | 
					
						
							|  |  |  | 	level_doors = [] | 
					
						
							|  |  |  | 	#创建关卡内活动部件 | 
					
						
							|  |  |  | 	for level_active_spot: Node in level_active_spots: | 
					
						
							|  |  |  | 		level_active_spot.queue_free() | 
					
						
							|  |  |  | 	for level_active_spot: LevelInstance.LevelActiveSpot in cur_level_instance.get_level_active_spots(): | 
					
						
							|  |  |  | 		var new_level_active: Node = level_active_spot.scene.instantiate() | 
					
						
							|  |  |  | 		add_child(new_level_active) | 
					
						
							|  |  |  | 		new_level_active.global_position = level_active_spot.pos | 
					
						
							|  |  |  | 		level_active_spots.append(new_level_active) | 
					
						
							|  |  |  | 		if new_level_active is LevelDoor: | 
					
						
							|  |  |  | 			level_doors.append(new_level_active) | 
					
						
							|  |  |  | 	#更新刷怪数据 | 
					
						
							|  |  |  | 	level_character_born_spots = cur_level_instance.get_character_born_spots() | 
					
						
							|  |  |  | 	level_enemy_cfgs = cur_level_instance.get_enemy_cfgs() | 
					
						
							|  |  |  | 	enemy_count = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	level_loading_rate = 1-level_loading_rate | 
					
						
							|  |  |  | 	level.set_level_loading_rate(level_loading_rate) | 
					
						
							|  |  |  | 	SignalManager.level_size_change.emit(cur_level_instance.get_level_size()) | 
					
						
							|  |  |  | 	SignalManager.level_pos_change.emit(cur_level_instance.get_level_pos()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SignalManager.level_loading_end.emit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func check_level_active(pos: Vector3) -> void: | 
					
						
							|  |  |  | 	if is_level_active: | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	var is_active: bool = cur_level_instance.is_in_active_area(pos) | 
					
						
							|  |  |  | 	if not is_active: | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	is_level_active = true | 
					
						
							|  |  |  | 	for level_door: LevelDoor in level_doors: | 
					
						
							|  |  |  | 		level_door.set_open(true) | 
					
						
							|  |  |  | 	#创建关卡内角色 | 
					
						
							|  |  |  | 	for character_spot: LevelInstance.ChacacterSpot in cur_level_instance.get_character_spots(): | 
					
						
							|  |  |  | 		Global.character_mgr.create_character(character_spot.cfg, Enum.ETeam.Monster, character_spot.pos) | 
					
						
							|  |  |  | 	#强制战斗关门刷怪 | 
					
						
							|  |  |  | 	if cur_level_instance.is_force_battle: | 
					
						
							|  |  |  | 		if enemy_born(level_character_born_spots.size()): | 
					
						
							|  |  |  | 			for level_door: LevelDoor in level_doors: | 
					
						
							|  |  |  | 				level_door.set_open(false) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func get_level_id_list(pos: Vector3, size: Vector3i) -> Array[Vector3i]: | 
					
						
							|  |  |  | 	var size_basic: Vector3  = Setting.size_basic | 
					
						
							|  |  |  | 	var ret: Array[Vector3i] = [] | 
					
						
							|  |  |  | 	for x in range(size.x): | 
					
						
							|  |  |  | 		for y in range(size.y): | 
					
						
							|  |  |  | 			for z in range(size.z): | 
					
						
							|  |  |  | 				var pos_sub: Vector3 = pos +Vector3(x*size_basic.x, y*size_basic.y, z*size_basic.z) | 
					
						
							|  |  |  | 				ret.append(Util.get_level_id(pos_sub)) | 
					
						
							|  |  |  | 	return ret | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func enemy_born(count: int) -> bool: | 
					
						
							|  |  |  | 	if level_character_born_spots.size() == 0: | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	var count_max: int = level_enemy_cfgs.size() | 
					
						
							|  |  |  | 	count = min(count, count_max - enemy_count) | 
					
						
							|  |  |  | 	if count == 0: | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	var count_start = enemy_count | 
					
						
							|  |  |  | 	for i in count: | 
					
						
							|  |  |  | 		var cfg_index: int                                  = count_start + i | 
					
						
							|  |  |  | 		var cfg: CharacterCfg                               = level_enemy_cfgs[cfg_index] | 
					
						
							|  |  |  | 		var pos_index: int                                  = enemy_count % level_character_born_spots.size() | 
					
						
							|  |  |  | 		var character_spot: LevelInstance.ChacacterBornSpot = level_character_born_spots[pos_index] | 
					
						
							|  |  |  | 		Global.character_mgr.create_character(cfg, Enum.ETeam.Monster, character_spot.pos) | 
					
						
							|  |  |  | 		enemy_count += 1 | 
					
						
							|  |  |  | 	return true |