diff options
Diffstat (limited to 'npc')
-rw-r--r-- | npc/functions/main.txt | 5 | ||||
-rw-r--r-- | npc/magic/config.txt | 264 | ||||
-rw-r--r-- | npc/scripts.conf | 3 |
3 files changed, 271 insertions, 1 deletions
diff --git a/npc/functions/main.txt b/npc/functions/main.txt index eac02526..8dd7c95f 100644 --- a/npc/functions/main.txt +++ b/npc/functions/main.txt @@ -613,3 +613,8 @@ function script iscollision { return checknpccell(getarg(0), getarg(1), getarg(2), cell_chkpass); } +function script readparam2 { + readbattleparam(getcharid(3), getarg(0)); + return; +} + diff --git a/npc/magic/config.txt b/npc/magic/config.txt new file mode 100644 index 00000000..0ea9d3b7 --- /dev/null +++ b/npc/magic/config.txt @@ -0,0 +1,264 @@ +// TMW2 script +// Author: Jesusalva <admin@tmw2.org> +// +// Magic Script Core Functions +// +// Used for our pseudo-magic. +// These are only helpers, you can add more restrictions and effects freely. +// FIXME +function script abizit { + return 0; +} + +// 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); + + // Prevents a possible glitch + if (.@target < 1 || .@target == getcharid(3)) + .@target=0; + + // Calculation FIX + if (.@type == HARM_MAGI) { + .@power+=(readparam2(bInt)/2); + .@dmg=rand2( + getunitdata(getcharid(3), UDT_MATKMIN), + getunitdata(getcharid(3), UDT_MATKMAX)); + // Apply defense + if (.@target) + .@dmg=max(0, .@dmg-getunitdata(.@target, UDT_MDEF)); + } else if (.@type == HARM_PHYS) { + .@power+=(readparam2(bStr)/2); + .@dmg=rand2( + getunitdata(getcharid(3), UDT_ATKMIN), + getunitdata(getcharid(3), UDT_ATKMAX)); + // Apply defense + if (.@target) + .@dmg=max(0, .@dmg-getunitdata(.@target, UDT_DEF)); + } else { + .@dmg = .@power; .@power = 100; + } + // 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 { + // FIXME + .@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; + } else { + // Update skill memory + LAST_SKILL[4]=LAST_SKILL[3]; + LAST_SKILL[3]=LAST_SKILL[2]; + LAST_SKILL[2]=LAST_SKILL[1]; + LAST_SKILL[1]=LAST_SKILL[0]; + LAST_SKILL[0]=.@sk; + MAGIC_RP+=1; + // Magic RP is gained by switching skills often + } + + // Update Magic EXP + MAGIC_EXP=MAGIC_EXP+.@pt+.@bonus; + return; +} + + +// 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 makes a variation from 80% to 130% of official values + for (.@i = 0; .@i < (.@lv+(.@adj-1))/.@adj; .@i++) { + .@lifetime=rand2(35,50)+.@lv*10; + // Abizit makes lifetime vary (like AdjustSpellpower) + .@lifetime = .@lifetime * (80 + abizit() * rand2(5,10)) / 100; + // Unfortunately this version does not returns the summoned monster GID + summon("Summoned Monster", .@id, .@lifetime); + /* + .@mids=summon("Summoned Monster", .@id, .@lifetime); + .@bhp=getunitdata(.@mids, UDT_MAXHP); + // Each skill level raises HP in 5% + .@lvx=.@bhp + max(0, (.@lv-1)*.@bhp/20); + // Abizit makes bonus HP vary (like AdjustSpellpower) + .@lvx = .@lvx * (80 + abizit() * rand2(5,10)) / 100; + setunitdata(.@mids, UDT_MAXHP, .@lvx); + setunitdata(.@mids, UDT_HP, .@lvx); + // 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); + */ + } + 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); + + getmapxy(.@m$, .@x, .@y, getunittype(.@t), .@t); + + .@c=getunits(.@b, .@mbs, false, .@m$, .@x-.@r, .@y-.@r, .@x+.@r, .@y+.@r); + for (.@i = 0; .@i < .@c; .@i++) { + // Filtering + if (!callfunc(.@f$, .@mbs[.@i])) + continue; + harm(.@mbs[.@i], .@d, .@t, .@e); + specialeffect(FX_ATTACK, AREA, .@mbs[.@i]); + // TODO: Handle MobPt to don't overload timer system? + } + return; +} + + +// rectharm(target, x, y, DMG, {type, element, filter, bl}) +// Same as areaharm() but causes a rectangle in (x,y) size, instead of a square +function script rectharm { + .@t=getarg(0); + .@rx=getarg(1); + .@ry=getarg(2); + .@d=getarg(3); + .@h=getarg(4, HARM_MISC); + .@e=getarg(5, Ele_Neutral); + .@f$=getarg(6, "filter_hostile"); + .@b=getarg(7, BL_PC | BL_MOB | BL_MER | BL_HOM); + + getmapxy(.@m$, .@x, .@y, getunittype(.@t), .@t); + + .@c=getunits(.@b, .@mbs, false, .@m$, .@x-.@rx, .@y-.@ry, .@x+.@rx, .@y+.@ry); + for (.@i = 0; .@i < .@c; .@i++) { + // Filtering + if (!callfunc(.@f$, .@mbs[.@i])) + continue; + harm(.@mbs[.@i], .@d, .@t, .@e); + specialeffect(FX_ATTACK, AREA, .@mbs[.@i]); + // TODO: Handle MobPt to don't overload timer system? + } + 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"); + + // FIXME + .@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; + + if (rand2(5) < abizit()) { + // Summon Magic (with magic level bonus) + SummonMagic(@skillId, .@mob, .@amt, MAGIC_LVL+@skillLv-1, @skillLv); + } else if (rand2(5) < abizit()) { + // Re-roll + dispbottom l("You cannot complete the casting correctly!"); + SummonMagic(@skillId, .@mob, 1, 1, 1); + } else if (abizit() <= 1 && any(true, false, false)) { + // Spell overwhelms you, causing it to be spawned as aggro vs you. (33%) + dispbottom l("The spell takes a mind of its own backfires!"); + getmapxy(.@m$, .@x, .@y, 0); + .@opo=monster(.@m$, .@x, .@y, "Failed summon", .@mob, 1); + unitattack(.@opo, getcharid(3)); + } else { + dispbottom l("The spell fails!"); + } + + // Get a single mana experience point (FIXME) + GetManaExp(@skillId, .@mex); + return; +} + +- script Magic Load NPC_HIDDEN,{ +OnInit: + end; +OnSkillInvoke: + end; +OnPCBonusEvent: + end; +} + diff --git a/npc/scripts.conf b/npc/scripts.conf index 7c1520e0..beed5f75 100644 --- a/npc/scripts.conf +++ b/npc/scripts.conf @@ -62,7 +62,8 @@ "npc/items/mirror.txt", "npc/items/rubber_bat.txt", -//@include "npc/magic/_import.txt", +//Magic +"npc/magic/config.txt", // Commands "npc/commands/debug-quest.txt", |