summaryrefslogblamecommitdiff
path: root/npc/026-7/boss.txt
blob: 6d785cb6a8d76e2b7678ee8221d657c2751bfc1a (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11





                                                                           
                                                    



                      




                                                                          
                                       

        







                                                                                














                                                                     
                     
                       
        




                                                         
                                     
                                                                  
                             
                                                                     
                                                       

























                                                                            














                                                                                 



                                                                                                                                    
                                                           


                                                                                                                                                           



                                                                            


                 






                                                                              










                                                                                
                                                           
                                                 





















                                                                         
                             







                                                                                
                                                        





                                                                                   

                          
































                                                                                            
                            







                                                                
                        
                                                                        



                                                            
                                                                                   





































































































































































































































                                                                                                                                                          


                                       
          
                           


                                             






                                                                   
                   



                                                                              
                                                  




                                                                           

                                                  

                                                                                
                   
                                  
                                                                                                                                                                                                                                                                                                                                                             
                                 
                                                                                 
                          

                    


                                                   
                   
                                  


                                                                                                                                                                                                        
                          

                    




                                                                                        


                                                                             





                                                                                                                       
                




                                                         
             
 
                                    


                                                    
                                                   

                                        

                      









                                                      
                                                                             






                                                                          





































                                                                                                             

                                                                                                         
                                                                                                
        


 



















                                                              
                                                             




                             








                                                                                   
 
// TMW2 scripts.
// Author:
//    Jesusalva
// Description:
//   The Impregnable Fortress Control Files - Boss Chamber - Final Showdown

026-7,39,34,0	script	Impregnable#B7F	NPC_HIDDEN,{
    function _moveNpc;
    end;

OnInit:
    .MK=0;
    .maxhp = 1000000; // 1,000,000 HP
    .mana = 0; // More mana = more likely to cast skills
    .immortal = true; // Set to FALSE when all four guardians are defeated
    .memohp = 999; // Memorand HP, controls spawns
    .mou = 0; // Temporary for Cutscene
    end;

// Maybe not OnTouch, but OnSit?
OnTouch:
    if (strcharinfo(2) == "Monster King") end;
    slide 39, 35;
    percentheal -15,0;
    dispbottom l("The throne is cursed, only the Monster King may seat on it.");
    end;

function _moveNpc {
    // Try to warp randomly, up to 30 attempts
    .@e=0;
    .@mx=getmapinfo(MAPINFO_SIZE_X, getarg(0))-20;
    .@my=getmapinfo(MAPINFO_SIZE_Y, getarg(0))-20;
    do {
        if (.@e >= 30)
            break;
        .npc_x = rand2(20, .@mx);
        .npc_y = rand2(20, .@my);
        .@e+=1;
    } while (!checknpccell(getarg(0), .npc_x, .npc_y, cell_chkpass));
    return;
} // _moveNpc

// Controls the Event
// TODO: Intro Cutscene
OnBegin:
    // Monster King is somewhere else, so nothing happens
    if ($@MK_SCENE != MK_NONE)
        end;
    // Lock the MK in the showdown
    $@MK_SCENE=MK_SHOWDOWN;
    // Initial assortment of monsters
    //siege_cast("026-7", .name$, 15, TP_TULIM|TP_HURNS|TP_NIVAL);
    // Spawn the boss himself
    .MK=monster("026-7", 39, 34, "The Monster King", MonsterKing, 1);
    immortal(.MK); // Immortal until conditions are met
    .immortal = true;
    // Mana is mostly carried over between attempts, but no negatives
    .mana = max(.mana, 0);
    .memohp = 999; // Reset Memorand HP
    // Reconfigure the AI
    .@opt=getunitdata(.MK, UDT_MODE);
    // Add knockback immunity
    .@opt=.@opt|MD_NOKNOCKBACK;
    // Mark as boss
    .@opt=.@opt|MD_BOSS;
    // Mark as aggressive
    .@opt=.@opt|MD_AGGRESSIVE;
    .@opt=.@opt|MD_ANGRY;
    // Make it more op
    .@opt=.@opt|MD_DETECTOR;
    .@opt=.@opt|MD_CASTSENSOR_CHASE;
    .@opt=.@opt|MD_CASTSENSOR_IDLE;
    .@opt=.@opt|MD_CHANGECHASE;
    .@opt=.@opt|MD_CHANGETARGET_MELEE;
    .@opt=.@opt|MD_CHANGETARGET_CHASE;
    setunitdata(.MK, UDT_MODE, .@opt);
    // The Four Generals which command his immortality
    .GUARD1=monster("026-7", 35, 30, "Air General", MonsterGeneral, 1);
    .GUARD4=monster("026-7", 44, 45, "Fire General", MonsterGeneral, 1);
    .GUARD3=monster("026-7", 35, 45, "Earth General", MonsterGeneral, 1);
    .GUARD2=monster("026-7", 44, 30, "Darkness General", MonsterGeneral, 1);
    // Boost these four generals or they'll become cheese too fast
    // Also, fix their elementals, but they have no elemental skills to speak of.
    setunitdata(.GUARD1, UDT_HP,    60000);
    setunitdata(.GUARD1, UDT_MAXHP, 60000);
    setunitdata(.GUARD2, UDT_HP,    60000);
    setunitdata(.GUARD2, UDT_MAXHP, 60000);
    setunitdata(.GUARD3, UDT_HP,    60000);
    setunitdata(.GUARD3, UDT_MAXHP, 60000);
    setunitdata(.GUARD4, UDT_HP,    60000);
    setunitdata(.GUARD4, UDT_MAXHP, 60000);
    setunitdata(.GUARD1, UDT_ELETYPE, Ele_Wind);
    setunitdata(.GUARD2, UDT_ELETYPE, Ele_Dark);
    setunitdata(.GUARD4, UDT_ELETYPE, Ele_Fire);
    setunitdata(.GUARD3, UDT_ELETYPE, Ele_Earth);
    // The remainder of MK army (Centered at the generals / 20 total)
    .@x = 35; .@y = 30; areamonster("026-7", .@x-3, .@y-3, .@x+3, .@y+3, "Air Officer", Reaper, 5); // Air Troops
    .@x = 44; .@y = 45; areamonster("026-7", .@x-3, .@y-3, .@x+3, .@y+3, "Fire Officer", LavaSkullSlime, 6); // Fire Troops
    .@x = 35; .@y = 45; areamonster("026-7", .@x-3, .@y-3, .@x+3, .@y+3, "Earth Officer", Snail, 5); // Earth Troops
    .@x = 44; .@y = 30; areamonster("026-7", .@x-3, .@y-3, .@x+3, .@y+3, "Darkness Officer", NightmareDragon, 5); // Darkness Troops
    // Monster King Personal Bodyguard is special (4 total)
    for (.@i = 0; .@i < 4; ++.@i) {
        areamonster("026-7", 37, 32, 41, 36, "Imperial Officer", any(VanityPixie, HolyPixie, ShadowPixie, NulityPixie, BlackSkullSlime, PinkieSuseran), 1);
    }
    // General ranged troops / Artillery (20 total)
    areamonster("026-7", 30, 30, 45, 45, "Ranged Support", RobinBandit, 12);
    areamonster("026-7", 30, 30, 45, 45, "Ranged Support", DustRevolver, 5);
    areamonster("026-7", 30, 30, 45, 45, "Ranged Support", DustRifle, 3);
    initnpctimer;
    end;

OnMFDispose:
    if (ispcdead() || getq(General_Fortress) < 6) warp("025-2", 100, 27);
    // Summons, for a whole minute, an allied solider (0.1% per siege won)
    if (rand2(1000) < $MK_TEMPVAR)
        summon("Allied Guard", any(FallenGuard1, FallenGuard2, FallenGuard3));
    end;

// Fail-safe Mechanism (will never happen)
OnTimer60000:
    consolebug("Warning! final fail-safe mechanism triggered to Monster King.");
    initnpctimer;
    end;

// Run every 10 seconds
OnTimer25000:
OnTimer15000:
    consolewarn("Warning, fail-safe mechanism triggered to Monster King.");
OnTimer10000:
    maptimer2("026-7", 10, "Impregnable#B7F::OnMFDispose");
    .mana += (.immortal ? 1 : 2); // Recover mana

    /* Regeneration & Defeat Loop */
    .@end = false;
    if (.immortal)
        setunitdata(.MK, UDT_HP, INT_MAX);
    if (!getmapusers("026-7")) {
        if (.immortal) {
            .@end = true;
        } else {
            .@hp = getunitdata(.MK, UDT_HP);
            .@mh = .maxhp;
            .@hp = max(.@mh, .@hp + (.@mh / 500)); // Regenerates 0.2% HP
            // Regeneration
            setunitdata(.MK, UDT_HP, .@hp);
            // Fully healed, players lost
            if (.@hp >= .@mh)
                .@end = true;
        }
    }

    /* Maybe the fight is over */
    if (!mobcount("026-7", "all") || getunittype(.MK) < 0) {
        $@MK_SCENE = MK_NONE;
        $@MK_CHALLENGE=false;
        killmonsterall("026-7");
        enablenpc .name$;
        if (!.@end) {
            // This is not due to full health! We actually won!
            kamibroadcast("The MONSTER KING has been DEFEATED!", "WORLD HEART");
            if ($GAME_STORYLINE != 5)
                goto L_NextAct;
            // Will not be cast if L_NextAct is summoned
            maptimer2("026-7", 10, "Impregnable#B7F::OnVictory");
        } else {
            // We actually lost?!
            kamibroadcast("The MONSTER KING has WON the showdown!", "WORLD HEART");
        }
        stopnpctimer;
        //end;
        goto OnPrepBlight;
    }

    /* Prepare some combat data */
    getmapxy(.@m$, .@x, .@y, UNITTYPE_MOB, .MK);
    .@c=getunits(BL_PC, .@pcs, MAX_CYCLE_PC, .@m$);
    .@mvp=0;.@rnd=0;.@def=-1;
    for (.@i = 0; .@i < .@c; .@i++) {
        if (!.@rnd || !rand2(.@c))
            .@rnd=.@pcs[.@i];
        if (readbattleparam(.@pcs[.@i], UDT_DEF) > .@def) {
            if (readparam(Hp, .@pcs[.@i]) < 1) continue;
            .@mvp=.@pcs[.@i];
            .@def=readbattleparam(.@pcs[.@i], UDT_DEF);
        }
    }

    /* Everyone is dead, get rid of their corpses and loop over */
    if (!.@mvp || !.@rnd) {
        mapwarp("026-7", "025-2", 100, 27);
        initnpctimer;
        end;
    }

    /* Maybe he lost his immortality */
    if (.immortal) {
        if (getunittype(.GUARD1) < 0 &&
            getunittype(.GUARD2) < 0 &&
            getunittype(.GUARD3) < 0 &&
            getunittype(.GUARD4) < 0) {
                .immortal = false;
                kamibroadcast("The Monster King has lost his immortality.", "Monster King");
                setunitdata(.MK, UDT_HP,    .maxhp);
                setunitdata(.MK, UDT_MAXHP, .maxhp);
                .mana += 25;
        }
    }

    /* Spawn every 20% HP lost, using siege logic 'cause lazy */
    if (!.immortal) {
        .@hp = getunitdata(.MK, UDT_HP) * 5 / .maxhp;
        if (.@hp < .memohp) {
            .memohp = .@hp;
            .mana += 25;
            siege_cast("026-7", .name$, 35, TP_TULIM|TP_HURNS|TP_NIVAL);
        }
    }

    /* Decide whenever the Monster King will use a skill. */
    // Each Mana point is worth 1% chance. He gains 6 points per minute. (12 later)
    // (While immortal, each mana point is worth 0.5% chance)
    if (rand2(.immortal ? 200 : 100) <= .mana) {
        .mana -= 5; // Mana cost for skill use. It can go negative
        // Give players 500ms to prepare
        specialeffect(FX_SPECIAL, AREA, .MK);
        sleep(500);
        // Initialization
        .@skill = rand2(25); .@mob = .MK; .@msg$ = ""; .@lv = 120; .@t = rand2(15);
        // Skills taken from Blanc, Terogan and Moubootaur (Sealed)
        switch (.@skill) {
        case 1:
		    .@msg$ = sprintf("Witness my sublime rain of death. Regeneration!");
		    .@hp=getunitdata(.@mob, UDT_HP);
		    .@mp=getunitdata(.@mob, UDT_MAXHP);
            .@hp = max(.@mp, .@hp + (.@mp / 250)); // Regenerates 0.4% HP
		    setunitdata(.@mob, UDT_HP, min(.@hp, .@mp));
            .@mobid=(rand2(.@lv) > 50 ? DeathCat : GreenSlime);
            monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1);
            break;
	    case 2:
		    .@msg$ = sprintf("Chaos shall be my founding stone! Falling star!");
            attachrid(.@rnd);
		    percentheal -5, -10;
            detachrid();
            .@mobid=(rand2(.@lv) > 50 ? BlackScorpion : RedSlime);
            monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1);
            break;
	    case 3:
		    .@msg$ = sprintf("I demand this world! Tyranny!");
            attachrid(.@rnd);
		    percentheal -1, -1;
		    SC_Bonus(.@t, any(SC_BLIND, SC_POISON), 1);
            detachrid();
            .@mobid=(rand2(.@lv) > 50 ? DarkLizard : Assassin);
            monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1);
            break;
	    case 4:
		    .@msg$ = sprintf("Stop on your tracks, unfair being! Freeze!");
            attachrid(.@rnd);
		    SC_Bonus((.@t / 2), any(SC_FREEZE, SC_SLEEP, SC_SLEEP, SC_SLEEP), 1);
            detachrid();
            .@mobid=(rand2(.@lv) > 50 ? BlueSlime : WhiteSlime);
            monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1);
            break;
	    case 5:
		    .@msg$ = sprintf("There is no free speech. Censorship!");
            attachrid(.@rnd);
		    SC_Bonus(.@t, SC_SILENCE, 1);
            detachrid();
            .@mobid=(rand2(.@lv) > 50 ? Thug : RedMushroom);
            monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1);
            break;
	    case 6:
		    .@msg$ = sprintf("And then... There was a quake. And all life died. Bleed!");
            attachrid(.@rnd);
		    SC_Bonus(.@t, SC_BLOODING, 1);
            detachrid();
            .@mobid=(rand2(.@lv) > 50 ? BlackSlime : OldSnake);
            monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1);
            break;
	    case 7:
		    .@msg$ = sprintf("Puny mortal, do your best to entertain me! Curse!");
            attachrid(.@rnd);
		    SC_Bonus(.@t, SC_CURSE, 1);
            detachrid();
            .@mobid=(rand2(.@lv) > 50 ? FireSkull : Skeleton);
            monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1);
            break;
	    case 8:
		    .@msg$ = sprintf("The problem with typos is - unpredictable side effects.");
            attachrid(.@rnd);
		    SC_Bonus(.@t, any(SC_SILENCE, SC_CURSE, SC_FREEZE, SC_BLOODING, SC_BLIND, SC_POISON, SC_DPOISON, SC_POISON, SC_BURNING, SC_SLEEP), 1);
            detachrid();
            .@mobid=(rand2(.@lv) > 50 ? Swashbuckler : Bluepar);
            monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1);
            break;
        case 9:
            mapannounce("026-7", "Monster King : ##BAncient Magic: Lag", 0);
            areasc2("026-7", 39, 38, 20, 15000, SC_CONFUSION, BL_PC, 1);
            break;
        case 10:
            mapannounce("026-7", "Monster King : ##BAncient Magic: Sleep", 0);
            areasc2("026-7", 39, 38, 20, 15000, SC_SLEEP, BL_PC, 1);
            break;
        case 11:
            mapannounce("026-7", "Monster King : ##BAncient Magic: Burning", 0);
            areasc2("026-7", 39, 38, 20, 15000, SC_BURNING, BL_PC, 1);
            break;
        case 12:
            mapannounce("026-7", "Monster King : ##BAncient Magic: Fear", 0);
            areasc2("026-7", 39, 38, 20, 15000, SC_FEAR, BL_PC, 1);
            break;
        case 13:
            .@msg$ = sprintf("##BAncient Magic: Obliterate");
            rectharm(.MK, 7, 7, rand2(700, 900), HARM_MISC, Ele_Dark, "filter_always", BL_PC | BL_MER | BL_HOM);
            break;
        case 14:
            .@msg$ = sprintf("##BAncient Magic: Terminate Homunculi");
            rectharm(.MK, 14, 14, rand2(1500, 2500), HARM_MISC, Ele_Dark, "filter_always", BL_MER | BL_HOM);
            break;
        case 15:
            mapannounce("026-7", "Monster King : ##BAncient Magic: Wizcat", 0);
            for (.@i=0;.@i <= 2+rand2(7);.@i++) {
                .@m=monster("026-7", rand2(30,50), rand2(30,45),
                    "Reinforcement", BlackCat, 1);
                setunitdata(.@m, UDT_RACE, RC_Legendary);
            }
            break;
        case 16:
            mapannounce("026-7", "Monster King : ##BAncient Magic: Silencing Nuke", 0);
            rectharm(.MK, 14, 14, rand2(450, 750), HARM_MISC, Ele_Dark, "filter_always", BL_PC | BL_MER | BL_HOM);
            areasc2("026-7", 40, 35, 20, 15000, SC_SILENCE, BL_PC, 1);
            break;
        case 17:
            // Second Attack Pattern: Holy Light (vs Tank)
            .@msg$ = sprintf("%s, I'll show you no mercy! ##BThunder Bolt##b!", strcharinfo(0, "cursed player", .@mvp));
            .@PW=125; .@SPW=25; .@RG=1;
            .@mtk = calcdmg(.@mob, .@mvp, HARM_MAGI);
            .@dmg = .@mtk * .@PW / 100;
            .@dsb = .@mtk * .@SPW / 100;
            sleep(1000);
            specialeffect(FX_LIGHTNING, AREA, .@mvp);
            areaharm(.@mvp, .@RG, .@dsb, HARM_MAGI, Ele_Wind, "filter_always", BL_PC|BL_MER|BL_HOM);
            harm(.@mvp, .@dmg, HARM_MAGI, Ele_Holy);
            break;
        case 18:
            .@msg$ = sprintf("Come forth, my minions! Wreak chaos and havoc!");
            specialeffect(FX_MGWARP, AREA, .MK); // Maybe 65 would also work
            sleep(1000);
            // Default amount: Half players + 3
            .@max = (getmapusers("026-7")/2) + 3;
            // Keep boundaries: Never less than 1, never more than 10
            .@max = limit(1, .@max, 10);
            for (.@i=0; .@i < .@max; .@i++) {
                .@mid = any(GoboBear, Centaur, BloodyMouboo, GreenSkullSlime, BlackMamba, JackO, Brainic, TerraniteProtector, Yeti, Reaper);
                .@x = monster(.@m$, .@x, .@y, strmobinfo(1, .@mid), .@mid, 1);
                set_aggro(.@x);
            }
            break;
        case 19:
            .@msg$ = sprintf("I shall ##Bdisable##b you, %s!", strcharinfo(0, "cursed player", .@mvp));
            specialeffect(FX_SMOKE, AREA, .MK);
            attachrid(.@mvp);
		    SC_Bonus(.@t, SC_SILENCE, 1);
		    SC_Bonus(.@t, SC_BLIND, 1);
		    SC_Bonus(.@t/3, SC_CURSE, 1);
            detachrid();
            break;
	    case 20:
            // First Attack Pattern: Napalm Beat (vs MVP)
            .@msg$ = sprintf("This battle is over, %s! ##BThunder Neddle##b!", strcharinfo(0, "cursed player", .@mvp));
            .@PW=35; .@SPW=5; .@RG=2;
            .@mtk = calcdmg(.@mob, .@mvp, HARM_MAGI);
            .@dmg = .@mtk * .@PW / 100;
            .@dsb = .@mtk * .@SPW / 100;
            sleep(1000);
            specialeffect(FX_LIGHTNING, AREA, .@mvp);
            areaharm(.@mvp, .@RG, .@dsb, HARM_MAGI, Ele_Wind, "filter_always", BL_PC|BL_MER|BL_HOM);
            harm(.@mvp, .@dmg, HARM_MAGI, Ele_Holy);
            break;
        case 21:
            .@msg$ = sprintf("##BMagic: Armageddon");
            rectharm(.MK, 6, 6, rand2(300, 500), HARM_MAGI, Ele_Fire, "filter_always", BL_PC | BL_MER | BL_HOM);
            break;
        case 22:
            .mana += 1;
            .@msg$ = sprintf("##BMagic: Tempest");
            rectharm(.MK, 3, 3, rand2(200, 300), HARM_MAGI, Ele_Wind, "filter_always", BL_PC | BL_MER | BL_HOM);
            break;
        case 23:
            .@msg$ = sprintf("##BMagic: Gaia Break");
            sc_start SC_INCDEFRATE, 15000, 10, .MK;
            rectharm(.MK, 2, 5, rand2(250, 350), HARM_MAGI, Ele_Earth, "filter_always", BL_PC | BL_MER | BL_HOM);
            break;
        case 24:
            .@msg$ = sprintf("##BMagic: Ground Strike");
            .@EF=any(SC_STUN, SC_BLIND, SC_BLOODING, SC_BLIND, SC_BLOODING);
            areasc2("026-7", .@x, .@y, 3, 12000, .@EF, BL_PC, 1);
            rectharm(.MK, 3, 3, rand2(250, 350), HARM_PHYS, Ele_Neutral, "filter_always", BL_PC | BL_MER | BL_HOM);
            break;
        // TODO: Skills which manipulate the map or weather
        default:
            .@mx=55; .@my=55; .@x=22; .@y=22;
            .@x1=rand2(.@mx, .@x); .@x2=rand2(.@mx, .@x); .@x3=rand2(.@mx, .@x);
            .@y1=rand2(.@my, .@y); .@y2=rand2(.@my, .@y); .@y3=rand2(.@my, .@y);
            .@x4=rand2(.@mx, .@x); .@x5=rand2(.@mx, .@x);
            .@y4=rand2(.@my, .@y); .@y5=rand2(.@my, .@y);
            // TODO: Maybe replace Dummy/EnergyBall with an invisible monster/FX?
            .@t1=monster("026-7", .@x1, .@y1, "", Dummy, 1);
            .@t2=monster("026-7", .@x2, .@y2, "", Dummy, 1);
            .@t3=monster("026-7", .@x3, .@y3, "", Dummy, 1);
            .@t4=monster("026-7", .@x4, .@y4, "", Dummy, 1);
            .@t5=monster("026-7", .@x5, .@y5, "", Dummy, 1);
            specialeffect(67, AREA, .@t1);
            specialeffect(67, AREA, .@t2);
            specialeffect(67, AREA, .@t3);
            specialeffect(67, AREA, .@t4);
            specialeffect(67, AREA, .@t5);
            immortal(.@t1); immortal(.@t2); immortal(.@t3);
            immortal(.@t4); immortal(.@t5);
            sleep(1500); // Saw a pillar? RUN!
            specialeffect(FX_LIGHTNING, AREA, .@t1);
            specialeffect(FX_LIGHTNING, AREA, .@t2);
            specialeffect(FX_LIGHTNING, AREA, .@t3);
            specialeffect(FX_LIGHTNING, AREA, .@t4);
            specialeffect(FX_LIGHTNING, AREA, .@t5);
            sleep(500);
            specialeffect(FX_CRITICAL, AREA, .@t1);
            specialeffect(FX_CRITICAL, AREA, .@t2);
            specialeffect(FX_CRITICAL, AREA, .@t3);
            specialeffect(FX_CRITICAL, AREA, .@t4);
            specialeffect(FX_CRITICAL, AREA, .@t5);
            areaharm(.@t1, 2, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM);
            areaharm(.@t2, 2, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM);
            areaharm(.@t3, 2, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM);
            areaharm(.@t4, 2, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM);
            areaharm(.@t5, 2, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM);
            sleep(1000);
            // FIXME: M+ fails to remove them, need @refresh (maybe @refreshall?)
            // NOTE: The effect Nº 67 (halo circle) is also not cleaned by M+
            unitkill(.@t1); unitkill(.@t2);
            unitkill(.@t4); unitkill(.@t5);
            break;
        }
        if (.@msg$ != "")
            unittalk(.@mob, .@msg$);
    }

    // Restart the endless loop
    initnpctimer;
    end;

