Skip to content

Instantly share code, notes, and snippets.

@seriallos
Last active January 19, 2026 22:30
Show Gist options
  • Select an option

  • Save seriallos/1b15ddda52ead945ab58e8140af5ca0a to your computer and use it in GitHub Desktop.

Select an option

Save seriallos/1b15ddda52ead945ab58e8140af5ca0a to your computer and use it in GitHub Desktop.
Midnight Item Level Bonuses

Item Levels in Midnight

Open Questions / Known Issues

  • This isn't final as of Jan 19th 2025 - this approach is based on testing on prepatch PTR and Midnight beta using my own characters or premades. I'll get a lot more feedback tomorrow when prepatch goes live on Raidbots and bug reports start showing up.
  • Timewalking items might be funky. Need to see some new items that drop once prepatch launches.
  • Some special items don't quite work (Heart of Azeroth is weird - seems to apply bonuses in a different order than expected)
  • Handling future eras is speculative but it seems to make sense
  • Not sure how to handle bonuses with squishEra of 0. Looks like if these bonuses are used, the era squish is skipped. But that seems extremely suspicious since it would cause weird issues in the future if my speculation about the system is correct.

Overview

Determining the item level of an item in Midnight using bonus IDs has significantly changed in Midnight in order to handle the item level squish.

I'll provide some info on what I've changed in the Raidbots bonuses.json and how I process bonus IDs using that data.

Strap in!

Core Concepts

The big concept is what Blizzard is calling an "item squish era" which buckets items into a pre-midnight or post-midnight timespan that can be scaled accordingly. It's my speculation that this concept can handle multiple eras so it's possible they will use this again in the future when item levels get too large again.

Each era defines a scaling curve to be used for items in the previous era. So if you have a pre-midnight item (era 1), you apply the Midnight (era 2) curve to the item level to scale it down. Midnight items do not need to have any curve applied since it's "baked into" the item level. Theoretically in the future there will be an era 3 at which point Midnight items would need to be scaled using that curve. It's likely that an era 1 item would need to be scaled using the era 2 curve and then the era 3 curve in sequence.

Most new item bonuses no longer use the base level from the Item data - instead, there will be a bonus ID that sets the base level and then potentially additional bonus IDs that offset that base level. Many of these bonus IDs include their item squish era which allows you to infer which era the item came from. Existing items from recent The War Within seasons will usually have a couple of era 1 bonus IDs that set their base level. Some older items will use the "legacy" bonus IDs that still require knowing the base level of the item.

Using Raidbots bonuses.json

I've updated the Raidbots bonuses.json to provide this data and am using it to determine/manipulate item levels on Raidbots.

Here are some of the new fields:

itemLevel properties set the base item level levelOffset properties apply an offset to the base level levelOffsetSecondary properties apply an additional level offset (for things like augment/matrix items from season turbo boost) dropLevelCurve properties are used for items that vary based on their drop level (the level the character was at when the item was acquired)

These fields have additional properties:

itemLevel: {
	amount: int, 	// the base level to set
	priority: int, 	// when multiple itemLevels are present, use the one with the lowest priority
	squishEra: int,	// the squish era for the bonus ID
	curveId: int, 	// an additional scaling curve to use on the level before other processing
}

levelOffset: {
	amount: int,			// the offset to apply
	squishEra: int,			// the squish era for the bonus ID
	craftingQuality: int,	// crafting quality of the item if crafted
}

levelOffsetSecondary: {
	amount: int,		// the offset to apply after era processing
}

dropLevelCurve: {
	curveId: int,		// the drop level lookup curve to use
	offset: int,		// level offset to apply
	priority: int,		// lowest priority wins in case of duplicates
	squishEra: int,		// squish era for the bonus ID
}

Here's some pseudo-code for how I process these to determine item level:

// set the base item level from equippable-items.json (which comes from ItemSparse DBC)
itemLevel = item.baseItemLevel
legacyLevelOffset = 0

operations = {} // collection of operations

foreach item.bonuses as bonus
	if bonus.itemLevel
		add a "set level" operation for era bonus.itemLevel.squishEra (or 0 if undefined)
	if bonus.levelOffset
		add a "level offset" operation for era bonus.levelOffset.squishEra (or 0 if undefined)
	if bonus.levelOffsetSecondary
		add a "level offset" operation for the current/max era
	if bonus.dropLevelCurve
		add a "drop level curve" operation for era bonus.dropLevelCurve.squishEra (or 0 if undefined)
	if bonus.level
		legacyLevelOffset += bonus.level

if operations.size > 0
	foreach itemSquishEras as itemSquishEra
		if itemSquishEra.curveId
			itemLevel = applyCurve(curveId, itemLevel)
		apply the lowest priority "set level" operation for this era
		apply the lowest priority "drop level curve" operation for this era using the item's drop level
		apply all level offset operations for this era
