Commit graph

375 commits

Author SHA1 Message Date
Kelsi
a7ab2756d6 feat(editor): selected-NPC editor gains role flag checkboxes
Adds Hostile/Quest/Vendor/Inn/Train/Bank/Auc/Repair/Flight checkboxes
to the selected-NPC editor matching the template editor's set. Lets
users toggle these on already-placed NPCs without removing and
re-placing them.
2026-05-06 04:17:31 -07:00
Kelsi
9625201952 feat(editor): selected-NPC editor gains Faction input (parity with template) 2026-05-06 04:15:39 -07:00
Kelsi
4e01dd5553 feat(editor): NPC template gains Faction ID input with common-value tooltip
The CreatureSpawn struct has a faction field that was already exported
to creature_template.faction but wasn't editable. Added an InputInt with
a tooltip listing the common AzerothCore FactionTemplate IDs (Stormwind,
Monster, Beast, Friendly, Critter, etc.) so users can pick the right
hostility/disposition without referencing the DBC manually.
2026-05-06 04:14:33 -07:00
Kelsi
da2e7a4133 feat(editor): viewport WOM/WOB lookups also probe per-zone roots
EditorViewport gains setActiveMapName() so rebuildObjects can pass
per-zone prefixes (output/<map>/models|buildings/, custom_zones/<map>/...)
to tryLoadByGamePath. EditorApp wires it from loadADT, loadWMOInstance,
and createNewTerrain. Now the editor's preview mirrors the main game's
priority: per-zone WOM/WOB beats global custom_zones/, beats game data.
2026-05-06 04:13:03 -07:00
Kelsi
db068d480b feat(wob): tryLoadByGamePath helper, used by editor + terrain_manager
Mirrors the WOM tryLoadByGamePath API: probes custom_zones/buildings/ +
output/buildings/ by default, with optional extraPrefixes (e.g. per-zone
output/<map>/buildings/) checked first. Both the editor and the main
game's terrain_manager now use the helper, removing duplicate inline
lookup loops in two more places.
2026-05-06 04:10:12 -07:00
Kelsi
99aaab3aa8 feat(editor): add Trainer/Banker/Auctioneer/Repair NPC flags + SQL export
CreatureSpawn struct gains four AzerothCore-standard NPC flag bits:
  trainer    -> npcflag 0x10
  repair     -> npcflag 0x1000
  banker     -> npcflag 0x20000
  auctioneer -> npcflag 0x200000
Saved/loaded via the JSON spawn file, exported to creature_template.npcflag,
exposed as checkboxes in the NPC template panel. Lets users build full
city NPCs (city auctioneer, weapon trainer, etc.) without dropping to SQL.
2026-05-06 04:03:23 -07:00
Kelsi
bc6e60c6e9 polish(editor): placement scale slider matches selected-object range (0.1-50) 2026-05-06 04:00:07 -07:00
Kelsi
a156b6246e polish(editor): NPC selected-editor Facing slider shows 'deg' unit (matches template) 2026-05-06 03:59:10 -07:00
Kelsi
597c6547ac feat(editor): WMO objects also try WOB open format first like M2->WOM does
The editor's M2 placement path tries WOM (custom_zones/models/, output/
models/) before falling back to game M2 files. WMO placement just went
straight to game files. Now mirrors the M2 path: probes
custom_zones/buildings/ + output/buildings/ for a .wob, converts via
toWMOModel, falls back to MPQ-extracted WMO only on miss. Lets exported
zones render their custom buildings without needing the original WMO.
2026-05-06 03:56:52 -07:00
Kelsi
cbf1d4638f fix(editor): WMO instance scale actually applied to renderer
WMORenderer::createInstance accepts a scale parameter (default 1.0),
but the editor's call site ignored obj.scale. So a WMO sized to 2.0 in
the panel still rendered at 1.0. Now passes obj.scale through, so the
loaded MODF scale + any user gizmo scaling work end-to-end.
2026-05-06 03:52:40 -07:00
Kelsi
32ff80f177 feat(editor): texture panel shows total pool count + dir count 2026-05-06 03:48:37 -07:00
Kelsi
f4805b8e69 feat(editor): object panel shows total pool count for M2/WMO assets
Helps users understand the search base — 'Pool: 1234 M2  56 WMO' tells
them why their filter might be matching too many results, and gives a
quick view into how much asset variety the loaded data has.
2026-05-06 03:47:54 -07:00
Kelsi
ebf90eba9f fix(editor): zone manifest reset on load + auto-load existing zone.json
Two related fixes:
1. loadADT now resets zoneManifest_ at the top so the previous zone's
   mapId/displayName/flags/audio don't bleed into the new export.
