summaryrefslogblamecommitdiff
path: root/npc/025-1/ctrl.c
blob: ace7b64ff8a4c6290eba57db5d9a45ba83453c1f (plain) (tree)
1
2
3
4
5
6
7
8







                                                                          



                             
                                   

                                       
                                
                                       

                                                  

           
                                


                                





                                         



                                                           
                              
                        
                               




                                

                                                

                          
                           

                             
                            


                                   
                                    

                                      

                                              
                            

                              
                             


                                    
                                     

                                       
                                             
                                           
     
                                 
                               


           






                                                                                     
                                                                                   


                                                
                     
 

                                   
                                                 


                                     
                         
                                   
                                          
                                                                             
                                                 
                    

     
                 
 











                                         
 
                                                            
                                               

                       





                              


                          

                                           
                                                                                                                     





                                                              

                                                          

                                                                         
         





                                       
              















                                                                                                                      

                     
                       
                                

                 


                           
                     




                                                                                                    
 



                              









                                                                                                                                                      
                                                  
                                                    
                                                                                                  
          
 
                                                         

                                                  




                                                               

                 

                        
                                        
                                                          
                            


                 
             



                        
                                        
                               
 

                     
                                                                        



                                   

                        
 
                            

                                                    
                    

                 


                                                         



                          
                                            





                                                                          
        
 
                                                         










                                                                                                                                                                                                                
                                   




























































                                                                                                                                                                                                             

        
                                                         

                                


                                                                                                                               






                                       
                                        



































                                                                                  
                                                                                                                                                                                                                                                                                























                                                                                                                                                                                                   
       
                                                           
                               
        

          
                     
                                                                 


           
                   
                    
                                                                           


                                                              
                 


        
 
                                                         
              
                                                           


                                     






                



                                                                                  



 
 
                                                         



























                                                                           
 



                

 





                                                                
                                                 
            


                               







                                                         
 
// TMW2 Script
// Notes: The Monster King will retake the town every
// OnTue0000
// (Tuesday, midnight)
// Only the world hero may begin a siege.
// Only one siege per day is allowed
// Writes to MK Temp Var. This variable will unlock the castle gates
// Then the inner gates, and finally, will be a co-requisite to the floors
// Variables:
//      $FORTRESS_STATE = int
//          0 - Locked
//          1 - Unlocked
//      $@FORTRESS_STATUE = bitmask
//          1,2,4,8,16 - broken statues
//          1024 - Fortress Gate
//          2048 - Siege started
//          4096 - Governor was spawned
//      $@FORT_BLACKLIST = int array
//          Char ID which already raided this week

// MAPFLAGS
025-1	mapflag	zone	SuperMMO
025-3	mapflag	zone	SuperMMO
026-0	mapflag	zone	SuperMMO
026-1	mapflag	zone	SuperMMO

/////////////////////////////////////////
// FUNCTIONS

// FTCleanup(status)
function	script	FTCleanup	{
    // Kills whatever called this function if time is wrong
    if ($GAME_STORYLINE < 3)
        end;
    // Reset variables
    $FORTRESS_STATE=getarg(0);
    $@FORTRESS_STATUE=0;
    // Enable the Magic Statues
    enablenpc "Magic Statue#1";
    enablenpc "Magic Statue#2";
    enablenpc "Magic Statue#4";
    enablenpc "Magic Statue#8";
    enablenpc "Magic Statue#16";
    // Kill stray monsters (including town gate)
    killmonsterall("025-1");
    // Main gate
    if ($FORTRESS_STATE) {
        hideonnpc "Gate#F";
        enablenpc "Ihclot";
        enablenpc "Salohnic";
        enablenpc "Xovilam";
        enablenpc "Drahcir";
        enablenpc "Selim";
        enablenpc "Commander Povo";
        enablenpc "Commander Cadis";
        enablenpc "Phoenix Rebirth";
        enablenpc "Anin The Traveler";
        donpcevent "#025-1_99_112::OnDisable";
    } else {
        hideoffnpc "Gate#F";
        disablenpc "Ihclot";
        disablenpc "Salohnic";
        disablenpc "Xovilam";
        disablenpc "Drahcir";
        disablenpc "Selim";
        disablenpc "Commander Povo";
        disablenpc "Commander Cadis";
        disablenpc "Phoenix Rebirth";
        disablenpc "Anin The Traveler";
        donpcevent "#025-1_99_112::OnEnable";
        mapwarp("025-1", "025-2", 100, 27);
    }
    deletearray $@FORT_BLACKLIST;
    enablenpc "#025-1_100_123";
    return;
}