// Monster King was defeated - game won
L_NextAct:
    $@MK_SCENE=MK_CUTSCENE;
    $GAME_STORYLINE=5;
    $MANA_BLVL-=10; // Set base level to 5~15
    $MANA_BLVL=max(0, $MANA_BLVL);
    // Thanksgiving event no longer happens after Monster King dies
    if ($EVENT$ == "Thanksgiving") {
        kamibroadcast("Thanksgiving ended!");
        sClear();
        $EVENT$="";
    }
    donpcevent "sThankAeros::OnTimer90000";
    // XXX Cutscene
    sleep(3000);
    .mou = monster("026-7", 39, 37, "Moubootaur", MobMoubootaur, 1);
    immortal(.mou);
    sc_start(SC_STUN, 90000, 1, 10000, SCFLAG_NOAVOID|SCFLAG_FIXEDTICK, .mou);
    maptimer2("026-7", 30, "Book#FoS::OnMFShake");
    sleep(3000);
    unittalk(.mou, "##1I'm free... At least!");
    sleep(6500);
    unittalk(.mou, "##1The blood in the Heart, as the prophecy foretold!");
    sleep(4500);
    maptimer2("026-7", 30, "Book#FoS::OnMFShake");
    sleep(30);
    unittalk(.mou, "##1All monsters, heed my command! ##BHostile Takeover!##b");
    sleep(1500);
    freeloop(true);
    for (.@i=0; .@i < 25; .@i++) {
        .@m = areamonster("026-7", 20, 20, 55, 55, "Subjugated Monster", any(PinkieEmperor, PanthomLord, TerraniteKing, YetiKing, PsiConscience, DemureSecondForm, Luvia, Birb, MonsterGeneral, MonsterColonel, LavaSlimeMother, BlackSlimeMother, WanderingShadow, BanditLord, HoodedAssassin, SpiderQueen, NightScorpion, SaxsoGhost, GiantMutatedBat), 1);
        immortal(.@m); // Broken?
        sc_start(SC_STUN, 90000, 1, 10000, SCFLAG_NOAVOID|SCFLAG_FIXEDTICK, .@m);
        sleep(200); // 5 s
    }
    freeloop(false);
    sleep(3000);
    unittalk(.mou, "##1My children, ##BArise!##b");
    sleep(1500);
    freeloop(true);
    for (.@i=0; .@i < 25; .@i++) {
        .@m = areamonster("026-7", 20, 20, 55, 55, "Subjugated Monster", any(Moubi, Moubi, Moubi, MoubooSlime, GreatMoubooSlime, Mouboo, Mouboo, EasterMouboo, AlphaMouboo, Shrewboo, BloodyMouboo), 1);
        immortal(.@m);
        sc_start(SC_STUN, 90000, 1, 10000, SCFLAG_NOAVOID|SCFLAG_FIXEDTICK, .@m);
        sleep(160); // 4 s
    }
    freeloop(false);
    sleep(3000);
    unittalk(.mou, "##1I have taken over the World Heart... Your chances are forfeit.");
    sleep(6000);
    unittalk(.mou, "##1But first, I'll make a Monster King puppet.");
    sleep(2000);
    .@m = monster("026-7", 39, 34, "Monster King (puppet)", MonsterKing, 1);
    immortal(.@m);
    sc_start(SC_STUN, 90000, 1, 10000, SCFLAG_NOAVOID|SCFLAG_FIXEDTICK, .@m);
    sleep(3000);
    unittalk(.mou, "##1Now, it would be inconvenient if you were to disturb me while I work...");
    sleep(6000);
    unittalk(.mou, "##1It'll take several days or even months to corrupt the Heart. Can't be bothered.");
    sleep(8000);
    unittalk(.mou, "##1Enjoy your final days while you can. The day on which everything will be a Mouboo is upon us!");
    sleep(5000);
    maptimer2("026-7", 10, "Impregnable#B7F::OnVictory");
    // Cleanup
    sleep(10000);
    $@MK_SCENE=MK_NONE;
    killmonsterall("026-7");
    .mou = 0;

    // This disables all mosnters :<
    //setbattleflag("monster_ai", 0x209);
    //setbattleflag("monster_active_enable", false);
    //setbattleflag("mob_count_rate", 25);
    //charcommand("@reloadbattleconf"); // Careful!
    //donpcevent("@exprate::OnReload");
    //donpcevent("@droprate::OnReload");
    //end;
    goto OnPrepBlight;

