@@ -25,7 +25,7 @@ DIR = {
|
||||
}
|
||||
|
||||
LEVEL_RE = re.compile(
|
||||
r"\{(\d+),new Level\(\)\{LevelID\s*=\s*\d+,spawns\s*=\s*new List<Spawn>\(\)\{",
|
||||
r"\{\s*(\d+)\s*,\s*new Level\(\)\s*\{\s*LevelID\s*=\s*\d+\s*,\s*spawns\s*=\s*new List<Spawn>\(\)\s*\{",
|
||||
re.MULTILINE,
|
||||
)
|
||||
|
||||
@@ -34,7 +34,7 @@ SPAWN_RE = re.compile(
|
||||
re.MULTILINE,
|
||||
)
|
||||
|
||||
POS_RE = re.compile(r"position\s*=\s*new Vector3Int\((-?\d+),(-?\d+),0\)")
|
||||
POS_RE = re.compile(r"position\s*=\s*new Vector3Int\((-?\d+),(-?\d+),-?\d+\)")
|
||||
PATH_RE = re.compile(r'path\s*=\s*"?([^",\s]+)"?')
|
||||
PDIR_RE = re.compile(r"playerDirection\s*=\s*(Direction\.\w+)")
|
||||
VDIR_RE = re.compile(r"vehicleDirection\s*=\s*(Direction\.\w+)")
|
||||
@@ -49,21 +49,51 @@ def kind_from_path(path: str) -> str:
|
||||
return "vehicle"
|
||||
if "enemy" in p:
|
||||
return "enemy"
|
||||
if "prop" in p:
|
||||
if "prop" in p or "nrop" in p:
|
||||
return "prop"
|
||||
return "prop_decor"
|
||||
|
||||
|
||||
def prop_placement_from_path(path: str) -> str | None:
|
||||
if "nprop" in path.lower():
|
||||
pl = path.lower()
|
||||
if "nprop" in pl or "nrop" in pl:
|
||||
return "ground"
|
||||
if "prop" in path.lower():
|
||||
if "prop" in pl:
|
||||
return "block"
|
||||
return None
|
||||
|
||||
|
||||
def parse_spawns(block: str) -> list[dict]:
|
||||
spawns = []
|
||||
def infer_theme_from_level(level_id: int, spawn_paths: list[str]) -> str:
|
||||
"""按主站关卡批次分配主题;道具路径可覆盖(snow/sanxing)。"""
|
||||
if 91601 <= level_id <= 91900:
|
||||
return "silu"
|
||||
if 91901 <= level_id <= 92200:
|
||||
return "redarmy"
|
||||
if 92201 <= level_id <= 92500:
|
||||
return "numMan"
|
||||
if 92501 <= level_id <= 92800:
|
||||
return "chinese"
|
||||
if 92801 <= level_id <= 93100:
|
||||
return "snow"
|
||||
if 93101 <= level_id <= 93700:
|
||||
return "sanxing"
|
||||
joined = " ".join(spawn_paths).lower()
|
||||
if "prop_sanxing" in joined or "nprop_sanxing" in joined:
|
||||
return "sanxing"
|
||||
if "prop_snow" in joined or "nprop_snow" in joined:
|
||||
return "snow"
|
||||
if "chinese" in joined or "panda" in joined:
|
||||
return "chinese"
|
||||
if "redarmy" in joined or "red_army" in joined:
|
||||
return "redarmy"
|
||||
if "numman" in joined:
|
||||
return "numMan"
|
||||
return "silu"
|
||||
|
||||
|
||||
def parse_spawns(block: str) -> tuple[list[dict], list[str]]:
|
||||
spawns: list[dict] = []
|
||||
paths: list[str] = []
|
||||
for m in SPAWN_RE.finditer(block):
|
||||
body = m.group(1)
|
||||
pm = POS_RE.search(body)
|
||||
@@ -71,6 +101,8 @@ def parse_spawns(block: str) -> list[dict]:
|
||||
continue
|
||||
path_m = PATH_RE.search(body)
|
||||
path = path_m.group(1) if path_m else ""
|
||||
if path:
|
||||
paths.append(path)
|
||||
item: dict = {
|
||||
"x": int(pm.group(1)),
|
||||
"y": int(pm.group(2)),
|
||||
@@ -86,7 +118,7 @@ def parse_spawns(block: str) -> list[dict]:
|
||||
if vdir:
|
||||
item["vehicleDirection"] = vdir.group(1)
|
||||
spawns.append(item)
|
||||
return spawns
|
||||
return spawns, paths
|
||||
|
||||
|
||||
def ring_border_key(bx: int, by: int) -> str:
|
||||
@@ -105,12 +137,13 @@ def parse_file(text: str) -> dict[int, dict]:
|
||||
bx, by = (10, 10)
|
||||
if bound:
|
||||
bx, by = int(bound.group(1)), int(bound.group(2))
|
||||
spawns = parse_spawns(chunk)
|
||||
spawns, spawn_paths = parse_spawns(chunk)
|
||||
levels[lid] = {
|
||||
"levelID": lid,
|
||||
"boundary": {"x": bx, "y": by},
|
||||
"borderKey": ring_border_key(bx, by),
|
||||
"spawns": spawns,
|
||||
"theme": infer_theme_from_level(lid, spawn_paths),
|
||||
}
|
||||
return levels
|
||||
|
||||
|
||||
Reference in New Issue
Block a user