Scholomance: replace kg's Cata 4-floor map with classic single-room layout
kg only ships the post-Cataclysm Scholomance (4 floors split as you ascend the school) but Ascension uses the classic single-floor layout where every wing branches off the central rooms. Fix: new dungeon_replacements section in ascension_overrides.json. When a tile_key is listed there, build_data skips kg entirely for that dungeon and synthesises a single-floor entry from a manually-supplied map (Atlas-addon Scholomance.blp upscaled to 2048x2048) and AtlasLoot's per-dungeon boss list. Coords come from AtlasLoot's 0..100 percent space scaled to the new map's pixel space directly. Pin classification: dungeonskull → boss (cls=3), None+name-contains-Rare → rare elite (cls=5), other interactives → cls=2.
This commit is contained in:
@@ -1,5 +1,18 @@
|
||||
{
|
||||
"_comment": "Ascension-specific corrections to the upstream kg / AtlasLoot data. Each entry overrides where an enemy/extra is rendered. Match by tile_key + name (case-insensitive substring). pos is in kg pixel space (z=4 stitched image, 6144x4096). kg_floor_id picks the floor (omit if the dungeon is single-floor).",
|
||||
|
||||
"_dungeon_replacements_comment": "When the kg map is the wrong layout for Ascension (e.g. retail/Cata layout vs classic), replace the entire dungeon's map with one we author manually. Coords are in the new map's pixel space (0..width, 0..height). Bosses come from AtlasLoot's per-dungeon entries with cords; pinType=dungeonskull → cls=3, pinType=None → cls=5 (rare).",
|
||||
"dungeon_replacements": {
|
||||
"scholomance": {
|
||||
"image": "maps/scholomance.webp",
|
||||
"width": 2048,
|
||||
"height": 2048,
|
||||
"atlasloot_id": "Scholomance",
|
||||
"label": "Scholomance",
|
||||
"note": "kg ships only the Cata 4-floor layout; Ascension uses the classic single-room layout. Map is Atlas-addon BLP upscaled to 2048."
|
||||
}
|
||||
},
|
||||
|
||||
"overrides": [
|
||||
{
|
||||
"tile_key": "stratholme",
|
||||
|
||||
+81
-1
@@ -225,8 +225,83 @@ def main() -> int:
|
||||
extras_db = json.loads(EXTRAS_PATH.read_text()).get("extras", {})
|
||||
|
||||
overrides = []
|
||||
dungeon_replacements = {}
|
||||
if OVERRIDES_PATH.exists():
|
||||
overrides = json.loads(OVERRIDES_PATH.read_text()).get("overrides", [])
|
||||
ov_doc = json.loads(OVERRIDES_PATH.read_text())
|
||||
overrides = ov_doc.get("overrides", [])
|
||||
dungeon_replacements = ov_doc.get("dungeon_replacements", {})
|
||||
|
||||
# Load AtlasLoot map data on demand for dungeon replacements.
|
||||
atlasloot_data = None
|
||||
al_path = Path("/tmp/atlasloot_maps.json")
|
||||
if al_path.exists():
|
||||
try:
|
||||
atlasloot_data = json.loads(al_path.read_text())
|
||||
except Exception:
|
||||
atlasloot_data = None
|
||||
|
||||
def replacement_entry(tile_key, repl, registry_entry):
|
||||
"""Build a complete dungeon record from a manual-override map +
|
||||
AtlasLoot bosses. Bypasses kg entirely for this dungeon."""
|
||||
al_id = repl["atlasloot_id"]
|
||||
al = (atlasloot_data or {}).get("OriginalWoW", {}).get(al_id, {})
|
||||
W, H = repl["width"], repl["height"]
|
||||
|
||||
enemies = []
|
||||
seen = set()
|
||||
for k, v in al.items():
|
||||
if not k.isdigit() or not isinstance(v, list):
|
||||
continue
|
||||
for ent in v:
|
||||
if not isinstance(ent, dict):
|
||||
continue
|
||||
if ent.get("SubZone"):
|
||||
continue
|
||||
cords = ent.get("cords")
|
||||
name = ent.get("1")
|
||||
if not (isinstance(cords, list) and len(cords) == 2 and name):
|
||||
continue
|
||||
key = (name, cords[0], cords[1])
|
||||
if key in seen:
|
||||
continue
|
||||
seen.add(key)
|
||||
pin = ent.get("pinType")
|
||||
lname = name.lower()
|
||||
if pin == "dungeonskull":
|
||||
cls = 3
|
||||
elif pin is None and "rare" in lname:
|
||||
cls = 5
|
||||
else:
|
||||
cls = 2 # quest item, summon spot, lever, etc.
|
||||
enemies.append({
|
||||
"id": None,
|
||||
"npc_id": None,
|
||||
"name": name,
|
||||
"pos": [round(cords[0] / 100 * W, 1), round(cords[1] / 100 * H, 1)],
|
||||
"classification": cls,
|
||||
"skippable": False, "required": False,
|
||||
"kill_priority": None, "pack_id": None, "patrol_id": None,
|
||||
})
|
||||
map_obj = {
|
||||
"image": repl["image"],
|
||||
"width": W, "height": H,
|
||||
"label": repl.get("label", tile_key),
|
||||
"kg_floor_id": None,
|
||||
"enemies": enemies,
|
||||
"packs": [], "patrols": [], "icons": [],
|
||||
}
|
||||
return {
|
||||
"id": tile_key,
|
||||
"expansion": "OriginalWoW",
|
||||
"name": registry_entry.get("name", tile_key),
|
||||
"acronym": registry_entry.get("acronym"),
|
||||
"tile_key": tile_key,
|
||||
"data_slug": registry_entry.get("data_slug"),
|
||||
"mapping_id": registry_entry.get("mapping_id"),
|
||||
"maps": [map_obj],
|
||||
"ascension_replaced": True,
|
||||
"replacement_note": repl.get("note"),
|
||||
}
|
||||
|
||||
def apply_overrides(tile_key, name, pos, floor_id):
|
||||
"""Return (pos, floor_id) possibly replaced by an Ascension override."""
|
||||
@@ -268,6 +343,11 @@ def main() -> int:
|
||||
except Exception:
|
||||
npc_index = {}
|
||||
|
||||
# Dungeon replacement: skip kg entirely for this one.
|
||||
if d["tile_key"] in dungeon_replacements:
|
||||
dungeons.append(replacement_entry(d["tile_key"], dungeon_replacements[d["tile_key"]], d))
|
||||
continue
|
||||
|
||||
entry = build_one(d, summary, npc_index, icon_index)
|
||||
if entry:
|
||||
extras = extras_db.get(d["tile_key"], [])
|
||||
|
||||
+222
-8425
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user