summaryrefslogtreecommitdiff
path: root/npc/magic
diff options
context:
space:
mode:
Diffstat (limited to 'npc/magic')
-rwxr-xr-xnpc/magic/level0-antiprotect.txt22
-rwxr-xr-xnpc/magic/level0-discharge.txt17
-rwxr-xr-xnpc/magic/level0-wand.txt83
-rwxr-xr-xnpc/magic/level1-aggravate.txt28
-rwxr-xr-xnpc/magic/level1-detect-magic.txt29
-rwxr-xr-xnpc/magic/level1-experience.txt45
-rwxr-xr-xnpc/magic/level1-flare-dart.txt51
-rwxr-xr-xnpc/magic/level1-grow-alizarin.txt37
-rwxr-xr-xnpc/magic/level1-grow-cobalt.txt37
-rwxr-xr-xnpc/magic/level1-grow-gamboge.txt37
-rwxr-xr-xnpc/magic/level1-grow-mauve.txt37
-rwxr-xr-xnpc/magic/level1-lesser-heal.txt50
-rwxr-xr-xnpc/magic/level1-magic-blade.txt54
-rwxr-xr-xnpc/magic/level1-make-sulphur.txt24
-rwxr-xr-xnpc/magic/level1-sense-spouse.txt24
-rwxr-xr-xnpc/magic/level1-summon-maggots.txt55
-rwxr-xr-xnpc/magic/level1-transmute-wood.txt36
-rwxr-xr-xnpc/magic/level2-arrow-hail.txt115
-rwxr-xr-xnpc/magic/level2-barrier.txt47
-rwxr-xr-xnpc/magic/level2-detect-players.txt33
-rwxr-xr-xnpc/magic/level2-enchant-lifestone.txt35
-rwxr-xr-xnpc/magic/level2-flying-backpack.txt42
-rwxr-xr-xnpc/magic/level2-happy-curse.txt42
-rwxr-xr-xnpc/magic/level2-hide.txt46
-rwxr-xr-xnpc/magic/level2-lay-on-hands.txt58
-rwxr-xr-xnpc/magic/level2-lightning-strike.txt86
-rwxr-xr-xnpc/magic/level2-magic-knuckles.txt51
-rwxr-xr-xnpc/magic/level2-make-arrows.txt26
-rwxr-xr-xnpc/magic/level2-make-iron-powder.txt26
-rwxr-xr-xnpc/magic/level2-make-shirt.txt24
-rwxr-xr-xnpc/magic/level2-make-short-tanktop.txt24
-rwxr-xr-xnpc/magic/level2-make-tanktop.txt24
-rwxr-xr-xnpc/magic/level2-protect.txt48
-rwxr-xr-xnpc/magic/level2-rain.txt104
-rwxr-xr-xnpc/magic/level2-shear.txt67
-rwxr-xr-xnpc/magic/level2-summon-fluffies.txt56
-rwxr-xr-xnpc/magic/level2-summon-mouboo.txt56
-rwxr-xr-xnpc/magic/level2-summon-pinkie.txt56
-rwxr-xr-xnpc/magic/level2-summon-snakes.txt57
-rwxr-xr-xnpc/magic/level2-summon-spiky-mushroom.txt56
-rwxr-xr-xnpc/magic/level2-summon-wickedmushroom.txt57
-rwxr-xr-xnpc/magic/level2-toxic-dart.txt57
-rwxr-xr-xnpc/magic/level3-necromancy.txt51
43 files changed, 2010 insertions, 0 deletions
diff --git a/npc/magic/level0-antiprotect.txt b/npc/magic/level0-antiprotect.txt
new file mode 100755
index 00000000..db938eab
--- /dev/null
+++ b/npc/magic/level0-antiprotect.txt
@@ -0,0 +1,22 @@
+- script antiprotect NPC32767,{
+ if(call("magic_checks", 1)) end;
+ callfunc "magic_exp";
+
+ if (@antiprotect)
+ goto L_Disable;
+
+ sc_end SC_PHYS_SHIELD;
+ message strcharinfo(0), "Shield : You are now protected against betsanc until you cast detsanc again or logout.";
+ @antiprotect = 1;
+ end;
+
+L_Disable:
+ message strcharinfo(0), "Shield : You are no longer protected against betsanc.";
+ @antiprotect = 0;
+ end;
+
+OnInit:
+ set .invocation$, chr(MAGIC_SYMBOL) + "detsanc"; // used in npcs that refer to this spell
+ registercmd .invocation$, strnpcinfo(0);
+ end;
+}
diff --git a/npc/magic/level0-discharge.txt b/npc/magic/level0-discharge.txt
new file mode 100755
index 00000000..986ccf62
--- /dev/null
+++ b/npc/magic/level0-discharge.txt
@@ -0,0 +1,17 @@
+- script discharge spell NPC32767,{
+ if(call("magic_checks")) end;
+ callfunc "magic_exp";
+
+ // tell the spells they were discharged
+ // XXX: maybe we could make it do area damage when you discharge (release your energy all of a sudden)
+ addtimer 0, "::OnDischarge"; // seeks OnDischarge in ALL npcs
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "discharge"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 0;
+ .exp_gain = 0;
+ end;
+}
diff --git a/npc/magic/level0-wand.txt b/npc/magic/level0-wand.txt
new file mode 100755
index 00000000..5852ef0e
--- /dev/null
+++ b/npc/magic/level0-wand.txt
@@ -0,0 +1,83 @@
+- script spell-wand NPC32767,{
+ if(call("magic_checks")) goto L_Failed;
+ set @wandspell[0], 0; // reset state
+ callfunc "adjust_spellpower";
+ callsub S_Loop; // set up wand
+ if(@wandspell[0] < 1) goto L_Failed;
+
+ // here we install
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 500, "Magic Timer::OnClear"; // set the new debuff
+ misceffect FX_MAGIC_GENERIC, strcharinfo(0);
+
+ callfunc "magic_exp";
+ goto L_FreeRecast;
+
+L_FreeRecast:
+ if (@wandspell[4] > 0)
+ addtimer 0, strnpcinfo(0) + "::OnSetRecast";
+ end;
+
+OnDischarge:
+ if (@wandspell[4] < 1) end;
+ @wandspell[4] = 0;
+ misceffect FX_FIRE_BURST, strcharinfo(0);
+ overrideattack;
+ end;
+
+OnSetRecast:
+ overrideattack @wandspell[3], 3, ATTACK_ICON_GENERIC, @wandspell[0], strnpcinfo(0)+"::OnAttack";
+ end;
+
+OnAttack:
+ if(target(BL_ID, @target_id, 22) != 22) goto L_FreeRecast; // 0x02 | 0x04 | 0x10
+ if (Sp < @wandspell[1]) goto L_LowSp;
+ Sp = (Sp - @wandspell[1]);
+ void call("elt_damage", @wandspell[2],@wandspell[2],ELT_NEUTRAL,ELT_NEUTRAL,FX_MAGIC_RED);
+ @wandspell[4] = @wandspell[4] - 1;
+ goto L_FreeRecast;
+
+S_Loop:
+ if ((getequipid(equip_hand1) == .Wands[.@wand_loop]) || (getequipid(equip_hand2) == .Wands[.@wand_loop]))
+ goto S_SetWand;
+ .@wand_loop = (.@wand_loop + 1);
+ if (.@wand_loop >= getarraysize(.Wands))
+ goto S_NoWand;
+ goto S_Loop;
+
+S_SetWand:
+ .@pwr = .WandsPwr[.@wand_loop];
+ if (QL_MORGAN == 2)
+ QL_MORGAN = 3;
+ setarray @wandspell[0],
+ .WandsAnim[.@wand_loop], // wand anim/id
+ (.@pwr * (BaseLevel / 15) + 2), // wand cost
+ (.@pwr * (@spellpower / 3)), // wand dmg
+ (((200 - Agi) * 1200) / 200), //delay
+ (.@pwr + (@spellpower / 10)); // charges
+ return;
+
+S_NoWand:
+ message strcharinfo(0), "Wand : ##3##BYou need a wand Equipped!";
+ return;
+
+L_LowSp:
+ message strcharinfo(0), "Wand : ##3##BOut of Mana";
+ end;
+
+L_Failed:
+ //misceffect FX_ELECTRICITY_RED, strcharinfo(0); // XXX: do we show an effect on fail?
+ //debugmes "cast or attack failed";
+ end;
+
+OnInit:
+ setarray .Wands[0], 0, 758, 1171;
+ setarray .WandsPwr[0], 0, 2, 1;
+ setarray .WandsAnim[0], 0, 35, 33;
+ .school = SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "confringo"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 0;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level1-aggravate.txt b/npc/magic/level1-aggravate.txt
new file mode 100755
index 00000000..137e121f
--- /dev/null
+++ b/npc/magic/level1-aggravate.txt
@@ -0,0 +1,28 @@
+- script spell-aggravate NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 3) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 1000, "Magic Timer::OnClear"; // set the new debuff
+ set @args$, ""; callfunc "adjust_spellpower"; // we reset @args$ because this spell should not have a target
+ @distance = (2 + (@spellpower / 50));
+ Sp = Sp - 3;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ callfunc "magic_exp";
+ foreach 2, getmapname(), (POS_X - @distance), (POS_Y - @distance), (POS_X + @distance), (POS_Y + @distance), strnpcinfo(0) + "::OnMob";
+ end;
+
+OnMob:
+ if (target(BL_ID, @target_id, 0x20) != 0x20) end; // line of sight
+ aggravate @target_id;
+ misceffect SFX_DEFAULT, @target_id;
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "itenplz"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 1;
+ .exp_gain = 0;
+ end;
+}
diff --git a/npc/magic/level1-detect-magic.txt b/npc/magic/level1-detect-magic.txt
new file mode 100755
index 00000000..693aeb7e
--- /dev/null
+++ b/npc/magic/level1-detect-magic.txt
@@ -0,0 +1,29 @@
+- script detect-magic NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 3) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 6000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 3;
+ misceffect FX_MAGIC_GENERIC, strcharinfo(0);
+ .@range = (@spellpower/50)+1;
+ foreach 1, getmapname(), POS_X - .@range, POS_Y - .@range, POS_X + .@range, POS_Y + .@range,
+ strnpcinfo(0) + "::OnNearbyNpc";
+ callfunc "magic_exp";
+ end;
+
+OnNearbyNpc:
+ .@e$ = strnpcinfo(2,@target_id);
+ if(.@e$ == "#_M" || .@e$ == "#MAGIC" || get(.IS_MAGIC, @target_id))
+ misceffect FX_MAGIC_DEFAULT, @target_id;
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "miteyo"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 1;
+ .exp_gain = 0;
+ end;
+}
diff --git a/npc/magic/level1-experience.txt b/npc/magic/level1-experience.txt
new file mode 100755
index 00000000..72d02610
--- /dev/null
+++ b/npc/magic/level1-experience.txt
@@ -0,0 +1,45 @@
+- script spell-experience NPC32767,{
+ //debugmes MAGIC_EXPERIENCE;
+ //debugmes (MAGIC_EXPERIENCE >> 0) & 0xFFFF; // magic exp
+ //debugmes (MAGIC_EXPERIENCE >> 16) & 0xFF; // last spell index
+ //debugmes (MAGIC_EXPERIENCE >> 24) & 0xFF; // heal exp
+
+ if(call("magic_checks")) end;
+ if (Sp < 1) end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 1000, "Magic Timer::OnClear"; // set the new debuff
+ @level = getskilllv(.school);
+ if (@level < .level) end;
+ callfunc "adjust_spellpower";
+ Sp = Sp - 1;
+ misceffect FX_MAGIC_GENERIC, strcharinfo(0);
+ callfunc "magic_exp";
+ @ratio = ((@last_exp*10) - rand(.MAX_MAGIC_EXP[@level]/30))/.MAX_MAGIC_EXP[@level];
+
+ @mes$ = "You feel completely overwhelmed by your magic.";
+ if(@ratio == 1) set @mes$, "You feel quite overwhelmed by your magic, but are beginning to see patterns.";
+ if(@ratio == 2) set @mes$, "You feel that you have only the bare minimum of control over your magic.";
+ if(@ratio == 3) set @mes$, "Trying to control your magic is still rather troublesome.";
+ if(@ratio == 4) set @mes$, "You feel you still have a few difficulties in controlling your magic.";
+ if(@ratio == 5) set @mes$, "You feel somewhat in control of your magic.";
+ if(@ratio == 6) set @mes$, "You feel mostly in control of your magic.";
+ if(@ratio == 7) set @mes$, "You feel quite in control of your magic.";
+ if(@ratio == 8) set @mes$, "You feel that you have very good control of your magic.";
+ if(@ratio == 9) set @mes$, "You feel in almost perfect control of your magic.";
+ if(@ratio >= 10) set @mes$, "You feel in perfect control of your magic" + if_then_else(@level >= MAX_MAGIC_LEVEL, ".", ", and seem on the verge of something more... perhaps you should see the Mana Seed to ask for more magic?");
+ if(@ratio >= 20) set @mes$, "You have perfect control of what you understand now, but there is now a distinct sensation of something more, something indescribable. If only the Mana Seed would give more magic to you...";
+ if(@ratio >= 45) set @mes$, "Magic flows naturally from you, readily and with ease. Your understanding of what you can currently control at present is flawless, far beyond your requirements to cast magic at this level.";
+ if(@ratio >= 45 && @level < MAX_MAGIC_LEVEL) set @mes$, @mes$ + " Surely the Mana Seed will more than readily offer more magic for such a proficient user.";
+ if(@level >= 5) set @mes$, "You are as proficient at magic as you can possibly be."; // this is the maximum magic level
+ message strcharinfo(0), "Magic : ##3##B"+@mes$;
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "abizit"; // used in npcs that refer to this spell
+ .level = 1;
+ .exp_gain = 0;
+ void call("magic_register");
+ setarray .MAX_MAGIC_EXP[0], 0, 0, 100, 1200, 8000, 40000, 65535;
+ end;
+}
diff --git a/npc/magic/level1-flare-dart.txt b/npc/magic/level1-flare-dart.txt
new file mode 100755
index 00000000..049b1768
--- /dev/null
+++ b/npc/magic/level1-flare-dart.txt
@@ -0,0 +1,51 @@
+- script flare-dart NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 10) end;
+ @level = getskilllv(.school);
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (@level <= 2 && countitem("SulphurPowder") >= 1) delitem "SulphurPowder", 1;
+ elif (@level <= 2) end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 500, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 10;
+ misceffect FX_MAGIC_BLACK, strcharinfo(0);
+ setarray @flarspell[0],
+ sqrt(@spellpower) * 5, //dmg
+ (BaseLevel/3) + 5, // dmg bonus
+ (@spellpower/50) + 3, // charges
+ (((200 - Agi) * 1200) / 200); // delay
+ callfunc "magic_exp";
+ goto L_FreeRecast;
+
+OnAttack:
+ if (target(BL_ID, @target_id, 50) != 50) goto L_FreeRecast; // 0x20 | 0x02 | 0x10
+ misceffect FX_MAGIC_BLACK, strcharinfo(0);
+ void call("elt_damage", @flarspell[0], @flarspell[1], ELT_WATER, ELT_FIRE, FX_MAGIC_BLACK);
+ @flarspell[2] = @flarspell[2] - 1;
+ goto L_FreeRecast;
+
+L_FreeRecast:
+ if (@flarspell[2] > 0)
+ addtimer 0, strnpcinfo(0) + "::OnSetRecast";
+ end;
+
+OnDischarge:
+ if (@flarspell[2] < 1) end;
+ @flarspell[2] = 0;
+ misceffect FX_FIRE_BURST, strcharinfo(0);
+ overrideattack;
+ end;
+
+OnSetRecast:
+ overrideattack @flarspell[3], 4, ATTACK_ICON_GENERIC, 34, strnpcinfo(0)+"::OnAttack";
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_WAR;
+ set .invocation$, chr(MAGIC_SYMBOL) + "flar"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 1;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level1-grow-alizarin.txt b/npc/magic/level1-grow-alizarin.txt
new file mode 100755
index 00000000..3e6810b9
--- /dev/null
+++ b/npc/magic/level1-grow-alizarin.txt
@@ -0,0 +1,37 @@
+- script grow-alizarin NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 4) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (countitem("AlizarinHerb") < 1 || countitem("Root") < 1) end;
+ delitem "AlizarinHerb", 1;
+ delitem "Root", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 2000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 4;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ setarray @summon[0], 0, (getskilllv(.school)/2)+1;
+ callfunc "magic_exp";
+ addtimer 4000-(@spellpower-9), strnpcinfo(0)+"::OnSummon";
+ end;
+
+OnSummon:
+ misceffect FX_PENTAGRAM_BURST, strcharinfo(0);
+ callsub S_SummonAll;
+ end;
+
+S_SummonAll:
+ summon getmapname(), rand(POS_X-2,POS_X+2), rand(POS_Y-2,POS_Y+2), BL_ID, 1032, 1, (@spellpower*50)+10000;
+ @summon[0] = @summon[0] + 1;
+ if (@summon[0] < @summon[1]) goto S_SummonAll;
+ return;
+
+OnInit:
+ .school = SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "modriphoo"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 1;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level1-grow-cobalt.txt b/npc/magic/level1-grow-cobalt.txt
new file mode 100755
index 00000000..62610053
--- /dev/null
+++ b/npc/magic/level1-grow-cobalt.txt
@@ -0,0 +1,37 @@
+- script grow-cobalt NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 4) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (countitem("CobaltHerb") < 1 || countitem("Root") < 1) end;
+ delitem "CobaltHerb", 1;
+ delitem "Root", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 2000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 4;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ setarray @summon[0], 0, (getskilllv(.school)/2)+1;
+ callfunc "magic_exp";
+ addtimer 4000-(@spellpower-9), strnpcinfo(0)+"::OnSummon";
+ end;
+
+OnSummon:
+ misceffect FX_PENTAGRAM_BURST, strcharinfo(0);
+ callsub S_SummonAll;
+ end;
+
+S_SummonAll:
+ summon getmapname(), rand(POS_X-2,POS_X+2), rand(POS_Y-2,POS_Y+2), BL_ID, 1030, 1, (@spellpower*50)+10000;
+ @summon[0] = @summon[0] + 1;
+ if (@summon[0] < @summon[1]) goto S_SummonAll;
+ return;
+
+OnInit:
+ .school = SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "modrisump"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 1;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level1-grow-gamboge.txt b/npc/magic/level1-grow-gamboge.txt
new file mode 100755
index 00000000..7557ddc8
--- /dev/null
+++ b/npc/magic/level1-grow-gamboge.txt
@@ -0,0 +1,37 @@
+- script grow-gamboge NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 4) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (countitem("GambogeHerb") < 1 || countitem("Root") < 1) end;
+ delitem "GambogeHerb", 1;
+ delitem "Root", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 2000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 4;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ setarray @summon[0], 0, (getskilllv(.school)/2)+1;
+ callfunc "magic_exp";
+ addtimer 4000-(@spellpower-9), strnpcinfo(0)+"::OnSummon";
+ end;
+
+OnSummon:
+ misceffect FX_PENTAGRAM_BURST, strcharinfo(0);
+ callsub S_SummonAll;
+ end;
+
+S_SummonAll:
+ summon getmapname(), rand(POS_X-2,POS_X+2), rand(POS_Y-2,POS_Y+2), BL_ID, 1031, 1, (@spellpower*50)+10000;
+ @summon[0] = @summon[0] + 1;
+ if (@summon[0] < @summon[1]) goto S_SummonAll;
+ return;
+
+OnInit:
+ .school = SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "modriyikam"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 1;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level1-grow-mauve.txt b/npc/magic/level1-grow-mauve.txt
new file mode 100755
index 00000000..3a12be2d
--- /dev/null
+++ b/npc/magic/level1-grow-mauve.txt
@@ -0,0 +1,37 @@
+- script grow-mauve NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 4) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (countitem("MauveHerb") < 1 || countitem("Root") < 1) end;
+ delitem "MauveHerb", 1;
+ delitem "Root", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 2000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 4;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ setarray @summon[0], 0, (getskilllv(.school)/2)+1;
+ callfunc "magic_exp";
+ addtimer 4000-(@spellpower-9), strnpcinfo(0)+"::OnSummon";
+ end;
+
+OnSummon:
+ misceffect FX_PENTAGRAM_BURST, strcharinfo(0);
+ callsub S_SummonAll;
+ end;
+
+S_SummonAll:
+ summon getmapname(), rand(POS_X-2,POS_X+2), rand(POS_Y-2,POS_Y+2), BL_ID, 1029, 1, (@spellpower*50)+10000;
+ @summon[0] = @summon[0] + 1;
+ if (@summon[0] < @summon[1]) goto S_SummonAll;
+ return;
+
+OnInit:
+ .school = SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "modrilax"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 1;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level1-lesser-heal.txt b/npc/magic/level1-lesser-heal.txt
new file mode 100755
index 00000000..27311157
--- /dev/null
+++ b/npc/magic/level1-lesser-heal.txt
@@ -0,0 +1,50 @@
+- script lesser-heal NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 6) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ @target_id = getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id) == 1)
+ set @target_id, BL_ID; // fallback to self
+ if (@args$ == "Mouboo" || @args$ == "mouboo") set @target_id, getnpcid("Mouboo");
+ .@range = (((MATK1 + getskilllv(SKILL_MAGIC) + getskilllv(.school) + 10) / 100) + 2);
+ if (distance(BL_ID, @target_id) >= .@range) end;
+ if (PVP_CHANNEL != get(PVP_CHANNEL, @target_id) && get(PVP_CHANNEL, @target_id) != 0) end;
+ if (countitem("Lifestone") < 1) end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 500, "Magic Timer::OnClear"; // set the new debuff
+ delitem "Lifestone", 1;
+ callfunc "adjust_spellpower";
+ Sp = Sp - 6;
+ misceffect FX_MAGIC_WHITE, strcharinfo(0);
+ callfunc "magic_exp";
+ if (@args$ == "Mouboo" || @args$ == "mouboo") goto L_Mouboo;
+ if (@target_id != BL_ID) goto L_NotMe;
+ goto L_Continue;
+
+L_NotMe:
+ misceffect FX_MAGIC_WHITE, @target_id;
+ void call("gain_heal_xp", min(200, (get(MaxHp, @target_id) - get(Hp, @target_id))), 1, 2, 2);
+ goto L_Continue;
+
+L_Continue:
+ if (getskilllv(SKILL_MAGIC_DARK) >= 1) sc_start SC_HALT_REGENERATE, 2000, 0;
+ if (get(Hp, @target_id) < 1) end;
+ addtimer 0, strnpcinfo(0) + "::OnSlowHeal", @target_id;
+ end;
+
+OnSlowHeal:
+ heal 200, 0, 1;
+ end;
+
+L_Mouboo:
+ mes "Mouboo : ##3##BYour spell seems to have no effect on the mouboo.";
+ close;
+
+OnInit:
+ .school = SKILL_MAGIC_LIFE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "lum"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 1;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level1-magic-blade.txt b/npc/magic/level1-magic-blade.txt
new file mode 100755
index 00000000..ab73cdc2
--- /dev/null
+++ b/npc/magic/level1-magic-blade.txt
@@ -0,0 +1,54 @@
+- script magic-blade NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 9) end;
+ .@level = getskilllv(.school);
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (.@level <= 2 && countitem("SharpKnife") >= 1) set .@component$, "SharpKnife";
+ elif (.@level <= 2 && countitem("Knife") >= 1) set .@component$, "Knife";
+ elif (.@level <= 2) end;
+ if (.@component$ != "") delitem .@component$, 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 500, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 9;
+ misceffect FX_MAGIC_BLACK, strcharinfo(0);
+ setarray @chizaspell[0],
+ if_then_else(.@component$ == "Knife", 40, 60), // dmg
+ Str, // do not allow to equip light armor, cast, and then switch to heavy armor to get bonus str
+ (@spellpower/15) + 10, // charges
+ (((200 - Agi) * 1200) / 200), // delay
+ @spellpower;
+
+ callfunc "magic_exp";
+ goto L_FreeRecast;
+
+OnDischarge:
+ if (@chizaspell[2] < 1) end;
+ @chizaspell[2] = 0;
+ misceffect FX_FIRE_BURST, strcharinfo(0);
+ overrideattack;
+ end;
+
+OnAttack:
+ if (target(BL_ID, @target_id, 22) != 22) goto L_FreeRecast; // 0x10 | 0x02 | 0x04
+ void call("melee_damage", @chizaspell[4], @target_id, (@chizaspell[0] + rand(@chizaspell[1] + 5)));
+ @chizaspell[2] = @chizaspell[2] - 1;
+ goto L_FreeRecast;
+
+L_FreeRecast:
+ if (@chizaspell[2] > 0)
+ addtimer 0, strnpcinfo(0) + "::OnSetRecast";
+ end;
+
+OnSetRecast:
+ overrideattack @chizaspell[3], 1, ATTACK_ICON_GENERIC, 30, strnpcinfo(0)+"::OnAttack";
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_WAR;
+ set .invocation$, chr(MAGIC_SYMBOL) + "chiza"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 1;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level1-make-sulphur.txt b/npc/magic/level1-make-sulphur.txt
new file mode 100755
index 00000000..f26a06b9
--- /dev/null
+++ b/npc/magic/level1-make-sulphur.txt
@@ -0,0 +1,24 @@
+- script make-sulphur NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 4) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (countitem("PileOfAsh") >= 1) delitem "PileOfAsh", 1; else end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 4000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 4;
+ misceffect FX_MAGIC_RED, strcharinfo(0);
+ setarray @create_params[0], (@spellpower/100)+1+(rand(max(1,(800-@spellpower)))/180), 50;
+ setarray @create_items$[0], "SulphurPowder", "PileOfAsh";
+ callfunc "magic_create_item";
+ callfunc "magic_exp";
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_TRANSMUTE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "gole"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 1;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level1-sense-spouse.txt b/npc/magic/level1-sense-spouse.txt
new file mode 100755
index 00000000..0ef1848d
--- /dev/null
+++ b/npc/magic/level1-sense-spouse.txt
@@ -0,0 +1,24 @@
+- script sense-spouse NPC32767,{
+ .@m = getpartnerid();
+ if (.@m < 1)
+ goto L_NotMarried;
+ if (isloggedin(.@m) < 1)
+ goto L_NotOnline;
+ if (sc_check(SC_HIDE, .@m) || getpvpflag(1, .@m) || get(INVISIBLE, .@m))
+ goto L_NotOnline;
+ message strcharinfo(0), "Spouse : Your spouse is... somewhere.";
+ end;
+
+L_NotOnline:
+ message strcharinfo(0), "Spouse : Your spouse is not online, or maybe just hiding from you.";
+ end;
+
+L_NotMarried:
+ message strcharinfo(0), "Spouse : You are not married, or no longer married (sorry for being the one telling you the bad news).";
+ end;
+
+OnInit:
+ set .invocation$, chr(MAGIC_SYMBOL) + "inzuwilt"; // used in npcs that refer to this spell
+ registercmd .invocation$, strnpcinfo(0);
+ end;
+}
diff --git a/npc/magic/level1-summon-maggots.txt b/npc/magic/level1-summon-maggots.txt
new file mode 100755
index 00000000..22b6b2f6
--- /dev/null
+++ b/npc/magic/level1-summon-maggots.txt
@@ -0,0 +1,55 @@
+- script summon-maggots NPC32767,{
+ end;
+
+OnCast:
+ if(call("magic_checks")) end;
+ if (Sp < 21) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (countitem("MaggotSlime") < 1 || countitem("Root") < 1) end;
+ delitem "MaggotSlime", 1;
+ delitem "Root", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 20000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 21;
+ misceffect FX_MAGIC_BLUE, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ callfunc "magic_exp";
+ .@puppet$ = "#"+strnpcinfo(0)+"#"+BL_ID;
+ .@puppet = puppet(getmapname(), POS_X, POS_Y, .@puppet$, 127);
+ if (.@puppet < 1) end;
+ .count = ((sqrt(@spellpower)+(@spellpower/15))/5)+1, .@puppet;
+ .master = BL_ID, .@puppet;
+ .lifetime = (@spellpower*50)+10000, .@puppet;
+ addnpctimer 5000-(@spellpower*5), .@puppet$+"::OnSummon";
+ addnpctimer 6000, .@puppet$+"::OnDestroy";
+ end;
+
+OnSummon:
+ if(get(Hp, .master) < 1) destroy; // destroy if master is missing
+ if(getmap(.master) != strnpcinfo(3)) destroy; // destroy if master left the map
+ specialeffect FX_PENTAGRAM_BURST;
+ .@i = 0;
+ .@x = getnpcx();
+ .@y = getnpcy();
+ .@map$ = strnpcinfo(3);
+ callsub S_SummonAll;
+ end;
+
+OnDestroy:
+ destroy;
+
+S_SummonAll:
+ summon .@map$, rand(.@x-2,.@x+2), rand(.@y-2,.@y+2), .master, 1002, 2, .lifetime;
+ .@i = .@i + 1;
+ if (.@i < .count) goto S_SummonAll;
+ destroy;
+
+OnInit:
+ .school = SKILL_MAGIC_ASTRAL;
+ set .invocation$, chr(MAGIC_SYMBOL) + "kalmurk"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ .level = 1;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level1-transmute-wood.txt b/npc/magic/level1-transmute-wood.txt
new file mode 100755
index 00000000..8645b208
--- /dev/null
+++ b/npc/magic/level1-transmute-wood.txt
@@ -0,0 +1,36 @@
+- script spell-transmute-wood NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 5) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (countitem("RawLog") >= 1) delitem "RawLog", 1; else end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 4000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 5;
+ misceffect FX_MAGIC_RED, strcharinfo(0);
+ if (@args$ == "boo") goto L_Mouboo;
+ elif (@args$ == "lurk") goto L_Skytlurk;
+ else message strcharinfo(0), "Magic : ##3##BYou do not know how to transmute wood into this kind of animal."; // FIXME: write a better sentence
+ end;
+
+L_Mouboo:
+ setarray @create_params[0], 1, 40;
+ setarray @create_items$[0], "MoubooFigurine", "WarpedLog";
+ callfunc "magic_create_item";
+ callfunc "magic_exp";
+ end;
+
+L_Skytlurk:
+ if (rand(2) == 1) getitem "Iten", 1;
+ else getitem "WarpedLog", 1;
+ message strcharinfo(0), "Magic : ##3##BYou have no idea what a Skrytlurk looks like.";
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_TRANSMUTE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "parum"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 1;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level2-arrow-hail.txt b/npc/magic/level2-arrow-hail.txt
new file mode 100755
index 00000000..3d7525b1
--- /dev/null
+++ b/npc/magic/level2-arrow-hail.txt
@@ -0,0 +1,115 @@
+- script arrow-hail NPC32767,{
+ // we can not start here because for the puppets this is OnClick
+ end;
+
+OnCast:
+ if(call("magic_checks")) end;
+ if (getskilllv(.school) < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (Sp < 25) end;
+ explode .@map_ext[0], getmapname(), "-";
+ if (.@map_ext[1] != 1) end; // XXX this is fugly, in the future let's use MF_OUTSIDE to detect if a map is "outside" or "inside"
+ if (getmapflag(getmapname(), MF_TOWN)) end;
+ if (countitem("Arrow") >= 20 && countitem("SulphurPowder") >= 1) delitem "Arrow", 20;
+ elif (countitem("IronArrow") >= 20 && countitem("SulphurPowder") >= 1) delitem "IronArrow", 20;
+ else end;
+ delitem "SulphurPowder", 1;
+ Sp = Sp - 25;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 5000, "Magic Timer::OnClear"; // set the new debuff
+
+ setarray @away[0], POS_X, POS_Y, getdir(), (.range + 1), 0;
+ callsub S_AwayFrom;
+
+ @nearby = 0;
+ foreach 1, getmapname(), @away[0] - 14, @away[1] - 14, @away[0] + 14, @away[1] + 14,
+ strnpcinfo(0) + "::OnNearbyNpc";
+ if (@nearby) goto L_Absorb;
+
+ callfunc "adjust_spellpower";
+ set @new_npc_name$, "#" + strnpcinfo(0) + "#" + getcharid(3); // make a unique puppet name for every player
+ callfunc "magic_exp";
+ misceffect FX_MAGIC_BLACK, strcharinfo(0);
+ set @spell_npc, puppet(getmapname(), POS_X, POS_Y, @new_npc_name$, 127); // clone npc => get puppet id
+ if (@spell_npc < 1) end;
+ set .max_hit, (@spellpower / 8), @spell_npc; // set .max_hit in the puppet
+ set .caster, getcharid(3), @spell_npc; // tell the puppet who controls it
+ .damage = 125, @spell_npc;
+ .damage_bonus = (@spellpower / 5), @spell_npc;
+ set .area_x, @away[0], @spell_npc; set .area_y, @away[1], @spell_npc;
+ donpcevent @new_npc_name$+"::OnLaunch"; // start the puppet timer and strike
+ initnpctimer @new_npc_name$; // start the destroy timer
+ end;
+
+S_AwayFrom:
+ if(@away[2] == 6 && !(iscollision(getmapname(), (@away[0] + 1), @away[1]))) // right
+ @away[0] = @away[0] + 1;
+ if(@away[2] == 4 && !(iscollision(getmapname(), @away[0], (@away[1] - 1)))) // up
+ @away[1] = @away[1] - 1;
+ if(@away[2] == 2 && !(iscollision(getmapname(), (@away[0] - 1), @away[1]))) // left
+ @away[0] = @away[0] - 1;
+ if(@away[2] == 0 && !(iscollision(getmapname(), @away[0], (@away[1] + 1)))) // down
+ @away[1] = @away[1] + 1;
+ @away[4] = @away[4] + 1;
+ if(@away[4] < @away[3]) goto S_AwayFrom;
+ return;
+
+L_Absorb:
+ message strcharinfo(0), "##3Arrow Hail : ##BA nearby arrow hail absorbs your magic!";
+ end;
+
+OnNearbyNpc:
+ explode .@nearby$[0], strnpcinfo(0,@target_id), "#";
+ if(.@nearby$[0] == "arrow-hail" || .@nearby$[1] == "arrow-hail")
+ @nearby = @nearby + 1;
+ end;
+
+OnLaunch:
+ if(get(Hp, .caster) < 1) destroy; // destroy if caster is missing
+ if(getmap(.caster) != strnpcinfo(3)) destroy; // destroy if caster left the map
+ .hit = .hit + 1;
+ if(.hit > .max_hit) destroy;
+ .launch = 0;
+ callsub S_Launch;
+ addnpctimer 250 + rand(50) + rand(50), strnpcinfo(0)+"::OnLaunch"; // loop until max
+ end;
+
+S_Launch:
+ npcareawarp .area_x - 6, .area_y - 6, .area_x + 6, .area_y + 6, 0, strnpcinfo(0);
+ misceffect FX_ARROW_HAIL;
+ .done = 0;
+ foreach 2, strnpcinfo(3), getnpcx(), getnpcy(), getnpcx(), getnpcy(), strnpcinfo(0) + "::OnHit", .caster;
+ if (get(PVP_CHANNEL, .caster) || getmapflag(getmap(.caster), MF_PVP))
+ foreach 0, strnpcinfo(3), getnpcx(), getnpcy(), getnpcx(), getnpcy(), strnpcinfo(0) + "::OnHit", .caster;
+ if(!.done && get(POS_X, .caster) == getnpcx() && get(POS_Y, .caster) == getnpcy())
+ set Hp, get(Hp, .caster) - (.damage + rand(.damage_bonus) + rand(.damage_bonus)), .caster; // injure caster
+ .launch = .launch + 1;
+ if(.launch < 3) goto S_Launch;
+ return;
+
+OnTimer30000:
+ debugmes "frillyar timeout! [this shouldn't happen]";
+ destroy;
+
+OnHit:
+ if(get(Hp, .caster) < 1) destroy; // destroy if caster is missing
+ if(getmap(.caster) != strnpcinfo(3)) destroy; // destroy if caster left the map
+
+ if(target(.caster, @target_id, 16) != 16 && .caster != @target_id) end;
+ if((get(BL_TYPE, @target_id) & 1) == 0) end; // either mob or pc
+ .@damage = .damage + rand(.damage_bonus) + rand(.damage_bonus);
+ if(.caster != @target_id)
+ .@damage = (.@damage * (100 - get(MDEF1, @target_id))) / 100;
+ injure .caster, @target_id, .@damage;
+ .done = 1;
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_WAR;
+ .range = 7;
+ set .invocation$, chr(MAGIC_SYMBOL) + "frillyar"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ .level = 2;
+ .exp_gain = 2;
+ end;
+}
diff --git a/npc/magic/level2-barrier.txt b/npc/magic/level2-barrier.txt
new file mode 100755
index 00000000..aa92344a
--- /dev/null
+++ b/npc/magic/level2-barrier.txt
@@ -0,0 +1,47 @@
+- script magic barrier NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 15) end;
+ .@level = getskilllv(.school);
+ if (.@level < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (.@level <= 3 && countitem("SmallMushroom") >= 1) delitem "SmallMushroom", 1;
+ elif (.@level <= 3) end;
+ @target_id = getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id) == 1)
+ set @target_id, BL_ID; // fallback to self
+
+ if (getequipid(equip_head, strcharinfo(0, @target_id)) == 888) end;
+
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 1000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 15;
+ misceffect FX_MAGIC_BLUE, strcharinfo(0);
+ callfunc "magic_exp";
+
+ if (distance(BL_ID, @target_id) >= (@spellpower/30)+2) set @target_id, BL_ID;
+ if (BL_ID == @target_id) set @args$, strcharinfo(0);
+ if (BL_ID != @target_id) misceffect FX_MAGIC_DEFAULT, @args$;
+ .@time = (@spellpower*200)+2000;
+ @asorm_time = .@time, @target_id;
+ sc_start SC_MBARRIER, .@time, max(30,(@spellpower/8))+20, @target_id;
+ message @args$, "Barrier : You are surrounded by a magical barrier.";
+ @asorm_future = gettimetick(0) + @asorm_time - 100, @target_id;
+ addtimer @asorm_time - 100, strnpcinfo(0)+"::OnEnd", @target_id;
+ end;
+
+OnEnd:
+ if (gettimetick(0) - @asorm_future < 0) end;
+ if (sc_check(SC_MBARRIER) != 1) end;
+ message strcharinfo(0), "Barrier : Your magical barrier dissipates.";
+ misceffect FX_MAGIC_DEFAULT, strcharinfo(0);
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_ASTRAL;
+ set .invocation$, chr(MAGIC_SYMBOL) + "asorm"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 3;
+ end;
+}
diff --git a/npc/magic/level2-detect-players.txt b/npc/magic/level2-detect-players.txt
new file mode 100755
index 00000000..9f05d567
--- /dev/null
+++ b/npc/magic/level2-detect-players.txt
@@ -0,0 +1,33 @@
+- script detect-players NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 7) end;
+ if (getskilllv(.school) < .level) end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 300, "Magic Timer::OnClear";
+ callfunc "adjust_spellpower";
+ Sp = Sp - 7;
+ misceffect FX_MAGIC_GENERIC, strcharinfo(0);
+ callfunc "magic_exp";
+ @inwilt$ = "";
+ .@d = @spellpower/2;
+ foreach 0, getmapname(), POS_X - .@d, POS_Y - .@d, POS_X + .@d, POS_Y + .@d, strnpcinfo(0)+"::OnPC";
+ message strcharinfo(0), if_then_else(@inwilt$=="", "You sense no-one else nearby.", "You sense the following: "+@inwilt$);
+ end;
+
+OnPC:
+ if (@target_id == BL_ID) end; // do not count the caster
+ if (sc_check(SC_HIDE, @target_id)) end; // do not count players with anwiltyp
+ if (getpvpflag(1, @target_id)) end; // do not count hidden GMs
+ if (get(INVISIBLE, @target_id) == 1) end; // do not count invisible GMs
+ if (@inwilt$ != "") set @inwilt$, @inwilt$ + ", ";
+ @inwilt$ = @inwilt$ + strcharinfo(0, @target_id) + if_then_else(@spellpower > 99, "("+get(BaseLevel, @target_id)+")", "");
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "inwilt"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 0;
+ end;
+}
diff --git a/npc/magic/level2-enchant-lifestone.txt b/npc/magic/level2-enchant-lifestone.txt
new file mode 100755
index 00000000..06fba65d
--- /dev/null
+++ b/npc/magic/level2-enchant-lifestone.txt
@@ -0,0 +1,35 @@
+- script enchant-lifestone NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 15) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("BugLeg") >= 1) delitem "BugLeg", 1;
+ elif (countitem("MaggotSlime") >= 1) delitem "MaggotSlime", 1;
+ elif (countitem("MauveHerb") >= 1 && countitem("AlizarinHerb") >= 1 && countitem("CobaltHerb") >= 1 && countitem("GambogeHerb") >= 1) goto L_Herbs;
+ else end;
+ goto L_Proceed;
+
+L_Herbs:
+ delitem "MauveHerb", 1;
+ delitem "AlizarinHerb", 1;
+ delitem "CobaltHerb", 1;
+ delitem "GambogeHerb", 1;
+ goto L_Proceed;
+
+L_Proceed:
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 4000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 15;
+ misceffect FX_MAGIC_GENERIC, strcharinfo(0);
+ getitem "Lifestone", 1;
+ callfunc "magic_exp";
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "manpahil"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level2-flying-backpack.txt b/npc/magic/level2-flying-backpack.txt
new file mode 100755
index 00000000..7fbf97d6
--- /dev/null
+++ b/npc/magic/level2-flying-backpack.txt
@@ -0,0 +1,42 @@
+- script flying-backpack NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 12) end;
+ .@level = getskilllv(.school);
+ if (.@level < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (.@level <= 3 && countitem("SilkCocoon") >= 1) delitem "SilkCocoon", 1;
+ elif (.@level <= 3) end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 1000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 12;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ callfunc "magic_exp";
+ @target_id = getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id) == 1)
+ set @target_id, BL_ID; // fallback to self
+ if (distance(BL_ID, @target_id) >= (@spellpower/30)+2) set @target_id, BL_ID;
+ if (BL_ID != @target_id) misceffect FX_MAGIC_GENERIC, @args$;
+ if (BL_ID == @target_id) set @args$, strcharinfo(0);
+ @plugh_time = (@spellpower*500)+5000, @target_id;
+ sc_start SC_FLYING_BACKPACK, @plugh_time, 0, @target_id;
+ message @args$, "Backpack : Your backpack is lifted by a mystical force; you no longer feel it pressing on your back.";
+ @plugh_future = gettimetick(0) + @plugh_time - 100, @target_id;
+ addtimer @plugh_time - 100, strnpcinfo(0)+"::OnEnd", @target_id;
+ end;
+
+OnEnd:
+ if (gettimetick(0) - @plugh_future < 0) end;
+ if (sc_check(SC_FLYING_BACKPACK) != 1) end;
+ message strcharinfo(0), "Backpack : Your backpack is no longer levitating.";
+ misceffect FX_MAGIC_GENERIC, strcharinfo(0);
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "plugh"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level2-happy-curse.txt b/npc/magic/level2-happy-curse.txt
new file mode 100755
index 00000000..d6287bb5
--- /dev/null
+++ b/npc/magic/level2-happy-curse.txt
@@ -0,0 +1,42 @@
+- script happy-curse NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 13) end;
+ .@level = getskilllv(.school);
+ if (.@level < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (.@level <= 3 && countitem("GingerBreadMan") >= 1) delitem "GingerBreadMan", 1;
+ elif (.@level <= 3) end;
+ @target_id = getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id))
+ set @target_id, BL_ID; // fallback to self
+
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 1000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 13;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ callfunc "magic_exp";
+
+ if (distance(BL_ID, @target_id) >= (@spellpower/100)+1) set @target_id, BL_ID;
+ if (BL_ID == @target_id) set @args$, strcharinfo(0);
+ @joyplim_count = 1, @target_id;
+ @joyplim_emote = if_then_else(getskilllv(SKILL_MAGIC_DARK) > 1, EMOTE_EVIL, EMOTE_HAPPY), @target_id;
+ @joyplim_total = (@spellpower/10), @target_id;
+ emotion @joyplim_emote, strcharinfo(0, @target_id);
+ addtimer 500, strnpcinfo(0)+"::OnEmote", @target_id;
+ end;
+
+OnEmote:
+ emotion @joyplim_emote, "self";
+ @joyplim_count = @joyplim_count + 1;
+ if (@joyplim_count < @joyplim_total) addtimer 500, strnpcinfo(0)+"::OnEmote";
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "joyplim"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level2-hide.txt b/npc/magic/level2-hide.txt
new file mode 100755
index 00000000..2a7e8dab
--- /dev/null
+++ b/npc/magic/level2-hide.txt
@@ -0,0 +1,46 @@
+- script spell-hide NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 11) end;
+ .@level = getskilllv(.school);
+ if (.@level < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (.@level <= 3 && countitem("CottonCloth") >= 1) delitem "CottonCloth", 1;
+ elif (.@level <= 3) end;
+ @target_id = getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id))
+ set @target_id, BL_ID; // fallback to self
+
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 1000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 11;
+ misceffect FX_MAGIC_BLUE, strcharinfo(0);
+ callfunc "magic_exp";
+
+ if (distance(BL_ID, @target_id) >= (@spellpower/30)+2) set @target_id, BL_ID;
+ if (BL_ID == @target_id) set @args$, strcharinfo(0);
+ if (BL_ID != @target_id) misceffect FX_MAGIC_DEFAULT, @args$;
+ .@time = (@spellpower*2500)+5000;
+ @anwiltyp_time = .@time, @target_id;
+ sc_start SC_HIDE, .@time, 0, @target_id;
+ message @args$, "Magic : You are hidden!";
+ if (BL_ID != @target_id) message strcharinfo(0), "Magic : You hid someone!";
+ @anwiltyp_future = gettimetick(0) + @anwiltyp_time - 100, @target_id;
+ addtimer @anwiltyp_time, strnpcinfo(0)+"::OnEnd", @target_id;
+ end;
+
+OnEnd:
+ if (gettimetick(0) - @anwiltyp_future < 0) end;
+ if (sc_check(SC_HIDE) != 1) end;
+ message strcharinfo(0), "Magic : You are no longer hidden.";
+ misceffect FX_MAGIC_GENERIC, strcharinfo(0);
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_ASTRAL;
+ set .invocation$, chr(MAGIC_SYMBOL) + "anwiltyp"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 2;
+ end;
+}
diff --git a/npc/magic/level2-lay-on-hands.txt b/npc/magic/level2-lay-on-hands.txt
new file mode 100755
index 00000000..529f9356
--- /dev/null
+++ b/npc/magic/level2-lay-on-hands.txt
@@ -0,0 +1,58 @@
+- script lay-on-hands NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 10) end;
+ if (getskilllv(.school) < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (@args$ == "Mouboo" || @args$ == "mouboo") goto L_Mouboo;
+ @target_id = getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id) || BL_ID == @target_id) end;
+ if (Hp <= get(MaxHp, @target_id) / 20) end; // hp needs to be > 1/20 * target hp
+ callfunc "adjust_spellpower";
+ if (distance(BL_ID, @target_id) >= (((sqrt(@spellpower)*12)+@spellpower)/100)+2) end;
+ if (sc_check(SC_HALT_REGENERATE,@target_id)) end;
+ if (getequipid(equip_head, @args$) == 888) end; // magic gm top hat
+ @needed = get(MaxHp, @target_id) - get(Hp, @target_id);
+ goto L_Pay;
+
+L_Pay:
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 500, "Magic Timer::OnClear"; // XXX should this be 0 ?
+ Sp = Sp - 10;
+ misceffect FX_MAGIC_WHITE, strcharinfo(0); // on caster
+ misceffect FX_MAGIC_WHITE, @args$; // on target
+
+ set .@fraction, max(80, 200 - (Vit + (@spellpower/10))); // pay at least 40%
+ .@payment = (@needed * .@fraction) / 200;
+ .@available = Hp - (MaxHp / 20);
+ set @heal_value, if_then_else(.@payment < .@available, @needed+1-1, (.@available * 200) / .@fraction); // FIXME / XXX why the f do I need to do +1-1 ?
+ if (.@payment > .@available) set .@payment, .@available;
+
+
+ @mexp = min(.exp_gain, .@payment/100);
+ void call("gain_heal_xp", @heal_value, 1, 1, 3);
+ callfunc "magic_exp";
+
+ set .@dark, getskilllv(SKILL_MAGIC_DARK) >= 2; // true if dark magic user
+ .@bad = (MaxHp/20)*(0-1);
+ if (.@dark) heal .@bad, 0;
+ sc_start SC_HALT_REGENERATE, if_then_else(.@dark, 5000, 10000), 0;
+
+ .@thp = get(Hp, @target_id);
+ if (.@thp < 1) end;
+ Hp = .@thp + @heal_value, @target_id;
+ end;
+
+L_Mouboo:
+ @spell = 1;
+ callfunc "QuestMoubooHeal";
+ @needed = 1000;
+ goto L_Pay;
+
+OnInit:
+ .school = SKILL_MAGIC_LIFE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "inma"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ set .exp_gain, 1; // this is MAX possible exp
+ end;
+}
diff --git a/npc/magic/level2-lightning-strike.txt b/npc/magic/level2-lightning-strike.txt
new file mode 100755
index 00000000..44969452
--- /dev/null
+++ b/npc/magic/level2-lightning-strike.txt
@@ -0,0 +1,86 @@
+- script lightning-strike NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 20) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ .@level = getskilllv(.school);
+ if (.@level < .level) end;
+ if (.@level <= 3 && countitem("IronPowder") >= 1) delitem "IronPowder", 1;
+ elif (.@level <= 3) end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 1000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 20;
+ misceffect FX_MAGIC_BLACK, strcharinfo(0);
+ setarray @ingravspell[0],
+ @spellpower,
+ Luk,
+ ((@spellpower/90)+1), // charges
+ (((200 - Agi) * 3000) / 200), // delay
+ 0, // in_rain
+ 0; // target id (tmp)
+
+ callfunc "magic_exp";
+ goto L_FreeRecast;
+
+OnAttack:
+ if (target(BL_ID, @target_id, 0x36) != 0x36) goto L_FreeRecast; // 0x10 | 0x02 | 0x04 | 0x20
+
+ .@p = get(.max_radius, "rain") + 1;
+ set @ingravspell[5], @target_id; // store it because foreach overwrites it
+ foreach 1, getmapname(), POS_X-.@p, POS_Y-.@p, POS_X+.@p, POS_Y+.@p, strnpcinfo(0)+"::OnNpc";
+ set @target_id, @ingravspell[5]; // now restore it
+
+ @ingravspell[2] = @ingravspell[2] - 1;
+ if (@ingravspell[4] & 1) goto L_InRain;
+ void call("elt_damage", @ingravspell[0], (@ingravspell[0]/2)+1, ELT_EARTH, ELT_WIND, FX_LIGHTNING1 + rand(3));
+ goto L_FreeRecast;
+
+L_FreeRecast:
+ if (@ingravspell[2] > 0)
+ addtimer 0, strnpcinfo(0) + "::OnSetRecast";
+ end;
+
+OnDischarge:
+ if (@ingravspell[2] < 1) end;
+ @ingravspell[2] = 0;
+ misceffect FX_FIRE_BURST, strcharinfo(0);
+ overrideattack;
+ end;
+
+OnSetRecast:
+ overrideattack @ingravspell[3], 8, ATTACK_ICON_GENERIC, 31, strnpcinfo(0)+"::OnAttack";
+ end;
+
+OnNpc:
+ .@name$ = strnpcinfo(0,@target_id);
+ explode .@nearby$[0], .@name$, "#";
+ if (.@nearby$[0] != "rain" && .@nearby$[1] != "rain") end;
+ setarray .@l[0], getnpcx(.@name$), getnpcy(.@name$), get(.radius, @target_id); // kaflosh x, y, radius
+ setarray @ingravspell[6], .@l[0]-.@l[2], .@l[1]-.@l[2], .@l[0]+.@l[2], .@l[1]+.@l[2]; // kaflosh x1, y1, x2, y2 <= this is "area"
+ if (POS_X >= @ingravspell[6] && POS_Y >= @ingravspell[7] && POS_X <= @ingravspell[8] && POS_Y <= @ingravspell[9])
+ @ingravspell[4] = @ingravspell[4] | 1;
+ end;
+
+L_InRain:
+ @ingravspell[10] = 0;
+ foreach 0, getmapname(), @ingravspell[6], @ingravspell[7], @ingravspell[8], @ingravspell[9], strnpcinfo(0)+"::OnEntityInRain";
+ if (@ingravspell[10] >= 1 && (@ingravspell[1] + rand(200)) >= 150) goto L_FreeRecast;
+ misceffect FX_LIGHTNING1 + rand(3), strcharinfo(0);
+ heal 0 - @ingravspell[0], 0;
+ goto L_FreeRecast;
+
+OnEntityInRain:
+ if (target(BL_ID, @target_id, 16) != 16) end; // 0x10
+ if (@ingravspell[1] + rand(200) <= 175) end;
+ @ingravspell[10] = @ingravspell[10] + 1;
+ void call("elt_damage", @ingravspell[0]/6, (((@ingravspell[0]/2)+1)/3)+1, ELT_EARTH, ELT_WIND, FX_LIGHTNING1 + rand(3));
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_WAR;
+ set .invocation$, chr(MAGIC_SYMBOL) + "ingrav"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 2;
+ end;
+}
diff --git a/npc/magic/level2-magic-knuckles.txt b/npc/magic/level2-magic-knuckles.txt
new file mode 100755
index 00000000..87f0ae90
--- /dev/null
+++ b/npc/magic/level2-magic-knuckles.txt
@@ -0,0 +1,51 @@
+- script magic-knuckles NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 20) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ .@level = getskilllv(.school);
+ if (.@level < .level) end;
+ if (.@level <= 3 && countitem("Beer") >= 1) delitem "Beer", 1;
+ elif (.@level <= 3) end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 500, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 20;
+ misceffect FX_MAGIC_BLACK, strcharinfo(0);
+ setarray @upmarmuspell[0],
+ @spellpower,
+ ((@spellpower/10) + 10), // charges
+ (((200 - Agi) * 1300) / 200), // delay
+ Str; // do not allow to equip light armor, cast, and then switch to heavy armor to get bonus str
+ callfunc "magic_exp";
+ goto L_FreeRecast;
+
+OnAttack:
+ if (target(BL_ID, @target_id, 22) != 22) goto L_FreeRecast; // 0x10 | 0x02 | 0x04
+ void call("melee_damage", @upmarmuspell[0], @target_id, (30 + rand((@upmarmuspell[3]*2) + 5)));
+ @upmarmuspell[1] = @upmarmuspell[1] - 1;
+ goto L_FreeRecast;
+
+L_FreeRecast:
+ if (@upmarmuspell[1] > 0)
+ addtimer 0, strnpcinfo(0) + "::OnSetRecast";
+ end;
+
+OnDischarge:
+ if (@upmarmuspell[1] < 1) end;
+ @upmarmuspell[1] = 0;
+ misceffect FX_FIRE_BURST, strcharinfo(0);
+ overrideattack;
+ end;
+
+OnSetRecast:
+ overrideattack @upmarmuspell[2], 1, ATTACK_ICON_GENERIC, 34, strnpcinfo(0)+"::OnAttack";
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_WAR;
+ set .invocation$, chr(MAGIC_SYMBOL) + "upmarmu"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level2-make-arrows.txt b/npc/magic/level2-make-arrows.txt
new file mode 100755
index 00000000..699af4d7
--- /dev/null
+++ b/npc/magic/level2-make-arrows.txt
@@ -0,0 +1,26 @@
+- script make-arrows NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 8) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("RawLog") < 1) end;
+ delitem "RawLog", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 5000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 8;
+ misceffect FX_MAGIC_RED, strcharinfo(0);
+ setarray @create_params[0], (@spellpower/40)+1+(rand(max(1,(800-@spellpower)))/80), 500;
+ setarray @create_items$[0], "Arrow", "WarpedLog";
+ callfunc "magic_create_item";
+ callfunc "magic_exp";
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_TRANSMUTE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "kularzufrill"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level2-make-iron-powder.txt b/npc/magic/level2-make-iron-powder.txt
new file mode 100755
index 00000000..8e781135
--- /dev/null
+++ b/npc/magic/level2-make-iron-powder.txt
@@ -0,0 +1,26 @@
+- script make-iron-powder NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 8) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("IronOre") < 1) end;
+ delitem "IronOre", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 5000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 8;
+ misceffect FX_MAGIC_RED, strcharinfo(0);
+ setarray @create_params[0], (@spellpower/140)+1+(rand(max(1,(900-@spellpower)))/220), 700;
+ setarray @create_items$[0], "IronPowder", "IronOre";
+ callfunc "magic_create_item";
+ callfunc "magic_exp";
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_TRANSMUTE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "zukminbirf"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 3;
+ end;
+}
diff --git a/npc/magic/level2-make-shirt.txt b/npc/magic/level2-make-shirt.txt
new file mode 100755
index 00000000..e379c71d
--- /dev/null
+++ b/npc/magic/level2-make-shirt.txt
@@ -0,0 +1,24 @@
+- script make-shirt NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 25) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("CottonCloth") >= 5) delitem "CottonCloth", 5; else end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 5000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 25;
+ misceffect FX_MAGIC_RED, strcharinfo(0);
+ setarray @create_params[0], 1, 425;
+ setarray @create_items$[0], "CottonShirt", "CottonCloth";
+ callfunc "magic_create_item";
+ callfunc "magic_exp";
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_TRANSMUTE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "patmuploo"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 2;
+ end;
+}
diff --git a/npc/magic/level2-make-short-tanktop.txt b/npc/magic/level2-make-short-tanktop.txt
new file mode 100755
index 00000000..a100fa97
--- /dev/null
+++ b/npc/magic/level2-make-short-tanktop.txt
@@ -0,0 +1,24 @@
+- script make-short-tanktop NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 25) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("CottonCloth") >= 3) delitem "CottonCloth", 3; else end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 5000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 25;
+ misceffect FX_MAGIC_RED, strcharinfo(0);
+ setarray @create_params[0], 1, 250;
+ setarray @create_items$[0], "ShortTankTop", "CottonCloth";
+ callfunc "magic_create_item";
+ callfunc "magic_exp";
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_TRANSMUTE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "patviloree"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 2;
+ end;
+}
diff --git a/npc/magic/level2-make-tanktop.txt b/npc/magic/level2-make-tanktop.txt
new file mode 100755
index 00000000..19f868e9
--- /dev/null
+++ b/npc/magic/level2-make-tanktop.txt
@@ -0,0 +1,24 @@
+- script make-tanktop NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 25) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("CottonCloth") >= 4) delitem "CottonCloth", 4; else end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 5000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 25;
+ misceffect FX_MAGIC_RED, strcharinfo(0);
+ setarray @create_params[0], 1, 350;
+ setarray @create_items$[0], "TankTop", "CottonCloth";
+ callfunc "magic_create_item";
+ callfunc "magic_exp";
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_TRANSMUTE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "patloree"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 2;
+ end;
+}
diff --git a/npc/magic/level2-protect.txt b/npc/magic/level2-protect.txt
new file mode 100755
index 00000000..8cdaf3ab
--- /dev/null
+++ b/npc/magic/level2-protect.txt
@@ -0,0 +1,48 @@
+- script protect NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 14) end;
+ .@level = getskilllv(.school);
+ if (.@level < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (.@level <= 3 && countitem("HardSpike") < 1) end;
+ @target_id = getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id))
+ set @target_id, BL_ID; // fallback to self
+
+ if (getequipid(equip_head, strcharinfo(0, @target_id)) == 888) end;
+
+ if (distance(BL_ID, @target_id) >= (@spellpower/30)+2) set @target_id, BL_ID;
+ if (get(@antiprotect, @target_id) > 0) end;
+ if (.@level <= 3) delitem "HardSpike", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 1500, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 14;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ callfunc "magic_exp";
+
+ if (BL_ID == @target_id) set @args$, strcharinfo(0);
+ misceffect FX_MAGIC_SHIELD, @args$;
+ .@time = (@spellpower*1000)+5000;
+ @betsanc_time = .@time, @target_id;
+ sc_start SC_PHYS_SHIELD, .@time, max(15,(@spellpower/20))+5, @target_id;
+ message @args$, "Shield : You feel more protected.";
+ @betsanc_future = gettimetick(0) + @betsanc_time - 100, @target_id;
+ addtimer @betsanc_time - 100, strnpcinfo(0)+"::OnEnd", @target_id;
+ end;
+
+OnEnd:
+ if (gettimetick(0) - @betsanc_future < 0) end;
+ if (sc_check(SC_PHYS_SHIELD) != 1) end;
+ message strcharinfo(0), "Shield : You feel less protected.";
+ misceffect FX_MAGIC_SHIELD_ENDS, strcharinfo(0);
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "betsanc"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 2;
+ end;
+}
diff --git a/npc/magic/level2-rain.txt b/npc/magic/level2-rain.txt
new file mode 100755
index 00000000..e95974e0
--- /dev/null
+++ b/npc/magic/level2-rain.txt
@@ -0,0 +1,104 @@
+- script rain NPC32767,{
+ // we can not start here because for the puppets this is OnClick
+ end;
+
+OnCast:
+ if(call("magic_checks")) end;
+ if (getskilllv(.school) < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (Sp < 17) end;
+ explode .@map_ext[0], getmapname(), "-";
+ if (.@map_ext[1] != 1) end; // XXX this is fugly, in the future let's use MF_OUTSIDE to detect if a map is "outside" or "inside"
+ if (getmapflag(getmapname(), MF_TOWN)) end;
+ if (getskilllv(.school) < 4 && countitem("BottleOfWater") >= 1) delitem "BottleOfWater", 1;
+ elif (getskilllv(.school) < 4) end;
+ Sp = Sp - 17;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 3000, "Magic Timer::OnClear"; // set the new debuff
+
+ callfunc "adjust_spellpower";
+ set @krad, min(.max_radius,(min(@spellpower,200)/30)+3); // kaflosh radius
+
+ @nearby = 0;
+ foreach 1, getmapname(), POS_X - .max_radius, POS_Y - .max_radius, POS_X + .max_radius, POS_Y + .max_radius,
+ strnpcinfo(0) + "::OnNearbyNpc";
+ if (@nearby) goto L_Absorb;
+
+ set @new_npc_name$, "#" + strnpcinfo(0) + "#" + getcharid(3); // make a unique puppet name for every player
+ callfunc "magic_exp";
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ set @spell_npc, puppet(getmapname(), POS_X, POS_Y, @new_npc_name$, 127); // clone npc => get puppet id
+ if (@spell_npc < 1) end;
+ set .caster, getcharid(3), @spell_npc; // tell the puppet who controls it
+ set .radius, @krad, @spell_npc; // this is also used by ingrav, don't rename
+ .initial_x = POS_X, @spell_npc;
+ .initial_y = POS_Y, @spell_npc;
+ .max = @spellpower/3, @spell_npc;
+ .max_launch = min(200,@spellpower/2)/100, @spell_npc;
+ donpcevent @new_npc_name$+"::OnLaunch"; // start
+ addnpctimer 30000, @new_npc_name$+"::OnDestroy"; // this is just a failsafe in case the npc is not properly destroyed
+ if(isin("011-1", 85, 31, 103, 45)) goto L_Pumpkins;
+ end;
+
+L_Absorb:
+ message strcharinfo(0), "##3Rain : ##BA nearby raincloud absorbs your magic.";
+ end;
+
+OnNearbyNpc:
+ explode .@nearby$[0], strnpcinfo(0,@target_id), "#";
+ if(.@nearby$[1] == "DruidTree0" || .@nearby$[1] == "DruidTree0") goto L_Tree;
+ if(.@nearby$[0] == "rain" || .@nearby$[1] == "rain")
+ @nearby = @nearby + 1;
+ end;
+
+L_Pumpkins:
+ callfunc "HalloweenQuestWaterPumpkins";
+ end;
+
+L_Tree:
+ set .@x, get(POS_X, @target_id); set .@y, get(POS_Y, @target_id);
+ if (.@x < POS_X-@krad || .@y < POS_Y-@krad || .@x > POS_X+@krad || .@y > POS_Y+@krad) end; // in max radius but not in puppet area
+ @flag = 1;
+ callfunc "QuestTreeTrigger";
+ close;
+
+OnLaunch:
+ if(get(Hp, .caster) < 1) destroy; // destroy if caster is missing
+ if(getmap(.caster) != strnpcinfo(3)) destroy; // destroy if caster left the map
+ .count = .count + 1;
+ if(.count > .max) destroy;
+ .launch = 0;
+ callsub S_Launch;
+ addnpctimer 400 + rand(100), strnpcinfo(0)+"::OnLaunch"; // loop until max
+ end;
+
+S_Launch:
+ npcareawarp .initial_x - .radius, .initial_y - .radius, .initial_x + .radius, .initial_y + .radius, 0, strnpcinfo(0);
+ misceffect FX_RAIN;
+ foreach 2, strnpcinfo(3), getnpcx()-1, getnpcy()-1, getnpcx()+1, getnpcy()+1, strnpcinfo(0) + "::OnHit", .caster;
+ .launch = .launch + 1;
+ if(.launch < .max_launch) goto S_Launch;
+ return;
+
+OnHit:
+ if(get(Hp, .caster) < 1) destroy; // destroy if caster is missing
+ if(getmap(.caster) != strnpcinfo(3)) destroy; // destroy if caster left the map
+ if(target(.caster, @target_id, 16) != 16 && .caster != @target_id) end;
+ if((get(BL_TYPE, @target_id) & 1) == 0) end; // either mob or pc
+ if(get(ELTTYPE, @target_id) == ELT_FIRE)
+ injure .caster, @target_id, ((rand((@spellpower/15)+5)+2) * (100 - get(MDEF1, @target_id))) / 100;
+ end;
+
+OnDestroy:
+ debugmes "kaflosh timeout! [this shouldn't happen]"; // XXX: looks like this CAN happen with higher levels of magic, so we might want to cap max charges
+ destroy;
+
+OnInit:
+ .school = SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "kaflosh"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ .level = 2;
+ .exp_gain = 1;
+ .max_radius = 15;
+ end;
+}
diff --git a/npc/magic/level2-shear.txt b/npc/magic/level2-shear.txt
new file mode 100755
index 00000000..79021013
--- /dev/null
+++ b/npc/magic/level2-shear.txt
@@ -0,0 +1,67 @@
+- script shear NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 23) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 1000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 23;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ setarray @chipchipspell[0],
+ @spellpower,
+ (((200 - Agi) * 2000) / 200); //delay
+ callfunc "magic_exp";
+ goto L_FreeRecast;
+
+OnAttack:
+ if (isloggedin(@target_id)) goto L_FreeRecast; // can not shear a player
+ if (sc_check(SC_SHEARED, @target_id)) goto L_FreeRecast; // mob already sheared
+ if (target(BL_ID, @target_id, 22) != 22) goto L_FreeRecast; // 0x10 | 0x02 | 0x04
+ sc_start SC_SHEARED, 600000, 0, @target_id;
+ .@score = rand(1000 - rand(@chipchipspell[0]));
+ set .@id, get(Class, @target_id); // get the mob ID
+ @chipchipspell[2] = 0;
+
+ if (.@id == 1020 && .@score < 300) set .@item$, "WhiteFur"; // Fluffy
+ elif (.@id == 1027 && .@score < 300) set .@item$, "WhiteFur"; // EasterFluffy
+ elif (.@id == 1019 && .@score < 250) set .@item$, "HardSpike"; // SpikyMushroom
+ elif (.@id == 1028 && .@score < 175) set .@item$, "CottonCloth"; // Mouboo
+ elif (.@id == 1029 && .@score < 700) set .@item$, "MauveHerb"; // MauvePlant
+ elif (.@id == 1030 && .@score < 700) set .@item$, "CobaltHerb"; // CobaltPlant
+ elif (.@id == 1031 && .@score < 700) set .@item$, "GambogeHerb"; // GambogePlant
+ elif (.@id == 1032 && .@score < 700) set .@item$, "AlizarinHerb"; // AlizarinPlant
+ elif (.@id == 1035 && .@score < 300) set .@item$, "SilkCocoon"; // SilkWorm
+ elif (.@id == 1018 && .@score < 180) set .@item$, "PinkAntenna"; // Pinkie
+ else end;
+ makeitem .@item$, 1, getmapname(), rand(POS_X - 1, POS_X + 1), rand(POS_Y - 1, POS_Y + 1);
+
+ if (.@id != 1020 && .@id != 1028 && .@id != 1018 && rand(2) != 1) end;
+ @value = 1;
+ callfunc "QuestSagathaHappy";
+ end;
+
+L_FreeRecast:
+ @chipchipspell[2] = 1;
+ addtimer 0, strnpcinfo(0) + "::OnSetRecast"; // we can't do it while already overridden, until it reaches a script terminator
+ end;
+
+OnDischarge:
+ if (@chipchipspell[2] < 1) end;
+ @chipchipspell[2] = 0;
+ misceffect FX_FIRE_BURST, strcharinfo(0);
+ overrideattack;
+ end;
+
+OnSetRecast:
+ overrideattack @chipchipspell[1], 1, ATTACK_ICON_SHEARING, 30, strnpcinfo(0)+"::OnAttack";
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "chipchip"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 0;
+ end;
+}
diff --git a/npc/magic/level2-summon-fluffies.txt b/npc/magic/level2-summon-fluffies.txt
new file mode 100755
index 00000000..1a2d5823
--- /dev/null
+++ b/npc/magic/level2-summon-fluffies.txt
@@ -0,0 +1,56 @@
+- script smfluffies NPC32767,{
+ end;
+
+OnCast:
+ if(call("magic_checks")) end;
+ if (Sp < 39) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("WhiteFur") < 1 || countitem("Root") < 1) end;
+ delitem "WhiteFur", 1;
+ delitem "Root", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 20000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 39;
+ misceffect FX_MAGIC_BLUE, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ callfunc "magic_exp";
+ .@puppet$ = "#"+strnpcinfo(0)+"#"+BL_ID;
+ .@puppet = puppet(getmapname(), POS_X, POS_Y, .@puppet$, 127);
+ if (.@puppet < 1) end;
+ .count = (@spellpower/170)+1+(@spellpower/430), .@puppet;
+ .master = BL_ID, .@puppet;
+ .lifetime = @spellpower*350, .@puppet;
+ addnpctimer 5000-(@spellpower*8), .@puppet$+"::OnSummon";
+ addnpctimer 6000, .@puppet$+"::OnDestroy";
+ end;
+
+OnSummon:
+ if(get(Hp, .master) < 1) destroy; // destroy if master is missing
+ if(getmap(.master) != strnpcinfo(3)) destroy; // destroy if master left the map
+ specialeffect FX_PENTAGRAM_BURST;
+ .@i = 0;
+ .@x = getnpcx();
+ .@y = getnpcy();
+ .@map$ = strnpcinfo(3);
+ callsub S_SummonAll;
+ end;
+
+OnDestroy:
+ destroy;
+
+S_SummonAll:
+ summon .@map$, rand(.@x-2,.@x+2), rand(.@y-2,.@y+2), .master, 1020, 2, .lifetime;
+ .@i = .@i + 1;
+ if (.@i < .count) goto S_SummonAll;
+ destroy;
+
+OnInit:
+ .school = SKILL_MAGIC_ASTRAL;
+ set .invocation$, chr(MAGIC_SYMBOL) + "kalakarenk"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ .level = 2;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level2-summon-mouboo.txt b/npc/magic/level2-summon-mouboo.txt
new file mode 100755
index 00000000..7232fe81
--- /dev/null
+++ b/npc/magic/level2-summon-mouboo.txt
@@ -0,0 +1,56 @@
+- script smmouboo NPC32767,{
+ end;
+
+OnCast:
+ if(call("magic_checks")) end;
+ if (Sp < 35) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("MoubooFigurine") < 1 || countitem("Root") < 1) end;
+ delitem "MoubooFigurine", 1;
+ delitem "Root", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 20000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 35;
+ misceffect FX_MAGIC_BLUE, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ callfunc "magic_exp";
+ .@puppet$ = "#"+strnpcinfo(0)+"#"+BL_ID;
+ .@puppet = puppet(getmapname(), POS_X, POS_Y, .@puppet$, 127);
+ if (.@puppet < 1) end;
+ .count = (@spellpower/270)+1, .@puppet;
+ .master = BL_ID, .@puppet;
+ .lifetime = @spellpower*100, .@puppet;
+ addnpctimer 4000-(@spellpower*9), .@puppet$+"::OnSummon";
+ addnpctimer 6000, .@puppet$+"::OnDestroy";
+ end;
+
+OnSummon:
+ if(get(Hp, .master) < 1) destroy; // destroy if master is missing
+ if(getmap(.master) != strnpcinfo(3)) destroy; // destroy if master left the map
+ specialeffect FX_PENTAGRAM_BURST;
+ .@i = 0;
+ .@x = getnpcx();
+ .@y = getnpcy();
+ .@map$ = strnpcinfo(3);
+ callsub S_SummonAll;
+ end;
+
+OnDestroy:
+ destroy;
+
+S_SummonAll:
+ summon .@map$, rand(.@x-2,.@x+2), rand(.@y-2,.@y+2), .master, 1028, 2, .lifetime;
+ .@i = .@i + 1;
+ if (.@i < .count) goto S_SummonAll;
+ destroy;
+
+OnInit:
+ .school = SKILL_MAGIC_ASTRAL;
+ set .invocation$, chr(MAGIC_SYMBOL) + "kalboo"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ .level = 2;
+ .exp_gain = 2;
+ end;
+}
diff --git a/npc/magic/level2-summon-pinkie.txt b/npc/magic/level2-summon-pinkie.txt
new file mode 100755
index 00000000..aeceec4d
--- /dev/null
+++ b/npc/magic/level2-summon-pinkie.txt
@@ -0,0 +1,56 @@
+- script smpinkie NPC32767,{
+ end;
+
+OnCast:
+ if(call("magic_checks")) end;
+ if (Sp < 35) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("PinkAntenna") < 1 || countitem("Root") < 1) end;
+ delitem "PinkAntenna", 1;
+ delitem "Root", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 20000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 35;
+ misceffect FX_MAGIC_BLUE, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ callfunc "magic_exp";
+ .@puppet$ = "#"+strnpcinfo(0)+"#"+BL_ID;
+ .@puppet = puppet(getmapname(), POS_X, POS_Y, .@puppet$, 127);
+ if (.@puppet < 1) end;
+ .count = (@spellpower/120)+1, .@puppet;
+ .master = BL_ID, .@puppet;
+ .lifetime = @spellpower*150, .@puppet;
+ addnpctimer 5000-(@spellpower*9), .@puppet$+"::OnSummon";
+ addnpctimer 6000, .@puppet$+"::OnDestroy";
+ end;
+
+OnSummon:
+ if(get(Hp, .master) < 1) destroy; // destroy if master is missing
+ if(getmap(.master) != strnpcinfo(3)) destroy; // destroy if master left the map
+ specialeffect FX_PENTAGRAM_BURST;
+ .@i = 0;
+ .@x = getnpcx();
+ .@y = getnpcy();
+ .@map$ = strnpcinfo(3);
+ callsub S_SummonAll;
+ end;
+
+OnDestroy:
+ destroy;
+
+S_SummonAll:
+ summon .@map$, rand(.@x-2,.@x+2), rand(.@y-2,.@y+2), .master, 1018, 2, .lifetime;
+ .@i = .@i + 1;
+ if (.@i < .count) goto S_SummonAll;
+ destroy;
+
+OnInit:
+ .school = SKILL_MAGIC_ASTRAL;
+ set .invocation$, chr(MAGIC_SYMBOL) + "kalgina"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ .level = 2;
+ .exp_gain = 2;
+ end;
+}
diff --git a/npc/magic/level2-summon-snakes.txt b/npc/magic/level2-summon-snakes.txt
new file mode 100755
index 00000000..a5add6f2
--- /dev/null
+++ b/npc/magic/level2-summon-snakes.txt
@@ -0,0 +1,57 @@
+- script summon-snakes NPC32767,{
+ end;
+
+OnCast:
+ if(call("magic_checks")) end;
+ if (Sp < 40) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("DarkCrystal") < 1 || countitem("SnakeEgg") < 1) end;
+ if (OrumQuest <= 40) end;
+ delitem "DarkCrystal", 1;
+ delitem "SnakeEgg", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 15000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 40;
+ misceffect FX_MAGIC_DARKRED, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ callfunc "magic_exp";
+ .@puppet$ = "#"+strnpcinfo(0)+"#"+BL_ID;
+ .@puppet = puppet(getmapname(), POS_X, POS_Y, .@puppet$, 127);
+ if (.@puppet < 1) end;
+ .count = (@spellpower/300)+1, .@puppet;
+ .master = BL_ID, .@puppet;
+ .lifetime = @spellpower*80, .@puppet;
+ addnpctimer 4000-(@spellpower*9), .@puppet$+"::OnSummon";
+ addnpctimer 6000, .@puppet$+"::OnDestroy";
+ end;
+
+OnSummon:
+ if(get(Hp, .master) < 1) destroy; // destroy if master is missing
+ if(getmap(.master) != strnpcinfo(3)) destroy; // destroy if master left the map
+ specialeffect FX_PENTAGRAM_BURST;
+ .@i = 0;
+ .@x = getnpcx();
+ .@y = getnpcy();
+ .@map$ = strnpcinfo(3);
+ callsub S_SummonAll;
+ end;
+
+OnDestroy:
+ destroy;
+
+S_SummonAll:
+ summon .@map$, rand(.@x-2,.@x+2), rand(.@y-2,.@y+2), .master, 1010, 2, .lifetime;
+ .@i = .@i + 1;
+ if (.@i < .count) goto S_SummonAll;
+ destroy;
+
+OnInit:
+ .school = SKILL_MAGIC_DARK;
+ set .invocation$, chr(MAGIC_SYMBOL) + "halhiss"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ .level = 2;
+ .exp_gain = 3;
+ end;
+}
diff --git a/npc/magic/level2-summon-spiky-mushroom.txt b/npc/magic/level2-summon-spiky-mushroom.txt
new file mode 100755
index 00000000..0b13aa0f
--- /dev/null
+++ b/npc/magic/level2-summon-spiky-mushroom.txt
@@ -0,0 +1,56 @@
+- script smsmushrooms NPC32767,{
+ end;
+
+OnCast:
+ if(call("magic_checks")) end;
+ if (Sp < 33) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("HardSpike") < 1 || countitem("Root") < 1) end;
+ delitem "HardSpike", 1;
+ delitem "Root", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 20000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 33;
+ misceffect FX_MAGIC_BLUE, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ callfunc "magic_exp";
+ .@puppet$ = "#"+strnpcinfo(0)+"#"+BL_ID;
+ .@puppet = puppet(getmapname(), POS_X, POS_Y, .@puppet$, 127);
+ if (.@puppet < 1) end;
+ .count = (@spellpower/120)+1, .@puppet;
+ .master = BL_ID, .@puppet;
+ .lifetime = @spellpower*400, .@puppet;
+ addnpctimer 5000-(@spellpower*9), .@puppet$+"::OnSummon";
+ addnpctimer 6000, .@puppet$+"::OnDestroy";
+ end;
+
+OnSummon:
+ if(get(Hp, .master) < 1) destroy; // destroy if master is missing
+ if(getmap(.master) != strnpcinfo(3)) destroy; // destroy if master left the map
+ specialeffect FX_PENTAGRAM_BURST;
+ .@i = 0;
+ .@x = getnpcx();
+ .@y = getnpcy();
+ .@map$ = strnpcinfo(3);
+ callsub S_SummonAll;
+ end;
+
+OnDestroy:
+ destroy;
+
+S_SummonAll:
+ summon .@map$, rand(.@x-2,.@x+2), rand(.@y-2,.@y+2), .master, 1019, 2, .lifetime;
+ .@i = .@i + 1;
+ if (.@i < .count) goto S_SummonAll;
+ destroy;
+
+OnInit:
+ .school = SKILL_MAGIC_ASTRAL;
+ set .invocation$, chr(MAGIC_SYMBOL) + "kalrenk"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ .level = 2;
+ .exp_gain = 1;
+ end;
+}
diff --git a/npc/magic/level2-summon-wickedmushroom.txt b/npc/magic/level2-summon-wickedmushroom.txt
new file mode 100755
index 00000000..94fea209
--- /dev/null
+++ b/npc/magic/level2-summon-wickedmushroom.txt
@@ -0,0 +1,57 @@
+- script smwmushroom NPC32767,{
+ end;
+
+OnCast:
+ if(call("magic_checks")) end;
+ if (Sp < 35) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("DarkCrystal") < 1 || countitem("SmallMushroom") < 1) end;
+ if (OrumQuest <= 36) end;
+ delitem "DarkCrystal", 1;
+ delitem "SmallMushroom", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 15000, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 35;
+ misceffect FX_MAGIC_DARKRED, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ callfunc "magic_exp";
+ .@puppet$ = "#"+strnpcinfo(0)+"#"+BL_ID;
+ .@puppet = puppet(getmapname(), POS_X, POS_Y, .@puppet$, 127);
+ if (.@puppet < 1) end;
+ .count = (@spellpower/250)+1, .@puppet;
+ .master = BL_ID, .@puppet;
+ .lifetime = @spellpower*80, .@puppet;
+ addnpctimer 4000-(@spellpower*9), .@puppet$+"::OnSummon";
+ addnpctimer 6000, .@puppet$+"::OnDestroy";
+ end;
+
+OnSummon:
+ if(get(Hp, .master) < 1) destroy; // destroy if master is missing
+ if(getmap(.master) != strnpcinfo(3)) destroy; // destroy if master left the map
+ specialeffect FX_PENTAGRAM_BURST;
+ .@i = 0;
+ .@x = getnpcx();
+ .@y = getnpcy();
+ .@map$ = strnpcinfo(3);
+ callsub S_SummonAll;
+ end;
+
+OnDestroy:
+ destroy;
+
+S_SummonAll:
+ summon .@map$, rand(.@x-2,.@x+2), rand(.@y-2,.@y+2), .master, 1106, 2, .lifetime;
+ .@i = .@i + 1;
+ if (.@i < .count) goto S_SummonAll;
+ destroy;
+
+OnInit:
+ .school = SKILL_MAGIC_DARK;
+ set .invocation$, chr(MAGIC_SYMBOL) + "helorp"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ .level = 2;
+ .exp_gain = 3;
+ end;
+}
diff --git a/npc/magic/level2-toxic-dart.txt b/npc/magic/level2-toxic-dart.txt
new file mode 100755
index 00000000..51bcbb40
--- /dev/null
+++ b/npc/magic/level2-toxic-dart.txt
@@ -0,0 +1,57 @@
+- script toxic-dart NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 15) end;
+ .@level = getskilllv(.school);
+ if (.@level < .level) end;
+ if (OrumQuest <= 37) end;
+ if (.@level <= 2 && countitem("Root") >= 2) delitem "Root", 2;
+ elif (.@level <= 2) end;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 500, "Magic Timer::OnClear"; // set the new debuff
+ callfunc "adjust_spellpower";
+ Sp = Sp - 15;
+ misceffect FX_MAGIC_DARKRED, strcharinfo(0);
+ setarray @phlexspell[0],
+ (sqrt(@spellpower) * 5), // elt damage
+ ((BaseLevel/3) + 5), // elt damage bonus
+ (((200 - Agi) * 1200) / 200), // delay
+ ((@spellpower/75) + 3), // charges
+ (5000+(@spellpower*1200)), // poison duration
+ (max(15,@spellpower/15)+5); // poison strength
+
+ callfunc "magic_exp";
+ goto L_FreeRecast;
+
+OnAttack:
+ if (target(BL_ID, @target_id, 50) != 50) goto L_FreeRecast; // 0x20 | 0x02 | 0x10
+ misceffect FX_MAGIC_DARKRED, strcharinfo(0);
+ void call("elt_damage", @phlexspell[0], @phlexspell[1], ELT_NEUTRAL, ELT_POISON, FX_FIRE_BURST);
+ if(@target_id != BL_ID && isloggedin(@target_id)) // this is a dirty trick to check if the target is a player
+ sc_start SC_POISON, @phlexspell[4], @phlexspell[5], @target_id;
+ @phlexspell[3] = @phlexspell[3] - 1;
+ goto L_FreeRecast;
+
+L_FreeRecast:
+ if (@phlexspell[3] > 0)
+ addtimer 0, strnpcinfo(0) + "::OnSetRecast";
+ end;
+
+OnDischarge:
+ if (@phlexspell[3] < 1) end;
+ @phlexspell[3] = 0;
+ misceffect FX_FIRE_BURST, strcharinfo(0);
+ overrideattack;
+ end;
+
+OnSetRecast:
+ overrideattack @phlexspell[2], 4, ATTACK_ICON_GENERIC, 31, strnpcinfo(0)+"::OnAttack";
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_DARK;
+ set .invocation$, chr(MAGIC_SYMBOL) + "phlex"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 2;
+ .exp_gain = 3;
+ end;
+}
diff --git a/npc/magic/level3-necromancy.txt b/npc/magic/level3-necromancy.txt
new file mode 100755
index 00000000..2a09bd65
--- /dev/null
+++ b/npc/magic/level3-necromancy.txt
@@ -0,0 +1,51 @@
+- script necromancy NPC32767,{
+ if(call("magic_checks")) end;
+ if (Sp < 50) end;
+ if (getskilllv(.school) < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ @target_id = getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id)) end;
+ if (get(Hp, @target_id) > 0) end;
+ if (Hp < (get(MaxHp, @target_id) / 3)) end; // hp must be at least a third of the max hp of the target
+ callfunc "adjust_spellpower";
+ if (distance(BL_ID, @target_id) >= (((sqrt(@spellpower)*12)+@spellpower)/100)+2) end;
+ if (get(@necromancer, @target_id) > 0) end; // someone else is already trying to resurrect this player
+ if (getmapflag(getmapname(), mf_nosave)) end; // do not allow for maps like illia or candor
+ if (countitem("Soul") >= 1) delitem "Soul", 1; else end;
+
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 20000, "Magic Timer::OnClear";
+ Sp = Sp - 50;
+ misceffect FX_MAGIC_DARKRED, strcharinfo(0); // on caster
+ misceffect FX_PENTAGRAM_BUILDUP, @args$; // on target
+
+ set @necromancer, CHAR_ID, @target_id; // tell the target who is reviving them
+
+ addtimer 6000, strnpcinfo(0)+"::OnRevive", @target_id; // TODO: make it take more or less time depending on the spell power
+ end;
+
+OnRevive:
+ .@necro = get(BL_ID, @necromancer);
+ if (.@necro < 1) goto L_Clean;
+ if (get(Hp, .@necro) < 1) end;
+ misceffect FX_PENTAGRAM_BURST, strcharinfo(0);
+ misceffect FX_CRITICAL, strcharinfo(0, .@necro);
+ heal 1, 0; // revive
+ Hp = 1;
+ Sp = 0;
+ Hp = 1, .@necro;
+ Sp = 0, .@necro;
+ goto L_Clean;
+
+L_Clean:
+ @necromancer = 0;
+ end;
+
+OnInit:
+ .school = SKILL_MAGIC_DARK;
+ set .invocation$, chr(MAGIC_SYMBOL) + "nevela"; // used in npcs that refer to this spell
+ void call("magic_register");
+ .level = 3;
+ .exp_gain = 1;
+ end;
+}