// FTStatue(id)
function	script	FTStatue	{
    .@id=getarg(0);
    mesn l("Magic Statue");
    mes l("There is a reading: The Mana Source. The Moubootaur. The Monster King.");
    mes l("The war. The blood. The inspiration. The mana. The world. The defiance.");
    mes l("The guard. The heir. The originals. The races. The later. The seal.");
    mes l("The fragments. The war. The Terranite. AEGIS MAGNA PROTECTIVE SCUTUM.");
    next;
    mesc l("It seems to be a defensive spell.");
    if ($FORTRESS_STATE)
        return false;

    // Break the statues?
    mesc l("Break the Statue?"), 1;
    mesc l("* Will be stun you for 10 seconds!");
    next;
    if (askyesno() == ASK_YES) {
        if ($@FORTRESS_STATUE & .@id)
            return false;
        sc_start SC_STUN, 10000, 1;
        doevent("Gate#F::OnStatueBreach");
        mapannounce("025-1", strcharinfo(0)+" has broken a statue!", bc_map);
        $@FORTRESS_STATUE=$@FORTRESS_STATUE|.@id;
        return true;
    }

    return false;
}










/////////////////////////////////////////
// NPC SCRIPTS

// Main gate - Also where the World Hero can begin the siege
025-1,99,112,0	script	Gate#F	NPC_NO_SPRITE,{
    function spawnMob;
    function spawnCore;
    // Main Story block - WHAT
    if ($GAME_STORYLINE < 3)
        die();
    // Still open
    if ($FORTRESS_STATE)
        end;
    // Siege ongoing
    if ($@FORTRESS_STATUE)
        end;
    // Only World Hero may interact
    if (strcharinfo(0) !=  $MOST_HEROIC$) {
        dispbottom l("I will not assault the Fortress Island by myself. Instead, I'll wait for %s.",  $MOST_HEROIC$);
        end;
    }

    // Hey, you can assault the town!
    mesc ".:: "+l("THE FORTRESS ISLAND TOWN") + " ::.", 1;
    mes l("Behind this gate, lies the Fortress Island Town.");
    next;
    mesc ".:: "+l("THE FORTRESS ISLAND TOWN") + " ::.", 1;
    mesc l("Assault?"), 1;
    mes l("* Ensure you and your team is ready and at their positions.");
    next;
    select
        l("Not now."),
        l("Information"),
        l("Bring it on, we're ready!");
    mes "";
    if (@menu == 1) {
        close;
    } else if (@menu == 2) {
        mesc l("* The siege resets at Tuesday 00:00");
        mesc l("* Sieges increase in difficulty as they are won");
        mesc l("* Unlike monster sieges, the difficulty does not fluctuates based on nº of players or their level!");
        dnext;
        mesc l("* The warp to this map will be suspended until the siege is finished.");
        mesc l("* The town is liberated once the Monster Governor is slain.");
        mesc l("* Monster Governor will only show up when the town magic shield is broken.");
        mesc l("* Monster Governor gives 500,000 exp and 100,000 jexp to whoever deals most damage to it");
        dnext;
        mesc l("* All monsters in the town and Impregnable Fortress give +25%% EXP");
        mesc l("* You cannot teleport in the town.");
        mesc l("* This is a Cursed Lands map, watch out for MP during the fights as well");
        mesc l("* The siege is lost if all players die.");
        close;
    }

    // FIRE THE EVENT
    hideonnpc "Gate#F";
    disablenpc "#025-1_100_123";
    initnpctimer;

    // Reset variables
    $@FORTRESS_STATUE=2048;

    // Spawn the gate
    .@g=monster("025-1", 99, 113, strmobinfo(1, FortressGate), FortressGate, 1, "Gate#F::OnSesame");
    .@bhp=getunitdata(.@g, UDT_MAXHP);
    .@bhp=.@bhp*(25+$MK_TEMPVAR)/25; // +4% per success or 8,000 HP
    setunitdata(.@g, UDT_MAXHP, .@bhp);
    setunitdata(.@g, UDT_HP,    .@bhp);

    // Initial defending waves
    spawnCore(true);
    spawnCore(false);

    // Front Gate Guardians (Lv 70~80)
    getmapxy(.@m$, .@x, .@y, 0);
    .@x1=.@x-5;
    .@x2=.@x+5;
    .@y1=.@y-5;
    .@y2=.@y+5;
	for (.@i = 0; .@i < 4; ++.@i) {
        spawnMob(any(AzulSkullSlime, YellowSkullSlime, Forain, GreenDragon, Michel, EliteDuck, Troll, Moonshroom, Terranite), .@x1, .@y1, .@x2, .@y2);
    }

    // Player blacklist (unable to use 025-2 warp)
    maptimer2("025-1", 10, "Gate#F::OnMPBlacklist");
    kamibroadcast($MOST_HEROIC$+"'s team has begun a siege on Fortress Town. Will they prevail?");
    close;

