Index: data/runes.lua ================================================================== --- data/runes.lua +++ data/runes.lua @@ -548,12 +548,12 @@ end; [0.3] = function(s,te,tl) s.visual_caster { amount = 100 * s.duration, time = s.duration, glow = 14; texture = sorcery.lib.image('sorcery_sputter.png'):glow(sorcery.lib.color(160,255,80)):render(); - minpos = { x = -0.1, y = 3.0, z = -0.1 }; - maxpos = { x = 0.1, y = 3.2, z = 0.1 }; + minpos = { x = -0.1, y = 4.0, z = -0.1 }; + maxpos = { x = 0.1, y = 4.2, z = 0.1 }; minvel = { x = -5.0, y = -0.5, z = -5.0 }; maxvel = { x = 5.0, y = 0.5, z = 5.0 }; minacc = { x = -0.4, y = 1.0, z = -0.4 }; maxacc = { x = 0.4, y = -1.0, z = 0.4 }; minexptime = 6, maxexptime = 6; @@ -602,19 +602,121 @@ iridium = { name = 'Spellshatter'; desc = 'Blast out a tidal wave of anti-magic that will nullify active spells, but also disenchant or destroy all magical items in range of its violently mundane grip'; cast = function(ctx) local where = ctx.caster:get_pos() - local what = minetest.get_objects_inside_radius(where, 3 + (2*ctx.stats.power)) + local radius = 3 + (2*ctx.stats.power) + local what = minetest.get_objects_inside_radius(where, radius) local who = {} local pfac = math.min(1, ctx.stats.power/8) for _, w in pairs(what) do if w:is_player() and w ~= ctx.caster then who[#who+1] = {player = w} end end - if not next(who) then return false end + --if not next(who) then return false end + local h = ctx.heading.eyeheight*1.1 + local tex = sorcery.lib.image('sorcery_sputter.png'):glow(sorcery.lib.color(160,255,80)):render(); + local epicenter = ctx.caster:get_pos() + vector.new(0, h/2, 0) + local maxima = vector.new(radius, radius, radius) + local potential_targets = minetest.find_nodes_in_area(epicenter - maxima, epicenter + maxima, {'group:sorcery_magical', 'group:sorcery_magitech'}) + local wreck = {} + for _, pos in pairs(potential_targets) do + if sorcery.lib.math.vdcomp(radius,epicenter,pos) then + print('got wreckable at',pos) + wreck[#wreck+1] = pos + end + end + sorcery.spell.cast { + name = 'sorcery:spellshatter'; + caster = ctx.caster; + anchor = epicenter; + --disjunction = true; + --range = radius; + duration = 10; + timeline = { + [0] = function(s) + s.visual_caster { + texture = tex; + amount = 100, time = 0.2; + minpos = { x = -0.1, y = -0.5, z = -0.1 }; + maxpos = { x = 0.1, y = h, z = 0.1 }; + minvel = { x = -10.0, y = -0.0, z = -10.0 }; + maxvel = { x = 10.0, y = 0.0, z = 10.0 }; + minexptime = 3, maxexptime = 3; + minsize = 5, maxsize = 8; + animation = { + type = 'vertical_frames', length = (21/6) + 0.1; + aspect_w = 16, aspect_h = 16; + } + } + s.visual_caster { + texture = tex; + amount = 5000, time = 2; + minpos = { x = -0.1, y = -0.5, z = -0.1 }; + maxpos = { x = 0.1, y = h, z = 0.1 }; + minvel = { x = -10.0, y = -0.0, z = -10.0 }; + maxvel = { x = 10.0, y = 0.0, z = 10.0 }; + minexptime = 3, maxexptime = 3; + minsize = 0.7, maxsize = 2; + animation = { + type = 'vertical_frames', length = (21/6) + 0.1; + aspect_w = 16, aspect_h = 16; + } + } + end; + }; + intervals = { + {period = 0.1, after = 0.15, fn = function(c) + print('interval running') + for i = 1,80 do + local life = 0.2 + math.random() * 2 + local dir = vector.new(math.random()-0.5,0,math.random()-0.5):normalize() + local pos = epicenter + (dir * (math.random()*radius)) + print('setting particle at',pos) + minetest.add_particle { + texture = tex; + pos = pos; + expirationtime = life; + velocity = {x = 0, y = math.random() * 0.3 + 0.1, z = 0}; + size = 0.4 + math.random() * 3; + glow = 14; + animation = { + type = 'vertical_frames', length = math.random(1,3)/10; + aspect_w = 16, aspect_h = 16; + } + } + end + if next(wreck) then + local k,p = sorcery.lib.tbl.pick(wreck) + + minetest.add_particle { + texture = sorcery.lib.image('sorcery_sparking.png'):glow(sorcery.lib.color(255,0,0)):render(); + pos = vector.offset(p,math.random(),math.random(),math.random()); + expirationtime = 1; + size = 5 + math.random() * 4; + glow = 14; + animation = { + type = 'vertical_frames', length = 0.3; + aspect_w = 64, aspect_h = 64; + } + } + minetest.add_particle { + texture = sorcery.lib.image('sorcery_crackle.png'):glow(sorcery.lib.color(255,0,0)):render(); + pos = vector.offset(p,math.random(),math.random(),math.random()); + expirationtime = 1; + size = 4 + math.random() * 6; + glow = 14; + animation = { + type = 'vertical_frames', length = 0.6; + aspect_w = 64, aspect_h = 64; + } + } + end + end}; + }; + } end; }; }; }; } Index: lib/math.lua ================================================================== --- lib/math.lua +++ lib/math.lua @@ -1,11 +1,9 @@ local fn = {} fn.vsep = function(vec) -- separate a vector into a direction + magnitude - local magnitude = math.max(math.abs(vec.x), math.abs(vec.y), math.abs(vec.z)) - local inv = 1 / magnitude - return vector.multiply(vec,inv), magnitude + return vec:normalize(), vec:length() end fn.vdcomp = function(dist,v1,v2) -- compare the distance between two points -- (cheaper than calculating distance outright) local d if v2 Index: recipes.lua ================================================================== --- recipes.lua +++ recipes.lua @@ -256,10 +256,11 @@ minetest.register_craftitem('sorcery:inferno_crystal', { -- made with melding wand from ruby, lithium ingot, and gunpowder -- under sign of the wyvern or the winged serpent inventory_image = 'sorcery_inferno_crystal.png'; description = 'Inferno Crystal'; + groups = {sorcery_magical = 1, fuel = 1}; _sorcery = { material = { gem = true; sacrifice_value = 900; }; Index: spell.lua ================================================================== --- spell.lua +++ spell.lua @@ -219,14 +219,15 @@ if f.subject == t then minetest.delete_particlespawner(f.handle) end end s.subjects[si] = nil end local interpret_timespec = function(when) + if when == nil then return 0 end local t if type(when) == 'number' then t = s.duration * when else - t = (s.duration * (when.whence or 0)) + when.secs + t = (s.duration * (when.whence or 0)) + (when.secs or 0) end if t then return math.min(s.duration,math.max(0,t)) end log.err('invalid timespec ' .. dump(when)) return 0 Index: vfx.lua ================================================================== --- vfx.lua +++ vfx.lua @@ -144,12 +144,12 @@ expirationtime = far / vel; size = math.random()*2.4 + 0.6; texture = sorcery.lib.image('sorcery_sputter.png'):glow(col):render(); glow = 14; animation = { - type = 'vertical_frames', length = far/vel; - aspect_w = 16, aspect_h = 16; + type = 'vertical_frames', length = math.floor((far/vel)*10)*.10; + aspect_w = 16, aspect_h = 16 }; } end end