@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