Bannerlord mechanics

Value and price

Bannerlord v1.4.8 · checked 2026-11-10 · updated 2026-11-12

How a crafted weapon's tier score (tierf), tier, value and trade price follow from its per-usage stats and pieces, at full precision for game v1.4.8. The stats themselves are in Weapon stats; the example recipes in Weapon templates.

Tier and value are TaleWorlds.Core.DefaultItemValueModel; trade price is DefaultTradeItemPriceFactorModel with DefaultPartyTradeModel.GetTradePenaltyFactor and TownMarketData.GetPrice (see Game code). No official module (SandBox, StoryMode, NavalDLC, BirthAndDeath) replaces any of these models. BirthAndDeath's only DLL, TaleWorlds.CampaignSystem.ViewModelCollection.BirthAndDeath.dll, holds its submodule and campaign options and no game model. The snippet tables and worked examples are computed by the Python model in src/bannerlord/crafting/.

Game version

The formulas were recovered from v1.4.6 IL of TaleWorlds.Core.dll and TaleWorlds.CampaignSystem.dll and compared method by method against v1.4.8 IL (cmp.txt), 172 methods: 92 match in full, 20 match in part, none differ. CraftingStats.CalculateWeaponTier is one of the partial matches: the v1.4.6 listing covers 11 of its 63 v1.4.8 instructions, and those 11 match.

38 methods were compared by header only: the v1.4.6 record holds no IL for them, so only their metadata tokens were compared, and those are unchanged. They include all of DefaultItemValueModel, among them the tier and value methods CalculateTierMeleeWeapon, CalculateTierCraftedWeapon, CalculateValue, GetFactor and CalculateWeaponTier, plus BladeData.Deserialize and CraftingCampaignBehavior.OpenNewPart. 22 methods are not in the v1.4.8 dumps: 21 DefaultItems getters, which only resolve material items, and DataExporter.GetPrice, which is in the exporter mod's DLL.

The evidence for the header-only tier and value methods is the export comparison in Validation: available usages, tierf ±0.001, tier and exact value match 5050/5050 unscaled and 5382/5382 scaled, price matches all 627,602 unscaled and 1,204,812 scaled export rows, and the largest value error is 0. The exports predate the current build (Weapon stats).

Tier

Per usage, from its integer stats:

t = 0.06 × v × (1 + weapon_length/100) − 3.5, clamped to [−1.5, 7.5]

v = max(thrust_damage × F(thrust type) × (thrust_speed/100)^1.5, 1.1 × swing_damage × F(swing type) × (speed_rating/100)^1.5) × class multiplier

The item's melee tier combines the usages:

  1. Keep the best and second-best t before clamping; both start at the lowest float, −3.4028234663852886 × 10³⁸. A t above the second best becomes the best if it is at least the best (the old best moves to second), else the second best.
  2. Clamp the best to [−1.5, 7.5]. With one usage, melee = best.
  3. With 2 or more usages, clamp the second best the same way, and melee = best × (1 + (second + 1.5) ÷ (best + 2.5))^0.2.

The pieces give the crafted tier:

crafted = 0.4 × (1.25 × average tier) + 0.6 × (1.3 × Σ(count × rank) ÷ (Σ count + 0.6) − 1.3)

tierf = 0.6 × melee + 0.4 × crafted

tier = clamp(round(tierf), 0, 6), rounded half to even.

Worked example, the one-handed sword recipe (wood_blade_1, vlandian_noble_guard_3, khuzait_grip_7, battania_pommel_6; see Weapon templates):

  1. Melee tier from its one usage: 0.8207.
  2. Piece tiers 1, 5, 2, 1: average 2.25, so 1.25 × 2.25 = 2.8125.
  3. Iron: the guard needs Iron5 ×1, the handle Iron2 ×1; blade and pommel need Wood. 1.3 × (5 + 2) ÷ (2 + 0.6) − 1.3 = 2.2.
  4. crafted = 0.4 × 2.8125 + 0.6 × 2.2 = 2.445.
  5. tierf = 0.6 × 0.8207 + 0.4 × 2.445 = 1.4704; tier 1.

Value

value = trunc(100 × 2.75^clamp(tierf, −1, 7.5) × (1 + 0.2 × (appearance − 1)) + 100 × max(0, appearance − 1))

Worked example, the one-handed sword: battania_pommel_6 has appearance 0.5, so 100 × 2.75^1.4704 × (1 + 0.2 × (0.5 − 1)) + 0 = 398.3, truncated to 398.

The 12 example recipes:

Tier score, value and price of the example weapons. Price is the sell price with Trade 86 and no market data.

Weapon Tier score from the stats Tier score from the pieces Tier score Rounded tier Appearance Value Price
One-handed sword 0.8207 2.445 1.4704 1 0.5 398 130
Two-handed sword 5.0111 3.4752 4.3967 4 0.5 7,688 2,012
Dagger -1.4511 2.3352 0.0634 0 0.5 95 32
Throwing knife 1.7095 1.9057 1.7880 2 0.5 549 175
One-handed axe 3.0244 2.6594 2.8784 3 0.5 1,655 484
Two-handed axe 5.8434 2.9867 4.7007 5 0.5 10,457 2,680
Throwing axe 2.9743 3.7635 3.2900 3 0.5 2,509 711
Two-handed polearm 1.2508 2.8093 1.8742 2 0.5 599 190
Pike 2.5033 2.87 2.6500 3 0.5 1,313 391
Javelin 3.0154 2.045 2.6272 3 0.5 1,283 383
Mace 4.926 4.5079 4.7587 5 0.5 11,089 2,831
Two-handed mace 5.6847 3.5997 4.8507 5 0.5 12,170 3,088
Rule Number
Swing damage counts this much more than thrust damage 1.1
Pierce damage counts 1.15
Blunt damage counts 1.45
Two-handed-only usages count 0.8
Throwing knives and throwing axes count 1.2
Javelins count 0.6
Usage score to tier score: times 0.06
Usage score to tier score: minus 3.5
Share of the tier score from the stats 0.6
Share of the tier score from the pieces 0.4
Value at tier score 0 100
Value multiplier per tier score point 2.75
Value multiplier per appearance point away from 1 0.2
Value added per appearance point above 1 100

