Comment: | changes, merges, additions galore |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
82178e0a166ffc2a1e7237d685f25111 |
User & Date: | lexi on 2020-08-16 02:05:40 |
Other Links: | manifest | tags |
2020-08-17
| ||
13:35 | fix bugs, finish grinder, add conduits and condensers to extract and transmit energy from leylines check-in: 9278734b41 user: lexi tags: trunk | |
2020-08-16
| ||
02:05 | changes, merges, additions galore check-in: 82178e0a16 user: lexi tags: trunk | |
2020-08-14
| ||
06:17 | fix(color): Actually get hsl brightening working Reimplemented based on the algorithms in Computer Graphics: Principles and Practice. Only lightens based on luminosity right now, which makes beautifully saturated, but not pastel colors, so some tweaking might be recommended. Leaf check-in: 794d5b023a user: glowpelt tags: glowpelt/hsl | |
2020-08-11
| ||
21:39 | initial commit check-in: 956134c50b user: lexi tags: trunk | |
Modified altar.lua from [3de8edac81] to [1cf2c5fc2a].
120 120 x = range(-0.6, 0.6); 121 121 z = range(-0.6, 0.6); 122 122 y = range(-0.6, 0.6); 123 123 }; 124 124 acceleration = { 125 125 x = 0; y = range(0,1); z = 0; 126 126 }; 127 - texture = 'sorcery_sparkle.png' .. 128 - '^[transform' .. (math.random(8) - 1) .. 129 - '^[multiply:' .. color:brighten(1.7):hex(); 127 + texture = sorcery.lib.image('sorcery_sparkle.png'): 128 + transform(math.random(8) - 1): 129 + multiply(color:brighten(1.7)): 130 + render(); 130 131 glow = 14; 131 132 } 132 133 end 133 134 for i=0,48 do 134 135 minetest.add_particle{ 135 136 pos = { 136 137 x = altar.x + range(-0.3,0.3);
Modified coins.lua from [cdf0329a68] to [e5af87fe4c].
101 101 on_construct = function(pos) 102 102 local meta = minetest.get_meta(pos) 103 103 local inv = meta:get_inventory() 104 104 inv:set_size('ingot',1) 105 105 inv:set_size('gem',1) 106 106 inv:set_size('output',1) 107 107 meta:set_string('formspec', [[ 108 - formspec_version[3] real_coordinates[true] 109 108 size[8,6] 110 109 list[context;ingot;2,0.5;1,1;] 111 110 image[2,0.5;1,1;sorcery_ingot_outline.png] 112 111 list[context;gem;3,0.5;1,1;] 113 112 image[3,0.5;1,1;sorcery_diamond_outline.png] 114 113 list[context;output;5,0.5;1,1;] 115 114 list[current_player;main;0,2;8,4;]
Modified data/enchants.lua from [ac299c4e97] to [b3a388d8b4].
1 +-- an optional 'enchant' function can be defined, and will 2 +-- be called when the enchantment is placed on the object 3 +local allgroups = { 4 + 'sword'; 'pick'; 'pickaxe'; 5 + 'sickle'; 'scythe'; 'shovel'; 6 + 'hoe'; 'helmet'; 'leggings'; 7 + 'chestplate'; 'boots'; 8 +} 1 9 return { 2 10 endure = { -- withstand more blows 3 11 name = 'Endure'; 12 + cost = 1; 4 13 tone = {232,102,255}; 5 14 desc = 'durability magnified'; 6 15 affinity = 'counterpraxic'; 7 - apply = function(stack,power) 16 + groups = allgroups; 17 + recipe = { 18 + {lens = 'convex', gem = 'amethyst', dmg = 2}; 19 + {lens = 'rectifier', gem = 'emerald', dmg = 4}; 20 + {lens = 'convex', gem = 'emerald', dmg = 2}; 21 + }; 22 + apply = function(stack,power,base) 23 + local caps = table.copy(stack:get_definition().tool_capabilities) 24 + for g,v in pairs(caps.groupcaps) do 25 + local unit = base.groupcaps[g].uses * 0.6 26 + caps.groupcaps[g].uses = v.uses + unit*power 27 + end 28 + stack:get_meta():set_tool_capabilities(caps) 29 + return stack 8 30 end; 9 31 }; 10 - drain = {}; -- health vampirism 32 + drain = { 33 + groups = {'sword'}; 34 + cost = 4; 35 + }; -- health vampirism 11 36 harvest = { -- kills or digging ore replenish durability 12 37 name = 'Harvest'; 38 + cost = 0; -- energy is only depleted when repair takes place 13 39 tone = {255,84,187}; 14 40 affinity = 'syncretic'; 41 + groups = { 42 + 'pick'; 'pickaxe'; 'sword'; 43 + }; 44 + recipe = { 45 + {lens = 'amplifier', gem = 'ruby', dmg = 5}; 46 + {lens = 'concave', gem = 'mese', dmg = 1}; 47 + {lens = 'concave', gem = 'sapphire', dmg = 1}; 48 + }; 15 49 desc = 'some damage is repaired when used to mine ore or kill an attacker'; 16 - apply = function(stack,power) 50 + on_dig = function(ctx) 51 + local orepfx = "stone_with_" -- }:< 52 + -- local oredrop = ' lump' 53 + local dug = minetest.get_node(ctx.target.under) 54 + local barename = string.sub(dug.name, string.find(dug.name, ':') + 1) 55 + print('is ore? ',dug.name,barename) 56 + if minetest.get_item_group(dug.name, ore) ~= 0 or 57 + string.sub(barename,1,string.len(orepfx)) == orepfx 58 + then 59 + print('is ore!') 60 + ctx.tool:add_wear(-(sorcery.enchant.strength(ctx.tool,'harvest') * 2000)) 61 + ctx.cost = 3 62 + end 17 63 end; 18 64 }; 19 65 conserve = { -- use less magical energy 20 66 name = 'Conserve'; 21 67 tone = {84,255,144}; 68 + cost = 0; 22 69 desc = 'enchantments last longer before running out of power to sustain them.'; 70 + groups = allgroups; 23 71 affinity = 'syncretic'; 24 - apply = function(stack,power) 25 - end; 72 + recipe = { 73 + {lens = 'rectifier', gem = 'mese', dmg = 7}; 74 + {lens = 'rectifier', gem = 'sapphire', dmg = 2}; 75 + {lens = 'rectifier', gem = 'amethyst', dmg = 2}; 76 + }; 77 + -- implemented in sorcery/enchanter.lua:register_on_dig 26 78 }; 27 79 dowse = { -- send up flare when valuable ores are nearby 28 80 name = 'Dowse'; 29 81 tone = {241,251,113}; 82 + cost = 1; 30 83 desc = 'strike colored sparks when used to dig near valuable ore.'; 84 + groups = {'pick','pickaxe'}; 31 85 affinity = 'cognic'; 32 - apply = function(stack,power) 86 + recipe = { 87 + {lens = 'concave', gem = 'ruby', dmg = 3}; 88 + {lens = 'concave', gem = 'emerald', dmg = 3}; 89 + {lens = 'concave', gem = 'sapphire', dmg = 3}; 90 + }; 91 + on_dig = function(ctx) 92 + local range = 4*sorcery.enchant.strength(ctx.tool,'dowse') 93 + local colors = { 94 + ['default:stone_with_gold' ] = {255,234,182}; 95 + ['default:stone_with_mese' ] = {231,255,151}; 96 + ['default:stone_with_diamond' ] = {180,253,255}; 97 + ['sorcery:stone_with_iridium' ] = {243,180,255}; 98 + ['sorcery:stone_with_tungsten'] = {119,234,196}; 99 + } 100 + local search = {} for k in pairs(colors) 101 + do search[#search+1] = k end 102 + local nodes = minetest.find_nodes_in_area( 103 + vector.subtract(ctx.pos,range), 104 + vector.add(ctx.pos,range), search) 105 + for _,n in pairs(nodes) do 106 + -- we're going to use some ugly math tricks 107 + -- to avoid having to do a square root, since 108 + -- that's an expensive operation and we don't 109 + -- need that level of precision; we can 110 + -- approximate the distance without it 111 + local delta = vector.subtract(n,ctx.pos) 112 + local dstsq = (delta.x^2) + (delta.y^2) + (delta.z^2) 113 + if dstsq < range^2 then 114 + local dstfac = 1 - (dstsq / range^2) 115 + ctx.sparks[#ctx.sparks+1] = { 116 + color = sorcery.lib.color(colors[minetest.get_node(n).name]); 117 + count = 100 * dstfac; 118 + } 119 + end 120 + end 33 121 end; 34 122 }; 35 123 pierce = { -- faster mining speed 36 124 name = 'Pierce'; 125 + cost = 3; 37 126 tone = {113,240,251}; 38 - desc = 'rip through solid stone like a hot knife through butter'; 127 + groups = { 128 + 'pick';'pickaxe';'axe';'shovel';'sickle'; 129 + }; 130 + desc = 'rip through solid stone or wood like a hot knife through butter'; 131 + recipe = { 132 + {lens = 'amplifier', gem = 'diamond', dmg = 4}; 133 + {lens = 'amplifier', gem = 'ruby', dmg = 4}; 134 + {lens = 'rectifier', gem = 'diamond', dmg = 2}; 135 + }; 39 136 affinity = 'praxic'; 40 - apply = function(stack,power) 137 + apply = function(stack,power,base) 138 + local caps = table.copy(stack:get_definition().tool_capabilities) 139 + for g,v in pairs(caps.groupcaps) do 140 + for i,t in pairs(v.times) do 141 + local unit = base.groupcaps[g].times[i] * 0.15 142 + caps.groupcaps[g].times[i] = math.max(0.01, t - unit*power) 143 + end 144 + end 145 + stack:get_meta():set_tool_capabilities(caps) 146 + return stack 41 147 end; 42 148 }; 43 149 rend = { -- more damage / mine higher level blocks 44 150 name = 'Rend'; 45 151 affinity = 'praxic'; 46 152 tone = {251,203,113}; 153 + groups = {'sword';'pick';'pickaxe';}; 154 + recipe = { 155 + {lens = 'convex', gem = 'mese', dmg = 3}; 156 + {lens = 'amplifier', gem = 'emerald', dmg = 7}; 157 + {lens = 'amplifier', gem = 'diamond', dmg = 7}; 158 + }; 159 + cost = 5; 47 160 desc = 'cleave through sturdy ores and tear mortal flesh with fearsome ease'; 48 - apply = function(stack,power) 161 + apply = function(stack,power,base) 162 + local caps = table.copy(stack:get_definition().tool_capabilities) 163 + for g,v in pairs(caps.groupcaps) do 164 + local unit = 2 165 + caps.groupcaps[g].maxlevel = caps[g].maxlevel + math.floor(unit*power) 166 + end 167 + stack:get_meta():set_tool_capabilities(caps) 168 + return stack 49 169 end; 50 170 }; 51 171 }
Modified data/gems.lua from [608081f8a9] to [6638dda90c].
18 18 19 19 return { 20 20 diamond = { 21 21 foreign = 'default:diamond'; 22 22 tone = {137,240,255}; 23 23 items = default_items('diamond'); 24 24 tools = true, armor = true; 25 + maxenergy = 2000; 25 26 slots = { 26 27 {affinity = {'praxic','counterpraxic'}, confluence = 1}; 27 28 {affinity = {'praxic','syncretic'}, confluence = 0.6}; 28 29 {affinity = {'counterpraxic', 'entropic'}, confluence = 0.7}; 29 30 }; 30 31 }; 31 32 mese = { 32 33 foreign = 'default:mese_crystal'; 33 34 foreign_shard = 'default:mese_crystal_fragment'; 34 35 tone = {255,253,94}; 36 + energysource = 5; 37 + maxenergy = 600; 35 38 items = default_items('mese'); 36 39 tools = true, armor = true; 37 40 slots = { 38 41 {affinity = {'praxic'}, confluence = 1}; 39 42 {affinity = {'praxic'}, confluence = 0.5}; 40 43 {affinity = {'cognic'}, confluence = 1}; 41 44 {affinity = {'syncretic'}, confluence = 0.9};
Modified data/gods.lua from [e99e28f75f] to [ae9e7f6603].
26 26 "flowerpot:flowers_tulip"; 27 27 "flowerpot:flowers_viola"; 28 28 "flowerpot:flowers_geranium"; 29 29 "flowerpot:flowers_chrysanthemum_green"; 30 30 "flowerpot:flowers_dandelion_white"; 31 31 "flowerpot:flowers_dandelion_yellow"; 32 32 }}; 33 - ["sorcery:dagger"] = {4, "sorcery:dagger_consecrated"}; 33 + ["sorcery:dagger"] = {8, "sorcery:dagger_consecrated"}; 34 34 ["sorcery:oil_mystic"] = {6, "sorcery:oil_purifying"}; 35 35 ["sorcery:potion_water"] = {2, "sorcery:holy_water"}; 36 36 -- ["default:steel_ingot"] = {15, "sorcery:holy_token_harvest"}; 37 37 }; 38 38 sacrifice = { 39 39 -- beattitudes 40 40 ["farming:straw" ] = 1; ................................................................................ 88 88 ["default:dirt"] = -5; 89 89 ["moreblocks:tar"] = -9; 90 90 ["default:bucket_lava"] = -12; 91 91 ["sorcery:blood"] = -15; 92 92 ["default:bones"] = -35; 93 93 }; 94 94 gifts = { 95 - -- gift specs = {favor, chance} where favor is the likelihood of a god bestowing the gift 96 - ["default:blueberry_bush_sapling"] = {35,15}; 97 - ["farming:coffee_beans"] = {31, 9}; 98 - ["farming:rhubarb"] = {29, 8}; 99 - ["farming:corn"] = {27, 5}; 100 - ["farming:grapes"] = {26, 6}; 101 - ["farming:seed_hemp"] = {26, 8}; 102 - ["farming:raspberries"] = {25, 5}; 103 - ["flowers:mushroom_red"] = {25, 2}; 104 - ["farming:garlic_clove"] = {25, 7}; 105 - ["farming:seed_mint"] = {25, 7}; 106 - ["farming:seed_barley"] = {24, 6}; 107 - ["farming:beans"] = {24, 6}; 95 + -- gift specs = {favor, chance} where chance is the likelihood of a god bestowing the gift 96 + ["default:blueberry_bush_sapling"] = {120,15}; 97 + ["default:blueberries"] = {60, 4}; 98 + ["farming:coffee_beans"] = {58, 9}; 99 + ["farming:seed_hemp"] = {55, 8}; 100 + ["farming:garlic_clove"] = {50, 7}; 101 + ["farming:seed_mint"] = {50, 7}; 102 + ["flowers:mushroom_red"] = {45, 2}; 103 + ["farming:grapes"] = {43, 6}; 104 + ["farming:seed_barley"] = {40, 6}; 105 + ["farming:rhubarb"] = {38, 8}; 106 + ["farming:beans"] = {35, 6}; 107 + ["farming:raspberries"] = {30, 5}; 108 + ["farming:corn"] = {27, 2}; 109 + ["farming:sugar"] = {24, 4}; 110 + ["farming:salt"] = {24, 3}; 108 111 ["farming:onion"] = {20, 7}; 109 - ["farming:carrot"] = {19, 7}; 110 - ["farming:sugar"] = {17, 3}; 111 - ["farming:salt"] = {17, 3}; 112 - ["default:apple"] = {16, 2}; 113 - ["default:blueberries"] = {15, 4}; 112 + ["farming:carrot"] = {20, 7}; 113 + ["default:apple"] = {18, 2}; 114 114 ["farming:wheat"] = {14, 2}; 115 115 }; 116 116 }; 117 117 }
Modified data/metals.lua from [b325d7e9c3] to [f4099f1a65].
42 42 }; 43 43 bronze = { 44 44 ingot = 'default:bronze_ingot'; 45 45 block = 'default:bronzeblock'; 46 46 artificial = true; 47 47 tone = {229,115,52}; 48 48 items = default_items('bronze'); 49 + maxenergy = 150; 49 50 slots = { 50 - {affinity = {'counterpraxic'}; confluence = 0.7;}; 51 + {affinity = {'counterpraxic'}; confluence = 0.7}; 51 52 }; 52 53 mix = { 53 54 metals = { 54 55 copper = 4; 55 56 tin = 1; 56 57 }; 57 58 }; 58 59 }; 59 60 steel = { 60 61 ingot = 'default:steel_ingot'; 61 62 block = 'default:steelblock'; 62 63 tone = {240,240,240}; 63 64 items = default_items('steel'); 65 + maxenergy = 200; 64 66 slots = { 65 - {affinity = {'praxic'}; confluence = 0.5;}; 67 + {affinity = {'praxic'}; confluence = 0.5}; 66 68 }; 67 69 }; 68 70 aluminum = { 69 71 tone = {196,64,32}, alpha = 128; 70 72 meltpoint = 1; 71 73 rarity = 12; depth = 158; 72 74 power = 3; speed = 2.4; 73 75 durability = 700; cooktime = 25; 74 76 armor_weight = 0.3; 77 + maxenergy = 400; 75 78 slots = { 76 - {affinity = {'syncretic'}; confluence = 0.7;}; 77 - {affinity = {'praxic'}; confluence = 0.4;}; 79 + {affinity = {'syncretic'}; confluence = 0.7}; 80 + {affinity = {'praxic'}; confluence = 0.4}; 78 81 }; 79 82 }; 80 83 levitanium = { 81 84 tone = {17,255,191}, alpha = 40; 82 85 meltpoint = 4; 83 86 rarity = 17; depth = 870; 84 87 power = 1; durability = 50; cooktime = 70; 85 88 armor_weight = -2.2; armor_protection = 1; 89 + maxenergy = 5000; 86 90 no_tools = true; 87 91 }; 88 92 platinum = { 89 93 tone = {255,233,118}, alpha = 50; 90 94 meltpoint = 1; 91 95 rarity = 15; depth = 580; 92 96 power = 4; speed = 3; 93 97 durability = 1400; cooktime = 40; 94 98 armor_weight = 0.7; 99 + maxenergy = 1000; 95 100 slots = { 96 101 {affinity = {'praxic','counterpraxic'}; confluence = 0.3}; 97 102 {affinity = {'counterpraxic'}; confluence = 0.8}; 98 103 } 99 104 }; 100 105 gold = { 101 106 ingot = 'default:gold_ingot'; 102 107 block = 'default:goldblock'; 103 108 tone = {255,225,47}; 109 + maxenergy = 3000; 104 110 slots = { 105 111 {affinity = {'praxic','counterpraxic'}; confluence = 1.4}; 106 112 {affinity = {'praxic','counterpraxic'}; confluence = 1.2}; 107 113 } 108 114 }; 109 115 silver = { 110 116 tone = {218,255,246}; 111 117 118 + maxenergy = 2000; 112 119 depth = 380; rarity = 13.5; 113 120 no_armor = true; no_tools = true; 114 121 power = 1; cooktime = 8; hardness = 1; 115 122 }; 116 123 electrum = { 117 124 tone = {212, 255, 0}, alpha = 80; 118 125 artificial = true; ................................................................................ 123 130 }; 124 131 }; 125 132 no_tools = true; 126 133 }; 127 134 tungsten = { 128 135 tone = {0,255,163}, alpha = 70; 129 136 rarity = 14; 130 - speed = 2.5; 137 + speed = 2.8; 131 138 power = 4; 132 139 meltpoint = 4; 133 140 cooktime = 100; 134 - durability = 2500; 141 + durability = 2700; 142 + maxenergy = 1500; 135 143 slots = { 136 144 {affinity = {'counterpraxic'}, confluence = 0.6}; 137 - {affinity = {'praxic','counterpraxic'}, confluence = 0.8}; 145 + {affinity = {'praxic','counterpraxic'}, confluence = 1}; 138 146 {affinity = {'praxic'}, confluence = 0.5}; 139 147 }; 140 148 }; 141 149 cobalt = { 142 150 tone = {48,101,255}, alpha = 90; 143 - rarity = 15; 144 - durabilty = 650; 151 + rarity = 17; 152 + durabilty = 900; 145 153 power = 3; 146 154 speed = 3.5; 147 155 cooktime = 30; 156 + maxenergy = 3500; 157 + slots = { 158 + { 159 + affinity = {'counterpraxic'}; 160 + confluence = 0.65; 161 + interference = {speed = 1}; 162 + }; 163 + } 148 164 }; 149 165 lithium = { 150 166 tone = {255,252,93}, alpha = 80; 151 - rarity = 12.5; 167 + rarity = 13; 152 168 no_tools = true; 153 169 no_armor = true; 154 170 }; 155 171 iridium = { 156 172 tone = {209,88,241}, alpha = 80; 157 - rarity = 17; 173 + rarity = 18; 158 174 meltpoint = 3; 159 175 cooktime = 340; 160 - durability = 1700; 176 + maxenergy = 1800; 177 + durability = 1900; 161 178 speed = 3.2; 162 179 img = { 163 180 -- ingot = 'sorcery_iridium_ingot.png'; 164 181 -- block = 'sorcery_iridium_block.png'; 165 182 }; 166 183 slots = { 167 184 {affinity={'counterpraxic','syncretic'}, confluence = 1.1}; 168 185 {affinity={'cognic','entropic'}, confluence = 0.8}; 169 186 }; 170 187 }; 171 - duranium = { 188 + duridium = { 172 189 tone = {255,64,175}, alpha = 70; 173 190 cooktime = 120; 174 191 artificial = true; 175 192 durability = 3400; 176 193 speed = 3.1; 177 194 power = 5; 178 195 mix = { ................................................................................ 181 198 aluminum = 4; 182 199 tin = 1; 183 200 }; 184 201 }; 185 202 img = { 186 203 -- ingot = 'sorcery_duranium_ingot.png'; 187 204 }; 205 + maxenergy = 1300; 188 206 slots = { 189 207 {affinity={'counterpraxic'}, confluence = 0.6}; 190 208 {affinity={'counterpraxic'}, confluence = 0.4}; 191 209 }; 192 210 }; 193 211 impervium = { 194 212 tone = {226,255,107}, alpha = 90; 195 213 cooktime = 260; 196 214 meltpoint = 5; 197 215 artificial = true; 198 216 speed = 2.1; 199 217 durability = 5300; 218 + maxenergy = 2300; 200 219 watercool = true; 201 220 mix = { 202 221 metals = { 203 222 duranium = 4; 204 223 iridium = 2; 205 224 levitanium = 1; 206 225 }; 207 226 }; 208 227 slots = { 209 - {affinity={'praxic'}, confluence = 1.2}; 228 + {affinity={'praxic'}, confluence = 1.2, interference={durability=2}}; 210 229 {affinity={'praxic','syncretic'}, confluence = 0.8}; 211 230 {affinity={'cognic'}, confluence = 0.9}; 212 231 }; 213 232 }; 214 233 eternium = { 215 234 tone = {156,82,222}, alpha = 100; 216 235 cooktime = 500; 217 236 meltpoint = 6; 218 237 artificial = true; 219 238 speed = 2; 239 + maxenergy = 1200; 220 240 durability = 8100; 221 241 watercool = true; 222 242 mix = { 223 243 metals = { 224 244 iridium = 2; 225 245 tungsten = 2; 226 246 lithium = 1; ................................................................................ 232 252 } 233 253 }; 234 254 unobtanium = { 235 255 tone = {114,255,214}, alpha = 120; 236 256 meltpoint = 3; 237 257 cooktime = 330; 238 258 artificial = true; 259 + maxenergy = 4000; 239 260 durability = 3300; 240 261 speed = 3.4; 241 262 slots = { 242 263 {affinity={'praxic'}, confluence = 0.7}; 243 264 {affinity={'counterpraxic'}, confluence = 1.2}; 244 265 {affinity={'cognic'}, confluence = 1.1}; 245 266 };
Modified data/oils.lua from [268d4500ec] to [f8f2204848].
5 5 -- recipes are described by two fields, the 'core', which consists of items which are included in the output, and 'mix', items with are incidental to the output. items listed in mix can leave leftovers in the crafting grid; core items will never leave leftovers (as it is assumed that they are being reused). the mortar and pestle is always implied. if core is empty, a bowl is automatically added to the recipe. 6 6 core = {}; 7 7 mix = { 8 8 'farming:sugar'; 9 9 'group:food_blueberries'; 10 10 'farming:raspberries'; 11 11 'sorcery:extract_wheat'; 12 - 'sorcery:extract_wheat'; 12 + 'xdecor:honey'; 13 13 }; 14 14 }; 15 15 berry = { 16 16 color = {151,67,183}; 17 17 core = {}; 18 18 mix = { 19 19 'group:food_raspberries';
Modified data/philters.lua from [db8db88125] to [6fff6fb29a].
1 1 return { 2 2 dark = { 3 3 color = {86,16,42}; 4 4 infusion = "default:obsidian_shard"; 5 5 }; 6 6 shimmering = { 7 - color = {112,255,170}; 7 + color = {224,255,155}; 8 8 infusion = "default:mese_crystal_fragment"; 9 9 }; 10 10 silent = { 11 11 color = {249,193,42}; 12 12 infusion = "sorcery:extract_cotton"; 13 13 }; 14 14 verdant = { 15 - infusion = "default:apple_sapling"; 15 + infusion = "default:sapling"; 16 16 color = {78,222,113}; 17 17 }; 18 18 blazing = { 19 19 infusion = "sorcery:oil_flame"; 20 20 color = {229,32,53}; 21 21 }; 22 22 }
Modified data/potions.lua from [a62297059e] to [c61093f3aa].
15 15 color = {186,241,233}; 16 16 infusion = 'sorcery:grease_fog'; 17 17 }; 18 18 Luminous = { 19 19 color = {255,237,160}; 20 20 style = 'dull'; 21 21 glow = 12; 22 - infusion = 'xdecor:honey'; 22 + infusion = 'sorcery:gem_luxite'; 23 23 }; 24 24 Soft = { 25 25 color = {174,210,85}; 26 26 style = 'sparkle'; 27 27 infusion = 'sorcery:extract_cotton'; 28 28 }; 29 29 Viscous = { 30 30 color = {119,51,111}; 31 31 infusion = 'sorcery:oil_bleak'; 32 32 }; 33 33 }
Modified data/register.lua from [b568fdc66a] to [d2f1e722e5].
1 1 return { 2 2 infusion = function(r) 3 3 sorcery.data.infusions[#sorcery.data.infusions + 1] = r 4 4 end; 5 5 alloy = function(mix) 6 6 sorcery.data.alloys[#sorcery.data.alloys + 1] = mix 7 7 end; 8 + kiln_recipe = function(mix) 9 + sorcery.data.kilnrecs[#sorcery.data.kilnrecs + 1] = mix 10 + end; 8 11 infusion_leftover = function(orig, leave) 9 12 sorcery.data.infusion_leftovers[orig] = leave 10 13 end; 11 14 }
Modified data/spells.lua from [196ad8b009] to [3dd4d17be3].
41 41 -- the item material and look up the slots offered by this 42 42 -- material. we iterate through the slot definitions to pick 43 43 -- out a candidate slot, criteria being that the slot 44 44 -- possesses the proper affinity, and that the corresponding 45 45 -- slot on the item enchantment record is empty, then pick 46 46 -- the final slot at random from this table if #candidates>0 47 47 -- (otherwise, we fail unceremoniously). 48 - -- 48 + 49 + local current_enchant = sorcery.enchant.get(subj) 50 + local material, eligible_spells = sorcery.enchant.getsubj(subj) 51 + if eligible_spells == nil 52 + or #eligible_spells == 0 53 + or material == nil 54 + or material.data.slots == nil 55 + or #material.data.slots == 0 56 + then return false end 57 + 58 + -- determine the properties the enchantment will have 59 + local power = 10 60 + local energy = material.data.maxenergy 61 + local reliability = 100 62 + if ctx.base.gem == 'sapphire' then power = power + 5 63 + elseif ctx.base.gem == 'amethyst' then 64 + energy = energy * (math.random() * 0.7) 65 + elseif ctx.base.gem == 'diamond' then 66 + if math.random(5) == 1 then 67 + power = power * 2 68 + reliability = reliability - (reliability / 4) 69 + else 70 + power = power + 5 71 + reliability = reliability - 10 72 + end 73 + end 74 + 75 + local viable_slots = {} 76 + for i,slot in pairs(material.data.slots) do 77 + if sorcery.lib.tbl.has(slot.affinity,aff) then 78 + for _,spell in pairs(current_enchant.spells) do 79 + if spell.slot == i then goto nonviable end 80 + end 81 + viable_slots[#viable_slots + 1] = i 82 + end 83 + ::nonviable::end 84 + if #viable_slots == 0 then return false end 85 + 86 + local target_slot = viable_slots[math.random(#viable_slots)] 49 87 -- once we have selected an appropriate slot, we iterate 50 88 -- through the list of known enchantments to check the 51 89 -- affinity of each against `aff`. if the affinity matches 52 90 -- the wand, we then check whether the 'recipe' matches. 53 91 -- if so, we've found the enchantment -- apply it to the 54 92 -- object and update its enchantment data. otherwise, we 55 93 -- move on to the next. if no matching recipe is found, 56 - -- we give up and bail, returning 'nil' to signify that 94 + -- we give up and bail, returning 'false' to signify that 57 95 -- a spell was not cast. 58 96 59 - enchantment_sparkle(ctx,affcolor) 97 + local focus_match = function(spec,stack) 98 + local default_mode 99 + if spec.lens then 100 + default_mode = 'dmg' 101 + if minetest.get_item_group(stack:get_name(), 'sorcery_enchanting_lens') == 0 102 + then return false end 103 + local proto = stack:get_definition()._proto 104 + if proto.kind ~= spec.lens or proto.gem ~= spec.gem 105 + then return false end 106 + elseif spec.item then 107 + default_mode = 'consume' 108 + if stack:get_name() ~= spec.item then 109 + return false end 110 + else 111 + return false 112 + end 113 + 114 + local mode 115 + if spec.dmg then mode = 'dmg' 116 + elseif spec.consume then mode = 'consume' 117 + else mode = default_mode end 118 + 119 + if mode == 'dmg' then 120 + stack:add_wear((spec.dmg or 1) * 1000) 121 + return stack 122 + elseif mode == 'consume' then 123 + stack:take_item(spec.consume or 1) 124 + return stack 125 + end 126 + end 127 + for ench,data in pairs(sorcery.data.enchants) do 128 + if data.affinity ~= aff or data.recipe == nil then goto skip end 129 + local newinv = {} 130 + for s,v in pairs(data.recipe) do 131 + newinv[s] = focus_match(v,inv:get_stack('foci',s)) 132 + if newinv[s] == false then goto skip end 133 + end 134 + -- is the tool compatible with the chosen spell? we check its groups to 135 + -- see if any of them grant it eligibility; if not, we skip to the next 136 + -- spell. NOTE: this means the same recipe could mean different things 137 + -- for different kinds of tools, if one were so inclined. 138 + for g,v in pairs(subj:get_definition().groups) do 139 + if v ~= 0 and sorcery.lib.tbl.has(data.groups, g) 140 + then goto enchant end 141 + end 142 + goto skip 143 + -- spell matches! 144 + ::enchant:: current_enchant.spells[#current_enchant.spells + 1] = { 145 + id = ench; 146 + slot = target_slot; 147 + boost = power; 148 + reliability = reliability; 149 + } 150 + current_enchant.energy = math.max(current_enchant.energy, energy) 151 + 152 + sorcery.enchant.set(subj, current_enchant) 153 + inv:set_stack('item',1,subj) 154 + for i,v in pairs(newinv) do inv:set_stack('foci',i,v) end 155 + sorcery.enchant.update_enchanter(ctx.target.under) 156 + enchantment_sparkle(ctx,affcolor) 157 + do return nil end 158 + ::skip::end 159 + return false 60 160 end 61 161 }; 62 162 end 63 163 -- note: this was written before terminology was standardized, 64 164 -- and "leytype" corresponds to what is otherwise known as an 65 165 -- "affinity"; "affinity" after this comment is widely misused 66 166 return { ................................................................................ 93 193 leytype = 'imperic'; 94 194 affinity = {'pine','dark'}; 95 195 cast = function(ctx) 96 196 if ctx.target == nil or ctx.target.type ~= 'node' then return false end 97 197 local meta = minetest.get_meta(ctx.target.under) 98 198 -- first we need to check if the wand has an identifying 'key' yet, 99 199 -- and set one if not. 100 - local wandmode = ctx.base.gem == 'amethyst' 200 + local wandmode = ctx.base.gem == 'sapphire' 101 201 local keycode 102 202 if ctx.meta:contains('sorcery_wand_key') then 103 203 keycode = ctx.meta:get_string('sorcery_wand_key') 104 204 else 105 205 keycode = sorcery.lib.str.rand(32) 106 206 ctx.meta:set_string('sorcery_wand_key', keycode) 207 + -- ctx.meta:mark_as_private('sorcery_wand_key') 107 208 end 108 209 if meta:contains('owner') then 109 210 -- owner is already set -- can we break the enchantment? 110 211 if meta:get_string('sorcery_wand_key') == keycode then 111 212 meta:set_string('owner','') 112 213 meta:set_string('sorcery_wand_key','') 113 214 meta:set_string('sorcery_seal_mode','') 114 215 enchantment_sparkle(ctx,sorcery.lib.color(101,255,142)) 115 216 else return false end 116 217 else 117 218 meta:set_string('sorcery_wand_key',keycode) 219 + meta:mark_as_private('sorcery_wand_key') 118 220 meta:set_string('owner',ctx.caster:get_player_name()) 119 221 if wandmode then 120 222 meta:set_string('sorcery_seal_mode','wand') 121 223 end 122 224 enchantment_sparkle(ctx,sorcery.lib.color(255,201,27)) 123 225 end 124 226 end; 125 227 }; 126 228 leyspark = { 127 229 name = 'Leyspark'; 128 230 leytype = 'cognic'; 231 + color = {255,246,142}; -- bright yellow 129 232 affinity = {'apple','silent'}; 130 - uses = 64; 233 + uses = 128; 131 234 desc = 'Reveal the strength and affinities of the local leyline'; 132 235 cast = function(ctx) 133 236 local color = ctx.base.gem == 'sapphire'; 237 + local duration = (ctx.base.gem == 'amethyst' and 4) or 2; 134 238 local ley = sorcery.ley.estimate(ctx.caster:get_pos()) 135 239 local emit = function(color,strength) 136 240 minetest.add_particlespawner { 137 241 amount = 70 * strength; 138 - time = 2 * strength; 242 + time = duration * strength; 139 243 attached = ctx.caster; 140 244 texture = sorcery.lib.image('sorcery_spark.png'): 141 - multiply(color):render(); 142 - minpos = { x = 0.5, z = 0.0, y = 1.5}; 143 - maxpos = { x = 0.5, z = 0.0, y = 1.5}; 245 + multiply(color:brighten(1.3)):render(); 246 + minpos = { x = -0.1, z = 0.5, y = 1.2}; 247 + maxpos = { x = 0.1, z = 0.3, y = 1.6}; 144 248 minvel = { x = -0.5, z = -0.5, y = -0.5}; 145 249 maxvel = { x = 0.5, z = 0.5, y = 0.5}; 146 250 minacc = { x = 0.0, z = 0.0, y = 0.5}; 147 - minacc = { x = 0.0, z = 0.0, y = 0.5}; 251 + maxacc = { x = 0.0, z = 0.0, y = 0.5}; 148 252 minsize = 0.4, maxsize = 0.8; 149 253 minexptime = 1, maxexptime = 1; 150 254 glow = 14; 151 255 animation = { 152 256 type = 'vertical_frames'; 153 257 aspect_w = 16; 154 258 aspect_h = 16; ................................................................................ 168 272 end 169 273 170 274 end; 171 275 }; 172 276 dowse = { 173 277 name = 'dowsing'; 174 278 leytype = 'cognic'; 279 + color = {65,116,255}; 175 280 affinity = {'acacia','dark','silent'}; 176 - uses = 128; 281 + uses = 176; 177 282 desc = 'Send up sparks of radia to indicate nearness or absence of attuned blocks'; 178 283 }; 179 284 verdant = { 180 285 name = 'verdant'; 181 286 color = {16,29,255}; 182 287 uses = 48; 183 288 leytype = 'imperic'; ................................................................................ 188 293 counterpraxic = anchorwand('counterpraxic',23, {'pine','shimmering','silent'}); 189 294 entropic = anchorwand('entropic', 8, {'jungle','dark'}); 190 295 syncretic = anchorwand('syncretic', 12, {'aspen','verdant','shimmering','blazing'}); 191 296 cognic = anchorwand('cognic', 36, {'acacia','verdant','dark'}); 192 297 shape = { 193 298 name = 'shaping'; 194 299 uses = 24; 300 + color = {255,114,65}; 301 + leytype = 'praxic'; 195 302 affinity = {'apple','blazing'}; 196 303 desc = 'With an enchanter, physically alter the mundane qualities of an object'; 197 304 }; 198 305 attune = { 199 306 name = 'attunement'; 200 307 uses = 38; 308 + color = {255,65,207}; 201 309 leytype = 'syncretic'; 202 310 affinity = {'pine','verdant','dark'}; 203 311 desc = 'Establish a connection between mystic mechanisms, like connecting two sides of a portal or impressing targets onto a dowsing wand in an enchanter'; 204 312 }; 205 313 meld = { 206 314 name = 'melding'; 207 315 uses = 48; 208 316 leytype = 'syncretic'; 317 + color = {172,65,255}; 209 318 affinity = {'apple','verdant'}; 210 319 desc = 'Meld the properties of three balanced items on an enchanter to create a new one with special properties, but destroying the old ones and losing two thirds of the mass in the process. The precise outcome is not always predictable.'; 211 320 }; 212 321 divide = { 213 322 name = 'division'; 214 323 uses = 19; 215 324 leytype = 'syncretic'; 325 + color = {255,65,121}; 216 326 affinity = {'apple','shimmering'}; 217 327 desc = 'Shatter an item on an enchanter, dividing its essence equally into three parts and precipitating it into new items embodying various properties of the destroyed item. The outcome is not always predictable.'; 218 328 }; 219 329 obliterate = { 220 330 name = 'obliteration'; 221 331 uses = 129; 332 + color = {175,6,212}; 222 333 affinity = {'aspen','dark'}; 223 334 leytype = 'occlutic'; 224 335 desc = 'Totally and irreversibly obliterate all items on an enchanter.'; 225 336 }; 226 337 sacrifice = { 227 338 name = 'sacrifice'; 228 339 uses = 58; 340 + color = {212,6,63}; 229 341 affinity = {'aspen','blazing'}; 230 342 leytype = 'syncretic'; 231 343 desc = 'Transform the matter of one to three items on an enchanter into energy and empower the item on the center of the enchanter with it. Useful to recharge wands in areas with weak leylines.'; 232 344 }; 233 345 transfer = { 234 346 name = 'transfer'; 235 347 uses = 65; 348 + color = {6,212,121}; 236 349 leytype = 'syncretic'; 237 350 affinity = {'aspen','shimmering','silent'}; 238 351 desc = 'Transfer ley-current from items on an enchanter into the item in the center, but at a 50% loss if they are of mismatched affinities. One third of maximum current is transferred, and when used on items with little power may destroy them or their enchantments'; 239 352 }; 353 + transmute = { 354 + name = 'transmutation'; 355 + uses = 7; 356 + color = {255,90,18}; 357 + leytype = 'imperic'; 358 + affinity = {'aspen','shimmering','dark','blazing'}; 359 + desc = 'Transmute three ingots into one of a different metal, determined by chance and influenced by configuration of the wand'; 360 + }; 240 361 disjoin = { 241 362 name = 'disjunction'; 242 363 uses = 32; 364 + color = {17,6,212}; 243 365 leytype = 'occlutic'; 244 366 affinity = {'jungle','silent'}; 245 367 desc = 'With an enchanter, disjoin the anchor holding a spell into an object so a new spell can instead be bound in'; 368 + }; 369 + luminate = { 370 + name = 'lumination'; 371 + desc = 'Banish darkness all about you for a few moments'; 372 + uses = 40; 373 + color = {244,255,157}; 374 + affinity = {'acacia','shimmering','blazing'}; 375 + leytype = 'cognic'; 376 + cast = function(ctx) 377 + local center = ctx.heading.pos 378 + local maxpower = 20 379 + local power = (ctx.base.gem == 'sapphire' and maxpower) or maxpower/2 380 + local range = (ctx.base.gem == 'emerald' and 10) or 5 381 + local duration = (ctx.base.gem == 'amethyst' and 60) or 30 382 + if ctx.base.gem == 'diamond' then 383 + power = power * (math.random()*2) 384 + range = range * (math.random()*2) 385 + duration = duration * (math.random()*2) 386 + end 387 + local lum = math.ceil((power/maxpower) * minetest.LIGHT_MAX) 388 + print('setting lum',lum) 389 + for i=1,power do 390 + local pos = vector.add(center, { 391 + x = math.random(-range,range); 392 + z = math.random(-range,range); 393 + y = math.random(0,range/2); 394 + }) 395 + local delta = vector.subtract(pos,center) 396 + local near = 1 - (delta.x^2 + delta.y^2 + delta.z^2)/(range^2) 397 + if minetest.get_node(pos).name == 'air' then 398 + minetest.set_node(pos,{name='sorcery:air_glimmer_' .. tostring(lum)}) 399 + do local lm = minetest.get_meta(pos) 400 + lm:set_float('duration',duration) 401 + lm:set_float('timeleft',duration) 402 + lm:set_float('power',lum * near) 403 + end 404 + end 405 + end 406 + end; 246 407 }; 247 408 }
Modified enchanter.lua from [f08588c5d9] to [2062a1f6be].
2 2 type = 'fixed'; 3 3 fixed = { 4 4 -0.5, -0.5, -0.5; 5 5 0.5, 0.1, 0.5; 6 6 }; 7 7 } 8 8 9 -local enchantable_tools = { 10 - pickaxe = {}, pick = {}; 11 - axe = {}; 12 - sword = {}; 13 - sickle = {}; 14 - shovel = {}; 15 - hoe = {}; 16 -}; 17 - 18 -sorcery.enchant = {} do 19 - local m = sorcery.lib.marshal 20 - local ench_t = m.g.struct { 21 - id = m.t.str; 22 - slot = m.t.u8; 23 - boost = m.t.u8; -- every enchantment has an intrinsic force 24 - -- separate from the confluence of the slot, which is 25 - -- determined by the composition of the wand used to generate 26 - -- it (for instance, a gold-wired wand at low wear, or a wand 27 - -- with specific gemstones, may have a boost level above 0) 28 - } 29 - local pack, unpack = m.transcoder { 30 - spells = m.g.array(8, ench_t); 31 - energy = m.t.u16; 32 - } 33 - local key = 'sorcery_enchantment_recs' 34 - sorcery.enchant.set = function(stack, data) 35 - local meta = stack:get_meta() 36 - meta:set_string(key, pack(data)) 37 - end 38 - sorcery.enchant.get = function(stack) 39 - local meta = stack:get_meta() 40 - if meta:contains(key) then 41 - local data = meta:get_string(key) 42 - return unpack(data) 43 - else 44 - return { 45 - spells = {}; 46 - energy = 0; 47 - } 48 - end 49 - end 50 - sorcery.enchant.strength = function(stack,id) 51 - -- this functions should be used whenever you need to 52 - -- determine the power of a particular enchantment on 53 - -- an enchanted item. 54 - local e = sorcery.enchant.get(stack) 55 - local p = 0.0 56 - local slots = sorcery.matreg.lookup[stack:get_name()].data.slots 57 - -- TODO handle strength-boosting spells! 58 - for _,s in pairs(e.spells) do 59 - if s.id == id then p = p + slots[s.slot] end 60 - end 61 - return p 62 - end 63 - sorcery.enchant.stackup = function(stack) 64 - -- stack update function. this should be called whenever 65 - -- the enchantment status of a stack changes; it will 66 - -- alter/reset tool capabilities and tooltip as necessary 67 - local e = sorcery.enchant.get(stack) 68 - local meta = stack:get_meta() 69 - local def = stack:get_definition() 70 - meta:set_string('tool_capabilities','') 71 - local done = {} 72 - local props = {} 73 - for _,s in pairs(e.spells) do 74 - if done[s.id] then goto skip end 75 - done[s.id] = true 76 - local pwr = sorcery.enchant.strength(stack,s.id) 77 - -- somewhat wasteful… 78 - local name, color, desc = sorcery.data.enchants[s.id].apply(stack,pwr) 79 - props[#props+1] = { 80 - title = name; 81 - desc = desc; 82 - color = sorcery.lib.color(desc); 83 - } 84 - ::skip::end 85 - if #e.spells > 0 then 86 - meta:set_string('description', sorcery.lib.ui.tooltip { 87 - title = 'Enchanted ' .. def.description; 88 - props = props; 89 - }) 90 - else 91 - meta:set_string('description','') 92 - end 93 - end 94 -end 95 - 96 -local enchanter_getsubj = function(item) 97 - if not item:is_empty() then 98 - for group, spells in pairs(enchantable_tools) do 99 - if minetest.get_item_group(item:get_name(), group) ~= 0 then 100 - return group, sorcery.matreg.lookup[item:get_name()] 101 - end 102 - end 103 - end 104 - return false 105 -end 106 9 local enchanter_update = function(pos) 107 10 local meta = minetest.get_meta(pos) 108 11 local inv = meta:get_inventory() 109 12 local item = inv:get_stack('item',1) 110 13 local slots = '' 111 - local itype, imat = enchanter_getsubj(item) 112 - if itype and imat and imat.data.slots then 14 + local imat = sorcery.enchant.getsubj(item) 15 + if imat and imat.data.slots then 113 16 local n = #imat.data.slots 114 17 local sw, sh = 2.1, 2.1; 115 18 local w = sw * n; 116 - local spells = sorcery.enchant.get(item).spells 19 + local item_enchantment = sorcery.enchant.get(item) 20 + local spells = item_enchantment.spells 117 21 for i=1,n do 118 22 local slot=imat.data.slots[i] 119 23 local x = (4 - (w/2) + (sw * (i-1))) + 0.2 120 24 local offtbl = { 121 25 [1] = {0}; 122 26 [2] = {0.3, 0.3}; 123 27 [3] = {0.3, 0, 0.3}; ................................................................................ 139 43 color = sorcery.lib.color(sorcery.data.affinities[aff].color); 140 44 desc = sorcery.data.affinities[aff].desc; 141 45 } 142 46 end 143 47 local hovertitle = 'Empty spell slot'; 144 48 local conf = tostring(math.floor(slot.confluence*100)) .. '%' 145 49 local hoverdesc = 'An enchantment of one the following affinities can be anchored into this slot at ' .. conf .. ' confluence'; 50 + local hovercolor = nil 146 51 for _,sp in pairs(spells) do 52 + local spdata = sorcery.data.enchants[sp.id] 147 53 if sp.slot == i then 54 + hovercolor = sorcery.lib.color(spdata.tone):readable() 148 55 hovertitle = sorcery.lib.str.capitalize(sp.id) 149 - hoverdesc = 'An enchantment is anchored in this slot at ' .. conf .. ' confluence' 56 + hoverdesc = sorcery.lib.str.capitalize(spdata.desc) .. '. Anchored in this slot at ' .. conf .. ' confluence' 57 + if sp.boost > 10 then 58 + hoverdesc = hoverdesc .. ' and boosted by ' .. tostring((sp.boost - 10) * 10) .. '%' 59 + elseif sp.boost < 10 then 60 + hoverdesc = hoverdesc .. ' but weakened by ' .. tostring((10 - sp.boost) * 10) .. '%' 61 + end 62 + hoverdesc = hoverdesc .. '.' 63 + local addrune = function(tex) 64 + pwr = pwr .. string.format([[ 65 + image[%f,%f;%f,%f;%s] 66 + ]], x+0.43,y+0.6,sw/2.7,sh/2.7, tex) 67 + end 68 + local rune = 'sorcery_enchant_' .. sp.id .. '.png' 69 + local energy = item_enchantment.energy 70 + local fullenergy = imat.data.maxenergy 71 + if energy <= fullenergy then 72 + addrune(rune .. '^[opacity:110^[lowpart:' .. tostring(math.floor((energy/fullenergy) * 100)) .. '%:' .. rune) 73 + elseif energy == fullenergy then addrune(rune) 74 + elseif energy >= fullenergy then 75 + addrune(rune .. '^[colorize:#ffffff:' .. 76 + tostring(255 * math.min(1,(energy / fullenergy * 2)))) 77 + end 150 78 break 151 79 end 152 80 end 153 81 slots = slots .. string.format([[ 154 82 image[%f,%f;%f,%f;sorcery_pentacle.png] 155 83 tooltip[%f,%f;%f,%f;%s;%s;%s] 156 84 ]], 157 85 x,y, sw,sh, 158 86 x+0.20,y+0.16, sw-0.84,sh-0.76, 159 87 minetest.formspec_escape(sorcery.lib.ui.tooltip { 160 88 title = hovertitle; 161 89 desc = hoverdesc; 90 + color = hovercolor; 162 91 props = ap; 163 92 }), 164 93 '#37002C','#FFC8F5' 165 94 ) .. pwr 166 95 end 167 96 end 168 97 ................................................................................ 175 104 list[context;foci;2.5,2;1,1;1] 176 105 list[context;foci;4.5,2;1,1;2] 177 106 list[current_player;main;0,4.7;8,4;] 178 107 listring[current_player;main] 179 108 listring[context;item] 180 109 ]] .. slots) 181 110 end 111 + 112 +sorcery.enchant = {} do 113 + sorcery.enchant.update_enchanter = enchanter_update 114 + local m = sorcery.lib.marshal 115 + local ench_t = m.g.struct { 116 + id = m.t.str; 117 + slot = m.t.u8; 118 + boost = m.t.u8; -- every enchantment has an intrinsic force 119 + -- separate from the confluence of the slot, which is 120 + -- determined by the composition of the wand used to generate 121 + -- it (for instance, a gold-wired wand at low wear, or a wand 122 + -- with specific gemstones, may have a boost level above 10) 123 + -- boost is divided by 10 to yield a float 124 + reliability = m.t.u8; 125 + -- reliability is a value between 0 and 100, where 0 means the 126 + -- spell fails every time and 100 means it never fails. not 127 + -- relevant for every spell 128 + } 129 + local pack, unpack = m.transcoder { 130 + spells = m.g.array(8, ench_t); 131 + energy = m.t.u16; 132 + } 133 + sorcery.enchant.getsubj = function(item) 134 + if not item:is_empty() then 135 + local eligible = {} 136 + for name, spell in pairs(sorcery.data.enchants) do 137 + for g,v in pairs(item:get_definition().groups) do 138 + if v~= 0 and sorcery.lib.tbl.has(spell.groups,g) then 139 + eligible[#eligible+1] = name 140 + goto skip 141 + end 142 + end 143 + ::skip::end 144 + return sorcery.matreg.lookup[item:get_name()], eligible 145 + else return nil end 146 + end 147 + local key = 'sorcery_enchantment_recs' 148 + sorcery.enchant.set = function(stack, data, noup) 149 + local meta = stack:get_meta() 150 + meta:set_string(key, sorcery.lib.str.meta_armor(pack(data),true)) 151 + if not noup then stack=sorcery.enchant.stackup(stack) end 152 + end 153 + sorcery.enchant.get = function(stack) 154 + local meta = stack:get_meta() 155 + if meta:contains(key) then 156 + local data = sorcery.lib.str.meta_dearmor(meta:get_string(key),true) 157 + return unpack(data) 158 + else 159 + return { 160 + spells = {}; 161 + energy = 0; 162 + } 163 + end 164 + end 165 + sorcery.enchant.strength = function(stack,id) 166 + -- this functions should be used whenever you need to 167 + -- determine the power of a particular enchantment on 168 + -- an enchanted item. 169 + local e = sorcery.enchant.get(stack) 170 + local p = 0.0 171 + local slots = sorcery.matreg.lookup[stack:get_name()].data.slots 172 + -- TODO handle strength-boosting spells! 173 + for _,s in pairs(e.spells) do 174 + print(dump(s)) 175 + if s.id == id then p = p + ((s.boost * slots[s.slot].confluence)/10) end 176 + end 177 + return p 178 + end 179 + sorcery.enchant.stackup = function(stack) 180 + -- stack update function. this should be called whenever 181 + -- the enchantment status of a stack changes; it will 182 + -- alter/reset tool capabilities and tooltip as necessary 183 + local e = sorcery.enchant.get(stack) 184 + local meta = stack:get_meta() 185 + local def = stack:get_definition() 186 + local mat = sorcery.enchant.getsubj(stack) 187 + local done = {} 188 + local props = {} 189 + local interference = {} 190 + -- meta:set_string('tool_capabilities','') 191 + meta:set_tool_capabilities(nil); -- TODO this probably only works 192 + -- in >5.3; maybe bring in the old JSON mechanism so it works in 193 + -- older versions as well? 194 + local basecaps = def.tool_capabilities 195 + for _,s in pairs(e.spells) do 196 + if done[s.id] then goto skip end 197 + done[s.id] = true 198 + local pwr = sorcery.enchant.strength(stack,s.id) 199 + -- somewhat wasteful… 200 + local e = sorcery.data.enchants[s.id] 201 + if e.apply then stack = e.apply(stack,pwr,basecaps) end 202 + props[#props+1] = { 203 + title = e.name; 204 + desc = e.desc; 205 + color = sorcery.lib.color(e.tone); 206 + } 207 + local inf = mat.data.slots[s.slot].interference 208 + if inf then for k,v in pairs(inf) do 209 + interference[k] = interference[k] + v 210 + end end 211 + ::skip::end 212 + if #interference > 0 then 213 + if interference.speed then stack = sorcery.data.enchants.pierce.apply(stack,-interference.speed,basecaps) end 214 + if interference.durability then stack = sorcery.data.enchants.endure.apply(stack,-interference.durability,basecaps) end 215 + end 216 + meta = stack:get_meta() -- necessary? unclear 217 + if #e.spells > 0 then 218 + meta:set_string('description', sorcery.lib.ui.tooltip { 219 + title = 'Enchanted ' .. def.description; 220 + props = props; 221 + }) 222 + else 223 + meta:set_string('description',def.description) 224 + end 225 + return stack 226 + end 227 +end 182 228 183 229 minetest.register_node('sorcery:enchanter', { 184 230 description = 'Enchanter'; 185 231 drawtype = 'mesh'; 186 232 mesh = 'sorcery-enchanter.obj'; 187 233 paramtype = 'light'; 188 234 paramtype2 = 'facedir'; ................................................................................ 196 242 "default_bronze_block.png"; 197 243 "default_junglewood.png"; 198 244 "default_gold_block.png"; 199 245 }; 200 246 on_construct = function(pos) 201 247 local meta = minetest.get_meta(pos) 202 248 local inv = meta:get_inventory() 249 + meta:set_string('infotext','Enchanter') 203 250 inv:set_size('item', 1) 204 251 inv:set_size('foci', 3) 205 252 enchanter_update(pos) 206 253 end; 207 254 on_metadata_inventory_put = enchanter_update; 208 255 on_metadata_inventory_move = enchanter_update; 209 256 on_metadata_inventory_take = enchanter_update; 210 257 }) 211 258 259 +minetest.register_craftitem('sorcery:enchanter_channeler',{ 260 + inventory_image = 'sorcery_enchanter_channeler.png'; 261 + description = 'Channeler'; 262 +}) 263 +minetest.register_craftitem('sorcery:enchanter_pedestal',{ 264 + inventory_image = 'sorcery_enchanter_pedestal.png'; 265 + description = 'Pedestal'; 266 +}) 267 +minetest.register_craft { 268 + output = 'sorcery:enchanter_channeler'; 269 + recipe = { 270 + {'','default:bronze_ingot',''}; 271 + {'basic_materials:gold_wire','basic_materials:steel_strip','basic_materials:gold_wire'}; 272 + {'','sorcery:electrum_ingot',''}; 273 + }; 274 + replacements = { 275 + {'basic_materials:gold_wire','basic_materials:empty_spool'}; 276 + {'basic_materials:gold_wire','basic_materials:empty_spool'}; 277 + }; 278 +} 279 +minetest.register_craft { 280 + output = 'sorcery:enchanter_pedestal'; 281 + recipe = { 282 + {'basic_materials:copper_strip','group:wood','basic_materials:copper_strip'}; 283 + {'','default:bronze_ingot',''}; 284 + {'','group:wood',''}; 285 + }; 286 +} 287 +minetest.register_craft { 288 + output = 'sorcery:enchanter'; 289 + recipe = { 290 + {'','sorcery:enchanter_channeler',''}; 291 + {'sorcery:enchanter_channeler','sorcery:enchanter_pedestal','sorcery:enchanter_channeler'}; 292 + {'group:wood','group:wood','group:wood'}; 293 + }; 294 +} 212 295 for i=1,10 do 213 296 minetest.register_node('sorcery:air_flash_' .. i, { 214 297 drawtype = 'airlike'; 215 298 pointable = false; walkable = false; 216 299 buildable_to = true; 217 300 sunlight_propagates = true; 218 301 light_source = i + 4; ................................................................................ 226 309 end 227 310 end 228 311 }); 229 312 end 230 313 231 314 minetest.register_on_dignode(function(pos, node, puncher) 232 315 if puncher == nil then return end -- i don't know why 233 - -- this is necessary but you get rare crashed without it 316 + -- this is necessary but you get rare crashes without it 234 317 235 318 -- we're goint to do something VERY evil here and 236 319 -- replace the air with a "glow-air" that removes 237 320 -- itself after a short period of time, to create 238 321 -- a flash of light when an enchanted tool's used 239 322 -- to dig out a node 240 323 local tool = puncher:get_wielded_item() 241 - local meta = tool:get_meta() 324 + local ench = sorcery.enchant.get(tool) 325 + if #ench.spells == 0 then return end 326 + print('enchanted!') 242 327 local sparks = {} 243 - local spark = function(name,color) 244 - if meta:contains('enchant_' .. name) then 245 - sparks[#sparks + 1] = { 246 - color = color; 247 - count = meta:get_int('enchant_' .. name); 248 - } 249 - end 328 + -- local spark = function(name,color) 329 + local material = sorcery.enchant.getsubj(tool) 330 + local totalcost = 0 331 + do local done = {} for _,sp in pairs(ench.spells) do 332 + if done[sp.id] then goto skip end 333 + done[sp.id] = true 334 + 335 + local data = sorcery.data.enchants[sp.id] 336 + local strength = sorcery.enchant.strength(tool,sp.id) 337 + local ch = math.random(1,100) 338 + local props = { 339 + fail = ch > sp.reliability; 340 + user = puncher; 341 + pos = pos; 342 + node = node; 343 + tool = tool; 344 + material = material.data; 345 + enchantment = ench; 346 + power = strength; 347 + spell = sp; 348 + sparks = sparks; 349 + cost = data.cost; 350 + } 351 + if data.on_dig then data.on_dig(props) end 352 + if props.cost ~= 0 then totalcost = totalcost + math.max(1,math.floor(props.cost * strength)) end 353 + 354 + if ch > sp.reliability then goto skip end 355 + sparks[#sparks + 1] = { 356 + color = sorcery.lib.color(data.tone):brighten(1.1); 357 + count = strength * 7; 358 + } 359 + ::skip::end end 360 + if totalcost > 0 then 361 + local conservation = sorcery.enchant.strength(tool,'conserve') * 0.5 362 + totalcost = totalcost - (totalcost * conservation) 363 + ench.energy = math.max(0,ench.energy - (totalcost - (material.data.energysource or 0))) 250 364 end 251 - spark('durable',sorcery.lib.color(0,89,245)) 252 - spark('fast',sorcery.lib.color(245,147,89)) 253 365 if #sparks == 0 then return end 254 366 if math.random(5) == 1 then 255 367 minetest.set_node(pos, {name='sorcery:air_flash_' .. tostring(math.random(10))}) 256 368 end 257 369 local range = function(min, max) 258 370 local span = max - min 259 371 local val = math.random() * span 260 372 return val + min 261 373 end 262 374 for _,s in pairs(sparks) do 263 - for i=0,math.floor(s.count * range(1,3)) do 375 + for i=1,math.floor(s.count * range(1,3)) do 264 376 local life = range(0.3,1); 265 377 minetest.add_particle { 266 378 pos = { 267 379 x = pos.x + range(-0.5,0.5); 268 380 z = pos.z + range(-0.5,0.5); 269 381 y = pos.y + range(-0.5,0.5); 270 382 }; ................................................................................ 276 388 velocity = { 277 389 x = range(-1.3,1.3); 278 390 z = range(-1.3,1.3); 279 391 y = range( 0.3,0.9); 280 392 }; 281 393 expirationtime = life; 282 394 size = range(0.5,1.5); 283 - vertical = true; 284 - texture = sorcery.lib.image('sorcery_spark.png'):multiply(s.color:brighten(1.2)):render(); 395 + texture = sorcery.lib.image('sorcery_spark.png'):multiply(s.color):render(); 285 396 glow = 14; 286 397 animation = { 287 398 type = "vertical_frames"; 288 399 aspect_w = 16; 289 400 aspect_h = 16; 290 - length = life * 1.1; 401 + length = life + 0.1; 291 402 }; 292 403 } 293 404 end 294 405 end 406 + 407 + -- destroy spells that can no longer be sustained 408 + if ench.energy == 0 then 409 + ench.spells = {} 410 + sorcery.enchant.set(tool,ench) 411 + else 412 + sorcery.enchant.set(tool,ench,true) 413 + end 414 + puncher:set_wielded_item(tool) 295 415 end) 416 + 417 +minetest.register_chatcommand('enchants', { 418 + description = 'Log information about the currently held object\'s enchantment'; 419 + privs = { server = true }; 420 + func = function(caller,params) 421 + local tool = minetest.get_player_by_name(caller):get_wielded_item() 422 + minetest.chat_send_player(caller, dump(sorcery.enchant.get(tool))) 423 + local binary = tool:get_meta():get_string('sorcery_enchantment_recs') 424 + local dumpout = '' 425 + for i=1,string.len(binary) do 426 + dumpout = dumpout .. string.format('%x%s',string.byte(binary,i),(i%16==0 and '\n') or ' ') 427 + end 428 + print(dumpout) 429 + end; 430 +})
Modified gems.lua from [79f4b638de] to [461d75b6c5].
1 1 --- gemstones 2 2 3 3 sorcery.register_gem = function(name,gem) 4 4 local itemname = gem.foreign or 'sorcery:gem_' .. name 5 5 local shardname = gem.foreign_shard or 'sorcery:gem_' .. name .. '_shard' 6 + local amuletname = gem.foreign_amulet or 'sorcery:gem_' .. name .. '_amulet' 6 7 7 8 local tools, armors = sorcery.matreg.tools, sorcery.matreg.armors 8 9 if gem.tools then for _,t in pairs(tools) do 9 10 sorcery.matreg.lookup[(gem.items and gem.items[t]) or ('sorcery:' .. t .. '_' .. name)] = { 10 11 gem = true; 11 12 id = name; data = gem; 12 13 } 13 14 end end 14 15 if gem.armor then for _,a in pairs(armors) do 15 - sorcery.matreg.lookup[(gem.items and gem.items[t]) or ('sorcery:' .. a .. '_' .. name)] = { 16 + sorcery.matreg.lookup[(gem.items and gem.items[a]) or ('sorcery:' .. a .. '_' .. name)] = { 16 17 gem = true; 17 18 id = name; data = gem; 18 19 } 19 20 end end 20 21 21 22 if gem.foreign_shard then 22 23 minetest.clear_craft {output=shardname} ................................................................................ 23 24 else 24 25 minetest.register_craftitem(shardname, { 25 26 description = sorcery.lib.str.capitalize(name) .. ' shard'; 26 27 inventory_image = 'sorcery_gem_' .. name .. '_shard.png'; 27 28 groups = { sorcery_shard = 1; }; 28 29 _proto = gem; 29 30 }) 31 + end 32 + if not gem.foreign_amulet then 33 + minetest.register_craftitem(amuletname, { 34 + description = sorcery.lib.str.capitalize(name) .. ' amulet'; 35 + inventory_image = sorcery.lib.image('sorcery_amulet.png'):multiply(sorcery.lib.color(gem.tone)):render(); 36 + _proto = { 37 + id = name; 38 + data = gem; 39 + }; 40 + }) 30 41 end 31 42 minetest.register_craft { 32 43 type = 'shapeless'; 33 44 recipe = (minetest.get_modpath('xdecor') and { 34 45 'xdecor:hammer', itemname; 35 46 }) or { itemname }; 36 47 output = shardname .. ' 9'; ................................................................................ 43 54 recipe = { 44 55 shardname, shardname, shardname; 45 56 shardname, shardname, shardname; 46 57 shardname, shardname, shardname; 47 58 }; 48 59 output = itemname; 49 60 }; 61 + minetest.register_craft { 62 + recipe = { 63 + {shardname,itemname,shardname}; 64 + {itemname,itemname,itemname}; 65 + {shardname,itemname,shardname}; 66 + }; 67 + output = amuletname; 68 + }; 50 69 51 70 -- generate lenses and crafting recipes 52 71 for _, kind in pairs { 'amplifier','rectifier','concave','convex' } do 53 72 local id = 'sorcery:lens_' .. kind .. '_' .. name 54 73 minetest.register_tool(id, { 55 74 inventory_image = sorcery.lib.image('sorcery_lens_overlay_gold.png'): 56 75 blit(sorcery.lib.image('sorcery_lens_' .. kind .. '.png'): 57 76 multiply(sorcery.lib.color(gem.tone):brighten(1.1))): 58 - render(); 77 + render(); 59 78 description = sorcery.lib.str.capitalize(name) .. ' ' .. kind .. ' lens'; 60 - group = { sorcery_enchanting_lens = 1 }; 79 + groups = { sorcery_enchanting_lens = 1 }; 80 + _proto = { 81 + gem = name; 82 + kind = kind; 83 + }; 61 84 }) 62 85 end 63 86 do local casing = 'sorcery:fragment_gold' 64 87 minetest.register_craft { 65 88 output = 'sorcery:lens_convex_' .. name; 66 89 recipe = { 67 90 {'', casing, ''};
Modified harvester.lua from [26814ac7ca] to [8384a43ac0].
36 36 local meta = minetest.get_meta(pos) 37 37 local inv = meta:get_inventory() 38 38 if inv:is_empty('charge') then return false end 39 39 40 40 local ley = sorcery.ley.estimate(pos) 41 41 local charged = false 42 42 for i=1,inv:get_size('charge') do 43 - local repair_per_tick = (65536 / 64) * (15 * ley.force) 43 + local curve = function(x) return ((x*10)^2)/10 end 44 44 local item = inv:get_stack('charge',i) 45 45 if minetest.get_item_group(item:get_name(), 'sorcery_wand') ~= 0 then 46 + local mese = 1 47 + if sorcery.wands.util.getproto(item).gem == 'mese' then 48 + mese = 1.5 end 49 + local repair_per_tick = (65536 / 80) * curve(ley.force) * mese 46 50 local spell = item:get_meta():get_string('sorcery_wand_spell') 47 51 if spell == '' then goto skip end 48 52 local aff = sorcery.data.spells[spell].leytype 49 53 if aff == ley.aff[1] or aff == ley.aff[2] then 50 54 repair_per_tick = repair_per_tick * 2 end 51 - else goto skip end -- item is not magical 52 - print('repair cycle! repairing item'..item:get_name()..' by',repair_per_tick * (elapse / 60)) 53 - item:set_wear(math.max(0,item:get_wear() - repair_per_tick * (elapse / 60))) 55 + item:set_wear(math.max(0,item:get_wear() - repair_per_tick * (elapse / 60))) 56 + else 57 + local e = sorcery.enchant.get(item) 58 + if #e.spells == 0 then goto skip end -- item is not magical 59 + local mat = sorcery.enchant.getsubj(item) 60 + if e.energy < mat.data.maxenergy then 61 + local energy_per_tick = (100 * curve(ley.force)) + ((mat.data.energysource or 0)*2) 62 + e.energy = math.min(e.energy + energy_per_tick, mat.data.maxenergy) 63 + sorcery.enchant.set(item,e,true) 64 + else goto skip end -- already fully charged 65 + end 66 + -- print('repair cycle! repairing item'..item:get_name()..' by',repair_per_tick * (elapse / 60)) 54 67 inv:set_stack('charge',i,item) 55 68 charged = true 56 69 ::skip::end 57 70 58 71 return charged 59 72 end; 60 73 61 74 on_construct = function(pos) 62 75 local meta = minetest.get_meta(pos) 63 76 local inv = meta:get_inventory() 64 77 inv:set_size('charge', 3) 78 + meta:set_string('infotext','Harvester') 65 79 meta:set_string('formspec', [[ 66 80 size[8,5] 67 81 list[context;charge;2.5,0;3,1;] 68 82 list[current_player;main;0,1.3;8,4;] 69 83 listring[] 70 84 ]]) 71 85 end;
Added hotmetallurgy.lua version [b05dd85eee].
1 +-- alloying furnace 2 +-- 3 +-- there are several kinds of alloy furnace, with varying 4 +-- capabilities. the simplest can alloy two simple metals; 5 +-- the most complex can alloy four high-grade metals such 6 +-- as titanium, platinum, iridium, or levitanium. 7 +-- 8 +-- furnace recipes follow a pattern: the number of crucibles 9 +-- determines the input slots, the type of crucible determines 10 +-- how hot the furnace can get, and various other components 11 +-- (like a coolant circulator) can be added to allow the 12 +-- creation of exotic metals. 13 +-- 14 +-- alloy furnaces produce ingots that can later be melted down 15 +-- again and cast into a mold to produce items of particular 16 +-- shapes. 17 + 18 +-- there are five kinds of crucibles: clay, aluminum, platinum, 19 +-- duridium, and impervium. clay crucibles are made by molding 20 +-- clay into the proper shape and then firing it in a furnace. 21 +-- others are made by casting. 22 + 23 +local fragments_per_ingot = 4 24 + 25 +for _, c in pairs { 'clay', 'aluminum', 'platinum', 'duranium' } do 26 + minetest.register_craftitem('sorcery:crucible_' .. c, { 27 + description = sorcery.lib.str.capitalize(c .. ' crucible'); 28 + inventory_image = 'sorcery_crucible_' .. c .. '.png'; 29 + }) 30 +end 31 + 32 +minetest.register_craftitem('sorcery:crucible_clay_molding', { 33 + description = sorcery.lib.str.capitalize('Crucible molding'); 34 + inventory_image = 'sorcery_crucible_clay_molding.png'; 35 +}) 36 + 37 +minetest.register_craft { 38 + recipe = { 39 + { 'default:clay_lump', '', 'default:clay_lump'}; 40 + { 'default:clay_lump', '', 'default:clay_lump'}; 41 + { 'default:clay_lump', 'default:clay_lump', 'default:clay_lump'}; 42 + }; 43 + output = 'sorcery:crucible_clay_molding'; 44 +} 45 +minetest.register_craft { 46 + type = 'shapeless'; 47 + recipe = { 'sorcery:crucible_clay_molding' }; 48 + output = 'default:clay_lump 7'; 49 +} 50 +minetest.register_craft { 51 + type = 'cooking'; 52 + recipe = 'sorcery:crucible_clay_molding'; 53 + cooktime = 40; 54 + output = 'sorcery:crucible_clay'; 55 +} 56 + 57 +local burn_layout = function(v) 58 + local layouts = { 59 + [1] = {w = 1, h = 1}; [2] = {w = 2, h = 1}; [3] = {w = 3, h = 1}; 60 + [4] = {w = 2, h = 2}; [5] = {w = 3, h = 2}; [6] = {w = 3, h = 2}; 61 + [7] = {w = 4, h = 2}; [8] = {w = 4, h = 2}; [9] = {w = 3, h = 3}; 62 + } 63 + local inpos = { x = 2.8, y = 1 } 64 + local insize = layouts[v.in] 65 + local outpos = { x = 5.2, y = 2.4 } 66 + local outsize = layouts[v.out] 67 + local fuelpos = { x = 2.8, y = 3.4 } 68 + local fuelsize = layouts[v.fuel] 69 + return string.format([[ 70 + list[context;input;%f,%f;%f,%f;] 71 + list[context;output;%f,%f;%f,%f;] 72 + list[context;fuel;%f,%f;%f,%f;] 73 + 74 + image[2.3,1.9;1,1;default_furnace_fire_bg.png^[lowpart:%u%%:default_furnace_fire_fg.png] 75 + image[3.2,1.9;1,1;gui_furnace_arrow_bg.png^[lowpart:%u%%:gui_furnace_arrow_fg.png^[transformR270] 76 + 77 + listring[context;output] listring[current_player;main] 78 + listring[context;input] listring[current_player;main] 79 + listring[context;fuel] listring[current_player;main] 80 + ]], 81 + 82 + --input 83 + inpos.x - insize.w/2, -- pos 84 + inpos.y - insize.h/2, 85 + insize.w, insize.h, -- size 86 + --output 87 + outpos.x - outsize.w/2, -- pos 88 + outpos.y - outsize.h/2, 89 + outsize.w, outsize.h, -- size 90 + --fuel 91 + fuelpos.x - fuelsize.w/2, -- pos 92 + fuelpos.y - fuelsize.h/2, 93 + fuelsize.w, fuelsize.h, -- size 94 + 95 + v.burn, v.prog 96 + ) 97 +end 98 + 99 +local kiln_formspec = function(kind, fuel_progress, cook_progress) 100 + return [[ 101 + size[8,8] 102 + list[current_player;main;0,4.2;8,4] 103 + list[context;wax;0,2;1,1] 104 + ]] .. burn_layout{ 105 + in = kind.size^2; 106 + out = kind.outsize; 107 + fuel = kind.fuelsize; 108 + burn = fuel_progress; 109 + prog = cook_progress; 110 + } 111 +end 112 + 113 +local smelter_formspec = function(kind, fuel_progress, smelt_progress) 114 + return [[ 115 + size[8,8] 116 + list[current_player;main;0,4.2;8,4] 117 + ]] .. burn_layout { 118 + in = kind.size; 119 + out = kind.outsize; 120 + fuel = kind.fuelsize; 121 + burn = fuel_progress; 122 + prog = smelt_progress; 123 + } 124 +end 125 + 126 +local find_recipe = function(inv) 127 + local mix = {} 128 + local count = 0 129 + for i=1,inv:get_size('input') do 130 + local m = inv:get_stack('input',i) 131 + if m:is_empty() then goto skip end 132 + local l = sorcery.data.metallookup[m:get_name()] 133 + if not l then return false end 134 + mix[l.id] = (mix[l.id] or 0) + l.value 135 + count = count + l.value 136 + ::skip::end 137 + -- everything is metal, we've finished summing it up. 138 + -- let's see if the assembled items match the ratio 139 + -- specified in any of the smelting recipes. 140 + local matches = 0 141 + for _,rec in pairs(sorcery.data.alloys) do 142 + local fac = nil 143 + local meltpoint = 1 144 + if rec.metals == nil then goto skip_recipe end 145 + for metal, ratio in pairs(rec.metals) do 146 + if mix[metal] and mix[metal] % ratio == 0 then 147 + if fac then 148 + if mix[metal] / ratio ~= fac then goto skip_recipe end 149 + else fac = math.floor(mix[metal] / ratio) end 150 + local m = sorcery.data.metals[metal] 151 + if m.meltpoint then 152 + meltpoint = math.max(meltpoint, m.meltpoint) end 153 + else goto skip_recipe end 154 + end 155 + do return rec, count, fac, meltpoint end 156 + ::skip_recipe::end 157 + return false 158 +end 159 + 160 +local update_smelter = function(pos) 161 + local meta = minetest.get_meta(pos) 162 + local inv = meta:get_inventory() 163 + local proto = minetest.registered_nodes[minetest.get_node(pos).name]._proto 164 + local recipe, count, factor, meltpoint = find_recipe(inv) 165 + if recipe and proto.temp >= meltpoint then 166 + minetest.get_node_timer(pos):start(1) 167 + else 168 + meta:set_float('burntime',0) 169 + end 170 +end 171 + 172 +local smelter_step = function(kind,active,pos,delta) 173 + local meta = minetest.get_meta(pos) 174 + local inv = meta:get_inventory() 175 + local recipe, count, factor = find_recipe(inv) 176 + local cooktime 177 + local elapsed = meta:get_float('burntime') + delta 178 + meta:set_float('burnleft',meta:get_float('burnleft') - delta) 179 + if (not active) and (not recipe) then return false end 180 + if meta:get_float('burnleft') <= 0 or not active then 181 + if recipe then 182 + local burn, frep = minetest.get_craft_result { 183 + method = 'fuel', width = 1; 184 + items = { inv:get_stack('fuel',1) }; 185 + } 186 + if burn.time == 0 then goto nofuel end 187 + inv:set_stack('fuel', 1, frep.items[1]) 188 + meta:set_float('burnleft',burn.time) 189 + meta:set_float('burnmax',burn.time) 190 + if not active then 191 + minetest.swap_node(pos, 192 + sorcery.lib.tbl.merge(minetest.get_node(pos), { 193 + name = kind.id .. '_active' 194 + })) 195 + active = true 196 + end 197 + else goto nofuel end 198 + end 199 + 200 + if not recipe then goto update end 201 + 202 + cooktime = ((recipe.cooktime / fragments_per_ingot) * count) / factor 203 + if elapsed >= cooktime then 204 + elapsed = 0 205 + -- remove used items 206 + for i=1,inv:get_size('input') do 207 + local s = inv:get_stack('input',i) 208 + if s:is_empty() then goto skip end 209 + s:take_item(1) inv:set_stack('input',i,s) 210 + ::skip::end 211 + 212 + local outstack 213 + if count % fragments_per_ingot == 0 then 214 + outstack = ItemStack { 215 + name = sorcery.data.metals[recipe.output].ingot or 'sorcery:' .. recipe.output .. '_ingot'; 216 + count = count / fragments_per_ingot; 217 + } 218 + else 219 + outstack = ItemStack { 220 + name = 'sorcery:fragment_' .. recipe.output; 221 + count = count; 222 + } 223 + end 224 + 225 + local leftover = inv:add_item('output',outstack) 226 + if not leftover:is_empty() then 227 + minetest.add_item(pos, leftover) 228 + end 229 + end 230 + 231 + ::update:: 232 + meta:set_float('burntime',elapsed) 233 + meta:set_string('formspec', smelter_formspec(kind, 234 + math.min(1, meta:get_float('burnleft') / 235 + meta:get_float('burnmax') 236 + ) * 100, -- fuel 237 + (cooktime and math.min(1, elapsed / cooktime) * 100) or 0 -- smelt 238 + )) 239 + do return active end 240 + 241 + ::nofuel:: 242 + if active then 243 + minetest.swap_node(pos, 244 + sorcery.lib.tbl.merge(minetest.get_node(pos), { name = kind.id })) 245 + end 246 + meta:set_float('burnleft',0) -- just in case 247 + ::noburn:: 248 + meta:set_float('burntime',0) -- just in case 249 + meta:set_string('formspec', smelter_formspec(kind, 0, 0)) 250 + return false 251 +end 252 +local register_kiln = function(kind) 253 + local box = { 254 + open = { 255 + type = 'fixed'; 256 + fixed = { 257 + -0.5,-0.5,-0.5, 258 + 0.5, 1.6, 0.5 259 + }; 260 + }; 261 + closed = { 262 + type = 'fixed'; 263 + fixed = { 264 + -0.5,-0.5,-0.5, 265 + 0.5, 0.7, 0.5 266 + }; 267 + }; 268 + } 269 + local id = 'sorcery:kiln_' .. kind.material 270 + local metal = sorcery.data.metals[kind.material] 271 + -- use some iffy heuristics to guess the texture 272 + local metaltex 273 + if kind.material == 'clay' then 274 + metaltex = 'default_brick.png'; 275 + else 276 + metaltex = (metal.img and metal.img.block) or 277 + (metal.ingot and 'default_' .. kind.material .. '_block.png') or 278 + sorcery.lib.image('default_steel_block.png'):multiply(sorcery.lib.color(metal.tone)):render(); 279 + end 280 + local tex = { 281 + open = { 282 + 'default_furnace_front.png'; 283 + metaltex; 284 + 'default_copper_block.png'; 285 + 'default_stone.png'; 286 + }; 287 + closed = { 288 + 'default_furnace_front_active.png'; 289 + 'default_copper_block.png'; 290 + metaltex; 291 + 'default_stone.png'; 292 + }; 293 + }; 294 + for _,state in pairs{'open','closed'} do 295 + local id_closed = id .. '_closed' 296 + local id_current = (state == 'closed' and id_closed) or id 297 + local desc = sorcery.lib.str.capitalize(kind.temp_name) .. ' kiln'; 298 + minetest.register_node(id_current, { 299 + _active = (state == 'closed'); 300 + _proto = kind; 301 + description = desc; 302 + drawtype = "mesh"; 303 + mesh = 'sorcery-kiln-' .. state .. '.obj'; 304 + drop = id; 305 + sunlight_propagates = true; 306 + paramtype1 = 'light'; 307 + paramtype2 = 'facedir'; 308 + selection_box = box[state]; 309 + collision_box = box[state]; 310 + tiles = tex[state]; 311 + light_source = (state == 'closed' and 7) or 0; 312 + on_construct = function(pos) 313 + local meta = minetest.get_meta(pos) 314 + local inv = meta:get_inventory() 315 + inv:set_size('input', kind.size^2) 316 + inv:set_size('output', kind.outsize) 317 + inv:set_size('fuel', kind.fuelsize) 318 + inv:set_size('wax', 1) 319 + 320 + meta:set_float('burnleft',0) 321 + meta:set_float('burnmax',0) 322 + meta:set_float('burntime',0) 323 + 324 + meta:set_string('infotext',desc) 325 + meta:set_string('formspec',kiln_formspec(kind,0,0)) 326 + end; 327 + on_timer = function(pos,delta) 328 + end; 329 + 330 + on_metadata_inventory_put = function(pos) 331 + minetest.get_node_timer(pos):start(1) end; 332 + on_metadata_inventory_move = function(pos) 333 + minetest.get_node_timer(pos):start(1) end; 334 + on_metadata_inventory_take = function(pos) 335 + minetest.get_node_timer(pos):start(1) end; 336 + }) 337 + end 338 + local ingot 339 + if kind.material == 'clay' then 340 + ingot = 'default:clay_brick'; 341 + else 342 + ingot = metal.ingot or 'sorcery:' .. kind.material .. '_ingot' 343 + end 344 + minetest.register_craft = { 345 + output = id_open; 346 + recipe = { 347 + {'default:copper_ingot', 'default:copper_ingot', 'default:copper_ingot'}; 348 + {ingot,'',ingot}; 349 + {ingot,'default:furnace',ingot}; 350 + }; 351 + } 352 +end 353 + 354 +local register_smelter = function(kind) 355 + local recipe = {{},{}; 356 + {'default:stone','default:furnace','default:stone'}; 357 + } do 358 + local on = kind.crucible 359 + local ti = 'default:tin_ingot' 360 + local cu = 'default:copper_ingot' 361 + local crucmap = { 362 + [2] = { {cu,cu,cu}, {on,ti,on} }; 363 + [3] = { {cu,on,cu}, {on,ti,on} }; 364 + [4] = { {on,cu,on}, {on,ti,on} }; 365 + [5] = { {on,cu,on}, {on,on,on} }; 366 + [6] = { {on,on,on}, {on,on,on} }; 367 + }; 368 + for y=1,2 do recipe[y] = crucmap[kind.size][y] end 369 + end 370 + 371 + local desc = 'smelter'; 372 + if kind.temp_name then desc = kind.temp_name .. ' ' .. desc end 373 + if kind.size_name then desc = kind.size_name .. ' ' .. desc end 374 + desc = sorcery.lib.str.capitalize(desc); 375 + local id = 'sorcery:smelter_' .. kind.material .. kind.size_name 376 + kind.id = id 377 + for _, active in pairs {false, true} do 378 + minetest.register_node((active and id .. '_active') or id, { 379 + _proto = kind; 380 + description = desc; 381 + drop = id; 382 + groups = { cracky = 2; }; 383 + paramtype2 = 'facedir'; 384 + light_source = (active and 9) or 0; 385 + on_construct = function(pos) 386 + local meta = minetest.get_meta(pos) 387 + local inv = meta:get_inventory() 388 + inv:set_size('input',kind.size) 389 + inv:set_size('output',kind.outsize) 390 + inv:set_size('fuel',kind.fuelsize) 391 + meta:set_string('infotext', desc) 392 + meta:set_string('formspec', smelter_formspec(kind, 0, 0)) 393 + meta:set_float('burnleft',0) 394 + meta:set_float('burnmax',0) 395 + meta:set_float('burntime',0) 396 + end; 397 + on_metadata_inventory_put = update_smelter; 398 + on_metadata_inventory_move = update_smelter; 399 + on_metadata_inventory_take = update_smelter; 400 + on_timer = function(pos,delta) return smelter_step(kind, active, pos, delta) end; 401 + -- allow_metadata_inventory_put = function(pos, listname, index, stack, player) 402 + -- end; 403 + tiles = { 404 + 'sorcery_smelter_top_' .. tostring(kind.size) .. '.png'; 405 + 'sorcery_smelter_bottom.png'; 406 + 'sorcery_smelter_side.png'; 407 + 'sorcery_smelter_side.png'; 408 + 'sorcery_smelter_side.png'; 409 + 'sorcery_smelter_front' .. ((active and '_hot') or '') .. '.png'; 410 + }; 411 + }) 412 + end 413 + minetest.register_craft { 414 + recipe = recipe; 415 + output = id; 416 + } 417 +end 418 + 419 +for _, t in pairs { 420 + {1, nil, 'clay'}; 421 + {2, 'hot','aluminum'}; 422 + {3, 'volcanic','platinum'}; 423 + {4, 'stellar','duridium'}; 424 + {5, 'nova','impervium'}; 425 +} do register_kiln { 426 + temp = t[1], temp_name = t[2]; 427 + material = t[3]; 428 + size = 3, outsize = 4, fuelsize = 1; -- future-proofing 429 + } 430 + 431 + for _, s in pairs { 432 + {2, 'small'}; 433 + {3, 'large'}; 434 + {4, 'grand'}; 435 + } do register_smelter { 436 + size = s[1], size_name = s[2]; 437 + temp = t[1], temp_name = t[2]; 438 + material = t[3]; 439 + crucible = 'sorcery:crucible_' .. t[3]; 440 + outsize = 4, fuelsize = 1; -- future-proofing 441 + } end 442 +end
Modified init.lua from [c38fa912b9] to [5c9fa3f240].
49 49 'register'; 50 50 } 51 51 52 52 for _,u in pairs { 53 53 'leylines'; 'ores'; 'gems'; 54 54 'potions'; 'infuser'; 'altar'; 'wands'; 55 55 'tools'; 'enchanter'; 'harvester'; 56 - 'smelter'; 'entities'; 'recipes'; 'coins'; 57 - 'interop'; 56 + 'metallurgy-hot'; 'entities'; 'recipes'; 57 + 'coins'; 'interop'; 'tnodes'; 58 58 } do sorcery.load(u) end
Modified lib/color.lua from [16b55419da] to [e07c3f3979].
43 43 end; 44 44 45 45 cast = { 46 46 number = function(n) return { 47 47 red = n; green = n; blue = n; 48 48 } end; 49 49 table = function(t) return { 50 - red = t[1]; green = t[2]; blue = t[3]; 50 + red = t[1]; green = t[2]; blue = t[3]; alpha = t[4]; 51 51 } end; 52 52 }; 53 53 54 54 construct = function(r,g,b,a) 55 55 local clip = function(v) 56 56 return math.max(0,math.min(255,v)) 57 + end; 58 + local from_hsl = function(hsl, alpha) 59 + -- Based on the algorithm in Computer Graphics: Principles and Practice, by 60 + -- James D. Foley et. al., 2nd ed., p. 596 61 + -- Degree version, though radian is more natural, I don't want to translate it yet 62 + local h = hsl.hue 63 + local s = hsl.saturation 64 + local l = hsl.luminosity 65 + local value = function(n1, n2, hue) 66 + if hue > 360 then 67 + hue = hue - 360 68 + elseif hue < 0 then 69 + hue = hue + 360 70 + end 71 + if hue < 60 then 72 + return n1 + (n2 - n1) * hue/60 73 + elseif hue < 180 then 74 + return n2 75 + elseif hue < 240 then 76 + return n1 + (n2 - n1) * (240 - hue)/60 77 + else 78 + return n1 79 + end 80 + end 81 + local m2 82 + if l < 0.5 then 83 + m2 = l * (1 + s) 84 + else 85 + m2 = l + s - l * s 86 + end 87 + local m1 = 2 * l - m2 88 + if s == 0 then 89 + -- Achromatic, there is no hue 90 + -- In book this errors if hue is not undefined, but we set hue to 0 in this case, not nil or something, so 91 + return color(l, l, l, alpha) 92 + else 93 + -- Chromatic case, so there is a hue 94 + return color( 95 + clip(value(m1, m2, h + 120)*255), 96 + clip(value(m1, m2, h)*255), 97 + clip(value(m1, m2, h - 120)*255), 98 + alpha 99 + ) 100 + end 57 101 end; 58 102 local warp = function(f) 59 103 return function(self, ...) 60 104 local n = color(self) 61 105 f(n, ...) 62 106 return n 63 107 end; ................................................................................ 71 115 minetest.colorize(self:hex(), text) 72 116 end; 73 117 74 118 luminosity = function(self) return 75 119 (self.red + self.green + self.blue) / 3 76 120 end; 77 121 78 - readable = function(self, target) 79 - target = target or 200 80 - local lum = self:luminosity() 81 - if lum < target then 82 - local f = 1.0 + (target - lum) / 255 83 - local nc = self:brighten(f * 1.5) 84 - -- i don't know why the *1.5 is necessary. it's 85 - -- an ugly hack to work around broken math, 86 - -- because i'm too much of a mathtard to actually 87 - -- find what's wrong 88 - return nc 122 + to_hsl = function(self) 123 + -- Based on the algorithm in Computer Graphics: Principles and Practice, by 124 + -- James D. Foley et. al., 2nd ed., p. 595 125 + -- We need the rgb between 0 and 1 126 + local r = self.red/255 127 + local g = self.green/255 128 + local b = self.blue/255 129 + local max = math.max(r, g, b) 130 + local min = math.min(r, g, b) 131 + local luminosity = (max + min)/2 132 + local hue = 0 133 + local saturation = 0 134 + if max == min then 135 + -- Achromatic case, because r=g=b 136 + saturation = 0 137 + hue = 0 -- Undefined, so just replace w/ 0 for usability 89 138 else 90 - return self 139 + -- Chromatic case 140 + if luminosity <= 0.5 then 141 + saturation = (max - min)/(max + min) 142 + else 143 + saturation = (max - min)/(2 - max - min) 144 + end 145 + -- Next calculate the hue 146 + local delta = max - min 147 + if r == max then 148 + hue = (g - b)/delta 149 + elseif g == max then 150 + hue = 2 + (b - r)/delta 151 + else -- blue must be max, so no point in checking 152 + hue = 4 + (r - g)/delta 153 + end 154 + hue = hue * 60 -- degrees 155 + --hue = hue * (math.pi / 3) -- for hue in radians instead of degrees 156 + if hue < 0 then 157 + hue = hue + 2 * math.pi 158 + end 91 159 end 160 + -- print("r"..self.red.."g"..self.green.."b"..self.blue.." is h"..hue.."s"..saturation.."l"..luminosity) 161 + local temp = from_hsl({hue=hue,saturation=saturation,luminosity=luminosity},self.alpha) 162 + -- print("back is r"..temp.red.."g"..temp.green.."b"..temp.blue) 163 + return { hue = hue, saturation = saturation, luminosity = luminosity } 164 + end; 165 + 166 + readable = function(self, target) 167 + target = target or 0.5 168 + local hsl = self:to_hsl() 169 + hsl.luminosity = target 170 + return from_hsl(hsl, self.alpha) 92 171 end; 93 172 94 173 bg = function(self, text) return 95 174 text .. minetest.get_background_escape_sequence(self:hex()) 96 175 end; 97 176 98 177 fade = warp(function(new, fac) 99 178 new.alpha = math.min(255, (new.alpha or 255) * fac) 100 179 end); 101 180 102 - brighten = warp(function(new, fac) 103 - local lum = new:luminosity() 104 - local newlum = lum * fac 105 - local delta = (newlum - lum) 106 - new.red = clip(new.red + delta) 107 - new.blue = clip(new.blue + delta) 108 - new.green = clip(new.green + delta) 109 - end); 181 + brighten = function(self, fac) 182 + -- Use HSL to brighten 183 + -- To HSL 184 + local hsl = self:to_hsl() 185 + -- Do the calculation, clamp to 0-1 instead of the clamp fn 186 + hsl.luminosity = math.min(math.max(hsl.luminosity * fac, 0), 1) 187 + -- Turn back into RGB color 188 + local t = from_hsl(hsl, self.alpha) 189 + -- print("brighten is r"..t.red.."g"..t.green.."b"..t.blue) 190 + return from_hsl(hsl, self.alpha) 191 + end; 110 192 111 193 darken = warp(function(new, fac) 194 + -- TODO: is there any point to this being different than brighten? Probably especially not now. 112 195 new.red = clip(new.red - (new.red * fac)) 113 196 new.blue = clip(new.blue - (new.blue * fac)) 114 197 new.green = clip(new.green - (new.green * fac)) 115 198 end); 116 199 } 117 200 if g == nil then 118 201 if type(r) == 'string' then
Modified lib/marshal.lua from [9b9bc45df4] to [9fd6c4419a].
61 61 end 62 62 return str 63 63 end; 64 64 dec = function(str) 65 65 local val = 0 66 66 for i = 0, bytes-1 do 67 67 local b = string.byte(str,bytes - i) 68 - val = (val * 0x100) + b 68 + val = (val * 0x100) + (b or 0) 69 69 end 70 70 if signed then 71 71 if val > spoint then val = 0 - (val - spoint) end 72 72 end 73 73 return val, string.sub(str, 1 + bytes) 74 74 end; 75 75 }
Modified lib/str.lua from [4468d8dfeb] to [e883d78392].
1 +local sanitable = { 2 + ['\xfe'] = '\xf0'; 3 + ['\1'] = '\xf1'; 4 + ['\2'] = '\xf2'; 5 + ['\3'] = '\xf3'; 6 + 7 + ['\xf0'] = '\xfe'; 8 + ['\xf1'] = '\1'; 9 + ['\xf2'] = '\2'; 10 + ['\xf3'] = '\3'; 11 +} 1 12 return { 2 13 capitalize = function(str) 3 14 return string.upper(string.sub(str, 1,1)) .. string.sub(str, 2) 4 15 end; 5 16 6 17 rand = function(min,max) 7 18 if not min then min = 16 end ................................................................................ 32 43 str = string.sub(str, 2) 33 44 end 34 45 if string.sub(str, #str,#str) == ' ' then 35 46 str = string.sub(str, 1, #str - 1) 36 47 end 37 48 return str 38 49 end; 50 + 51 + meta_armor = function(str,mark_struct) 52 + -- binary values stored in metadata need to be sanitized so 53 + -- they don't contain values that will disrupt parsing of the 54 + -- KV store, as minetest (stupidly) uses in-band signalling 55 + local sanitized = string.gsub(str, '[\xfe\1\2\3]', function(char) 56 + return '\xfe' .. sanitable[char] 57 + end) 58 + if sanitized ~= str and mark_struct then 59 + -- use different type code to mark struct headers for 60 + -- back-compat 61 + return string.gsub(sanitized,'^\xfe\xf0\x99','\xfe\x98') 62 + else return sanitized end 63 + end; 64 + meta_dearmor = function(str,cond) 65 + local dearmor = function(s) 66 + return string.gsub(s, '\xfe([\xf0\xf1\xf2\xf3])', function(char) 67 + return sanitable[char] 68 + end) 69 + end 70 + if cond then 71 + if string.sub(str,1,2) == '\xfe\x98' then 72 + return dearmor(string.gsub(str,'^\xfe\x98','\xfe\xf0\x99')) 73 + else return str end 74 + else return dearmor(str) end 75 + end; 39 76 }
Modified lib/ui.lua from [6423ac3b4f] to [a001c55363].
20 20 else 21 21 c = l.color(dui.colors.neutral) 22 22 end 23 23 24 24 str = str .. '\n ' .. c:fmt('* ') 25 25 26 26 if prop.title then 27 - str = str .. c:brighten(1.5):fmt(prop.title) .. ': ' 27 + str = str .. c:brighten(1.3):fmt(prop.title) .. ': ' 28 28 end 29 29 30 30 local lines = minetest.wrap_text(prop.desc, 50, true) 31 31 str = str .. c:fmt(lines[1]) 32 32 for i=2,#lines do 33 33 str = str .. '\n' .. string.rep(' ',5) .. c:fmt(lines[i]) 34 34 end 35 35 end 36 36 end 37 37 return str 38 38 end; 39 39 }
Added metallurgy-hot.lua version [3c9b60f14d].
1 +-- alloying furnace 2 +-- 3 +-- there are several kinds of alloy furnace, with varying 4 +-- capabilities. the simplest can alloy two simple metals; 5 +-- the most complex can alloy four high-grade metals such 6 +-- as titanium, platinum, iridium, or levitanium. 7 +-- 8 +-- furnace recipes follow a pattern: the number of crucibles 9 +-- determines the input slots, the type of crucible determines 10 +-- how hot the furnace can get, and various other components 11 +-- (like a coolant circulator) can be added to allow the 12 +-- creation of exotic metals. 13 +-- 14 +-- alloy furnaces produce ingots that can later be melted down 15 +-- again and cast into a mold to produce items of particular 16 +-- shapes. 17 + 18 +-- there are four kinds of crucibles: clay, aluminum, platinum, 19 +-- and duranium. clay crucibles are made by molding clay into 20 +-- the proper shape and then firing it in a furnace. others 21 +-- are made by casting. 22 + 23 +local fragments_per_ingot = 4 24 + 25 +for _, c in pairs { 'clay', 'aluminum', 'platinum', 'duranium' } do 26 + minetest.register_craftitem('sorcery:crucible_' .. c, { 27 + description = sorcery.lib.str.capitalize(c .. ' crucible'); 28 + inventory_image = 'sorcery_crucible_' .. c .. '.png'; 29 + }) 30 +end 31 + 32 +minetest.register_craftitem('sorcery:crucible_clay_molding', { 33 + description = sorcery.lib.str.capitalize('Crucible molding'); 34 + inventory_image = 'sorcery_crucible_clay_molding.png'; 35 +}) 36 + 37 +minetest.register_craft { 38 + recipe = { 39 + { 'default:clay_lump', '', 'default:clay_lump'}; 40 + { 'default:clay_lump', '', 'default:clay_lump'}; 41 + { 'default:clay_lump', 'default:clay_lump', 'default:clay_lump'}; 42 + }; 43 + output = 'sorcery:crucible_clay_molding'; 44 +} 45 +minetest.register_craft { 46 + type = 'shapeless'; 47 + recipe = { 'sorcery:crucible_clay_molding' }; 48 + output = 'default:clay_lump 7'; 49 +} 50 +minetest.register_craft { 51 + type = 'cooking'; 52 + recipe = 'sorcery:crucible_clay_molding'; 53 + cooktime = 40; 54 + output = 'sorcery:crucible_clay'; 55 +} 56 + 57 +local burn_layout = function(v) 58 + local layouts = { 59 + [1] = {w = 1, h = 1}; [2] = {w = 2, h = 1}; [3] = {w = 3, h = 1}; 60 + [4] = {w = 2, h = 2}; [5] = {w = 3, h = 2}; [6] = {w = 3, h = 2}; 61 + [7] = {w = 4, h = 2}; [8] = {w = 4, h = 2}; [9] = {w = 3, h = 3}; 62 + } 63 + local inpos = { x = 2.8, y = 1 } 64 + local insize = layouts[v.inp] 65 + local outpos = { x = 5.2, y = 2.4 } 66 + local outsize = layouts[v.out] 67 + local fuelpos = { x = 2.8, y = 3.4 } 68 + local fuelsize = layouts[v.fuel] 69 + return string.format([[ 70 + list[context;input;%f,%f;%f,%f;] 71 + list[context;output;%f,%f;%f,%f;] 72 + list[context;fuel;%f,%f;%f,%f;] 73 + 74 + image[2.3,1.9;1,1;default_furnace_fire_bg.png^[lowpart:%u%%:default_furnace_fire_fg.png] 75 + image[3.2,1.9;1,1;gui_furnace_arrow_bg.png^[lowpart:%u%%:gui_furnace_arrow_fg.png^[transformR270] 76 + 77 + listring[context;output] listring[current_player;main] 78 + listring[context;input] listring[current_player;main] 79 + listring[context;fuel] listring[current_player;main] 80 + ]], 81 + 82 + --input 83 + inpos.x - insize.w/2, -- pos 84 + inpos.y - insize.h/2, 85 + insize.w, insize.h, -- size 86 + --output 87 + outpos.x - outsize.w/2, -- pos 88 + outpos.y - outsize.h/2, 89 + outsize.w, outsize.h, -- size 90 + --fuel 91 + fuelpos.x - fuelsize.w/2, -- pos 92 + fuelpos.y - fuelsize.h/2, 93 + fuelsize.w, fuelsize.h, -- size 94 + 95 + v.burn, v.prog 96 + ) 97 +end 98 + 99 +local kiln_formspec = function(kind, fuel_progress, cook_progress) 100 + return [[ 101 + size[8,8] 102 + list[current_player;main;0,4.2;8,4] 103 + list[context;wax;0,2;1,1] 104 + ]] .. burn_layout{ 105 + inp = kind.size^2; 106 + out = kind.outsize; 107 + fuel = kind.fuelsize; 108 + burn = fuel_progress; 109 + prog = cook_progress; 110 + } 111 +end 112 + 113 +local smelter_formspec = function(kind, fuel_progress, smelt_progress) 114 + return [[ 115 + size[8,8] 116 + list[current_player;main;0,4.2;8,4] 117 + ]] .. burn_layout { 118 + inp = kind.size; 119 + out = kind.outsize; 120 + fuel = kind.fuelsize; 121 + burn = fuel_progress; 122 + prog = smelt_progress; 123 + } 124 +end 125 + 126 +local find_recipe = function(inv) 127 + local mix = {} 128 + local count = 0 129 + for i=1,inv:get_size('input') do 130 + local m = inv:get_stack('input',i) 131 + if m:is_empty() then goto skip end 132 + local l = sorcery.data.metallookup[m:get_name()] 133 + if not l then return false end 134 + mix[l.id] = (mix[l.id] or 0) + l.value 135 + count = count + l.value 136 + ::skip::end 137 + -- everything is metal, we've finished summing it up. 138 + -- let's see if the assembled items match the ratio 139 + -- specified in any of the smelting recipes. 140 + local matches = 0 141 + for _,rec in pairs(sorcery.data.alloys) do 142 + local fac = nil 143 + local meltpoint = 1 144 + if rec.metals == nil then goto skip_recipe end 145 + for metal, ratio in pairs(rec.metals) do 146 + if mix[metal] and mix[metal] % ratio == 0 then 147 + if fac then 148 + if mix[metal] / ratio ~= fac then goto skip_recipe end 149 + else fac = math.floor(mix[metal] / ratio) end 150 + local m = sorcery.data.metals[metal] 151 + if m.meltpoint then 152 + meltpoint = math.max(meltpoint, m.meltpoint) end 153 + else goto skip_recipe end 154 + end 155 + do return rec, count, fac, meltpoint end 156 + ::skip_recipe::end 157 + return false 158 +end 159 + 160 +local update_smelter = function(pos) 161 + local meta = minetest.get_meta(pos) 162 + local inv = meta:get_inventory() 163 + local proto = minetest.registered_nodes[minetest.get_node(pos).name]._proto 164 + local recipe, count, factor, meltpoint = find_recipe(inv) 165 + if recipe and proto.temp >= meltpoint then 166 + minetest.get_node_timer(pos):start(1) 167 + else 168 + meta:set_float('burntime',0) 169 + end 170 +end 171 + 172 +local smelter_step = function(kind,active,pos,delta) 173 + local meta = minetest.get_meta(pos) 174 + local inv = meta:get_inventory() 175 + local recipe, count, factor = find_recipe(inv) 176 + local cooktime 177 + local elapsed = meta:get_float('burntime') + delta 178 + meta:set_float('burnleft',meta:get_float('burnleft') - delta) 179 + if (not active) and (not recipe) then return false end 180 + if meta:get_float('burnleft') <= 0 or not active then 181 + if recipe then 182 + local burn, frep = minetest.get_craft_result { 183 + method = 'fuel', width = 1; 184 + items = { inv:get_stack('fuel',1) }; 185 + } 186 + if burn.time == 0 then goto nofuel end 187 + inv:set_stack('fuel', 1, frep.items[1]) 188 + meta:set_float('burnleft',burn.time) 189 + meta:set_float('burnmax',burn.time) 190 + if not active then 191 + minetest.swap_node(pos, 192 + sorcery.lib.tbl.merge(minetest.get_node(pos), { 193 + name = kind.id .. '_active' 194 + })) 195 + active = true 196 + end 197 + else goto nofuel end 198 + end 199 + 200 + if not recipe then goto update end 201 + 202 + cooktime = ((recipe.cooktime / fragments_per_ingot) * count) / factor 203 + if elapsed >= cooktime then 204 + elapsed = 0 205 + -- remove used items 206 + for i=1,inv:get_size('input') do 207 + local s = inv:get_stack('input',i) 208 + if s:is_empty() then goto skip end 209 + s:take_item(1) inv:set_stack('input',i,s) 210 + ::skip::end 211 + 212 + local outstack 213 + if count % fragments_per_ingot == 0 then 214 + outstack = ItemStack { 215 + name = sorcery.data.metals[recipe.output].ingot or 'sorcery:' .. recipe.output .. '_ingot'; 216 + count = count / fragments_per_ingot; 217 + } 218 + else 219 + outstack = ItemStack { 220 + name = 'sorcery:fragment_' .. recipe.output; 221 + count = count; 222 + } 223 + end 224 + 225 + local leftover = inv:add_item('output',outstack) 226 + if not leftover:is_empty() then 227 + minetest.add_item(pos, leftover) 228 + end 229 + end 230 + 231 + ::update:: 232 + meta:set_float('burntime',elapsed) 233 + meta:set_string('formspec', smelter_formspec(kind, 234 + math.min(1, meta:get_float('burnleft') / 235 + meta:get_float('burnmax') 236 + ) * 100, -- fuel 237 + (cooktime and math.min(1, elapsed / cooktime) * 100) or 0 -- smelt 238 + )) 239 + do return active end 240 + 241 + ::nofuel:: 242 + if active then 243 + minetest.swap_node(pos, 244 + sorcery.lib.tbl.merge(minetest.get_node(pos), { name = kind.id })) 245 + end 246 + meta:set_float('burnleft',0) -- just in case 247 + ::noburn:: 248 + meta:set_float('burntime',0) -- just in case 249 + meta:set_string('formspec', smelter_formspec(kind, 0, 0)) 250 + return false 251 +end 252 +local register_kiln = function(kind) 253 + local box = { 254 + open = { 255 + type = 'fixed'; 256 + fixed = { 257 + -0.5,-0.5,-0.5, 258 + 0.5, 1.6, 0.5 259 + }; 260 + }; 261 + closed = { 262 + type = 'fixed'; 263 + fixed = { 264 + -0.5,-0.5,-0.5, 265 + 0.5, 0.7, 0.5 266 + }; 267 + }; 268 + } 269 + local id = 'sorcery:kiln_' .. kind.material 270 + local metal = sorcery.data.metals[kind.material] 271 + -- use some iffy heuristics to guess the texture 272 + local metaltex 273 + if kind.material == 'clay' then 274 + metaltex = 'default_brick.png'; 275 + else 276 + metaltex = (metal.img and metal.img.block) or 277 + (metal.ingot and 'default_' .. kind.material .. '_block.png') or 278 + sorcery.lib.image('default_steel_block.png'):multiply(sorcery.lib.color(metal.tone)):render(); 279 + end 280 + local tex = { 281 + open = { 282 + 'default_furnace_front.png'; 283 + metaltex; 284 + 'default_copper_block.png'; 285 + 'default_stone.png'; 286 + }; 287 + closed = { 288 + 'default_furnace_front_active.png'; 289 + 'default_copper_block.png'; 290 + metaltex; 291 + 'default_stone.png'; 292 + }; 293 + }; 294 + for _,state in pairs{'open','closed'} do 295 + local id_closed = id .. '_closed' 296 + local id_current = (state == 'closed' and id_closed) or id 297 + local desc = (kind.temp_name and sorcery.lib.str.capitalize(kind.temp_name) .. ' kiln') or 'Kiln' 298 + minetest.register_node(id_current, { 299 + description = desc; 300 + drawtype = "mesh"; 301 + mesh = 'sorcery-kiln-' .. state .. '.obj'; 302 + drop = id; 303 + groups = { 304 + cracky = (state == 'open' and 2) or nil; 305 + }; 306 + sunlight_propagates = true; 307 + paramtype1 = 'light'; 308 + paramtype2 = 'facedir'; 309 + selection_box = box[state]; 310 + collision_box = box[state]; 311 + tiles = tex[state]; 312 + light_source = (state == 'closed' and 7) or 0; 313 + on_construct = function(pos) 314 + local meta = minetest.get_meta(pos) 315 + local inv = meta:get_inventory() 316 + inv:set_size('input', kind.size^2) 317 + inv:set_size('output', kind.outsize) 318 + inv:set_size('fuel', kind.fuelsize) 319 + inv:set_size('wax', 1) 320 + 321 + meta:set_float('burnleft',0) 322 + meta:set_float('burnmax',0) 323 + meta:set_float('burntime',0) 324 + 325 + meta:set_string('infotext',desc) 326 + meta:set_string('formspec',kiln_formspec(kind,0,0)) 327 + end; 328 + on_timer = function(pos,delta) 329 + end; 330 + 331 + on_metadata_inventory_put = function(pos) 332 + minetest.get_node_timer(pos):start(1) end; 333 + on_metadata_inventory_move = function(pos) 334 + minetest.get_node_timer(pos):start(1) end; 335 + on_metadata_inventory_take = function(pos) 336 + minetest.get_node_timer(pos):start(1) end; 337 + }) 338 + end 339 + local ingot 340 + if kind.material == 'clay' then 341 + ingot = 'default:clay_brick'; 342 + else 343 + ingot = metal.ingot or 'sorcery:' .. kind.material .. '_ingot' 344 + end 345 + minetest.register_craft { 346 + output = id; 347 + recipe = { 348 + {'default:copper_ingot', 'default:copper_ingot', 'default:copper_ingot'}; 349 + {ingot,'',ingot}; 350 + {ingot,'default:furnace',ingot}; 351 + }; 352 + } 353 +end 354 + 355 +local register_smelter = function(kind) 356 + local recipe = {{},{}; 357 + {'default:stone','default:furnace','default:stone'}; 358 + } do 359 + local on = kind.crucible 360 + local ti = 'default:tin_ingot' 361 + local cu = 'default:copper_ingot' 362 + local crucmap = { 363 + [2] = { {cu,cu,cu}, {on,ti,on} }; 364 + [3] = { {cu,on,cu}, {on,ti,on} }; 365 + [4] = { {on,cu,on}, {on,ti,on} }; 366 + [5] = { {on,cu,on}, {on,on,on} }; 367 + [6] = { {on,on,on}, {on,on,on} }; 368 + }; 369 + for y=1,2 do recipe[y] = crucmap[kind.size][y] end 370 + end 371 + 372 + local desc = 'smelter'; 373 + if kind.temp_name then desc = kind.temp_name .. ' ' .. desc end 374 + if kind.size_name then desc = kind.size_name .. ' ' .. desc end 375 + desc = sorcery.lib.str.capitalize(desc); 376 + local id = 'sorcery:smelter_' .. kind.material .. kind.size_name 377 + kind.id = id 378 + for _, active in pairs {false, true} do 379 + minetest.register_node((active and id .. '_active') or id, { 380 + _proto = kind; 381 + description = desc; 382 + drop = id; 383 + groups = { 384 + cracky = (active and 2) or nil; 385 + }; 386 + paramtype2 = 'facedir'; 387 + light_source = (active and 9) or 0; 388 + on_construct = function(pos) 389 + local meta = minetest.get_meta(pos) 390 + local inv = meta:get_inventory() 391 + inv:set_size('input',kind.size) 392 + inv:set_size('output',kind.outsize) 393 + inv:set_size('fuel',kind.fuelsize) 394 + meta:set_string('infotext', desc) 395 + meta:set_string('formspec', smelter_formspec(kind, 0, 0)) 396 + meta:set_float('burnleft',0) 397 + meta:set_float('burnmax',0) 398 + meta:set_float('burntime',0) 399 + end; 400 + on_metadata_inventory_put = update_smelter; 401 + on_metadata_inventory_move = update_smelter; 402 + on_metadata_inventory_take = update_smelter; 403 + on_timer = function(pos,delta) return smelter_step(kind, active, pos, delta) end; 404 + -- allow_metadata_inventory_put = function(pos, listname, index, stack, player) 405 + -- end; 406 + tiles = { 407 + 'sorcery_smelter_top_' .. tostring(kind.size) .. '.png'; 408 + 'sorcery_smelter_bottom.png'; 409 + 'sorcery_smelter_side.png'; 410 + 'sorcery_smelter_side.png'; 411 + 'sorcery_smelter_side.png'; 412 + 'sorcery_smelter_front' .. ((active and '_hot') or '') .. '.png'; 413 + }; 414 + }) 415 + end 416 + minetest.register_craft { 417 + recipe = recipe; 418 + output = id; 419 + } 420 +end 421 + 422 +for _, t in pairs { 423 + {1, nil, 'clay'}; 424 + {2, 'hot','aluminum'}; 425 + {3, 'volcanic','platinum'}; 426 + {4, 'stellar','duridium'}; 427 + {5, 'nova','impervium'}; 428 +} do register_kiln { 429 + temp = t[1], temp_name = t[2]; 430 + material = t[3]; 431 + size = 3, outsize = 4, fuelsize = 1; -- future-proofing 432 + } 433 + 434 + for _, s in pairs { 435 + {2, 'small'}; 436 + {3, 'large'}; 437 + {4, 'grand'}; 438 + } do register_smelter { 439 + size = s[1], size_name = s[2]; 440 + temp = t[1], temp_name = t[2]; 441 + material = t[3]; 442 + crucible = 'sorcery:crucible_' .. t[3]; 443 + outsize = 4, fuelsize = 1; -- future-proofing 444 + } end 445 +end
Added models/sorcery-kiln-closed.obj version [fb9010b25d].
1 +# Blender v2.82 (sub 7) OBJ File: 'kiln.blend' 2 +# www.blender.org 3 +mtllib sorcery-kiln-closed.mtl 4 +o furnace-front_Cube.002 5 +v -0.288540 -0.410913 -0.500000 6 +v 0.288540 -0.410913 -0.500000 7 +v 0.288540 0.152026 -0.500000 8 +v -0.288540 0.152026 -0.500000 9 +vt 0.000000 0.987748 10 +vt 0.000000 0.012252 11 +vt 1.000000 0.012252 12 +vt 1.000000 0.987748 13 +vn 0.0000 0.0000 1.0000 14 +g furnace-front_Cube.002_furnace.001 15 +usemtl furnace.001 16 +s off 17 +f 4/1/1 1/2/1 2/3/1 3/4/1 18 +o bronze.001_bronze 19 +v 0.500000 0.593635 -0.500000 20 +v 0.500000 0.593635 0.500000 21 +v -0.500000 0.593635 -0.500000 22 +v -0.500000 0.593635 0.500000 23 +v 0.500000 0.365016 -0.500000 24 +v -0.500000 0.365016 0.500000 25 +v 0.500000 0.365016 0.500000 26 +v -0.500000 0.365016 -0.500000 27 +vt 1.000000 0.385690 28 +vt 1.000000 0.614310 29 +vt 0.000000 0.614310 30 +vt 0.000000 0.385690 31 +vt 1.000000 0.614310 32 +vt 1.000000 0.385690 33 +vt 1.000000 0.385690 34 +vt 1.000000 0.614310 35 +vt 0.000000 0.614310 36 +vt 0.000000 0.385690 37 +vt 0.000000 0.385690 38 +vt 0.000000 0.614310 39 +vt 0.000000 1.000000 40 +vt 1.000000 1.000000 41 +vt 1.000000 0.000000 42 +vt 0.000000 0.000000 43 +vt 1.000000 0.000000 44 +vt 1.000000 1.000000 45 +vt 0.000000 1.000000 46 +vt 0.000000 0.000000 47 +vn 0.0000 0.0000 1.0000 48 +vn -1.0000 0.0000 0.0000 49 +vn 1.0000 0.0000 0.0000 50 +vn 0.0000 0.0000 -1.0000 51 +vn -0.0000 -1.0000 0.0000 52 +vn 0.0000 1.0000 0.0000 53 +g bronze.001_bronze_bronze 54 +usemtl bronze 55 +s off 56 +f 11/5/2 6/6/2 8/7/2 10/8/2 57 +f 10/8/3 8/7/3 7/9/3 12/10/3 58 +f 9/11/4 5/12/4 6/13/4 11/14/4 59 +f 12/15/5 7/16/5 5/12/5 9/11/5 60 +f 12/17/6 9/18/6 11/19/6 10/20/6 61 +f 6/21/7 5/22/7 7/23/7 8/24/7 62 +o metal 63 +v 0.500000 -0.500000 -0.500000 64 +v 0.500000 -0.500000 0.500000 65 +v -0.500000 -0.500000 -0.500000 66 +v -0.500000 -0.500000 0.500000 67 +v 0.500000 -0.410913 -0.500000 68 +v -0.500000 -0.410913 0.500000 69 +v 0.500000 -0.410913 0.500000 70 +v -0.500000 -0.410913 -0.500000 71 +v -0.288539 -0.410913 -0.452614 72 +v 0.288539 -0.410913 -0.452614 73 +v -0.288540 -0.410913 -0.500000 74 +v 0.288540 -0.410913 -0.500000 75 +v 0.500000 0.593635 -0.500000 76 +v 0.500000 0.593635 0.500000 77 +v -0.500000 0.593635 -0.500000 78 +v -0.500000 0.593635 0.500000 79 +v 0.500000 0.692600 -0.500000 80 +v -0.500000 0.593635 0.500000 81 +v 0.500000 0.593635 -0.500000 82 +v -0.500000 0.593635 -0.500000 83 +v 0.500000 0.692600 0.500000 84 +v -0.500000 0.692600 0.500000 85 +v -0.500000 0.692600 -0.500000 86 +vt 0.000000 1.000000 87 +vt 1.000000 1.000000 88 +vt 1.000000 0.000000 89 +vt 0.000000 0.000000 90 +vt 0.000000 0.440608 91 +vt 0.000000 0.529696 92 +vt 0.333333 0.529696 93 +vt 0.666667 0.529696 94 +vt 1.000000 0.529696 95 +vt 1.000000 0.440608 96 +vt 0.000000 0.529696 97 +vt 0.000000 0.440608 98 +vt 0.000000 0.440608 99 +vt 0.000000 0.529696 100 +vt 1.000000 0.529696 101 +vt 1.000000 0.440608 102 +vt 1.000000 0.440608 103 +vt 1.000000 0.529696 104 +vt 1.000000 1.000000 105 +vt 1.000000 0.000000 106 +vt 0.000000 0.000000 107 +vt 0.000000 1.000000 108 +vt 1.000000 1.000000 109 +vt 0.000000 1.000000 110 +vt 0.000000 0.000000 111 +vt 1.000000 0.000000 112 +vt 1.000000 0.450518 113 +vt 0.000000 0.450518 114 +vt 0.000000 0.549482 115 +vt 1.000000 0.549482 116 +vt 0.000000 0.450518 117 +vt 1.000000 0.450518 118 +vt 1.000000 0.549482 119 +vt 0.000000 0.549482 120 +vt 0.000000 0.450518 121 +vt 0.000000 0.549482 122 +vt 1.000000 0.450518 123 +vt 1.000000 0.549482 124 +vn 0.0000 -1.0000 0.0000 125 +vn 0.0000 0.0000 -1.0000 126 +vn 1.0000 0.0000 0.0000 127 +vn -1.0000 0.0000 0.0000 128 +vn 0.0000 0.0000 1.0000 129 +vn 0.0000 1.0000 -0.0000 130 +g metal_metal_metal.001 131 +usemtl metal.001 132 +s off 133 +f 15/25/8 13/26/8 14/27/8 16/28/8 134 +f 15/29/9 20/30/9 23/31/9 24/32/9 17/33/9 13/34/9 135 +f 13/34/10 17/33/10 19/35/10 14/36/10 136 +f 16/37/11 18/38/11 20/39/11 15/40/11 137 +f 14/41/12 19/42/12 18/38/12 16/37/12 138 +f 17/33/13 20/39/13 18/38/13 19/42/13 139 +f 31/43/8 26/44/8 30/45/8 32/46/8 140 +f 29/47/13 35/48/13 34/49/13 33/50/13 141 +f 31/51/9 32/52/9 35/53/9 29/54/9 142 +f 30/55/12 26/56/12 33/57/12 34/58/12 143 +f 26/59/10 31/51/10 29/54/10 33/60/10 144 +f 32/61/11 30/55/11 34/58/11 35/62/11 145 +l 21 22 146 +l 28 32 147 +l 27 25 148 +o stone_Cube.008 149 +v 0.452614 0.365016 -0.452614 150 +v 0.452614 -0.410913 -0.452614 151 +v -0.452614 -0.410913 0.452614 152 +v -0.452614 0.365016 0.452614 153 +v 0.452614 0.365016 0.452614 154 +v 0.452614 -0.410913 0.452614 155 +v -0.452614 0.365016 -0.452614 156 +v -0.452614 -0.410913 -0.452614 157 +v 0.452614 0.152026 -0.452614 158 +v -0.452614 0.152026 -0.452614 159 +v -0.288539 -0.410913 -0.452614 160 +v 0.288539 -0.410913 -0.452614 161 +v -0.288539 0.152026 -0.452614 162 +v 0.288539 0.152026 -0.452614 163 +v -0.288540 -0.410913 -0.500000 164 +v 0.288540 -0.410913 -0.500000 165 +v 0.288540 0.152026 -0.500000 166 +v -0.288540 0.152026 -0.500000 167 +vt 0.000000 0.718717 168 +vt 0.000000 0.990645 169 +vt 1.000000 0.990645 170 +vt 1.000000 0.718717 171 +vt 0.818747 0.718717 172 +vt 0.181253 0.718717 173 +vt 1.000000 -0.000000 174 +vt 1.000000 0.723899 175 +vt 1.000000 0.997788 176 +vt 0.000000 0.997788 177 +vt 0.000000 -0.000000 178 +vt 0.000000 0.000000 179 +vt 0.000000 0.995330 180 +vt 1.000000 0.995330 181 +vt 1.000000 0.722116 182 +vt 1.000000 -0.000000 183 +vt 1.000000 0.000000 184 +vt 1.000000 0.987517 185 +vt 0.000000 0.987518 186 +vt 0.818747 0.000000 187 +vt 0.000000 0.000000 188 +vt 0.181253 0.000000 189 +vt 0.458944 -0.150330 190 +vt 0.541056 -0.150330 191 +vt 0.541056 0.825165 192 +vt 0.458944 0.825165 193 +vt 0.000003 0.458944 194 +vt 0.000000 0.541056 195 +vt 1.000000 0.541056 196 +vt 0.999997 0.458944 197 +vt 0.458944 0.825165 198 +vt 0.541056 0.825165 199 +vt 0.541056 -0.150330 200 +vt 0.458944 -0.150330 201 +vn 0.0000 0.0000 -1.0000 202 +vn 1.0000 0.0000 0.0000 203 +vn -1.0000 0.0000 0.0000 204 +vn -0.0000 0.0000 1.0000 205 +vn 0.0000 -1.0000 -0.0000 206 +vn 0.0000 1.0000 -0.0000 207 +g stone_Cube.008_stone.001 208 +usemtl stone.001 209 +s off 210 +f 45/63/14 42/64/14 36/65/14 44/66/14 49/67/14 48/68/14 211 +f 37/69/15 44/70/15 36/71/15 40/72/15 41/73/15 212 +f 38/74/16 39/75/16 42/76/16 45/77/16 43/78/16 213 +f 41/79/17 40/80/17 39/81/17 38/74/17 214 +f 47/82/14 49/67/14 44/66/14 37/69/14 215 +f 43/83/14 45/63/14 48/68/14 46/84/14 216 +f 46/84/14 48/68/14 49/67/14 47/82/14 217 +f 46/85/15 50/86/15 53/87/15 48/88/15 218 +f 48/89/18 53/90/18 52/91/18 49/92/18 219 +f 49/93/16 52/94/16 51/95/16 47/96/16 220 +f 47/82/18 37/69/18 41/79/18 38/74/18 43/83/18 46/84/18 221 +f 42/76/19 39/75/19 40/80/19 36/71/19
Added models/sorcery-kiln-open.obj version [14e1653fbc].
1 +# Blender v2.82 (sub 7) OBJ File: 'kiln.blend' 2 +# www.blender.org 3 +mtllib sorcery-kiln-open.mtl 4 +o furnace 5 +v -0.288540 -0.410913 -0.500000 6 +v 0.288540 -0.410913 -0.500000 7 +v 0.288540 0.152026 -0.500000 8 +v -0.288540 0.152026 -0.500000 9 +vt 0.000000 0.987748 10 +vt 0.000000 0.012252 11 +vt 1.000000 0.012252 12 +vt 1.000000 0.987748 13 +vn 0.0000 0.0000 1.0000 14 +g furnace_furnace_furnace.002 15 +usemtl furnace.002 16 +s off 17 +f 4/1/1 1/2/1 2/3/1 3/4/1 18 +o metal.001 19 +v 0.508325 1.576141 0.354696 20 +v 0.508325 0.586871 0.500792 21 +v -0.491675 1.576141 0.354696 22 +v -0.491675 0.586871 0.500792 23 +v 0.508325 1.590600 0.452599 24 +v -0.491675 0.586871 0.500792 25 +v 0.508325 1.576141 0.354696 26 +v -0.491675 1.576141 0.354696 27 +v 0.508325 0.601329 0.598694 28 +v -0.491675 0.601329 0.598694 29 +v -0.491675 1.590600 0.452599 30 +v 0.508325 -0.506765 -0.499208 31 +v 0.508325 -0.506765 0.500792 32 +v -0.491675 -0.506765 -0.499208 33 +v -0.491675 -0.506765 0.500792 34 +v 0.508325 -0.417677 -0.499208 35 +v -0.491675 -0.417677 0.500792 36 +v 0.508325 -0.417677 0.500792 37 +v -0.491675 -0.417677 -0.499208 38 +v 0.460939 -0.417677 -0.451822 39 +v -0.444289 -0.417677 0.453406 40 +v 0.460939 -0.417677 0.453406 41 +v -0.444289 -0.417677 -0.451822 42 +v 0.344038 0.275759 0.336506 43 +v -0.327389 0.275759 0.336506 44 +v 0.344038 0.275759 -0.334922 45 +v -0.327389 0.275759 -0.334922 46 +v 0.344038 -0.302932 0.336506 47 +v -0.327389 -0.302932 0.336506 48 +v 0.344038 -0.302932 -0.334922 49 +v -0.327389 -0.302932 -0.334922 50 +v 0.344038 0.497017 0.336506 51 +v 0.344038 0.441703 0.336506 52 +v 0.344038 0.386388 0.336506 53 +v 0.344038 0.331074 0.336506 54 +v -0.327389 0.497017 -0.334922 55 +v -0.327389 0.441703 -0.334922 56 +v -0.327389 0.386388 -0.334921 57 +v -0.327389 0.331074 -0.334922 58 +v -0.327389 0.331074 0.336506 59 +v -0.327389 0.386388 0.336506 60 +v -0.327389 0.441703 0.336506 61 +v -0.327389 0.497017 0.336506 62 +v 0.344038 0.331074 -0.334922 63 +v 0.344038 0.386388 -0.334921 64 +v 0.344038 0.441703 -0.334922 65 +v 0.344038 0.497017 -0.334922 66 +v 0.381991 0.275759 0.374458 67 +v -0.365341 0.275759 0.374458 68 +v 0.381991 0.275759 -0.372874 69 +v -0.365341 0.275759 -0.372874 70 +v 0.381991 0.331074 0.374458 71 +v -0.365341 0.331074 -0.372874 72 +v -0.365341 0.497017 0.374458 73 +v -0.365341 0.552332 0.374458 74 +v 0.381991 0.497017 -0.372874 75 +v 0.381991 0.552332 -0.372874 76 +v -0.365341 0.552332 -0.372874 77 +v 0.381991 0.552332 0.374458 78 +v 0.381991 0.497017 0.374458 79 +v 0.381991 0.441703 0.374458 80 +v 0.381991 0.386388 0.374458 81 +v -0.365341 0.497017 -0.372874 82 +v -0.365341 0.441703 -0.372874 83 +v -0.365341 0.386388 -0.372874 84 +v -0.365341 0.331074 0.374458 85 +v -0.365341 0.386388 0.374458 86 +v -0.365341 0.441703 0.374458 87 +v 0.381991 0.331074 -0.372874 88 +v 0.381991 0.386388 -0.372874 89 +v 0.381991 0.441703 -0.372874 90 +v -0.280214 -0.417677 -0.451822 91 +v 0.296863 -0.417677 -0.451822 92 +v -0.280215 -0.417677 -0.499208 93 +v 0.296865 -0.417677 -0.499208 94 +v -0.378077 0.552332 0.387194 95 +v 0.394726 0.552332 -0.385610 96 +v -0.378077 0.552332 -0.385610 97 +v 0.394726 0.552332 0.387194 98 +v -0.378077 -0.323989 0.387194 99 +v 0.394726 -0.323989 -0.385610 100 +v -0.378077 -0.323989 -0.385610 101 +v 0.394726 -0.323989 0.387194 102 +vt 1.000000 1.000000 103 +vt 1.000000 0.000000 104 +vt 0.000000 0.000000 105 +vt 0.000000 1.000000 106 +vt 1.000000 1.000000 107 +vt 0.000000 1.000000 108 +vt 0.000000 0.000000 109 +vt 1.000000 0.000000 110 +vt 1.000000 0.450518 111 +vt 0.000000 0.450518 112 +vt 0.000000 0.549482 113 +vt 1.000000 0.549482 114 +vt 0.000000 0.450518 115 +vt 1.000000 0.450518 116 +vt 1.000000 0.549482 117 +vt 0.000000 0.549482 118 +vt 0.000000 0.450518 119 +vt 0.000000 0.549482 120 +vt 1.000000 0.450518 121 +vt 1.000000 0.549482 122 +vt 0.000000 1.000000 123 +vt 1.000000 1.000000 124 +vt 1.000000 0.000000 125 +vt 0.000000 0.000000 126 +vt 0.000000 0.440608 127 +vt 0.000000 0.529696 128 +vt 0.333333 0.529696 129 +vt 0.666667 0.529696 130 +vt 1.000000 0.529696 131 +vt 1.000000 0.440608 132 +vt 0.000000 0.529696 133 +vt 0.000000 0.440608 134 +vt 1.000000 1.000000 135 +vt 0.666667 1.000000 136 +vt 0.333333 1.000000 137 +vt 0.000000 1.000000 138 +vt 0.047386 0.952614 139 +vt 0.349129 0.952614 140 +vt 0.650871 0.952614 141 +vt 0.952614 0.952614 142 +vt 0.000000 0.440608 143 +vt 0.000000 0.529696 144 +vt 1.000000 0.529696 145 +vt 1.000000 0.440608 146 +vt 1.000000 0.000000 147 +vt 0.952614 0.047386 148 +vt 1.000000 0.440608 149 +vt 1.000000 0.529696 150 +vt 0.000000 0.000000 151 +vt 0.047386 0.047386 152 +vt 0.949216 0.949216 153 +vt 0.050784 0.949216 154 +vt 0.000000 1.000000 155 +vt 1.000000 1.000000 156 +vt 1.000000 1.000000 157 +vt 0.000000 1.000000 158 +vt 0.000000 0.000000 159 +vt 1.000000 0.000000 160 +vt 0.050784 0.050784 161 +vt 0.000000 0.000000 162 +vt 0.050784 0.949216 163 +vt 0.949216 0.949216 164 +vt 1.000000 1.000000 165 +vt 0.000000 1.000000 166 +vt -0.000000 0.000000 167 +vt 1.000000 0.000000 168 +vt 1.000000 1.000000 169 +vt 0.000000 1.000000 170 +vt 0.000000 1.000000 171 +vt 0.000000 0.000000 172 +vt 1.000000 1.000000 173 +vt 0.000000 1.000000 174 +vt 0.000000 0.000000 175 +vt 1.000000 1.000000 176 +vt 1.000000 0.000000 177 +vt 0.949216 0.611024 178 +vt 0.050784 0.611024 179 +vt 0.050784 0.537008 180 +vt 0.949216 0.537008 181 +vt 0.050784 0.050784 182 +vt 0.000000 0.000000 183 +vt 0.949216 0.462992 184 +vt 0.050784 0.462992 185 +vt 0.050784 0.388976 186 +vt 0.949216 0.388976 187 +vt 0.949216 0.949216 188 +vt 0.050784 0.949216 189 +vt 0.000000 1.000000 190 +vt 1.000000 1.000000 191 +vt 0.050784 0.611024 192 +vt 0.949216 0.611024 193 +vt 0.949216 0.537008 194 +vt 0.050784 0.537008 195 +vt 0.050784 0.050784 196 +vt 0.000000 0.000000 197 +vt 0.050784 0.462992 198 +vt 0.949216 0.462992 199 +vt 0.949216 0.388976 200 +vt 0.050784 0.388976 201 +vt 0.050784 0.949216 202 +vt 0.949216 0.949216 203 +vt 1.000000 1.000000 204 +vt 0.000000 1.000000 205 +vt 0.050784 0.611024 206 +vt 0.050784 0.537008 207 +vt 0.949216 0.050784 208 +vt 1.000000 0.000000 209 +vt 0.050784 0.462992 210 +vt 0.050784 0.388976 211 +vt 0.050784 0.050784 212 +vt 0.000000 0.000000 213 +vt 0.949216 0.611024 214 +vt 0.949216 0.537008 215 +vt 0.050784 0.949216 216 +vt 0.949216 0.949216 217 +vt 1.000000 1.000000 218 +vt 0.000000 1.000000 219 +vt 0.949216 0.462992 220 +vt 0.949216 0.388976 221 +vt 0.000000 0.388976 222 +vt 1.000000 0.388976 223 +vt 1.000000 0.314960 224 +vt 0.000000 0.314960 225 +vt 1.000000 0.388976 226 +vt 0.000000 0.388976 227 +vt 0.000000 0.314960 228 +vt 1.000000 0.314960 229 +vt 0.000000 0.388976 230 +vt 0.000000 0.314960 231 +vt 1.000000 0.388976 232 +vt 1.000000 0.314960 233 +vt 1.000000 0.685040 234 +vt 0.000000 0.685040 235 +vt 0.000000 0.611024 236 +vt 1.000000 0.611024 237 +vt 1.000000 0.537008 238 +vt 0.000000 0.537008 239 +vt 0.000000 0.462992 240 +vt 1.000000 0.462992 241 +vt 0.000000 0.685040 242 +vt 1.000000 0.685040 243 +vt 1.000000 0.611024 244 +vt 0.000000 0.611024 245 +vt 0.000000 0.537008 246 +vt 1.000000 0.537008 247 +vt 1.000000 0.462992 248 +vt 0.000000 0.462992 249 +vt 0.000000 0.685040 250 +vt 0.000000 0.611024 251 +vt 0.000000 0.537008 252 +vt 0.000000 0.462992 253 +vt 1.000000 0.685040 254 +vt 1.000000 0.611024 255 +vt 1.000000 0.537008 256 +vt 1.000000 0.462992 257 +vt 0.949216 0.050784 258 +vt 1.000000 0.000000 259 +vt 0.949216 0.050784 260 +vt 0.050784 0.050784 261 +vt 0.000000 0.000000 262 +vt 1.000000 0.000000 263 +vt 0.949216 0.050784 264 +vt 1.000000 0.000000 265 +vt 0.949216 0.050784 266 +vt 1.000000 0.000000 267 +vt 1.000000 0.685040 268 +vt 0.000000 0.685040 269 +vt 1.000000 0.685040 270 +vt 0.000000 0.685040 271 +vt 1.000000 0.685040 272 +vt 0.000000 0.685040 273 +vt 1.000000 0.685040 274 +vt 0.000000 0.685040 275 +vt 1.000000 0.685040 276 +vt 0.000000 0.685040 277 +vt 1.000000 0.685040 278 +vt 0.000000 0.685040 279 +vn 0.0000 -0.1461 -0.9893 280 +vn 0.0000 0.1461 0.9893 281 +vn 0.0000 0.9893 -0.1461 282 +vn 0.0000 -0.9893 0.1461 283 +vn 1.0000 0.0000 0.0000 284 +vn -1.0000 0.0000 0.0000 285 +vn 0.0000 -1.0000 0.0000 286 +vn 0.0000 0.0000 -1.0000 287 +vn 0.0000 1.0000 0.0000 288 +vn 0.0000 -0.0000 1.0000 289 +g metal.001_metal.001_metal.002 290 +usemtl metal.002 291 +s off 292 +f 11/5/2 6/6/2 10/7/2 12/8/2 293 +f 9/9/3 15/10/3 14/11/3 13/12/3 294 +f 11/13/4 12/14/4 15/15/4 9/16/4 295 +f 10/17/5 6/18/5 13/19/5 14/20/5 296 +f 6/21/6 11/13/6 9/16/6 13/22/6 297 +f 12/23/7 10/17/7 14/20/7 15/24/7 298 +f 18/25/8 16/26/8 17/27/8 19/28/8 299 +f 18/29/9 23/30/9 78/31/9 79/32/9 20/33/9 16/34/9 300 +f 16/34/6 20/33/6 22/35/6 17/36/6 301 +f 20/37/10 79/38/10 78/39/10 23/40/10 27/41/10 76/42/10 77/43/10 24/44/10 302 +f 19/45/7 21/46/7 23/47/7 18/48/7 303 +f 22/49/10 20/37/10 24/44/10 26/50/10 304 +f 17/51/11 22/52/11 21/46/11 19/45/11 305 +f 23/40/10 21/53/10 25/54/10 27/41/10 306 +f 21/53/10 22/49/10 26/50/10 25/54/10 307 +f 48/55/8 43/56/8 57/57/8 73/58/8 308 +f 30/59/11 31/60/11 35/61/11 34/62/11 309 +f 43/56/8 44/63/8 70/64/8 57/57/8 310 +f 42/65/10 49/66/10 74/67/10 69/68/10 311 +f 34/69/10 35/70/10 33/71/10 32/72/10 312 +f 28/73/7 30/59/7 34/62/7 32/74/7 313 +f 31/75/6 29/76/6 33/77/6 35/70/6 314 +f 29/76/9 28/78/9 32/79/9 33/77/9 315 +f 40/80/6 47/81/6 46/82/6 41/83/6 316 +f 45/84/10 42/65/10 69/68/10 71/85/10 317 +f 42/86/6 45/87/6 44/88/6 43/89/6 318 +f 50/90/8 41/91/8 68/92/8 75/93/8 319 +f 36/94/7 51/95/7 50/96/7 37/97/7 320 +f 41/91/8 46/98/8 72/99/8 68/92/8 321 +f 38/100/7 49/101/7 48/102/7 39/103/7 322 +f 40/104/10 51/105/10 60/106/10 67/107/10 323 +f 51/95/11 40/108/11 41/109/11 50/96/11 324 +f 44/63/8 39/110/8 56/111/8 70/64/8 325 +f 49/101/11 42/112/11 43/113/11 48/102/11 326 +f 47/114/10 40/104/10 67/107/10 58/115/10 327 +f 47/81/9 36/116/9 37/117/9 46/82/9 328 +f 31/118/10 30/119/10 54/120/10 55/121/10 329 +f 45/87/9 38/122/9 39/123/9 44/88/9 330 +f 70/124/9 56/125/9 52/126/9 53/127/9 331 +f 73/128/11 57/129/11 55/130/11 54/131/11 332 +f 56/132/7 73/128/7 54/131/7 52/133/7 333 +f 57/134/6 70/124/6 53/127/6 55/135/6 334 +f 62/136/6 59/137/6 58/138/6 67/139/6 335 +f 68/140/6 72/141/6 71/142/6 69/143/6 336 +f 63/144/7 61/145/7 60/146/7 64/147/7 337 +f 65/148/7 75/149/7 74/150/7 66/151/7 338 +f 61/145/11 62/152/11 67/153/11 60/146/11 339 +f 75/149/11 68/154/11 69/155/11 74/150/11 340 +f 59/137/9 63/156/9 64/157/9 58/138/9 341 +f 72/141/9 65/158/9 66/159/9 71/142/9 342 +f 51/105/10 36/160/10 64/161/10 60/106/10 343 +f 28/162/10 29/163/10 53/164/10 52/165/10 344 +f 36/160/10 47/114/10 58/115/10 64/161/10 345 +f 37/166/8 50/90/8 75/93/8 65/167/8 346 +f 30/119/10 28/162/10 52/165/10 54/120/10 347 +f 46/98/8 37/166/8 65/167/8 72/99/8 348 +f 49/66/10 38/168/10 66/169/10 74/67/10 349 +f 29/163/10 31/118/10 55/121/10 53/164/10 350 +f 38/168/10 45/84/10 71/85/10 66/169/10 351 +f 39/110/8 48/55/8 73/58/8 56/111/8 352 +f 62/152/10 61/145/10 81/170/10 82/171/10 353 +f 59/137/10 62/136/10 82/172/10 80/173/10 354 +f 63/156/10 59/137/10 80/173/10 83/174/10 355 +f 61/145/10 63/144/10 83/175/10 81/170/10 356 +f 82/171/9 81/170/9 85/176/9 86/177/9 357 +f 80/173/7 82/172/7 86/178/7 84/179/7 358 +f 83/174/11 80/173/11 84/179/11 87/180/11 359 +f 81/170/6 83/175/6 87/181/6 85/176/6 360 +f 84/179/8 86/177/8 85/176/8 87/180/8 361 +l 8 12 362 +l 7 5 363 +o bronze_Cube.006 364 +v 0.500000 0.593635 -0.500000 365 +v 0.500000 0.593635 0.500000 366 +v -0.500000 0.593635 -0.500000 367 +v -0.500000 0.593635 0.500000 368 +v 0.500000 0.365016 -0.500000 369 +v -0.500000 0.365016 0.500000 370 +v 0.500000 0.365016 0.500000 371 +v -0.500000 0.365016 -0.500000 372 +v 0.452614 0.365016 -0.452614 373 +v -0.452614 0.365016 0.452614 374 +v 0.452614 0.365016 0.452614 375 +v -0.452614 0.365016 -0.452614 376 +v 0.335714 0.593635 0.335714 377 +v -0.335714 0.593635 0.335714 378 +v 0.335714 0.593635 -0.335714 379 +v -0.335714 0.593635 -0.335714 380 +v 0.335714 0.559096 0.335714 381 +v -0.335714 0.559096 0.335714 382 +v -0.335714 0.559096 -0.335714 383 +v 0.335714 0.559096 -0.335714 384 +v -0.373666 0.559096 0.373666 385 +v 0.373666 0.559096 -0.373666 386 +v -0.373666 0.559096 -0.373666 387 +v 0.373666 0.559096 0.373666 388 +vt 0.000000 1.000000 389 +vt 0.000000 0.000000 390 +vt 0.164286 0.164286 391 +vt 0.164286 0.835714 392 +vt 1.000000 0.385690 393 +vt 1.000000 0.614310 394 +vt 0.000000 0.614310 395 +vt 0.000000 0.385690 396 +vt 1.000000 0.614310 397 +vt 1.000000 0.385690 398 +vt 1.000000 0.385690 399 +vt 1.000000 0.614310 400 +vt 0.000000 0.614310 401 +vt 0.000000 0.385690 402 +vt 0.000000 0.385690 403 +vt 0.000000 0.614310 404 +vt 1.000000 0.000000 405 +vt 0.000000 0.000000 406 +vt 0.047386 0.047386 407 +vt 0.952614 0.047386 408 +vt 0.000000 1.000000 409 +vt 0.047386 0.952614 410 +vt 1.000000 1.000000 411 +vt 0.952614 0.952614 412 +vt 1.000000 0.000000 413 +vt 1.000000 1.000000 414 +vt 0.835714 0.835714 415 +vt 0.835714 0.164286 416 +vt 0.949216 0.050784 417 +vt 0.949216 0.949216 418 +vt 1.000000 1.000000 419 +vt 1.000000 0.000000 420 +vt 0.625000 0.250000 421 +vt 0.625000 0.000000 422 +vt 0.625000 0.000000 423 +vt 0.625000 0.250000 424 +vt 0.625000 0.750000 425 +vt 0.625000 0.500000 426 +vt 0.625000 0.500000 427 +vt 0.625000 0.750000 428 +vt 0.625000 1.000000 429 +vt 0.625000 1.000000 430 +vt 0.050784 0.949216 431 +vt 0.050784 0.050784 432 +vt 0.000000 0.000000 433 +vt 0.000000 1.000000 434 +vn 0.0000 1.0000 0.0000 435 +vn 0.0000 0.0000 1.0000 436 +vn -1.0000 0.0000 0.0000 437 +vn 1.0000 0.0000 0.0000 438 +vn 0.0000 0.0000 -1.0000 439 +vn -0.0000 -1.0000 -0.0000 440 +vn 0.0000 -0.3768 0.9263 441 +vn -0.9263 -0.3768 0.0000 442 +vn 0.0000 -0.3768 -0.9263 443 +vn 0.9263 -0.3768 0.0000 444 +g bronze_Cube.006_bronze.002 445 +usemtl bronze.002 446 +s off 447 +f 90/182/12 91/183/12 101/184/12 103/185/12 448 +f 94/186/13 89/187/13 91/188/13 93/189/13 449 +f 93/189/14 91/188/14 90/190/14 95/191/14 450 +f 92/192/15 88/193/15 89/194/15 94/195/15 451 +f 95/196/16 90/197/16 88/193/16 92/192/16 452 +f 94/198/17 93/199/17 97/200/17 98/201/17 453 +f 93/199/17 95/202/17 99/203/17 97/200/17 454 +f 92/204/17 94/198/17 98/201/17 96/205/17 455 +f 95/202/17 92/204/17 96/205/17 99/203/17 456 +f 89/206/12 88/207/12 102/208/12 100/209/12 457 +f 88/207/12 90/182/12 103/185/12 102/208/12 458 +f 91/183/12 89/206/12 100/209/12 101/184/12 459 +f 104/210/17 107/211/17 109/212/17 111/213/17 460 +f 103/214/15 101/215/15 105/216/15 106/217/15 461 +f 100/218/14 102/219/14 107/220/14 104/221/14 462 +f 102/219/13 103/214/13 106/217/13 107/220/13 463 +f 101/222/16 100/218/16 104/221/16 105/223/16 464 +f 106/224/17 105/225/17 108/226/17 110/227/17 465 +f 107/211/17 106/224/17 110/227/17 109/212/17 466 +f 105/225/17 104/210/17 111/213/17 108/226/17 467 +f 96/205/18 109/212/18 110/227/18 99/203/18 468 +f 98/201/19 111/213/19 109/212/19 96/205/19 469 +f 97/200/20 108/226/20 111/213/20 98/201/20 470 +f 99/203/21 110/227/21 108/226/21 97/200/21 471 +o stone.001_Cube.009 472 +v 0.452614 0.365016 -0.452614 473 +v 0.452614 -0.410913 -0.452614 474 +v -0.452614 -0.410913 0.452614 475 +v -0.452614 0.365016 0.452614 476 +v 0.452614 0.365016 0.452614 477 +v 0.452614 -0.410913 0.452614 478 +v -0.452614 0.365016 -0.452614 479 +v -0.452614 -0.410913 -0.452614 480 +v 0.452614 0.152026 -0.452614 481 +v -0.452614 0.152026 -0.452614 482 +v -0.288539 -0.410913 -0.452614 483 +v 0.288539 -0.410913 -0.452614 484 +v -0.288539 0.152026 -0.452614 485 +v 0.288539 0.152026 -0.452614 486 +v -0.288540 -0.410913 -0.500000 487 +v 0.288540 -0.410913 -0.500000 488 +v 0.288540 0.152026 -0.500000 489 +v -0.288540 0.152026 -0.500000 490 +v 0.412127 0.365016 -0.420224 491 +v 0.412127 -0.410913 -0.420224 492 +v -0.412127 -0.410913 0.404029 493 +v -0.428808 0.361504 0.401848 494 +v 0.412127 0.365016 0.404029 495 +v 0.412127 -0.410913 0.404029 496 +v -0.428808 0.361503 -0.422405 497 +v -0.412127 -0.410913 -0.420224 498 +v -0.262728 -0.410913 -0.420224 499 +v 0.262728 -0.410913 -0.420224 500 +vt 0.000000 0.718717 501 +vt 0.000000 0.990645 502 +vt 1.000000 0.990645 503 +vt 1.000000 0.718717 504 +vt 0.818747 0.718717 505 +vt 0.181253 0.718717 506 +vt 1.000000 -0.000000 507 +vt 1.000000 0.723899 508 +vt 1.000000 0.997788 509 +vt 0.000000 0.997788 510 +vt 0.000000 -0.000000 511 +vt 0.000000 0.000000 512 +vt 0.000000 0.995330 513 +vt 1.000000 0.995330 514 +vt 1.000000 0.722116 515 +vt 1.000000 -0.000000 516 +vt 1.000000 0.000000 517 +vt 1.000000 0.987517 518 +vt 0.000000 0.987518 519 +vt 0.818747 0.000000 520 +vt 0.000000 0.000000 521 +vt 0.181253 0.000000 522 +vt 0.458944 -0.150330 523 +vt 0.541056 -0.150330 524 +vt 0.541056 0.825165 525 +vt 0.458944 0.825165 526 +vt 0.000003 0.458944 527 +vt 0.000000 0.541056 528 +vt 1.000000 0.541056 529 +vt 0.999997 0.458944 530 +vt 0.458944 0.825165 531 +vt 0.541056 0.825165 532 +vt 0.541056 -0.150330 533 +vt 0.458944 -0.150330 534 +vt 0.000000 0.000000 535 +vt 1.000000 0.000000 536 +vt 1.000000 0.997788 537 +vt 0.000000 0.997788 538 +vt 1.000000 0.000000 539 +vt 0.818747 0.000000 540 +vt 1.000000 0.987517 541 +vt 0.000000 0.987518 542 +vt 1.000000 -0.000000 543 +vt 0.181253 0.000000 544 +vt 0.000000 0.000000 545 +vt 0.000000 0.990645 546 +vt 1.000000 0.990645 547 +vt 0.000000 0.995330 548 +vt 1.000000 0.995330 549 +vt 0.000000 -0.000000 550 +vt 0.000000 0.000000 551 +vt 0.000000 0.000000 552 +vn 0.0000 0.0000 -1.0000 553 +vn 1.0000 0.0000 0.0000 554 +vn -1.0000 0.0000 0.0000 555 +vn -0.0000 0.0000 1.0000 556 +vn 0.0000 -1.0000 -0.0000 557 +vn 0.0000 1.0000 0.0000 558 +vn -0.0020 0.9994 -0.0350 559 +vn -0.0021 0.9985 0.0555 560 +vn 0.1460 0.9893 -0.0000 561 +vn 0.0000 0.0028 1.0000 562 +vn -0.0016 0.0014 1.0000 563 +vn 0.0013 -0.0014 -1.0000 564 +vn 0.9998 0.0216 -0.0000 565 +g stone.001_Cube.009_stone.002 566 +usemtl stone.002 567 +s off 568 +f 121/228/22 118/229/22 112/230/22 120/231/22 125/232/22 124/233/22 569 +f 113/234/23 120/235/23 112/236/23 116/237/23 117/238/23 570 +f 114/239/24 115/240/24 118/241/24 121/242/24 119/243/24 571 +f 117/244/25 116/245/25 115/246/25 114/239/25 572 +f 123/247/22 125/232/22 120/231/22 113/234/22 573 +f 119/248/22 121/228/22 124/233/22 122/249/22 574 +f 122/249/22 124/233/22 125/232/22 123/247/22 575 +f 122/250/23 126/251/23 129/252/23 124/253/23 576 +f 124/254/26 129/255/26 128/256/26 125/257/26 577 +f 125/258/24 128/259/24 127/260/24 123/261/24 578 +f 117/244/26 114/239/26 132/262/26 135/263/26 579 +f 116/237/27 112/236/27 130/264/27 134/265/27 580 +f 123/247/26 113/234/26 131/266/26 139/267/26 581 +f 115/246/28 116/245/28 134/268/28 133/269/28 582 +f 114/239/26 119/243/26 137/270/26 132/262/26 583 +f 119/248/26 122/249/26 138/271/26 137/272/26 584 +f 112/230/29 118/229/29 136/273/29 130/274/29 585 +f 118/241/30 115/240/30 133/275/30 136/276/30 586 +f 122/249/26 123/247/26 139/267/26 138/271/26 587 +f 113/234/26 117/238/26 135/277/26 131/266/26 588 +f 138/271/31 136/278/31 137/272/31 589 +f 130/279/25 139/267/25 131/266/25 590 +f 130/279/32 136/278/32 138/271/32 139/267/32 591 +f 135/277/24 134/265/24 130/264/24 131/266/24 592 +f 132/262/33 133/269/33 134/268/33 135/277/33 593 +f 137/272/34 136/278/34 133/275/34 132/262/34
Modified ores.lua from [45b89ab03b] to [a381d20de4].
1 1 local fragments_per_ingot = 4 2 2 3 3 minetest.register_lbm { 4 - label = "delete duranium ore"; 5 - name = "sorcery:delete_duranium_ore"; 4 + label = "delete duranium ore again"; 5 + name = "sorcery:delete_duranium_ore_again"; 6 6 nodenames = {'sorcery:stone_with_duranium'}; 7 7 action = function(pos,node) 8 8 minetest.set_node(pos, {name = 'default:stone'}) 9 9 end 10 10 } 11 11 12 12 sorcery.data.alloys = {} 13 +sorcery.data.kilnrecs = {} 13 14 sorcery.data.metallookup = { 14 15 -- compat bullshit 15 16 ['moreores:silver_ingot'] = { 16 17 id = 'silver'; data = sorcery.data.metals.silver; 17 18 value = fragments_per_ingot; 18 19 }; 19 20 ['moreores:silver_block'] = { ................................................................................ 39 40 }; 40 41 } 41 42 42 43 local tools, armors = sorcery.matreg.tools, sorcery.matreg.armors 43 44 for name, metal in pairs(sorcery.data.metals) do 44 45 local ingot = metal.ingot or 'sorcery:' .. name .. '_ingot' 45 46 local block = metal.block or 'sorcery:' .. name .. '_block' 47 + local screw = 'sorcery:screw_' .. name 46 48 local fragment = 'sorcery:fragment_' .. name 47 49 if not metal.no_tools then for _,t in pairs(tools) do 48 50 sorcery.matreg.lookup[(metal.items and metal.items[t]) or ('sorcery:' .. t .. '_' .. name)] = { 49 51 metal = true; 50 52 id = name; data = metal; 51 53 } 52 54 end end 53 55 if not metal.no_armor then for _,a in pairs(armors) do 54 - sorcery.matreg.lookup[(metal.items and metal.items[t]) or ('sorcery:' .. a .. '_' .. name)] = { 56 + sorcery.matreg.lookup[(metal.items and metal.items[a]) or ('sorcery:' .. a .. '_' .. name)] = { 55 57 metal = true; 56 58 id = name; data = metal; 57 59 } 58 60 end end 59 61 sorcery.data.metallookup[ingot] = { 60 62 id = name; data = metal; 61 63 value = fragments_per_ingot; ................................................................................ 63 65 sorcery.data.metallookup[block] = { 64 66 id = name; data = metal; 65 67 value = fragments_per_ingot * 9; 66 68 } 67 69 sorcery.data.metallookup[fragment] = { 68 70 id = name; data = metal; 69 71 value = 1; 72 + } 73 + sorcery.data.metallookup[screw] = { 74 + id = name; data = metal; 75 + value = 0; -- prevent use in smelting 76 + } 77 + minetest.register_craftitem(screw, { 78 + description = sorcery.lib.str.capitalize(name) .. ' screw'; 79 + inventory_image = sorcery.lib.image('sorcery_screw.png'):multiply(sorcery.lib.color(metal.tone)):render(); 80 + }) 81 + -- TODO: replace crafting recipe with kiln recipe 82 + minetest.register_craft { 83 + output = screw.. ' 4'; 84 + recipe = { 85 + {fragment,fragment,fragment}; 86 + {'', fragment,''}; 87 + {'', fragment,''}; 88 + }; 70 89 } 71 90 if not sorcery.compat.defp(ingot) then 72 91 -- TODO: remove instant_ores dependency 73 92 instant_ores.register_metal { 74 93 name = 'sorcery:' .. name; 75 94 description = sorcery.lib.str.capitalize(name); 76 95 color = sorcery.lib.color(metal.tone):hex() .. ':' .. ((metal.alpha and tostring(metal.alpha)) or '45');
Modified potions.lua from [676a9b76a9] to [fc0276bae8].
28 28 newstack[1]:get_meta():from_table(meta) 29 29 end; 30 30 walkable = false; 31 31 selection_box = { 32 32 type = "fixed", 33 33 fixed = {-0.25, -0.5, -0.25, 0.25, 0.3, 0.25} 34 34 }; 35 + on_construct = function(pos) 36 + minetest.get_meta(pos):set_string('infotext',label) 37 + end; 35 38 sounds = default.node_sound_glass_defaults(); 36 39 } 37 40 if extra then for k,v in pairs(extra) do node[k] = v end end 38 41 if not node.groups then node.groups = {} end 39 42 node.groups.dig_immediate = 3; 40 43 node.groups.attached_node = 1; 41 44 node.groups.vessel = 1;
Deleted smelter.lua version [07ab2b0675].
1 --- alloying furnace 2 --- 3 --- there are several kinds of alloy furnace, with varying 4 --- capabilities. the simplest can alloy two simple metals; 5 --- the most complex can alloy four high-grade metals such 6 --- as titanium, platinum, iridium, or levitanium. 7 --- 8 --- furnace recipes follow a pattern: the number of crucibles 9 --- determines the input slots, the type of crucible determines 10 --- how hot the furnace can get, and various other components 11 --- (like a coolant circulator) can be added to allow the 12 --- creation of exotic metals. 13 --- 14 --- alloy furnaces produce ingots that can later be melted down 15 --- again and cast into a mold to produce items of particular 16 --- shapes. 17 - 18 --- there are four kinds of crucibles: clay, aluminum, platinum, 19 --- and duranium. clay crucibles are made by molding clay into 20 --- the proper shape and then firing it in a furnace. others 21 --- are made by casting. 22 - 23 -local fragments_per_ingot = 4 24 - 25 -for _, c in pairs { 'clay', 'aluminum', 'platinum', 'duranium' } do 26 - minetest.register_craftitem('sorcery:crucible_' .. c, { 27 - description = sorcery.lib.str.capitalize(c .. ' crucible'); 28 - inventory_image = 'sorcery_crucible_' .. c .. '.png'; 29 - }) 30 -end 31 - 32 -minetest.register_craftitem('sorcery:crucible_clay_molding', { 33 - description = sorcery.lib.str.capitalize('Crucible molding'); 34 - inventory_image = 'sorcery_crucible_clay_molding.png'; 35 -}) 36 - 37 -minetest.register_craft { 38 - recipe = { 39 - { 'default:clay_lump', '', 'default:clay_lump'}; 40 - { 'default:clay_lump', '', 'default:clay_lump'}; 41 - { 'default:clay_lump', 'default:clay_lump', 'default:clay_lump'}; 42 - }; 43 - output = 'sorcery:crucible_clay_molding'; 44 -} 45 -minetest.register_craft { 46 - type = 'shapeless'; 47 - recipe = { 'sorcery:crucible_clay_molding' }; 48 - output = 'default:clay_lump 7'; 49 -} 50 -minetest.register_craft { 51 - type = 'cooking'; 52 - recipe = 'sorcery:crucible_clay_molding'; 53 - cooktime = 40; 54 - output = 'sorcery:crucible_clay'; 55 -} 56 - 57 -local smelter_formspec = function(kind, fuel_progress, smelt_progress) 58 - local layouts = { 59 - [1] = {w = 1, h = 1}; [2] = {w = 2, h = 1}; [3] = {w = 3, h = 1}; 60 - [4] = {w = 2, h = 2}; [5] = {w = 3, h = 2}; [6] = {w = 3, h = 2}; 61 - } 62 - local inpos = { x = 2.8, y = 1 } 63 - local insize = layouts[kind.size] 64 - local outpos = { x = 5.2, y = 2.4 } 65 - local outsize = layouts[kind.outsize] 66 - local fuelpos = { x = 2.8, y = 3.4 } 67 - local fuelsize = layouts[kind.fuelsize] 68 - return string.format([[ 69 - size[8,8] 70 - list[context;input;%f,%f;%f,%f;] 71 - list[context;output;%f,%f;%f,%f;] 72 - list[context;fuel;%f,%f;%f,%f;] 73 - list[current_player;main;0,4.2;8,4] 74 - 75 - image[2.3,1.9;1,1;default_furnace_fire_bg.png^[lowpart:%u%%:default_furnace_fire_fg.png] 76 - image[3.2,1.9;1,1;gui_furnace_arrow_bg.png^[lowpart:%u%%:gui_furnace_arrow_fg.png^[transformR270] 77 - 78 - listring[context;output] listring[current_player;main] 79 - listring[context;input] listring[current_player;main] 80 - listring[context;fuel] listring[current_player;main] 81 - ]], 82 - --input 83 - inpos.x - insize.w/2, -- pos 84 - inpos.y - insize.h/2, 85 - insize.w, insize.h, -- size 86 - --output 87 - outpos.x - outsize.w/2, -- pos 88 - outpos.y - outsize.h/2, 89 - outsize.w, outsize.h, -- size 90 - --fuel 91 - fuelpos.x - fuelsize.w/2, -- pos 92 - fuelpos.y - fuelsize.h/2, 93 - fuelsize.w, fuelsize.h, -- size 94 - 95 - fuel_progress, smelt_progress 96 - ) 97 -end 98 - 99 -local find_recipe = function(inv) 100 - local mix = {} 101 - local count = 0 102 - for i=1,inv:get_size('input') do 103 - local m = inv:get_stack('input',i) 104 - if m:is_empty() then goto skip end 105 - local l = sorcery.data.metallookup[m:get_name()] 106 - if not l then return false end 107 - mix[l.id] = (mix[l.id] or 0) + l.value 108 - count = count + l.value 109 - ::skip::end 110 - -- everything is metal, we've finished summing it up. 111 - -- let's see if the assembled items match the ratio 112 - -- specified in any of the smelting recipes. 113 - local matches = 0 114 - for _,rec in pairs(sorcery.data.alloys) do 115 - local fac = nil 116 - local meltpoint = 1 117 - if rec.metals == nil then goto skip_recipe end 118 - for metal, ratio in pairs(rec.metals) do 119 - if mix[metal] and mix[metal] % ratio == 0 then 120 - if fac then 121 - if mix[metal] / ratio ~= fac then goto skip_recipe end 122 - else fac = math.floor(mix[metal] / ratio) end 123 - local m = sorcery.data.metals[metal] 124 - if m.meltpoint then 125 - meltpoint = math.max(meltpoint, m.meltpoint) end 126 - else goto skip_recipe end 127 - end 128 - do return rec, count, fac, meltpoint end 129 - ::skip_recipe::end 130 - return false 131 -end 132 - 133 -local update_smelter = function(pos) 134 - local meta = minetest.get_meta(pos) 135 - local inv = meta:get_inventory() 136 - local proto = minetest.registered_nodes[minetest.get_node(pos).name]._proto 137 - local recipe, count, factor, meltpoint = find_recipe(inv) 138 - if recipe and proto.temp >= meltpoint then 139 - minetest.get_node_timer(pos):start(1) 140 - else 141 - meta:set_float('burntime',0) 142 - end 143 -end 144 - 145 -local smelter_step = function(kind,active,pos,delta) 146 - local meta = minetest.get_meta(pos) 147 - local inv = meta:get_inventory() 148 - local recipe, count, factor = find_recipe(inv) 149 - local cooktime 150 - local elapsed = meta:get_float('burntime') + delta 151 - meta:set_float('burnleft',meta:get_float('burnleft') - delta) 152 - if (not active) and (not recipe) then return false end 153 - if meta:get_float('burnleft') <= 0 or not active then 154 - if recipe then 155 - local burn, frep = minetest.get_craft_result { 156 - method = 'fuel', width = 1; 157 - items = { inv:get_stack('fuel',1) }; 158 - } 159 - if burn.time == 0 then goto nofuel end 160 - inv:set_stack('fuel', 1, frep.items[1]) 161 - meta:set_float('burnleft',burn.time) 162 - meta:set_float('burnmax',burn.time) 163 - if not active then 164 - minetest.swap_node(pos, 165 - sorcery.lib.tbl.merge(minetest.get_node(pos), { 166 - name = kind.id .. '_active' 167 - })) 168 - active = true 169 - end 170 - else goto nofuel end 171 - end 172 - 173 - if not recipe then goto update end 174 - 175 - cooktime = ((recipe.cooktime / fragments_per_ingot) * count) / factor 176 - if elapsed >= cooktime then 177 - elapsed = 0 178 - -- remove used items 179 - for i=1,inv:get_size('input') do 180 - local s = inv:get_stack('input',i) 181 - if s:is_empty() then goto skip end 182 - s:take_item(1) inv:set_stack('input',i,s) 183 - ::skip::end 184 - 185 - local outstack 186 - if count % fragments_per_ingot == 0 then 187 - outstack = ItemStack { 188 - name = sorcery.data.metals[recipe.output].ingot or 'sorcery:' .. recipe.output .. '_ingot'; 189 - count = count / fragments_per_ingot; 190 - } 191 - else 192 - outstack = ItemStack { 193 - name = 'sorcery:fragment_' .. recipe.output; 194 - count = count; 195 - } 196 - end 197 - 198 - local leftover = inv:add_item('output',outstack) 199 - if not leftover:is_empty() then 200 - minetest.add_item(pos, leftover) 201 - end 202 - end 203 - 204 - ::update:: 205 - meta:set_float('burntime',elapsed) 206 - meta:set_string('formspec', smelter_formspec(kind, 207 - math.min(1, meta:get_float('burnleft') / 208 - meta:get_float('burnmax') 209 - ) * 100, -- fuel 210 - (cooktime and math.min(1, elapsed / cooktime) * 100) or 0 -- smelt 211 - )) 212 - do return active end 213 - 214 - ::nofuel:: 215 - if active then 216 - minetest.swap_node(pos, 217 - sorcery.lib.tbl.merge(minetest.get_node(pos), { name = kind.id })) 218 - end 219 - meta:set_float('burnleft',0) -- just in case 220 - ::noburn:: 221 - meta:set_float('burntime',0) -- just in case 222 - meta:set_string('formspec', smelter_formspec(kind, 0, 0)) 223 - return false 224 -end 225 - 226 -local register_smelter = function(kind) 227 - local recipe = {{},{}; 228 - {'default:stone','default:furnace','default:stone'}; 229 - } do 230 - local on = kind.crucible 231 - local ti = 'default:tin_ingot' 232 - local cu = 'default:copper_ingot' 233 - local crucmap = { 234 - [2] = { {cu,cu,cu}, {on,ti,on} }; 235 - [3] = { {cu,on,cu}, {on,ti,on} }; 236 - [4] = { {on,cu,on}, {on,ti,on} }; 237 - [5] = { {on,cu,on}, {on,on,on} }; 238 - [6] = { {on,on,on}, {on,on,on} }; 239 - }; 240 - for y=1,2 do recipe[y] = crucmap[kind.size][y] end 241 - end 242 - 243 - local desc = 'smelter'; 244 - if kind.temp_name then desc = kind.temp_name .. ' ' .. desc end 245 - if kind.size_name then desc = kind.size_name .. ' ' .. desc end 246 - desc = sorcery.lib.str.capitalize(desc); 247 - local id = 'sorcery:smelter_' .. kind.material .. kind.size_name 248 - kind.id = id 249 - for _, active in pairs {false, true} do 250 - minetest.register_node((active and id .. '_active') or id, { 251 - _proto = kind; 252 - description = desc; 253 - drop = id; 254 - groups = { cracky = 2; }; 255 - paramtype2 = 'facedir'; 256 - light_source = (active and 9) or 0; 257 - on_construct = function(pos) 258 - local meta = minetest.get_meta(pos) 259 - local inv = meta:get_inventory() 260 - inv:set_size('input',kind.size) 261 - inv:set_size('output',kind.outsize) 262 - inv:set_size('fuel',kind.fuelsize) 263 - meta:set_string('infotext', desc) 264 - meta:set_string('formspec', smelter_formspec(kind, 0, 0)) 265 - meta:set_float('burnleft',0) 266 - meta:set_float('burnmax',0) 267 - meta:set_float('burntime',0) 268 - end; 269 - on_metadata_inventory_put = update_smelter; 270 - on_metadata_inventory_move = update_smelter; 271 - on_metadata_inventory_take = update_smelter; 272 - on_timer = function(pos,delta) return smelter_step(kind, active, pos, delta) end; 273 - -- allow_metadata_inventory_put = function(pos, listname, index, stack, player) 274 - -- end; 275 - tiles = { 276 - 'sorcery_smelter_top_' .. tostring(kind.size) .. '.png'; 277 - 'sorcery_smelter_bottom.png'; 278 - 'sorcery_smelter_side.png'; 279 - 'sorcery_smelter_side.png'; 280 - 'sorcery_smelter_side.png'; 281 - 'sorcery_smelter_front' .. ((active and '_hot') or '') .. '.png'; 282 - }; 283 - }) 284 - end 285 - minetest.register_craft { 286 - recipe = recipe; 287 - output = id; 288 - } 289 -end 290 - 291 -for _, s in pairs { 292 - {2, 'small'}; 293 - {3, 'large'}; 294 - {4, 'grand'}; 295 -} do for _, t in pairs { 296 - {1, nil, 'clay'}; 297 - {2, 'hot','aluminum'}; 298 - {3, 'volcanic','platinum'}; 299 - {4, 'stellar','duranium'}; 300 - {5, 'nova','impervium'}; 301 -} do 302 - register_smelter { 303 - size = s[1], size_name = s[2]; 304 - temp = t[1], temp_name = t[2]; 305 - material = t[3]; 306 - crucible = 'sorcery:crucible_' .. t[3]; 307 - outsize = 4, fuelsize = 1; 308 - } 309 -end end
Added test/common.lua version [7f2fc6a53d].
1 +local qv = 0 2 +local testn = 0 3 +test = function(name,expr) 4 + testn = testn + 1 5 + print(string.format('% 3u ',testn) .. 6 + (expr and '\x1b[32mPASS\x1b[m' or '\x1b[31mFAIL\x1b[m') .. 7 + ' ' .. name) 8 + if not expr and qv == 0 then qv = testn end 9 +end 10 +report = function() os.exit(qv) end 11 + 12 +hexdump = function(s) 13 + local hexlines, charlines = {},{} 14 + for i=1,#s do 15 + local line = math.floor((i-1)/16) + 1 16 + hexlines[line] = (hexlines[line] or '') .. string.format("%02x ",string.byte(s, i)) 17 + charlines[line] = (charlines[line] or '') .. ' ' .. string.gsub(string.sub(s, i, i), '[^%g ]', '\x1b[;35m·\x1b[36;1m') .. ' ' 18 + end 19 + local str = '' 20 + for i=1,#hexlines do 21 + str = str .. '\x1b[1;36m' .. charlines[i] .. '\x1b[m\n' .. hexlines[i] .. '\n' 22 + end 23 + return str 24 +end 25 + 26 +function dump(o) 27 + if type(o) == "table" then 28 + local str = '' 29 + for k,p in pairs(o) do 30 + str = str .. (k .. ' = {' .. dump(p) ..'}\n') 31 + end 32 + return str 33 + else 34 + return tostring(o) 35 + end 36 +end 37 +
Added test/encode.lua version [765ecd04d6].
1 +dofile'test/common.lua' 2 +local m = dofile'lib/marshal.lua' 3 +local s = dofile'lib/str.lua' 4 +local ench_t = m.g.struct { 5 + id = m.t.str; 6 + slot = m.t.u8; 7 + boost = m.t.u8; 8 + reliability = m.t.u8; 9 +} 10 +local pack, unpack = m.transcoder { 11 + spells = m.g.array(8, ench_t); 12 + energy = m.t.u16; 13 +} 14 + 15 +local packed = pack{ 16 + energy = 1550; 17 + spells = { 18 + { slot = 0; boost = 15; reliability = 100; id = 'dowse' }; 19 + { slot = 1; boost = 3; reliability = 0; id = 'e' }; 20 + }; 21 +} 22 + 23 +print('\x1b[1munarmored\x1b[m\n' .. hexdump(packed)) 24 +print('\x1b[1marmored\x1b[m\n' .. hexdump(s.meta_armor(packed))) 25 +print('\x1b[1marmored (struct mode)\x1b[m\n' .. hexdump(s.meta_armor(packed,true))) 26 +print('\x1b[1mdearmored\x1b[m\n' .. hexdump(s.meta_dearmor(s.meta_armor(packed)))) 27 +print('\x1b[1mdearmored (struct mode)\x1b[m\n' .. hexdump(s.meta_dearmor(s.meta_armor(packed,true),true))) 28 + 29 +test('dearmor(armor(x)) == x',s.meta_dearmor(s.meta_armor(packed)) == packed) 30 +test('struct_dearmor(struct_armor(x)) == x',s.meta_dearmor(s.meta_armor(packed,true),true) == packed) 31 +test('struct_dearmor("string") == "string"',s.meta_dearmor('string',true) == 'string') 32 +report()
Modified test/marshal.lua from [f9d9d412d5] to [c7cd728357].
1 +dofile'test/common.lua' 1 2 local m = dofile"lib/marshal.lua" 2 3 local car_t = m.g.struct { 3 4 brand = m.t.str; 4 5 year = m.t.u16; 5 6 } 6 7 local pack, unpack = m.transcoder { 7 8 version = m.t.u16; ................................................................................ 35 36 cars = { 36 37 {brand = 'dodge', year = 2596}; 37 38 {brand = 'subaru', year = 321}; 38 39 }; 39 40 } 40 41 if m.wrong(s) then print(s.exp) os.exit(1) end 41 42 42 -local str = 'serialized:' 43 -for i=1,#s do 44 - str = str ..' '.. string.format("%x",string.byte(str, i)) 45 -end 46 -print(str) 43 +print(hexdump(s)) 47 44 48 45 local v = unpack(s) 49 46 50 -local function dump(o) 51 - if type(o) == "table" then 52 - local str = '' 53 - for k,p in pairs(o) do 54 - str = str .. (k .. ' = {' .. dump(p) ..'}\n') 55 - end 56 - return str 57 - else 58 - return tostring(o) 59 - end 60 -end 61 - 62 47 print(dump(v))
Modified test/rand.lua from [1bb191f684] to [a1bc3992a0].
1 +dofile'test/common.lua' 1 2 local str = dofile "lib/str.lua" 2 3 local rnd = str.rand(5,45) 3 4 print(rnd) 4 -print(str.capitalize(rnd)) 5 + 6 +test('random strings do not match',str.rand(5,45) ~= str.rand(5,45)) 7 +test('strings are correct length',#str.rand(44,45) == 45) 8 +report()
Added textures/sorcery_amulet.png version [9548ac041a].
cannot compute difference between binary files
Modified textures/sorcery_enchant_conserve.png from [cbdb21cff9] to [3451249f04].
cannot compute difference between binary files
Modified textures/sorcery_enchant_dowse.png from [d2f6a92230] to [efa02ac638].
cannot compute difference between binary files
Modified textures/sorcery_enchant_endure.png from [aafc064fe5] to [84094793b8].
cannot compute difference between binary files
Modified textures/sorcery_enchant_harvest.png from [1be6ae9ec0] to [40b1201c27].
cannot compute difference between binary files
Modified textures/sorcery_enchant_pierce.png from [cbba8fc2f9] to [fd3ecbaa4b].
cannot compute difference between binary files
Modified textures/sorcery_enchant_rend.png from [db77c91590] to [3f9d55bb9f].
cannot compute difference between binary files
Added textures/sorcery_enchanter_channeler.png version [cf624a00b3].
cannot compute difference between binary files
Added textures/sorcery_enchanter_pedestal.png version [acba9558af].
cannot compute difference between binary files
Added textures/sorcery_gem_diamond_shard.png version [1d314919ff].
cannot compute difference between binary files
Added textures/sorcery_screw.png version [0f1a74e38b].
cannot compute difference between binary files
Added textures/sorcery_transparent.png version [574440e638].
cannot compute difference between binary files
Added tnodes.lua version [74f7716464].
1 +for i=1,minetest.LIGHT_MAX do 2 + minetest.register_node('sorcery:air_glimmer_' .. tostring(i), { 3 + drawtype = 'airlike'; 4 + light_source = 5 + math.ceil(i * (11/minetest.LIGHT_MAX)); 5 + sunlight_propagates = true; 6 + buildable_to = true; 7 + pointable = false; 8 + walkable = false; 9 + floodable = true; 10 + on_construct = function(pos) 11 + local meta = minetest.get_meta(pos) 12 + meta:set_float('duration',10) 13 + meta:set_float('timeleft',10) 14 + meta:set_int('power',minetest.LIGHT_MAX) 15 + minetest.get_node_timer(pos):start(1) 16 + end; 17 + on_timer = function(pos,dtime) 18 + local meta = minetest.get_meta(pos) 19 + local elapsed = dtime + meta:get_float('duration') - meta:get_float('timeleft') 20 + local level = 1 - (elapsed / meta:get_float('duration')) 21 + local lum = math.ceil(level*meta:get_int('power')) 22 + print('elapsed time',elapsed) 23 + print('light level',level) 24 + print('lum',lum) 25 + if lum ~= i then 26 + if lum <= 0 then 27 + minetest.remove_node(pos) 28 + return false 29 + else 30 + minetest.swap_node(pos,{name='sorcery:air_glimmer_'..tostring(lum)}) 31 + end 32 + end 33 + minetest.add_particlespawner { 34 + amount = 3 * meta:get_int('power'); 35 + time = 1.1; 36 + minpos = vector.subtract(pos,2); 37 + maxpos = vector.add(pos,2); 38 + minvel = {x = -0.5; z = -0.5; y = -0.3}; 39 + maxvel = {x = 0.5; z = 0.5; y = 0.3}; 40 + minsize = 0.3, maxsize = 0.9; 41 + minexptime = 0.5, maxexptime = 1.2; 42 + texture = 'sorcery_spark.png'; 43 + animation = { 44 + glow = i; 45 + length = 1.2; 46 + type = 'vertical_frames'; 47 + aspect_w = 16; 48 + aspect_h = 16; 49 + } 50 + } 51 + meta:set_float('timeleft',meta:get_float('duration') - elapsed) 52 + return true 53 + end; 54 + }) 55 +end
Modified wands.lua from [327c4e54ef] to [8ffba5fe57].
73 73 local name = wand.wood .. 'wood wand' 74 74 if wand.core ~= nil then name = wand.core .. '-core ' .. name end 75 75 if full then 76 76 if wand.gem ~= nil then name = wand.gem .. ' ' .. name end 77 77 if wand.wire ~= nil then name = wand.wire .. 'clad ' .. name end 78 78 end 79 79 return u.str.capitalize(name) 80 + end; 81 + fullname = function(stack) 82 + local proto = sorcery.wands.util.getproto(stack) 83 + local wm = stack:get_meta() 84 + local spell = wm:get_string('sorcery_wand_spell') 85 + if spell ~= '' then 86 + local sd = sorcery.data.spells[spell] 87 + return u.str.capitalize(sd.name) .. ' wand'; 88 + else 89 + return sorcery.wands.util.basename(proto) 90 + end 80 91 end; 81 92 wear = function(item) 82 93 local meta = item:get_meta() 83 94 local spell = meta:get_string('sorcery_wand_spell') 84 95 local proto = sorcery.wands.util.getproto(item) 85 96 if spell == "" then return 0 end 86 97 ................................................................................ 218 229 if kind.gem then 219 230 img.gem = u.image('sorcery_wand_' .. kind.gem .. '_tip.png') 220 231 img.whole = img.gem:blit(img.whole) 221 232 end 222 233 return img 223 234 end 224 235 225 -local createstand = function(name, desc, tex, extra) 236 +local createstand = function(name, wood, desc, tex, extra) 226 237 local hitbox = { 227 238 type = "fixed"; 228 239 fixed = { 229 240 -0.5, -0.5, -0.3; 230 241 0.5, -0.1, 0.3; 231 242 }; 232 243 } ................................................................................ 239 250 sunlight_propagates = true; 240 251 paramtype = 'light'; 241 252 paramtype2 = 'facedir'; 242 253 tiles = images; 243 254 selection_box = hitbox; 244 255 collision_box = hitbox; 245 256 use_texture_alpha = true; 257 + _proto = { 258 + wood = wood; 259 + }; 246 260 groups = { 247 261 sorcery_wand_stand = 1; 248 262 choppy = 2; 249 263 oddly_breakable_by_hand = 2; 250 264 }; 251 265 } 252 266 minetest.register_node(name, u.tbl.merge(auto,extra)) 253 267 end 254 - 268 +local update_stand_info = function(pos) 269 + local woodname = minetest.registered_nodes[minetest.get_node(pos).name]._proto.wood 270 + local meta = minetest.get_meta(pos) 271 + local inv = meta:get_inventory() 272 + if inv:is_empty('wand') then 273 + meta:set_string('infotext',u.str.capitalize(woodname) .. ' wand stand') 274 + else 275 + local stack = inv:get_stack('wand',1) 276 + local spell = stack:get_meta():get_string('sorcery_wand_spell') 277 + local color = u.color(127,127,127) 278 + if spell ~= '' then 279 + color = u.color(sorcery.data.spells[spell].color):readable() 280 + end 281 + local wand_proto = sorcery.wands.util.getproto(stack) 282 + meta:set_string('infotext',color:fmt(sorcery.wands.util.fullname(stack) .. ' stand')) 283 + end 284 +end 255 285 for woodname, wood in pairs(sorcery.wands.materials.wood) do 256 - local blank = u.image('doors_blank.png'); -- haaaaack 286 + local blank = u.image('sorcery_transparent.png'); -- haaaaack 257 287 local name = 'sorcery:wand_stand_' .. woodname 258 - createstand(name , 288 + createstand(name, woodname, 259 289 u.str.capitalize(woodname .. 'wood wand stand'), 260 290 { wood.tex; blank; blank; blank; }, { 261 291 on_construct = function(pos) 262 292 local meta = minetest.get_meta(pos) 263 293 local inv = meta:get_inventory() 264 294 inv:set_size('wand', 1) 295 + update_stand_info(pos) 265 296 end; 266 297 on_rightclick = function(pos,node,user,stack) 267 298 local meta = minetest.get_meta(pos) 268 299 local stand = meta:get_inventory() 300 + local wand_proto = sorcery.wands.util.getproto(stack) 269 301 if minetest.get_item_group(stack:get_name(), 'sorcery_wand') ~= 0 then 270 302 stand:set_stack('wand',1,stack) 271 303 minetest.swap_node(pos, { 272 - name = sorcery.wands.util.baseid(stack:get_definition()._proto) .. '_stand_' .. woodname; 304 + name = sorcery.wands.util.baseid(wand_proto) .. '_stand_' .. woodname; 273 305 param2 = node.param2; 274 306 }) 275 307 stack = ItemStack(nil) 276 308 end 309 + update_stand_info(pos) 277 310 return stack 278 311 end 279 312 } 280 313 ) 281 314 local plank = wood.plank or 'default:' .. woodname .. '_wood' 282 315 minetest.register_craft { 283 316 recipe = { ................................................................................ 294 327 local gemimg = u.image('default_diamond_block.png') 295 328 if kind.gem 296 329 then gemimg = gemimg:multiply(u.color(sorcery.wands.materials.gem[kind.gem].tone)) 297 330 else gemimg = gemimg:fade(1) end 298 331 299 332 createstand( 300 333 kind.id .. '_stand_' .. woodname, 334 + woodname, 301 335 u.str.capitalize(woodname) .. 'wood wand stand with ' .. string.lower(sorcery.wands.util.basename(kind,true)), { 302 336 wood.tex; 303 337 sorcery.wands.materials.wood[kind.wood].tex; 304 338 gemimg; 305 - (kind.wire and sorcery.wands.materials.wire[kind.wire].tex) or u.image('doors_blank.png'); -- haaaaack 339 + (kind.wire and sorcery.wands.materials.wire[kind.wire].tex) or u.image('sorcery_transparent.png'); -- haaaaack 306 340 }, { 307 341 drop = 'sorcery:wand_stand_' .. woodname; 308 342 after_dig_node = function(pos,node,meta,digger) 309 343 local stack = meta.inventory.wand[1] 310 344 if stack and not stack:is_empty() then 311 345 -- luv 2 defensive coding 312 346 minetest.add_item(pos, stack) ................................................................................ 325 359 else goto failure end 326 360 end 327 361 stand:set_stack('wand',1,ItemStack(nil)) 328 362 minetest.swap_node(pos, { 329 363 name = 'sorcery:wand_stand_' .. woodname; 330 364 param2 = node.param2; 331 365 }) 332 - ::failure:: return stack 366 + ::failure:: 367 + update_stand_info(pos) 368 + return stack 333 369 end; 334 370 } 335 371 ) 336 372 end 337 373 end 338 374 sorcery.wands.createkind = function(kind) 339 375 if sorcery.wands.kinds[kind.id] then return false end ................................................................................ 372 408 local update_wand_description = function(stack) 373 409 local proto = sorcery.wands.util.getproto(stack) 374 410 local wm = stack:get_meta() 375 411 local spell = wm:get_string('sorcery_wand_spell') 376 412 if spell ~= "" then 377 413 local sd = sorcery.data.spells[spell] 378 414 wm:set_string('description', u.ui.tooltip { 379 - title = u.str.capitalize(sd.name) .. ' wand'; 415 + title = sorcery.wands.util.fullname(stack); 380 416 desc = sorcery.wands.util.basedesc(proto); 381 417 props = { 382 418 { color = u.color(sd.color); desc = sd.desc } 383 419 }; 384 420 }) 385 421 else 386 422 wm:set_string('description', u.ui.tooltip {