Comment: | add force field emitters, generators, rework leyline distribution algorithm, add utility function for automatically dumping out inventories when an item is dug, add draconium and tyrannium alloys (tentatively), various fixes |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
f7f6898cbda00c7271bbe38e53f5e936 |
User & Date: | lexi on 2020-08-21 11:52:17 |
Other Links: | manifest | tags |
2020-08-28
| ||
14:08 | add recipes, cookbooks, disassembly (to create recipes from items), attunement, farcasters, and portals; various edits for bug fixes and improvements check-in: 9ef6cbcf31 user: lexi tags: trunk | |
2020-08-21
| ||
11:52 | add force field emitters, generators, rework leyline distribution algorithm, add utility function for automatically dumping out inventories when an item is dug, add draconium and tyrannium alloys (tentatively), various fixes check-in: f7f6898cbd user: lexi tags: trunk | |
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 | |
Modified coins.lua from [e5af87fe4c] to [f5d6bba856].
49 49 end 50 50 inv:set_stack('output',1,ItemStack(nil)) 51 51 do return end 52 52 53 53 ::foundmetal:: if not inv:is_empty('gem') then 54 54 local id = slot_gem:get_name() 55 55 for name,gem in pairs(sorcery.data.gems) do 56 - print('scanning gem',name,dump(gem)) 57 56 if gem.foreign then 58 57 if id == gem.foreign then gemname = name 59 58 else goto skip end 60 59 else 61 60 if id == 'sorcery:gem_' .. name then gemname = name 62 61 else goto skip end 63 62 end 64 63 coincount = math.min(coincount, slot_gem:get_count()) 65 64 do break end 66 65 ::skip::end 67 66 end 68 67 69 68 coincount = coincount * coins_per_ingot 70 - print('names',coinname,gemname) 71 69 72 70 local coinname = 'sorcery:coin_' .. metalname .. 73 71 ((gemname and '_' .. gemname) or '') 74 72 75 73 inv:set_stack('output',1,ItemStack { 76 74 name = coinname; 77 75 count = coincount;
Modified data/enchants.lua from [9a3424a733] to [fc080855fd].
58 58 {lens = 'concave', gem = 'mese', dmg = 1}; 59 59 {lens = 'concave', gem = 'sapphire', dmg = 1}; 60 60 }; 61 61 desc = 'some damage is repaired when used to mine ore or kill an attacker'; 62 62 on_dig = function(ctx) 63 63 local orepfx = "stone_with_" -- }:< 64 64 -- local oredrop = ' lump' 65 - local dug = minetest.get_node(ctx.target.under) 66 - local barename = string.sub(dug.name, string.find(dug.name, ':') + 1) 67 - print('is ore? ',dug.name,barename) 68 - if minetest.get_item_group(dug.name, ore) ~= 0 or 65 + local barename = string.sub(ctx.node.name, string.find(ctx.node.name, ':') + 1) 66 + if minetest.get_item_group(ctx.node.name, 'ore') ~= 0 or 69 67 string.sub(barename,1,string.len(orepfx)) == orepfx 70 68 then 71 - print('is ore!') 72 69 ctx.tool:add_wear(-(sorcery.enchant.strength(ctx.tool,'harvest') * 2000)) 73 70 ctx.cost = 3 74 71 end 75 72 end; 76 73 }; 77 74 conserve = { -- use less magical energy 78 75 name = 'Conserve';
Modified data/gems.lua from [6638dda90c] to [c84e6c472a].
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 25 maxenergy = 2000; 26 + hardness = 8; 27 + randomfind = false; 26 28 slots = { 27 29 {affinity = {'praxic','counterpraxic'}, confluence = 1}; 28 30 {affinity = {'praxic','syncretic'}, confluence = 0.6}; 29 31 {affinity = {'counterpraxic', 'entropic'}, confluence = 0.7}; 30 32 }; 31 33 }; 32 34 mese = { ................................................................................ 33 35 foreign = 'default:mese_crystal'; 34 36 foreign_shard = 'default:mese_crystal_fragment'; 35 37 tone = {255,253,94}; 36 38 energysource = 5; 37 39 maxenergy = 600; 38 40 items = default_items('mese'); 39 41 tools = true, armor = true; 42 + randomfind = false; 40 43 slots = { 41 44 {affinity = {'praxic'}, confluence = 1}; 42 45 {affinity = {'praxic'}, confluence = 0.5}; 43 46 {affinity = {'cognic'}, confluence = 1}; 44 47 {affinity = {'syncretic'}, confluence = 0.9}; 45 48 }; 46 49 };
Modified data/greases.lua from [018bd8935a] to [0a57245423].
59 59 color = {222,57,239}; 60 60 core = { 'sorcery:oil_mystic', 'sorcery:oil_dawn', 'sorcery:oil_mushroom' }; 61 61 mix = { 62 62 'sorcery:powder_cobalt'; 63 63 'sorcery:powder_cobalt'; 64 64 'sorcery:extract_grape'; 65 65 }; 66 + }; 67 + neutralizing = { 68 + color = {221,148,95}; 69 + core = { 'sorcery:oil_dawn', 'sorcery:oil_berry' }; 70 + mix = { 71 + 'sorcery:powder_aluminum'; 72 + 'sorcery:powder_lithium'; 73 + 'sorcery:extract_pine'; 74 + }; 66 75 }; 67 76 }
Modified data/metals.lua from [f9ae7215e3] to [a6eaeb7ad1].
27 27 copper = { 28 28 dye = 'orange'; 29 29 ingot = 'default:copper_ingot'; 30 30 block = 'default:copperblock'; 31 31 tone = {255,176,61}; 32 32 no_tools = true; no_armor = true; 33 33 hardness = 2; 34 + conduct = 0.1; 34 35 }; 35 36 brass = { 36 37 tone = {255,226,87}; 37 38 dye = 'bright_orange'; 38 39 artificial = true; 39 40 no_tools = true; no_armor = true; 40 41 hardness = 3; ................................................................................ 136 137 no_armor = true; no_tools = true; 137 138 power = 1; cooktime = 8; hardness = 1; 138 139 }; 139 140 electrum = { 140 141 tone = {212, 255, 0}, alpha = 80; 141 142 artificial = true; 142 143 hardness = 1; 144 + conduct = 0.5; 143 145 dye = 'bright_green'; 144 146 mix = { 145 147 metals = { 146 148 silver = 1; 147 149 gold = 1; 148 150 }; 149 151 }; ................................................................................ 172 174 rarity = 17; 173 175 durabilty = 900; 174 176 hardness = 6; 175 177 power = 3; 176 178 speed = 3.5; 177 179 cooktime = 30; 178 180 maxenergy = 3500; 181 + conduct = 2.0; 179 182 slots = { 180 183 { 181 184 affinity = {'counterpraxic'}; 182 185 confluence = 0.65; 183 186 interference = {speed = 1}; 184 187 }; 185 188 } ................................................................................ 197 200 tone = {209,88,241}, alpha = 80; 198 201 dye = 'purple'; 199 202 rarity = 18; 200 203 meltpoint = 3; 201 204 cooktime = 340; 202 205 hardness = 7; 203 206 maxenergy = 1800; 207 + conduct = 5; 204 208 durability = 1900; 205 209 speed = 3.2; 206 210 img = { 207 211 -- ingot = 'sorcery_iridium_ingot.png'; 208 212 -- block = 'sorcery_iridium_block.png'; 209 213 }; 210 214 slots = { ................................................................................ 238 242 }; 239 243 impervium = { 240 244 tone = {226,255,107}, alpha = 90; 241 245 cooktime = 260; 242 246 meltpoint = 5; 243 247 artificial = true; 244 248 speed = 2.1; 245 - hardness = 20; 249 + hardness = 15; 246 250 durability = 5300; 247 251 maxenergy = 2300; 248 252 watercool = true; 249 253 mix = { 250 254 metals = { 251 255 duranium = 4; 252 256 iridium = 2; ................................................................................ 261 265 }; 262 266 eternium = { 263 267 tone = {156,82,222}, alpha = 100; 264 268 cooktime = 500; 265 269 meltpoint = 6; 266 270 artificial = true; 267 271 speed = 2; 268 - hardness = 9; 272 + hardness = 10; 269 273 maxenergy = 1200; 270 274 durability = 8100; 271 275 watercool = true; 272 276 mix = { 273 277 metals = { 274 278 iridium = 2; 275 279 tungsten = 2; 276 280 lithium = 1; 277 281 }; 278 282 }; 283 + sinter = { 284 + 'sorcery:powder_iridium'; 285 + 'sorcery:powder_iridium'; 286 + 'sorcery:powder_tungsten'; 287 + 'sorcery:powder_tungsten'; 288 + 'sorcery:powder_lithium'; 289 + }; 279 290 slots = { 280 291 {affinity={'praxic','entropic'}, confluence = 1.4}; 281 292 {affinity={'praxic','syncretic'}, confluence = 1.1}; 282 293 } 283 294 }; 284 295 unobtanium = { 285 296 tone = {114,255,214}, alpha = 120; 286 297 meltpoint = 3; 287 298 cooktime = 330; 288 299 artificial = true; 289 300 maxenergy = 4000; 290 301 hardness = 7; 291 302 durability = 3300; 303 + conduct = 15; 292 304 speed = 3.4; 293 305 slots = { 294 306 {affinity={'praxic'}, confluence = 0.7}; 295 307 {affinity={'counterpraxic'}, confluence = 1.2}; 296 308 {affinity={'cognic'}, confluence = 1.1}; 297 309 }; 298 310 mix = { ................................................................................ 299 311 metals = { 300 312 impervium = 8; 301 313 eternium = 4; 302 314 cobalt = 1; 303 315 }; 304 316 }; 305 317 }; 306 - -- draconium = {artificial=true;}; 307 - -- tyrannium = {artificial=true;}; 318 + draconium = { 319 + tone = {255,20,80}, alpha = 110; 320 + artificial=true; 321 + meltpoint = 5; 322 + cooktime = 120; 323 + hardness = 8; 324 + maxconduct = 10; 325 + speed = 1.7; 326 + maxenergy = 2200; 327 + durability = 1500; 328 + slots = { 329 + {affinity={'praxic'},confluence=3}; 330 + {affinity={'syncretic'},confluence=2}; 331 + }; 332 + sinter = { 333 + 'sorcery:powder_lithium'; 334 + 'sorcery:powder_aluminum'; 335 + 'sorcery:powder_iridium'; 336 + 'sorcery:oil_flame'; 337 + }; 338 + }; 339 + tyrannium = { 340 + tone = {46,255,245}, alpha = 80; 341 + artificial=true; 342 + hardness = 20; 343 + meltpoint = 6; 344 + cooktime = 240; 345 + maxenergy = 800; 346 + durability = 4000; 347 + speed = 3.0; 348 + slots = {}; 349 + }; 308 350 };
Modified data/spells.lua from [47b0c7f3e9] to [a738b55bd0].
384 384 local duration = (ctx.base.gem == 'amethyst' and 60) or 30 385 385 if ctx.base.gem == 'diamond' then 386 386 power = power * (math.random()*2) 387 387 range = range * (math.random()*2) 388 388 duration = duration * (math.random()*2) 389 389 end 390 390 local lum = math.ceil((power/maxpower) * minetest.LIGHT_MAX) 391 - print('setting lum',lum) 392 391 for i=1,power do 393 392 local pos = vector.add(center, { 394 393 x = math.random(-range,range); 395 394 z = math.random(-range,range); 396 395 y = math.random(0,range/2); 397 396 }) 398 397 local delta = vector.subtract(pos,center)
Modified enchanter.lua from [41724791de] to [15ff8624ed].
231 231 mesh = 'sorcery-enchanter.obj'; 232 232 paramtype = 'light'; 233 233 paramtype2 = 'facedir'; 234 234 groups = { cracky = 2, oddly_breakable_by_hand = 2 }; 235 235 sunlight_propagates = true; 236 236 selection_box = hitbox; 237 237 collision_box = hitbox; 238 + after_dig_node = sorcery.lib.node.purge_container; 238 239 tiles = { 239 240 "default_obsidian.png"; 240 241 "default_steel_block.png"; 241 242 "default_bronze_block.png"; 242 243 "default_junglewood.png"; 243 244 "default_gold_block.png"; 244 245 }; ................................................................................ 412 413 if ench.energy == 0 then 413 414 ench.spells = {} 414 415 sorcery.enchant.set(tool,ench) 415 416 else 416 417 sorcery.enchant.set(tool,ench,true) 417 418 end 418 419 puncher:set_wielded_item(tool) 420 + 421 + -- perform leyline checks and call notify if necessary 422 + if minetest.get_item_group(node.name, 'sorcery_ley_device') ~= 0 then 423 + for _,p in pairs(sorcery.ley.txofs) do 424 + local sum = vector.add(pos,p) 425 + if minetest.get_item_group(minetest.get_node(sum).name, 'sorcery_ley_device') ~= 0 then 426 + sorcery.ley.notify(sum) 427 + end 428 + end 429 + end 419 430 end) 420 431 421 432 minetest.register_chatcommand('enchants', { 422 433 description = 'Log information about the currently held object\'s enchantment'; 423 434 privs = { server = true }; 424 435 func = function(caller,params) 425 436 local tool = minetest.get_player_by_name(caller):get_wielded_item()
Added forcefield.lua version [4c792fc807].
1 +local constants = { 2 + cost_per_barrier = 0.1; 3 + -- 0.1 points of current will be required per second per 4 + -- unit of charge given to a barrier-block when ley-force 5 + -- of counterpraxic affinity is not available 6 +} 7 +local aimtbl = { 8 + [0] = {x = 0, y = 1, z = 0}; 9 + [1] = {x = 0, y = 0, z = 1}; 10 + [2] = {x = 0, y = 0, z = -1}; 11 + [3] = {x = 1, y = 0, z = 0}; 12 + [4] = {x = -1, y = 0, z = 0}; 13 + [5] = {x = 0, y = -1, z = 0}; 14 +} 15 +local pofstbl = { 16 + [0] = {x=0.5, y=0, z=0.5}; 17 + [1] = {x=0.5, y=0.5, z=0}; 18 + [2] = {x=0.5, y=0.5, z=0}; 19 + [3] = {x=0, y=0.5, z=0.5}; 20 + [4] = {x=0, y=0.5, z=0.5}; 21 + [5] = {x=0.5, y=0, z=0.5}; 22 +} 23 +local calc_cost = function(pos,time) 24 + local node = minetest.get_node(pos) 25 + local aim = aimtbl[math.floor(node.param2 / 4)] 26 + local tgts = {} 27 + for i=1,5 do 28 + local tpos = vector.add(pos, vector.multiply(aim,i)) 29 + local n = minetest.get_node(tpos) 30 + if n.name == 'air' then tgts[#tgts + 1] = {tpos,0} else 31 + local f = minetest.get_item_group(n.name, 'sorcery_force_barrier') 32 + if f > 0 then 33 + tgts[#tgts + 1] = {tpos,f} 34 + else break end 35 + end 36 + end 37 + return { 38 + aim = aim; 39 + maxcost = #tgts * constants.cost_per_barrier * time; 40 + mincost = math.min(1,#tgts) * constants.cost_per_barrier * time; 41 + targets = tgts; 42 + } 43 +end 44 +for i=1,10 do 45 + minetest.register_node('sorcery:air_barrier_' .. tostring(i), { 46 + drawtype = 'airlike'; 47 + walkable = true; 48 + pointable = false; 49 + sunlight_propagates = true; 50 + paramtype = 'light'; 51 + light_source = i; 52 + groups = { 53 + sorcery_force_barrier = i; 54 + }; 55 + -- _proto = { 56 + -- strength = i; 57 + -- }; 58 + on_construct = function(pos) 59 + minetest.get_node_timer(pos):start(1) 60 + end; 61 + on_timer = function(pos,delta) 62 + local dec = 40*delta 63 + local node = minetest.get_node(pos) 64 + local newstr = math.ceil(10 * ((node.param2 - dec) / 0xFF)) 65 + local newnode = 'sorcery:air_barrier_' .. tostring(newstr) 66 + if newstr <= 0 then 67 + minetest.remove_node(pos) 68 + return false 69 + else 70 + for _,c in pairs {{165,255,252}, {146,205,255}, {190,93,253}} do 71 + minetest.add_particlespawner { 72 + time = 1; 73 + amount = 15; 74 + minpos = vector.add(pos, -0.6); 75 + maxpos = vector.add(pos, 0.6); 76 + minvel = {x = 0, y = 0, z = 0}; 77 + maxvel = {x = 0, y = 0, z = 0}; 78 + minacc = {x = -0.1, y = -0.1, z = -0.1}; 79 + maxacc = {x = 0.1, y = 0.1, z = 0.1}; 80 + minexptime = 0.5; 81 + maxexptime = 1.0; 82 + minsize = 0.2; 83 + minsize = 0.7; 84 + texture = sorcery.lib.image('sorcery_spark.png'):multiply(sorcery.lib.color(c)):render(); 85 + glow = 14; 86 + animation = { 87 + length = 1.1; 88 + type = 'vertical_frames'; 89 + aspect_h = 16, aspect_w = 16; 90 + }; 91 + } 92 + end 93 + minetest.swap_node(pos, { 94 + name = newnode; 95 + param1 = node.param1; 96 + param2 = newstr; 97 + }) 98 + return true 99 + end 100 + end; 101 + }) 102 +end 103 +minetest.register_node('sorcery:emitter_barrier', { 104 + description = "Barrier Screen Emitter"; 105 + paramtype2 = 'facedir'; 106 + groups = { 107 + cracky = 2; 108 + sorcery_ley_device = 1; 109 + }; 110 + tiles = { 111 + 'sorcery_emitter_barrier_top.png'; 112 + 'sorcery_emitter_barrier_bottom.png'; 113 + 'sorcery_emitter_barrier_front.png^[transformR270'; 114 + 'sorcery_emitter_barrier_front.png^[transformFXR90'; 115 + 'sorcery_emitter_barrier_side.png'; 116 + 'sorcery_emitter_barrier_side.png'; 117 + }; 118 + on_construct = function(pos) 119 + minetest.get_node_timer(pos):start(1) 120 + end; 121 + on_timer = function(pos,delta) 122 + local orientation = math.floor(minetest.get_node(pos).param2 / 4) 123 + local costs = calc_cost(pos,delta) 124 + local l = sorcery.ley.netcaps(pos,delta) 125 + if l.self.powerdraw >= costs.mincost then 126 + local dist = l.self.powerdraw / (constants.cost_per_barrier * delta) 127 + for i=1,math.floor(dist) do 128 + local t = costs.targets[i] 129 + local str = math.min(0xFF,t[2] + 50*delta); 130 + minetest.swap_node(t[1], { 131 + name = 'sorcery:air_barrier_' .. math.max(1, math.floor(10*(str/0xFF))); 132 + param2 = str; 133 + }) 134 + minetest.get_node_timer(t[1]):start(1) 135 + end 136 + 137 + local pn = vector.add(pos, vector.divide(costs.aim,2)); 138 + local pp = vector.add(pn, pofstbl[orientation]) 139 + pn = vector.subtract(pn, pofstbl[orientation]) 140 + 141 + minetest.add_particlespawner { 142 + time = 1; 143 + amount = 20 * dist; 144 + minpos = pn; 145 + maxpos = pp; 146 + minvel = costs.aim; 147 + maxvel = vector.multiply(costs.aim,2); 148 + minsize = 0.3; 149 + maxsize = 0.5; 150 + minexptime = dist*0.5; 151 + maxexptime = dist*0.5; 152 + texture = sorcery.lib.image('sorcery_spark.png'):multiply(sorcery.lib.color(240,255,160)):render(); 153 + glow = 14; 154 + animation = { 155 + length = dist + 0.1; 156 + type = 'vertical_frames'; 157 + aspect_h = 16, aspect_w = 16; 158 + }; 159 + } 160 + return true 161 + end 162 + return false 163 + end; 164 + after_place_node = function(pos, placer, stack, point) 165 + local vec = vector.subtract(point.under, pos) 166 + local n = minetest.get_node(pos) 167 + n.param2 = minetest.dir_to_facedir(vec) 168 + minetest.swap_node(pos,n) 169 + end; 170 + _sorcery = { 171 + ley = { 172 + mode='consume', affinity={'counterpraxic'}, 173 + power = function(pos,time) 174 + local l = calc_cost(pos,time) 175 + return l.mincost, l.maxcost 176 + end; 177 + }; 178 + on_leychange = function(pos) 179 + minetest.get_node_timer(pos):start(1) 180 + end; 181 + }; 182 +})
Modified harvester.lua from [8384a43ac0] to [97dec98beb].
15 15 16 16 minetest.register_node('sorcery:harvester', { 17 17 description = 'Harvester'; 18 18 drawtype = 'mesh'; 19 19 paramtype = 'light'; 20 20 paramtype2 = 'facedir'; 21 21 mesh = 'sorcery-harvester.obj'; 22 + after_dig_node = sorcery.lib.node.purge_container; 22 23 groups = { cracky = 2; oddly_breakable_by_hand = 1; }; 23 24 sunlight_propagates = true; 24 25 selection_box = hitbox; 25 26 collision_box = hitbox; 26 27 tiles = { 27 28 amethyst:render(); 28 29 'default_copper_block.png';
Modified infuser.lua from [c06011384f] to [3997cbe28f].
194 194 end 195 195 196 196 minetest.register_node("sorcery:infuser", { 197 197 description = "Infuser"; 198 198 drawtype = "mesh"; 199 199 mesh = "infuser.obj"; 200 200 paramtype2 = "facedir"; 201 + after_dig_node = sorcery.lib.node.purge_container; 201 202 tiles = { -- FIXME 202 203 "default_stone.png", 203 204 "default_copper_block.png", 204 205 "default_steel_block.png", 205 206 "default_bronze_block.png", 206 207 "default_tin_block.png", 207 208 };
Modified init.lua from [8277bf1fce] to [752c791349].
25 25 -- and load them automatically, as interdependencies 26 26 -- exist (especially with /lib) and we need to be very 27 27 -- careful about the order they're loaded in 28 28 29 29 sorcery.unit('data') {'ui'} 30 30 sorcery.unit('lib') { 31 31 -- convenience 32 - 'str'; 32 + 'str', 'node'; 33 33 -- serialization 34 34 'marshal', 'json'; 35 35 -- data structures 36 36 'tbl', 'class'; 37 37 -- wrappers 38 38 'color', 'image', 'ui'; 39 39 } ................................................................................ 47 47 'potions', 'oils', 'greases', 48 48 'draughts', 'elixirs', 49 49 'philters', 'extracts'; 50 50 'register'; 51 51 } 52 52 53 53 for _,u in pairs { 54 - 'leylines'; 'ores'; 'gems'; 54 + 'ores'; 'gems'; 'leylines'; 55 55 'potions'; 'infuser'; 'altar'; 'wands'; 56 56 'tools'; 'enchanter'; 'harvester'; 57 57 'metallurgy-hot', 'metallurgy-cold'; 58 58 'entities'; 'recipes'; 'coins'; 59 - 'interop'; 'tnodes'; 59 + 'interop'; 'tnodes'; 'forcefield'; 60 60 } do sorcery.load(u) end
Modified leylines.lua from [112e3b2a50] to [8532b8e5fe].
71 71 output = 'sorcery:conduit 4'; 72 72 recipe = { 73 73 {'default:copper_ingot', 'default:copper_ingot', 'default:copper_ingot'}; 74 74 {'default:copper_ingot', 'sorcery:electrumblock', 'default:copper_ingot'}; 75 75 {'default:copper_ingot', 'default:copper_ingot', 'default:copper_ingot'}; 76 76 }; 77 77 }; 78 -minetest.register_craft { 79 - output = 'sorcery:wire 4'; 80 - recipe = { 81 - {'', 'basic_materials:copper_wire',''}; 82 - {'', 'sorcery:fragment_electrum', ''}; 83 - {'', 'basic_materials:copper_wire',''}; 78 + 79 +local makeswitch = function(switch, desc, tex, tiles, power) 80 + for _,active in pairs{true,false} do 81 + local turn = function(pos) 82 + local n = minetest.get_node(pos) 83 + minetest.sound_play('doors_steel_door_open', { 84 + gain = 0.7; 85 + pos = pos; 86 + }, true) 87 + local leymap = active and sorcery.ley.mapnet(pos) or nil 88 + minetest.swap_node(pos, { 89 + name = active and (switch .. '_off') 90 + or switch; 91 + param1 = n.param1; 92 + param2 = n.param2; 93 + }) 94 + if active then 95 + -- if we're turning it off, use the old map, 96 + -- because post-swap the network will be 97 + -- broken and notify won't reach everyone 98 + leymap.map[leymap.startpos] = nil 99 + sorcery.ley.notifymap(leymap.map) 100 + else sorcery.ley.notify(pos) end 101 + end 102 + local tl = table.copy(tiles) 103 + tl[6] = tex .. '^sorcery_ley_switch_panel.png^sorcery_ley_switch_' .. (active and 'down' or 'up') .. '.png'; 104 + minetest.register_node(switch .. (active and '' or '_off'), { 105 + description = desc; 106 + drop = switch; 107 + tiles = tl; 108 + paramtype2 = 'facedir'; 109 + groups = { 110 + cracky = 2; choppy = 1; 111 + punch_operable = 1; 112 + sorcery_ley_device = active and 1 or 0; 113 + }; 114 + _sorcery = { 115 + ley = active and { 116 + mode = 'signal'; power = power; 117 + } or nil; 118 + }; 119 + on_punch = function(pos,node,puncher,point) 120 + if puncher ~= nil then 121 + if puncher:get_wielded_item():is_empty() then 122 + turn(pos) 123 + end 124 + end 125 + return minetest.node_punch(pos,node,puncher,point) 126 + end; 127 + on_rightclick = turn; 128 + }) 129 + end 130 +end 131 + 132 +for _,b in pairs { 133 + {'Applewood', 'wood', 'default_wood.png'}; 134 + {'Junglewood', 'junglewood', 'default_junglewood.png'}; 135 + {'Pine', 'pine_wood', 'default_pine_wood.png'}; 136 + {'Acacia', 'acacia_wood', 'default_pine_wood.png'}; 137 + {'Aspen', 'aspen_wood', 'default_aspen_wood.png'}; 138 + {'Stone', 'stone', 'default_stone.png'}; 139 + {'Cobblestone', 'cobble', 'default_cobble.png'}; 140 + {'Stone Brick', 'stonebrick', 'default_stone_brick.png'}; 141 + {'Brick', 'brick', 'default_brick.png'}; 142 +} do 143 + local id = 'sorcery:conduit_half_' .. b[2] 144 + local switch = 'sorcery:conduit_switch_' .. b[2] 145 + local item = (b[4] or 'default') .. ':' .. b[2] 146 + local tex = b[3] 147 + local mod = '^[lowpart:50:' 148 + local sidemod = '^[transformR270^[lowpart:50:' 149 + local unflip = '^[transformR90' 150 + local tiles = { 151 + 'sorcery_conduit_copper_top.png'..mod..tex; -- top 152 + tex..mod..'sorcery_conduit_copper_top.png'; 153 + tex .. sidemod .. 'sorcery_conduit_copper_side.png' .. unflip; -- side 154 + 'sorcery_conduit_copper_side.png' .. sidemod .. tex .. unflip; -- side 155 + 'sorcery_conduit_copper_side.png'; -- back 156 + tex; -- front 157 + } 158 + minetest.register_node(id, { 159 + description = 'Half-' .. b[1] .. ' Conduit'; 160 + paramtype2 = 'facedir'; 161 + groups = { 162 + cracky = 2; 163 + choppy = 1; 164 + sorcery_ley_device = 1; 165 + sorcery_ley_conduit = 1; 166 + }; 167 + _sorcery = { 168 + ley = { mode = 'signal'; power = 5; } 169 + }; 170 + tiles = tiles; 171 + }) 172 + minetest.register_craft { 173 + output = id .. ' 4'; 174 + recipe = { 175 + {item, 'sorcery:conduit'}; 176 + {item, 'sorcery:conduit'}; 177 + }; 178 + }; 179 + makeswitch(switch, b[1] .. " Conduit Switch", tex, tiles, 5) 180 + minetest.register_craft { 181 + output = switch; 182 + recipe = { 183 + {'xdecor:lever_off',id}; 184 + }; 84 185 } 85 -}; 186 +end 187 +makeswitch('sorcery:conduit_switch', "Conduit Switch", 'sorcery_conduit_copper_side.png', { 188 + 'sorcery_conduit_copper_top.png'; 189 + 'sorcery_conduit_copper_top.png'; 190 + 'sorcery_conduit_copper_side.png'; 191 + 'sorcery_conduit_copper_side.png'; 192 + 'sorcery_conduit_copper_side.png'; 193 + 'sorcery_conduit_copper_side.png'; 194 +}, 10) 195 +minetest.register_craft { 196 + output = 'sorcery:conduit_switch'; 197 + recipe = { 198 + {'xdecor:lever_off','sorcery:conduit'}; 199 + }; 200 +} 201 + 202 +for name,metal in pairs(sorcery.data.metals) do 203 + if metal.conduct then 204 + local cable = 'sorcery:cable_' .. name 205 + minetest.register_node(cable, { 206 + description = sorcery.lib.str.capitalize(name) .. " Cable"; 207 + drawtype = 'nodebox'; 208 + groups = { 209 + sorcery_ley_device = 1; snappy = 3; attached = 1; 210 + sorcery_ley_cable = 1; 211 + }; 212 + _sorcery = { 213 + ley = { mode = 'signal', power = metal.conduct }; 214 + }; 215 + sunlight_propagates = true; 216 + node_box = { 217 + type = 'connected'; 218 + disconnected = { -0.05, -0.35, -0.40; 0.05, -0.25, 0.40 }; 219 + connect_front = { -0.05, -0.35, -0.50; 0.05, -0.25, 0.05 }; 220 + connect_back = { -0.05, -0.35, -0.05; 0.05, -0.25, 0.50 }; 221 + connect_right = { -0.05, -0.35, -0.05; 0.50, -0.25, 0.05 }; 222 + connect_left = { -0.50, -0.35, -0.05; 0.05, -0.25, 0.05 }; 223 + connect_top = { -0.05, -0.25, -0.05; 0.05, 0.50, 0.05 }; 224 + connect_bottom = { -0.05, -0.50, -0.05; 0.05, -0.35, 0.05 }; 225 + }; 226 + connects_to = { 'group:sorcery_ley_device', 'default:mese' }; 227 + -- harcoding mese is kind of cheating -- figure out a 228 + -- better way to do this for the longterm 229 + paramtype = 'light'; 230 + -- paramtype2 = 'facedir'; 231 + after_place_node = function(pos, placer, stack, point) 232 + local vec = vector.subtract(point.under, pos) 233 + local n = minetest.get_node(pos) 234 + n.param2 = minetest.dir_to_facedir(vec) 235 + minetest.swap_node(pos,n) 236 + end; 237 + tiles = { 'sorcery_ley_plug.png' }; 238 + }) 239 + 240 + minetest.register_craft { 241 + output = cable .. ' 8'; 242 + recipe = { 243 + {'basic_materials:copper_wire','basic_materials:copper_wire','basic_materials:copper_wire'}; 244 + { metal.parts.fragment, metal.parts.fragment, metal.parts.fragment }; 245 + {'basic_materials:copper_wire','basic_materials:copper_wire','basic_materials:copper_wire'}; 246 + }; 247 + replacements = { 248 + {'basic_materials:copper_wire', 'basic_materials:empty_spool'}; 249 + {'basic_materials:copper_wire', 'basic_materials:empty_spool'}; 250 + {'basic_materials:copper_wire', 'basic_materials:empty_spool'}; 251 + {'basic_materials:copper_wire', 'basic_materials:empty_spool'}; 252 + {'basic_materials:copper_wire', 'basic_materials:empty_spool'}; 253 + {'basic_materials:copper_wire', 'basic_materials:empty_spool'}; 254 + }; 255 + }; 256 + end 257 +end 258 + 259 +-- ley.notify will normally be called automatically, but if a 260 +-- ley-producer or consume has fluctuating levels of energy 261 +-- consumption, it should call this function when levels change 262 +sorcery.ley.notifymap = function(map) 263 + for pos,name in pairs(map) do 264 + local props = minetest.registered_nodes[name]._sorcery 265 + if props and props.on_leychange then 266 + props.on_leychange(pos) 267 + end 268 + end 269 +end 270 +sorcery.ley.notify = function(pos) 271 + local n = sorcery.ley.mapnet(pos) 272 + sorcery.ley.notifymap(n.map) 273 +end 86 274 87 275 sorcery.ley.field_to_current = function(strength,time) 88 276 local ley_factor = 0.25 89 277 -- a ley harvester will produce this much current with 90 278 -- access to a full-strength leyline 91 279 92 280 return strength * ley_factor * time; ................................................................................ 102 290 -0.5, -0.5, -0.5; 103 291 0.5, 1.2, 0.5; 104 292 }; 105 293 }; 106 294 minetest.register_node('sorcery:condenser', { 107 295 description = 'Condenser'; 108 296 drawtype = 'mesh'; 297 + paramtype2 = 'facedir'; 109 298 mesh = 'sorcery-condenser.obj'; 110 299 selection_box = box; 111 300 collision_box = box; 112 301 tiles = { 113 302 amethyst:render(); 114 303 'sorcery_condenser.png'; 115 304 'default_tin_block.png'; ................................................................................ 122 311 sorcery_ley_device = 1; 123 312 }; 124 313 on_construct = function(pos) 125 314 local meta = minetest.get_meta(pos) 126 315 meta:set_string('infotext','Condenser') 127 316 end; 128 317 _sorcery = { 129 - ley = { mode = 'produce' }; 130 - on_leycalc = function(pos,time) 131 - local l = sorcery.ley.estimate(pos) 132 - return { 133 - power = sorcery.ley.field_to_current(l.force, time); 134 - affinity = l.aff; 135 - } 136 - end; 318 + ley = { mode = 'produce'; 319 + power = function(pos,time) 320 + return sorcery.ley.field_to_current(sorcery.ley.estimate(pos).force, time); 321 + end; 322 + affinity = function(pos) 323 + return sorcery.ley.estimate(pos).aff 324 + end; 325 + }; 137 326 }; 138 327 }) 139 328 end 140 329 141 330 minetest.register_craft { 142 331 output = 'sorcery:condenser'; 143 332 recipe = { 144 333 {'sorcery:accumulator'}; 145 334 {'sorcery:conduit'}; 146 335 }; 147 336 } 337 +sorcery.ley.txofs = { 338 + {x = 0, z = 0, y = 0}; 339 + {x = -1, z = 0, y = 0}; 340 + {x = 1, z = 0, y = 0}; 341 + {x = 0, z = -1, y = 0}; 342 + {x = 0, z = 1, y = 0}; 343 + {x = 0, z = 0, y = -1}; 344 + {x = 0, z = 0, y = 1}; 345 +} 148 346 sorcery.ley.mapnet = function(startpos,power) 149 347 -- this function returns a list of all the nodes accessible from 150 348 -- a ley network and their associated positions 151 - local net = {} 349 + local net,checked = {},{} 152 350 power = power or 0 153 351 154 352 local devices = { 155 353 consume = {}; 156 354 produce = {}; 157 355 signal = {}; 158 356 } 159 357 local numfound = 0 160 358 local maxconduct = 0 161 359 local minconduct 360 + local startkey 162 361 local foundp = function(p) 163 - for k in pairs(net) do 362 + for _,k in pairs(checked) do 164 363 if vector.equals(p,k) then return true end 165 364 end 166 365 return false 167 366 end 168 367 -- we're implementing this with a recursive function to start with 169 368 -- but this could rapidly lead to stack overflows so we should 170 369 -- replace it with a linear one at some point 171 370 local function find(positions) 172 371 local searchnext = {} 173 372 for _,pos in pairs(positions) do 174 - for _,p in pairs { 175 - {x = 0, z = 0, y = 0}; 176 - {x = -1, z = 0, y = 0}; 177 - {x = 1, z = 0, y = 0}; 178 - {x = 0, z = -1, y = 0}; 179 - {x = 0, z = 1, y = 0}; 180 - {x = 0, z = 0, y = -1}; 181 - {x = 0, z = 0, y = 1}; 182 - } do local sum = vector.add(pos,p) 373 + for _,p in pairs(sorcery.ley.txofs) do 374 + local sum = vector.add(pos,p) 183 375 if not foundp(sum) then 376 + checked[#checked + 1] = sum 184 377 local nodename = minetest.get_node(sum).name 378 + if nodename == 'ignore' then 379 + minetest.load_area(sum) 380 + nodename = minetest.get_node(sum).name 381 + end 185 382 if minetest.get_item_group(nodename,'sorcery_ley_device') ~= 0 186 383 or sorcery.data.compat.ley[nodename] then 187 - local d = sorcery.ley.sample(pos,1,nodename) 384 + local d = sorcery.ley.sample(pos,1,nodename,{query={mode=true}}) 188 385 assert(d.mode == 'signal' 189 386 or d.mode == 'consume' 190 387 or d.mode == 'produce') 191 388 devices[d.mode][#(devices[d.mode]) + 1] = { 192 389 id = nodename; pos = sum; 193 390 } 194 391 if d.mode == 'signal' then 392 + d.power = sorcery.ley.sample(pos,1,nodename,{query={power=true}}).power 195 393 if d.power > power then 196 394 if minconduct then 197 395 if d.power < minconduct then 198 396 minconduct = d.power 199 397 end 200 398 else minconduct = d.power end 201 399 if d.power > maxconduct then 202 400 maxconduct = d.power 203 401 end 204 402 end 205 403 end 206 404 numfound = numfound + 1; 207 405 net[sum] = nodename; 406 + if not startkey then 407 + if vector.equals(startpos,sum) then 408 + startkey = sum 409 + end 410 + end 208 411 searchnext[#searchnext + 1] = sum; 209 412 end 210 413 end 211 414 end 212 415 end 213 416 if #searchnext > 0 then find(searchnext) end 214 417 end ................................................................................ 216 419 find{startpos} 217 420 218 421 if numfound > 0 then 219 422 return { 220 423 count = numfound; 221 424 map = net; 222 425 devices = devices; 426 + startpos = startkey; 223 427 conduct = { 224 428 min = minconduct; 225 429 max = maxconduct; 226 430 }; 227 431 } 228 432 else return nil end 229 433 end ................................................................................ 241 445 [3] = 'signal'; 242 446 } 243 447 for i=1,#afftbl do afftbl [afftbl [i]] = i end 244 448 for i=1,#modetbl do modetbl[modetbl[i]] = i end 245 449 local m = sorcery.lib.marshal 246 450 local enc, dec = m.transcoder { 247 451 mode = m.t.u8; 248 - power = m.t.u32; -- power generated/consumed * 10,000 452 + minpower = m.t.u32; -- min power generated/consumed * 10,000 453 + maxpower = m.t.u32; -- max power generated/consumed * 10,000 249 454 affinity = m.g.array(m.t.u8); -- indexes into afftbl 250 455 } 251 456 sorcery.ley.encode = function(l) 252 457 local idxs = {} 253 458 for _,k in pairs(l.affinity) do 254 459 idxs[#idxs+1] = afftbl[k] 255 460 end 256 461 return meta_armor(enc { 257 462 mode = modetbl[l.mode]; 258 - power = l.power * 10000; 463 + minpower = l.minpower * 10000; 464 + maxpower = l.maxpower * 10000; 259 465 affinity = idxs; 260 466 }, true) 261 467 end 262 468 sorcery.ley.decode = function(str) 263 469 local obj = dec(meta_dearmor(str,true)) 264 470 local affs = {} 265 471 for _,k in pairs(obj.affinity) do 266 472 affs[#affs+1] = afftbl[k] 267 473 end 268 474 return { 269 475 mode = modetbl[obj.mode]; 270 - power = obj.power / 10000.0; 476 + minpower = obj.minpower / 10000.0; 477 + maxpower = obj.maxpower / 10000.0; 478 + power = (obj.minpower == obj.maxpower) and obj.minpower or nil; 271 479 affinity = affs; 272 480 } 273 481 end 274 482 end 275 483 sorcery.ley.setnode = function(pos,l) 276 484 local meta = minetest.get_node(pos) 277 485 meta:set_string('sorcery:ley',sorcery.ley.encode(l)) 278 486 end 279 487 280 -sorcery.ley.sample = function(pos,timespan,name) 488 +sorcery.ley.sample = function(pos,timespan,name,flags) 281 489 -- returns how much ley-force can be transmitted by a 282 490 -- device over timespan 491 + local ret = {} 283 492 name = name or minetest.get_node(pos).name 493 + flags = flags or {} 494 + flags.query = flags.query or { 495 + mode = true; power = true; affinity = true; 496 + minpower = true; maxpower = true; 497 + } 284 498 local props = minetest.registered_nodes[name]._sorcery 285 - local callback = props and props.on_leycalc or nil 286 - local p,a,m 287 - if callback then 288 - local gen = callback(pos,timespan) 289 - p = gen.power 290 - a = gen.affinity 291 - m = gen.mode 499 + 500 + local evaluate = function(v) 501 + if type(v) == 'function' then 502 + return v(pos) 503 + else return v end 292 504 end 293 505 294 - if not (p and a and m) then 506 + local leymeta do 295 507 local nm = minetest.get_meta(pos) 296 508 if nm:contains('sorcery:ley') then 297 - local l = sorcery.ley.decode(nm:get_string('sorcery:ley')) 298 - p = p or sorcery.ley.field_to_current(l.power,timespan) 299 - a = a or l.affinity 300 - m = m or l.mode 509 + leymeta = sorcery.ley.decode(nm:get_string('sorcery:ley')) 510 + end 511 + end 512 + 513 + local compat = sorcery.data.compat.ley[name] 514 + 515 + local lookup = function(k,default) 516 + if leymeta and leymeta[k] then return leymeta[k] 517 + elseif props and props.ley and props.ley[k] then return props.ley[k] 518 + elseif compat and compat[k] then return compat[k] 519 + else return default end 520 + end 521 + if flags.query.mode then ret.mode = evaluate(lookup('mode','none')) end 522 + if flags.query.affinity then ret.affinity = evaluate(lookup('affinity',{})) end 523 + if flags.query.minpower or flags.query.maxpower or flags.query.power then 524 + local condset = function(name,var) 525 + if flags.query[name] then ret[name] = var end 526 + end 527 + local p = lookup('power') 528 + if p then 529 + if type(p) == 'function' then 530 + -- we have a single function to calculate power usage; we need to 531 + -- check whether it returns min,max or a constant 532 + local min, max = p(pos,timespan) 533 + if (not max) or min == max then 534 + ret.power = min 535 + condset('power',min) 536 + condset('minpower',min) 537 + condset('maxpower',min) 538 + else 539 + condset('minpower',min) 540 + condset('maxpower',max) 541 + end 542 + else -- power usage is simply a constant 543 + condset('power',p) 544 + condset('minpower',p) 545 + condset('maxpower',p) 546 + end 547 + else 548 + local feval = function(v) 549 + if type(v) == 'function' then 550 + return v(pos,timespan) 551 + else return v * timespan end 552 + end 553 + local min = feval(lookup('minpower')) 554 + local max = feval(lookup('maxpower')) 555 + condset('minpower',min) 556 + condset('maxpower',max) 557 + if min == max then condset('power',min) end 301 558 end 302 559 end 303 560 304 - if (not (p and a and m)) and props and props.ley then 305 - p = p or sorcery.ley.field_to_current(props.ley.power,timespan) 306 - a = a or props.ley.affinity 307 - m = m or props.ley.mode 561 + if ret.power then 562 + if flags.query.minpower and not ret.minpower then ret.minpower = power end 563 + if flags.query.maxpower and not ret.maxpower then ret.maxpower = power end 308 564 end 309 - 310 - if (not (p and a and m)) then 311 - local compat = sorcery.data.compat.ley[name] 312 - if compat then 313 - p = p or sorcery.ley.field_to_current(compat.power,timespan) 314 - a = a or compat.affinity 315 - m = m or compat.mode 316 - end 317 - end 318 - 319 - return { 320 - power = p or 0; 321 - mode = m or 'none'; 322 - affinity = a or {}; 323 - } 565 + return ret 324 566 end 325 567 326 568 sorcery.ley.netcaps = function(pos,timespan,exclude) 327 569 local net = sorcery.ley.mapnet(pos) 328 570 local maxpower = 0 329 571 local freepower = 0 330 572 local affs,usedaffs = {},{} 573 + local flexpowerdevs = {} 574 + local devself 331 575 for _,n in pairs(net.devices.produce) do 576 + if vector.equals(pos,n.pos) then devself = n end 332 577 if not exclude or not vector.equals(n.pos,exclude) then 333 578 local ln = sorcery.ley.sample(n.pos,timespan,n.id) 579 + n.powersupply = ln.power 580 + n.affinity = ln.affinity 334 581 maxpower = maxpower + ln.power 582 + -- production power does not vary, tho at some point it 583 + -- might be useful to enable some kind of power scaling 335 584 for _,a in pairs(ln.affinity) do 336 585 affs[a] = (affs[a] or 0) + 1 337 586 end 338 587 end 339 588 end 340 589 freepower = maxpower; 341 590 for _,n in pairs(net.devices.consume) do 591 + if vector.equals(pos,n.pos) then devself = n end 342 592 if not exclude or not vector.equals(n.pos,exclude) then 343 - local ln = sorcery.ley.sample(n.pos,timespan,n.id) 344 - freepower = freepower - ln.power 593 + local ln = sorcery.ley.sample(n.pos,timespan,n.id, { 594 + query = { power = true; minpower = true; maxpower = true; affinity = true; }; 595 + }) 596 + n.powerdraw = (ln.minpower <= freepower) and ln.minpower or 0 597 + freepower = freepower - n.powerdraw 598 + -- merge in sample data and return it along with the map 599 + n.minpower = ln.minpower 600 + n.maxpower = ln.maxpower 601 + n.affinity = ln.affinity 602 + if ln.maxpower > ln.minpower then 603 + flexpowerdevs[#flexpowerdevs+1] = n 604 + end 345 605 for _,a in pairs(ln.affinity) do 346 606 usedaffs[a] = (usedaffs[a] or 0) + 1 347 607 end 348 608 end 349 609 end 610 + 611 + -- now we know the following: all devices; if possible, have been 612 + -- given the minimum amount of power they need to run. if freepower 613 + -- < 0 then the network is overloaded and inoperable. if freepower>0, 614 + -- we now need to distribute the remaining power to devices that 615 + -- have a variable power consumption. there's no clean way of doing 616 + -- this, so we use the following algorithm: 617 + -- 1. take a list of devices that want more power 618 + -- 2. divide the amount of free power by the number of such devices 619 + -- to derive the maximum power that can be allocated to any device 620 + -- 3. iterate through the devices. increase their power consumption by 621 + -- the maximum term. any device that is satiated can be removed from 622 + -- the list. 623 + -- 4. if there is still power remaining, repeat until there is not. 624 + 625 + while freepower > 0 and #flexpowerdevs > 0 do 626 + local nextiter = {} 627 + local maxgive = freepower / #flexpowerdevs 628 + for _,d in pairs(flexpowerdevs) do 629 + local give = math.min(maxgive,d.maxpower - d.powerdraw) 630 + freepower = freepower - give 631 + d.powerdraw = d.powerdraw + give 632 + if d.powerdraw < d.maxpower then 633 + nextiter[#nextiter+1] = d 634 + end 635 + end 636 + flexpowerdevs = nextiter 637 + end 350 638 351 639 return { 352 640 net = net; 353 641 freepower = freepower; 354 642 maxpower = maxpower; 355 643 affinity = affs; 356 644 affinity_balance = usedaffs; 645 + self = devself; 357 646 } 358 647 end 648 + 649 +minetest.register_on_placenode(function(pos, node) 650 + if minetest.get_item_group(node.name, 'sorcery_ley_device') ~= 0 then 651 + sorcery.ley.notify(pos) 652 + end 653 +end) 654 + 655 +local constants = { 656 + generator_max_energy_output = 5; 657 + -- how much energy a generator makes after 658 + 659 + generator_time_to_max_energy = 150; 660 + -- seconds of activity 661 + 662 + generator_power_drain_speed = 0.1; 663 + -- points of energy output drained per second of no fuel 664 +} 665 +local update_generator = function(pos) 666 + minetest.get_node_timer(pos):start(1) 667 +end 668 +local generator_update_formspec = function(pos) 669 + local meta = minetest.get_meta(pos) 670 + local burnprog = math.min(1,meta:get_float('burnleft') / meta:get_float('burntime')) 671 + local power = meta:get_float('power') 672 + local inv = meta:get_inventory() 673 + local lamps = '' 674 + for i=0,4 do 675 + local color 676 + if power - i >= 1 then 677 + color = 'red' 678 + elseif power - i > 0 then 679 + color = 'yellow' 680 + else 681 + color = 'off' 682 + end 683 + lamps = lamps .. string.format([[ 684 + image[%f,0.5;1,1;sorcery_statlamp_%s.png] 685 + ]], 2.5 + i, color) 686 + end 687 + meta:set_string('formspec', string.format([[ 688 + size[8,5.8] 689 + list[context;fuel;0.5,0.5;1,1] 690 + list[current_player;main;0,2;8,4] 691 + image[1.5,0.5;1,1;default_furnace_fire_bg.png^[lowpart:%u%%:default_furnace_fire_fg.png] 692 + ]], math.floor(burnprog * 100)) .. lamps) 693 +end 694 +for _,active in pairs{true,false} do 695 + local id = 'sorcery:generator' .. (active and '_active' or '') 696 + minetest.register_node(id, { 697 + description = 'Generator'; 698 + paramtype2 = 'facedir'; 699 + groups = { cracky = 2; sorcery_ley_device = 1; }; 700 + drop = 'sorcery:generator'; 701 + tiles = { 702 + 'sorcery_ley_generator_top.png'; 703 + 'sorcery_ley_generator_bottom.png'; 704 + 'sorcery_ley_generator_side.png'; 705 + 'sorcery_ley_generator_side.png'; 706 + 'sorcery_ley_generator_back.png'; 707 + 'sorcery_ley_generator_front_' .. (active and 'on' or 'off') .. '.png'; 708 + }; 709 + on_construct = function(pos) 710 + local meta = minetest.get_meta(pos) 711 + local inv = meta:get_inventory() 712 + meta:set_string('infotext','Generator') 713 + meta:set_float('burntime',0) 714 + meta:set_float('burnleft',0) 715 + meta:set_float('power',0) 716 + generator_update_formspec(pos) 717 + inv:set_size('fuel',1) 718 + end; 719 + after_dig_node = sorcery.lib.node.purge_container; 720 + on_metadata_inventory_put = update_generator; 721 + on_metadata_inventory_take = update_generator; 722 + on_timer = function(pos,delta) 723 + local meta = minetest.get_meta(pos) 724 + local inv = meta:get_inventory() 725 + local self = minetest.get_node(pos) 726 + local timeleft = meta:get_float('burnleft') - delta 727 + local again = false 728 + local power = meta:get_float('power') 729 + local burning = active 730 + if timeleft < 0 then timeleft = 0 end 731 + if not active or timeleft == 0 then 732 + if inv:is_empty('fuel') then 733 + -- no fuel, can't start/keep going. drain power if 734 + -- necessary, otherwise bail 735 + burning = false 736 + if power > 0 then 737 + power = math.max(0, power - constants.generator_power_drain_speed) 738 + again = true 739 + end 740 + else 741 + -- fuel is present, let's burn it 742 + local res,decin = minetest.get_craft_result { 743 + method = 'fuel'; 744 + items = {inv:get_stack('fuel',1)}; 745 + } 746 + meta:set_float('burntime',res.time) 747 + timeleft = res.time 748 + inv:set_stack('fuel',1,decin.items[1]) 749 + again = true 750 + burning = true 751 + end 752 + else 753 + local eps = constants.generator_max_energy_output / constants.generator_time_to_max_energy 754 + power = math.min(constants.generator_max_energy_output, power + eps*delta) 755 + again = true 756 + end 757 + ::stop:: meta:set_float('power',power) 758 + meta:set_float('burnleft',timeleft) 759 + generator_update_formspec(pos) 760 + if burning and not active then 761 + minetest.swap_node(pos, { 762 + name = 'sorcery:generator_active'; 763 + param1 = self.param1, param2 = self.param2; 764 + }) 765 + elseif active and not burning then 766 + minetest.swap_node(pos, { 767 + name = 'sorcery:generator'; 768 + param1 = self.param1, param2 = self.param2; 769 + }) 770 + end 771 + return again 772 + end; 773 + allow_metadata_inventory_put = function(pos,listname,index,stack,user) 774 + local res = minetest.get_craft_result { 775 + method = 'fuel'; 776 + items = {stack}; 777 + } 778 + if res.time ~= 0 then return stack:get_count() 779 + else return 0 end 780 + end; 781 + _sorcery = { 782 + ley = { 783 + mode = 'produce', affinity = {'praxic'}; 784 + power = function(pos,delta) 785 + local meta = minetest.get_meta(pos) 786 + return meta:get_float('power') * delta; 787 + end; 788 + }; 789 + }; 790 + }) 791 +end
Added lib/node.lua version [a0d38cfe10].
1 +return { 2 + purge_container = function(pos,node,meta,user) 3 + local offset = function(pos,range) 4 + local r = function(min,max) 5 + return (math.random() * (max - min)) + min 6 + end 7 + return { 8 + x = pos.x + r(0 - range, range); 9 + y = pos.y; 10 + z = pos.z + r(0 - range, range); 11 + } 12 + end 13 + for name, inv in pairs(meta.inventory) do 14 + for _, item in pairs(inv) do 15 + if not item:is_empty() then 16 + minetest.add_item(offset(pos,0.4), item) 17 + end 18 + end 19 + end 20 + end; 21 +}
Modified metallurgy-cold.lua from [c21bb1a7ca] to [c1d9a4ce4b].
34 34 35 35 metal_grindvalue = 4; 36 36 -- how many powders an ingot is worth 37 37 38 38 default_grindvalue = 1; 39 39 -- number of items produced when not otherwise 40 40 -- specified 41 + 42 + default_grindcost = 1; 43 + -- number of items needed to perform a grind when 44 + -- not otherwise specified 41 45 42 46 default_hardness = 1; 43 47 -- difficulty to grind an item when not otherwise 44 48 -- specified 45 49 46 50 metal_grindcost = 1; 47 51 -- number of metal items needed to perform a grind 48 52 } 49 53 local mill_formspec_update = function(pos,pct,stat1,stat2) 50 54 -- eventually we'll want to display available 51 - -- energy here, but for now we're just assuming 52 - -- max energy available 55 + -- energy here 53 56 54 57 -- local meta = minetest.get_meta(pos) 55 58 -- local inv = meta:get_inventory() 56 59 -- local torque = 20 57 60 stat1 = stat1 or 'off' 58 61 minetest.get_meta(pos):set_string('formspec', string.format([[ 59 62 size[8,7.2] ................................................................................ 79 82 if slot == 'grinder' then 80 83 if minetest.get_item_group(item:get_name(), 'sorcery_mill_grindhead')~=0 81 84 then return 1 end 82 85 elseif slot == 'input' then 83 86 local metal = sorcery.data.metallookup[item:get_name()] 84 87 local mat = sorcery.matreg.lookup[item:get_name()] 85 88 local comp = sorcery.data.compat.grindables[item:get_name()] 86 - if metal or mat.metal or comp then 89 + if metal or (mat and mat.metal) or comp then 87 90 return item:get_count() 88 91 else 89 - local mat = item:get_definition()._matprop 92 + mat = item:get_definition()._matprop 90 93 if mat and mat.grindvalue then 91 94 return item:get_count() 92 95 end 93 96 end 94 97 end 95 98 return 0 96 99 end 97 100 local matprops = function(item) 98 101 local metal = sorcery.data.metallookup[item:get_name()] 99 102 if not metal then 100 103 -- allow grinding of armor and tools back to their 101 104 -- original components 102 105 local mat = sorcery.matreg.lookup[item:get_name()] 103 - if mat.metal then 106 + if mat and mat.metal then 104 107 metal = mat 105 - else 106 - return nil 107 108 end 108 109 end 109 110 local mp = item:get_definition()._matprop 110 111 or sorcery.data.compat.grindables[item:get_name()] 111 112 or {} 112 113 113 114 again = true 114 115 if metal then mp = { 115 - hardness = metal.data.hardness or mp.hardness or constants.default_hardness; 116 - grindvalue = metal.value or mp.grindvalue or (metal and constants.metal_grindvalue) or constants.default_grindvalue; 117 - powder = metal.data.parts.powder or mp.powder; 118 - grindcost = constants.metal_grindcost or mp.grindcost; -- invariant for metal 116 + hardness = mp.hardness or metal.data.hardness; 117 + grindvalue = ((mp.grindvalue or metal.value) or (metal and constants.metal_grindvalue)); 118 + powder = mp.powder or metal.data.parts.powder; 119 + grindcost = mp.grindcost or constants.metal_grindcost; -- invariant for metal 119 120 } end 120 121 121 - mp.torque = constants.grind_torque_factor * mp.hardness 122 + mp.torque = constants.grind_torque_factor * mp.hardness 123 + mp.grindvalue = mp.grindvalue or constants.default_grindvalue 124 + mp.grindcost = mp.grindcost or constants.default_grindcost 125 + mp.hardness = mp.hardness or constants.default_hardness; 122 126 123 127 if item:get_wear() ~= 0 then 124 128 -- prevent cheating by recovering metal from items before they 125 129 -- are destroyed 126 130 local wearfac = (item:get_wear() / 65535) 127 131 mp.grindvalue = math.max(1,math.ceil(mp.grindvalue * wearfac)) 128 132 mp.hardness = math.max(1,math.ceil(mp.grindcost * wearfac)) ................................................................................ 134 138 minetest.register_node('sorcery:mill',{ 135 139 description = 'Mill'; 136 140 groups = { 137 141 cracky = 2; 138 142 sorcery_ley_device = 1; 139 143 }; 140 144 paramtype2 = 'facedir'; 145 + after_dig_node = sorcery.lib.node.purge_container; 141 146 on_construct = function(pos) 142 147 local meta = minetest.get_meta(pos) 143 148 local inv = meta:get_inventory() 144 149 inv:set_size('input',1) 145 150 inv:set_size('output',4) 146 151 inv:set_size('grinder',2) 147 152 meta:set_float('grindtime',0) ................................................................................ 163 168 on_metadata_inventory_move = function(pos,fl,fi,tl,ti) 164 169 if fl == 'input' or tl == 'input' then 165 170 minetest.get_meta(pos):set_float('grindtime',0) 166 171 end 167 172 mill_update(pos) 168 173 end; 169 174 _sorcery = { 170 - ley = { mode = 'consume'; affinity = {'praxic'}}; 171 - on_leyconnect = mill_update; 172 - on_leycalc = function(pos,time) 173 - local meta = minetest.get_meta(pos) 174 - local active = meta:get_int('active') == 1 175 - if not active then return { power = 0; } end 176 - local inv = meta:get_inventory() 177 - local item = inv:get_stack('input',1) 178 - if item:is_empty() then 179 - meta:set_int('active', 0) 180 - return { power = 0; } 181 - end 182 - return { 183 - power = matprops(item).torque * time; 184 - } 185 - end; 175 + ley = { 176 + mode = 'consume', affinity = {'praxic'}; 177 + power = function(pos,time) 178 + local meta = minetest.get_meta(pos) 179 + local active = meta:get_int('active') == 1 180 + if not active then return 0 end 181 + local inv = meta:get_inventory() 182 + local item = inv:get_stack('input',1) 183 + if item:is_empty() then 184 + meta:set_int('active', 0) 185 + return 0 186 + end 187 + return matprops(item).torque * time; 188 + end; 189 + }; 190 + on_leychange = mill_update; 186 191 }; 187 192 on_timer = function(pos,delta) 188 193 local meta = minetest.get_meta(pos) 189 194 local inv = meta:get_inventory() 190 195 local elapsed = meta:get_float('grindtime') + delta 191 196 local ley = sorcery.ley.netcaps(pos,delta,pos) 192 197 local again = false 193 198 local active = false 194 199 local reqtime -- sigh 195 200 local statcolor = 'off' 196 201 local grinders_on 197 202 if inv:is_empty('input') or inv:is_empty('grinder') then 198 - print('empty') 199 203 elapsed = 0 200 204 mill_formspec_update(pos, 0) 201 205 else 202 206 local item = inv:get_stack('input',1) 203 207 local mp = matprops(item) 204 208 if mp.grindcost > item:get_count() then 205 209 elapsed = 0 206 210 mill_formspec_update(pos, 0) 207 - print('bad grindcost') 208 211 goto stop 209 212 end 210 213 211 - -- print('power supply',ley.maxpower) 212 - -- print('power available',ley.freepower) 213 - -- print('power needed',mp.torque*delta) 214 214 if ley.maxpower < (mp.torque * delta) then 215 215 -- not enough potential energy in the system to grind 216 216 -- so don't bother 217 - print('not enough power') 218 217 statcolor = 'red' 219 218 elapsed = 0 goto stop 220 219 elseif ley.freepower < (mp.torque * delta) then 221 220 -- the net has enough potential energy to supply us, 222 221 -- but too much of it is in use right now. give up 223 222 -- on this round, but try again in a bit to see if 224 223 -- more energy is available 225 - print('currently not enough power') 226 224 statcolor = 'yellow' 227 225 elapsed = 0 again = true goto stop 228 226 end 229 227 230 228 local grinders = 0 231 229 local grindpower = 0 232 230 local grind_wear = {} ................................................................................ 242 240 if dif == 0 then 243 241 wear = constants.grind_wear 244 242 elseif dif < 0 then 245 243 wear = constants.grind_wear * ((dif * -1)/constants.grind_range) 246 244 elseif dif > 0 then 247 245 if dif > constants.grind_grace_range then 248 246 wear = 0 249 - print('grinder reject') 250 247 goto reject 251 248 else 252 249 wear = constants.grind_wear * (1 + (dif/constants.grind_range)) * constants.grind_grace_penalty 253 250 end 254 251 end 255 252 ::accept:: grinders = grinders + 1 256 253 grindpower = grindpower + hh ................................................................................ 269 266 if grindpower < mp.hardness then 270 267 statcolor = 'yellow' 271 268 else statcolor='green' end 272 269 grindpower = grindpower / grinders 273 270 -- if there is more power available than needed, 274 271 -- and/or if the blades are stronger than needed, 275 272 -- speed up the grind 276 - local speedboost = math.max(0.05,((grindpower - mp.hardness)/constants.grind_range) * grinders) * ((mp.torque * delta) / ley.freepower) 273 + local speedboost = math.max(0.05,((grindpower - mp.hardness)/constants.grind_range) * grinders) 277 274 reqtime = mp.grindvalue * mp.hardness * constants.grind_factor * (1-speedboost) 278 275 if elapsed >= reqtime then 279 276 item:take_item(mp.grindcost) 280 277 inv:set_stack('input',1,item) 281 278 local pw = ItemStack{ 282 279 name=mp.powder; 283 280 count=mp.grindvalue; ................................................................................ 345 342 metal = name; 346 343 }; 347 344 }); 348 345 minetest.register_craft { 349 346 output = id; 350 347 recipe = { 351 348 {f,i,f}; 352 - {i,i,i}; 349 + {i,'',i}; 353 350 {f,i,f}; 354 351 }; 355 352 } 356 353 end
Modified metallurgy-hot.lua from [3c9b60f14d] to [45fd80ebe6].
294 294 for _,state in pairs{'open','closed'} do 295 295 local id_closed = id .. '_closed' 296 296 local id_current = (state == 'closed' and id_closed) or id 297 297 local desc = (kind.temp_name and sorcery.lib.str.capitalize(kind.temp_name) .. ' kiln') or 'Kiln' 298 298 minetest.register_node(id_current, { 299 299 description = desc; 300 300 drawtype = "mesh"; 301 + after_dig_node = sorcery.lib.node.purge_container; 301 302 mesh = 'sorcery-kiln-' .. state .. '.obj'; 302 303 drop = id; 303 304 groups = { 304 305 cracky = (state == 'open' and 2) or nil; 305 306 }; 306 307 sunlight_propagates = true; 307 308 paramtype1 = 'light'; ................................................................................ 376 377 local id = 'sorcery:smelter_' .. kind.material .. kind.size_name 377 378 kind.id = id 378 379 for _, active in pairs {false, true} do 379 380 minetest.register_node((active and id .. '_active') or id, { 380 381 _proto = kind; 381 382 description = desc; 382 383 drop = id; 384 + after_dig_node = sorcery.lib.node.purge_container; 383 385 groups = { 384 386 cracky = (active and 2) or nil; 385 387 }; 386 388 paramtype2 = 'facedir'; 387 389 light_source = (active and 9) or 0; 388 390 on_construct = function(pos) 389 391 local meta = minetest.get_meta(pos)
Modified ores.lua from [48691b218f] to [caa4bf5370].
125 125 no_armor = metal.no_armor; 126 126 no_tools = metal.no_tools; 127 127 durability = metal.durability; 128 128 power = metal.power; 129 129 speed = metal.speed; 130 130 artificial = metal.artificial; 131 131 cooktime = metal.cooktime; 132 - hardness = metal.hardness; 132 + hardness = (metal.hardness/8) * 3; -- scaled wrt diamond 133 + level = math.ceil(((metal.hardness/8) * 3)) + 1; 133 134 ingot_image = (metal.image and metal.image.ingot) or nil; 134 135 lump_image = (metal.image and metal.image.lump) or nil; 135 136 armor_weight = metal.armor_weight; 136 137 armor_protection = metal.armor_protection; 137 138 } 138 139 end 139 140 minetest.register_craftitem(fragment, {
Modified recipes.lua from [0b99f84f61] to [c451769631].
250 250 }; 251 251 output = "sorcery:infuser"; 252 252 } 253 253 254 254 255 255 ---- altar 256 256 -- candles 257 +minetest.register_craftitem('sorcery:core_counterpraxic',{ 258 + description = 'Counterpraxis Core'; 259 + inventory_image = 'sorcery_core_counterpraxic.png'; 260 +}); 261 +-- 262 +minetest.register_craftitem('sorcery:suppression_matrix',{ 263 + description = 'Suppression Matrix'; 264 + inventory_image = 'sorcery_suppression_matrix.png'; 265 +}); 266 + 267 +minetest.register_craftitem('sorcery:inverter_coil',{ 268 + description = 'Inverter Coil'; 269 + inventory_image = 'sorcery_inverter_coil.png'; 270 +}); 271 + 272 +minetest.register_craftitem('sorcery:beam_generator',{ 273 + description = 'Beam Generator'; 274 + inventory_image = 'sorcery_beam_generator.png'; 275 +}); 276 + 277 +minetest.register_craftitem('sorcery:leyline_stabilizer',{ 278 + description = 'Leyline Stabilizer'; 279 + inventory_image = 'sorcery_leyline_stabilizer.png'; 280 +}); 281 + 282 +minetest.register_craftitem('sorcery:field_emitter',{ 283 + description = 'Field Emitter'; 284 + inventory_image = 'sorcery_field_emitter.png'; 285 +}) 286 + 287 +minetest.register_craft { 288 + output = 'sorcery:leyline_stabilizer'; 289 + recipe = { 290 + {'basic_materials:copper_wire','group:sorcery_ley_cable','basic_materials:copper_wire'}; 291 + {'sorcery:grease_neutralizing','group:sorcery_ley_cable','sorcery:grease_neutralizing'}; 292 + {'basic_materials:copper_wire','group:sorcery_ley_cable','basic_materials:copper_wire'}; 293 + }; 294 + replacements = { 295 + {'basic_materials:copper_wire', 'basic_materials:empty_spool'}; 296 + {'basic_materials:copper_wire', 'basic_materials:empty_spool'}; 297 + {'basic_materials:copper_wire', 'basic_materials:empty_spool'}; 298 + {'basic_materials:copper_wire', 'basic_materials:empty_spool'}; 299 + {'sorcery:grease_neutralizing', 'xdecor:bowl'}; 300 + {'sorcery:grease_neutralizing', 'xdecor:bowl'}; 301 + }; 302 +} 303 + 304 +minetest.register_craft { 305 + output = 'sorcery:beam_generator'; 306 + recipe = { 307 + {'xpanes:bar_flat','xpanes:pane_flat','xpanes:bar_flat'}; 308 + {'sorcery:screw_aluminum','sorcery:gem_sapphire','sorcery:screw_aluminum'}; 309 + {'xpanes:bar_flat','sorcery:gem_luxite','xpanes:bar_flat'}; 310 + }; 311 +} 312 + 313 +minetest.register_craft { 314 + output = 'sorcery:suppression_matrix'; 315 + recipe = { 316 + {'sorcery:fragment_electrum','basic_materials:steel_strip','sorcery:fragment_cobalt'}; 317 + {'basic_materials:copper_strip','xpanes:bar_flat','basic_materials:copper_strip'}; 318 + {'sorcery:fragment_cobalt','basic_materials:steel_strip','sorcery:fragment_electrum'}; 319 + }; 320 +} 321 + 322 +minetest.register_craft { 323 + output = 'sorcery:core_counterpraxic'; 324 + recipe = { 325 + {'sorcery:gem_ruby_shard','sorcery:tungsten_ingot','sorcery:gem_ruby_shard'}; 326 + {'sorcery:tungsten_ingot','sorcery:gem_emerald','sorcery:tungsten_ingot'}; 327 + {'sorcery:gem_ruby_shard','sorcery:tungsten_ingot','sorcery:gem_ruby_shard'}; 328 + }; 329 +} 330 + 331 +minetest.register_craft { 332 + output = 'sorcery:inverter_coil'; 333 + recipe = { 334 + {'sorcery:screw_platinum','basic_materials:steel_wire','sorcery:screw_platinum'}; 335 + {'basic_materials:copper_wire','default:tin_ingot','basic_materials:copper_wire'}; 336 + {'sorcery:screw_platinum','basic_materials:steel_wire','sorcery:screw_platinum'}; 337 + }; 338 + replacements = { 339 + {'basic_materials:steel_wire', 'basic_materials:empty_spool'}; 340 + {'basic_materials:copper_wire', 'basic_materials:empty_spool'}; 341 + {'basic_materials:copper_wire', 'basic_materials:empty_spool'}; 342 + {'basic_materials:steel_wire', 'basic_materials:empty_spool'}; 343 + }; 344 +} 345 + 346 +minetest.register_craft { 347 + output = 'sorcery:field_emitter'; 348 + recipe = { 349 + {'basic_materials:steel_bar','xpanes:pane_flat','basic_materials:steel_bar'}; 350 + {'sorcery:beam_generator','sorcery:leyline_stabilizer','sorcery:beam_generator'}; 351 + {'sorcery:beam_generator','basic_materials:copper_wire','sorcery:beam_generator'}; 352 + }; 353 + replacements = { 354 + {'basic_materials:copper_wire', 'basic_materials:empty_spool'}; 355 + }; 356 +} 357 + 358 +minetest.register_craft { 359 + output = 'sorcery:emitter_barrier'; 360 + recipe = { 361 + {'sorcery:suppression_matrix','sorcery:suppression_matrix','sorcery:suppression_matrix'}; 362 + {'sorcery:field_emitter','sorcery:core_counterpraxic','sorcery:inverter_coil'}; 363 + {'default:tin_ingot','default:tin_ingot','default:tin_ingot'}; 364 + }; 365 +} 366 + 367 +minetest.register_craft { 368 + output = 'sorcery:generator'; 369 + recipe = { 370 + {'sorcery:aluminum_ingot','sorcery:aluminum_ingot','sorcery:aluminum_ingot'}; 371 + {'default:bronze_ingot','basic_materials:copper_wire','default:bronze_ingot'}; 372 + {'default:steel_ingot','default:furnace','default:steel_ingot'}; 373 + }; 374 + replacements = { 375 + {'basic_materials:copper_wire', 'basic_materials:empty_spool'}; 376 + }; 377 +} 378 + 257 379 minetest.register_craftitem('sorcery:candle', { 258 380 -- TODO make candle node 259 381 inventory_image = 'sorcery_candle.png'; 260 382 description = 'Votive Candle'; 261 383 groups = { 262 384 candle = 1; 263 385 };
Added textures/sorcery_beam_generator.png version [58c2e4401c].
cannot compute difference between binary files
Added textures/sorcery_core_counterpraxic.png version [39479c1b28].
cannot compute difference between binary files
Added textures/sorcery_emitter_barrier_bottom.png version [a6363e789d].
cannot compute difference between binary files
Added textures/sorcery_emitter_barrier_front.png version [76e1531fe0].
cannot compute difference between binary files
Added textures/sorcery_emitter_barrier_side.png version [b566c1148a].
cannot compute difference between binary files
Added textures/sorcery_emitter_barrier_top.png version [2705ace703].
cannot compute difference between binary files
Added textures/sorcery_field_emitter.png version [fdceff2168].
cannot compute difference between binary files
Added textures/sorcery_inverter_coil.png version [a40914f554].
cannot compute difference between binary files
Added textures/sorcery_ley_generator_back.png version [aedb4f096c].
cannot compute difference between binary files
Added textures/sorcery_ley_generator_bottom.png version [f23afab857].
cannot compute difference between binary files
Added textures/sorcery_ley_generator_front_off.png version [811455addd].
cannot compute difference between binary files
Added textures/sorcery_ley_generator_front_on.png version [cf5b54dd34].
cannot compute difference between binary files
Added textures/sorcery_ley_generator_side.png version [07ad2d2926].
cannot compute difference between binary files
Added textures/sorcery_ley_generator_top.png version [7147d2203f].
cannot compute difference between binary files
Added textures/sorcery_ley_plug.png version [ac3ad24938].
cannot compute difference between binary files
Added textures/sorcery_ley_switch_base.png version [eca6656993].
cannot compute difference between binary files
Added textures/sorcery_ley_switch_down.png version [5722e6a77c].
cannot compute difference between binary files
Added textures/sorcery_ley_switch_panel.png version [3f4a278966].
cannot compute difference between binary files
Added textures/sorcery_ley_switch_up.png version [3e480e03fd].
cannot compute difference between binary files
Added textures/sorcery_leyline_stabilizer.png version [148e93c8c1].
cannot compute difference between binary files
Added textures/sorcery_suppression_matrix.png version [9c64f4969e].
cannot compute difference between binary files
Modified tnodes.lua from [74f7716464] to [27d6ea2995].
15 15 minetest.get_node_timer(pos):start(1) 16 16 end; 17 17 on_timer = function(pos,dtime) 18 18 local meta = minetest.get_meta(pos) 19 19 local elapsed = dtime + meta:get_float('duration') - meta:get_float('timeleft') 20 20 local level = 1 - (elapsed / meta:get_float('duration')) 21 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 22 if lum ~= i then 26 23 if lum <= 0 then 27 24 minetest.remove_node(pos) 28 25 return false 29 26 else 30 27 minetest.swap_node(pos,{name='sorcery:air_glimmer_'..tostring(lum)}) 31 28 end
Modified wands.lua from [8ffba5fe57] to [12fce408ba].
687 687 -- meta:set_string('formspec',wandwork_form(false)) 688 688 end; 689 689 on_timer = function(...) 690 690 if water then return wandwork_soak(...); 691 691 else return false end 692 692 end; 693 693 on_rightclick = wandwork_rightclick; 694 + after_dig_node = sorcery.lib.node.purge_container; 694 695 allow_metadata_inventory_put = function(pos, list, index, stack, user) 695 696 local meta = minetest.get_meta(pos) 696 697 local wwi = meta:get_inventory() 697 698 if list == 'preview' then return 0 698 699 elseif list == 'wandparts' then 699 700 if (not wwi:is_empty('preview')) and 700 701 find_core(stack) then return 1