Scatter of the 12 example weapons, tier score on the x axis from 0 to 5, value on a log y axis from 100 to 30,000. Dagger 0.0634, 95; one-handed sword 1.4704, 398; throwing knife 1.7880, 549; two-handed polearm 1.8742, 599; javelin 2.6272, 1,283; pike 2.6500, 1,313; one-handed axe 2.8784, 1,655; throwing axe 3.2900, 2,509; two-handed sword 4.3967, 7,688; two-handed axe 4.7007, 10,457; mace 4.7587, 11,089; two-handed mace 4.8507, 12,170.

Trade price

TaleWorlds.CampaignSystem.GameComponents.DefaultTradeItemPriceFactorModel.GetPrice. The formulas below cover crafted weapons; other item types add category and horse branches to the same model.

item_value = value, or round(value × price_factor) with an item_modifiers.xml modifier.

sell price = max(1, floor(item_value × base ÷ (1 + penalty)))

buy price = max(1, ceil(item_value × base × (1 + penalty))); buying from a caravan with Silver Tongue: ceil(price × 0.85).

base = clamp((demand ÷ (0.1 × supply + 0.04 × in_store_value + 2))^0.6, 0.8, 1.3); when selling, in_store_value += value first.

Town.GetItemPrice and Village.GetItemPrice read that market data and pass no merchant, so Merchant.Absent applies and the at-war, village, caravan and same-faction terms below stay off; a village uses its trade-bound town's market. Those terms apply only to TownMarketData.GetPrice callers that pass a merchant party. Trade goods clamp base to 0.1..10 instead, and animals use exponent 0.3.

penalty is built in this order:

  1. p = 0.06.
  2. p += 0.5 when at war with the merchant's faction (only with a client party).
  3. When selling, unless the client is a caravan: p += (1.5 + 0.25 × max(0, tierf − 1)) × A; A = 0.5 with Artisan Smith on a player-crafted weapon, else 1.
  4. Merchant in a village: p += 1 when selling, 0.1 when buying.
  5. Merchant is a caravan: p += 1 when selling, 0.1 when buying.
  6. With no client party: penalty = p × 0.2, and the steps below are skipped.
  7. Caravan client: p ×= 0.5.
  8. p ×= 1 ÷ (1 + 0.002 × Trade), Trade being the Trade skill of the client's party leader.
  9. penalty = p × (1 + Σ factors).
Factor Value Condition
Appraiser −0.15 selling
Arms Dealer −0.2 selling
Aserai culture feat −0.1 party has the feat
Village Network −0.1 merchant's village is in the party's faction
Rumor Network −0.05 merchant's town is in the party's faction
Distributed Goods −0.15 buying from a village
Smuggler Connections −0.5 main party, hero has the perk, crime rating with the merchant's faction above 0

Exporter quote

price in craftable_items*.csv is a sell quote with no market: the exporter passes isSelling=true, no merchant, and in_store_value = supply = demand = 0. Demand 0 makes base clamp to 0.8 for every weapon, so with no perks:

price = floor(value × 0.8 ÷ (1 + (1.56 + 0.25 × max(0, tierf − 1)) ÷ (1 + 0.002 × Trade)))

The exports fit only Trade = 86, so they reflect the export save's party leader. That skill is inferred from the prices.

Worked example, the one-handed sword (value 398, tierf 1.4704) at Trade 86: penalty = (0.06 + 1.5 + 0.25 × 0.4704) ÷ (1 + 0.002 × 86) = 1.4314, so price = floor(398 × 0.8 ÷ (1 + 1.4314)) = 130.

Sell price of the one-handed sword example (value 398, tier score 1.4704) with no market data, so the market factor is 0.8.

Trade skill Price penalty Price
0 1.6776 118
50 1.5251 126
86 1.4314 130
100 1.398 132
150 1.2905 139
200 1.1983 144
300 1.0485 155
Price input Number
Base penalty 0.06
Extra penalty when selling 1.5
Extra selling penalty per tier score point above 1 0.25
Penalty is divided by 1 plus this per Trade skill point 0.002
Market factor, lowest 0.8
Market factor, highest 1.3

Quirks

Validation

Compared with the game-generated exports described in Weapon stats, on the same sample:

Item check Unscaled Scaled
Available usages 5050/5050 5382/5382
tierf ±0.001 5050/5050 5382/5382
tier 5050/5050 5382/5382
value exact 5050/5050 5382/5382
price, every export row, value and tierf from the export 627,602/627,602 1,204,812/1,204,812
price, sampled items, computed from XML 5,050/5,050 5,382/5,382

Largest value error: 0 unscaled, 0 scaled.

price rows matching each Trade skill, of 1,832,414: 84: 200,231, 85: 469,823, 86: 1,832,414, 87: 459,223, 88: 238,939.

Trade price with a market, merchant or perks is not validated: exports only exercise a no-market sell quote with no perks.

Game code

Formula Method
Tier, value TaleWorlds.Core.DefaultItemValueModel
Trade price GameComponents.DefaultTradeItemPriceFactorModel, DefaultPartyTradeModel.GetTradePenaltyFactor, TownMarketData.GetPrice
Perk values CharacterDevelopment.DefaultPerks.InitializeAll

IL decoded from game v1.4.8:

Changelog