else
	// very old item that only uses older bonus IDs
	itemLevel += legacyLevelOffset

To fully process bonus IDs, you'll probably need to use these additional JSON files

equippable-items.json to get the base item level for legacy items item-curves.json to scale a value using a curve item-squish-era.json for the list of era and the curves used for scaling

Examples

Here are some example items and a log of what my current code is doing

War Within Season 3 raid/M+ item

Rune-Branded Armbands, level 112
neck=,id=237963,bonus_id=12291/6652/9881/10255/10879/10396

'Item 237963 DBC base level 246',
'Bonus 12291: Found base item level 684, priority 9999, era 1',
'Bonus 9881: LEGACY increase ilevel by 438',
'Era 1: set item level 684 (prev 246)',
'Era 2: apply era curve 92181 level 684 -> 124'

War Within Crafted item

Ring of Earthen Craftsmanship (160)
finger2=,id=215135,bonus_id=10421/9633/8902/10879/10396/9627/12050/10520/8960/8793/12053,crafted_stats=32/49,crafting_quality=5

'Item 215135 DBC base level 610',
'Bonus 10421: Found base item level 593, priority 100, era 1',
'Bonus 9627: Found item level offset 13, era 2',
'Bonus 12050: Found base item level 678, priority 70, era 1',
'Bonus 12053: Found base item level 707, priority 65, era 1',
'Era 1: set item level 707 (prev 610)',
'Era 2: apply era curve 92181 level 707 -> 147',
'Era 2: apply level offset 13, 147 -> 160'

Vanilla item, no bonus IDs

Weather-Beaten Fishing Hat (5)
head=,id=33820

'Item 33820 DBC base level 5',
'Era 2: apply era curve 92181 level 5 -> 5'

Midnight World Drop Item with Quality Upgrade

# Sash of Herbicide (126)
waist=,id=248039,bonus_id=13573/13613/13615/6652,drop_level=80

'Item 248039 DBC base level 415',
'Bonus 13573: Found item drop level curve 92772, offset 0, priority 300, era 2',
'Bonus 13613: Found item drop level curve 92772, offset 6, priority 200, era 2',
'Era 2: apply era curve 92181 level 415 -> 73',
'Era 2: apply drop level curve 92772, 120 + 6 -> 126'

Midnight Crafted

Arcanoweave Cord (275)
waist=,id=239664,bonus_id=12214/8960/12494/12066/13622/12667,crafted_stats=40/36,crafting_quality=2

'Item 239664 DBC base level 577',
'Bonus 12214: Found base item level 246, priority 100, era 2',
'Bonus 12494: Found item level offset 3, era 2',
'Bonus 12066: Found base item level 246, priority 70, era 2',
'Bonus 13622: Found base item level 272, priority 65, era 2',
'Era 2: set item level 272 (prev 577)',
'Era 2: apply level offset 3, 272 -> 275'

Underlying DBC Data

For folks dealing with the DBCs directly, here are some rawer notes on what I've found in ItemBonus

ItemBonus::Type 48 (SetLegacyItemLevel)

Value[0]	curveId		Curve::Id (unused?)
Value[1]	itemLevel
Value[2]	eraId 		ItemSquishEra::Id

Directly set the item level. Probably runs the item level through curve but the only examples I've seen use curve that doesn't change the item level

ItemBonus::Type 49 (SetItemLevel)

Value[0]	scalingId	ItemScalingConfig::Id
Value[1]	priority

Changes behavior based on ItemScalingConfig::flags. Applies during the eraId phase. Lowest priority in the same phase is applied.

0x0 - Directly set the item level using the ItemScalingConfig making sure to apply the curve and offset from ItemOffsetCurve
0x1 - ?? Unknown - has been seen on timewalking gear. Might indicate skipping the era squish altogether?
0x2	- Scale the item level based on the item's drop level using the ItemOffsetCurve from the ItemScalingConfig

ItemBonus::Type 51 (SetItemLevelDropLevel)

Value[0]	scalingId	ItemScalingConfig::Id
Value[1]	priority

Set the item level based on the item's drop level and the ItemOffsetCurve from the ItemScalingConfig. Lowest priority for the era is used.

ItemBonus::Type 52 (ItemLevelOffset)

Value[0]	amount			
Value[1]	eraId				ItemSquishEra::Id
Value[2]	craftingQuality?
Value[3]	?

Applies an item level offset after applying any item levels or drop level curves for the era.

ItemBonus::Type 53 (AugmentItemLevelOffset)

Value[0]	amount
Value[1]	?priority?

Applies an item level offset without regard for item squish. Used for crafted item augments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment