summaryrefslogblamecommitdiff
path: root/npc/functions/siege.txt
blob: 284e1fb8b1950c3f43e5d605eecee97af72172bd (plain) (tree)


















                                                                                                                                                      







                                                                                 
             
 
                                                       
                                     




                                                         
                                                 





                                               



                            
 
                                      



                
                                                                                           
 





                            
                                                                                
                         
                                             


                                         
                                          
 
                                                                        
                                                                                                          
                                          
     








                                                                                   
                                                                                


                                                  
                       


                                                              
                 
 
                                
                                                                       
                                                                     








                                     



                                          





                                                                         

















                                            
                                       














                                                        
                                                             
                                         
                      
                                         
                   
 



                                                                          



                                                                                                  
                                                                      
                                                                          


           




                                         



                                                                    




                                           
                                 



                         






































                                                                                  
                                                                                                                                                                     

     




                                            
                         




                                                                                                                                    
                                                                                          


           











                                                           



                                                                      


                                       
                                                          


                                       
                                                          


                                       
                                                          


           




                                            







                                                    















                                                                                                      
// TMW2 scripts.
// Authors:
//    Jesusalva
// Description:
//    Town Siege utilities

// Siege Spawn
// Can be used anywhere to spawn on the whole map, margins respected.
// siege_spawn( map, mobID, Amount, eventID )
function	script	siege_spawn	{
    .@mp$=getarg(0);
    .@mid=getarg(1);
    .@qnt=getarg(2);
    .@ev$=getarg(3);

    areamonster(.@mp$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@mp$)-20, getmapinfo(MAPINFO_SIZE_Y, .@mp$)-20, strmobinfo(1, .@mid), .@mid, .@qnt, .@ev$);
    return;
}

// Calculate player average level
// if highest is set, it will return highest player level, with minimum the value
// passed. (A level "0" is clearly not valid, of course)
// siege_calcdiff ( map{, highest_lvl} )
function	script	siege_calcdiff	{
    .@bsum=0;
    .@highest=getarg(1, false);
    .@c = getunits(BL_PC, .@players, false, getarg(0));
    .@skip=0;

    // There is at least one player, do things properly
    for (.@i = 0; .@i < .@c; .@i++) {
        /*
        // Dead players are not counted
        if (ispcdead(strcharinfo(0, "", .@players[.@i])))
            continue;
        */
        .@b=readparam(BaseLevel, .@players[.@i]);

        // GMs are not counted
        if (getgroupid(.@players[.@i]) >= 60) {
            .@skip+=1;
            .@b=0;
        }
        .@bsum+=.@b;
        if (.@b > .@highest)
            .@highest=.@b;
    }

    // Sanitize and fallback if needed
    .@c-=.@skip;
    if (!.@c)
        .@c=1;

    //debugmes "calcdiff: Total %d Average %d Highest %d", .@bsum, (.@bsum/.@c), .@highest;

    if (getarg(1,false))
        return .@highest;
    else
        return (.@bsum/.@c);
}

// push to $@SIEGE_TMPMOBS the <mobID> if their level is within a x levels range
// above or below <level>
// siege_push ( mobID, {level{, variation}} )
function	script	siege_push	{
    .@mi=getarg(0);
    .@lv=getarg(1,0);
    .@var=getarg(2,10); // Old Default: 15

    if ( is_between(.@lv-.@var, .@lv+(.@var/2), strmobinfo(3, .@mi)) ) {
        //debugmes "Monster %s (%d) level %d ~= %d", strmobinfo(1, .@mi), .@mi, strmobinfo(3, .@mi), .@lv;
        array_push($@SIEGE_TMPMOBS, .@mi);
    }
    return;
}