/////////////////////////////////////////////////////////
OnSesame:
    debugmes("[INFO] FORTRESS TOWN WAS BREACHED");
    $@FORTRESS_STATUE = $@FORTRESS_STATUE|1024;
    donpcevent "#025-1_99_112::OnDisable";
    kamibroadcast("The Fortress Town Gate has been breached!");
    close;

// Heartbeat (B1)
OnTimer15000:
    if ($FORTRESS_STATE)
        end;
    .@breach=($@FORTRESS_STATUE & 1024);
    if (mobcount("025-1", "all") < (.@breach ? 200 : 100))
        spawnCore(.@breach);
    end;

// Heartbeat (B2)
OnTimer30000:
    if ($FORTRESS_STATE)
        end;

    // Initial variables
    .@breach=($@FORTRESS_STATUE & 1024);
    .@ppl=getmapusers("025-1");

    // Fail condition
    if (.@ppl <= 0) {
        kamibroadcast("Players failed to conquer the Fortress Island!");
        FTCleanup($FORTRESS_STATE);
        end;
    }

    // Spawn mobs
    spawnCore(.@breach);

    // Summon reinforcements
    maptimer2("025-1", 10, "Gate#F::OnMPReinforce");

    // Restart timer
    initnpctimer;
    end;
/////////////////////////////////////////////////////////
OnMPBlacklist:
    array_push($@FORT_BLACKLIST, getcharid(0));
    goto OnMPReinforce;

OnMPReinforce:
    // Dispose dead bodies
    if (ispcdead() || getmap() != "025-1") {
        warp "025-2", 96, 25;
        end;
    }
    // Summon allies
    // Last a whole minute
    summon("Allied Guard", any(FallenGuard1, FallenGuard2, FallenGuard3));
    end;

/////////////////////////////////////////////////////////
OnStatueBreach:
    spawnCore(true);
    getmapxy(.@m$, .@x, .@y, 0);
    .@x1=.@x-5;
    .@x2=.@x+5;
    .@y1=.@y-5;
    .@y2=.@y+5;
    // Statue Guardians (Lv 70~90)
	for (.@i = 0; .@i < 6; ++.@i) {
        spawnMob(any(AzulSkullSlime, YellowSkullSlime, Forain, GreenDragon, Michel, EliteDuck, Troll, Moonshroom, Terranite, JackO, BlackMamba, Centaur, GoboBear, TerraniteProtector), .@x1, .@y1, .@x2, .@y2);
    }
    // Maybe spawn monster governor
    if (
        ($@FORTRESS_STATUE & 1) &&
        ($@FORTRESS_STATUE & 2) &&
        ($@FORTRESS_STATUE & 4) &&
        ($@FORTRESS_STATUE & 8) &&
        ($@FORTRESS_STATUE & 16)) {
        // The monster Governor shall now make their appearance!
        spawnCore(true);
        .@x1=97;
        .@y1=21;
        .@x2=102;
        .@y2=25;
        // Governor's Personal Bodyguard (Lv 90~110)
	    for (.@i = 0; .@i < 4; ++.@i) {
            spawnMob(any(TerraniteProtector, LavaSkullSlime, VanityPixie, HolyPixie, ShadowPixie, NulityPixie, BlackSkullSlime, Reaper, NightmareDragon, WhirlyBird, PinkieSuseran), .@x1, .@y1, .@x2, .@y2);
        }
        .@mob=monster("025-1", any(99, 100), any(22, 23, 24), "Monster Governor", MonsterGeneral, 1, "Gate#F::OnConquest");
        // Stat and Strengthen the governor
        // Set governor metadata
        setunitdata(.@mob, UDT_LEVEL, 100+$MK_TEMPVAR);
        // Update monster modes
        .@opt=getunitdata(.@mob, UDT_MODE);
        .@opt=.@opt|MD_AGGRESSIVE;
        .@opt=.@opt|MD_BOSS;
        .@opt=.@opt|MD_NOKNOCKBACK;
        setunitdata(.@mob, UDT_MODE, .@opt);
        // Increase health in 2% per siege
        .@bhp=75000;
        .@bhp=.@bhp*(50+$MK_TEMPVAR)/50;
        setunitdata(.@mob, UDT_MAXHP, .@bhp);
        setunitdata(.@mob, UDT_HP,    .@bhp);
        // Accuracy is very very high, immune to crits, always crit
        setunitdata(.@mob, UDT_HIT, 9999);
        setunitdata(.@mob, UDT_LUK, 65535);
        // Increase damage in 1% per siege (remember crit)
        .@atk=320;
        .@atk=.@atk*(100+$MK_TEMPVAR)/100;
        setunitdata(.@mob, UDT_ATKMIN, .@atk);
        setunitdata(.@mob, UDT_ATKMAX, .@atk);
        // Ranged monster
        setunitdata(.@mob, UDT_ATKRANGE, 8);
        // Increase defenses in 0.5% per siege
        .@def=getunitdata(.@mob, UDT_DEF);
        .@def=.@def*(200+$MK_TEMPVAR)/200;
        setunitdata(.@mob, UDT_DEF, .@def);
        .@def=getunitdata(.@mob, UDT_MDEF);
        .@def=.@def*(200+$MK_TEMPVAR)/200;
        setunitdata(.@mob, UDT_MDEF, .@def);
        .@def=getunitdata(.@mob, UDT_FLEE);
        .@def=.@def*(200+$MK_TEMPVAR)/200;
        setunitdata(.@mob, UDT_FLEE, .@def);
        .@def=getunitdata(.@mob, UDT_PDODGE);
        .@def=.@def*(200+$MK_TEMPVAR)/200;
        setunitdata(.@mob, UDT_PDODGE, .@def);
        // "Normalize" criticals
        setunitdata(.@mob, UDT_CRIT, rand2(900, 2700));

        // Announce that the Fortress Town can now be conquered
        kamibroadcast("##1"+"Aegis Scutum has been nullified, the Monster Governor has appeared at Fortress Town!");
        mapannounce "025-1", "Defeat the Monster Governor to capture the fortress town.", bc_map;
    }
    end;

