[General] How are objects sorted in the Object editor?

Status
Not open for further replies.
Hello, I am trying to reproduce Units/items palette from the editor as a debug UI tool. To achieve this, I need lists of ids from the editor, which I recovered from slk files but I can't find the logic behind the ordering in the editor, someone has a clue or a way to get those Ids in the same order as they are in the editor?

Otherwise, I have to manually sort the Ids and it's tiresome.
22-04-18-21-11-42.gif
 
If you look at Retera Model Studio, where it has "Unit Browser" on the right hand side, OR the different version if you use "File -> Open Internal -> Unit" to get a list of units, both of these are doing an algorithmic and not human-entered sort order. This algorithmic ordering is not using the algorithm from Warcraft III, since I do not have that. It is a close replica that I invented years ago by staring at the World Editor and thinking about how things appeared to be sorted.

If I'm not mistaken, Reforged also changed the Unit Editor sort order -- or at least the default order -- from what it was previously. Previously we used the SLK sort string if I recall, and I think on Reforged they might have sorted by name.

So anyway, in my code there are two main files you're interested in if you want to read my implementation.



The first one is UnitOptionPanel (older code):
1650398724399.png

The UnitOptionPanel only loads SLK units and didn't use my newer API that was developed a few years later to load SLK+Object Editor information. But, the premise is still generally the same as what I imagine you would use in-game in your custom scripts. First before displaying anything, I iterate the list of all units in the game and populate them into bins using a function called "sortRaces()" here: ReterasModelStudio/UnitOptionPanel.java at ea3afb3dce58b42e987be0da688cf0a40ac70bad · Retera/ReterasModelStudio

You can see here further down in that same function, where I categorize each unit as either a
(1) unit
(2) hero
(2) building
(3) uprooted building + building
(4) special

It is worth noting that after I developed this UI component for my own libraries, at some point I modified my implementation so that it does not exactly match the one used in the World Editor. Instead, my UI offers a fourth top-level category -- along with "Melee", "Campaign" and "Custom" there is also the "Hidden" option. This contains units like the Kobold Shoveler that do not display typically in these views in the World Editor, but are still present in the game data. Presumably that level of categorization will not matter to you, but I guess that's up to you.

After these bins are created during the sortRaces() setup, there's another function that gets called when the user changes the dropdown boxes to actually populate what is onscreen. For me that function is this relayout() function here. It is a little bit long, but probably it could be shortened if you cared about having cleaner code. There is a lot of repetition where I didn't make any utility function and I just copied the thing for units, and heroes, and buildings, etc. I think I wrote this 6 or more years ago originally.

The second one is UnitEditorTree (newer code, supports custom units):
1650398657961.png
This second component, notably, is using a totally different sort mechanism. The code is a bit more complicated. Each of these expandable folder icons is represented in an instance of a custom class, so the entire tree is constructed of different files managing each level of depth. But, at the deepest innermost level, the sorting for units is ultimately delegated to this MutableGameUnitComparator: ReterasModelStudio/MutableGameUnitComparator.java at 0.04 · Retera/ReterasModelStudio

Here are some of the classes for the folders if you ever want to go down a rabbit hole reading about that:
 
Level 3
Joined
May 10, 2007
Messages
40
Hello, I am trying to reproduce Units/items palette from the editor as a debug UI tool. To achieve this, I need lists of ids from the editor, which I recovered from slk files but I can't find the logic behind the ordering in the editor, someone has a clue or a way to get those Ids in the same order as they are in the editor?

Otherwise, I have to manually sort the Ids and it's tiresome.
I have thoroughly investigated this and though I cannot tell you exactly WHY some of the units are in the order they are in, I can tell you the exact way they are sorted in the editor.

First, the units are sorted according to hardcoded groups. If several units share the same group (like if many custom units are derived from the same standard unit), then they are sorted according to unit level (this is how the creep types appear in the order from lowest to highest level) Finally, units of the same level are sorted alphabetically (this is why most campaign heroes appear in alphabetical order)

This is the order of hardcoded groups the World Editor uses:

Swordsman
Captain

