summaryrefslogblamecommitdiff
path: root/npc/functions/mkbot.txt
blob: f7ef00631616b31035dcaa92767485a1236f2331 (plain) (tree)
1
2
3
4
5
6
7
8
9
10




                                




                                                                
                                   




                                                                              

                                                                               
                                                                           
                                                                   










                                                                           

                                                   
                       




                                                    

                  
                           







                                                                                                                           

                                                             
                                
                                                          

                                                                    
                            
                                       
                                                      
     
                            
              


                                                                                                    






                                                          



                                  
                
                 
                
                
 




                                                                            

                                                                 

                                                   
                                                     
                                                                                       
                                                      


                                            
                                   
                     

            
 








                                                                                








                                                                                                                                          

                                     

                 
                        

                               

                                                           
                               

                                           




                                     
            

     












                                                                                                        

                                                                                                   
                                                                                                                 
                                                                                                             
                                                                    
                                                                                  
                      

                                              
                        

                                             

                        
                        



                   

                              

                                                          
                                                      
                                                                                                                                     
     

                                                                            
                                                  


                                  
                                   
                                                                                


                        
                        

                                



                                                                   
                                                                    
                              
                     

            
 



                                                                                               
                                                                

                                                                 
                                
                                 
                       
                    
                                    
                                                                                       
                                                       
                                      
                                                       
         
                    
                                         
                                                                                       
                                                       



                                                      
                                         
                                                                                       
                                                       


                                                     
                  
                                         
                                                                                       
                                                       


                                                       
     
 
                                                                              

                                          
                                                                                              



                                                                                   

                      




                                                                                                                                            

     
                                                             

                                                          












                                                                                                                                   
                      
     
                               
                                             
                                                                                                 
                    
                                                                        




                                                                                  

                                             
     
 
                                     
                         



                 
// TMW-2 Script
// Author:
//  Jesusalva
// Description:
//  GM Bot for the Monster King.
// VARIABLES
//  $GAME_STORYLINE - Current Storyline status
//  $@MK - Monster King Game ID
//  $@MK_SCENE - Current event being handled by the Monster King
//  $MK_TEMPVAR - Temporary Variable
//  $@MK_THROTTLE - Event Throttler
//
// Storyline statuses:
//  0 - The Monster King is inactive (leading sieges to Hurnscald and Nivalis)
//  1 - The Monster King is known by players and is giving them a month break
//  2 - The Monster King is currently sieging towns at random
//  3 - The Monster King is preparing to perfom the Rite and Lightbringer seeks
//      a wielder
//  4 - The Rite is CONCLUDED. Players must walk to MK evil lair and fight.
//  5 - The Monster King is dead. Or something. Depends on players.
//
// $MK_TEMPVAR meaning depends on GAME STORYLINE
//  GS 0
//      Ignored
//  GS 1
//      Tracks the day since 1970 when the town was cleared. A month break.
//  GS 2
//      Player score (1pt per Lieutenant, 10pts per Colonel)
//      Affects the end of Game Story 2 and begin of Game Story 3
//      Because we must wait players...
//  GS 3
//      Number of successful Fortress Town breaches
//  GS 4
//      Inheirs stage 3