OnVictory:
    // Not killed by a player? It doesn't counts, then
    if (!playerattached())
        end;
    // Prizes
    Mobpt += 165;
    getitem StrangeCoin, 50;
    if (!MK_WINNER) {
        MK_WINNER=gettimetick(2); // TODO
        getitem StrangeCoin, 1950; // Total: 2,000 Strange Coins on first win
        getitembound MysteriousFruit, 3, 4; // You get 3 char bound fruits
    }
    // Effects
    specialeffect(FX_FANFARE, SELF, getcharid(3));
    // Bailout
    sleep2(5000);
    warp "025-1", 99, 22;
    close;

OnPrepBlight:
    if ($SHADY_HOLDER$ != "") end;
    .@c=getunits(BL_PC, .@pcs, MAX_CYCLE_PC, "026-7");
    .@mvp=0;.@def=-1;
    for (.@i = 0; .@i < .@c; .@i++) {
        .@atk = readbattleparam(.@pcs[.@i], UDT_ATKMAX);
        if (.@atk > .@def) {
            // Lets check if they qualify
            attachrid(.@pcs[.@i]);
            if (islegendary()) .@atk=false; // Already legendary, so nope
            if (ispcdead()) .@atk=false; // Dead, so nope
            if (!checkweight(Blightbringer, 1)) .@atk=false; // Overweight, so nope
            detachrid();
            // They qualify: Remember this, and look for someone worthier
            if (.@atk) {
                .@mvp=.@pcs[.@i];
                .@def=.@atk;
            }
        } // if qualified
    } // for Loop
    if (.@mvp) {
        attachrid(.@mvp);
        addtimer(10, "Impregnable#B7F::OnBlightbringer");
    }
    end;

