I won't lie, the way I make the mod table is kind of messy, but it's really just 3 steps, and I'll have comments of what's happening and why.
First let's look at the structure at a base mod (subject to change) before showing how to extract higher tiers from it:
'addedWeaponPhysicalDamage1': {
type: 'addedPhysFlat',
weights: [
{ name: 'weapon_physical', weight: 1000, max_tier: N },
{ name: 'ring', weight: 250, max_tier: N-4 }
],
stats: [
{
name: 'minimum_weapon_physical_damage',
type: 'flat',
min: 5,
max: 7
},
{
name: 'maximum_weapon_physical_damage',
type: 'flat',
min: 10,
max: 14
},
],
required_level: 1,
breakpoint_index: 0
},And now the code to create higher tier modifiers:
const allMods: BaseMods = {};
for(let key in baseMods){
let val = baseMods[key];
allMods[key] = val; //all mods includes the first mod
let curLevel = val.required_level;
let weightMultiplier = 1.2; //these multipliers are subject to change
let statMultiplier = 1.5;
let tempKey = key;
//create a mod for each level breakpoint
//these are arbitrary and subject to change
//right now im using [1,5,12,20,29,39,50,62]
for(let i = val.breakpoint_index+1; i < levelBreakpoints.length; i++){
curLevel = levelBreakpoints[i];
//create the next tier of weights
let newWeights = val.weights.map((w) => ({
...w,
weight: Math.floor(w.weight / weightMultiplier)
}));
//same thing but with stats
let newStats = val.stats.map((stat) => ({
...stat,
min: Math.floor(stat.min * statMultiplier),
max: Math.floor(stat.max * statMultiplier)
}));
//increase the key name e.g addedPhys1 becomes addedPhys2
let suffix = Number(tempKey.slice(tempKey.length-1)) + 1;
let prefix = tempKey.slice(0, tempKey.length-1);
let newKey = prefix + suffix;
tempKey = newKey;
//add the new mod and increase the multipliers
allMods[newKey] = {
...val,
weights: newWeights,
stats: newStats,
required_level: curLevel,
breakpoint_index: i
}
weightMultiplier += .3;
statMultiplier += 1.1;
}
}
For this step we'll create a map with the keys as all the item tag names and values as sets of item_classes associated with that tag. We're making this to use it in the final step. First let's look at an item for context:
{
name: "Twig",
item_class: 'wand',
weight: 800,
tags: ['wand', 'weapon', 'weapon_1h', '1h', 'weapon_magic'],
drop_level: levelBreakpoints[0],
implicits: [
{
name: 'spell_damage',
type: 'increased',
min: 10,
max: 20
},
]
},As you can see, there's an item_class and tags associated with this specific item. Now let's build the tag table:
const tagTable: TagTable = {};
for(let item of items){
for(let tag of item.tags){
if(tagTable[tag] === undefined){
tagTable[tag] = new Set();
}
tagTable[tag].add(item.item_class);
}
}The final step is to build the mod table, which we will use to roll the mods on items. Let's look at the code:
const itemModMap: ItemModMap = {};
//loop through the allMods map we made in step 1
for(let key in allMods){
let val = allMods[key];
//loop through the weights of the mod
//the weight.name will be a tag
for(let weight of val.weights){
let tag = weight.name;
//ignore this, i dont think its necessary i just got lazy
if(tagTable[tag] === undefined){
tagTable[tag] = new Set();
}
//some items don't get all the tiers of the mod
if(val.breakpoint_index > weight.max_tier) continue;
//loop through the item_classes of that tag
for(let item_class of tagTable[tag]){
if(itemModMap[item_class] === undefined){
itemModMap[item_class] = [];
}
itemModMap[item_class].push({
name: key,
type: val.type,
weight: weight.weight,
stats: val.stats,
required_level: val.required_level,
tier: val.breakpoint_index
});
}
}
}Now we have map with the item_class as a key and all the mods for that class as a value. This allows us to easily look up all the mods of a given item class. Ok, that's all for this one. Bye.