000-0,0,0,0	script	Monster King	NPC_HIDDEN,{
OnSlaveDie:
    end;
OnBourneAgain:
    // Reset aggro
    $@MK_AGGRO=0;
    if (playerattached()) {
        if (!FLAGS & FLAG_MKFIRSTBLOOD) {
            channelmes("#world", strcharinfo(0)+" did an act worth of notice.");
            FLAGS = FLAGS | FLAG_MKFIRSTBLOOD;
            dispbottom l("Oh well, this sucks, but that was only an illusion.");
            dispbottom l("The real Monster King is probably on his fortress. It'll take more than that to take him down.");
        } else {
            dispbottom l("While it is utterly pointless, you once again vanish the Monster King's illusion.");
        }
        if ($REBIRTH_WINNER$ == "" && TOP3AVERAGELVL() < 100)
            getexp min(641500, BaseLevel**3), 0;
        else if (!$FIRESOFSTEAM)
            Mobpt+=max(13500, rand2(10000, BaseLevel*90));
        else
            Mobpt+=(max(13500, rand2(10000, BaseLevel*90)) * 2 / 3);
        Mobpt = Mobpt + 165;
        //$MOST_HEROIC$=strcharinfo(0);
        specialeffect(FX_FANFARE, AREA, getcharid(3));
    }
    // We need to start over
    .bar=true;
OnInit:
    $@MK=monster("boss", 45, 45, "The Monster King", MonsterKing, 1, "Monster King::OnBourneAgain");

    if (!.bar) {
        // Variables which other NPCs must take in account
        $@MK_AGGRO=0;
        $@MK_SCENE=0;
    } else {
        .bar=false;
    }

    // Variables only for this NPC
    .users=getusers(1);
    .nearby=getusers(8);
    .mp$="boss";
    .aid=2000000;
    .cid=150002;
    // Constants

    // This script is superseded, so no initialization is required.
    // (Sieges and Personal Sieges no longer happen after Monster King dies)
    if ($GAME_STORYLINE >= 5)
        end;

    // We should jump straight to loop (it runs every 90 seconds)
OnTimer90000:
    // Regenerate some data, and kill spurious mobs
    .users=getusers(1);
    if (mobcount(.mp$, "Monster King::OnSlaveDie")) {
        announce ("Monster King: Noobs, you are all a bunch of noobs!"), bc_map|bc_npc;
        killmonster(.mp$, "Monster King::OnSlaveDie");
    }

    // We are on an event, so skip this loop
    if ($@MK_SCENE || $@GM_EVENT) {
        initnpctimer;
        end;
    }

    // Check if MK is still alive
    if (getunittype($@MK) < 0) {
        consolebug("Monster King GID %d is not a valid unit type!", $@MK);
        sleep(300); // Wait 5 minutes for the respawn
        consolewarn("Forcefully respawning Monster King now (GID was invalid)");
        .bar=true;
        goto OnInit;
    }

    // The Monster King is online. This loop is not needed
    if (isloggedin(.aid, .cid)) {
        if (!$@MK_SCENE)
            unitwarp($@MK, "boss", 45, 45);
        else
            rodex_sendmail(.cid, "MKBot", "Running Event", "An event is currently running by the MK Bot. Please logout and suppress it.");
        initnpctimer;
    }

    // Raise aggro (1 pt per 2 users)
    $@MK_AGGRO+=(.users/2);

    // Mana Stone
    if (.mp$ == "011-1")
        enablenpc "Mana Stone";

    // The Monster King will not move anymore because story
    if ($GAME_STORYLINE == 0 ||
        $GAME_STORYLINE >= 5) {
        if (.mp$ != "boss")
            unitwarp($@MK, "boss", 45, 45);
        // Do not leave orphan timers
        if ($GAME_STORYLINE >= 5)
            stopnpctimer;
        else
            initnpctimer;
        end;
    }

    // Check if MK is hurt, and if so, respawn it in boss map (summon cleanup)
    if (getunitdata($@MK, UDT_HP) < getunitdata($@MK, UDT_MAXHP)) {
        unitwarp($@MK, "boss", 45, 45);
        sleep(50); // No exp for hitters
        unitkill($@MK);
        sleep(50); // No exp for hitters
        $@MK=monster("boss", 45, 45, "The Monster King", MonsterKing, 1, "Monster King::OnBourneAgain");
        // Monster King shall keep tending to his wounds in the keep for a cycle
        initnpctimer;
        end;
    }


    // Select a random map. Never shows up at Candor and cities, nor indoors. Not all maps either.
    setarray .@m$,  "boss", "boss", "001-1", "001-3", "001-4", "001-5", "001-6", "001-7", "001-10",
                    "003-1", "003-1-3", "004-1", "004-2", "007-1", "009-1", "010-1", "010-1-1", "010-2", "011-1",
                    "012-1", "014-1", "014-2", "014-3", "014-4", "014-5", "015-1", "015-2", "015-3", "015-5",
                    "018-1-1", "018-2", "018-3", "018-4", "018-4-1",
                    "019-1", "019-2", "019-4", "020-1", "021-1", "022-1", "023-1";
    .mp$=any_of(.@m$);

    // Try to warp randomly, up to 30 attempts
    .@e=0; .@x=0; .@y=0;
    .@mx=getmapinfo(MAPINFO_SIZE_X, .mp$)-20;
    .@my=getmapinfo(MAPINFO_SIZE_Y, .mp$)-20;
    do {
        if (.@e >= 30) {
            .mp$="boss";
            .@x=45;
            .@y=45;
            break;
        }
        .@x = rand2(20, .@mx);
        .@y = rand2(20, .@my);
        .@e+=1;
    } while (!checknpccell(.mp$, .@x, .@y, cell_chkpass));
    if (!checknpccell(.mp$, .@x, .@y, cell_chkpass)) {
        Exception("mk.bot runtime error: GM_ERR_128 highlight @Jesusalva", RB_DEBUGMES|RB_IRCBROADCAST); .mp$="boss"; .@x=45; .@y=45;
    }

    // Monster King will not warp around for sightseeing if he is threatened
    if ($GAME_STORYLINE > 2 && $@MK_AGGRO < 150) {
        .mp$="boss";.@x=45;.@y=45;
    }

    unitwarp($@MK, .mp$, .@x, .@y);
    sleep(50); // For some reason or other, adding sleep(norid) and sleep2(rid).
    .nearby=getusers(8);

    // Handle Mana Stone
    if (.mp$ == "011-1")
        disablenpc "Mana Stone";

    // Debug markers
    if ($@GM_OVERRIDE)
        debugmes "Monster King (bot): "+.mp$+" ("+.@x+", "+.@y+")";

    // If too few players are online, we don't need an event AT ALL!
    if (.users < rand2(2,4)) {
        initnpctimer;
        end;
    }

    // Siege events (req. 300 aggro, 3 users, and 70% chances to begin)
    if ($@MK_AGGRO >= ($GAME_STORYLINE == 2 ? 300 : 900) && .users >= 3 && rand2(0,100) < 70 &&
        is_between(1, 4, $GAME_STORYLINE) && $@MK_THROTTLE < gettimetick(2) &&
        $@MK_TRIGGERED){
        // Delta handles the compulsory wait time between waves.
        // 7 hours normally, 24 hours if the army is in disarray.
        .@delta=7;
        $@SIEGE_ABORTED = false;
        if ($GAME_STORYLINE >= 3)
            .@delta=24;
        // Tulimshar
        if (compare(.mp$, "003-")) {
            announce ("Monster King: I smell humans! Humans must die!"), bc_map|bc_npc;
            $@MK_THROTTLE=gettimetick(2)+.@delta*60*60;
            $@MK_SCENE=MK_SIEGE_TULIM;
            donpcevent("Lieutenant Dausen::OnMKSiege");
        }
        // Halinarzo
        else if (compare(.mp$, "009-")) {
            announce ("Monster King: I smell humans! Humans must die!"), bc_map|bc_npc;
            $@MK_THROTTLE=gettimetick(2)+.@delta*60*60;
            $@MK_SCENE=MK_SIEGE_HALIN;
            donpcevent("Lieutenant Jacob::OnMKSiege");
        }
        // Hurnscald
        else if (compare(.mp$, "012-")) {
            announce ("Monster King: I smell humans! Humans must die!"), bc_map|bc_npc;
            $@MK_THROTTLE=gettimetick(2)+.@delta*60*60;
            $@MK_SCENE=MK_SIEGE_HURNS;
            donpcevent("#HurnscaldSiege::OnMKSiege");
        }
        // Nivalis
        else if (compare(.mp$, "020-")) {
            announce ("Monster King: I smell humans! Humans must die!"), bc_map|bc_npc;
            $@MK_THROTTLE=gettimetick(2)+.@delta*60*60;
            $@MK_SCENE=MK_SIEGE_NIVAL;
            donpcevent("Lieutenant Joshua::OnMKSiege");
        }
    }

    // If a player is nearby while the Monster King prepares, event may happen
    // Minimum 80 Aggro
    if (.nearby > 1 && $@MK_AGGRO >= 80 &&
        ($GAME_STORYLINE == 1 || ($GAME_STORYLINE >= 3 && $@MK_THROTTLE >= gettimetick(2)) )){
        // We should decide event kind, but that's NYI
        announce ("Monster King: I smell humans! Humans must die!"), bc_map|bc_npc;

        getmapxy(.@m$, .@x, .@y, UNITTYPE_MOB, $@MK);

        // Spawn stuff
        areamonster(.@m$, .@x-20, .@y-20, .@x+20, .@y+20, "Monster", ManaGhost, min(60, $@MK_AGGRO/10)+.nearby, "Monster King::OnSlaveDie");

        // Remove some aggro. TODO: Do not remove so much aggro if it was high
        .@diff=($@MK_AGGRO*$GAME_STORYLINE)/5;
        $@MK_AGGRO=max(.@diff, 0);
    }

    // Maybe, just maybe, game storyline must be updated here
    if ($GAME_STORYLINE == 1 && $MK_TEMPVAR &&
        $MK_TEMPVAR <= gettimeparam(GETTIME_DAYOFMONTH)) {
        // Game Story Change: Idle MK -> Active MK
        kamibroadcast("I can't handle it anymore! NO MORE!", "Monster King");
        sleep(2500);
        kamibroadcast("Come, my minions! Lay siege to towns! LEAVE NO OPPOSITION TO ME!", "Monster King");
        sleep(2500);
        kamibroadcast("Burn, destroy, do whatever you need, until your last breath, my lieutenants and colonels!", "Monster King");
        sleep(2500);
        kamibroadcast("##4 .:: Game Story Instructions on #world ::.");
        channelmes("#world", "##1 **GAME STORY CHANGE** - The Monster King minions will now attack cities and lay waste to them.");
        channelmes("#world", "##1 Players must defeat the lieutenants and colonels in order to prevent sieges from continuing.");

        // Apply the changes
        $GAME_STORYLINE=2;
        $MK_TEMPVAR=0;
    }
    if ($GAME_STORYLINE == 2 &&
        $MK_TEMPVAR >= MK_SIEGE_TOTALPOWER) {
        kamibroadcast("##1##BThe Monster King army is in total disarray and disorder!", "Saulc");
        sleep(2500);
        kamibroadcast("##1##BIt's our chance to strike back!", "Saulc");
        sleep(2500);

        // Apply the changes
        $GAME_STORYLINE=3;
        $MK_TEMPVAR=0; // In past, we forced 1 month wait. Now we have KW mechs...
        $MANA_BLVL-=10; // Set level to 20~30
        $MANA_JLVL-=5; // Set job level to 15
    }

    // We're done, restart loop timer
    $@MK_TRIGGERED=false;
    initnpctimer;
    end;
}