/////////////////////////////////////////////////////////
// spawnMob(Mob, X1, Y1, X2, Y2)
function spawnMob {
    //.@mob=monster("025-1", rand2(getarg(1), getarg(3)), rand2(getarg(2), getarg(4)), strmobinfo(1, getarg(0)), getarg(0), 1);
    .@mob=areamonster("025-1", getarg(1), getarg(2), getarg(3), getarg(4),
                     strmobinfo(1, getarg(0)), getarg(0), 1);
    .@opt=getunitdata(.@mob, UDT_MODE);
    // Make aggressive
    .@opt=.@opt|MD_AGGRESSIVE;
    // All forces can suffer knockback
    if (.@opt & MD_NOKNOCKBACK)
        .@opt=.@opt^MD_NOKNOCKBACK;
    // Save new options
    setunitdata(.@mob, UDT_MODE, .@opt);

    // Increase health in 1%+1% per siege
    .@bhp=getunitdata(.@mob, UDT_MAXHP);
    .@bhp=.@bhp*(101+$MK_TEMPVAR)/100;
    setunitdata(.@mob, UDT_MAXHP, .@bhp);
    setunitdata(.@mob, UDT_HP,    .@bhp);

    // Increase accuracy in 10%+1% per siege
    .@acc=getunitdata(.@mob, UDT_HIT);
    .@acc=.@acc*(110+$MK_TEMPVAR)/100;
    setunitdata(.@mob, UDT_HIT, .@acc);

    // TODO: adjust ViewRange
    return;
}

// spawnCore(breach)
function spawnCore {
    // Now, the thing is, I don't care with how powerful your invading forces are.
    // I only care with how many success you have.
    if (getarg(0)) {
        .@x1=24;
        .@y1=21;
        .@x2=175;
        .@y2=105;
        .@am=2+$MK_TEMPVAR;
    } else {
        .@x1=25;
        .@y1=110;
        .@x2=180;
        .@y2=120;
        .@am=1+($MK_TEMPVAR/3);
    }
    freeloop(true);
    // Level 40~60 Section
	for (.@i = 0; .@i < .@am*3; ++.@i) {
        spawnMob(any(Tipiou, Pollet, Wolvern, FireSkull, DarkLizard, BlackScorpion, EarthFairy, FireFairy, WaterFairy, WindFairy, PoisonFairy, DustGatling, DustRifle, DustRevolver, MountainSnake, HoodedNinja, ForestMushroom, GoldenScorpion, Yeti), .@x1, .@y1, .@x2, .@y2);
    }
    // Level 60~80 Section
	for (.@i = 0; .@i < .@am*2; ++.@i) {
        spawnMob(any(Yeti, WickedMushroom, Archant, Scar, Crafty, AzulSkullSlime, YellowSkullSlime, Forain, GreenDragon, Michel, EliteDuck, Troll, Moonshroom, Terranite), .@x1, .@y1, .@x2, .@y2);
    }
    // Level 80~100 section
	for (.@i = 0; .@i < .@am; ++.@i) {
        spawnMob(any(RedSkullSlime, Terranite, JackO, BlackMamba, GreenSkullSlime, Centaur, GoboBear, TerraniteProtector), .@x1, .@y1, .@x2, .@y2);
    }
    // Summoners Section
	for (.@i = 0; .@i < .@am; ++.@i) {
        spawnMob(any(GreenSlimeMother, BlueSlimeMother, YellowSlimeMother, RedSlimeMother, WhiteSlimeMother, AzulSlimeMother, LavaSlimeMother, BlackSlimeMother), .@x1, .@y1, .@x2, .@y2);
    }
    if (getarg(0)) {
        // DemiBoss section (Internal only, increases every ~2 weeks)
	    for (.@i = 0; .@i < (.@am/2); ++.@i) {
            spawnMob(any(VanityPixie, HolyPixie, ShadowPixie, NulityPixie, Reaper, BlackSkullSlime, NightmareDragon, WhirlyBird, PinkieSuseran), .@x1, .@y1, .@x2, .@y2);
        }
    }
    freeloop(false);
    return;
}