// Selects a monster based on player average strength and base difficulty
// It'll select monsters from 20 levels below to 20 levels above
// tp_mask is the same as TP_* constants and changes mobs present. Only TP_TULIM,
// TP_HURNS and TP_NIVAL are supported. You can use them with the "|" operand, eg.,
// TP_TULIM | TP_HURNS.
//
// It currently only creates $@SIEGE_TMPMOBS, you need to use any_of() manually.
// siege_selectmob ( blvl, difficulty{, tp_mask} )
function	script	siege_selectmob	{
    .@blv=getarg(0);
    .@dif=getarg(1, 0);
    .@tp=getarg(2, 0);

    // We don't need .@dif, so we convert difficulty to levels
    .@blv+=.@dif;

    deletearray $@SIEGE_TMPMOBS;
    setarray $@SIEGE_TMPMOBS, ManaGhost, CandiedSlime, Bif, SlimeBlast;
    // Now we must select mobs, using array_push() to $@SIEGE_TMPMOBS
    // First, mobs on all envs
    siege_push(BlackScorpion, .@blv);
    siege_push(GreenSlime, .@blv);
    siege_push(CaveMaggot, .@blv);
    siege_push(MagicGoblin, .@blv);
    siege_push(AngryBat, .@blv);
    siege_push(BlackSlime, .@blv);
    siege_push(BlackScorpion, .@blv);
    siege_push(Forain, .@blv);
    siege_push(Terranite, .@blv);
    siege_push(JackO, .@blv);
    siege_push(BlackMamba, .@blv);
    siege_push(TerraniteProtector, .@blv);
    siege_push(Reaper, .@blv);

    // What if we are trying to select a boss and they're... overleveled?
    // We need a level 105, 120 and a level 135 monsters
    siege_push(FallenKing2, .@blv);
    siege_push(TerraniteKing, .@blv);

    // Now, mobs on only certain envs
    if (.@tp & TP_TULIM) {
        siege_push(AngryScorpion, .@blv);
        siege_push(AngryRedScorpion, .@blv);
        siege_push(DesertBandit, .@blv);
        siege_push(LavaSlime, .@blv);
        siege_push(OldSnake, .@blv);
        siege_push(Snake, .@blv);
    }
    if (.@tp & TP_HURNS) {
        siege_push(RedSlime, .@blv);
        siege_push(Bandit, .@blv);
        siege_push(RedMushroom, .@blv);
        siege_push(RobinBandit, .@blv);
        siege_push(AngryYellowSlime, .@blv);
        siege_push(GrassSnake, .@blv);
        siege_push(WickedMushroom, .@blv);
        siege_push(GreenDragon, .@blv);
    }
    if (.@tp & TP_NIVAL) {
        siege_push(Bluepar, .@blv);
        siege_push(Wolvern, .@blv);
        siege_push(Yeti, .@blv);
        siege_push(Moggun, .@blv); // PS. Not aggressive
    }

    // Removed
    //siege_push(DarkLizard, .@blv);
    //siege_push(Crafty, .@blv);

    return;
}

/////////////////////////////////////////////////////////////
// Prepare a siege with optional announce
// siege_setup ( map )
function	script	siege_setup	{
    .@m$=getarg(0);

    // Save old map zone
    $@MZONE$[getmapinfo(MAPINFO_ID, .@m$)]=getmapinfo(MAPINFO_ZONE, .@m$);

    // Apply changes
    addmapmask .@m$, MASK_MATTACK;
    changemusic .@m$, any("mythica.ogg", "eric_matyas_ghouls.ogg", "misuse.ogg", "Arabesque.ogg");
    disablenpc("Mana Stone");
    pvpon(.@m$);
    setmapflag(.@m$,mf_zone,"MMO"); // MMO Zone: Overrides GM Commands
    setmapflag(.@m$,mf_bexp,rand(120,140)); // 20~40% EXP UP on siege maps
    return;
}

// Revert what siege_setup did
// siege_revert ( map )
function	script	siege_revert	{
    .@m$=getarg(0);

    // Revert map zone and delete backup
    setmapflag(.@m$,mf_zone,$@MZONE$[getmapinfo(MAPINFO_ID, .@m$)]);
    $@MZONE$[getmapinfo(MAPINFO_ID, .@m$)]="";

    removemapmask .@m$, MASK_MATTACK;
    changemusic .@m$, "caketown.ogg"; // :>
    enablenpc("Mana Stone");
    pvpoff(.@m$);
    removemapflag(.@m$,mf_bexp);
    setmapflag(.@m$,mf_bexp,100);
    killmonsterall(.@m$);
    return;
}

