You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
241 lines
7.5 KiB
GDScript
241 lines
7.5 KiB
GDScript
@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 enemy_nums: Array[LevelEnemy]
|
|
|
|
@onready var grid_block_material: Material = load("res://render/material/level_grid_block.tres") as Material
|
|
|
|
#character
|
|
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]
|
|
#main
|
|
var mark_white_list: Array[Vector3i]
|
|
var mark_black_list: Array[Vector3i]
|
|
var grid_main_cache_cells: Array[GridMainCacheCellData]
|
|
|
|
|
|
class ChacacterSpot:
|
|
var pos: Vector3
|
|
var cfg: CharacterCfg
|
|
|
|
|
|
class ChacacterBornSpot:
|
|
var pos: Vector3
|
|
var type: int
|
|
|
|
|
|
class LevelActiveSpot:
|
|
var pos: Vector3
|
|
var scene: PackedScene
|
|
|
|
|
|
class GridMainCacheCellData:
|
|
var pos: Vector3i
|
|
var id: int
|
|
var orientation: int
|
|
|
|
|
|
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 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() -> void:
|
|
init_level_character()
|
|
init_level_main()
|
|
|
|
|
|
func set_focus() -> void:
|
|
var level_range: CSGBox3D = $LevelRange as CSGBox3D
|
|
var level_size: Vector3 = level_range.size
|
|
var focus_min: Vector3 = get_global_position() + Vector3(0.640001, 0.640001, 0.640001)
|
|
var focus_max: Vector3 = get_global_position() + level_size - Vector3(0.640001, 0.639999, 0.639999)
|
|
grid_block_material.set_shader_parameter("focus_min", focus_min)
|
|
grid_block_material.set_shader_parameter("focus_max", focus_max)
|
|
|
|
|
|
func init_level_character() -> void:
|
|
var level_character: GridMap = %LevelGridCharacter as GridMap
|
|
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()
|
|
var used_cells: Array[Vector3i] = level_character.get_used_cells()
|
|
for pos in used_cells:
|
|
if pos.x < id_min.x or pos.x > id_max.x:
|
|
continue
|
|
if pos.y < id_min.y or pos.y > id_max.y:
|
|
continue
|
|
if pos.z < id_min.z or pos.z > id_max.z:
|
|
continue
|
|
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("chara_spot_"):
|
|
var character_born_spot = ChacacterBornSpot.new()
|
|
character_born_spot.pos = float_pos
|
|
character_born_spots.append(character_born_spot)
|
|
elif item_name.begins_with("chara_enemy_"):
|
|
var character_name: String = item_name.trim_prefix("chara_enemy_")
|
|
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("chara_active_"):
|
|
var scene_name: String = item_name.trim_prefix("chara_active_")
|
|
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 init_level_main() -> void:
|
|
var level_main: GridMap = %LevelGridMain as GridMap
|
|
var id_min: Vector3i = Util.get_level_grid_pos2(pos_min())
|
|
var id_max: Vector3i = Util.get_level_grid_pos2(pos_max())
|
|
# 正前面
|
|
for x in range(id_min.x, id_max.x+1):
|
|
for y in range(id_min.y, id_max.y+1):
|
|
var pos: Vector3i = Vector3i(x, id_max.z, y)
|
|
add_grid_main_cache_cell(level_main, pos)
|
|
# 底面黑块
|
|
for x in range(id_min.x, id_max.x+1):
|
|
for z in range(id_min.z, id_max.z+1):
|
|
var pos: Vector3i = Vector3i(x, id_min.y, z)
|
|
var id: int = level_main.get_cell_item(pos)
|
|
if not(id == GridMap.INVALID_CELL_ITEM or z == id_max.z):
|
|
continue
|
|
mark_black_list.append(pos)
|
|
# 底面黑块延申空气墙
|
|
for mark_black in mark_black_list:
|
|
for y in range(id_min.y, id_max.y -1):
|
|
var pos: Vector3i = Vector3i(mark_black.x, y, mark_black.z)
|
|
add_grid_main_cache_cell(level_main, pos)
|
|
mark_white_list.append(pos)
|
|
# 顶面
|
|
for x in range(id_min.x, id_max.x+1):
|
|
for z in range(id_min.z, id_max.z+1):
|
|
var pos: Vector3i = Vector3i(x, id_max.y, z)
|
|
add_grid_main_cache_cell(level_main, pos)
|
|
var pos_down: Vector3i = Vector3i(x, id_max.y - 1, z)
|
|
if level_main.get_cell_item(pos_down) == GridMap.INVALID_CELL_ITEM:
|
|
mark_white_list.append(pos)
|
|
else:
|
|
mark_black_list.append(pos)
|
|
|
|
|
|
func add_grid_main_cache_cell(level_main: GridMap, pos: Vector3i) -> void:
|
|
var id: int = level_main.get_cell_item(pos)
|
|
if id == GridMap.INVALID_CELL_ITEM:
|
|
return
|
|
var cache_data = GridMainCacheCellData.new()
|
|
cache_data.pos = pos
|
|
cache_data.id = id
|
|
cache_data.orientation= level_main.get_cell_item_orientation(pos)
|
|
grid_main_cache_cells.append(cache_data)
|
|
|
|
|
|
func set_replace(is_active: bool)-> void:
|
|
var level_main: GridMap = %LevelGridMain as GridMap
|
|
if is_active:
|
|
for cache_data in grid_main_cache_cells:
|
|
level_main.set_cell_item(cache_data.pos, GridMap.INVALID_CELL_ITEM)
|
|
for pos in mark_white_list:
|
|
level_main.set_cell_item(pos, 0)
|
|
for pos in mark_black_list:
|
|
level_main.set_cell_item(pos, 1)
|
|
else:
|
|
for pos in mark_white_list:
|
|
level_main.set_cell_item(pos, GridMap.INVALID_CELL_ITEM)
|
|
for pos in mark_black_list:
|
|
level_main.set_cell_item(pos, GridMap.INVALID_CELL_ITEM)
|
|
for cache_data in grid_main_cache_cells:
|
|
level_main.set_cell_item(cache_data.pos, cache_data.id, cache_data.orientation)
|
|
|
|
|
|
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 outter_pos_min() -> Vector3:
|
|
return pos_min() - Vector3(0.72, 0.72, 0.72)
|
|
|
|
|
|
func outter_pos_max() -> Vector3:
|
|
return pos_max() - Vector3(0.72, 0.72, 0.72)
|
|
|
|
|
|
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
|