summaryrefslogtreecommitdiff
path: root/world/map/npc/magic
diff options
context:
space:
mode:
Diffstat (limited to 'world/map/npc/magic')
-rw-r--r--world/map/npc/magic/_import.txt10
-rw-r--r--world/map/npc/magic/_procedures.txt46
-rw-r--r--world/map/npc/magic/event-boss-powerup-disarm.txt41
-rw-r--r--world/map/npc/magic/event-boss-powerup-grenades.txt40
-rw-r--r--world/map/npc/magic/event-boss-powerup-headshot.txt54
-rw-r--r--world/map/npc/magic/event-boss-powerup-lifedrain.txt44
-rw-r--r--world/map/npc/magic/event-boss-powerup-manadrain.txt44
-rw-r--r--world/map/npc/magic/event-boss-powerup-poison.txt35
-rw-r--r--world/map/npc/magic/event-boss-powerup-tormenta.txt38
-rw-r--r--world/map/npc/magic/event-boss-powerup-totheabyss.txt57
-rw-r--r--world/map/npc/magic/event-boss-powerup-tothecrypt.txt57
-rw-r--r--world/map/npc/magic/level1-grow-shadow.txt40
-rw-r--r--world/map/npc/magic/level2-magic-knuckles.txt68
-rw-r--r--world/map/npc/magic/level2-shear.txt1
14 files changed, 558 insertions, 17 deletions
diff --git a/world/map/npc/magic/_import.txt b/world/map/npc/magic/_import.txt
index 5b1ea65c..4c5dc1ed 100644
--- a/world/map/npc/magic/_import.txt
+++ b/world/map/npc/magic/_import.txt
@@ -14,6 +14,7 @@ npc: npc/magic/level1-grow-mauve.txt
npc: npc/magic/level1-grow-alizarin.txt
npc: npc/magic/level1-grow-gamboge.txt
npc: npc/magic/level1-grow-cobalt.txt
+npc: npc/magic/level1-grow-shadow.txt
npc: npc/magic/level1-summon-maggots.txt
npc: npc/magic/level1-sense-spouse.txt
npc: npc/magic/level1-detect-magic.txt
@@ -46,3 +47,12 @@ npc: npc/magic/level2-make-shirt.txt
npc: npc/magic/level3-necromancy.txt
npc: npc/magic/event-summon-managuardian.txt
npc: npc/magic/event-summon-manatyrant.txt
+npc: npc/magic/event-boss-powerup-lifedrain.txt
+npc: npc/magic/event-boss-powerup-manadrain.txt
+npc: npc/magic/event-boss-powerup-poison.txt
+npc: npc/magic/event-boss-powerup-tormenta.txt
+npc: npc/magic/event-boss-powerup-totheabyss.txt
+npc: npc/magic/event-boss-powerup-tothecrypt.txt
+npc: npc/magic/event-boss-powerup-disarm.txt
+npc: npc/magic/event-boss-powerup-grenades.txt
+npc: npc/magic/event-boss-powerup-headshot.txt
diff --git a/world/map/npc/magic/_procedures.txt b/world/map/npc/magic/_procedures.txt
index eaacd774..601d5b15 100644
--- a/world/map/npc/magic/_procedures.txt
+++ b/world/map/npc/magic/_procedures.txt
@@ -94,6 +94,52 @@ L_Return:
return 0;
}
+
+// this function is call()-only
+// Custom version of checks for Dungeon Masters boss "powerups".
+// Both GMs and player eventers MAY eventually call "boss powerups".
+// By default, only GMs >= 40 can use BossPowers, but:
+// - If someone abuses BossPowers, setting #BOSS_POWERS_DISABLED = 1 on them locks them out.
+// - Some (trusted) player can be allowed to invoke this by setting #IS_EVENTER = 42 on them.
+// On TMWA these changes need GM Lv 80 to issue @setvar, so access can only be changed by Lv 80.
+// Advantage of this permissions system is: no need to shuffle GM levels, nor there's need to restart server.
+
+function|script|boss_powerup_checks
+{
+ set .@flags, getarg(0);
+ set .@nonmagic, .@flags & (1<<0);
+
+ if ($BOSS_KILLSWITCH) goto L_Killswitch; // If things go wrong, boss powers can be completely disabled.
+ if (#BOSS_POWERS_DISABLED) goto L_Killswitch; // If someone abuses BossPowers they can get DENY flag set.
+ if (HIDDEN) goto L_Hidden; // can not cast with @hide
+ if (@_M_BLOCK) goto L_Blocked; // check if last debuff ended
+ if (Hp < 1) goto L_Dead; // can not cast when dead
+ if (GM >= 40) goto L_Allowed; // GM >= 40 can use boss actions
+ if (#IS_EVENTER == 42) goto L_Allowed; // Trusted player(s) could be allowed to access Eventer "magic":
+ // Use @setvar #IS_EVENTER 0 42 Nick (GM Lv 80 command) to do it.
+ smsg SMSG_FAILURE, "BossPowers: Only few of mere mortals may try to enter the twilight zone";
+ return 1; // Not allowed by default.
+
+L_Allowed:
+ return 0; // Whoever gets here allowed to invoke BossPowers spells
+
+L_Killswitch:
+ smsg SMSG_FAILURE, "BossPowers: disabled by kill switch!";
+ return 2;
+
+L_Hidden:
+ smsg SMSG_FAILURE, "BossPowers: can't be used when hidden!";
+ return 3;
+
+L_Blocked:
+ smsg SMSG_FAILURE, "BossPowers: cooldown is in effect. Please wait.";
+ return 4;
+
+L_Dead:
+ smsg SMSG_FAILURE, "BossPowers: you're dead!";
+ return 5;
+}
+
function|script|elt_damage
{
// args are damage, dmgplus(mutation), bonus_elt, malus_elt, effect
diff --git a/world/map/npc/magic/event-boss-powerup-disarm.txt b/world/map/npc/magic/event-boss-powerup-disarm.txt
new file mode 100644
index 00000000..27a199a0
--- /dev/null
+++ b/world/map/npc/magic/event-boss-powerup-disarm.txt
@@ -0,0 +1,41 @@
+-|script|powerup-disarm|32767
+{
+ end;
+
+OnCast:
+ if(call("boss_powerup_checks")) end;
+ if (getmapflag(getmap(), MF_TOWN)) goto L_Fail_town;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 12000, "Magic Timer::OnClear"; // set the new debuff
+ sc_start SC_COOLDOWN, 12000, 0, BL_ID;
+ misceffect FX_MEDIUM_EXPLOSION, strcharinfo(0);
+ set @dist, 12;
+ foreach 0, getmap(), (POS_X - @dist), (POS_Y - @dist), (POS_X + @dist), (POS_Y + @dist), strnpcinfo(0) + "::OnHit";
+ end;
+
+OnHit:
+ if (@target_id == BL_ID) end; // Do not disarm caster
+ if ((get(Hp, @target_id)) < 1) end; // Do not touch dead
+ message strcharinfo(0, @target_id), "[boss-disarm] : "+strcharinfo(0, BL_ID)+" disarms you!";
+ addtimer 500, strnpcinfo(0)+"::OnUnequip", @target_id;
+ end;
+
+OnUnequip:
+ misceffect FX_EMOTE_SURPRISE, strcharinfo(0);
+ unequipbyid 8; // Hand ?1
+ unequipbyid 9; // Hand ?2
+ unequipbyid 10; // Ammo
+ end;
+
+L_Fail_town:
+ message strcharinfo(0), "[boss-disarm] : can't use boss tricks in towns!";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "mapdisarm"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ set .level, 0;
+ set .exp_gain, 0;
+ end;
+}
diff --git a/world/map/npc/magic/event-boss-powerup-grenades.txt b/world/map/npc/magic/event-boss-powerup-grenades.txt
new file mode 100644
index 00000000..0a692314
--- /dev/null
+++ b/world/map/npc/magic/event-boss-powerup-grenades.txt
@@ -0,0 +1,40 @@
+-|script|powerup-grenades|32767
+{
+ end;
+
+OnCast:
+ if(call("boss_powerup_checks")) end;
+ if (getmapflag(getmap(), MF_TOWN)) goto L_Fail_town;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 16000, "Magic Timer::OnClear"; // set the new debuff
+ sc_start SC_COOLDOWN, 16000, 0, BL_ID;
+ misceffect FX_MEDIUM_EXPLOSION, strcharinfo(0);
+ set @dist, 5;
+ foreach 0, getmap(), (POS_X - @dist), (POS_Y - @dist), (POS_X + @dist), (POS_Y + @dist), strnpcinfo(0) + "::OnHit";
+ end;
+
+OnHit:
+ if (@target_id == BL_ID) end; // Do not hit caster
+ if ((get(Hp, @target_id))) < 1 end; // Do not touch dead
+ message strcharinfo(0, @target_id), "[boss-grenades] : "+strcharinfo(0, BL_ID)+" dropped grenade on you!";
+ addtimer (100+rand(300)), strnpcinfo(0)+"::OnGrenadeHit", @target_id;
+ end;
+
+OnGrenadeHit:
+ misceffect FX_MEDIUM_SMOKE, strcharinfo(0);
+ heal (0 - rand(Hp)), 0;
+ set Sp, (Sp / 3);
+ end;
+
+L_Fail_town:
+ message strcharinfo(0), "[boss-grenades] : not allowed in towns!";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "grenades"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ set .level, 0;
+ set .exp_gain, 0;
+ end;
+}
diff --git a/world/map/npc/magic/event-boss-powerup-headshot.txt b/world/map/npc/magic/event-boss-powerup-headshot.txt
new file mode 100644
index 00000000..5e3dc4f9
--- /dev/null
+++ b/world/map/npc/magic/event-boss-powerup-headshot.txt
@@ -0,0 +1,54 @@
+-|script|powerup-headshot|32767
+{
+ end;
+
+OnCast:
+ if(call("boss_powerup_checks")) end;
+ if (getmapflag(getmap(), MF_TOWN)) goto L_Fail_town;
+ set @target_id, getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id) == 1) goto L_Fail_target;
+ if (distance(BL_ID, @target_id) > 9) goto L_Too_far;
+ if ((get(Hp, @target_id)) < 1) goto L_Too_dead; // Do not touch dead
+ if (target(BL_ID, @target_id, 0x20) != 0x20) goto L_No_los;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 16000, "Magic Timer::OnClear"; // set the new debuff
+ sc_start SC_COOLDOWN, 16000, 0, BL_ID;
+
+ misceffect FX_MEDIUM_EXPLOSION, strcharinfo(0);
+ misceffect FX_CHANNELLING_CAST_RED, @target_id;
+ set @tgthp, (get(Hp, @target_id) / 2);
+ set Sp, 1, @target_id; // Hurt target
+ if (@tgthp < 1500) set @tgthp, 1; // Boss or not? (>3000 HP)
+ set Hp, @tgthp, @target_id; // Hurt target
+ message strcharinfo(0, @target_id), "[boss-headshot] : "+strcharinfo(0, BL_ID)+" shot you!";
+ set @tgthp, 0;
+ end;
+
+L_Fail_town:
+ message strcharinfo(0), "[boss-headshot] : not allowed in towns!";
+ end;
+
+L_Fail_target:
+ message strcharinfo(0), "[boss-headshot] : need valid target (player).";
+ end;
+
+L_Too_far:
+ message strcharinfo(0), "[boss-headshot] : target is too far away.";
+ end;
+
+L_Too_dead:
+ message strcharinfo(0), "[boss-headshot] : why shoot already dead?!";
+ end;
+
+L_No_los:
+ message strcharinfo(0), "[boss-headshot] : no line of sight to target";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "headshot"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ set .level, 0;
+ set .exp_gain, 0;
+ end;
+}
diff --git a/world/map/npc/magic/event-boss-powerup-lifedrain.txt b/world/map/npc/magic/event-boss-powerup-lifedrain.txt
new file mode 100644
index 00000000..5399ea37
--- /dev/null
+++ b/world/map/npc/magic/event-boss-powerup-lifedrain.txt
@@ -0,0 +1,44 @@
+-|script|powerup-lifedrain|32767
+{
+ end;
+
+OnCast:
+ if(call("boss_powerup_checks")) end;
+ if (getmapflag(getmap(), MF_TOWN)) goto L_Fail_town;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 30000, "Magic Timer::OnClear"; // set the new debuff
+ sc_start SC_COOLDOWN, 30000, 0, BL_ID;
+ misceffect FX_PENTAGRAM_BURST, strcharinfo(0);
+ set @dist, 12;
+ foreach 0, getmap(), (POS_X - @dist), (POS_Y - @dist), (POS_X + @dist), (POS_Y + @dist), strnpcinfo(0) + "::OnHit";
+ end;
+
+OnHit:
+ if (@target_id == BL_ID) end; // Do not drain caster
+ set @targethp, get(Hp, @target_id); // Get HP of victim
+ if (@targethp > 0) goto L_cont;
+ set @targethp, 0;
+ end; // Do not drain dead!
+L_cont:
+ set @hpgain, min((@targethp / 4), 500); // Boss could be beefy -> clamp
+ message strcharinfo(0, @target_id), "[boss-lifedrain] : "+strcharinfo(0, BL_ID)+" drains "+(@hpgain * 2)+" hitpoints!";
+ misceffect FX_CHANNELLING_RAISE_RED, strcharinfo(0, @target_id);
+ set Hp, (@targethp - (2 * @hpgain)), @target_id; // Drain victim
+ set @targethp, (get(Hp, BL_ID) + @hpgain); // Compute caster's HP + bonus
+ set Hp, (@targethp), BL_ID; // Heal caster by half drain
+ set @hpgain, 0;
+ set @targethp, 0;
+ end;
+
+L_Fail_town:
+ message strcharinfo(0), "[boss-lifedrain] : aura of this place doesn't lets you to drain life!";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "maplifedrain"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ set .level, 0;
+ set .exp_gain, 0;
+ end;
+}
diff --git a/world/map/npc/magic/event-boss-powerup-manadrain.txt b/world/map/npc/magic/event-boss-powerup-manadrain.txt
new file mode 100644
index 00000000..b6f7f835
--- /dev/null
+++ b/world/map/npc/magic/event-boss-powerup-manadrain.txt
@@ -0,0 +1,44 @@
+-|script|powerup-manadrain|32767
+{
+ end;
+
+OnCast:
+ if(call("boss_powerup_checks")) end;
+ if (getmapflag(getmap(), MF_TOWN)) goto L_Fail_town;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 20000, "Magic Timer::OnClear"; // set the new debuff
+ sc_start SC_COOLDOWN, 20000, 0, BL_ID;
+ misceffect FX_CHANNELLING_CAST_BLUE, strcharinfo(0);
+ set @dist, 16;
+ foreach 0, getmap(), (POS_X - @dist), (POS_Y - @dist), (POS_X + @dist), (POS_Y + @dist), strnpcinfo(0) + "::OnHit";
+ end;
+
+OnHit:
+ if (@target_id == BL_ID) end; // Do not drain caster
+ if ((get(Hp, @target_id)) < 1) end; // Do not touch dead
+ set @targetmp, get(Sp, @target_id); // Get MP of victim
+ if (@targetmp > 0) goto L_cont;
+ set @targetmp, 0;
+ end; // Do not drain dead!
+L_cont:
+ set @hpgain, min((@targetmp * 2 ), 900); // Clamp in case of weird setups.
+ message strcharinfo(0, @target_id), "[boss-manadrain] : "+strcharinfo(0, BL_ID)+" drains all your mana!";
+ misceffect FX_CHANNELLING_RAISE_BLUE, strcharinfo(0, @target_id);
+ set Sp, 1, @target_id; // Drain victim
+ set Hp, (Hp + @hpgain), BL_ID; // Heal caster by computed amount
+ set @hpgain, 0;
+ set @targetmp, 0;
+ end;
+
+L_Fail_town:
+ message strcharinfo(0), "[boss-manadrain] : aura of this place doesn't lets you drain mana!";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "mapmanadrain"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ set .level, 0;
+ set .exp_gain, 0;
+ end;
+}
diff --git a/world/map/npc/magic/event-boss-powerup-poison.txt b/world/map/npc/magic/event-boss-powerup-poison.txt
new file mode 100644
index 00000000..a37f5aa9
--- /dev/null
+++ b/world/map/npc/magic/event-boss-powerup-poison.txt
@@ -0,0 +1,35 @@
+-|script|powerup-masspoison|32767
+{
+ end;
+
+OnCast:
+ if (call("boss_powerup_checks")) end;
+ if (getmapflag(getmap(), MF_TOWN)) goto L_Fail_town;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 16000, "Magic Timer::OnClear"; // set the new debuff
+ sc_start SC_COOLDOWN, 16000, 0, BL_ID;
+ misceffect FX_MAGIC_SNAKE_CAST, strcharinfo(0);
+ set @dist, 12;
+ foreach 0, getmap(), (POS_X - @dist), (POS_Y - @dist), (POS_X + @dist), (POS_Y + @dist), strnpcinfo(0) + "::OnHit";
+ end;
+
+OnHit:
+ if (@target_id == BL_ID) end; // Do not poison caster
+ if ((get(Hp, @target_id)) < 1) end; // Do not poison dead!
+ message strcharinfo(0, @target_id), "[boss-masspoison] : "+strcharinfo(0, BL_ID)+" poisoned you!";
+ misceffect FX_EMOTE_DISGUST, strcharinfo(0, @target_id);
+ sc_start SC_POISON, 1, 60, @target_id;
+ end;
+
+L_Fail_town:
+ message strcharinfo(0), "[boss-masspoison] : can't mass-poison in towns!";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "mappoison"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ set .level, 0;
+ set .exp_gain, 0;
+ end;
+}
diff --git a/world/map/npc/magic/event-boss-powerup-tormenta.txt b/world/map/npc/magic/event-boss-powerup-tormenta.txt
new file mode 100644
index 00000000..52e6f42f
--- /dev/null
+++ b/world/map/npc/magic/event-boss-powerup-tormenta.txt
@@ -0,0 +1,38 @@
+-|script|powerup-tormenta|32767
+{
+ end;
+
+OnCast:
+ if(call("boss_powerup_checks")) end;
+ bonus bMaxHP, 20000;
+ set Hp, (Hp+20000), BL_ID;
+ set Class, 1137, BL_ID;
+ warp getmap(), POS_X, POS_Y; // Refresh witch appearance
+ addtimer 1500, strnpcinfo(0)+"::OnFix";
+ message strcharinfo(0), "[boss-tormenta] : Tormenta impersonation started!";
+ end;
+
+OnFix:
+ set @fix_count, @fix_count + 1;
+ if (@fix_count > 1000) goto L_done; // Timed out.
+ if (get(Class, BL_ID) != 1137) goto L_done; // Caster attempted charclass?
+ set Class, 1142, BL_ID;
+ set Class, 1137, BL_ID;
+ addtimer 1500, strnpcinfo(0)+"::OnFix";
+ end;
+L_done:
+ message strcharinfo(0, BL_ID), "[boss-tormenta] : Tormenta impersonation ended!";
+ set @fix_count, 0;
+ set Class, 0, BL_ID;
+ bonus bMaxHP, 0;
+ set Hp, 100, BL_ID;
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "tormenta"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ set .level, 0;
+ set .exp_gain, 0;
+ end;
+}
diff --git a/world/map/npc/magic/event-boss-powerup-totheabyss.txt b/world/map/npc/magic/event-boss-powerup-totheabyss.txt
new file mode 100644
index 00000000..d215db8b
--- /dev/null
+++ b/world/map/npc/magic/event-boss-powerup-totheabyss.txt
@@ -0,0 +1,57 @@
+-|script|powerup-totheabyss|32767
+{
+ end;
+
+// Armageddon-like action to be thrown by boss - by Hello=)
+// Hurts everyone near boss, throws FX and teleports 'em to abyss!
+
+OnCast:
+ if (call("boss_powerup_checks")) end;
+ if (getmapflag(getmap(), MF_TOWN)) goto L_Fail_town;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 60000, "Magic Timer::OnClear"; // set the new debuff
+ sc_start SC_COOLDOWN, 60000, 0, BL_ID;
+ misceffect FX_RED_MAGIC_CAST, strcharinfo(0);
+ set @dist, 25;
+ foreach 0, getmap(), (POS_X - @dist), (POS_Y - @dist), (POS_X + @dist), (POS_Y + @dist), strnpcinfo(0) + "::OnHit";
+ end;
+
+OnHit:
+ if ((get(Hp, @target_id)) < 1) end; // Do not touch dead
+ set Sp, 1, @target_id; // Hurt target
+ set Hp, min(((Hp/2)), 100), @target_id; // Hurt target
+ sc_start SC_POISON, 1, 10, @target_id; // Poison target
+ message strcharinfo(0, @target_id), "[boss-to-the-abyss] : "+strcharinfo(0, BL_ID)+" ##B PULLS YOU TO THE ABYSS!!";
+ misceffect FX_RED_MAGIC_CAST, strcharinfo(0, @target_id);
+ addtimer 1000, strnpcinfo(0)+"::OnTeleport", @target_id;
+ end;
+
+// Runs attached to player, beware. Dont try access vars from former code!
+OnTeleport:
+ warp "070-3", 40+rand(5), 25+rand(5); // warp (under char's RID!)
+ addtimer 1500, strnpcinfo(0)+"::OnArrival"; // To play FX after player's arrival -> map
+ end; // Done.
+
+// Runs attached to player, beware. Dont try access vars from former code!
+OnArrival:
+ misceffect 50, strcharinfo(0); // Unfortunately hell glow lacks const.
+ addtimer 15000, strnpcinfo(0)+"::OnClean"; // To cancel former "infinite" FX.
+ end; // Done.
+
+// Runs attached to player, beware. Dont try access vars from former code!
+OnClean:
+ warp getmap(), POS_X, POS_Y; // Actually to get rid of infinite FX
+ end; // Done.
+
+L_Fail_town:
+ message strcharinfo(0), "[boss-to-the-abyss] : portal to abyss can't be opened in towns!";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "totheabyss"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ set .level, 0;
+ set .exp_gain, 0;
+ end;
+}
diff --git a/world/map/npc/magic/event-boss-powerup-tothecrypt.txt b/world/map/npc/magic/event-boss-powerup-tothecrypt.txt
new file mode 100644
index 00000000..8ae4b3b6
--- /dev/null
+++ b/world/map/npc/magic/event-boss-powerup-tothecrypt.txt
@@ -0,0 +1,57 @@
+-|script|powerup-tothecrypt|32767
+{
+ end;
+
+// Armageddon-like action to be thrown by boss - by Hello=)
+// Hurts everyone near boss, throws FX and teleports 'em to crypt!
+
+OnCast:
+ if (call("boss_powerup_checks")) end;
+ if (getmapflag(getmap(), MF_TOWN)) goto L_Fail_town;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 60000, "Magic Timer::OnClear"; // set the new debuff
+ sc_start SC_COOLDOWN, 60000, 0, BL_ID;
+ misceffect FX_BLUE_MAGIC_CAST, strcharinfo(0);
+ set @dist, 25;
+ foreach 0, getmap(), (POS_X - @dist), (POS_Y - @dist), (POS_X + @dist), (POS_Y + @dist), strnpcinfo(0) + "::OnHit";
+ end;
+
+OnHit:
+ if ((get(Hp, @target_id)) < 1) end; // Do not touch dead
+ set Sp, 1, @target_id; // Hurt target
+ set Hp, min(((Hp/2)), 100), @target_id; // Hurt target
+ sc_start SC_POISON, 1, 10, @target_id; // Poison target
+ message strcharinfo(0, @target_id), "[boss-to-the-crypt] : "+strcharinfo(0, BL_ID)+" ##B PULLS YOU TO THE CRYPT!!";
+ misceffect FX_CHANNELLING_RAISE, strcharinfo(0, @target_id);
+ addtimer 1000, strnpcinfo(0)+"::OnTeleport", @target_id;
+ end;
+
+// Runs attached to player, beware. Dont try access vars from former code!
+OnTeleport:
+ warp "027-5", 71+rand(3), 51+rand(3); // warp (under char's RID!)
+ addtimer 1500, strnpcinfo(0)+"::OnArrival"; // To play FX after player's arrival -> map
+ end; // Done.
+
+// Runs attached to player, beware. Dont try access vars from former code!
+OnArrival:
+ misceffect 50, strcharinfo(0); // Unfortunately hell glow lacks const.
+ addtimer 15000, strnpcinfo(0)+"::OnClean"; // To cancel former "infinite" FX.
+ end; // Done.
+
+// Runs attached to player, beware. Dont try access vars from former code!
+OnClean:
+ warp getmap(), POS_X, POS_Y; // Actually to get rid of infinite FX
+ end; // Done.
+
+L_Fail_town:
+ message strcharinfo(0), "[boss-to-the-crypt] : portal to crypt can't be opened in towns!";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "tothecrypt"; // used in npcs that refer to this spell
+ void call("magic_register", "OnCast");
+ set .level, 0;
+ set .exp_gain, 0;
+ end;
+}
diff --git a/world/map/npc/magic/level1-grow-shadow.txt b/world/map/npc/magic/level1-grow-shadow.txt
new file mode 100644
index 00000000..fff821db
--- /dev/null
+++ b/world/map/npc/magic/level1-grow-shadow.txt
@@ -0,0 +1,40 @@
+-|script|grow-shadow|32767
+{
+ if(call("magic_checks")) end;
+ if (Sp < 4) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (countitem("ShadowHerb") < 1 || countitem("Root") < 1) end;
+ delitem "ShadowHerb", 1;
+ delitem "Root", 1;
+ set @_M_BLOCK, 1; // block casting, until the timer clears it
+ addtimer 2000, "Magic Timer::OnClear"; // set the new debuff
+ sc_start SC_COOLDOWN, 2000, 0, BL_ID;
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 4;
+ set CASTS, CASTS + 1;
+ if (CASTS < 0) set CASTS, 1; // overflow
+ misceffect FX_MAGIC_GROW_CAST, strcharinfo(0);
+ setarray @summon[0], 0, (getskilllv(.school)/2)+1;
+ callfunc "magic_exp";
+ addtimer 4000-(@spellpower-9), strnpcinfo(0)+"::OnSummon";
+ end;
+
+OnSummon:
+ misceffect FX_MAGIC_GROW_SPAWN, strcharinfo(0);
+ callsub S_SummonAll;
+ end;
+
+S_SummonAll:
+ summon getmap(), rand(POS_X-2,POS_X+2), rand(POS_Y-2,POS_Y+2), BL_ID, "Shadow Plant Summon", ShadowPlant, 1, (@spellpower*50)+10000;
+ set @summon[0], @summon[0] + 1;
+ if (@summon[0] < @summon[1]) goto S_SummonAll;
+ return;
+
+OnInit:
+ set .school, SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "modrisha"; // used in npcs that refer to this spell
+ void call("magic_register");
+ set .level, 1;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level2-magic-knuckles.txt b/world/map/npc/magic/level2-magic-knuckles.txt
index a45bf3d6..0674f689 100644
--- a/world/map/npc/magic/level2-magic-knuckles.txt
+++ b/world/map/npc/magic/level2-magic-knuckles.txt
@@ -1,6 +1,18 @@
-|script|magic-knuckles|32767
{
if @_U_BLOCK >= 1 goto L_Still_Exhausted;
+/*
+ set @upmarmu_spell_npc_name$, "#Upmarmu#" + getcharid(3); // make a unique puppet name for every player
+ set .upmarmu_spell_npc, getnpcid(@upmarmu_spell_npc_name$);
+ if ( .upmarmu_spell_npc >= 1 ) goto L_NPC_Exists; // if this npc already exist reuse it so that idle recovery timer does not get destroyed
+
+ set .upmarmu_spell_npc, puppet(getmap(), 0, 0, @upmarmu_spell_npc_name$, 127); // clone npc => get puppet id (npc 127 is invisible and can't be targeted)
+ if (.upmarmu_spell_npc < 1) end;
+ set .caster, getcharid(3), .upmarmu_spell_npc; // tell the puppet who controls it
+ goto L_NPC_Exists;
+
+L_NPC_Exists:
+*/
if (call("magic_checks")) end;
if (Sp < 20) end;
if (getskilllv(SKILL_MAGIC) < .level) end;
@@ -16,13 +28,19 @@
set Sp, Sp - 20;
set CASTS, CASTS + 1;
if (CASTS < 0) set CASTS, 1; // overflow
+
+ set .@delay, (200-(Agi+Agi2))/8;
+ if ( .@delay < 12 ) set .@delay, 12; // 144 attack delay max @ 97 agi
+ elif ( .@delay > 22 ) set .@delay, 22; // 484 attack delay min
+
misceffect FX_MAGIC_KNUCKLE_CAST, strcharinfo(0);
setarray @upmarmuspell[0],
- max(1, (BASE_ATK - 100 + min(100, (Int+Int2))) * 2 ), // dmg
- ((@spellpower/10) + (((Dex+Dex2) * 8)/(sqrt(BaseLevel + 34)) + 20)), // charges (you get more at lower levels)
- ((sqrt((300 - ((Agi+Agi2) * 2)) + (5/2))) * 4), // delay
- (((Agi+Agi2) + (Int+Int2)) / 5), // dmg bonus
+ max(1, BASE_ATK + (@spellpower / 6)), // dmg
+ ((@spellpower/12) + (((Dex+Dex2) * 8)/(sqrt(BaseLevel + 34)) + 20)), // charges (you get more at lower levels)
+ .@delay, // delay
+ (((Str+Str2) + (Dex+Dex2)) / 5), // dmg bonus
(((BaseLevel/5) + Str) * 2); // do not allow to equip light armor, cast, and then switch to heavy armor to get bonus str
+
callfunc "magic_exp";
goto L_FreeRecast;
@@ -31,19 +49,12 @@ OnAttack:
if (target(BL_ID, @target_id, 22) != 22) goto L_FreeRecast; // 0x10 | 0x02 | 0x04
void call("elt_damage", @upmarmuspell[0], (@upmarmuspell[3] + @upmarmuspell[4]), ELT_WATER, ELT_FIRE, FX_NONE);
- // This timer is if you stopped somewhere below max hits then after 25sec you recover fully and start at 0 hits again
- stopnpctimer;
- // to get this work stoptimer must be executed here or after setnpctimer and then started again else
- // a timer somehow detaches that cant be set anymore, startnpctimer then attaches it again somehow
- // i think the problem is in npc_timerevent_calc_next somewhere
- if (@num_upmarmu_hits < 1) initnpctimer;
- setnpctimer 0;
- startnpctimer;
+// addtimer 0, @upmarmu_spell_npc_name$ + "::OnResetTimer";
set @upmarmuspell[1], @upmarmuspell[1] - 1;
set @num_upmarmu_hits, @num_upmarmu_hits + 1;
- if @num_upmarmu_hits > UPMARMU_HITS_TILL_EXHAUST goto L_Exhausted;
+ if @num_upmarmu_hits >= UPMARMU_HITS_TILL_EXHAUST goto L_Exhausted;
goto L_FreeRecast;
L_FreeRecast:
@@ -66,8 +77,7 @@ L_Still_Exhausted:
end;
L_StopTimer:
- stopnpctimer;
- setnpctimer 0;
+// addtimer 0, @upmarmu_spell_npc_name$ + "::OnStopTimer";
end;
OnDischarge:
@@ -75,17 +85,41 @@ OnDischarge:
set @upmarmuspell[1], 0;
misceffect FX_MAGIC_DISCHARGE, strcharinfo(0);
overrideattack;
- goto L_StopTimer;
+ end;
OnSetRecast:
overrideattack (@upmarmuspell[2] * @upmarmuspell[2]), 1, ATTACK_ICON_GENERIC, OVERRIDE_KNUCKLES, strnpcinfo(0)+"::OnAttack", @upmarmuspell[1]; // delay needs to be squared
end;
+/*
+OnResetTimer:
+ // This timer is if you stopped somewhere below max hits then after 25sec you recover fully and start at 0 hits again
+ stopnpctimer;
+ // to get this work stoptimer must be executed here or after setnpctimer and then started again else
+ // a timer somehow detaches that cant be set anymore, startnpctimer then attaches it again somehow
+ // i think the problem is in npc_timerevent_calc_next somewhere
+ if (@num_upmarmu_hits < 1) initnpctimer;
+ setnpctimer 0;
+ startnpctimer;
+ end;
+
+OnStopTimer:
+ stopnpctimer;
+ setnpctimer 0;
+ end;
+
OnTimer25000:
if (attachrid(getcharid(3)) < 1) end;
set @num_upmarmu_hits, 0;
detachrid;
- goto L_StopTimer;
+
+ stopnpctimer;
+ setnpctimer 0;
+ end;
+
+OnDestroy:
+ destroy;
+*/
OnInit:
set .school, SKILL_MAGIC_WAR;
diff --git a/world/map/npc/magic/level2-shear.txt b/world/map/npc/magic/level2-shear.txt
index 8f259bd3..133e53c3 100644
--- a/world/map/npc/magic/level2-shear.txt
+++ b/world/map/npc/magic/level2-shear.txt
@@ -35,6 +35,7 @@ OnAttack:
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 == 1189 && .@score < 700) set .@item$, "ShadowHerb"; // ShadowPlant
elif (.@id == 1035 && .@score < 300) set .@item$, "SilkCocoon"; // SilkWorm
elif (.@id == 1018 && .@score < 180) set .@item$, "PinkAntenna"; // Pinkie
else end;