// Create the Siege Boss for #SiegeCtrl utility, DO NEVER CAST TWICE
// siege_boss ( map, difficulty )
function	script	siege_boss	{
    .@m$=getarg(0);
    .@s=getarg(1,0);

    // If Difficulty is 0: There is no boss
    if (!.@s)
        return;

    // We will now prepare the boss
    // It must be stronger than players in at least 15 levels, so the mob group
    // is different. The siege difficulty, as usual, gives an extra level to them.
    .@val=siege_calcdiff(.@m$)+15;
    .@val+=.@s;

    // We must cap this at 100 to prevent running out of monsters
    // Also, .@val can NEVER be less than 50, to prevent cheating :<
    if (.@val > 100)
        .@val=100;
    else if (.@val < 50)
        .@val=50;

    // Get their event/designation
    if (.@val >= 80)
        .@ts$="Colonel";
    else
        .@ts$="Lieutenant";

    // Select a type for them (saved as .@mobId)
    siege_selectmob(siege_calcdiff(.@m$, .@val), .@s);
    array_remove($@SIEGE_TMPMOBS, Bif);
    array_remove($@SIEGE_TMPMOBS, CandiedSlime);
    array_remove($@SIEGE_TMPMOBS, ManaGhost);
    array_remove($@SIEGE_TMPMOBS, SlimeBlast);
    if (array_entries($@SIEGE_TMPMOBS) > 0) {
        .@mobId=any_of($@SIEGE_TMPMOBS);
    } else {
        .@mobId=Yetifly;
        Exception("[WARNING] Insufficient monsters in database: Highlight @jesusalva - Broken reference: "+siege_calcdiff(.@m$, .@val), RB_DEBUGMES|RB_IRCBROADCAST);
    }

    // We want spawn point to be fixed
    .@lx=array_find($@LOCMASTER_MAP$, .@m$);
    .@xm=$@LOCMASTER_X[.@lx];
    .@ym=$@LOCMASTER_Y[.@lx];

    // Announce and spawn
    areamonster(.@m$, .@xm-1, .@ym-1, .@xm+1, .@ym+1, .@ts$+" "+strmobinfo(1, .@mobId), .@mobId, 1, "#SiegeCtrl::On"+.@ts$+"Death");

    // Spawn some scouts
    areamonster(.@m$, .@xm-1, .@ym-1, .@xm+1, .@ym+1, "Scout", any(GreenSlime,RedSlime,AngryYellowSlime), 3);

    announce("##1The Monster "+.@ts$+" arrived! It is a "+strmobinfo(1, .@mobId), bc_all);
    return;
}

// Spawn some monsters
// siege_cast ( map, NPCName, {, difficulty{, tpflag}} )
function	script	siege_cast	{
    // mz - map ; n - name ; d - difficulty ; tp - teleport
    // a - ammount ; e - mobId
    .@mz$=getarg(0);
    .@n$=getarg(1);
    .@d=getarg(2,0);
    .@tp=getarg(3,0);

    siege_selectmob(siege_calcdiff(.@mz$), .@d, .@tp);

    // How many monsters? This value is multiplied by 3;
    // 1 per player (= 3 mobs), 1 each 5 difficulty, 1 always present.
    .@a=getmapusers(.@mz$);
    .@a=(.@d/5)+1;

    .@e=any_of($@SIEGE_TMPMOBS);
    array_remove($@SIEGE_TMPMOBS, .@e);
    siege_spawn(.@mz$, .@e, .@a, "#SiegeCtrl::OnRespawn");

    .@e=any_of($@SIEGE_TMPMOBS);
    array_remove($@SIEGE_TMPMOBS, .@e);
    siege_spawn(.@mz$, .@e, .@a, "#SiegeCtrl::OnRespawn");

    .@e=any_of($@SIEGE_TMPMOBS);
    array_remove($@SIEGE_TMPMOBS, .@e);
    siege_spawn(.@mz$, .@e, .@a, "#SiegeCtrl::OnRespawn");
    return;
}


// Utility NPC
-	script	#SiegeCtrl	NPC_HIDDEN,{
    end;

OnRespawn:
    if (playerattached()) {
        getmapxy(.@m$,.@x,.@y,0);
        if (rand(10000) <= $coinsrate)
            makeitem StrangeCoin, 1, .@m$, .@x, .@y;
    }
    end;

// Boss Death Labels
OnLieutenantDeath:
    getitem StrangeCoin, 1;
    mapannounce(getmap(), l("##2The Monster Lieutenant was defeated by @@!", strcharinfo(0)), bc_map);
    $MK_TEMPVAR+=1;
    end;

OnColonelDeath:
    getitem StrangeCoin, 5;
    $MOST_HEROIC$=strcharinfo(0);
    mapannounce(getmap(), l("##2The Monster Colonel was defeated by @@!", strcharinfo(0)), bc_map);
    $MK_TEMPVAR+=10;
    end;

}