2. When loading a zone that has a previously-exported zone.json on disk,
   call manifest.load() to restore the user-customized metadata. Without
   this every reload would reset Map ID back to 9000 etc.
2026-05-06 03:46:40 -07:00
Kelsi
f9187ef58a fix(editor): exportZone preserves user displayName + dedupes tile list
Two related zone-manifest bugs:
1. displayName was always overwritten with the .adt prefix on every
   export, throwing away whatever the user typed in the Zone Metadata
   panel.
2. tiles vector was push_back'd to without clearing, so re-exporting the
   same zone would accumulate duplicate tile entries.

Both fixed by checking displayName.empty() before assignment and calling
tiles.clear() before the rebuild loop.
2026-05-06 03:42:54 -07:00
Kelsi
28c63cb6d9 fix(editor): exportContentPack uses zoneManifest.mapId instead of hardcoded 9000
Users who set a custom Map ID via the Zone Metadata panel saw it ignored
when exporting the WCP — the pack info would always say mapId=9000.
Now reads from zoneManifest_, falling back to 9000 only when the field
is unset (0).
2026-05-06 03:41:29 -07:00
Kelsi
f856a90281 feat(editor): preserve WMO instance scale across ADT load/save
The MODF scale field (u16 / 1024 = float) is now propagated in both
directions: load reads wp.scale -> obj.scale, syncToTerrain converts
obj.scale * 1024 -> wp.scale (clamped to u16). Combined with the prior
loader/writer changes this means non-1.0 WMO scales (used by some
WotLK content) survive a save/reload cycle.
2026-05-06 03:40:03 -07:00
Kelsi
db1968f2cc feat(adt): preserve MODF nameSet + scale fields across load/save round-trip
WMOPlacement struct gains nameSet and scale fields (defaulting to 0 and
1024 = 1.0). The loader now reads them when the entry is the full 64
bytes (WotLK+); the writer emits the actual values rather than always
hard-coding (0, 1024). Older expansions still round-trip cleanly because
defaults match the previous behaviour.
2026-05-06 03:37:13 -07:00
Kelsi
446b0970dc fix(sql): translate spawn.id to creature SQL entry for quest links
The editor stores quest hooks (questGiverNpcId, turnInNpcId, KillCreature
targetName) as the spawner's per-spawn .id sequence. The SQL exporter
writes creature_template entries as 'creatureStartEntry + index'. The
two number spaces are different, so quest links pointed at non-existent
creature entries. Added a spawn.id -> SQL entry map built from the
spawns vector and used it in:
  - RequiredNpcOrGo[1..4] for KillCreature objectives
  - creature_queststarter / creature_questender
