// TMW2 script // Author: Jesusalva // // Magic Script Core Functions // // Used for our pseudo-magic. // These are only helpers, you can add more restrictions and effects freely. // Important Variables: // MAGIC_EXP // Current mana magic experience // LAST_SKILL // Last Mana Skill used // MAGIC_LVL // Maximum tier of usable magic, capped by Mana Stone // MAGIC_SUBCLASS // Bitmasked magic subclass. // AdjustSpellpower(power=100, {target=@skillTarget{, type=HARM_MAGI}}) function script AdjustSpellpower { .@power=getarg(0, 100); .@target=getarg(1, @skillTarget); .@type=getarg(2, HARM_MAGI); .@src=getcharid(3); .@dmg=calcdmg(.@src, .@target, .@type); // Abizit Influence (80%~130% at best, worst shot at perfect ctrl is 105%) .@dmg = .@dmg * (80 + abizit() * rand2(5,10)) / 100; .@dmg = .@dmg * .@power / 100; return .@dmg; } // An alias for simplification // AdjustAttackpower(power=100, {target=@skillTarget{, type=HARM_PHYS}}) function script AdjustAttackpower { .@power=getarg(0, 100); .@target=getarg(1, @skillTarget); .@type=getarg(2, HARM_PHYS); return AdjustSpellpower(.@power, .@target, .@type); } // SkillID, EXP Points function script GetManaExp { .@sk=getarg(0); .@pt=getarg(1); .@bonus=rand2(0,getskilllv(TMW2_SAGE)*3/2); if (LAST_SKILL == .@sk) { .@pt=limit(0, (.@pt+.@bonus)/3, 1); .@bonus=0; } LAST_SKILL=.@sk; MAGIC_EXP=MAGIC_EXP+.@pt+.@bonus; return; } // SkillID, Mana{, MP per level} function script MagicCheck { // PRE EXECUTION // Load Variables .@sk=getarg(0); .@mp=getarg(1); .@amp=getarg(2,0); // Check Skill if (getskilllv(.@sk) < 1) return 0; // Load mana cost .@mp=.@mp+getskilllv(.@sk)*.@amp-.@amp; // Check mana if (readparam(Sp) < .@mp) { dispbottom l("Insufficient mana: @@/@@.", readparam(Sp), .@mp); return 0; } // Apply mana cost heal 0, 0-.@mp; return 1; } // SkillID, MobID{, SkillLevelPerMob=2{, Level Override}} function script SummonMagic { .@sk=getarg(0); .@id=getarg(1); .@adj=getarg(2,2); .@lv=getarg(3,getskilllv(.@sk)); if (.@adj < 1) { debugmes "\033[31mInvalid MobPerSkillLevel for SummonMagic (.@adj): "+.@adj+"\033[0m"; dispbottom l("Invalid parameter specified, blame saulc."); end; } // Cause effect // Summoned monsters live from 45 to 60 seconds, and each skill levels grants 10s extra life // The 35~50 is not a defect, remember skill starts at level 1... // PS. Abizit gives 3s per level, and +1 HP per level for (.@i = 0; .@i < (.@lv+(.@adj-1))/.@adj; .@i++) { .@lifetime=rand(35,50)+.@lv*10; // Abizit makes lifetime vary (like AdjustSpellpower) .@lifetime = .@lifetime * (80 + abizit() * rand2(5,10)) / 100; .@mids=summon("Summoned Monster", .@id, .@lifetime); .@bhp=getunitdata(.@mids, UDT_MAXHP); .@lvx=max(0, (.@lv-1)*.@bhp/50); // Abizit makes bonus HP vary (like AdjustSpellpower) .@lvx = .@lvx * (80 + abizit() * rand2(5,10)) / 100; setunitdata(.@mids, UDT_MAXHP, .@bhp+.@lvx); setunitdata(.@mids, UDT_HP, .@bhp+.@lvx); } dispbottom l("All monsters summoned!"); return; } // areaharm(target, range, DMG, {type, element, filter, bl}) // Defaults to HARM_MISC, Ele_Neutral, filter filter_hostile and all BLs // Valid BL: BL_MOB | BL_PC | BL_HOM | BL_MER // Do not use: NPC, PET, ELEM // Range centers on caster (player), implement and use areaharm2 elsewhere function script areaharm { .@t=getarg(0); .@r=getarg(1); .@d=getarg(2); .@h=getarg(3, HARM_MISC); .@e=getarg(4, Ele_Neutral); .@f$=getarg(5, "filter_hostile"); .@b=getarg(6, BL_PC | BL_MOB | BL_MER | BL_HOM); // FIXME: Retrieve from .@t not from "0"/caster //getmapxy(.@m$, .@x, .@y, 0); // Ideally we would have @skillTargetX/Y and not use getmap() but meh .@m$=getmap(); getunitdata(.@t, UDT_MAPIDXY, .@loc); .@x=.@loc[1]; .@y=.@loc[2]; debugmes("Loc %s (%d, %d) - Real loc %s", .@m$, .@x, .@y, str(.@loc[0])); .@c=getunits(.@b, .@mbs, false, .@m$, .@x-.@r, .@y-.@r, .@x+.@r, .@y+.@r); debugmes "Begin"; for (.@i = 0; .@i < .@c; .@i++) { // Filtering if (!callfunc(.@f$, .@mbs[.@i])) continue; debugmes "Target %d", .@mbs[.@i]; harm(.@mbs[.@i], .@d, .@t, .@e); debugmes "Harmed"; specialeffect(FX_ATTACK, AREA, .@mbs[.@i]); debugmes "FX'ed"; } debugmes "Done"; return; } // mescordialog(text, color, {dialog=1}) function script mescordialog { if (getarg(2, true)) mesc getarg(0), getarg(1); else dispbottom col(getarg(0), getarg(1)); return; } // ShowAbizit({dialog=1}) function script ShowAbizit { .@dial=getarg(0, true); if (.@dial) mesn l("Current Magic Control"); .@val=MAGIC_EXP+rand(-MAGIC_LVL*5, MAGIC_LVL*5); .@base=((MAGIC_LVL*2)**3); if (.@val > .@base*5) mescordialog l("You are perfectly in control of your magic."), 3, .@dial; else if (.@val > .@base*4) mescordialog l("You are mostly in control of your magic."), 2, .@dial; else if (.@val > .@base*3) mescordialog l("You are somewhat in control of your magic."), 4, .@dial; else if (.@val > .@base*2) mescordialog l("Your magic is more powerful than you, but you can control."), 7, .@dial; else if (.@val > .@base) mescordialog l("You still are overwhelmed by your magic."), 6, .@dial; else mescordialog l("You are completly overwhelmed by your magic."), 1, .@dial; return; } // SK_summon(ID, amount, mexp) function script SK_summon { .@mob=getarg(0); .@amt=getarg(1); .@mex=getarg(2); if ($@GM_OVERRIDE || debug) debugmes "Skill "+@skillId+" Lv "+@skillLv; // Blocked from summoning magic if (alignment() < 0 && !isequippedcnt(AegisShield)) return; if (rand2(5) < abizit()) { // Summon Magic (with magic level bonus) SummonMagic(@skillId, .@mob, .@amt, MAGIC_LVL+@skillLv-1, @skillLv); } else { dispbottom l("The spell fails!"); } // Get a single mana experience point (this is NOT used by Mana Stone) GetManaExp(@sk, .@mex); return; } ///////////////////////////////////////// // RegisterMagic(MSP, Skill, MaxLv, Item, Amount, Class, Cost, {PreReq, PostReq}) function script RegisterMagic { .@msp=getarg(0); .@ski=getarg(1); .@max=getarg(2); .@ite=getarg(3); .@amo=getarg(4); .@cla=getarg(5); .@cos=getarg(6); .@pre=getarg(7, false); .@pos=getarg(8, false); $@MSK_MSPCOST[.@ski]=.@msp; $@MSK_MAXLV[.@ski]=.@max; $@MSK_ITEM[.@ski]=.@ite; $@MSK_AMOUNT[.@ski]=.@amo; $@MSK_COST[.@ski]=.@cos; $@MSK_PREREQ[.@ski]=.@pre; $@MSK_POSTREQ[.@ski]=.@pos; array_push($@MSK_CLASS[.@cla], .@ski); return; } - script Magic Load NPC_HIDDEN,{ OnInit: /* RegisterMagic(MSP, Skill, MaxLv, Item, Amount, Class, Cost, {PreReq, PostReq}) */ //////////////////////// Scholarship // Mana Wisdom RegisterMagic(1, TMW2_SAGE, 5, SpellBookPage, 1, CLASS_SCHOLARSHIP, 0); // Accumulate Power RegisterMagic(1, HW_MAGICPOWER, 5, SpellBookPage, 1, CLASS_SCHOLARSHIP, 0); // Windwalker RegisterMagic(3, SN_WINDWALK, 3, SpellBookPage, 1, CLASS_SCHOLARSHIP, 0); // Last Standing Man RegisterMagic(3, CR_TRUST, 2, SpellBookPage, 1, CLASS_SCHOLARSHIP, 0); /* Skillchain */ // Healing RegisterMagic(1, AL_HEAL, 4, SpellBookPage, 1, CLASS_SCHOLARSHIP, 0, false, AB_HIGHNESSHEAL); // High Healing RegisterMagic(2, AB_HIGHNESSHEAL, 1, SpellBookPage, 1, CLASS_SCHOLARSHIP, 0, AL_HEAL, false); /* Skillchain */ // Provoke RegisterMagic(1, SM_PROVOKE, 1, SpellBookPage, 1, CLASS_SCHOLARSHIP, 0, false, EVOL_AREA_PROVOKE); // Mass Provoke RegisterMagic(2, EVOL_AREA_PROVOKE, 10, SpellBookPage, 1, CLASS_SCHOLARSHIP, 0, SM_PROVOKE, false); //////////////////////// Physical Sciences // Ground Strike RegisterMagic(2, ASC_METEORASSAULT, 3, FluoPowder, 3, CLASS_PHYSICAL, 0); /* Skillchain */ // Falkon Punch RegisterMagic(1, SM_BASH, 10, FluoPowder, 3, CLASS_PHYSICAL, 0, false, MC_MAMMONITE); // Supreme Attack RegisterMagic(1, MC_MAMMONITE, 10, FluoPowder, 3, CLASS_PHYSICAL, 0, SM_BASH, KN_AUTOCOUNTER); // Counter Attack RegisterMagic(2, KN_AUTOCOUNTER, 5, FluoPowder, 3, CLASS_PHYSICAL, 0, MC_MAMMONITE, false); /* Skillchain */ // Arrow Shower RegisterMagic(3, AC_SHOWER, 10, FluoPowder, 3, CLASS_PHYSICAL, 0, false, SN_SHARPSHOOTING); // Sharpshooter RegisterMagic(3, SN_SHARPSHOOTING, 1, FluoPowder, 3, CLASS_PHYSICAL, 0, AC_SHOWER, false); //////////////////////// Destructive Magic //////////////////////// Trickmaster //////////////////////// Other: Summonning //////////////////////// Other: Misc // Chargd Shot RegisterMagic(0, AC_CHARGEARROW, 1, CLASS_OTHER, NPCEyes, 1, 0); end; }