@@ -17,14 +17,26 @@ amulet_grades = {'Slight', 'Minor', 'Major', 'Grand', 'Ultimate' }; -- what kind of amulet each rune grade translates to phial_kinds = { - lesser = {grade = 1; name = 'Lesser'; infusion = 'sorcery:powder_brass'}; - simple = {grade = 2; name = 'Simple'; infusion = 'sorcery:powder_silver'}; - great = {grade = 3; name = 'Great'; infusion = 'sorcery:powder_gold'}; - splendid = {grade = 4; name = 'Splendid'; infusion = 'sorcery:powder_electrum'}; - exalted = {grade = 5; name = 'Exalted'; infusion = 'sorcery:powder_levitanium'}; - supreme = {grade = 6; name = 'Supreme'; infusion = 'sorcery:essence_force'}; + lesser = {grade = 1, name = 'Lesser'; infusion = 'sorcery:powder_brass'; + dist = { Fragile = 1, Weak = 0.7, Ordinary = 0.1, Pristine = 0.05, Sublime = 0.01 }; + }; + simple = {grade = 2, name = 'Simple'; infusion = 'sorcery:powder_silver'; + dist = { Fragile = 1, Weak = 0.8, Ordinary = 0.2, Pristine = 0.07, Sublime = 0.015 }; + }; + great = {grade = 3, name = 'Great'; infusion = 'sorcery:powder_gold'; + dist = { Fragile = 1, Weak = 0.9, Ordinary = 0.5, Pristine = 0.1, Sublime = 0.05 }; + }; + splendid = {grade = 4, name = 'Splendid'; infusion = 'sorcery:powder_electrum'; + dist = { Fragile = 1, Weak = 0.95, Ordinary = 0.7, Pristine = 0.3, Sublime = 0.1 }; + }; + exalted = {grade = 5, name = 'Exalted'; infusion = 'sorcery:powder_iridium'; + dist = { Fragile = 0, Weak = 1, Ordinary = 0.9, Pristine = 0.5, Sublime = 0.25 }; + }; + supreme = {grade = 6, name = 'Supreme'; infusion = 'sorcery:powder_levitanium'; + dist = { Fragile = 0, Weak = 0, Ordinary = 1, Pristine = 0.7, Sublime = 0.4 }; + }; }; } local calc_phial_props = function(phial) --> mine interval: float, time factor: float local g = phial:get_definition()._proto.data.grade @@ -56,9 +68,9 @@ local id = f('phial_%s', name); sorcery.register_potion_tbl { name = id; label = f('%s Phial',p.name); - desc = "A powerful liquid consumed in the operation of a rune forge. Its quality determines how fast new runes can be constructed and how much energy is required by the process."; + desc = "A powerful liquid consumed in the operation of a rune forge. Its quality determines how fast new runes can be constructed and how much energy is required by the process, and affects your odds of getting a high-quality rune."; color = color:brighten(1 + fac*0.5); imgvariant = (fac >= 5) and 'sparkle' or 'dull'; glow = 5+p.grade; extra = { @@ -199,9 +211,9 @@ local m = stack:get_meta() local proto = stack:get_definition()._sorcery.amulet if not m:contains('amulet_rune') then return nil end local rune = m:get_string('amulet_rune') - local rg = m:get_string('amulet_rune_grade') + local rg = m:get_int('amulet_rune_grade') local rd = sorcery.data.runes[rune] local spell = rd.amulets[proto.base] if not spell then return nil end local title,desc,cast,apply,remove,mingrade = spell.name, spell.desc, spell.cast, spell.apply, spell.remove, spell.mingrade -- FIXME in serious need of refactoring @@ -208,15 +220,17 @@ local base_spell = true if proto.frame and spell.frame and spell.frame[proto.frame] then local sp = spell.frame[proto.frame] - title = sp.name or title - desc = sp.desc or desc - cast = sp.desc or cast - apply = sp.apply or apply - remove = sp.remove or remove - mingrade = sp.mingrade or remove - base_spell = false + if not sp.mingrade or rg >= sp.mingrade then + title = sp.name or title + desc = sp.desc or desc + cast = sp.desc or cast + apply = sp.apply or apply + remove = sp.remove or remove + mingrade = sp.mingrade or mingrade + base_spell = false + end end return { rune = rune, grade = rg; @@ -240,9 +254,10 @@ local pow_max = l.self.powerdraw >= l.self.maxpower local has_phial = function() return not i:is_empty('phial') end if time and has_phial() and pow_min and not probe.disjunction then -- roll for runes - local int, powerfac = calc_phial_props(i:get_stack('phial',1)) + local phial = i:get_stack('phial',1) + local int, powerfac = calc_phial_props(phial) local rolls = math.floor(time/int) local newrunes = {} for _=1,rolls do local choices = {} @@ -270,16 +285,25 @@ end for _,r in pairs(newrunes) do if i:room_for_item('cache',r) and has_phial() then - local qual = math.random(#constants.rune_grades) + local qual + -- iterate through qualities from highest to lowest, rolling against the phial's + -- distribution for each, and stopping when we find one + local qdist = phial:get_definition()._proto.data.dist + for i=#constants.rune_grades,1,-1 do + local chance = qdist[constants.rune_grades[i]] + if chance == 1 or math.random() <= chance then + qual = i + break + end + end rune_set(r,{grade = qual}) i:add_item('cache',r) -- consume a phial local ph = i:get_stack('phial',1) - local n = ph:get_name() ph:take_item(1) i:set_stack('phial',1,ph) - minetest.add_item(pos,i:add_item('refuse',ItemStack(sorcery.register.residue.db[n]))) + minetest.add_item(pos,i:add_item('refuse',ItemStack(sorcery.register.residue.db[ph:get_name()]))) else break end end end