City Building 0
City Building 1
City Building 2
City Building 3
City Building 4
City Building 5
City Building 6
City Building 7
City Building 8
City Building 9
City Building 10
City Building 11
City Building 12
City Building 13
City Building 14
City Building 15

Tree of Life
Tree of Ages
Tree of Eternity
Moon Well
Altar of Elders
Ancient of War
Ancient of Lore
Ancient of Wind
Hunter's Hall
Ancient Protector
Chimaera Roost
Entangled Gold Mine
Corrupted Moon Well
Ancient of Wonders
Corrupted Tree of Life
Corrupted Tree of Ages
Corrupted Tree of Eternity
Corrupted Ancient Protector
Fountain of Power
Horn of Cenarius Pedestal

Keeper of the Grove
Priestess of the Moon
Demon Hunter
Demon Hunter (Demon Form)
Warden

Wisp
Archer
Huntress
Dryad
Glaive Thrower
Hippogryph
Hippogryph Rider
Chimaera
Druid of the Talon (Night Elf Form)
Druid of the Talon (Storm Crow Form)
Druid of the Claw (Night Elf Form)
Druid of the Claw (Bear Form)
Mountain Giant
Treant
Tharifas
Avatar of Vengeance
Spirit of Vengeance
Faerie Dragon

Grain Warehouse
Town Hall
Keep
Castle
Farm
Altar of Kings
Barracks
Lumber Mill
Blacksmith
Workshop
Arcane Sanctum
Gryphon Aviary
Scout Tower
Guard Tower
Cannon Tower
Arcane Tower
Arcane Vault
Sky-Fury Tower
Earth-Fury Tower
High Elven Guard Tower
Dalaran Guard Tower
High Elven Barracks
High Elven Farms (9)

Paladin
Archmage
Mountain King
Blood Mage

Peasant
Footman
Knight
Rifleman
Mortar Team
Flying Machine
Gryphon Rider
Priest
Sorceress
Siege Engine
Siege Engine (Barrage)
Militia
Spell Breaker
Dragonhawk Rider
Emissary
Water Elemental (Level 1)
High Elf (Female)
Water Elemental (Level 2)
Water Elemental (Level 3)
High Elf (Male)
Archer
Phoenix
Medivh
Medivh (Raven Form)
Searinox

Gold Mine
Goblin Merchant
Fountain of Health
Fountain of Mana
Goblin Laboratory
Way Gate
Dragon Roosts (6)
Mercenary Camp (Lordaeron Summer)
Mercenary Camp (Lordaeron Fall)
Mercenary Camp (Lordaeron Winter)
Mercenary Camp (Barrens)
Mercenary Camp (Ashenvale)
Mercenary Camp (Felwood)
Mercenary Camp (Northrend)
Mercenary Camp (Cityscape)
Mercenary Camp (Dalaran)
Mercenary Camp (Village)
Mercenary Camp (Dungeon)
Mercenary Camp (Underground)
Circle of Power
Circle of Power (medium)
Circle of Power (large)
Tavern
Marketplace
Mercenary Camp (Sunken Ruins)
Mercenary Camp (Icecrown Glacier)
Goblin Shipyard
Mercenary Camp (Outland)
Mercenary Camp (Black Citadel)
Creep Huts (24)

Great Hall
Stronghold
Fortress
Altar of Storms
Barracks
War Mill
Tauren Totem
Spirit Lodge
Beastiary
Orc Burrow
Watch Tower
Pig Farm
Voodoo Lounge
Dragon Roost
Fountain of Blood
Defiled Fountain of Life
Fel Orc Burrow (Chaos)

Blademaster
Far Seer
Tauren Chieftain
Blademaster of Blackrock Clan
Shadow Hunter