2026-05-06 03:33:36 -07:00
Kelsi
d258144df4 docs(format-spec): document WOB->WMO restoration details under WOB section 2026-05-06 03:31:04 -07:00
Kelsi
f022459971 fix(editor): NPC template scale slider matches selected-NPC editor range (0.1-50)
Template was a SliderFloat 0.5-10 while the selected-NPC editor uses
DragFloat 0.1-50. Inconsistent ceilings made it surprising that an NPC
could be scaled higher after placement than during placement. Now both
use DragFloat with the same range.
2026-05-06 03:30:30 -07:00
Kelsi
3abe47adc6 perf(editor): periodic M2 model GPU cache cleanup every 30s
The new persistent path->modelId map keeps models alive across rebuilds,
which is great for the common case of moving an instance, but means
models that lost all references stay in GPU memory forever. Added a
30s timer that calls m2Renderer->cleanupUnusedModels(), which has its
own 60s grace period before actual eviction — so models stick around
~60-90s after their last instance is removed and then get freed.
2026-05-06 03:26:39 -07:00
Kelsi
c1b6c9f621 fix(editor): exportZone clears autoSavePendingChanges_ flag
quickSave was the only path that cleared the flag, but exportZone is
also reachable through 'Export Open Format' and exportContentPack
without going through quickSave. Now any successful zone export clears
the dirty state so the asterisk and quit-confirm dialog reset properly.
2026-05-06 03:26:01 -07:00
Kelsi
5241bbd669 perf(editor): cache M2/WMO models across rebuilds, only clear instances
The editor's rebuildObjects path was destroying every cached model and
re-uploading it on every (debounced) change. Added M2Renderer::clearInstances
that drops only the instance list while keeping models loaded. Editor's
clearObjects switches to clearInstances (M2) + clearInstances (WMO),
and persistent path->modelId maps survive across rebuilds. clearTerrain
fully evicts when loading a new zone.
2026-05-06 03:23:06 -07:00
Kelsi
f18976ced9 feat(editor): --info-woc CLI prints collision mesh metadata
Completes the --info* CLI family. Reports tile coords, triangle count,
walkable/steep classification breakdown, and world-space bounds — useful
for verifying that collision exports cover the expected area.
2026-05-06 03:17:10 -07:00
Kelsi
8787b13dc1 feat(editor): --info-wob CLI prints WOB building metadata
Companion to --info for WOM. Reports name, group/portal/doodad counts,
total vertex/triangle/material counts. Useful for verifying converted
WMOs and debugging building rendering issues without launching the GUI.
2026-05-06 03:15:43 -07:00
Kelsi
683d703fbc feat(editor): --info <wom> CLI prints model metadata for inspection
Useful for verifying WOM exports and debugging conversion issues without
loading the GUI. Accepts either /path/to/file.wom or /path/to/file
(loader expects no extension). Reports version, name, geometry counts,
texture/bone/animation/batch counts, and bound radius.
2026-05-06 03:14:12 -07:00
Kelsi
248dcd4eb4 feat(editor): quest objective limit raised to 10 (matches SQL slot capacity)
UI was capped at 4 but the SQL exporter writes RequiredNpcOrGo[1..4] +
RequiredItemId[1..6] = 10 total slots. Allowing 10 lets users define
mixed kill+collect quests fully.
2026-05-06 03:13:26 -07:00
Kelsi
ce778ed674 feat(editor): patrol waypoint reorder (up/dn) + insert-after-cursor (+after)
Previously waypoints could only be appended or removed; reordering meant
clearing and re-adding the whole path. Now each waypoint row has up/dn
swap buttons and a +after that inserts a new waypoint at the current
brush cursor right after this index — slicing long segments doesn't
require redoing the rest of the path.
2026-05-06 03:12:45 -07:00
Kelsi
0be537e73d feat(editor): --validate <zoneDir> CLI scores zone open-format completeness
New CLI option that runs ContentPacker::validateZone on a zone directory
and prints the open-format score (0-7) with per-file breakdown including
magic-byte validity. Exits 0 if 7/7, 1 otherwise — useful for CI checks
on exported zones.
2026-05-06 03:09:56 -07:00
Kelsi
7822790c60 feat(editor): status bar asterisk also reflects unsaved object/NPC/quest changes 2026-05-06 03:01:09 -07:00
Kelsi
848947604e fix(editor): quit-confirm dialog also triggers for unsaved object/NPC/quest changes
Previously only terrain edits would trigger the 'unsaved changes' prompt
on quit, so a user who only added NPCs or quests could lose their work
by closing the window. Now checks autoSavePendingChanges_ alongside
terrain dirty state.
2026-05-06 03:00:10 -07:00
Kelsi
11f0580ccb docs(format-spec): bump to v1.2, document WOC mesh-append + SQL export
- WOC: add note that addMesh() also appends placed WMO group geometry
- New section on SQL server export covering coord/orientation conversion
  rules, table list, and how quest objectives map to RequiredNpcOrGo/
  RequiredItem slots.
