Inappropriate material levels for randarts
Posted: Tue Feb 19, 2013 6:33 pm
Randarts generated for random bosses are often useless (particularly weapons) because the material level of the item has no bearing on the level of difficulty of the zone (or the boss). This is caused because the filter parameter "ingore_material_restriction=true" allows any material level to be used. I have fixed this in Infinite500 by updating the resolver for calculating randarts to take the level of the actor into account, ensuring that most randarts are of appropriate quality for the boss that drops them.
Changes to modules/tome/resolvers.lua (patch, includes a resolver for power level vs. zone base level): The corresponding I500 code showing the changes marked by I5 in comments:
Changes to modules/tome/resolvers.lua (patch, includes a resolver for power level vs. zone base level): The corresponding I500 code showing the changes marked by I5 in comments:
Code: Select all
--I5 Resolves material level based on actor level
-- @param base = base value at level = base_level (scales as sqrt)
-- @param spread = number of std deviations (1 usually) in material level
-- @param min, max = material level limits
function resolvers.matlevel(base, base_level, spread, mn, mx)
return {__resolver="matlevel", base, base_level, spread, mn, mx}
end
function resolvers.calc.matlevel(t, e)
local mean = math.min(e.level/10+1,t[1] * (e.level/t[2])^.5) -- I5 material level scales up with sqrt of actor level or level/10
local spread = math.max(t[3],mean/5) -- spread out probabilities at high level
local mn = t[4] or 1
local mx = t[5] or 5
local rand = math.floor(rng.normalFloat(mean,spread))
return util.bound(rand,mn,mx)
end
-- Estimate actor final level for drop calculations (.__resolve_last does not work)
function actor_final_level(e)
local finlevel = math.max(math.max(e.level,e.start_level),1)
if game.zone.actor_adjust_level and e.forceLevelup then
return math.max(finlevel, game.zone:actor_adjust_level(game.level, e) + e:getRankLevelAdjust())
else
return math.max(finlevel, game.zone.base_level + e:getRankLevelAdjust())
end
end
--- Resolves drops creation for an actor; drops a created on the fly randart
function resolvers.drop_randart(t)
return {__resolver="drop_randart", __resolve_last=true, t}
end
--- Actually resolve the drops creation for an actor
function resolvers.calc.drop_randart(t, e)
t = t[1]
local filter = t.filter
local matresolver = resolvers.matlevel(5,50,1,2) --I5 material level resolver, min material level 2
-- game.log("#LIGHT_BLUE#Calculating randart drop for %s (uid %d, est level %d)",e.name,e.uid,actor_final_level(e))
if not filter then
--I5 if not matlevel then --I5
--I5 filter = {ingore_material_restriction=true, no_tome_drops=true, ego_filter={keep_egos=true, ego_chance=-1000}, special=function(e) return (not e.unique and e.randart_able) and (not e.material_level or e.material_level >= 2) and true or false
-- end}
-- else-- I5 scale up randart material level with level of actor
filter = {ingore_material_restriction=true, no_tome_drops=true, ego_filter={keep_egos=true, ego_chance=-1000}, special=function(eq)
-- local afl = actor_final_level(e)
local matlevel = resolvers.calc.matlevel(matresolver,{level = actor_final_level(e)}) --I5
-- game.log("Checking equipment %s against material level %d for %s (final level %d)",eq.name,matlevel,e.name, actor_final_level(e))
return (not eq.unique and eq.randart_able) and eq.material_level == matlevel and true or false
end} --I5
-- end
end
-- print("Randart Drops resolver")
local base = nil
if filter then
if not filter.defined then
base = game.zone:makeEntity(game.level, "object", filter, nil, true)
else
base = game.zone:makeEntityByName(game.level, "object", filter.defined)
end
end
local o = game.state:generateRandart{base=base, lev=resolvers.current_level}
if o then
-- print("Zone made us a randart drop according to filter!", o:getName{force_id=true})
e:addObject(e.INVEN_INVEN, o)
game.zone:addEntity(game.level, o, "object")
if t.id then o:identify(t.id) end
end
-- Delete the origin field
return nil
end