Peon
Grunt
Raider
Tauren
Troll Headhunter
Demolisher
Kodo Beast
Wind Rider
Troll Batrider
Troll Witch Doctor
Shaman
Eye Wards (2)
Stasis Trap
Spirit Wolf (Level 1)
Dire Wolf (Level 2)
Shadow Wolf (Level 3)
Healing Ward
Orc Warlock
Fel Orc Warlock
Fel Orc Grunt
Serpent Ward (Level 1)
Fel Orc Raider
Serpent Ward (Level 2)
Fel Orc Kodo Beast
Fel Orc Peon
Serpent Ward (Level 3)
Serpent Ward (Level 4)
Spirit Walker
Spirit Walker (Ethereal)
Troll Berserker

Necropolis
Halls of the Dead
Black Citadel
Ziggurat
Spirit Tower
Nerubian Tower
Altar of Darkness
Crypt
Sacrificial Pit
Graveyard
Slaughterhouse
Temple of the Damned
Boneyard
Haunted Gold Mine
Shrine
Tomb of Relics
Demon Gate
Infected Granary
Frostmourne Pedestal
Book of Summoning Pedestal

Death Knight
Lich
Dreadlord
Crypt Lord

Acolyte
Shade
Ghoul
Abomination
Meat Wagon
Crypt Fiend
Burrowed Crypt Fiend
Gargoyle
Stone Form Gargoyle
Banshee
Necromancer
Skeleton Warrior
Skeletal Mage
Obsidian Statue
Misc. Undead 1 (Destroyer, Pit Lord, Frost Wyrm)
Misc. Undead 2 (Zombie, Archimonde)
Carrion Beetle (Level 1)
Burrowed Carrion Beetle (Level 2)
Carrion Beetle (Level 2)
Burrowed Carrion Beetle (Level 3)
Carrion Beetle (Level 3)

