sorcery  Diff

Differences From Artifact [bd35ca52e8]:

  • File data/runes.lua — part of check-in [96c5289a2a] at 2020-10-21 03:35:35 on branch trunk — add rune forges, runes, amulet frames, write sacrifice spell, touch up amulet graphics, enable enchantment of amulets (though spells cannot yet be cast), defuckulate syncresis core icon, unfuckitize sneaky leycalc bug that's probably been the cause of some long-standing wackiness, add item classes, add some more textures, disbungle various other asstastrophes, remove sneaky old debug code, improve library code, add utility for uploading merge requests (user: lexi, size: 6898) [annotate] [blame] [check-ins using]

To Artifact [720c3d8102]:


     9      9   		name = 'Translocate';
    10     10   		tone = {0,235,233};
    11     11   		minpower = 3;
    12     12   		rarity = 15;
    13     13   		amulets = {
    14     14   			amethyst = {
    15     15   				name = 'Joining';
    16         -				desc = 'Give this amulet to another and they can arrive at your side in a flash from anywhere in the world — though returning whence they came may be a more difficult matter';
           16  +				desc = 'Give this amulet to another and they can arrive safely at your side in a flash from anywhere in the world — though returning whence they came may be a more difficult matter';
           17  +				apply = function(ctx)
           18  +					local maker = ctx.user:get_player_name()
           19  +					ctx.meta:set_string('rune_join_target',maker)
           20  +				end;
           21  +				remove = function(ctx) ctx.meta:set_string('rune_join_target','') end;
    17     22   				frame = {
    18     23   					gold = {
    19     24   						name = 'Exchange';
    20     25   						desc = 'Give this amulet to another and they will be able to trade places with you no matter where in the world each of you might be.'; 
    21     26   					};
    22     27   					cobalt = {
    23     28   						name = 'Sending';
................................................................................
    27     32   						name = 'Arrival';
    28     33   						desc = "Give this amulet to another and they will be able to arrive at your side in a flash from anywhere in the world, carrying others with them in the spell's grip";
    29     34   					};
    30     35   				};
    31     36   			};
    32     37   			sapphire = {
    33     38   				name = 'Return';
    34         -				desc = 'Use this amulet once to bind it to a particular point in the world, then use it again to return instantly to that point.';
           39  +				desc = 'Use this amulet once to bind it to a particular point in the world, then discharge its spell to return instantly to that point.';
           40  +				remove = function(ctx)
           41  +					ctx.meta:set_string('rune_return_dest','')
           42  +				end;
           43  +				cast = function(ctx)
           44  +					if not ctx.meta:contains('rune_return_dest') then
           45  +						local pos = ctx.caster:get_pos()
           46  +						ctx.meta:set_string('rune_return_dest',minetest.pos_to_string(pos))
           47  +						return true -- play effects but do not break spell
           48  +					else
           49  +						local pos = minetest.string_to_pos(ctx.meta:get_string('rune_return_dest'))
           50  +						ctx.meta:set_string('rune_return_dest','')
           51  +						local subjects = { ctx.caster }
           52  +						local center = ctx.caster:get_pos()
           53  +						ctx.sparkle = false
           54  +						for _,s in pairs(subjects) do
           55  +							local offset = vector.subtract(s:get_pos(), center)
           56  +							local pt = sorcery.lib.node.get_arrival_point(vector.add(pos,offset))
           57  +							if pt then
           58  +								sorcery.vfx.body_sparkle(s,sorcery.lib.color(20,120,255),2)
           59  +								sorcery.vfx.body_sparkle(nil,sorcery.lib.color(20,255,120),2,pt)
           60  +								s:set_pos(pt)
           61  +							end
           62  +						end
           63  +					end
           64  +				end;
    35     65   				frame = {
    36     66   					iridium = {
    37     67   						name = 'Mass Return';
    38     68   						desc = 'Use this amulet once to bind it to a particular point in the world, then carry yourself and everyone around you back to that point in a flash simply by using it again';
    39     69   					};
    40     70   				};
    41     71   			};
................................................................................
   114    144   			ruby = {
   115    145   				name = 'Shattering';
   116    146   				desc = 'Tear a violent wound in the earth with the destructive force of this amulet';
   117    147   			};
   118    148   			diamond = {
   119    149   				name = 'Killing';
   120    150   				desc = 'Wield this amulet against a foe to instantly snuff the life out of their mortal form, regardless of their physical protections.';
          151  +				cast = function(ctx)
          152  +					if not (ctx.target and ctx.target.type == 'object') then return false end
          153  +					local tgt = ctx.target.ref
          154  +					if not minetest.is_player(obj) then return false end
          155  +					local tgth = tgt:get_properties().eye_height
          156  +					sorcery.vfx.bloodburst(vector.add(tgt:get_pos(),{x=0,y=tgth/2,z=0}),20)
          157  +					minetest.sound_play('sorcery_bloody_burst', { pos = pos, gain = 1.5 })
          158  +					tgt:set_hp(0)
          159  +				end;
   121    160   				frame = {
   122    161   					iridium = {
   123    162   						name = 'Massacre';
   124    163   						desc = "Unleash the dark and wicked force that lurks within this fell amulet to instantaneously slay all those who surround you, friend and foe alike";
   125    164   					};
   126    165   				};
   127    166   			};
................................................................................
   179    218   	};
   180    219   	dominate = {
   181    220   		name = 'Dominate';
   182    221   		tone = {235,0,228};
   183    222   		minpower = 4;
   184    223   		rarity = 40;
   185    224   		amulets = {
          225  +			amethyst = {
          226  +				name = 'Suffocation';
          227  +				desc = 'Wrap this spell tightly around your victim\'s throat, cutting off their oxygen until you release them.';
          228  +			};
   186    229   			ruby = {
   187    230   				name = 'Exsanguination';
   188    231   				desc = 'Rip the life force out of another, leaving them on the brink of death, and use it to mend your own wounds and invigorate your own being';
          232  +				cast = function(ctx)
          233  +					if not (ctx.target and ctx.target.type == 'object') then return false end
          234  +					local tgt = ctx.target.ref
          235  +					local takefac = math.min(99,50 + (ctx.stats.power * 5)) / 100
          236  +					local dmg = tgt:get_hp() * takefac
          237  +					print("!!! dmg calc",takefac,dmg,tgt:get_hp())
          238  +
          239  +					local numhits = math.random(6,10+ctx.stats.power/2)
          240  +					local function dohit(hitsleft)
          241  +						if tgt == nil or tgt:get_properties() == nil then return end
          242  +						tgt:punch(ctx.caster, 1, {
          243  +							full_punch_interval = 1;
          244  +							damage_groups = { fleshy = dmg / numhits }
          245  +						})
          246  +						local tgth = tgt:get_properties().eye_height
          247  +						sorcery.vfx.bloodburst(vector.add(tgt:get_pos(),{x=0,y=tgth/2,z=0}),math.random(10 * takefac, 40 * takefac))
          248  +						ctx.caster:set_hp(ctx.caster:get_hp() + math.max(1,(dmg/numhits)*takefac))
          249  +
          250  +						local sound = {'sorcery_bloody_hit','sorcery_crunch',false}
          251  +						sound = sound[math.random(#sound)]
          252  +						if sound ~= false then
          253  +							minetest.sound_play(sound, { pos = pos, gain = math.random(5,15)*0.1 })
          254  +						end
          255  +
          256  +						local nexthit = math.random() * 0.4 + 0.1
          257  +						local dir = vector.subtract(ctx.caster:get_pos(), tgt:get_pos())
          258  +						local spark = sorcery.lib.image('sorcery_spark.png')
          259  +						minetest.add_particlespawner {
          260  +							amount = math.random(80*takefac,150*takefac);
          261  +							texture = spark:blit(spark:multiply(sorcery.lib.color(255,20,10))):render();
          262  +							time = nexthit;
          263  +							attached = tgt;
          264  +							minpos = {x = -0.3, y = -0.5, z = -0.3};
          265  +							maxpos = {x =  0.3, y = tgth, z = 0.3};
          266  +							minvel = vector.multiply(dir,0.5);
          267  +							maxvel = vector.multiply(dir,0.9);
          268  +							minacc = vector.multiply(dir,0.1);
          269  +							maxacc = vector.multiply(dir,0.2);
          270  +							minexptime = nexthit * 1.5;
          271  +							maxexptime = nexthit * 2;
          272  +							minsize = 0.5;
          273  +							maxsize = 5 * takefac;
          274  +							glow = 14;
          275  +							animation = {
          276  +								type = 'vertical_frames';
          277  +								aspect_w = 16, aspect_h = 16;
          278  +								length = nexthit*2 + 0.1;
          279  +							};
          280  +						}
          281  +
          282  +						if hitsleft > 0 then
          283  +							minetest.after(nexthit, function() dohit(hitsleft-1) end)
          284  +						end
          285  +					end
          286  +					dohit(numhits)
          287  +				end;
   189    288   			};
   190    289   			amethyst = {
   191    290   				name = 'Disarming';
   192    291   				desc = 'Wield this amulet against a foe to rip all the weapons in their possession out of their grasp';
   193    292   				frame = {
   194    293   					iridium = {
   195    294   						name = 'Peacemaking';