2026-05-06 02:57:07 -07:00
Kelsi
7b2cbcfc92 feat(editor): status bar shows cursor world position alongside camera
Cam in dim yellow, cursor (when brush is on terrain) in cyan. Useful for
quickly noting positions where to drop spawns/objects without flying over
to read the brush coords manually.
2026-05-06 02:56:10 -07:00
Kelsi
6610d950cb fix(editor): flyToSelected uses atan2(to.y, to.x) for correct camera yaw
Camera::getForward = (cos(yaw), sin(yaw), sin(pitch)) — to make it
parallel to a direction vector we need atan2(y, x). The implementation
had x and y swapped, causing Fly To to point the camera 90deg off from
the target so the user often saw nothing.
2026-05-06 02:55:05 -07:00
Kelsi
fa631a45d6 refactor(sql): use core::coords::renderToCanonical for render->WoW swap
Replaces hand-written x/y swap with the canonical helper from
include/core/coordinates.hpp so the conversion stays in sync if the
coord convention changes.
2026-05-06 02:52:46 -07:00
Kelsi
0f42ebab3d feat(editor): quest objectives now have a Target ID field + spawn picker
The SQL exporter writes objective targets to RequiredNpcOrGo/RequiredItem
slots based on the objective's targetName field, but the UI never let
the user fill that field. Added an InputText for Target ID and, for Kill
objectives, a dropdown that auto-fills with the entry of any placed NPC.
2026-05-06 02:51:12 -07:00
Kelsi
d44a8a48ce feat(editor): patrol path waypoints color-coded by traversal order
Path direction was ambiguous from a static screenshot: ribbon and waypoints
were uniform orange/white. Now ribbons fade from bright at the start to
dim at the end, and waypoints go green (NPC home) -> yellow/orange
(intermediate) -> red (last) so direction of travel reads at a glance.
2026-05-06 02:50:04 -07:00
Kelsi
e041ae7ac7 fix(sql): convert editor yaw (from +renderX/west) to WoW yaw (from +X/north)
Editor's orientation is measured from +renderX (which maps to west in WoW
canonical), but AzerothCore creature.orientation is the WoW yaw measured
from +X (north). Without conversion an editor 0deg NPC ended up facing
west in-game, off by 90deg even after the radians fix. Now applies
`wowYaw = π/2 - editorYaw` and normalizes to [0, 2π).
2026-05-06 02:49:02 -07:00
Kelsi
edce3abf41 fix(sql): swap render-coord x/y to WoW canonical for creature/waypoint export
Editor stores positions in render coords (renderX=wowY=west, renderY=wowX
=north, renderZ=wowZ=up) but AzerothCore creature.position_x/y are in
WoW canonical space (X=north-south, Y=west-east). Without the swap every
exported creature appeared on the wrong end of the map. Same swap now
applied to creature spawns AND waypoint_data path points.
2026-05-06 02:47:03 -07:00
Kelsi
b30b44ab7e chore(cli): --convert-m2 reports WOM version + batch count in success message 2026-05-06 02:45:23 -07:00
Kelsi
469f046db5 feat(editor): NPC list shows hostile/friendly/questgiver/vendor counts
Helps users see at-a-glance the makeup of their zone's creature pop
without having to scroll the list looking at each entry's flags.
2026-05-06 02:41:23 -07:00
Kelsi
273c2fe10c feat(sql): export quest objectives to RequiredNpcOrGo/RequiredItem slots
quest_template now writes up to 4 KillCreature objectives into the
RequiredNpcOrGo/RequiredNpcOrGoCount slots and up to 6 CollectItem
objectives into the RequiredItemId/RequiredItemCount slots. The numeric
target ID is parsed from the objective's targetName field — empty/non-
numeric targets emit 0 (objective hooked up but unwired).
2026-05-06 02:38:05 -07:00
Kelsi
b7d9d54b29 feat(sql): emit creature_queststarter/questender for quest-NPC links
quest_template alone tells the server about the quest but not who hands
it out. Without creature_queststarter/questender entries, players can't
acquire or turn in the quest. Now writes both tables when the quest has
questGiverNpcId / turnInNpcId set.
2026-05-06 02:35:29 -07:00
Kelsi
22c9bc354c feat(editor): placed-object list also has name filter (parity with NPC list) 2026-05-06 02:34:41 -07:00
Kelsi
590ec6b3a3 feat(editor): NPC spawn list has name filter for fast lookup
A zone with 50+ creatures made finding a specific spawn tedious. Added
a case-insensitive name-filter input above the list, capped at 200
visible entries with a 'refine filter' hint when exceeded.
2026-05-06 02:34:05 -07:00
Kelsi
eadb6a5886 feat(woc): add WMO collision meshes to exported zone collision
WoweeCollision previously only contained terrain triangles; placed WMO
buildings had no collision in the exported zone, so players could walk
through walls. Added WoweeCollisionBuilder::addMesh() that transforms a
local-space mesh into world space with slope-based walkability flags,
and the editor's exportZone now walks every placed WMO and feeds each
group's geometry through it. Indoor vs outdoor groups are tagged via
the WMO group flag.
2026-05-06 02:33:22 -07:00
Kelsi
88c105103b fix(content-pack): validateZone accepts WOM2/WOM3 as valid WOM files
ContentPacker.validateZone only matched WOM1 magic (0x314D4F57). Any zone
exported with animated (WOM2) or multi-batch (WOM3) models was scored as
having invalid WOM files, lowering the open-format score from 7/7 to 6/7
even though everything is correct. Now accepts the WOM family.
2026-05-06 02:18:37 -07:00
Kelsi
49b7268dc9 feat(editor): show camera (x,y,z) in status bar
Helpful for navigation and noting positions for spawn placement, plus
diagnostic value when debugging coordinate issues. Shown only after a
terrain is loaded.
2026-05-06 02:10:50 -07:00
Kelsi
7c506f582a feat(editor): flyToSelected places camera with proper aim and offset
Previously just teleported camera 30u directly above the target — the user
still had to manually look down to see anything. Now positions the camera
back along the current view direction, slightly elevated, and aims it at
the selection so the target is visible immediately. Removes the round-trip
through manual rotation after every Fly To.
2026-05-06 02:04:50 -07:00
Kelsi
f1223cfc69 chore(editor): cap texture-not-found warnings at 5 with suppression count
Some checks are pending
Build / Build (arm64) (push) Waiting to run
Build / Build (x86-64) (push) Waiting to run
Build / Build (macOS arm64) (push) Waiting to run
Build / Build (windows-arm64) (push) Waiting to run
Build / Build (windows-x86-64) (push) Waiting to run
Security / CodeQL (C/C++) (push) Waiting to run
Security / Semgrep (push) Waiting to run
Security / Sanitizer Build (ASan/UBSan) (push) Waiting to run
Character body/skin textures live in CharSections-composed paths that
don't exist as standalone BLPs. Exporting a zone with many character
NPCs would spam hundreds of warnings. Now logs the first 5, suppresses
the rest, and reports the total skipped count in the summary line.
2026-05-06 02:03:30 -07:00