Space Fel Orc
Hydralisk
(Presumably, Kobold Shoveler is here, but I can't find a tutorial on how to get it to appear in editor)
Marine
Orc Juggernaught (Cinematic)
(Presumably, Sammy! goes here)
Zergling

Alchemists (4)
Critters, Villagers and Owl Scouts (31)
Arachnathids (7)
Bandits (6)
Bears (7) (Not including Misha in Orc > Campaign > Special)
Blue Dragonspawn (5)
Ships (Not including Northrend Ship) (13)
Centaur (6)
Clockwerk Goblins and Pocket Factories (7)
Spider Crabs (3)
Dark Trolls (6)
Draenei Units (10) (Not including Akama, Salamander or Demolisher)
Draenei Campaign Buildings (3)
Red Dragons (3)
Black Dragons (3)
Bronze Dragons (3)
Green Dragons (3)
Blue Dragons (3)
Nether Dragons (3)
Hawks (3)
Creep Elementals (4)
Corrupted Treants (3)
Eredar (3)
Faceless Ones (3)
Felguards (3)
Felhounds (3)
Spirit Beasts (3)
Forest Trolls (6)
Tentacle and Forgotten One (2)
Furbolg and Feral Pandaren (7)
Banshee Ghosts (2)
Sea Giants (3)
Spiders (6)
Gnoll Archers (2)
Gnolls (4)
Goblin Zeppelin, Sapper, Shredder & Blaster (4)
Stone Golems (3)
Iron Golems (3)
Harpies (5)
Creep Acolytes (3)
Hydras (4)
Ice Trolls (6)
Infernal Cannons (3)
Kobolds (4)
Lava Spawn (3)
Lizards (3)
Lobstrokk/Makrura (7) (Including Summoned Prawn)
Bandit Wizards (6) (Including Chaplain and Hydromancer)
Magnataur (3)
Mammoths (3)
Mur'gul (6) (Reaver not included)
Murloc (6)
Naga (11) (Including Mur'gul Reaver, Summoner, Submerged, Naga Sea Witch, Not Including Dragon Turtle)
Nerubians (6)
Ogres (7) (Including Stonemaul)
Owlbears/Wildkin (3)
Storm, Earth and Fire (6)
Polar Bears (2)
Polar Furbolgs (6)
Quilbeasts (4)
Quilboars, Razormane, Bristleback (6)
Revenants (9) (Including Sunken Ruins types)
Salamanders (5) (Including Draenei Variant)
Sasquatches (4)
Satyrs (5)
Skeletal Orcs (3)
Dark Minions (3)
Sludges (3) (Not including Dalaran Reject)
Stormreavers (4) (Not including Gul'Dan or Drak'thul)
Demonesses/Succubi (5)
Tinkers (2)
Sea and Dragon Turtles (6) (Including Naga Variant)
Tuskarr (7)
Unbroken (3)
Voidwalkers (4)
Watery Minions (3)
Wendigos (4)
Dragon Hawk
Frost and Timber Wolves (6)
Skeletal Archers (4)
Demons (RoC Pit Lord, Magtheridon, Kil'jaedens, Doom Guards/Balrogs, Infernal) (7)
Additional Units (over a hundred) (Including some Tavern Heroes)

This order hints at some things about the development of the game, some we know, and some we can't be sure about.

Also fun fact, the seashells enviromental doodad is the only non-destructible that is sorted in a different group than the others in the editor.
 

Attachments

  • 11 creeps 3.png
    11 creeps 3.png
    94.6 KB · Views: 5
  • 10 creeps 2.png
    10 creeps 2.png
    128.3 KB · Views: 5
  • 9 creeps 1.png
    9 creeps 1.png
    165.3 KB · Views: 5
  • 8 Zerg and Critters.png
    8 Zerg and Critters.png
    45.9 KB · Views: 5
  • 7 Undead.png
    7 Undead.png
    61.8 KB · Views: 5
  • 6 Orc.png
    6 Orc.png
    70.2 KB · Views: 5
  • 5 Creep Huts.png
    5 Creep Huts.png
    16.3 KB · Views: 5
  • 4 neutral buildings.png
    4 neutral buildings.png
    36.8 KB · Views: 6
  • 3 Human.png
    3 Human.png
    74.3 KB · Views: 6
  • 2 Night Elf.png
    2 Night Elf.png
    63.8 KB · Views: 6
  • 1 city buildings.png
    1 city buildings.png
    5.5 KB · Views: 5
  • 12 additional campaign units.png
    12 additional campaign units.png
    196.5 KB · Views: 6
A long while ago, I heard or learned from somewhere -- maybe a source online -- that you can customize the sort order groups you are referring to @Jeppe109 . They are not black magic.

If you edit the UnitMetaData.slk that defines which properties of units are modifiable from the Object Editor, you can add a modifiable property that changes the SLK column named "unitClass". This is the same thing I was alluding to in my previous post -- that MutableGameUnitComparator.java file is sorting units with readSLKTag("unitClass",...) as the code to determine this sort order. This "unitClass" field is responsible for the exact groups you are referring to, and if you bring it into the editor as a modifiable field you can see more about the groups and you can change the groups.

There is a similar field on Doodads called "doodClass". From what I can tell, the Seashells doodad you mentioned is the only doodad where "doodClass" was left completely empty (from a quick look at the table in Microsoft Excel). Other doodads that have no well defined class use a single underscore character as their doodad class, "_", which is apparently handled differently than an empty string.
 
Level 3
Joined
May 10, 2007
Messages
40
A long while ago, I heard or learned from somewhere -- maybe a source online -- that you can customize the sort order groups you are referring to @Jeppe109 . They are not black magic.

If you edit the UnitMetaData.slk that defines which properties of units are modifiable from the Object Editor, you can add a modifiable property that changes the SLK column named "unitClass". This is the same thing I was alluding to in my previous post -- that MutableGameUnitComparator.java file is sorting units with readSLKTag("unitClass",...) as the code to determine this sort order. This "unitClass" field is responsible for the exact groups you are referring to, and if you bring it into the editor as a modifiable field you can see more about the groups and you can change the groups.

There is a similar field on Doodads called "doodClass". From what I can tell, the Seashells doodad you mentioned is the only doodad where "doodClass" was left completely empty (from a quick look at the table in Microsoft Excel). Other doodads that have no well defined class use a single underscore character as their doodad class, "_", which is apparently handled differently than an empty string.
Of course they're not black magic. At worst, it could have been hardcoded into the program.
Thank you for being clear, it is good to have stuff like this properly documented.
 
Status
Not open for further replies.
Top