Overview
Comment: | add cool and informative visuals for taps, add more capacity to rune forge, many bug fixes, fixed some bugs, and fixed some bugs |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
94064fe5c99fad4567c598b2e72cf80a |
User & Date: | lexi on 2021-07-04 20:27:42 |
Other Links: | manifest | tags |
Context
2021-07-05
| ||
00:59 | add Mundanity spell, bug fixes check-in: 1276138728 user: lexi tags: trunk | |
2021-07-04
| ||
20:27 | add cool and informative visuals for taps, add more capacity to rune forge, many bug fixes, fixed some bugs, and fixed some bugs check-in: 94064fe5c9 user: lexi tags: trunk | |
2021-07-03
| ||
02:25 | many bug fixers, some minor refactoring, allow non-drinkable potions to be empowered in various ways, allow gods to be petitioned for recipes (next up: cookbooks!) check-in: c71731cf58 user: lexi tags: trunk | |
Changes
Modified altar.lua from [080406f8d2] to [7e265da854].
46 46 local props = object:get_properties() 47 47 local node = minetest.get_node(pos) 48 48 props.wield_item = itemstring 49 49 object:set_properties(props) 50 50 object:set_yaw(math.pi*2 - node.param2*(math.pi / 2)) 51 51 end 52 52 end 53 + 54 +-- remove unknown gifts 55 +minetest.register_on_mods_loaded(function() 56 + for name, god in pairs(sorcery.data.gods) do 57 + local bad = {} 58 + for g in pairs(god.gifts) do 59 + -- can't mutate table while we're iterating it 60 + if not minetest.registered_nodes[g] then bad[#bad+1] = g end 61 + end 62 + for _, g in ipairs(bad) do god.gifts[g] = nil end 63 + end 64 +end) 53 65 54 66 for name, god in pairs(sorcery.data.gods) do 55 67 local hitbox = { 56 68 0-(god.idol.width / 2.0), 0-(god.idol.height / 2.0), -0.15, 57 69 god.idol.width / 2.0, god.idol.height / 2.0, 0.15 58 70 } -- {xmin, ymin, zmin, 59 71 -- xmax, ymax, zmax} in nodes from node center. 60 72 paramtype = "light"; 61 - minetest.register_node('sorcery:idol_' .. name, { 73 + sorcery.lib.node.reg_autopreserve('sorcery:idol_' .. name, { 62 74 description = god.idol.desc; 63 75 drawtype = "mesh"; 64 76 mesh = 'sorcery-idol-' .. name .. '.obj'; 65 77 paramtype = 'light'; 66 78 paramtype2 = 'facedir'; 67 79 sunlight_propagates = true; 68 80 stack_max = 1; 69 81 tiles = god.idol.tex; 70 82 selection_box = { type = "fixed"; fixed = {hitbox}; }; 71 83 collision_box = { type = "fixed"; fixed = {hitbox}; }; 72 84 groups = { cracky = 2, sorcery_idol = 1, heavy = 1, sorcery_worship = 1}; 73 85 74 - after_place_node = function(pos, placer, stack, pointat) 75 - local meta = minetest.get_meta(pos) 76 - local stackmeta = stack:get_meta() 77 - meta:set_int('favor', stackmeta:get_int('favor')) 78 - meta:set_string('last_sacrifice', stackmeta:get_string('last_sacrifice')) 79 - 86 + on_construct = function(pos) 80 87 minetest.get_node_timer(pos):start(1) 81 88 end; 82 89 83 - drop = { 84 - -- for some idiot reason this is necessary for 85 - -- preserve_metadata to work right 86 - max_items = 1; 87 - items = { 88 - { items = {'sorcery:idol_' .. name} } 89 - }; 90 - }; 91 - 92 - preserve_metadata = function(pos, node, meta, newstack) 93 - newstack[1]:get_meta():from_table(meta) 94 - end; 95 - 96 90 on_timer = function(pos, elapsed) 97 91 local altar = minetest.find_node_near(pos, 3, "sorcery:altar") 98 92 -- TODO even without an altar, an idol with high favor could still be the source of miracles 93 + -- refills nearby partly empty troughs at cost to favor? 99 94 if not altar then return true end 100 95 101 96 local altarmeta = minetest.get_meta(altar) 102 97 local inv = altarmeta:get_inventory() 103 98 local idolmeta = minetest.get_meta(pos) 104 99 local divine_favor = idolmeta:get_int('favor') 105 100 local bestow = function(item,color) ................................................................................ 234 229 } 235 230 end 236 231 -- preserve wear 237 232 local gift 238 233 if type(tx) == 'string' then 239 234 gift = ItemStack(tx) 240 235 else gift = tx end 236 + if not gift:is_known() then goto skip end 241 237 local wear = stack:get_wear() 242 238 if wear > 0 then 243 239 gift:set_wear(wear) 244 240 end 245 241 -- preserve meta 246 242 local gm = gift:get_meta() 247 243 gm:from_table( ................................................................................ 264 260 if divine_favor >= cost then 265 261 bestow(gift) 266 262 divine_favor = divine_favor - cost 267 263 log.act(god.name, 'has consecrated', s, 'into', tx, 'for the cost of', cost, 'points of divine favor') 268 264 goto refresh 269 265 end 270 266 end 271 - end 267 + ::skip::end 272 268 end 273 269 274 270 ::refresh:: 275 271 idolmeta:set_int('favor', divine_favor) 276 272 update_altar(altar,nil) 277 273 return true 278 274 end;
Modified astrolabe.lua from [cc031237ac] to [21ab3e0c25].
77 77 drawtype = 'mesh'; 78 78 mesh = 'sorcery-astrolabe.obj'; 79 79 groups = { 80 80 cracky = 2, choppy = 2; 81 81 dig_immediate = 2; 82 82 sorcery_tech = 1; 83 83 }; 84 + sunlight_propagates = true; 85 + paramtype = 'light'; 84 86 selection_box = albox, collision_box = albox; 85 87 after_dig_node = sorcery.lib.node.purge_containers; 86 88 tiles = { 87 89 'default_steel_block.png'; 88 90 'default_bronze_block.png'; 89 91 'default_copper_block.png'; 90 92 'default_aspen_wood.png';
Modified data/elixirs.lua from [ba37716134] to [c432830d8f].
22 22 end; 23 23 infusion = 'sorcery:grease_pine'; 24 24 }; 25 25 Rapidity = { 26 26 color = {183,28,238}; qual = 'speed'; 27 27 apply = inc('speed'); 28 28 describe = function(potion) 29 - return 'good', 'Quickened', 'This potion will take effect more quiclkly and easily' 29 + return 'good', 'quickened', 'This potion will take effect more quickly and easily' 30 30 end; 31 31 infusion = 'sorcery:liquid_sap_acacia_bottle'; 32 32 }; 33 33 Purity = { 34 34 color = {244,255,255}; qual = 'purity'; 35 35 apply = inc('purity'); 36 36 describe = function(potion) 37 - return 'good', 'purified', 'This potion\'s impurities and undesirable side effects are diminished or eliminated' 37 + return 'good', 'purified', 'This potion\'s impurities and undesirable qualities are diminished or eliminated' 38 38 end; 39 39 infusion = 'sorcery:oil_purifying'; 40 40 }; 41 41 Beauty = { 42 42 color = {255,20,226}; qual = 'beauty'; 43 43 apply = inc('beauty'); 44 44 describe = function(potion)
Modified gems.lua from [68440cd05e] to [12e0882fa3].
54 54 end 55 55 if not gem.foreign_amulet then 56 56 local img = sorcery.lib.image 57 57 local img_stone = img('sorcery_amulet.png'):multiply(sorcery.lib.color(gem.tone)) 58 58 local img_sparkle = img('sorcery_amulet_sparkle.png') 59 59 local useamulet = function(stack,user,target) 60 60 local sp = sorcery.amulet.getspell(stack) 61 + print('got spell',dump(sp)) 61 62 if not sp or not sp.cast then return nil end 62 63 63 64 local usedamulet if stack:get_count() == 1 then 64 65 usedamulet = stack 65 66 else 66 67 usedamulet = ItemStack(stack) 67 68 usedamulet:set_count(1)
Modified infuser.lua from [0b21397e89] to [fedc837bad].
204 204 205 205 local inv = meta:get_inventory() 206 206 local infusion = inv:get_list('infusion') 207 207 local potions = inv:get_list('potions') 208 208 local elixir = infusion[1]:get_definition() 209 209 local probe = sorcery.spell.probe(pos) 210 210 local fx = infuser_mods(pos) 211 + local sparkle_color = {sorcery.lib.color(255, 0, 145)}; 211 212 if probe.disjunction then return true end 212 213 213 214 local potionct = 0 214 215 216 + local cancel = true 215 217 do 216 218 local ingredient -- *eyeroll* 217 219 if infusion[1]:is_empty() then goto cancel end 218 220 ingredient = infusion[1]:get_name() 219 221 for i = 1,#potions do 220 222 if potions[i]:is_empty() then goto skip end 221 223 potionct = potionct + 1 222 224 local base = potions[i]:get_name() 223 225 local potion = potions[i]:get_definition() 224 226 if elixir_can_apply(elixir._proto,potion) then 225 227 -- at least one combination makes a valid potion; 226 228 -- we can start the infuser 227 - goto start 229 + if elixir._proto.color then 230 + sparkle_color[#sparkle_color+1] = sorcery.lib.color(elixir._proto.color) 231 + end 232 + cancel = false 228 233 end 229 234 for _,v in pairs(sorcery.register.infusions.db) do 230 235 if v.infuse == ingredient and v.into == base then 231 236 -- at least one combination makes a valid 232 237 -- potion; we can start the infuser 233 - goto start 238 + if v.output.data and v.output.data.color then 239 + sparkle_color[#sparkle_color+1] = sorcery.lib.color(v.output.data.color) 240 + end 241 + cancel = false 234 242 end 235 243 end 236 244 ::skip:: end 237 245 238 - ::cancel:: do 246 + ::cancel:: if cancel then 239 247 infuser_stop(pos) 240 248 return false 241 249 end 242 250 243 251 ::start:: 244 252 end 245 253 ................................................................................ 268 276 type = "vertical_frames"; 269 277 aspect_h = 16; 270 278 aspect_w = 16; 271 279 length = 4.1; 272 280 }; 273 281 } 274 282 end 275 - -- for i=0,4 do 276 - spawn('sorcery_spark.png^[multiply:#FF8FDD', 1, 32 * 4) 277 - -- end 278 - -- for i=0,4 do 279 - spawn('sorcery_spark.png^[multiply:#FFB1F6', 0.5, 64 * 4) 280 - -- end 281 - 283 + local spark = sorcery.lib.image('sorcery_spark.png') 284 + for i = 1,4 do 285 + local fac = 1 / i 286 + local _, spc = sorcery.lib.tbl.pick(sparkle_color) 287 + local sp = spark:glow(spc) 288 + 289 + spawn(sp:render(), fac, (32/fac) * 4) 290 + end 291 + 282 292 local discharge = sorcery.lib.node.discharger(pos) 283 293 284 294 if newtime >= infusion_time then 285 295 -- finished 286 296 local ingredient = infusion[1]:get_name() 287 297 local result, residue = sorcery.alchemy.infuse(infusion[1], potions) 288 298 for i, r in pairs(result) do
Modified keg.lua from [5c653d450d] to [59c6df911a].
123 123 m:set_int('charge',0) 124 124 else m:set_int('charge', amtleft) end 125 125 sorcery.liquid.sound_dip(chg,avail,pos) 126 126 update() 127 127 128 128 -- fancy visuals 129 129 local color = sorcery.lib.color(liq.color or {255,255,255}) 130 - local spritz = sorcery.lib.image('sorcery_droplet.png') 131 - local drop = sorcery.lib.image('sorcery_drop.png') 132 - spritz = spritz:blit(spritz:multiply(color)) 133 - drop = drop:blit (drop:multiply (color)) 130 + local spritz = sorcery.lib.image('sorcery_droplet.png'):glow(color) 131 + local drop = sorcery.lib.image('sorcery_drop.png'):glow(color) 134 132 local facing = minetest.facedir_to_dir(minetest.get_node(pos).param2) 135 133 local noz = vector.add(pos, vector.rotate( 136 134 vector.new(0.0,0,-0.48), 137 135 vector.dir_to_rotation(facing) 138 136 )) 139 137 local minnoz = vector.offset(noz, -0.03, -0.32, -0.03); 140 138 local maxnoz = vector.offset(noz, 0.03, -0.32, 0.03); ................................................................................ 149 147 minsize = 0.4, maxsize = 1; 150 148 glow = 14; -- FIXME liquid glow prop 151 149 minexptime = 0.5, maxexptime = 0.5; 152 150 animation = { 153 151 type = 'sheet_2d'; 154 152 frames_w = 14; 155 153 frames_h = 1; 156 - frame_length = 0.5/14; 154 + frame_length = (0.5/14) + 0.02; 157 155 } 158 156 } 159 157 minetest.after(0.2, function() 160 158 minetest.add_particlespawner { 161 159 amount = math.random(5,11) * chg, time = 0.13 * chg; 162 160 texture = drop:render(); 163 161 minpos = vector.offset(minnoz, 0,-0.05,0); ................................................................................ 169 167 minsize = 0.3, maxsize = 0.5; 170 168 glow = 14; -- FIXME liquid glow prop 171 169 minexptime = 1, maxexptime = 1.5; 172 170 animation = { 173 171 type = 'sheet_2d'; 174 172 frames_w = 10; 175 173 frames_h = 1; 176 - frame_length = 1.5/10; 174 + frame_length = (1.5/10) + 0.02; 177 175 } 178 176 } 179 177 end) 180 178 181 179 return filled 182 180 end 183 181 end
Modified lib/node.lua from [087023acf7] to [3dbeb921b1].
358 358 end 359 359 return i, false 360 360 end 361 361 else 362 362 return function(i) return i, false end 363 363 end 364 364 end; 365 + 366 + autopreserve = function(id, tbl) 367 + tbl.drop = tbl.drop or { 368 + max_items = 1; 369 + items = { 370 + { items = {id} }; 371 + }; 372 + } 373 + local next_apn = tbl.after_place_node 374 + tbl.after_place_node = function(...) local pos, who, stack = ... 375 + minetest.get_meta(pos):from_table(stack:get_meta():to_table()) 376 + if next_apn then return next_apn(...) end 377 + end 378 + local next_pm = tbl.preserve_metadata 379 + tbl.preserve_metadata = function(...) local pos, node, meta, drops = ... 380 + drops[1]:get_meta():from_table({fields = meta}) 381 + if next_pm then return next_pm(...) end 382 + end 383 + return tbl 384 + end; 385 + reg_autopreserve = function(id, tbl) 386 + minetest.register_node(id, sorcery.lib.node.autopreserve(id, tbl)) 387 + end; 365 388 }
Modified liquid.lua from [6a40bd16e3] to [02b94765c1].
194 194 L.image(fmt('sorcery_liquid_%s.png', liq.imgvariant or 'dull')) 195 195 :multiply(L.color(liq.color))):render() 196 196 197 197 -- local img_glass = L.image('vessels_drinking_glass.png'):blit( 198 198 -- L.image(fmt('sorcery_liquid_glass_%s.png', liq.imgvariant or 'dull')) 199 199 -- :multiply(L.color(liq.color))) 200 200 201 - minetest.register_node(':'..bottle, { 201 + sorcery.lib.node.reg_autopreserve(':'..bottle, { 202 202 description = liq.desc_bottle or fmt('%s Bottle', L.str.capitalize(liq.name)); 203 203 inventory_image = img_bottle; 204 204 drawtype = 'plantlike', tiles = {img_bottle}; 205 205 is_ground_content = false, walkable = false; 206 206 sunlight_propagates = true, paramtype = 'light'; 207 207 light_source = liq.glow or 0; 208 208 selection_box = { type = 'fixed', fixed = {-0.25, -0.5, -0.25, 0.25, 0.3, 0.25} }; ................................................................................ 244 244 pos = pos; 245 245 }, true) 246 246 end; 247 247 248 248 sorcery.liquid.sound_dip = function(amt_output, amt_basin, pos) 249 249 sorcery.liquid.sound_pour(amt_output, amt_basin, pos) 250 250 end; 251 + 251 252 252 253 -- pre-register basic liquids used in Sorcery and common ones sorcery depends on 253 254 254 255 sorcery.liquid.register{ 255 256 id = 'default:water'; 256 257 name = 'water'; 257 258 kind = 'default:drink'; ................................................................................ 290 291 ['vessels:glass_bottle'] = 'sorcery:blood'; 291 292 }; 292 293 } 293 294 294 295 minetest.register_abm { 295 296 label = 'Rainfall'; 296 297 nodenames = {'group:sorcery_collect_rainwater'}; 297 - interval = 230; 298 - chance = 40; 298 + interval = 120; 299 + chance = 27; 299 300 min_y = -400; 300 301 catch_up = true; 301 302 action = function(pos, node) 302 303 -- TODO vary by season and biome? 303 304 if minetest.get_natural_light(vector.offset(pos,0,1,0), 0.5) >= 15 then 304 305 if node.name == 'sorcery:trough' then 305 306 node.name = 'default:trough_water_1'
Modified potions.lua from [0b54227d82] to [1dfd3579b4].
24 24 drawtype = "plantlike"; 25 25 tiles = {image}; 26 26 inventory_image = image; 27 27 paramtype = "light"; 28 28 is_ground_content = false; 29 29 light_source = glow and math.min(minetest.LIGHT_MAX,glow) or 0; 30 30 drop = 'sorcery:' .. name; 31 - preserve_metadata = function(pos,node,meta,newstack) 32 - newstack[1]:get_meta():from_table(meta) 33 - end; 34 31 walkable = false; 35 32 selection_box = { 36 33 type = "fixed", 37 34 fixed = {-0.25, -0.5, -0.25, 0.25, 0.3, 0.25} 38 35 }; 39 36 on_construct = function(pos) 40 37 minetest.get_meta(pos):set_string('infotext',label) ................................................................................ 43 40 } 44 41 if extra then for k,v in pairs(extra) do node[k] = v end end 45 42 if not node.groups then node.groups = {} end 46 43 node.groups.dig_immediate = 3; 47 44 node.groups.attached_node = 1; 48 45 node.groups.vessel = 1; 49 46 node.groups.not_in_creative_inventory = 1; 50 - minetest.register_node("sorcery:"..name, node) 47 + sorcery.lib.node.reg_autopreserve("sorcery:"..name, node) 51 48 end 52 49 53 50 sorcery.register_oil = function(name,label,desc,color,imgvariant,extra) 54 51 local image = 'xdecor_bowl.png^(sorcery_oil_' .. (imgvariant or 'dull') .. '.png^[colorize:'..tostring(color)..':140)' 55 52 sorcery.register.residue.link('sorcery:' .. name, 'xdecor:bowl') 56 53 extra.description = label; 57 54 extra.inventory_image = image;
Modified runeforge.lua from [65aa0a1ed6] to [b7d5d6135c].
5 5 -- passively consumes ley-current 6 6 -- -- are phials & rune-wrenches enough for this now? 7 7 8 8 local constants = { 9 9 rune_mine_interval = 240; 10 10 -- how often a powered forge rolls for new runes 11 11 12 - rune_cache_max = 4; 12 + rune_cache_max = 6; 13 13 -- how many runes a runeforge can hold at a time 14 14 15 15 rune_grades = {'Fragile', 'Weak', 'Ordinary', 'Pristine', 'Sublime'}; 16 16 -- how many grades of rune quality/power there are 17 17 18 18 amulet_grades = {'Slight', 'Minor', 'Major', 'Grand', 'Ultimate' }; 19 19 -- what kind of amulet each rune grade translates to ................................................................................ 35 35 dist = { Fragile = 0, Weak = 1, Ordinary = 0.9, Pristine = 0.5, Sublime = 0.25 }; 36 36 }; 37 37 supreme = {grade = 6, name = 'Supreme'; infusion = 'sorcery:powder_levitanium'; 38 38 dist = { Fragile = 0, Weak = 0, Ordinary = 1, Pristine = 0.7, Sublime = 0.4 }; 39 39 }; 40 40 }; 41 41 } 42 -local calc_phial_props = function(phial) --> mine interval: float, time factor: float 42 +local calc_phial_props = function(phial) --> mine interval: float, power factor: float 43 43 local m = phial:get_meta() 44 44 local g = phial:get_definition()._proto.data.grade 45 45 local i = constants.rune_mine_interval 46 46 local fac = (g-1) / 5 47 - fac = fac + 0.4 * m:get_int('speed') 48 - return i - ((i*0.5) * fac), 0.5 * fac 47 + fac = fac + 0.2 * m:get_int('speed') 48 + return math.max(3,i - ((i*0.5) * fac)), 0.5 * fac 49 49 end 50 50 sorcery.register.runes.foreach('sorcery:generate',{},function(name,rune) 51 51 local id = 'sorcery:rune_' .. name 52 52 rune.image = rune.image or string.format('sorcery_rune_%s.png',name) 53 53 rune.item = id 54 54 local c = sorcery.lib.color(rune.tone) 55 55 minetest.register_craftitem(id, { ................................................................................ 89 89 _proto = { id = name, desc = desc, name = p.name, kind = phkind, data = p, quals = {force = true, speed = true}, color = color }; 90 90 }; 91 91 } 92 92 sorcery.register.infusions.link { 93 93 infuse = p.infusion; 94 94 into = 'sorcery:potion_subtle'; 95 95 output = 'sorcery:'..id; 96 + _proto = { 97 + data = { color = color }; 98 + }; 96 99 } 97 100 end 98 101 99 102 local register_rune_wrench = function(w) 100 103 local mp = sorcery.data.metals[w.metal].parts 101 104 minetest.register_tool(w.name, { 102 105 description = w.desc; ................................................................................ 231 234 local base_spell = true 232 235 233 236 if proto.frame and spell.frame and spell.frame[proto.frame] then 234 237 local sp = spell.frame[proto.frame] 235 238 if not sp.mingrade or rg >= sp.mingrade then 236 239 title = sp.name or title 237 240 desc = sp.desc or desc 238 - cast = sp.desc or cast 241 + cast = sp.cast or cast 239 242 apply = sp.apply or apply 240 243 remove = sp.remove or remove 241 244 mingrade = sp.mingrade or mingrade 242 245 base_spell = false 243 246 end 244 247 end 245 248 ................................................................................ 318 321 else break end 319 322 end 320 323 end 321 324 322 325 has_phial = has_phial() 323 326 local spec = string.format([[ 324 327 formspec_version[3] size[10.25,8] real_coordinates[true] 325 - list[context;cache;%f,0.25;%u,1;] 326 328 list[context;amulet;3.40,1.50;1,1;] 327 329 list[context;active;5.90,1.50;1,1;] 328 330 329 331 list[context;wrench;1.25,1.75;1,1;] 330 332 list[context;phial;7.25,1.75;1,1;] 331 333 list[context;refuse;8.50,1.75;1,1;] 332 334 333 335 list[current_player;main;0.25,3;8,4;] 334 336 337 + style_type[list;size=0.8] 338 + list[context;cache;%f,0.25;%u,1;] 339 + 335 340 image[0.25,0.50;1,1;sorcery_statlamp_%s.png] 336 - ]], (10.5 - constants.rune_cache_max*1.25)/2, constants.rune_cache_max, 341 + ]], (10.5 - 0.8*(constants.rune_cache_max*1.25))/2, constants.rune_cache_max, 337 342 ((not (has_phial and pow_min)) and 'off' ) or 338 343 ( probe.disjunction and 'blue' ) or 339 344 ((has_phial and pow_max) and 'green') or 'yellow') 340 345 341 346 local ghost = function(slot,x,y,img) 342 347 if i:is_empty(slot) then spec = spec .. string.format([[ 343 348 image[%f,%f;1,1;%s.png] ................................................................................ 397 402 local max,min = 0 398 403 for _,r in pairs(sorcery.data.runes) do 399 404 if r.minpower > max then max = r.minpower end 400 405 if min == nil or r.minpower < min then min = r.minpower end 401 406 end 402 407 -- high-quality phials reduce power usage 403 408 local fac = select(2, calc_phial_props(phial)) 404 - min = min * fac max = max * fac 409 + min = min / fac max = max / fac 405 410 return min*time,max*time 406 411 end; 407 412 }; 408 413 on_leychange = runeforge_update; 409 414 recipe = { 410 415 note = 'Periodically creates runes when sufficiently powered and can be used to imbue them into an amulet, giving it a powerful magical effect'; 411 416 };
Modified tap.lua from [17fb78473a] to [9cfe073fce].
1 1 local log = sorcery.logger('tap') 2 +local sap_interval = 20; 3 + 4 +local function tapdrip(liq, pos) 5 + return sorcery.vfx.drip(liq, vector.offset(pos, 0, -0.3, 0), math.random(5,12), sap_interval, 2) 6 +end 7 + 2 8 minetest.register_node('sorcery:tap',{ 3 9 description = 'Tree Tap'; 4 10 drawtype = 'mesh'; 5 11 mesh = 'sorcery-tap.obj'; 6 12 inventory_image = 'sorcery_tap_inv.png'; 7 13 tiles = { 8 14 'default_copper_block.png'; ................................................................................ 16 22 paramtype = 'light', paramtype2 = 'wallmounted'; 17 23 selection_box = { type='fixed', fixed = {-0.2,-0.5,-0.35; 0.3,0.1,0.4} }; 18 24 collision_box = { type='fixed', fixed = {-0.2,-0.5,-0.35; 0.3,0.1,0.4} }; 19 25 node_placement_prediction = ''; 20 26 on_place = function(stack,who,where) 21 27 if where.type ~= 'node' then return end 22 28 local bl = minetest.get_node(where.under) 23 - -- FIXME prevent tapping 'dead' non-tree wood blocks 24 29 25 30 local tree = sorcery.tree.get(where.under) 26 - if not tree or tree.sap == false then return end; 31 + if not tree or tree.def.sap == false then return end; 27 32 28 - -- disallow vertical attachment 33 + -- disallow vertical attachment, bc that makes no sense 29 34 if vector.subtract(where.under,where.above).y ~= 0 then return end 30 35 31 36 minetest.set_node(where.above, { 32 37 name = 'sorcery:tap'; 33 38 param2 = minetest.dir_to_wallmounted(vector.subtract(where.under,where.above)) 34 39 }) 40 + 41 + if sorcery.lib.node.tree_is_live(where.under) then 42 + -- start dripping immediately to indicate the tree is alive 43 + tapdrip(tree.def.sapliq, where.above) 44 + end 35 45 36 46 stack:take_item(1) 37 47 return stack 38 48 end; 49 + on_screwdriver = function() return false end; 39 50 _sorcery = { 40 51 recipe = { 41 52 note = 'Extract syrups and oils from trees'; 42 53 }; 43 54 }; 44 55 }) 45 56 ................................................................................ 48 59 recipe = { 49 60 {'','sorcery:screw_steel','basic_materials:steel_bar'}; 50 61 {'sorcery:pipe','sorcery:valve','sorcery:screw_steel'}; 51 62 {'','sorcery:pipe',''}; 52 63 }; 53 64 } 54 65 55 -local sap_interval = 60; 56 66 local abm_cache 57 67 local abm_cache_time 58 68 minetest.register_abm { 59 69 label = 'Sap drip'; 60 70 nodenames = {'sorcery:tap'}; 61 71 neighbors = {'group:tree'}; 62 72 interval = sap_interval; 63 - chance = 7; 73 + chance = 4; 64 74 catch_up = true; 65 75 action = function(pos, node) 66 76 local now = os.time() 67 77 if abm_cache_time == nil or now > abm_cache_time + (sap_interval-1) then 68 78 abm_cache = { treehash = {} } 69 79 abm_cache_time = now 70 80 end ................................................................................ 101 111 end 102 112 end 103 113 104 114 if (not live) 105 115 or tree.sap == false 106 116 or not tree.sapliq then return end 107 117 if mass_trunk < 12*3 then return end -- too small 118 + 119 + tapdrip(tree.sapliq,pos) 108 120 109 121 local mass = mass_leaves + mass_trunk 110 122 local max_mass = 400 111 123 local ltratio = mass_leaves / mass_trunk 112 124 local mratio = mass / max_mass 113 125 local outof = 15 / mratio 114 126 local chance = math.max(1, math.floor(outof - (25 * ltratio))) / 3
Modified vfx.lua from [8567a33693] to [48046fb0bd].
148 148 animation = { 149 149 type = 'vertical_frames', length = far/vel; 150 150 aspect_w = 16, aspect_h = 16; 151 151 }; 152 152 } 153 153 end 154 154 end 155 + 156 +function sorcery.vfx.drip(liquid, noz, amt, time, exp) 157 + if type(liquid) == 'string' then liquid = sorcery.register.liquid.db[liquid] end 158 + local minnoz = vector.offset(noz, -0.03, 0.0, -0.03); 159 + local maxnoz = vector.offset(noz, 0.03, 0.0, 0.03); 160 + local drop = sorcery.lib.image('sorcery_drop.png'):multiply(liquid.color) 161 + return minetest.add_particlespawner { 162 + amount = amt, time = time; 163 + texture = drop:render(); 164 + minpos = minnoz, maxpos = maxnoz; 165 + minvel = vector.new(0,0,0); 166 + maxvel = vector.new(0,-0.2,0); 167 + minacc = vector.new(0,-0.2,0); 168 + maxacc = vector.new(0,-0.23,0); 169 + minsize = 0.4, maxsize = 1; 170 + glow = liquid.glow or 2; 171 + minexptime = exp, maxexptime = exp; 172 + animation = { 173 + type = 'sheet_2d'; 174 + frames_w = 10; 175 + frames_h = 1; 176 + frame_length = (exp/10) + 0.01; 177 + }; 178 + vertical = true; 179 + } 180 +end