// TMW2 Script
// Author:
// Jesusalva
// Description:
// Magic Blackbox
// Contains the internals for Scripture skill.
/* Type dictionary:
0 = Do nothing
1 = areaharm (healing will multiply power by -1)
2 = areasc
4 = summon elemental
*/
033-2,49,27,0 script Grandmaster NPC_BLUESAGE,{
mesn;
mes l("In the Crossroads, magic works differently. Chants have a flexible structure and are awfully powerful.");
next;
mesn;
mes l("The basic structure, for example, is:");
mesc l("Great fire, destroy everything!"), 1;
next;
mesn;
mes l("The first word is the ##Bintensity##b: Meager, Violent, Great, Epic, Legendary.");
mes l("The second word is the ##Belement##b: magic, fire, water, sacrament, darkness, hocus.");
mes l("The third word is the ##Baction##b: destroy, manifest, heal, blind, curse, poison, neutralize.");
mes l("The fourth and last word is the ##Brange##b: me, here, around, everything, everywhere.");
//mesc l("The range is centered on... I'm not sure. I believe on you!");
next;
mesn;
mes l("The more powerful the chant is, the more mana is consumed. If you don't have enough mana, your health will also be drained. \"Manifest\" is a summoning magic, \"neutralize\" will temporarily stop monsters, and the others... should be self-evident.");
mes l("Sacrament is holy magic. Hocus is actually ethereal magic, with extremely limited uses. Magic is a neutral element. You cannot use nature magic, I'm not sure why, but monsters can - so consider the element you'll use carefully.");
close;
OnInit:
.distance=6;
end;
}
function script Crossroads_Magic {
// Respect SC_SILENCE
if (getstatus(SC_SILENCE)) return;
// Structure: "«Power» «Element», «Action» «Range»!"
.@msg$ = getarg(0);
explode(.@x$, .@msg$, " ");
// Not enough arguments
if (getarraysize(.@x$) != 4) return;
// Prepare the environment variables, including offset
.@o = 0; // Array Offset
.@Cost = 0; // MP Cost
.@PW = 20; // Power (in % of MATK)
.@RG = 0; // Range (circular tiles)
.@EL = 0; // Element
.@TY = 0; // Type uses a special logic
.@SC = 0; // Status Condition, if any
.@F$ = "filter_hostile"; // Skill Target
// Power word (optional)
.@mp = 10+(readparam2(bInt)*20);
.@w$ = .@x$[.@o];
if (.@w$ == "meager") {
.@PW += min(25, .@mp);
.@Cost += 25;
} else if (.@w$ == "violent") {
.@PW += min(50, .@mp);
.@Cost += 50;
} else if (.@w$ == "great") {
.@PW += min(75, .@mp);
.@Cost += 75;
} else if (.@w$ == "epic") {
.@PW += min(100, .@mp);
.@Cost += 100;
} else if (.@w$ == "legendary") {
.@PW += min(150, .@mp);
.@Cost += 150;
} else {
// Not a valid power, so not a valid magic
return;
}
.@o += 1;
// Element
.@w$ = .@x$[.@o];
if (.@w$ == "magic") {
.@EL = Ele_Neutral;
} else if (.@w$ == "water" ||
.@w$ == "ice") {
.@EL = Ele_Water;
} else if (.@w$ == "fire") {
.@EL = Ele_Fire;
} else if (.@w$ == "sacrament") {
.@EL = Ele_Holy;
} else if (.@w$ == "darkness") {
.@EL = Ele_Dark;
} else if (.@w$ == "hocus") {
.@EL = Ele_Ghost;
} else {
// Not a valid element, so not a valid magic
return;
}
.@o += 1;
// Action Verb
.@w$ = .@x$[.@o];
/* Damage Only */
if (.@w$ == "destroy" ||
.@w$ == "beat" ||
.@w$ == "eviscerate") {
.@TY = 1;
.@PW += rand2(3);
/* HP recovery */
} else if (
.@w$ == "heal" ||
.@w$ == "recover") {
.@PW *= -1;
.@TY = 1;
.@F$ = "filter_friendlynotme";
/* Damage + Ailment */
} else if (.@w$ == "blind") {
.@SC = SC_BLIND;
.@TY = 1 | 2;
.@Cost *= 2;
.@PW /= 2;
if (.@EL != Ele_Ghost) .@PW = .@PW * 4 / 5; // Bonus: Hocus
} else if (.@w$ == "curse") {
.@SC = SC_CURSE;
.@TY = 1 | 2;
.@Cost *= 2;
.@PW /= 2;
if (.@EL != Ele_Ghost) .@PW = .@PW * 4 / 5; // Bonus: Hocus
} else if (.@w$ == "poison") {
.@SC = SC_POISON;
.@TY = 1 | 2;
.@Cost *= 2;
.@PW /= 2;
if (.@EL != Ele_Ghost) .@PW = .@PW * 4 / 5; // Bonus: Hocus
} else if (.@w$ == "tranquilize" || .@w$ == "neutralize") {
.@SC = SC_SLEEP;
.@TY = 1 | 2;
.@Cost *= 2;
.@PW /= 2;
if (.@EL != Ele_Ghost) .@PW = .@PW * 4 / 5; // Bonus: Hocus
/* Elemental Summoning */
} else if (.@w$ == "manifest") {
.@TY = 4;
} else {
// Invalid magic type
return;
}
.@o += 1;
// Range or filter, please do not simplify the fractions
.@w$ = .@x$[.@o];
if (.@w$ == "me") {
.@F$ = "filter_onlyme";
.@Cost /= 2;
} else if (.@w$ == "here") {
.@RG = 1;
.@Cost = .@Cost * 12 / 10;
} else if (.@w$ == "around") {
.@RG = 3;
.@PW = .@PW * 9 / 10;
.@Cost = .@Cost * 14 / 10;
} else if (.@w$ == "everything") {
.@RG = 5;
.@PW = .@PW * 7 / 10;
.@Cost = .@Cost * 16 / 10;
} else if (.@w$ == "everywhere") {
.@RG = 7;
.@PW = .@PW * 5 / 10;
.@Cost = .@Cost * 18 / 10;
} else {
// Invalid range
return;
}
.@o+=1;
/* Final Adjustments */
// This spell is too costly currently as it is based on ML, give a discount
.@Cost = .@Cost * 2 / 5;
// Cast Delay
.@agi = min(readparam2(bAgi), 150);
.@dex = min(readparam2(bDex), 150);
.@agi += rand2(readparam2(bLuk)) / 5;
.@dex += rand2(readparam2(bVit)) / 5;
.@del = (500 + (.@PW*3)) - ((.@agi + .@dex / 2) * 5 / 3);
.@del = max(10, .@del);
sleep2(.@del);
// Check if you were killed while casting
if (ispcdead())
return;
/* Note: You cannot heal if MP cost go over, to stop cheaters */
if (.@PW < 0 && .@Cost > Sp)
return;
/* Chanting success! */
if ($@GM_OVERRIDE)
debugmes "Chanting » \"%s\" (PW %d Cost %d)", .@msg$, .@PW, .@Cost;
/* Deduct the MP, HP is paid in a 3:1 ratio */
if (.@Cost > Sp)
Hp -= (.@Cost - Sp) * 3;
Sp -= min(.@Cost, Sp);
// areaharm()
if (.@TY & 1) {
.@dmg = AdjustSpellpower(.@PW) * 11 / 10;
areaharm(getcharid(3), .@RG, .@dmg, HARM_MAGI, .@EL, .@F$);
}
// areasc()
if (.@TY & 2) {
.@ch = 60 * readparam2(bInt); // 0.6% per intelligence point
.@du = (readparam2(bVit) + readparam2(bInt)) * 10; // 0.1s per str+int
// Power multipliers
.@du *= .@PW / 100;
.@ch *= .@PW / 100;
areasc(.@RG, .@du, .@SC, BL_MOB|BL_PC|BL_HOM|BL_MER, 1, .@F$, getcharid(3), .@ch);
}
// summon()
if (.@TY & 4) {
switch (.@EL) {
case Ele_Neutral: .@MB = ElectroWorm; break;
case Ele_Water: .@MB = WaterFairy; break;
case Ele_Fire: .@MB = FireFairy; break;
case Ele_Holy: .@MB = PoisonFairy; break;
case Ele_Dark: .@MB = BlackScorpion; break;
case Ele_Ghost: .@MB = MisterPrickel; break;
default: .@MB = Assassin; break; // ???
}
.@t = 10 + (min(readparam2(bInt), 150) / 15) + (.@PW/5);
.@a = 1 + (.@PW/25) + (.@RG/2); // Amount of spawns
// Actual summoning core
for (.@i=0; .@i < .@a; .@i++) {
.@m = summon("Summoned Monster", .@MB, .@t);
/* Monster final stats depends on the power you're using */
.@bhp = getunitdata(.@m, UDT_MAXHP);
.@ak1 = getunitdata(.@m, UDT_ATKMIN);
.@ak2 = getunitdata(.@m, UDT_ATKMAX);
.@bhp = .@bhp * (.@PW) / 100;
.@ak1 = .@ak1 * (.@PW) / 100;
.@ak2 = .@ak2 * (.@PW) / 100;
setunitdata(.@m, UDT_MAXHP, .@bhp);
setunitdata(.@m, UDT_HP, .@bhp);
setunitdata(.@m, UDT_ATKMIN, .@ak1);
setunitdata(.@m, UDT_ATKMAX, .@ak2);
}
}
return;
}