OnBlightbringer:
    // Repeat all checks
    if ($SHADY_HOLDER$ != "") end;
    if (islegendary()) end;
    if (ispcdead()) end;
    inventoryplace Blightbringer, 1;

    $SHADY_HOLDER$ = strcharinfo(0);
    getitembound Blightbringer, 1, 1; // Account bound or char bound? (1 or 4)
    dispbottom l("For defeating the Monster King, you've got the Legendary @@.", getitemlink(Blightbringer));
    dispbottom l("This item cannot be traded normally and is a Legendary Item.");
    dispbottom l("You can transfer it with \"@grantpower\" command. Please contact a GM for more info.");
    dispbottom l("Protip: If you plan in selling it, it's adviseable to ask for GM mediation.");
    end;

}


// Room Traps, only against players
026-7,0,0,0	script	#MKBossTrap01	NPC_TRAP_ONLINE,0,0,{
    end;

OnTouch:
OnTouchNPC:
    WorldHeartTrap();
    sleep(500); // Wait 500ms for animation
    setnpcdisplay .name$, NPC_TRAP_ONLINE;
    // Move the trap away after it disarms (up to 30 attempts)

OnInit:
    .@e=0;
    do {
        if (.@e >= 30)
            break;
        .@x = rand2(21, 60);
        .@y = rand2(21, 60);
        .@e+=1;
    } while (!checknpccell("026-7", .@x, .@y, cell_chkpass));
    movenpc .name$, .@x, .@y;
    end;
}

// Create more traps
026-7,0,0,0	duplicate(#MKBossTrap01)	#MKBossTrap02	NPC_TRAP_ONLINE,0,0
026-7,0,0,0	duplicate(#MKBossTrap01)	#MKBossTrap03	NPC_TRAP_ONLINE,0,0
026-7,0,0,0	duplicate(#MKBossTrap01)	#MKBossTrap04	NPC_TRAP_ONLINE,0,0
026-7,0,0,0	duplicate(#MKBossTrap01)	#MKBossTrap05	NPC_TRAP_ONLINE,0,0
026-7,0,0,0	duplicate(#MKBossTrap01)	#MKBossTrap06	NPC_TRAP_ONLINE,0,0
026-7,0,0,0	duplicate(#MKBossTrap01)	#MKBossTrap07	NPC_TRAP_ONLINE,0,0
026-7,0,0,0	duplicate(#MKBossTrap01)	#MKBossTrap08	NPC_TRAP_ONLINE,0,0
026-7,0,0,0	duplicate(#MKBossTrap01)	#MKBossTrap09	NPC_TRAP_ONLINE,0,0
026-7,0,0,0	duplicate(#MKBossTrap01)	#MKBossTrap10	NPC_TRAP_ONLINE,0,0