Index: altar.lua ================================================================== --- altar.lua +++ altar.lua @@ -62,11 +62,11 @@ end for _, g in ipairs(bad) do god.gifts[g] = nil end end end) -local std_god_interval = 70 +local std_god_interval = 40 for name, god in pairs(sorcery.data.gods) do local hitbox = { 0-(god.idol.width / 2.0), 0-(god.idol.height / 2.0), -0.15, god.idol.width / 2.0, god.idol.height / 2.0, 0.15 @@ -78,10 +78,34 @@ output = 'sorcery:idol_' .. name; recipe = god.idol.craft; }; end local god_interval = std_god_interval * (god.freq or 1) + local add_sparkles = function(pos,divine_favor) + divine_favor = divine_favor or minetest.get_meta(pos):get_int('favor') + if divine_favor > 5 then + local ct = divine_favor / 5 + minetest.add_particlespawner { + texture = L.image('sorcery_glitter.png'):glow(L.color(god.color)):render(); + glow = 14; + amount = ct / (1 / god_interval), time = god_interval; + minpos = pos:offset(-0.4, -0.5, -0.4); + maxpos = pos:offset( 0.4,god.idol.height-0.5,0.4); + minvel = vector.new(0, 0.05, 0); + minvel = vector.new(0, 0.1, 0); + minacc = vector.new(0, 0.1, 0); + maxacc = vector.new(0, 0.2, 0); + minexptime = 4, maxexptime = 4; + minsize = 0.3, maxsize = 1; + animation = { + type = 'vertical_frames'; + length = 0.1; + aspect_w = 16, aspect_h = 16; + } + } + end + end sorcery.lib.node.reg_autopreserve('sorcery:idol_' .. name, { description = god.idol.desc; drawtype = "mesh"; mesh = 'sorcery-idol-' .. name .. '.obj'; paramtype = 'light'; @@ -89,14 +113,19 @@ sunlight_propagates = true; stack_max = 1; tiles = god.idol.tex; selection_box = { type = "fixed"; fixed = {hitbox}; }; collision_box = { type = "fixed"; fixed = {hitbox}; }; - groups = { cracky = 2, sorcery_idol = 1, heavy = 1, sorcery_worship = 1}; + groups = { cracky = 2, sorcery_idol = 1, heavy = 1, sorcery_worship = 1, sorcery_instantiate = 1}; + _sorcery = { + idol_god = name; + on_load = function(pos) add_sparkles(pos) end; + }; on_construct = function(pos) minetest.get_node_timer(pos):start(god_interval) + add_sparkles(pos) end; on_timer = function(pos, elapsed) local altar = minetest.find_node_near(pos, 3, "sorcery:altar") -- TODO even without an altar, an idol with high favor could still be the source of miracles @@ -105,31 +134,11 @@ local altarmeta = minetest.get_meta(altar) local inv = altarmeta:get_inventory() local idolmeta = minetest.get_meta(pos) local divine_favor = idolmeta:get_int('favor') - if divine_favor > 5 then - local ct = divine_favor / 5 - minetest.add_particlespawner { - texture = L.image('sorcery_glitter.png'):glow(L.color(god.color)):render(); - glow = 14; - amount = ct / (1 / god_interval), time = god_interval; - minpos = pos:offset(-0.4, -0.5, -0.4); - maxpos = pos:offset( 0.4,god.idol.height-0.5,0.4); - minvel = vector.new(0, 0.05, 0); - minvel = vector.new(0, 0.1, 0); - minacc = vector.new(0, 0.1, 0); - maxacc = vector.new(0, 0.2, 0); - minexptime = 4, maxexptime = 4; - minsize = 0.3, maxsize = 1; - animation = { - type = 'vertical_frames'; - length = 0.1; - aspect_w = 16, aspect_h = 16; - } - } - end + add_sparkles(pos,divine_favor) local bestow = function(item,color) if type(item) == 'string' then item = ItemStack(item) end if color == nil then @@ -195,11 +204,11 @@ local gift = sorcery.lib.tbl.pick(god.gifts) local data = god.gifts[gift] local value, rarity = data[1], data[2] if value <= divine_favor and math.random(rarity) == 1 then bestow(gift) - log.act(god.name .. ' has produced ' .. gift .. ' upon an altar as a gift') + log.act(god.name,'has produced',gift,'upon an altar as a gift') if math.random(god.generosity) == 1 then -- unappreciated gifts may incur divine -- irritation divine_favor = divine_favor - 1 end @@ -233,11 +242,12 @@ end bestow(nil) end divine_favor = divine_favor + value - print(god.name.." has accepted a sacrifice of "..s..", raising divine favor by "..value.." points to "..divine_favor) + log.actf("%s has accepted a sacrifice of %s, raising divine favor by %u points to %u at altar %s", god.name, s, value, divine_favor, minetest.pos_to_string(pos)) + idolmeta:set_string('last_sacrifice', s) goto refresh end end Index: data/gods.lua ================================================================== --- data/gods.lua +++ data/gods.lua @@ -32,97 +32,109 @@ }; bless = { potions = {}; tools = {}; }; - gifts = {}; + gifts = { + ['sorcery:screw_steel'] = {7,1}; + ['sorcery:pipe'] = {16,2}; + ['sorcery:valve'] = {18,3}; + ['sorcery:fragment_vidrium'] = {20,4}; + ['sorcery:fragment_lithium'] = {23,5}; + ['sorcery:screw_platinum'] = {31,5}; + ['sorcery:screw_tungsten'] = {33,5}; + ['sorcery:powder_firestorm'] = {48,7}; + }; consecrate = { ["sorcery:dagger"] = {17, "sorcery:dagger_consecrated"}; ["sorcery:oil_mystic"] = {9, "sorcery:oil_purifying"}; ["sorcery:potion_water"] = {4, "sorcery:holy_water"}; ["default:paper"] = function(ctx) local stack = ItemStack('sorcery:recipe') - local mode = select(2,L.tbl.pick{'cook','craft','infuse','grind','enchant'}) + local mode = select(2,L.tbl.pick{'cook','craft','grind','enchant'}) sorcery.cookbook.setrecipe(stack, mode, nil, { pred = function(c) local me = ctx.god + local g = function(n) + return minetest.get_item_group(c.item, n) ~= 0 + end if (mode == 'enchant' or - minetest.get_item_group(c.item, 'sorcery_magical') ~= 0 or - minetest.get_item_group(c.item, 'sorcery_magitech') ~= 0 or - minetest.get_item_group(c.item, 'sorcery_ley_device') ~= 0 or - minetest.get_item_group(c.item, 'sorcery_tech') ~= 0 or - minetest.get_item_group(c.item, 'crafttool') ~= 0 or - me.sacrifice [c.item] or - me.consecrate[c.item]) and - mod ~= 'farming' + (ctx.favor > 35 and (g 'sorcery_magical' + or g 'sorcery_magitech' + or g 'sorcery_ley_device')) + or g 'sorcery_tech' + or g 'crafttool' + or me.sacrifice [c.item] + or me.consecrate[c.item]) + and mod ~= 'farming' then return true end end; }) - return 6, stack + return 3, stack end; -- ["default:gold_ingot"] = {15, "sorcery:holy_token_magic"}; }; sacrifice = { - ['sorcery:essence_frost'] = 25; - ['sorcery:essence_flame'] = 25; - ['sorcery:essence_force'] = 30; + ['sorcery:essence_frost'] = 15; + ['sorcery:essence_flame'] = 15; + ['sorcery:essence_force'] = 20; - ['sorcery:gem_luxite'] = 6; - ['sorcery:gem_ruby'] = 10; - ['sorcery:gem_amethyst'] = 16; - ['sorcery:gem_sapphire'] = 25; - ['sorcery:gem_emerald'] = 34; - ['default:mese_crystal'] = 42; - ['default:diamond'] = 50; + ['sorcery:gem_luxite'] = 4; + ['sorcery:gem_ruby'] = 7; + ['sorcery:gem_amethyst'] = 9; + ['sorcery:gem_sapphire'] = 12; + ['sorcery:gem_emerald'] = 14; + ['default:mese_crystal'] = 18; + ['default:diamond'] = 25; - ['sorcery:gem_luxite_amulet'] = 20; - ['sorcery:gem_ruby_amulet'] = 35; - ['sorcery:gem_amethyst_amulet'] = 48; - ['sorcery:gem_sapphire_amulet'] = 56; - ['sorcery:gem_emerald_amulet'] = 63; - ['sorcery:gem_mese_amulet'] = 78; - ['sorcery:gem_diamond_amulet'] = 91; + ['sorcery:gem_luxite_amulet'] = 8; + ['sorcery:gem_ruby_amulet'] = 14; + ['sorcery:gem_amethyst_amulet'] = 18; + ['sorcery:gem_sapphire_amulet'] = 23; + ['sorcery:gem_emerald_amulet'] = 14; + ['sorcery:gem_mese_amulet'] = 36; + ['sorcery:gem_diamond_amulet'] = 50; ['sorcery:oil_mystic'] = 2; - ['sorcery:oil_berry'] = 4; - ['sorcery:oil_wind'] = 6; - ['sorcery:oil_bleak'] = 6; - ['sorcery:oil_stone'] = 7; - ['sorcery:oil_mushroom'] = 8; - ['sorcery:oil_flame'] = 8; - ['sorcery:oil_dawn'] = 11; - ['sorcery:oil_luscious'] = 12; - ['sorcery:oil_luck'] = 16; + ['sorcery:oil_berry'] = 3; + ['sorcery:oil_wind'] = 4; + ['sorcery:oil_bleak'] = 4; + ['sorcery:oil_stone'] = 5; + ['sorcery:oil_mushroom'] = 6; + ['sorcery:oil_flame'] = 7; + ['sorcery:oil_dawn'] = 8; + ['sorcery:oil_luscious'] = 9; + ['sorcery:oil_luck'] = 11; ['sorcery:oil_sagnuine'] = -15; - ['sorcery:grease_fog'] = 17; - ['sorcery:grease_pine'] = 18; - ['sorcery:grease_storm'] = 20; - ['sorcery:grease_whisper'] = 21; - ['sorcery:grease_thunder'] = 22; - ['sorcery:grease_enchanting'] = 24; - ['sorcery:grease_lift'] = 32; + ['sorcery:grease_fog'] = 15; + ['sorcery:grease_pine'] = 16; + ['sorcery:grease_storm'] = 18; + ['sorcery:grease_whisper'] = 19; + ['sorcery:grease_thunder'] = 20; + ['sorcery:grease_enchanting'] = 22; + ['sorcery:grease_lift'] = 28; ['sorcery:grease_war'] = -5; - ['sorcery:warding_plate'] = 6; + ['sorcery:warding_plate'] = 5; ['sorcery:ley_puncture'] = 8; ['sorcery:pulse_rectifier'] = 8; ['sorcery:current_felicitator'] = 12; - ['sorcery:infuser_concentrator'] = 15; - ['sorcery:infuser_tube'] = 23; - ['sorcery:inverter_coil'] = 31; - ['sorcery:inversion_matrix'] = 70; - ['sorcery:inferno_crystal'] = 75; - ['sorcery:beam_generator'] = 83; - ['sorcery:field_emitter'] = 92; - ['sorcery:catalytic_converter'] = 95; - ['sorcery:gravity_manipulator'] = 97; + ['sorcery:infuser_concentrator'] = 7; + ['sorcery:infuser_tube'] = 9; + ['sorcery:inverter_coil'] = 10; + ['sorcery:inversion_matrix'] = 22; + ['sorcery:inferno_crystal'] = 24; + ['sorcery:beam_generator'] = 27; + ['sorcery:field_emitter'] = 30; + ['sorcery:catalytic_converter'] = 30; + ['sorcery:gravity_manipulator'] = 50; - ['sorcery:core_syncretic'] = 64; - ['sorcery:core_mandatic'] = 53; - ['sorcery:core_praxic'] = 72; - ['sorcery:core_counterpraxic'] = 31; + ['sorcery:core_syncretic'] = 25; + ['sorcery:core_mandatic'] = 27; + ['sorcery:core_praxic'] = 29; + ['sorcery:core_counterpraxic'] = 17; ['sorcery:sap'] = 1; ['sorcery:sap_apple'] = 2; ['sorcery:sap_aspen'] = 3; ['sorcery:sap_pine'] = 3; ADDED global.lua Index: global.lua ================================================================== --- global.lua +++ global.lua @@ -0,0 +1,18 @@ +-- abuses the engine to provide additional generic features useful to multiple units +local log = sorcery.logger 'global' + +minetest.register_lbm { + name = 'sorcery:activate_nodes'; + label = 'trigger instantiation-time callbacks'; + nodenames = { 'group:sorcery_instantiate' }; + run_at_every_load = true; + action = function(pos,node) + local s = minetest.registered_nodes[node.name]._sorcery + if not s or not s.on_load then + log.errf('node type "%s" marked for instantiation-time callback, but no callback specified', node.name) + return + end + + s.on_load(pos,node) + end; +} Index: init.lua ================================================================== --- init.lua +++ init.lua @@ -165,11 +165,11 @@ sorcery.registry.mk('residue',false) end sorcery.stage('startup',data) for _,u in pairs { - 'vfx'; 'context'; 'attunement'; 'itemclass'; 'craft'; 'spell'; + 'global'; 'vfx'; 'context'; 'attunement'; 'itemclass'; 'craft'; 'spell'; 'liquid'; 'tree'; 'potions'; 'metal', 'gems'; 'leylines'; 'infuser'; 'altar'; 'wands'; 'tools', 'crafttools'; 'enchanter'; 'harvester'; 'metallurgy-hot', 'metallurgy-cold'; 'entities'; 'recipes'; 'coins'; 'interop'; 'tnodes'; 'forcefield'; 'farcaster'; 'portal'; Index: liquid.lua ================================================================== --- liquid.lua +++ liquid.lua @@ -134,10 +134,16 @@ top:render(); 'sorcery_trough_side.png'; 'sorcery_trough_bottom.png'; }; _sorcery = { + material = liq == nil and { + metal = true; + name = 'aluminum'; + data = sorcery.data.metals.aluminum; + value = 7*4; + } or nil; container = { type = 'bucket'; hold = 'liquid'; has = liq and liq.id; charge = liq and Q * i; Index: recipes.lua ================================================================== --- recipes.lua +++ recipes.lua @@ -302,18 +302,19 @@ sorcery_tech_component = 1; }; }) -local regtech = function(id, desc, groups, recipe, qty, replacements) +local regtech = function(id, desc, groups, recipe, qty, replacements, props) minetest.register_craftitem('sorcery:' .. id,{ description = desc; inventory_image = 'sorcery_'..id..'.png'; groups = sorcery.lib.tbl.merge({ sorcery_magitech = 1; sorcery_tech_component = 1; }, groups or {}); + _sorcery = props; }) if recipe then minetest.register_craft { output = string.format('sorcery:%s %u', id, qty or 1); recipe = recipe; @@ -324,10 +325,40 @@ local regcore = function(core,name) regtech('core_'..core, name .. ' Core', {sorcery_magitech_core = 1}) end +local mprop = function(metal, amt) + local gc, gv + amt = amt or 1 + if math.floor(amt) ~= amt then + if amt < 1 then + gc = math.floor(1 / amt) + else + local n = 0 + for i = 2,10 do + if math.floor(amt * i) == amt * i then + n = i + break + end + end + if n == 0 then error "can't determine metal value for item" end + gc = i + gv = amt * i + end + else + gc = 1 + gv = amt + end + return { material = { + metal = true; id = metal; + data = sorcery.data.metals[metal]; + grindcost = gc; + grindvalue = gv; + value = amt; + }} +end regtech('field_emitter', 'Field Emitter', {metal = 1}) regtech('leyline_stabilizer', 'Leyline Stabilizer', {metal = 1}) regtech('beam_generator', 'Beam Generator', {metal = 1}) regtech('inversion_matrix', 'Inversion Matrix', {metal = 1}) @@ -338,16 +369,16 @@ regtech('gravity_manipulator', 'Gravity Manipulator', {metal = 1}) regtech('valve','Valve', {metal = 1}, { {'','default:bronze_ingot',''}; {'basic_materials:plastic_sheet','basic_materials:steel_bar','basic_materials:plastic_sheet'}; {'','default:bronze_ingot',''}; -},3) +},3,nil, mprop('bronze',2*4,1,2*4)) regtech('pipe','Pipe', {metal = 1}, { {ingot('aluminum'),'',ingot('aluminum')}; {ingot('aluminum'),'',ingot('aluminum')}; {ingot('aluminum'),'',ingot('aluminum')}; -}, 6) +}, 6, nil, mprop('aluminum', 4)) minetest.register_craft { output = 'sorcery:trough'; recipe = { {ingot('aluminum'),'',ingot('aluminum')}; Index: wands.lua ================================================================== --- wands.lua +++ wands.lua @@ -225,18 +225,18 @@ for i=1,matprops.bond do local prop = 'bound_user_' .. tostring(i) if meta:contains(prop) then userct = i local name = meta:get_string(prop) - print('wand bound to',name,i) + -- print('wand bound to',name,i) if name == user:get_player_name() then found = true break end else break end end if not found then if userct < matprops.bond then - print('binding wand to caster') + -- print('binding wand to caster') minetest.sound_play("xdecor_enchanting", { --FIXME make own sounds pos = user:get_pos(); gain = 0.8; }) sorcery.vfx.cast_sparkle(user, sorcery.lib.color(25,129,255), 2)