|  |  |  | @tool | 
					
						
							|  |  |  | extends Node3D | 
					
						
							|  |  |  | class_name LevelInstance | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @export var size: Vector3i = Vector3i.ONE: | 
					
						
							|  |  |  | 	set(value): | 
					
						
							|  |  |  | 		if (value.x<1) or (value.y<1) or (value.z<1): | 
					
						
							|  |  |  | 			value = Vector3i.ONE | 
					
						
							|  |  |  | 		size = value | 
					
						
							|  |  |  | 		_on_size_change() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @export var is_force_battle: bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @export var focus: bool: | 
					
						
							|  |  |  | 	get: return false | 
					
						
							|  |  |  | 	set(value): | 
					
						
							|  |  |  | 		set_focus_from(false) | 
					
						
							|  |  |  | 		set_focus_to(true) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @export var cancel_focus: bool: | 
					
						
							|  |  |  | 	get: return false | 
					
						
							|  |  |  | 	set(value): | 
					
						
							|  |  |  | 		set_focus_from(false) | 
					
						
							|  |  |  | 		set_focus_to(false) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @export var enemy_nums: Array[LevelEnemy] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @onready var grid_block_material: Material = load("res://render/material/grid_block.tres") as Material | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var level_area_cfg: LevelAreaCfg #运行时设置 | 
					
						
							|  |  |  | var character_spots: Array[ChacacterSpot] #运行时设置 | 
					
						
							|  |  |  | var character_born_spots: Array[ChacacterBornSpot] #运行时设置 | 
					
						
							|  |  |  | var level_active_spots: Array[LevelActiveSpot] #运行时设置 | 
					
						
							|  |  |  | var enemy_cfgs: Array[CharacterCfg] #运行时设置 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ChacacterSpot: | 
					
						
							|  |  |  | 	var pos: Vector3 | 
					
						
							|  |  |  | 	var cfg: CharacterCfg | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ChacacterBornSpot: | 
					
						
							|  |  |  | 	var pos: Vector3 | 
					
						
							|  |  |  | 	var type: int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class LevelActiveSpot: | 
					
						
							|  |  |  | 	var pos: Vector3 | 
					
						
							|  |  |  | 	var scene: PackedScene | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func _on_size_change() -> void: | 
					
						
							|  |  |  | 	var level_range: CSGBox3D = $LevelRange as CSGBox3D | 
					
						
							|  |  |  | 	var size_basic: Vector3   = Setting.size_basic | 
					
						
							|  |  |  | 	level_range.size = Vector3(size.x*size_basic.x, size.y*size_basic.y, size.z*size_basic.z) | 
					
						
							|  |  |  | 	level_range.position = level_range.size / 2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func set_focus_from(is_focus: bool) -> void: | 
					
						
							|  |  |  | 	_set_focus(is_focus, "from") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func set_focus_to(is_focus: bool) -> void: | 
					
						
							|  |  |  | 	_set_focus(is_focus, "to") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func _set_focus(is_focus: bool, key: String) -> void: | 
					
						
							|  |  |  | 	if not grid_block_material: | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	if is_focus: | 
					
						
							|  |  |  | 		grid_block_material.set_shader_parameter("is_focus_"+key, true) | 
					
						
							|  |  |  | 		grid_block_material.set_shader_parameter("focus_min_"+key, pos_min() - Vector3.ONE * 0.32) | 
					
						
							|  |  |  | 		grid_block_material.set_shader_parameter("focus_max_"+key, pos_max() + Vector3.ONE * 0.32) | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		grid_block_material.set_shader_parameter("is_focus_"+key, false) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func get_level_size() -> Vector2: | 
					
						
							|  |  |  | 	var level_range: CSGBox3D = $LevelRange as CSGBox3D | 
					
						
							|  |  |  | 	var level_size: Vector3   = level_range.size | 
					
						
							|  |  |  | 	return Vector2(level_size.x, level_size.z) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func get_level_pos() -> Vector2: | 
					
						
							|  |  |  | 	var pos: Vector3 = get_global_position() | 
					
						
							|  |  |  | 	return Vector2(pos.x, pos.z) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func set_level_range_visible(value: bool) -> void: | 
					
						
							|  |  |  | 	var level_range: CSGBox3D = $LevelRange as CSGBox3D | 
					
						
							|  |  |  | 	level_range.visible = value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init_character_spots(level_character: GridMap) -> void: | 
					
						
							|  |  |  | 	character_spots = [] | 
					
						
							|  |  |  | 	character_born_spots = [] | 
					
						
							|  |  |  | 	level_active_spots = [] | 
					
						
							|  |  |  | 	enemy_cfgs = [] | 
					
						
							|  |  |  | 	var id_min: Vector3i          = Util.get_level_grid_pos(pos_min()) | 
					
						
							|  |  |  | 	var id_max: Vector3i          = Util.get_level_grid_pos(pos_max()) | 
					
						
							|  |  |  | 	var mesh_library: MeshLibrary = level_character.get_mesh_library() | 
					
						
							|  |  |  | 	for x in range(id_min.x, id_max.x): | 
					
						
							|  |  |  | 		for y in range(id_min.y, id_max.y): | 
					
						
							|  |  |  | 			for z in range(id_min.z, id_max.z): | 
					
						
							|  |  |  | 				var pos: Vector3i      = Vector3i(x, y, z) | 
					
						
							|  |  |  | 				var float_pos: Vector3 = Util.get_level_float_pos(pos) + Vector3(0.32, 0, 0.32) | 
					
						
							|  |  |  | 				var item_id: int       = level_character.get_cell_item(pos) | 
					
						
							|  |  |  | 				if item_id == GridMap.INVALID_CELL_ITEM: | 
					
						
							|  |  |  | 					continue | 
					
						
							|  |  |  | 				var item_name: String = mesh_library.get_item_name(item_id) | 
					
						
							|  |  |  | 				if item_name.begins_with("cp_"): | 
					
						
							|  |  |  | 					var character_born_spot = ChacacterBornSpot.new() | 
					
						
							|  |  |  | 					character_born_spot.pos = float_pos | 
					
						
							|  |  |  | 					character_born_spots.append(character_born_spot) | 
					
						
							|  |  |  | 				elif item_name.begins_with("c_"): | 
					
						
							|  |  |  | 					var character_name: String      = item_name.trim_prefix("c_") | 
					
						
							|  |  |  | 					var character_cfg: CharacterCfg = Util.get_character_cfg_by_name(character_name) | 
					
						
							|  |  |  | 					if not character_cfg: | 
					
						
							|  |  |  | 						continue | 
					
						
							|  |  |  | 					var character_spot = ChacacterSpot.new() | 
					
						
							|  |  |  | 					character_spot.cfg = character_cfg | 
					
						
							|  |  |  | 					character_spot.pos = float_pos | 
					
						
							|  |  |  | 					character_spots.append(character_spot) | 
					
						
							|  |  |  | 				elif item_name.begins_with("a_"): | 
					
						
							|  |  |  | 					var scene_name: String = item_name.trim_prefix("a_") | 
					
						
							|  |  |  | 					var scene: PackedScene = Util.get_level_active_scene_by_name(scene_name) | 
					
						
							|  |  |  | 					if not scene: | 
					
						
							|  |  |  | 						continue | 
					
						
							|  |  |  | 					var level_active_spot = LevelActiveSpot.new() | 
					
						
							|  |  |  | 					level_active_spot.scene = scene | 
					
						
							|  |  |  | 					level_active_spot.pos   = float_pos | 
					
						
							|  |  |  | 					level_active_spots.append(level_active_spot) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for enemy_num: LevelEnemy in enemy_nums: | 
					
						
							|  |  |  | 		for i in enemy_num.num: | 
					
						
							|  |  |  | 			enemy_cfgs.append(enemy_num.cfg) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func get_character_spots() -> Array[ChacacterSpot]: | 
					
						
							|  |  |  | 	return character_spots | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func get_character_born_spots() -> Array[ChacacterBornSpot]: | 
					
						
							|  |  |  | 	return character_born_spots | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func get_enemy_cfgs() -> Array[CharacterCfg]: | 
					
						
							|  |  |  | 	return enemy_cfgs | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func get_level_active_spots() -> Array[LevelActiveSpot]: | 
					
						
							|  |  |  | 	return level_active_spots | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func pos_min() -> Vector3: | 
					
						
							|  |  |  | 	return get_global_position() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func pos_max() -> Vector3: | 
					
						
							|  |  |  | 	var level_range: CSGBox3D = $LevelRange as CSGBox3D | 
					
						
							|  |  |  | 	var level_size: Vector3   = level_range.size | 
					
						
							|  |  |  | 	return get_global_position() + level_size | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func is_in_active_area(pos: Vector3) -> bool: | 
					
						
							|  |  |  | 	var active_pos_min: Vector3 = pos_min() + Vector3(0.96, 0, 0.96) | 
					
						
							|  |  |  | 	var active_pos_max: Vector3 = pos_max() - Vector3(0.96, 0, 0.96) | 
					
						
							|  |  |  | 	return pos.x >= active_pos_min.x and pos.x <= active_pos_max.x and \ | 
					
						
							|  |  |  | 	pos.z >= active_pos_min.z and pos.z <= active_pos_max.z and \ | 
					
						
							|  |  |  | 	pos.y >= active_pos_min.y and pos.y <= active_pos_max.y |