/////////////////////////////////////////////////////////
OnInit:
    sleep(200); // Ensure the NPCs will exist when this run
    FTCleanup($FORTRESS_STATE);
    end;

OnTue0000:
    FTCleanup(false);
    kamibroadcast("The Monster Army has retaken Fortress Town!");
    end;

OnConquest:
    $MK_TEMPVAR+=1;
    FTCleanup(true);
    kamibroadcast("Fortress Town has been captured by the Allied Forces!");
    // Experience injection to the brave (500k EXP, 100k JEXP)
    if (playerattached())
        getexp 500000, 100000;
    stopnpctimer;
    end;
}


/////////////////////////////////////////////////////////
// Statue NPCs
025-1,32,55,0	script	Magic Statue#1	NPC_STATUE_WIZARD,{
    .@b=FTStatue(strnpcinfo(2, "0"));
    if (.@b)
        disablenpc .name$;
    close;

OnInit:
    .distance=2;
    end;
}

025-1,160,25,0	duplicate(Magic Statue#1)	Magic Statue#2	NPC_STATUE_BACCHUS
025-1,156,97,0	duplicate(Magic Statue#1)	Magic Statue#4	NPC_STATUE_FAFA
025-1,134,70,0	duplicate(Magic Statue#1)	Magic Statue#8	NPC_STATUE_EVILMAN
025-1,80,37,0	duplicate(Magic Statue#1)	Magic Statue#16	NPC_STATUE_GUARD





/////////////////////////////////////////////////////////
// The Impregnable Fortress Gate
025-1,99,20,0	script	The Impregnable Fortress	NPC_NO_SPRITE,3,1,{
    // Operation not permitted
    if (!$FORTRESS_STATE || $@FORTRESS_STATUE)
        end;
    // Not unlocked
    if ($GAME_STORYLINE >= 3 && $MK_TEMPVAR < MKIF_LV_0F) {
        mesc l("The gate is sealed shut."), 1;
        mesc l("The monster army is still strong on this floor!"), 1;
        mesc l("Minimum wins: %d/%d", $MK_TEMPVAR, MKIF_LV_0F), 1;
        close;
    }
    mesc l("Visit the Impregnable Fortress, 0F?");
    mesc l("Minimum wins: %d/%d", $MK_TEMPVAR, MKIF_LV_0F);
    if (askyesno() == ASK_YES)
        warp "025-3", 100, 178;
    closeclientdialog;
    close;

OnTouch:
    // Operation not permitted
    if (!$FORTRESS_STATE || $@FORTRESS_STATUE)
        end;
    // Not unlocked
    if ($GAME_STORYLINE >= 3 && $MK_TEMPVAR < MKIF_LV_0F)
        end;
    warp "025-3", 100, 178;
    end;

OnInit:
    .distance=4;
    end;
}


/////////////////////////////////////////////////////////
// Real access to 025-1 map
025-2,96,24,0	script	Fortress Town Access	NPC_HIDDEN,8,0,{
    end;
OnTouch:
    // Disabled
    if ($GAME_STORYLINE < 3 || $@FORTRESS_STATUE)
        end;
    // Open
    if ($FORTRESS_STATE)
        cwarp "025-1", 99, 122;
    // Blacklisted
    if (array_find($@FORT_BLACKLIST, getcharid(0)) != -1)
        end;
    // Not blacklisted
    warp "025-1", 99, 122;
    end;
}