Overview
Comment: | add some more spells, add spell infrastructure to support metamagic, especially disjunction, various tweaks and bugfixes. [emergency commit] |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
00922196a9362e9cadeb8f074f7a9459 |
User & Date: | lexi on 2020-10-24 01:21:08 |
Other Links: | manifest | tags |
Context
2020-10-26
| ||
03:58 | add over-time spellcasting abstraction to enable metamagic and in particular disjunction, add more animations and sound effects, add excavation spell, possibly some others, forget when the last commit was, edit a bunch of magitech to make it subject to the disjunction mechanism (throw up a disjunction aura and waltz right through those force fields bby, wheee), also illumination spells, tweak runeforge and rune frequence to better the balance and also limit player frustration, move some math functions into their own library category, various tweaks and bugfixes, probably other shit i don't remember check-in: 147592b8e9 user: lexi tags: trunk | |
2020-10-24
| ||
01:21 | add some more spells, add spell infrastructure to support metamagic, especially disjunction, various tweaks and bugfixes. [emergency commit] check-in: 00922196a9 user: lexi tags: trunk | |
2020-10-23
| ||
00:08 | fix some showstopping bugs, more amulet spells, add sound effects, improve teleportation visuals check-in: 90e64c483c user: lexi tags: trunk | |
Changes
Modified data/runes.lua from [47aa367750] to [4908250df2].
1 2 3 4 5 6 7 8 9 10 11 12 13 .. 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 ... 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 ... 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 ... 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
-- a rune is an abstract object created by a runeforge, which can be -- applied to an amulet in order to imbue that amulet with unique -- and fearsome powers. the specific spell depends on the stone the -- rune is applied to, and not all runes can necessarily be applied -- to all stones. return { translocate = { name = 'Translocate'; tone = {0,235,233}; minpower = 3; rarity = 15; amulets = { ................................................................................ else local pos = minetest.string_to_pos(ctx.meta:get_string('rune_return_dest')) ctx.meta:set_string('rune_return_dest','') local subjects = { ctx.caster } local center = ctx.caster:get_pos() ctx.sparkle = false local delay = math.max(3,10 - ctx.stats.power) + 3*(math.random()*2-1) print('teledelay',delay,ctx.stats.power) for _,s in pairs(subjects) do local offset = vector.subtract(s:get_pos(), center) local pt = sorcery.lib.node.get_arrival_point(vector.add(pos,offset)) if pt then minetest.sound_play('sorcery_stutter', { object = s, gain = 0.8; },true) local windup = minetest.sound_play('sorcery_windup',{ object = s, gain = 0.4; }) local mydelay = delay + math.random(-10,10)*.1; local spark = sorcery.lib.image('sorcery_spark.png') local sh = s:get_properties().eye_height local sparkle = function(amt,time,minsize,maxsize) minetest.add_particlespawner { amount = amt, time = time, attached = s; minpos = { x = -0.3, y = -0.5, z = -0.3 }; maxpos = { x = 0.3, y = sh*1.1, z = 0.3 }; minvel = { x = -0.4, y = -0.2, z = -0.4 }; maxvel = { x = 0.4, y = 0.2, z = 0.4 }; minacc = { x = -0.5, y = -0.4, z = -0.5 }; maxacc = { x = 0.5, y = 0.4, z = 0.5 }; minexptime = 1.0, maxexptime = 2.0; minsize = minsize, maxsize = maxsize, glow = 14; texture = spark:blit(spark:multiply(sorcery.lib.color(29,205,247))):render(); animation = { type = 'vertical_frames'; aspect_w = 16, aspect_h = 16; }; } end sparkle(mydelay*100,mydelay,0.3,1.3) minetest.after(mydelay*0.4, function() local timeleft = mydelay - (mydelay*0.4) sparkle(timeleft*150, timeleft, 0.6,1.8) end) minetest.after(mydelay*0.7, function() local timeleft = mydelay - (mydelay*0.7) sparkle(timeleft*80, timeleft, 2,4) end) sorcery.lib.node.preload(pt,s) minetest.after(mydelay, function() minetest.sound_stop(windup) minetest.sound_play('sorcery_zap', { pos = pt, gain = 0.4 },true) minetest.sound_play('sorcery_zap', { pos = s:get_pos(), gain = 0.4 },true) sorcery.vfx.body_sparkle(nil,sorcery.lib.color(20,255,120),2,s:get_pos()) s:set_pos(pt) sorcery.vfx.body_sparkle(s,sorcery.lib.color(20,120,255),2) end) end end end end; frame = { iridium = { name = 'Mass Return'; ................................................................................ }; disjoin = { name = 'Disjoin'; tone = {159,235,0}; minpower = 4; rarity = 20; amulets = { amethyst = { name = 'Unsealing'; desc = 'Wielding this amulet, a touch of your hand will unravel even the mightiest protective magics, leaving doors unsealed and walls free to tear down'; }; emerald = { name = 'Mundanity'; desc = 'Strip away the effects of all active potions and spells in your immediate vicinity, leaving adversaries without their magicks to enhance and protect them, and allies free of any curses they may be hobbled by -- and, of course, vice versa'; }; } }; repulse = { name = 'Repulse'; tone = {0,180,235}; minpower = 1; rarity = 7; amulets = { amethyst = { name = 'Hurling'; desc = 'Wielding this amulet, a mere flick of your fingers will lift any target of your choice bodily into the air and press upon them with tremendous repulsive force, throwing them like a hapless ragdoll out of your path'; }; sapphire = { name = 'Flinging'; desc = 'Toss an enemy violently into the air, and allow the inevitable impact to do your dirty work for you'; }; emerald = { name = 'Shockwave'; ................................................................................ amulets = { amethyst = { name = 'Sapping'; desc = 'Punch a hole in enemy fortifications big enough to slip through but small enough to avoid immediate attention'; }; ruby = { name = 'Shattering'; desc = 'Tear a violent wound in the earth with the destructive force of this amulet'; }; emerald = { name = 'Detonate'; desc = 'Wielding this amulet, you can loose an extraordinarily powerful bolt of flame from your fingertips that will explode violently on impact, wreaking total havoc wherever it lands'; cast = function(ctx) local speed = 40 local radius = math.random(math.floor(ctx.stats.power*0.5),math.ceil(ctx.stats.power)) ................................................................................ bolt:set_velocity(vel) end; }; luxite = { name = 'Lethal Aura'; desc = 'For a time, anyone who approaches you, whether friend or foe, will suffer immediate retaliation as they are quickly sapped of their life force'; }; diamond = { name = 'Killing'; mingrade = 4; desc = 'Wield this amulet against a foe to instantly snuff the life out of their mortal form, regardless of their physical protections.'; cast = function(ctx) if not (ctx.target and ctx.target.type == 'object') then return false end local tgt = ctx.target.ref |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 .. 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 ... 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 ... 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 ... 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 |
-- a rune is an abstract object created by a runeforge, which can be -- applied to an amulet in order to imbue that amulet with unique -- and fearsome powers. the specific spell depends on the stone the -- rune is applied to, and not all runes can necessarily be applied -- to all stones. local sparkle = function(color, spell, amt,time,minsize,maxsize,sh) spell.visual_subjects { amount = amt, time = time, -- attached = s; minpos = { x = -0.3, y = -0.5, z = -0.3 }; maxpos = { x = 0.3, y = sh*1.1, z = 0.3 }; minvel = { x = -0.4, y = -0.2, z = -0.4 }; maxvel = { x = 0.4, y = 0.2, z = 0.4 }; minacc = { x = -0.5, y = -0.4, z = -0.5 }; maxacc = { x = 0.5, y = 0.4, z = 0.5 }; minexptime = 1.0, maxexptime = 2.0; minsize = minsize, maxsize = maxsize, glow = 14; texture = sorcery.vfx.glowspark(color):render(); animation = { type = 'vertical_frames'; aspect_w = 16, aspect_h = 16; }; } end local sparktrail = function(fn,tgt,color) return (fn or minetest.add_particlespawner)({ amount = 240, time = 1, attached = tgt; minpos = {x = -0.4, y = -0.5, z = -0.4}; maxpos = {x = 0.4, y = tgt:get_properties().eye_height or 0.5, z = 0.4}; minacc = {x = 0.0, y = 0.05, z = 0.0}; maxacc = {x = 0.0, y = 0.15, z = 0.0}; minexptime = 1.5, maxexptime = 5; minsize = 0.5, maxsize = 2.6, glow = 14; texture = sorcery.vfx.glowspark(color):render(); animation = { type = 'vertical_frames', length = 5.1; aspect_w = 16, aspect_h = 16; }; }); end return { translocate = { name = 'Translocate'; tone = {0,235,233}; minpower = 3; rarity = 15; amulets = { ................................................................................ else local pos = minetest.string_to_pos(ctx.meta:get_string('rune_return_dest')) ctx.meta:set_string('rune_return_dest','') local subjects = { ctx.caster } local center = ctx.caster:get_pos() ctx.sparkle = false local delay = math.max(3,10 - ctx.stats.power) + 3*(math.random()*2-1) for _,s in pairs(subjects) do local offset = vector.subtract(s:get_pos(), center) local pt = sorcery.lib.node.get_arrival_point(vector.add(pos,offset)) if pt then -- minetest.sound_play('sorcery_stutter', { -- object = s, gain = 0.8; -- },true) local mydelay = delay + math.random(-10,10)*.1; local sh = s:get_properties().eye_height local color = sorcery.lib.color(29,205,247) sorcery.lib.node.preload(pt,s) sorcery.spell.cast { duration = mydelay; caster = ctx.caster; subjects = {{player=s,dest=pt}}; timeline = { [0] = function(sp,_,timeleft) sparkle(color,sp,timeleft*100, timeleft, 0.3,1.3, sh) sp.windup = (sp.play_now{ sound = 'sorcery_windup'; where = 'subjects'; gain = 0.4; fade = 1.5; })[1] end; [0.4] = function(sp,_,timeleft) sparkle(color,sp,timeleft*150, timeleft, 0.6,1.8, sh) end; [0.7] = function(sp,_,timeleft) sparkle(color,sp,timeleft*80, timeleft, 2,4, sh) end; [1] = function(sp) sp.silence(sp.windup) minetest.sound_play('sorcery_zap', { pos = pt, gain = 0.4 },true) minetest.sound_play('sorcery_zap', { pos = s:get_pos(), gain = 0.4 },true) sorcery.vfx.body_sparkle(nil,sorcery.lib.color(20,255,120),2,s:get_pos()) s:set_pos(pt) sorcery.vfx.body_sparkle(s,sorcery.lib.color(20,120,255),2) end; }; sounds = { [0] = { pos = 'subjects'; sound = 'sorcery_stutter'; }; }; } end end end end; frame = { iridium = { name = 'Mass Return'; ................................................................................ }; disjoin = { name = 'Disjoin'; tone = {159,235,0}; minpower = 4; rarity = 20; amulets = { sapphire = { name = 'Unsealing'; desc = 'Wielding this amulet, a touch of your hand will unravel even the mightiest protective magics, leaving doors unsealed and walls free to tear down'; }; amethyst = { name = 'Purging'; desc = 'Free yourself from the grip of any malicious spellwork with a snap of your fingers — interrupting all of your own active spells in the process, including impending translocations'; cast = function(ctx) local h = ctx.heading.eyeheight * 1.1 minetest.add_particlespawner { time = 0.2, amount = math.random(200,250), attached = ctx.caster; glow = 14, texture = sorcery.vfx.glowspark(sorcery.lib.color(156,255,10)):render(); minpos = {x = -0.3, y = -0.5, z = -0.3}; maxpos = {x = 0.3, y = h, z = 0.3}; minvel = {x = -1.8, y = -1.8, z = -1.8}; maxvel = {x = 1.8, y = 1.8, z = 1.8}; minsize = 0.2, maxsize = 5; animation = { type = 'vertical_frames', length = 4.1; aspect_w = 16, aspect_h = 16; }; minexptime = 2, maxexptime = 4; } minetest.sound_play('sorcery_disjoin',{object=ctx.caster},true) sorcery.spell.disjoin{target=ctx.caster} end; }; emerald = { name = 'Disjunction Field'; desc = 'Render an area totally opaque to spellwork for a period of time, disrupting any existing spells and preventing further spellcasting therein'; }; ruby = { name = 'Disjunction'; desc = 'Wield this amulet against a spellcaster to disrupt and abort all their spells in progress, perhaps to trap a foe intent on translocating away, or unleash its force upon the victim of a malign hex to free them from its clutches'; frame = { iridium = { name = 'Nullification'; desc = 'Not only will your victim\'s spells be nullified, but all enchanted objects they carry will be stripped of their power — or possibly even destroyed outright'; }; }; }; luxite = { name = 'Disjunctive Aura'; desc = 'For a time, all magic undertaken in your vicinity will fail totally'; cast = function(ctx) sorcery.spell.cast { caster = ctx.caster, attach = 'caster'; disjunction = true, range = 4 + ctx.stats.power; duration = 10 + ctx.stats.power * 3; timeline = { [0] = function(s,_,tl) sparkle(sorcery.lib.color(120,255,30), s, 30 * tl, tl, 0.3,1.4, ctx.heading.eyeheight*1.1) end }; sounds = { [0] = { sound = 'sorcery_disjoin', pos = 'caster' }; [1] = { sound = 'sorcery_powerdown', pos = 'caster' }; }; } end }; diamond = { name = 'Mundanity'; desc = 'Strip away the effects of all active potions and spells in your immediate vicinity, leaving adversaries without their magicks to enhance and protect them, and allies free of any curses they may be hobbled by -- and, of course, vice versa'; frame = { 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'; }; }; }; } }; repulse = { name = 'Repulse'; tone = {0,180,235}; minpower = 1; rarity = 7; amulets = { amethyst = { name = 'Hurling'; desc = 'Wielding this amulet, a mere flick of your fingers will lift any target of your choice bodily into the air and press upon them with tremendous repulsive force, throwing them like a hapless ragdoll out of your path'; cast = function(ctx) if not (ctx.target and ctx.target.type == 'object') then return false end local tgt = ctx.target.ref local line = vector.subtract(ctx.caster:get_pos(), tgt:get_pos()) -- direction vector from target to caster print('line',dump(line)) local dir,mag = sorcery.lib.math.vsep(line) if mag > 6 then return false end -- no cheating! local force = 20 + (ctx.stats.power * 2.5) minetest.sound_play('sorcery_hurl',{pos=tgt:get_pos()},true) local immortal = tgt:get_luaentity():get_armor_groups().immortal or 0 if minetest.is_player(tgt) or immortal == 0 then tgt:punch(ctx.caster, 1, { full_punch_interval = 1; damage_groups = { fleshy = force / 10 }; }) end sparktrail(nil,tgt,sorcery.lib.color(101,226,255)) if dir.y > 0 then dir.y = 0 end -- spell always lifts dir = vector.add(dir, {x=0,z=0,y=-0.25}) local vel = vector.multiply(dir,0-force) tgt:add_velocity(vel) end; }; ruby = { name = 'Liftoff'; desc = 'Lift yourself high into the air with a blast of violent repulsive force against the ground, and drift down safely to a position of your choice'; cast = function(ctx) local power = 14 * (1+(ctx.stats.power * 0.2)) minetest.sound_play('sorcery_hurl',{object=ctx.caster},true) sorcery.spell.cast { caster = ctx.caster; subjects = {{player=ctx.caster}}; duration = power * 0.25; timeline = { [0] = function(s,_,tl) sparktrail(s.visual_subjects,ctx.caster,sorcery.lib.color(255,252,93)) ctx.caster:add_velocity{y=power;x=0,z=0} s.affect { duration = power * 0.25; raise = 2; fall = (power * 0.25) * 0.3; impacts = { gravity = 0.1; }; } end; }; } end; }; sapphire = { name = 'Flinging'; desc = 'Toss an enemy violently into the air, and allow the inevitable impact to do your dirty work for you'; }; emerald = { name = 'Shockwave'; ................................................................................ amulets = { amethyst = { name = 'Sapping'; desc = 'Punch a hole in enemy fortifications big enough to slip through but small enough to avoid immediate attention'; }; ruby = { name = 'Shattering'; desc = 'Tear a violent wound in the land with the destructive force of this amulet'; }; emerald = { name = 'Detonate'; desc = 'Wielding this amulet, you can loose an extraordinarily powerful bolt of flame from your fingertips that will explode violently on impact, wreaking total havoc wherever it lands'; cast = function(ctx) local speed = 40 local radius = math.random(math.floor(ctx.stats.power*0.5),math.ceil(ctx.stats.power)) ................................................................................ bolt:set_velocity(vel) end; }; luxite = { name = 'Lethal Aura'; desc = 'For a time, anyone who approaches you, whether friend or foe, will suffer immediate retaliation as they are quickly sapped of their life force'; }; mese = { name = 'Cataclysm'; desc = 'Use this amulet once to pick a target, then visit devastation upon it from afar with a mere snap of your fingers'; }; diamond = { name = 'Killing'; mingrade = 4; desc = 'Wield this amulet against a foe to instantly snuff the life out of their mortal form, regardless of their physical protections.'; cast = function(ctx) if not (ctx.target and ctx.target.type == 'object') then return false end local tgt = ctx.target.ref |
Modified entities.lua from [2261aac8b4] to [9e257faffc].
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
age = u.marshal.t.u32; lastemit = u.marshal.t.u32; } minetest.register_entity('sorcery:spell_projectile_flamebolt',{ initial_properties = { visual = "sprite"; -- use_texture_alpha = true; textures = {'sorcery_fireball.png'}; groups = {immortal = 1}; visual_size = { x = 2, y = 2, z = 2 }; physical = true; collide_with_objects = true; pointable = false; glow = 14; static_save = false; }; on_step = function(self,dtime,collision) local pos = self.object:get_pos() if not self._meta then self._meta = { age = 0; lastemit = 0; emitters = {} } goto emit end self._meta.age = self._meta.age + dtime if self._meta.age >= 6 then goto destroy elseif (self._meta.age - self._meta.lastemit) < 3 then goto collcheck end ::emit:: do self._meta.lastemit = self._meta.age local spawn = function(num, life_min, life_max, size_min, size_max, gl, speed, img) table.insert(self._meta.emitters, minetest.add_particlespawner { amount = num; minexptime = life_min; |
| < > > > > > > > > > > > |
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
age = u.marshal.t.u32; lastemit = u.marshal.t.u32; } minetest.register_entity('sorcery:spell_projectile_flamebolt',{ initial_properties = { visual = "sprite"; use_texture_alpha = true; textures = {'sorcery_fireball.png'}; visual_size = { x = 2, y = 2, z = 2 }; physical = true; collide_with_objects = true; pointable = false; glow = 14; static_save = false; shaded = false; }; on_activate = function(self) self.object:set_armor_groups{immortal = 1} end; on_step = function(self,dtime,collision) local pos = self.object:get_pos() if not self._meta then self._meta = { age = 0; lastemit = 0; emitters = {} } goto emit end self._meta.age = self._meta.age + dtime if self._meta.age >= 6 then goto destroy elseif (self._meta.age - self._meta.lastemit) < 3 then goto collcheck end -- fireballs dissipate when entering antimagic fields do local probe = sorcery.spell.probe(self.object:get_pos()) if probe.disjunction and not self._meta.ignore_disjunction then sorcery.vfx.cast_sparkle(nil,sorcery.lib.color(255,90,10),3,0.3,self.object:get_pos()) goto destroy end end ::emit:: do self._meta.lastemit = self._meta.age local spawn = function(num, life_min, life_max, size_min, size_max, gl, speed, img) table.insert(self._meta.emitters, minetest.add_particlespawner { amount = num; minexptime = life_min; |
Modified gems.lua from [d9755d7797] to [58885d2bb0].
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
local img = sorcery.lib.image local img_stone = img('sorcery_amulet.png'):multiply(sorcery.lib.color(gem.tone)) local img_sparkle = img('sorcery_amulet_sparkle.png') local useamulet = function(stack,user,target) local sp = sorcery.amulet.getspell(stack) if not sp or not sp.cast then return nil end local stats = sorcery.amulet.stats(stack) local ctx = { caster = user; target = target; stats = stats; amulet = stack; meta = stack:get_meta(); -- avoid spell boilerplate color = sorcery.lib.color(sp.tone); today = minetest.get_day_count(); heading = { pos = user:get_pos(); yaw = user:get_look_dir(); pitch = user:get_look_vertical(); angle = user:get_look_horizontal(); eyeheight = user:get_properties().eye_height; }; |
> > > > > |
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
local img = sorcery.lib.image local img_stone = img('sorcery_amulet.png'):multiply(sorcery.lib.color(gem.tone)) local img_sparkle = img('sorcery_amulet_sparkle.png') local useamulet = function(stack,user,target) local sp = sorcery.amulet.getspell(stack) if not sp or not sp.cast then return nil end local stats = sorcery.amulet.stats(stack) local probe = sorcery.spell.probe(user:get_pos()) -- amulets don't work in antimagic fields, though some may want to -- implement this logic themselves (for instance to check a range) if (probe.disjunction and not sp.ignore_disjunction) then return nil end local ctx = { caster = user; target = target; stats = stats; amulet = stack; meta = stack:get_meta(); -- avoid spell boilerplate color = sorcery.lib.color(sp.tone); today = minetest.get_day_count(); probe = probe; heading = { pos = user:get_pos(); yaw = user:get_look_dir(); pitch = user:get_look_vertical(); angle = user:get_look_horizontal(); eyeheight = user:get_properties().eye_height; }; |
Modified init.lua from [e9275c1995] to [c1be2dc670].
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
local data = sorcery.unit('data',nil,'lore')
local root = sorcery.unit()
sorcery.stage('bootstrap',data,root)
data {'ui'}
sorcery.unit('lib') {
-- convenience
'str';
-- serialization
'marshal', 'json';
-- data structures
'tbl', 'class';
-- wrappers
'color', 'image', 'ui';
-- game
................................................................................
sorcery.registry.mk(k,v)
end
end
end
sorcery.stage('startup',data)
for _,u in pairs {
'vfx'; 'attunement'; 'context'; 'itemclass';
'potions'; 'metal', 'gems'; 'leylines'; 'infuser';
'altar'; 'wands'; 'tools', 'crafttools'; 'enchanter';
'harvester'; 'metallurgy-hot', 'metallurgy-cold';
'entities'; 'recipes'; 'coins'; 'interop';
'tnodes'; 'forcefield'; 'farcaster'; 'portal';
'cookbook', 'writing'; 'disassembly'; 'displacer';
'gravitator'; 'precipitator'; 'calendar', 'astrolabe';
|
|
|
|
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
local data = sorcery.unit('data',nil,'lore') local root = sorcery.unit() sorcery.stage('bootstrap',data,root) data {'ui'} sorcery.unit('lib') { -- convenience 'str', 'math'; -- serialization 'marshal', 'json'; -- data structures 'tbl', 'class'; -- wrappers 'color', 'image', 'ui'; -- game ................................................................................ sorcery.registry.mk(k,v) end end end sorcery.stage('startup',data) for _,u in pairs { 'vfx'; 'attunement'; 'context'; 'itemclass'; 'spell'; 'potions'; 'metal', 'gems'; 'leylines'; 'infuser'; 'altar'; 'wands'; 'tools', 'crafttools'; 'enchanter'; 'harvester'; 'metallurgy-hot', 'metallurgy-cold'; 'entities'; 'recipes'; 'coins'; 'interop'; 'tnodes'; 'forcefield'; 'farcaster'; 'portal'; 'cookbook', 'writing'; 'disassembly'; 'displacer'; 'gravitator'; 'precipitator'; 'calendar', 'astrolabe'; |
Modified lib/tbl.lua from [eefda5e589] to [6f943d189b].
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 ... 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 ... 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
local new = fn.copy(r1) for i=1,#r2 do new[#new + 1] = r2[i] end return new end fn.capitalize = function(str) return string.upper(string.sub(str, 1,1)) .. string.sub(str, 2) end fn.has = function(tbl,value,eqfn) for k,v in pairs(tbl) do if eqfn then if eqfn(v,value,tbl) then return true, k end else if value == v then return true, k end end ................................................................................ table.sort(keys) return fn.each(keys, function(k,i) return f(tbl[k],k,i) end) end fn.iter = function(tbl,fn) for i=1,#tbl do fn(tbl[i], i) end end fn.map = function(tbl,fn) local new = {} for k,v in pairs(tbl) do local nv, nk = fn(v, k) new[nk or k] = nv ................................................................................ fn.fold = function(tbl,fn,acc) if #tbl == 0 then fn.each_o(tbl, function(v) acc = fn(acc, v, k) end) else for i=0,#tbl do acc = fn(acc,tbl[i],i) end end return acc end fn.walk = function(tbl,path) if type(path) == 'table' then |
< < < < | < < | | |
86 87 88 89 90 91 92 93 94 95 96 97 98 99 ... 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 ... 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
local new = fn.copy(r1) for i=1,#r2 do new[#new + 1] = r2[i] end return new end fn.has = function(tbl,value,eqfn) for k,v in pairs(tbl) do if eqfn then if eqfn(v,value,tbl) then return true, k end else if value == v then return true, k end end ................................................................................ table.sort(keys) return fn.each(keys, function(k,i) return f(tbl[k],k,i) end) end fn.iter = function(tbl,fn) for i,v in ipairs(tbl) do fn(v, i) end end fn.map = function(tbl,fn) local new = {} for k,v in pairs(tbl) do local nv, nk = fn(v, k) new[nk or k] = nv ................................................................................ fn.fold = function(tbl,fn,acc) if #tbl == 0 then fn.each_o(tbl, function(v) acc = fn(acc, v, k) end) else for i,v in ipairs(tbl) do acc = fn(acc,v,i) end end return acc end fn.walk = function(tbl,path) if type(path) == 'table' then |
Modified sorcery.md from [246ca8c1c8] to [b729085cc9].
16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
* **xdecor** for various tools and ingredients, especially honey and the hammer * **basic_materials** for crafting ingredients * **instant_ores** for ore generation. temporary, will be removed and replaced with home-grown mechanism soon * **farming redo** for potion ingredients * **late** for spell, potion, and gravitator effects * **note**: in order for the gravitator to work, the late condition interval must be lowered from its default of 1.0 to 0.1. this currently can only be done by altering a variable at the top of `late/conditions.lua`, though a note in the source suggests a configuration option will be added eventually. hopefully this is so. # interoperability sorcery has special functionality to ensure it can cooperate with various other modules, although they are not necessarily required for it to function. ## xdecor by default, `sorcery` disables the xdecor enchanter, since `sorcery` offers its own, much more sophisticated enchantment mechanism. however, the two can coexist if you really want; a configuration flag can be used to prevent `sorcery` disabling the xdecor enchanter. ## hopper |
> > > |
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
* **xdecor** for various tools and ingredients, especially honey and the hammer * **basic_materials** for crafting ingredients * **instant_ores** for ore generation. temporary, will be removed and replaced with home-grown mechanism soon * **farming redo** for potion ingredients * **late** for spell, potion, and gravitator effects * **note**: in order for the gravitator to work, the late condition interval must be lowered from its default of 1.0 to 0.1. this currently can only be done by altering a variable at the top of `late/conditions.lua`, though a note in the source suggests a configuration option will be added eventually. hopefully this is so. ## libraries * **luajit**, because `sorcery`'s code uses modern features not available in the ancient lua version bundled with minetest. alternately, it may be possible to build minetest against a more recent lua version if you're feeling masochistic; luajit will probably be faster tho and has first-party support # interoperability sorcery has special functionality to ensure it can cooperate with various other modules, although they are not necessarily required for it to function. ## xdecor by default, `sorcery` disables the xdecor enchanter, since `sorcery` offers its own, much more sophisticated enchantment mechanism. however, the two can coexist if you really want; a configuration flag can be used to prevent `sorcery` disabling the xdecor enchanter. ## hopper |
Modified vfx.lua from [343a5ccf55] to [aaa85eb70f].
1 2 3 4 5 6 7 8 |
sorcery.vfx = {} sorcery.vfx.cast_sparkle = function(caster,color,strength,duration,pos) local ofs = pos and function(x) return vector.add(pos,x) end or function(x) return x end local height = caster:get_properties().eye_height minetest.add_particlespawner { |
> > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
sorcery.vfx = {} sorcery.vfx.glowspark = function(color) local spark = sorcery.lib.image('sorcery_spark.png') return spark:blit(spark:multiply(color)) end sorcery.vfx.cast_sparkle = function(caster,color,strength,duration,pos) local ofs = pos and function(x) return vector.add(pos,x) end or function(x) return x end local height = caster:get_properties().eye_height minetest.add_particlespawner { |
Modified wands.lua from [b35b5eeee9] to [e661ef77a3].
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
|
end local wand_cast = function(stack, user, target) local meta = stack:get_meta() local wand = sorcery.wands.util.getproto(stack) if meta:contains('sorcery_wand_spell') == false then return nil end local spell = meta:get_string('sorcery_wand_spell') local castfn = sorcery.data.spells[spell].cast if castfn == nil then return nil end local matprops = sorcery.wands.util.matprops(wand) if matprops.bond then local userct, found = 0, false for i=1,matprops.bond do local prop = 'bound_user_' .. tostring(i) if meta:contains(prop) then ................................................................................ local context = { base = wand; stats = matprops; meta = meta; item = stack; caster = user; target = target; today = minetest.get_day_count(); heading = { pos = user:get_pos(); yaw = user:get_look_dir(); pitch = user:get_look_vertical(); angle = user:get_look_horizontal(); eyeheight = uprops.eye_height; |
|
>
>
>
>
>
>
>
|
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
|
end local wand_cast = function(stack, user, target) local meta = stack:get_meta() local wand = sorcery.wands.util.getproto(stack) if meta:contains('sorcery_wand_spell') == false then return nil end local spell = meta:get_string('sorcery_wand_spell') local spelldata = sorcery.data.spells[spell] -- wands don't work in anti-magic fields local probe = sorcery.spell.probe(user:get_pos()) if probe.disjunction and not spelldata.ignore_disjunction then return nil end local castfn = spelldata.cast if castfn == nil then return nil end local matprops = sorcery.wands.util.matprops(wand) if matprops.bond then local userct, found = 0, false for i=1,matprops.bond do local prop = 'bound_user_' .. tostring(i) if meta:contains(prop) then ................................................................................ local context = { base = wand; stats = matprops; meta = meta; item = stack; caster = user; target = target; probe = probe; today = minetest.get_day_count(); heading = { pos = user:get_pos(); yaw = user:get_look_dir(); pitch = user:get_look_vertical(); angle = user:get_look_horizontal(); eyeheight = uprops.eye_height; |