summaryrefslogtreecommitdiff
path: root/npc/magic
diff options
context:
space:
mode:
authorJesusaves <cpntb1@ymail.com>2022-10-23 21:44:22 -0300
committerJesusaves <cpntb1@ymail.com>2022-10-23 21:44:22 -0300
commita7c45a192268da2601cef47a4cdba987ae2327ca (patch)
treec5fb5b97db109fe7106496dd96498c475881046b /npc/magic
downloadserverdata-a7c45a192268da2601cef47a4cdba987ae2327ca.tar.gz
serverdata-a7c45a192268da2601cef47a4cdba987ae2327ca.tar.bz2
serverdata-a7c45a192268da2601cef47a4cdba987ae2327ca.tar.xz
serverdata-a7c45a192268da2601cef47a4cdba987ae2327ca.zip
Initial commit (Moubootaur Legends fork)
Diffstat (limited to 'npc/magic')
-rw-r--r--npc/magic/abizit.txt33
-rw-r--r--npc/magic/demure.txt154
-rw-r--r--npc/magic/dragokin.txt42
-rw-r--r--npc/magic/drops.txt65
-rw-r--r--npc/magic/forget.txt52
-rw-r--r--npc/magic/guild.txt166
-rw-r--r--npc/magic/mpregen.txt57
-rw-r--r--npc/magic/ovh.txt13
-rw-r--r--npc/magic/parum.txt56
-rw-r--r--npc/magic/plantkingdom.txt62
-rw-r--r--npc/magic/revive.txt52
-rw-r--r--npc/magic/scrolls.txt36
-rw-r--r--npc/magic/study.txt48
-rw-r--r--npc/magic/transmigration.txt330
14 files changed, 1166 insertions, 0 deletions
diff --git a/npc/magic/abizit.txt b/npc/magic/abizit.txt
new file mode 100644
index 0000000..8c38a1d
--- /dev/null
+++ b/npc/magic/abizit.txt
@@ -0,0 +1,33 @@
+// TMW2 script
+// Author: Jesusalva <admin@tmw2.org>
+//
+// Magic Script: -
+//
+// Abizit() reports your magic power
+
+- script sk#abizit 32767,{
+ end;
+
+OnCall:
+ // Must have magic
+ if (!MAGIC_LVL)
+ end;
+
+ // Check cooldown
+ if (@abizit_at > gettimetick(2)) {
+ dispbottom l("Skill is in cooldown for @@.", FuzzyTime(@abizit_at));
+ end;
+ }
+
+ ShowAbizit(false);
+
+ // set cooldown
+ @abizit_at=gettimetick(2);
+ @abizit_at=@abizit_at+4;
+ end;
+
+OnInit:
+ bindatcmd "sk-abizit", "sk#abizit::OnCall", 0, 100, 0;
+ bindatcmd "abizit", "sk#abizit::OnCall", 0, 100, 0;
+ end;
+}
diff --git a/npc/magic/demure.txt b/npc/magic/demure.txt
new file mode 100644
index 0000000..c885e1b
--- /dev/null
+++ b/npc/magic/demure.txt
@@ -0,0 +1,154 @@
+// TMW2 script
+// Author: Jesusalva <admin@tmw2.org>
+//
+// Magic Script: TMW2_DEMURE
+//
+// Let yourself rage and go out of control destroy everything around you
+// Doubles attack speed but nullifies evade complety for 30 seconds.
+// Each level grants +30s and +1% evade and +5% attack speed.
+// After level 1, evade penalty/cooldown raises in 1s per additional level
+//
+// Cooldown is cast duration
+/*
+ SC_INCAGI: 190
+ SC_INCVIT: 191
+ SC_INCINT: 192
+ SC_INCDEX: 193
+ SC_INCLUK: 194
+ SC_INCHIT: 195
+ SC_INCHITRATE: 196
+ SC_INCFLEE: 197
+ SC_INCFLEERATE: 198
+ SC_INCMHPRATE: 199
+ SC_INCMSPRATE: 200
+ SC_INCATKRATE: 201
+ SC_INCMATKRATE: 202
+ SC_INCDEFRATE: 203
+
+ SC_WALKSPEED
+ SC_INVINCIBLE (?)
+ SC_MANA_PLUS (?)
+ SC_INCMHP
+ SC_INCMSP
+
+ // The basic ones
+ SC_STONE: 0
+ SC_FREEZE: 1
+ SC_STUN: 2
+ SC_SLEEP: 3
+ SC_POISON: 4
+ SC_CURSE: 5
+ SC_SILENCE: 6
+ SC_CONFUSION: 7
+ SC_BLIND: 8
+ SC_BLOODING: 9
+ SC_DPOISON: 10
+ SC_FEAR: 11
+ SC_COLD: 12
+ SC_BURNING: 13
+ SC_DEEP_SLEEP: 14
+ SC_PROVOKE: 20
+ SC_ENDURE: 21
+
+ // Original potion ones
+ SC_ATTHASTE_POTION1: 55
+ SC_ATTHASTE_POTION2: 56
+ SC_ATTHASTE_POTION3: 57
+ SC_ATTHASTE_INFINITY: 58
+ SC_MOVHASTE_HORSE: 59
+ SC_MOVHASTE_INFINITY: 60
+ SC_PLUSATTACKPOWER: 61
+ SC_PLUSMAGICPOWER: 62
+
+ // Guild Skills
+ SC_INCALLSTATUS
+ SC_SLOWPOISON
+ SC_BENEDICTIO (?)
+ SC_GDSKILL_REGENERATION (?)
+ SC_ANGELUS: DEF+
+ SC_BLESSING: STR/DEX/INT+
+ SC_IMPOSITIO: Wpn ATK+
+ SC_FORTUNE: CRIT+
+
+ // Guild & Party skills
+ SC_KAIZEL: Auto Revive
+ SC_MAXIMIZEPOWER: Always at full power
+ SC_MAGNIFICAT: MP Regen × 2
+
+ // Tested Newer ones
+ SC_RICHMANKIM: 167 (Target EXP+)
+
+ // Untested Newer ones
+ SC_CRITICALPERCENT: 262
+ SC_RESIST_PROPERTY_WATER: 664
+ SC_RESIST_PROPERTY_GROUND: 665
+ SC_RESIST_PROPERTY_FIRE: 666
+ SC_RESIST_PROPERTY_WIND: 667
+
+ » Create SC to boost skill power?
+ » Maybe SC to boost elemental damage
+
+ // Potionable Skills (Scrolls?)
+ TMW2_OVERLOAD (Pierce Double Damage)
+ TMW2_MAGNUSHEAL (Area Healing based on MATK, affects homun)
+ TMW2_FIREARROW (A weak fire-based attack. Bleeds.)
+ TMW2_FROSTDIVER (A weak ice-based attack. Freeze.)
+ TMW2_LIGHTNINGBOLT (A strong wind-based attack)
+ TMW2_HOLYLIGHT (A strong holy-based attack vs tile)
+ TMW2_METEORSHOWER (A strong AoE earth-based attack, which also stuns)
+ TMW2_ARROWSHOWER (AoE attack, causes your damage to become arrows)
+ TMW2_ALLINONE (Xanthem's Gambit - Weak w/ shields, multi-ele multi-attack)
+ «Summons»
+ «Little Wonders - Recover/dispel ailments, but no heal»
+
+ // Art of War: TMW2_HORIZONTALSLASH + TMW2_DIAGONALSLASH + TMW2_VERTICALSLASH + TMW2_STAB + TMW2_GRANDBLAST (possibly?)
+*/
+
+function script SK_Demure {
+ // non-melee weapons not allowed
+ if (getiteminfo(getequipid(EQI_HAND_R), ITEMINFO_RANGE) > 3) {
+ dispbottom l("Only melee weapons are permitted for use with this skill.");
+ end;
+ }
+
+ // Determine length: 30s per skill level
+ .@length=getskilllv(TMW2_DEMURE)*30000;
+ .@effect=25+getskilllv(TMW2_DEMURE);
+ .@penalty=getskilllv(TMW2_DEMURE)-101;
+ .@malus=(getskilllv(TMW2_DEMURE)-1)*1000;
+
+ // Add two SC_ effects: One to raise attack speed and other to drop evade
+ //sc_start(<effect type>, <ticks>, <value 1>{, <rate>, <flag>{, <GID>}})
+ sc_start SC_ATTHASTE_POTION2, .@length, .@effect;
+ SC_Bonus(.@length, SC_INCHITRATE, .@effect);
+ SC_Bonus(.@length, SC_INCATKRATE, .@effect);
+ SC_Bonus((.@length+.@malus), SC_INCFLEERATE, .@penalty);
+ SC_Bonus((.@length+.@malus), SC_INCDEFRATE, .@penalty);
+ SC_Bonus((.@length+.@malus), SC_INCMHPRATE, .@penalty);
+
+ // set cooldown and timer
+ @demure_at=gettimetick(2);
+ @demure_at=@demure_at+(.@length+.@malus)/1000;
+ addtimer(rand(786,1346), "sk#demure::OnTMW2DemureCheck");
+
+ // Get a few mana experience points (this is NOT used by Mana Stone)
+ GetManaExp(TMW2_DEMURE, rand(1,getskilllv(TMW2_DEMURE)));
+ return;
+}
+
+- script sk#demure 32767,{
+ end;
+
+// If you switch to a bow, you lose the effect at once and loop dies
+OnTMW2DemureCheck:
+ if (@demure_at < gettimetick(2))
+ end;
+ if (getiteminfo(getequipid(EQI_HAND_R), ITEMINFO_RANGE) > 3)
+ sc_start SC_ATTHASTE_POTION2, 100, -50;
+ else
+ addtimer(rand(786,1346), "sk#demure::OnTMW2DemureCheck");
+ end;
+
+OnInit:
+ end;
+}
diff --git a/npc/magic/dragokin.txt b/npc/magic/dragokin.txt
new file mode 100644
index 0000000..bf8344f
--- /dev/null
+++ b/npc/magic/dragokin.txt
@@ -0,0 +1,42 @@
+// TMW2 script
+// Author: Jesusalva <admin@tmw2.org>
+//
+// Magic Script: TMW2_DRAGOKIN
+//
+// Summons a Green Dragon because they are cool :3
+//
+// Cooldown is cast duration
+
+function script SK_Dragokin {
+ // Blocked from summoning magic
+ if (alignment() < 0)
+ return;
+
+ // Other requeriments: 5x Dragon Scale or Demure Axe
+ if (!(countitem(DragonScales) >= 4 || countitem(DemureAxe))) {
+ dispbottom l("You need 4x @@ to cast this skill.", getitemlink(DragonScales));
+ return;
+ }
+
+ // Setup
+ @sk=TMW2_DRAGOKIN;
+ @mp=50;
+ @amp=4;
+
+ // Check if you have mana to cast
+ // MagicCheck(SkillID, Mana{, MP per level})
+ if (!MagicCheck(@sk, @mp, @amp))
+ return;
+
+ // Destroy reagents
+ if (!countitem(DemureAxe))
+ delitem DragonScales, 4;
+
+ // set cooldown
+ @dragokin_at=gettimetick(2);
+ @dragokin_at=@dragokin_at+16;
+
+ // Summon the dragons and give Mana EXP
+ SK_summon(GreenDragon, 5, 5);
+ return;
+}
diff --git a/npc/magic/drops.txt b/npc/magic/drops.txt
new file mode 100644
index 0000000..fcfc57e
--- /dev/null
+++ b/npc/magic/drops.txt
@@ -0,0 +1,65 @@
+// TMW2 script
+// Author: Jesusalva <admin@tmw2.org>
+//
+// Magic Script: TMW2_DROPS
+//
+// Realm of Drops - A passive skill which drastically improves drop rates
+
+function script SK_drops {
+ .@mobId=getarg(0, killedrid);
+ if (getskilllv(TMW2_DROPS) <= 0)
+ return;
+ if (.@mobId <= 0)
+ return;
+ if (@skdrop[.@mobId] < 0)
+ return;
+
+ // Keep in mind that it is reset on logout
+ @skdrop[.@mobId]+=1;
+ .@lv=getmonsterinfo(.@mobId, MOB_LV);
+ .@min=10-getskilllv(TMW2_DROPS)+(.@lv/10);
+
+ // Maybe we are in condition for the bonus drop
+ if (@skdrop[.@mobId] % .@min == 0) {
+ // This creates .@item and .@rate with same index
+ deletearray($@MobDrop_item);
+ deletearray($@MobDrop_rate);
+ getmobdrops(.@mobId);
+ .@count = $@MobDrop_count;
+ copyarray(.@item[0], $@MobDrop_item[0], .@count);
+ copyarray(.@rate[0], $@MobDrop_rate[0], .@count);
+
+ // .@total => sum of all drop rates
+ // .@array => The real array for relative_array_random()
+ .@total = 0;
+ .@array = -1;
+ for (.@i = 0; .@i < .@count; ++.@i) {
+ .@s = getarraysize(.@array);
+ array_push(.@array, .@item[.@i]);
+ array_push(.@array, .@rate[.@i]);
+ .@total+=.@rate[.@i];
+ }
+
+ // Now we determine if you can, or cannot, get a bonus drop
+ if (.@total < 500) {
+ if (.@total < 200) {
+ // Hard limit: 2% of total drop rate (-1 prevents execution)
+ @skdrop[.@mobId]=-1;
+ return;
+ } else {
+ // Soft limit: Half the efficiency
+ if (@skdrop[.@mobId] % (.@min*2) != 0)
+ return;
+ }
+ }
+
+ // You can! So give you a random bonus drop with proper ponderation
+ .@drop = relative_array_random(.@array);
+ getmapxy(.@m$, .@x, .@y, 0);
+ makeitem(.@drop, 1, .@m$, .@x, .@y);
+ if ($@GM_OVERRIDE || debug)
+ debugmes("Realm of Drops: Created %d as bonus drop in (%d,%d) [TDR %d KL %d]", .@drop, .@x, .@y, .@total, @skdrop[.@mobId]);
+ }
+ return;
+}
+
diff --git a/npc/magic/forget.txt b/npc/magic/forget.txt
new file mode 100644
index 0000000..81e3cdf
--- /dev/null
+++ b/npc/magic/forget.txt
@@ -0,0 +1,52 @@
+// TMW2 script
+// Author: Jesusalva <admin@tmw2.org>
+//
+// Magic Script: Forgetful NPCs
+// Allows you to get rid of unwanted skills
+
+// ForgetfulNPC( NAME, SCHOOL )
+function script ForgetfulNPC {
+ .@n$=getarg(0);
+ .@school=getarg(1);
+ mesc l("Teaching %s your skills will make you both forget them.", .@n$), 1;
+ mesc l("Once your skill is forgotten, the Magic Skill Points used will be freed."), 1;
+ mesc l("But be careful: learning fees and research points WILL NOT be given back!"), 1;
+ do
+ {
+ next;
+ mesc l("Which skill will you FORGET permanently today?"), 1;
+ setarray .@forget$, l("Cancel"), "-1";
+ freeloop(true);
+ for (.@i=0; .@i < getarraysize($@MSK_MAGIC) ; .@i++) {
+ .@sk=$@MSK_MAGIC[.@i];
+ if (getskilllv(.@sk)) {
+ if ($@MSK_CLASS[.@sk] == .@school) {
+ array_push(.@forget$, getskillname(.@sk));
+ array_push(.@forget$, str(.@sk));
+ }
+ }
+ }
+ freeloop(false);
+ menuint2(.@forget$);
+ deletearray(.@forget$);
+ if (@menuret < 1)
+ close;
+ mes "";
+ mesc l("Skill @@ will be permanently lost!", getskillname(@menuret)), 1;
+ mesc l("Continue anyway?"), 1;
+ if (askyesno() == ASK_YES) {
+ .@msp=0;
+ .@lv=$@MSK_MSPCOST[@menuret]+max(0, getskilllv(@menuret)-5);
+ skill @menuret, 0, 0;
+ MAGIC_PTS-=.@lv;
+ mesc l("Skill @@ has been lost", getskillname(@menuret)), 3;
+ mesc l("You recovered @@ magic skill points", .@lv), 3;
+ } else {
+ mesn l("%s, the Forgetful", .@n$);
+ mesq l("Uh, what?");
+ }
+ } while (@menuret);
+ return;
+}
+
+
diff --git a/npc/magic/guild.txt b/npc/magic/guild.txt
new file mode 100644
index 0000000..e538b71
--- /dev/null
+++ b/npc/magic/guild.txt
@@ -0,0 +1,166 @@
+// TMW2 script
+// Author: Jesusalva <admin@tmw2.org>
+//
+// Magic Script: TMW2_GD
+//
+// Guild Magic
+// Reserved SCs: SC_INCALLSTATUS SC_ANGELUS SC_BLESSING SC_IMPOSITIO SC_KAIZEL SC_MAGNIFICAT
+// For testing: SC_TWOHANDQUICKEN
+// BROKEN: SC_ASSNCROS
+
+/*
+SC_ENCHANTPOISON
+Endows a single target's equipped weapon with the Poison property temporarily. This skill also gives the chance of leaving enemies poisoned while physically attacking.
+
+SC_POISONREACT
+Gives a 50% chance of autocasting Level 5 Envenom when the user is physically attacked for a set number of autocasts. If the user is struck with a Nature property attack, the user will retaliate with a stronger physical attack, which has a 50% chance of leaving the attacker poisoned. This skill will end after a set duration, reaching the autocast limit or performing one poison counter.
+
+SC_SLOWPOISON
+Stops the HP drain from the Poison status effect that affects a single target. It does not nullify the defense drop from the forementioned status effect. (no params)
+
+SC_SUFFRAGIUM
+Shortens the Variable Cast Time of a single target's next skill. (15%)
+
+SC_BENEDICTIO
+Blesses a targeted location to endow the armor of all players within the area of effect with the Holy property. (no params)
+
+SC_KYRIE <sc3: hits/durability>
+Creates a protective barrier on a single target that blocks every form of physical damage until its durability wears off or expires. Its durability is a portion of the target's Max HP. This skill cannot be used in conjunction with Assumptio.
+
+*SC_GLORIA
+Temporarily boosts LUK by 30 to the user and party members.
+
+SC_LEXAETERNA
+Weakens a single target so it can take double damage from the next incoming attack. Healing, misses, status effects and the retaliation from Shield Reflect do not trigger the effect. (PVP or used versus monsters. no params)
+
+SC_MAXIMIZEPOWER
+Alters the damage variance of the equipped weapon to inflict the maximum of its damage. Maintaining this skill active will drain SP. (args = sp drain?)
+
+SC_ENERGYCOAT
+Coats the caster with spiritual energy to buffer all incoming damage temporarily. The more remaining SP the caster has, the more damage is buffered and the more SP is drained. (no params?)
+
+SC_ASSUMPTIO
+Places a temporary buff on a single target that doubles their Hard Defense and Hard Magic Defense. This skill cannot be used in conjunction with Kyrie Eleison and Kaite.
+
+// SC_GDSKILL_BATTLEORDER
+-- SC_LEADERSHIP (aura)
+-- SC_GLORYWOUNDS (aura)
+-- SC_SOULCOLD (aura)
+-- SC_HAWKEYES (aura)
+
+SC_HUMMING
+Increase HIT of players in the area of effect by +2 per SkillLV. The accuracy rate increased by this skill is affected by Dancing Lesson skill level and DEX of the caster. (integer value)
+
+*/
+
+// GD_allboost ( lv{, target} )
+// Increases all stats
+function script GD_allboost {
+ .@lv=getarg(0, @skillLv);
+ .@t$=getarg(1, "filter_sameguild");
+ // range, time, SC, BL, power, filter
+ areasc(3+.@lv, 40000+(5000*.@lv), SC_INCALLSTATUS, BL_PC, .@lv, .@t$);
+ return;
+}
+
+
+// GD_regeneration ( lv )
+// 12x12 HP and MP recovery
+function script GD_regenerating {
+ .@lv=getarg(0, @skillLv);
+ .@t$=getarg(1, "filter_sameguild");
+ // range, time, SC, BL, power, filter
+ areasc(12, 8000+(1000*.@lv), SC_GDSKILL_REGENERATION, BL_PC, 15+(5*.@lv), .@t$);
+ return;
+}
+
+
+// GD_defboost ( lv )
+// Places a temporary buff on the user and all party members in a 14x14 area around the user that increases Soft Defense. (VIT def)
+function script GD_defboost {
+ .@lv=getarg(0, @skillLv);
+ .@t$=getarg(1, "filter_sameguild");
+ // range, time, SC, BL, power, filter
+ areasc(4+.@lv, 40000+(5000*.@lv), SC_ANGELUS, BL_PC, .@lv*4, .@t$);
+ return;
+}
+
+
+// GD_atkboost ( lv )
+// Places a temporary buff on a single target that increases STR, DEX and INT. (The damage dealing stats)
+function script GD_atkboost {
+ .@lv=getarg(0, @skillLv);
+ .@t$=getarg(1, "filter_sameguild");
+ // range, time, SC, BL, power, filter
+ areasc(4+.@lv, 40000+(5000*.@lv), SC_BLESSING, BL_PC, .@lv*2, .@t$);
+ return;
+}
+
+
+// GD_atkboost2 ( lv )
+// Blesses a single target's weapon to increase its attack power
+function script GD_atkboost2 {
+ .@lv=getarg(0, @skillLv);
+ .@t$=getarg(1, "filter_sameguild");
+ // range, time, SC, BL, power, filter
+ areasc(4+.@lv, 40000+(5000*.@lv), SC_IMPOSITIO, BL_PC, 5+(5*.@lv), .@t$);
+ return;
+}
+
+
+// GD_critboost ( lv )
+// Boost the critical hit rate
+function script GD_critboost {
+ .@lv=getarg(0, @skillLv);
+ .@t$=getarg(1, "filter_sameguild");
+ // range, time, SC, BL, 1, power, filter
+ areasc(1+.@lv, 30000+(5000*.@lv), SC_FORTUNE, BL_PC, 3*.@lv, .@t$);
+ return;
+}
+
+
+// GD_autorevive ( lv )
+// Automatically revive guild mates once they die - VERY IMPORTANT SKILL
+// Will not stick on you - if you die, YOU ARE DEAD.
+// After being resurrected Kaizel is dispelled but you have a 2 seconds lasting Kyrie Eleison (Absolute shield) buff.
+function script GD_autorevive {
+ .@lv=getarg(0, @skillLv);
+ // range, time, SC, BL, 1, power, filter
+ areasc(2+.@lv, 25000+10000*.@lv, SC_KAIZEL, BL_PC, 10*.@lv, "filter_sameguildnotyou");
+ return;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// SK_maximizepower ( lv )
+// Damage always at max
+function script SK_maximizepower {
+ .@lv=getarg(0, @skillLv);
+ // range, time, SC, BL, power, filter
+ areasc(1+.@lv, 60000*.@lv, SC_MAXIMIZEPOWER, BL_PC, 1, "filter_sameguildorparty");
+ return;
+}
+
+
+// SK_spregen ( lv )
+// Temporarily doubles the SP Recovery rate of the user.
+function script SK_spregen {
+ .@lv=getarg(0, @skillLv);
+ // range, time, SC, BL, 1, power, filter
+ areasc(.@lv, 20000+(10000*.@lv), SC_MAGNIFICAT, BL_PC, 1, "filter_sameguildorparty");
+ return;
+}
+
diff --git a/npc/magic/mpregen.txt b/npc/magic/mpregen.txt
new file mode 100644
index 0000000..dc8ad2b
--- /dev/null
+++ b/npc/magic/mpregen.txt
@@ -0,0 +1,57 @@
+// TMW2 script
+// Author: Jesusalva <jesusalva@tmw2.org>
+//
+// Magic Script: -
+//
+// mpgen to make mana from HP
+
+function script SK_mpregen {
+ // Convert HP to mana (20% HP - 1) (To prevent 5 casts from killing)
+ .@basehp=(MaxHp/5)-1;
+ // How much MP is that worth?
+ // Well, 400HP:120MP so base formula is 4:1
+ // Let's have a 50% penalty, so, 6:1
+ .@lv=getskilllv(TMW2_MPREGEN);
+ .@ratio=max(40, 60-.@lv);
+ .@mpheal=.@basehp*.@ratio/100;
+ heal -.@basehp, .@mpheal;
+ // Temporarily block healing and regeneration skills
+ SC_Bonus(1+.@lv, SC_HALT_REGENERATION, 1);
+ return;
+}
+
+function script SK_transfermp {
+ .@mp = Sp;
+ .@me = getcharid(3);
+ .@tg = getarg(0, @skillTarget);
+ detachrid();
+ attachrid(.@tg);
+ .@mo = MaxSp - Sp;
+ // Heal will be the smallest from:
+ // Current MP or Missing Mp
+ .@vl = min(.@mo, .@mp);
+ Sp += .@vl;
+ detachrid();
+ attachrid(.@me);
+ Sp -= .@vl;
+ return;
+}
+
+/*
+- script sk#mpgen 32767,{
+ end;
+
+OnCall:
+ // Must have magic
+ if (!MAGIC_LVL)
+ end;
+
+ unitskilluseid(getcharid(3), TMW2_MPREGEN, 1, getcharid(3));
+ end;
+
+OnInit:
+ bindatcmd "sk-mpgen", "sk#mpgen::OnCall", 0, 100, 0;
+ end;
+}
+*/
+
diff --git a/npc/magic/ovh.txt b/npc/magic/ovh.txt
new file mode 100644
index 0000000..476be29
--- /dev/null
+++ b/npc/magic/ovh.txt
@@ -0,0 +1,13 @@
+// TMW2 script
+// Author: Jesusalva <admin@tmw2.org>
+//
+// Magic Script: TMW2_OVHFIRE
+//
+// Burns down the user to a toast, but they'll survive, because they are awesome.
+
+function script SK_OVHFire {
+ specialeffect FX_HELLBLAZE, AREA, getcharid(3);
+ return;
+}
+
+
diff --git a/npc/magic/parum.txt b/npc/magic/parum.txt
new file mode 100644
index 0000000..3fa73bc
--- /dev/null
+++ b/npc/magic/parum.txt
@@ -0,0 +1,56 @@
+// TMW2 script
+// Author: Jesusalva <admin@tmw2.org>
+//
+// Magic Script: TMW2_PARUM
+//
+// Attempts to transmutate Raw Logs.
+// May create arrows, Mouboo Figurines, Warped Logs.
+// With enough ManaExp may create WoodenLog.
+// Is not powerful enough to create overly complex stuff like Wooden Sword, Wooden Shield or Wooden Bow
+// Final item is random
+// TODO: Using too much transmutation magic may have dire consequences! Like, uh, transmutating your head!
+// Nah, it is probably just propaganda... I hope. ¬.¬
+
+function script SK_parum {
+ // Create the stuff based on MAGIC_EXP
+ .@r=rand(1,41);
+ // Each 2 mexp reduces chance to get a fail
+ if (.@r < 42-(MAGIC_EXP/2)) {
+ getitem WarpedLog, 1;
+ } else {
+ // Proeficiency makes more likely to finish it
+ if (.@r > 30-abizit())
+ getitem MoubooFigurine, 1;
+ else if (.@r > 20-abizit() && MAGIC_EXP > 82)
+ getitem WoodenLog, 1;
+ else
+ getitem Arrow, .@r;
+ }
+ // I know, the code is not very sane. A number from 0 to 40 is cast.
+ // You will get lots of useless Warped Logs until you have 82 MExp.
+ // If you do not get a Warped Log, you have 25% chances of getting the
+ // Mouboo figurine. The other will be arrows, unless you hit the 82 MExp value
+ // which will add 25% chances to get a Wooden Log too. These values are estimate.
+
+ // Get a few mana experience points (this is NOT used by Mana Stone)
+ GetManaExp(TMW2_PARUM, rand2(1,3));
+ return;
+}
+
+- script sk#parum 32767,{
+ end;
+
+/*
+OnFriendlyDeath:
+ emote 4;
+ end;
+*/
+
+OnCall:
+ // Deprecated
+ dispbottom l("The usage of @sk-commands was deprecated");
+ end;
+
+OnInit:
+ end;
+}
diff --git a/npc/magic/plantkingdom.txt b/npc/magic/plantkingdom.txt
new file mode 100644
index 0000000..d6765fb
--- /dev/null
+++ b/npc/magic/plantkingdom.txt
@@ -0,0 +1,62 @@
+// TMW2 script
+// Author: Jesusalva <admin@tmw2.org>
+//
+// Magic Script: TMW2_PLANTKINGDOM
+//
+// Summons plants
+
+- script sk#plantkingdom 32767,{
+ end;
+
+OnCall:
+ // Blocked from summoning magic
+ if (alignment() < 0)
+ return;
+
+ // Other requeriments: 2x Root
+ if (countitem(Root) < 2) {
+ dispbottom l("You need 2x @@ to cast this skill.", getitemlink(Root));
+ end;
+ }
+
+ // Check cooldown
+ if (@plantkingdom_at > gettimetick(2)) {
+ dispbottom l("Skill is in cooldown for @@.", FuzzyTime(@plantkingdom_at));
+ end;
+ }
+
+ // Setup
+ @sk=TMW2_PLANTKINGDOM;
+ @mp=30;
+ @amp=3;
+
+ // Check if you have mana to cast
+ // MagicCheck(SkillID, Mana{, MP per level})
+ if (!MagicCheck(@sk, @mp, @amp))
+ end;
+
+ // Destroy reagents
+ delitem Root, 2;
+
+ // set cooldown
+ @plantkingdom_at=gettimetick(2);
+ @plantkingdom_at=@plantkingdom_at+54;
+
+ // As usual, magic profeciency affects
+ if (rand(1,6) < abizit()+1) {
+ // Summon Magic
+ // SummonMagic(SkillID, MobID{, SkillLevelPerMob=2{, Level Override}})
+ SummonMagic(@sk, any(ShadowPlant, AlizarinPlant, CobaltPlant, MauvePlant, GambogePlant, PlushroomField, ChagashroomField, MananaTree, CrocoTree, AlizarinPlant, CobaltPlant, MauvePlant, GambogePlant), 2, MAGIC_LVL+getskilllv(@sk)-1);
+ } else {
+ dispbottom l("The spell fails!");
+ }
+
+ // Get 3~4 mana experience point (this is NOT used by Mana Stone)
+ GetManaExp(@sk, rand2(3,4));
+
+ end;
+
+OnInit:
+ bindatcmd "sk-plantkingdom", "sk#plantkingdom::OnCall", 0, 100, 0;
+ end;
+}
diff --git a/npc/magic/revive.txt b/npc/magic/revive.txt
new file mode 100644
index 0000000..96620c7
--- /dev/null
+++ b/npc/magic/revive.txt
@@ -0,0 +1,52 @@
+// TMW2 script
+// Author: Jesusalva <admin@tmw2.org>
+//
+// Magic Script: TMW2_REVIVE
+// Magic Script: TMW2_RESSURECT
+//
+// Skill to revive players
+// TODO: Reimburse EXP?
+
+// revive target (level, target)
+function script SK_resurrect {
+ .@lv=getarg(0);
+ .@tg=getarg(1);
+ .@me=getcharid(3);
+ attachrid(.@tg);
+ if (ispcdead()) {
+ recovery(.@tg);
+ percentheal 100, 0;
+ percentheal -(100 - 10 * .@lv), 0;
+ }
+ detachrid();
+ attachrid(.@me);
+ return;
+}
+
+// revives getarg(0)
+function script SK_revive {
+ .@target=getarg(0);
+ if (getunittype(.@target) != UNITTYPE_PC) {
+ dispbottom l("This skill can only be used on players!");
+ return;
+ }
+ recovery(.@target);
+ return;
+}
+
+// revive in getarg(0) range from caster
+function script SK_ressurect {
+ .@r=getarg(0);
+ getmapxy(.@m$, .@x, .@y, 0);
+ recovery(.@m$, .@x-.@r, .@y-.@r, .@x+.@r, .@y+.@r);
+ return;
+}
+
+// revives the whole map [ULTIMATE]
+function script SK_sanctum {
+ BaseLevel-=1; // Maybe EXP Gain -300% for a hour?
+ recovery(getmap());
+ //maptimer AUTOREVIVE 15 minutes
+ return;
+}
+
diff --git a/npc/magic/scrolls.txt b/npc/magic/scrolls.txt
new file mode 100644
index 0000000..6df45c4
--- /dev/null
+++ b/npc/magic/scrolls.txt
@@ -0,0 +1,36 @@
+// TMW2 Script
+// Author:
+// Jesusalva
+// Description:
+// Scroll System
+
+// SummonScroll(mob, life, {mob2, minlv})
+function script SummonScroll {
+ .@mob = getarg(0);
+ .@tim = getarg(1, 60);
+ .@mbb = getarg(2, 0);
+ .@blv = getarg(3, 0);
+
+ // Depending on alignment status, invoke superior form
+ if (alignment_cansummon() && alignment() > 1 && BaseLevel > .@blv && .@mbb) {
+ .@mids = summon("Summoned Monster", .@mbb, .@tim);
+ } else {
+ .@mids = summon("Summoned Monster", .@mob, .@tim);
+ }
+
+ // Reconfigure monster modes
+ .@opt=getunitdata(.@mids, UDT_MODE);
+ // Disable looting
+ if (.@opt & MD_LOOTER)
+ .@opt=.@opt^MD_LOOTER;
+ // All summons can suffer knockback
+ if (.@opt & MD_NOKNOCKBACK)
+ .@opt=.@opt^MD_NOKNOCKBACK;
+ // Strip summons from BOSS mode and immunity
+ if (.@opt & MD_BOSS)
+ .@opt=.@opt^MD_BOSS;
+ // Save new options
+ setunitdata(.@mids, UDT_MODE, .@opt);
+ return;
+}
+
diff --git a/npc/magic/study.txt b/npc/magic/study.txt
new file mode 100644
index 0000000..b747f8b
--- /dev/null
+++ b/npc/magic/study.txt
@@ -0,0 +1,48 @@
+// TMW2 script
+// Author: Jesusalva <admin@tmw2.org>
+//
+// Magic Script: TMW2_STUDY
+//
+// Skill to study a target monster
+// Will report the monster exact current stats, and is part of research
+
+function script SK_study {
+ .@mobGD=getarg(0);
+ if (.@mobGD <= 0)
+ return;
+
+ // We want monsters
+ if (getunittype(.@mobGD) != UNITTYPE_MOB) {
+ dispbottom l("This skill can only be used on monsters!");
+ return;
+ }
+ .@mobID=getunitdata(.@mobGD, UDT_CLASS);
+
+ // Research Points
+ if (array_rfind(@study, .@mobGD) < 0) {
+ .@mult=max(1, 11-getskilllv(TMW2_STUDY));
+ .@rp=getmonsterinfo(.@mobID, MOB_LV)/.@mult;
+ array_push(@study, .@mobGD);
+ if (.@rp) {
+ MAGIC_RP+=.@rp;
+ dispbottom l("Research Points +%d", .@rp);
+ }
+ }
+
+ // Report
+ dispbottom l("%s - %s/%s HP, %s/%s MP",
+ getmonsterinfo(.@mobID, MOB_NAME),
+ fnum(getunitdata(.@mobGD, UDT_HP)),
+ fnum(getunitdata(.@mobGD, UDT_MAXHP)),
+ fnum(getunitdata(.@mobGD, UDT_SP)),
+ fnum(getunitdata(.@mobGD, UDT_MAXSP)));
+
+ // Truncate.
+ // We're saving the GID so it must be "big enough"
+ // But not too big so rfind() is not expensive
+ if (getarraysize(@study) > 99) {
+ deletearray(@study, 30);
+ }
+ return;
+}
+
diff --git a/npc/magic/transmigration.txt b/npc/magic/transmigration.txt
new file mode 100644
index 0000000..f16f854
--- /dev/null
+++ b/npc/magic/transmigration.txt
@@ -0,0 +1,330 @@
+// TMW2 script
+// Author: Jesusalva <admin@tmw2.org>
+//
+// Magic Script: TMW2_TRANSMIGRATION
+//
+// Attempts to make stuff from other stuff
+// This is actually referred as transmutation in human-readable forms, and
+// transmigration in scripts.
+
+- script sk#mkpot 32767,{
+ end;
+OnCall:
+ // Check cooldown
+ if (@mkpot_at > gettimetick(2)) {
+ dispbottom l("Skill is in cooldown for @@.", FuzzyTime(@mkpot_at));
+ end;
+ }
+
+ // Check requisites
+ if (!MagicCheck(TMW2_TRANSMIGRATION, 215, -5))
+ end;
+
+ .@q=getq(General_Auldsbel);
+
+ do {
+ mes ".:: " + l("Transmutation Skill") + " ::.";
+ mesc l("What will you transmute today?");
+ mes "";
+ menuint
+ rif(@transmemo, l("Repeat ")+getitemname(@transmemo)), @transmemo,
+ l("Crazy Rum"), CrazyRum,
+ l("Coal"), 9901, // 9901 cheat code
+ l("Mouboo Figurine"), MoubooFigurine,
+ rif(.@q >= 9, l("Downgrade Snake Skin")), SnakeSkin,
+ rif(.@q >= 9, l("Downgrade Snake Egg")), SnakeEgg,
+ rif(.@q >= 9, l("Downgrade Snake Tongue")), SnakeTongue,
+ rif(.@q >= 7, l("Downgrade Scorpion Stinger")), ScorpionStinger,
+ rif(.@q >= 7, l("Downgrade Scorpion Claw")), ScorpionClaw,
+ l("Downgrade Ore"), IronOre;
+
+ mes "";
+ .@itemid=(@menuret == 9901 ? Coal : @menuret);
+ mesc l("Transmutating @@ will require:", getitemlink(@menuret));
+
+ // Requeriments listing
+ switch (@menuret) {
+ case CrazyRum:
+ mesc l("* @@/@@ @@", countitem(Plushroom), 10, getitemlink(Plushroom));
+ mesc l("* @@/@@ @@", countitem(Milk), 3, getitemlink(Milk));
+ break;
+ case 9901: // This is coal
+ mesc l("* @@/@@ @@", countitem(WoodenLog), 5, getitemlink(WoodenLog));
+ break;
+ case MoubooFigurine:
+ mesc l("* @@/@@ @@", countitem(WoodenLog), 1, getitemlink(WoodenLog));
+ break;
+ case SnakeSkin:
+ menuint
+ l("Black Mamba Skin -> Mountain Snake Skin"), MountainSnakeSkin,
+ l("Mountain Snake Skin -> Snake Skin"), SnakeSkin,
+ l("Snake Skin -> Cave Snake Skin"), CaveSnakeSkin,
+ l("Cancel");
+ break;
+ case SnakeEgg:
+ menuint
+ l("Black Mamba Egg -> Mountain Snake Egg"), MountainSnakeEgg,
+ l("Mountain Snake Egg -> Snake Egg"), SnakeEgg,
+ l("Snake Egg -> Cave Snake Egg"), CaveSnakeEgg,
+ l("Cancel");
+ break;
+ case SnakeTongue:
+ menuint
+ l("Black Mamba Tongue -> Mountain Snake Tongue"), MountainSnakeTongue,
+ l("Mountain Snake Tongue -> Snake Tongue"), SnakeTongue,
+ l("Snake Tongue -> Cave Snake Tongue"), CaveSnakeTongue,
+ l("Cancel");
+ break;
+ case ScorpionStinger:
+ menuint
+ l("Black Scorpion Stinger -> Red Scorpion Stinger"), RedScorpionStinger,
+ l("Red Scorpion Stinger -> Scorpion Stinger"), ScorpionStinger,
+ l("Cancel");
+ break;
+ case ScorpionClaw:
+ menuint
+ l("Golden Scorpion Claw -> Black Scorpion Claw"), BlackScorpionClaw,
+ l("Black Scorpion Claw -> Red Scorpion Claw"), RedScorpionClaw,
+ l("Red Scorpion Claw -> Scorpion Claw"), ScorpionClaw,
+ l("Cancel");
+ break;
+ case IronOre:
+ menuint
+ l("Platinum Ore -> Iridium Ore"), IridiumOre,
+ l("Iridium Ore -> Titanium Ore"), TitaniumOre,
+ l("Titanium Ore -> Lead Ore"), LeadOre,
+ l("Lead Ore -> Tin Ore"), TinOre,
+ l("Tin Ore -> Gold Ore"), GoldOre,
+ l("Gold Ore -> Silver Ore"), SilverOre,
+ l("Silver Ore -> Copper Ore"), CopperOre,
+ l("Copper Ore -> Iron Ore"), IronOre,
+ l("Iron Ore -> Coal"), Coal,
+ l("Cancel"), 0;
+ break;
+ default:
+ Exception("ERROR, INVALID TRANSMIGRATION OPTION", RB_DEFAULT|RB_SPEECH); @menuret=0; break;
+ }
+ // Confirmation
+ if (@menuret) {
+ next;
+ mesc l("Transmute?!");
+ .@me=@menuret;
+ if (askyesno() == ASK_NO)
+ @menuret=0;
+ else
+ @menuret=.@me;
+ }
+ } while (!@menuret);
+
+ // Close the dialog
+ closeclientdialog;
+
+ // Check and Consume the reagents
+ switch (@menuret) {
+ case CrazyRum:
+ if (!transcheck(Plushroom, 10, Milk, 3)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case MoubooFigurine:
+ if (!transcheck(WoodenLog, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case 9901: // Coal cheat code
+ if (!transcheck(WoodenLog, 5)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ .@me=WoodenLog;
+ @menuret=Coal;
+ break;
+ // Snake Skin Chain
+ case MountainSnakeSkin:
+ if (!transcheck(BlackMambaSkin, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case SnakeSkin:
+ if (!transcheck(MountainSnakeSkin, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case CaveSnakeSkin:
+ if (!transcheck(SnakeSkin, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ // Snake Egg Chain
+ case MountainSnakeEgg:
+ if (!transcheck(BlackMambaEgg, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case SnakeEgg:
+ if (!transcheck(MountainSnakeEgg, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case CaveSnakeEgg:
+ if (!transcheck(SnakeEgg, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ // Snake Tongue Chain
+ case MountainSnakeTongue:
+ if (!transcheck(BlackMambaTongue, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case SnakeTongue:
+ if (!transcheck(MountainSnakeTongue, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case CaveSnakeTongue:
+ if (!transcheck(SnakeTongue, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ // Scorpion Stinger Chain
+ case RedScorpionStinger:
+ if (!transcheck(BlackScorpionStinger, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case ScorpionStinger:
+ if (!transcheck(RedScorpionStinger, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ // Scorpion Claw Chain
+ case BlackScorpionClaw:
+ if (!transcheck(GoldenScorpionClaw, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case RedScorpionClaw:
+ if (!transcheck(BlackScorpionClaw, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case ScorpionClaw:
+ if (!transcheck(RedScorpionClaw, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ // Ore Chain (the biggest one)
+ case IridiumOre:
+ if (!transcheck(PlatinumOre, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case TitaniumOre:
+ if (!transcheck(IridiumOre, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case LeadOre:
+ if (!transcheck(TitaniumOre, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case TinOre:
+ if (!transcheck(LeadOre, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case GoldOre:
+ if (!transcheck(TinOre, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case SilverOre:
+ if (!transcheck(GoldOre, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case CopperOre:
+ if (!transcheck(SilverOre, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case IronOre:
+ if (!transcheck(CopperOre, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+ case Coal:
+ if (!transcheck(IronOre, 1)) {
+ dispbottom l("Not enough items!");
+ end;
+ }
+ break;
+
+ default:
+ Exception("ERROR, INVALID TRANSMIGRATION REAGENTS", RB_DEFAULT|RB_SPEECH|RB_ISFATAL); break;
+ }
+
+ // Do the roll from 1 to 100
+ // Base success chance is 0%
+ // Each abizit() point gives you 18% success rate (max 90%)
+ // Each skill level gives you 1% success rate (max 10%)
+ .@r=rand2(1, 100)-abizit()*18-getskilllv(TMW2_TRANSMIGRATION);
+
+ // Backfire chance: 30%
+ if (.@r >= 70) {
+ dispbottom l("The spell backfires!");
+ percentheal -(rand2(5, 15)), 0;
+ // Chance for nothing to happen
+ } else if (.@r >= 30) {
+ dispbottom l("Your reagents vanish into emptiness!");
+ // Chance for you getting a junk item
+ } else if (.@r > 0) {
+ dispbottom l("Your spell takes a mind of its own and shapes in something else!");
+ getitem any(WarpedLog, .@me), 1;
+ // You were successful
+ } else {
+ dispbottom l("*plim*");
+ getitem @menuret, 1;
+ }
+
+ // Store to memory
+ @transmemo=.@me;
+
+ // set cooldown
+ @mkpot_at=gettimetick(2);
+ @mkpot_at=@mkpot_at+6;
+
+ // Get a few mana experience points (this is NOT used by Mana Stone)
+ GetManaExp(TMW2_TRANSMIGRATION, rand2(4,9));
+ end;
+
+OnInit:
+ bindatcmd "sk-trans", "sk#mkpot::OnCall", 0, 100, 0;
+ end;
+}