summaryrefslogblamecommitdiff
path: root/npc/033-2/magic.txt
blob: 0ee0dc2befd420f689f72f22eefe8e17ae2655d5 (plain) (tree)








































                                                                                                                                                                                                                                                                     


                                      

















































































































































                                                                               

                                                             



















                                                                            
                                                 























                                                                                          
                                                                



















                                                                       
// 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;
}