summaryrefslogblamecommitdiff
path: root/npc/functions/hub.txt
blob: 2290059536ab44aa7b82c16cf85df6b56af51724 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16















                                                
                               
                                                       

                                     
                            
                                                     

                                 






                                         
                                              
 

                              






                                                              
                     
                                                   
                         

                                                          




                                                                                                               
                
                                      
                                  


                                                          
                                                               


                                                       
                             
                                                                       
                                                

                                         
                                          

                                    









                                                   
                                        


                                                                                   
                                                               



                                   
                                                 
                          
                                              

                                                                                                                                    






                                                        







                                                                                  







                                                                                  

                                              
                                              

                                                                



                                            





                                                               
                                                                   
                                  



                                                         







                                 
                                 
     




                                                              
                                  

                                      
                                             



                                                                                                            
                                               
                                   


                                         









                                                                         
                                         
                                     
                                              









                                                         
              


                                                                                                                              
                                     



                                              
                                               




                                                                                                             
                           
                                                                                   




                                                       

                     












                                                                                                                                                          
                           
                  
                                      










                                                    

                                             


           

                                         

                            
                                                                                                             

                                                      


               




                                                                                 

                                                                                                         
                                 
                  
                             
                                                     


                                                   







                                                                                      




                                                                                 
                                                                                              
                                              
                                                                
                                                                                                                                                                                 


                                                              

                         
                                                      

                          
                                                                                 



                                  





                             


                          


                          
                        
                                   
                  
                               



                                                                                
                           
                                             
                  

                            
                                           

                           
                              
                                           


                           
                                           


                                
                                           


                           
                                           


                            
                                           


                                
                                           


                               
                                           


                              
                                           
                  
                                 
                           
                                                                                   
                                                                          
                  
                                        
                   





                                                                
                                                                         
                 
                                    
                  
                                        
                             
                           
                                  
                                              
                                                                        
                           
                                        

                          

                                                                   
                                        

                             
                           
                                   

                                                                                                
                                        
                  
                                        
                          
                                                  
                            
                                   
                              
                                                                            
                                                                          
                                         

                           
                                   
                                
                               
                                                                                      
                                                                           
                                         

                             
                                   
                                
                                         
                                                                                      
                                                                                                                 
                                         
                  



                                        

                                         


                                                                     
                                          
                  
                            

                                         
                                                           
                                                                    
                                          
                  
                           



                                           
                                

                                                                      
                                          
                  

                                        
                                         
                              

                                         
                                                           
                                              
                  
                                

                                         
                                                           
                                              
                  
                          

                                         

                                                                     
                                              
                  







                                                                             
                                         





                                                                                       
                                                                                                               
                                         




                                     
                                                                                           
                                                                                                  
                                                             
                                         
                  

                                        
                                                    


                                         
                                     
                                                            
                                                                      


                                             
                                   

                                         
                                    
                                                                      
                                                                                                                  











                                                                         
          
 
                                       





                                                                            

                        
                                              


                        
                                   

                                                                



                                                                                   

                                    
                  

                                   
                  
 


 
 

                                            
                                
                                                             






















                                            
 


























                                                                              
                                                 


                                                     

                               
                                 
                                                                                
                                             
                  
                                




                                                      

                                        

                                                                                
                                             
                  
                                






                                                      

                                        

                                                                                
                                             
                  
                       








                                                      

                                        

                                                                                
                                             
                  
                             










                                                      

                                        

                                                                             
                                             
                  
 

                                        







































                                                                                                                
                              

                           
                                 


                                                 
                                                                                
                       
                                                                                
                       
                                                                                


                             
                                 


                                                 
                                                                                
                       
                                                                                
                       
                                                                                
                       
                                                                                
                       
                                                                                


                           
                                 


                                                 
                                                                                  
                                                                             
                       
                                                                              
                       
                                                                              
                       
                                                                             
                       
                                                                             
                       
                                                                               
                       
                                                                              
                       


                                                                                            
                  

                                        
                      


                        


                         


                           
                                   
                         
                                  

                                                           
                  
                                 








                                                        


                                           
                                        


                                                                                        
                               

                                                                                                   


                                                                                          
                               









                                                                         





                                                                            
                                      
             

                                            







                                             







                                               
                  
                        

                                                
                                       
                      













                                                                     

                                    




                                        

                          
                            
                              

                           
                         
                         






                                             


            
                      




                                                         


           



 


                                                                             







                                      
                                             

                                                      
                  
                               
 
                                  
                         
                          
                           
                           

                                            
                                                            

                                             

         


                                                        
                                                                                                                                                                     

         


                                     
                        
                                        
                             

                                               

     


                                                                



                                                                        














                                                                                 
                               

                                                                            
         







                                                                       



                                         
                        






























                                  
                          















                                       


                                     


                                    








                                                        

                                                        


           
// TMW2 scripts.
// Authors:
//    Jesusalva
//    TMW Org.
// Description:
//    HUB functions (Login, Logout, Death)

// HUB_Login ()
function	script	HUB_Login	{
    getmapxy(.@mapa$, .@a,.@b, 0);

    // Login on Blue Sage Workshop/Library
    if (.@mapa$ == "020-7-1") {
        addtimer(1000, "#BlueSageHUB::OnCycle");
    }

    // Random Treasure cleaning
    if (CHAREG_CLEANUP < gettimetick(2)-CHEST_WAITTIME)
        deletearray RNGTREASURE_DATE;

    // PVP Cooldown cleaning
    if (CHAREG_CLEANUP < gettimetick(2)-PVP_WAITTIME)
        deletearray PVP_COOLDOWN;

    return;
}

// HUB_Logout ( {dead} )
function	script	HUB_Logout	{
    .@dead=getarg(0, false);
    getmapxy(.@mapa$, .@a,.@b, 0);
    .@zone$=getmapinfo(MAPINFO_ZONE, .@mapa$);

    // Hardcore Server
    if ($HARDCORE && .@dead) {
        // Update Absolutions
        if (ABSOLVE_DAY != gettimeparam(GETTIME_DAYOFMONTH)) {
            ABSOLVE_DAY=gettimeparam(GETTIME_DAYOFMONTH);
            ABSOLVE_CNT=0;
        }

        // Main Loop
        if (@grace) {
            // Grace is upon you (ie. script death)
            @grace=false;
        } else if (.@zone$ == "MMO" && ABSOLVE_CNT <= 3) {
            // Absolve (limited attempts)
            ABSOLVE_CNT+=1;
            dispbottom l("This is a special map so your death is not counted.");
            dispbottom b(l("You have %d non-counting deaths remaining today.", 3-ABSOLVE_CNT));
            if (ABSOLVE_CNT == 3)
                dispbottom col(l("WARNING: if you die again today in a special map it will be PERMANENT."), 1);
        } else {
            // Meet your final demise!
            atcommand("@dropall");
            makeitem CoinBag, Zeny/500, .@mapa$, .@a, .@b;
            Zeny=0;
            //resetlvl(2); // FIXME: Split the exp
            // TODO: Warp back to Candor or it'll be unplayable
            // TODO: It could be @jail, but it is buggy
            atcommand("@jailfor 1d "+strcharinfo(0));
        }
    // Vanished on Cindy Cave
    } else if (.@mapa$ == "021-4" && strcharinfo(0) == $@CINDY_HERO$) {
        donpcevent("Cindy#Outside::OnReckless");
        recovery(getcharid(3));
        warp any("010-1", "010-2"), 0, 0;
        sc_start2 SC_POISON, 1, 90, 10000;
        die();
        if (!$HARDCORE) heal -1, -1;
    } else if (.@mapa$ == "021-4") {
        .@pl = getmapusers("021-4")-1;
        if (.@pl < 1)
            donpcevent("Cindy#Outside::OnCleanUp");
        recovery(getcharid(3));
        warp "Save", 0, 0;
    }
    // Logout while donating blood
    if (getq(HurnscaldQuest_BloodDonor) == 2) {
        slide 35, 28;
        setpcblock(PCBLOCK_SOFT, false);
        setq HurnscaldQuest_BloodDonor, 0, gettimetick(2)+3600; // one hour penalty
    }
    // Logout/Death on Nard's ship hold
    if (compare(.@mapa$, "002-2") || compare(.@mapa$,"nard")) {
        setq2 ShipQuests_Peter, 0;
        setq3 ShipQuests_Peter, -1;
    }
    // Logout on botcheck area
    if (compare(.@mapa$,"botcheck") && !.@dead) {
        if (!is_staff()) {
            atcommand "@jail "+strcharinfo(0);
            rodex_sendmail(getcharid(0), "TMW2 Team", "Error detected!", "Please contact GM Team, error code: BOTCHECK-AUTOJAILED");
        }
    }
    // Died on Terranite Cave where exp penalty is lower
    if (.@mapa$ == "015-6" && .@dead) {
        @deathpenalty_override=2;
        @deathpenalty_realvalue=readparam(BaseExp);
        @deathpenalty_realvaljob=readparam(JobExp);
    }
    // Died or logged out at Tulimshar Arena (FIXME)
    if (compare(.@mapa$, "ARENA")) {
        if ('UDTf) {
            'UDTf=0;
            killmonster(getmap(), instance_npcname("Arnea#003-13")+"::OnGladius");
            deltimer(instance_npcname("Arnea#003-13")+"::OnVerify");
        }
    }
    // Died or logged out at Candor Battle
    if (.@mapa$ == "006-1") {
        if (@crazypoints > CRAZYPOINTS) {
            CRAZYPOINTS=@crazypoints;
            dispbottom l("Crazyfefe Cave: New Highscore: @@ points", CRAZYPOINTS);
            @crazypoints=0;
        }
    }
    // Died or logged during Bandit Lord fight
    if (.@mapa$ == "015-2") {
        if (isin("015-2", 228, 227, 282, 280))
            killmonster("015-2", "#BanditLordDen::OnLordDeath");
    }
    // Died or logged out on Blue Sage House
    if (.@mapa$ == "020-7-1") {
        callfunc("BSClearNest", @nestid);
    }
    // Died or logged out on Player Story 2 - Magic School Port
    if (compare(.@mapa$, "0030")) {
        if (@ASSASSIN > 0)
            delcells "MQ2Wall"+getcharid(0);
        killmonsterall(getmap());
    }
    // Died or logged out on Player Story 5 - Forgotten Throne Room
    if (compare(.@mapa$, "hmc")) {
        if (@instid > 0)
            .@n$=instance_npcname("#Core02331", @instid);
        else
            .@n$=instance_npcname("#Core02331");
        deltimer(.@n$+"::OnW01");
        deltimer(.@n$+"::OnW02");
        deltimer(.@n$+"::OnE07");
        deltimer(.@n$+"::OnE08");
        deltimer(.@n$+"::OnE09");
        deltimer(.@n$+"::OnE10");
        deltimer(.@n$+"::OnE11");
        deltimer(.@n$+"::OnE12");
        killmonsterall(getmap());
    }
    // Died or logged out on Player Story 6 - Forgotten Shrine
    if (compare(.@mapa$, "brb3")) {
        //.@n$=instance_npcname("#Core02331");
        .@q=getq(LoFQuest_Barbara);
        // Reset quest to: Forgotten Chamber Puzzle incomplete
        if (.@q < 4 && .@q >= 2) {
            setq1 LoFQuest_Barbara, 1;
            setq3 LoFQuest_Barbara, 1;
            // FIXME: Enable Mana Stone#01863
            dispbottom col(l("WARNING: You died at Forgotten Shrine and the Shrine defense triggered."), 1);
            dispbottom col(l("WARNING: Your progress on the quest was lost!"), 1);
        }
    }
    // Died or logged out during Sagratha Fight
    if (compare(.@mapa$, "sgt2")) {
        setq1 HurnscaldQuest_Sagratha, 3;
        setq3 HurnscaldQuest_Sagratha, 0;
    }
    // First death produces a warning message
    if (PC_DIE_COUNTER <= 1 && .@dead) {
        dispbottom l("Dying outside a town square will cause EXP loss.");
    }
    // If you were travelling and died/logged out, cleaning is needed
    if (@timer_navio_running) {
        @timer_navio_running=0;
        // Logged out? Correct your position to inside the ship
        // Of course, this is messy... But still better than Save Point
        if (!.@dead) {
            if (compare(.@mapa$, "016-"))
                warp "016-1", 28, 27;
            else if (compare(.@mapa$, "002-"))
                warp "002-1", 55, 40;
            else
                warp "Save", 0, 0;
        }
    }
    // Crazyfefe hot fix
    if (.@dead) {
        // It was PK
        if (killerrid > 2000000 && killerrid < 2100000) {
            // PVP flag was off
            /*
            if (!getmapflag(.@mapa$, mf_pvp) && !getmapflag(.@mapa$, mf_pvp_noparty) && !getmapflag(.@mapa$, mf_pvpnoguild)) {
                recovery(getcharid(3));
                warp .@mapa$, .@a, .@b;
                percentheal 100, 100;
                dispbottom l("REVENGE TIME!");
                .@trueid=getcharid(3);
                //detachrid();
                attachrid(killerrid);
                setpcblock(PCBLOCK_SOFT, true);
                sc_start SC_WALKSPEED,120000,50;
                sc_end SC_CASH_PLUSEXP;
                sc_end SC_OVERLAPEXPUP;
                sc_start SC_OVERLAPEXPUP, 300000, -20;
                dispbottom l("For cowardingly killing in a \"secure\" area, you will be severely punished.");
                //Karma+=1;
                sc_start SC_STUN, 15000, 1, 10000, SCFLAG_NOAVOID|SCFLAG_FIXEDTICK;
                addtimer(15000, "#mobptsys::OnUnlock");
                percentheal -88, -100;
                detachrid();
                attachrid(.@trueid);
            }
            */
            HONOR+=1;
        }
    }

    // This allows code to override death penalty, just once:
    // @deathpenalty_override
    // Valid values: 1- No penalty. 2- Halved penalty.
    // You must also set: @deathpenalty_realvalue and @deathpenalty_realvaljob
    if (@deathpenalty_override && .@dead) {
        if (is_staff())
            debugmes("Old values: %d %d Current Values: %d %d", @deathpenalty_realvalue, @deathpenalty_realvaljob, readparam(BaseExp), readparam(JobExp));
        addtimer(300, "#QuirinoHUB::OnNoPenaltyCommand");
    }

    // Register logout time
    if (!.@dead) {
        CHAREG_CLEANUP=gettimetick(2);
        // Send updates to Vault API
        if (##VAULT) {
            .@api$=json_encode("UID", ##VAULT,
                               "GID", getcharid(3),
                               "VAR1N", "HELLO",
                               "VAR1V", ##01_HELLO,
                               "VAR2N", "WORLD",
                               "VAR2V", ##01_WORLD);
            api_send(API_FLUSHVAULT, .@api$);
        }
    }

    callfunc "02524_Avenge_BlackBox", .@dead;
    return;
}

// HUB_SkillInvoke (  )
function	script	HUB_SkillInvoke	{
    // Something is... wrong
    if (!@skillId) {
        Exception("ILLEGAL SKILL PASSED TO HUB. It has been compromised, Jim.", RB_DEBUGMES|RB_IRCBROADCAST);
        debugmes "Legal Caster: %s", strcharinfo(0);
        debugmes "Effective Caster: %d", @skillCaster;
        return;
    }

    // Homunculus Cycle
    /* *********************************************************************** */
    //debugmes "Skill caster %d", @skillCaster;
    if (@skillCaster != getcharid(3)) {
        switch (@skillId) {
        case TMW2_SKILLX:
            sc_start SC_RICHMANKIM, 180000, @skillLv+rand2(9*@skillLv), 10000, SCFLAG_NONE, @skillTarget;
            gethomunexp @skillLv;
            break;
        case TMW2_HOMUN_HEAL:
            .@heal=gethominfo(6)*(5+rand2(@skillLv));
            heal .@heal, 0;
            harm(@skillCaster, -.@heal, HARM_MISC);
            break;
        case TMW2_LITTLE_WONDERS:
            sc_end SC_POISON;
            sc_end SC_CURSE;
            sc_end SC_SILENCE;
            sc_end SC_CONFUSION;
            sc_end SC_BLIND;
            sc_start SC_CURSE, rand2(3500, 5000), 1, 10000, SCFLAG_NONE, @skillCaster;
            break;
        }
        return;
    }
    /* *********************************************************************** */

    // TODO: Detect what was script-cast and what was player-case. Then, readd RB_IRCBROADCAST
    // If you can't do this: You can't do this
    if (getskilllv(@skillId) < @skillLv && @skillId != BS_GREED)
        Exception("System ERROR, HSI."+@skillId+" INVALID CAST (got "+@skillLv+" expected "+getskilllv(@skillId)+", sub-LC."+(getcharid(3)-2000000)+")", RB_DEBUGMES|RB_ISFATAL);
    // You are AFK for over 3 minutes, that's crazy, disregard
    if (checkidle() > 180)
        return;

    // Record to database
    skillInvoke[@skillId] = skillInvoke[@skillId] + 1;

    // Script-based skills
    /* *********************************************************************** */
    switch (@skillId) {
        case TMW2_FAKESKILL:
            atcommand("@refresh");
            break;
        case TMW2_FAKESKILL2:
            CMD_toevent();
            break;
        case TMW2_CRAFT:
            UserCtrlPanel();
            break;
        case TMW2_OVHFIRE:
            SK_OVHFire();
            break;
        case TMW2_MPREGEN:
            SK_mpregen();
            break;
        case TMW2_STUDY:
            SK_study(@skillTarget);
            break;
        case EVOL_AREA_PROVOKE:
            if (@skillTargetX && @skillTargetY)
                massprovoke(1+@skillLv, getmap(), @skillTargetX, @skillTargetY);
            else
                massprovoke(1+@skillLv);
            // SC_PROVOKE ?
            GetManaExp(@skillId, rand2(1,3));
            break;
        case TMW2_GD_INCALL:
            GD_allboost();
            GetManaExp(GD_DEVELOPMENT, 10);
            break;
        case TMW2_GD_REGEN:
            GD_regenerating();
            GetManaExp(GD_DEVELOPMENT, 10);
            break;
        case TMW2_GD_DEFUP:
            GD_defboost();
            GetManaExp(GD_DEVELOPMENT, 10);
            break;
        case TMW2_GD_BATTLEPLAN:
            GD_atkboost();
            GetManaExp(GD_DEVELOPMENT, 10);
            break;
        case TMW2_GD_ATKUP:
            GD_atkboost2();
            GetManaExp(GD_DEVELOPMENT, 10);
            break;
        case TMW2_GD_CRITUP:
            GD_critboost();
            GetManaExp(GD_DEVELOPMENT, 10);
            break;
        case TMW2_GD_AUTOREVIVE:
            GD_autorevive();
            GetManaExp(GD_DEVELOPMENT, 10);
            break;
        case TMW2_GDP_MAXPOWER:
            SK_maximizepower();
            GetManaExp(GD_DEVELOPMENT, 10);
            break;
        case TMW2_GDP_SPREGEN:
            SK_spregen();
            GetManaExp(GD_DEVELOPMENT, 10);
            break;
        // Weapon Overload attack
        case TMW2_OVERLOAD:
            .@PW=200+(@skillLv > 3 ? @skillLv : 0)+(@skillLv > 7 ? @skillLv*2 : 0);
            areaharm(@skillTarget, 0, AdjustAttackpower(.@PW), HARM_MISC);
            break;
        ////////////////////////////////
        // Magic v3
        // The basic offensive skill from Trickmaster
        case TMW2_MANABOMB:
            // This skill takes 100% mana for a 1:1 ratio damage
            // And is a trick. Each level improves ratio in 1
            // Has no cooldown, so it is powerful with pots
            // And is a good starter offensive skill
            areaharm(@skillTarget, 0, Sp*@skillLv, HARM_MISC, Ele_Ghost);
            Sp=0;
            GetManaExp(@skillId, 1);
            break;
        ////////////////////////////////
        // XXX: Healing Class
        case TMW2_FIRSTAID:
            .@PW=90+(10*@skillLv);
            // First aid only works on you, so
            .@heal=max(AdjustSpellpower(.@PW), AdjustAttackpower(.@PW));
            heal .@heal, 0;
            GetManaExp(TMW2_HEALING, 1);
            break;
        case TMW2_HEALING:
            .@PW=130+(20*@skillLv);
            harm(@skillTarget, -AdjustSpellpower(.@PW), HARM_MISC);
            GetManaExp(TMW2_HEALING, 2);
            break;
        case TMW2_MAGNUSHEAL:
            // Area healing
            .@PW=200+(20*@skillLv);
            .@RG=4+(@skillLv/5);
            areaharm(@skillTarget, .@RG, -AdjustSpellpower(.@PW), HARM_MISC, "filter_friendly");
            GetManaExp(TMW2_HEALING, 3);
            break;
        ////////////////////////////////
        // XXX: Fire Class
        // (May burn targets for damage over time)
        case TMW2_FIREARROW:
            .@PW=140+(10*@skillLv);
            // 4% chance, 2.5s
            harm(@skillTarget, AdjustSpellpower(.@PW), HARM_MAGI, Ele_Fire);
            sc_start SC_BLOODING, 4500, 1, 400, SCFLAG_NONE, @skillTarget;
            GetManaExp(TMW2_FIREBALL, 1);
            break;
        case TMW2_FIREBALL:
            .@PW=140+(10*@skillLv);
            .@RG=2+(@skillLv/5);
            // 22% chance, 2.5s
            areaharm(@skillTarget, .@RG, AdjustSpellpower(.@PW), HARM_MAGI, Ele_Fire);
            sc_start SC_BLOODING, 2500, 1, 4200, SCFLAG_NONE, @skillTarget;
            GetManaExp(TMW2_FIREBALL, 2);
            break;
        case TMW2_ARMAGEDDON:
            .@PW=140+(10*@skillLv);
            .@RG=5+(@skillLv/5);
            // 18% chance, 3s, 3x3 radius
            areaharm(@skillTarget, .@RG, AdjustSpellpower(.@PW), HARM_MAGI, Ele_Fire);
            areasc(.@RG, 6000, SC_BLOODING, BL_MOB|BL_PC|BL_HOM|BL_MER, 1, "filter_hostile", @skillTarget, 1800);
            GetManaExp(TMW2_FIREBALL, 3);
            break;
        ////////////////////////////////
        // XXX: Holy Class
        // (Single DPS + AOE)
        case TMW2_NAPALMBEAT:
            .@PW=35+(5*@skillLv);
            .@dmg=AdjustSpellpower(.@PW);
            .@RG=2+(@skillLv/3);
            harm(@skillTarget, .@dmg/10, HARM_MAGI, Ele_Holy);
            areaharm(@skillTarget, .@RG, .@dmg, HARM_MAGI, Ele_Holy);
            GetManaExp(TMW2_HOLYLIGHT, 1);
            break;
        case TMW2_HOLYLIGHT:
            .@PW=125+(25*@skillLv);
            .@dmg=AdjustSpellpower(.@PW);
            harm(@skillTarget, .@dmg, HARM_MAGI, Ele_Holy);
            areaharm(@skillTarget, 1, .@dmg/5, HARM_MAGI, Ele_Holy);
            GetManaExp(TMW2_HOLYLIGHT, 2);
            break;
        case TMW2_JUDGMENT:
            .@PW=250+(50*@skillLv);
            .@SPW=60+(15*@skillLv);
            .@dmg=AdjustSpellpower(.@PW);
            .@dsub=AdjustSpellpower(.@SPW);
            .@RG=3+(@skillLv/5);
            harm(@skillTarget, .@dmg, HARM_MAGI, Ele_Holy);
            areaharm(@skillTarget, .@RG, .@dsub, HARM_MAGI, Ele_Holy);
            GetManaExp(TMW2_HOLYLIGHT, 3);
            break;
        ////////////////////////////////
        // XXX: Wind Class
        // (Smaller cooldown than others)
        case TMW2_MAGICSTRIKE:
            .@PW=125+(25*@skillLv);
            .@dmg=AdjustSpellpower(.@PW);
            harm(@skillTarget, .@dmg, HARM_MAGI, Ele_Wind);
            GetManaExp(TMW2_LIGHTNINGBOLT, 1);
            break;
        case TMW2_LIGHTNINGBOLT:
            .@PW=150+(50*@skillLv);
            .@dmg=AdjustSpellpower(.@PW);
            harm(@skillTarget, .@dmg, HARM_MAGI, Ele_Wind);
            GetManaExp(TMW2_LIGHTNINGBOLT, 2);
            break;
        case TMW2_TEMPEST:
            .@PW=125+(25*@skillLv);
            .@dmg=AdjustSpellpower(.@PW);
            .@RG=2+(@skillLv/5);
            areaharm(@skillTarget, .@RG, .@dmg, HARM_MAGI, Ele_Wind);
            GetManaExp(TMW2_LIGHTNINGBOLT, 3);
            break;
        ////////////////////////////////
        // XXX: Ice Class
        // (May freeze the targets)
        case TMW2_FROSTDIVER:
            .@PW=80+(10*@skillLv);
            // 22% chance, 2.5s
            harm(@skillTarget, AdjustSpellpower(.@PW), HARM_MAGI, Ele_Water);
            sc_start SC_FREEZE, 2500, 1, 2200, SCFLAG_NONE, @skillTarget;
            GetManaExp(TMW2_NILFHEIM, 1);
            break;
        case TMW2_FROSTNOVA:
            .@PW=80+(10*@skillLv);
            .@RG=2+(@skillLv/5);
            // 18% chance, 3s, 3x3 radius
            areaharm(@skillTarget, .@RG, AdjustSpellpower(.@PW), HARM_MAGI, Ele_Water);
            areasc(.@RG, 3000, SC_FREEZE, BL_MOB|BL_PC|BL_HOM|BL_MER, 1, "filter_hostile", @skillTarget, 1800);
            GetManaExp(TMW2_NILFHEIM, 2);
            break;
        case TMW2_NILFHEIM:
            // Nilfheim cast on self?
            .@PW=80+(10*@skillLv);
            .@RG=4+(@skillLv/5);
            areaharm(getcharid(3), .@RG*3/2, AdjustSpellpower(.@PW), HARM_MAGI, Ele_Water);
            areasc(.@RG, 15000, SC_FREEZE, BL_PC | BL_MOB | BL_MER | BL_HOM, 1, "filter_hostile");
            // Maybe filter_notme() would work better, indeed
            GetManaExp(TMW2_NILFHEIM, 3);
            break;
        ////////////////////////////////
        // XXX: Earth Class
        // DEF Effects at Gaia Break, more expensive
        case TMW2_METEORSTRIKE:
            .@PW=130+(20*@skillLv);
            .@dmg=AdjustSpellpower(.@PW);
            .@TM=1200+(@skillLv*300);
            harm(@skillTarget, .@dmg, HARM_MAGI, Ele_Earth);
            sc_start SC_STUN, .@TM, 1, 800, SCFLAG_NONE, @skillTarget;
            GetManaExp(TMW2_METEORSTRIKE, 1);
            break;
        case TMW2_METEORSHOWER:
            .@PW=130+(15*@skillLv);
            .@dmg=AdjustSpellpower(.@PW);
            .@RG=3+(@skillLv/5);
            .@TM=800+(@skillLv*200);
            areaharm(@skillTarget, .@RG, .@dmg, HARM_MAGI, Ele_Earth);
            areasc(.@RG, .@TM, SC_STUN, BL_MOB | BL_PC | BL_HOM | BL_MER, 1, "filter_hostile", @skillTarget, 800);
            GetManaExp(TMW2_METEORSTRIKE, 2);
            break;
        case TMW2_GAIABREAK:
            .@PWA=170+(30*@skillLv);
            .@PWB=110+(10*@skillLv);
            .@dmg=AdjustSpellpower(.@PWA);
            .@dsub=AdjustSpellpower(.@PWB);
            harm(@skillTarget, .@dmg, HARM_MAGI, Ele_Earth);
            rectharm(@skillTarget, 2, 5, .@dsub, HARM_MAGI, Ele_Earth);
            areasc(2, 5000, SC_INCDEFRATE, BL_PC, 10, "filter_friendly");
            GetManaExp(TMW2_METEORSTRIKE, 3);
            break;
        /*

        // TODO: Ultimate Skills (T5/0)
        // Sanctum: AoE resurrection, HP like Resurrect, 30min+ cooldown and
        // inflict ailment on caster.
        // [Ultimate] revives the whole map, like @raisemap
        case TMW2_SANCTUM:
            SK_sanctum();
            break;

        // Support magic
        // STATUS: Awaiting for Alchemy rework
        // TODO: Debuffs
        // TODO: Buffs

        // XXX: Resurrection skills
        // [MAPZONE] Need special care because scripts
        // [WIP] Maybe a custom recovery and a flag @canRevive ?
        // ---------------------------------------------
        // Revive: Makes char alive with 5% HP/Lvl
        // Resurrect: Makes char alive with ±80% HP and give a protection SC (lvl)
        // Redemption: AoE resurrection (HP works like revive, though)
        case TMW2_REVIVE:
            SK_revive(@skillTarget);
            break;
        case TMW2_RESSURECT:
            SK_ressurect(@skillLv);
            break;





        // Physical Class - mostly builtin
        // TODO: Archery effect-absorb skill
        case TMW2_ARROWOFDEVOUR:
            //.@x=getstatus(SC_POISON)+getstatus(SC_DPOISON);
            // if SC_POISON or SC_DPOISON
            break;
        case TMW2_ARROWOFURGES:
            // if SC_SILENCE or SC_FEAR
            break;
        case TMW2_ULTIMATEARROW:
            // if SC_BLIND or SC_BLOODING
            break;
        case TMW2_EXECUTION:
            // if SC_CURSE or SC_FEAR
            break;
        case TMW2_SHATTERARROW:
            // if SC_STONE or SC_STUN
            break;
        case TMW2_ARROWOFADVANTAGE:
            // IF SC_BURNING or SC_CONFUSION
            break;
        case TMW2_WAKENINGARROW:
            // if SC_SLEEP or SC_DEEP_SLEEP
            break;
        case TMW2_BURNINGARROW:
            // if SC_FREEZE or SC_COLD
            break;


        // TODO Assassin skill
        // Higher chance of success if monster HP+ATK < your own HP
        // (Maybe put level on that?) Never works on boss
        // Maybe arrow only?
        case TMW2_ASSASSINATE:
            // SC_COMA TODO
            break;

        case TMW2_SNARE:
            // 100.00% inflict STUN/SLEEP/whatever
            // Does not work on boss monsters
            // (Maybe the one which makes next hit critical?)
            // Was it SC_STONE?
            break;
        // Arrow pierce? (Maybe arrow shot disregarding defense, HARM_MISC ?)


        case TMW2_RICHNESS:
            // Passive, bonus2 bAddGetZenyNum, 5, 100; - Better not
            break;
        // TODO: Effect resisting passives?
        // Windwalker... No wait.
        // Immunity to knockback? Meeeeh. Easier to have a trait-giving quest.
        // After all, we have about 20 traits and you can only pick 5.


        // XXX: Sword skills are a 5-skills combo
        // No cast time, but cooldown present
        // DEF lowers as cast, damage based on combo.
        case TMW2_HORIZONTALSLASH:
            .@PW=100;
            .@PW+=(5*@skillLv);
            @SCombo=@skillTarget;
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            GetManaExp(@skillId, rand2(1,3));
            break;
        case TMW2_DIAGONALSLASH:
            .@PW=100;
            if (LAST_SKILL[0] == TMW2_HORIZONTALSLASH)
                .@PW+=20;
            if (.@PW >= 120)
                .@PW+=30;
            if (@SCombo != @skillTarget)
                .@PW=100;
            .@PW+=(5*@skillLv);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            GetManaExp(@skillId, rand2(1,3));
            break;
        case TMW2_VERTICALSLASH:
            .@PW=100;
            if (LAST_SKILL[0] == TMW2_DIAGONALSLASH)
                .@PW+=30;
            if (LAST_SKILL[1] == TMW2_HORIZONTALSLASH)
                .@PW+=20;
            if (.@PW >= 150)
                .@PW+=100;
            if (@SCombo != @skillTarget)
                .@PW=100;
            .@PW+=(5*@skillLv);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            GetManaExp(@skillId, rand2(1,3));
            break;
        case TMW2_STAB:
            .@PW=100;
            if (LAST_SKILL[0] == TMW2_VERTICALSLASH)
                .@PW+=40;
            if (LAST_SKILL[1] == TMW2_DIAGONALSLASH)
                .@PW+=30;
            if (LAST_SKILL[2] == TMW2_HORIZONTALSLASH)
                .@PW+=20;
            if (.@PW >= 190)
                .@PW+=200;
            if (@SCombo != @skillTarget)
                .@PW=100;
            .@PW+=(5*@skillLv);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            GetManaExp(@skillId, rand2(1,3));
            break;
        case TMW2_GRANDBLAST:
            .@PW=100;
            if (LAST_SKILL[0] == TMW2_STAB)
                .@PW+=50;
            if (LAST_SKILL[1] == TMW2_VERTICALSLASH)
                .@PW+=40;
            if (LAST_SKILL[2] == TMW2_DIAGONALSLASH)
                .@PW+=30;
            if (LAST_SKILL[3] == TMW2_HORIZONTALSLASH)
                .@PW+=20;
            if (.@PW >= 200)
                .@PW+=300;
            if (@SCombo != @skillTarget)
                .@PW=100;
            .@PW+=(5*@skillLv);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Holy);
            GetManaExp(@skillId, rand2(2,3));
            break;

        */
        ////////////////////////////////
        // XXX: Physical Class (Regular)
        case TMW2_FALKONSTRIKE:
            .@PW=100+(25*@skillLv);
            .@ST=0+(10*@skillLv);
            .@TM=100+(90*@skillLv);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            sc_start SC_STUN, .@TM, 1, .@ST, SCFLAG_NONE, @skillTarget;
            GetManaExp(@skillId, rand2(1,3));
            break;
        case TMW2_GROUNDSTRIKE:
            .@PW=50+(40*@skillLv);
            .@dmg=AdjustAttackpower(.@PW);
            .@RG=2+(@skillLv/5);
            .@TM=100+(@skillLv*200);
            .@ST=500+(100*@skillLv);
            .@EF=any(SC_STUN, SC_BLIND, SC_BLOODING, SC_BLIND, SC_BLOODING);
            areaharm(@skillTarget, .@RG, .@dmg, HARM_PHYS, Ele_Neutral);
            areasc(.@RG, .@TM, .@EF, BL_MOB | BL_PC | BL_HOM | BL_MER, 1, "filter_hostile", @skillTarget, .@ST);
            GetManaExp(@skillId, rand2(1,3));
            break;
        case TMW2_SUPREMEATTACK:
            .@PW=100+(50*@skillLv);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            GetManaExp(@skillId, rand2(1,3));
            break;
        ////////////////////////////////
        // XXX: Physical Class (Archery)
        case TMW2_CHARGEDARROW:
            .@PW=100+(50*@skillLv);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            GetManaExp(@skillId, rand2(1,3));
            break;
        case TMW2_ARROWSHOWER:
            .@PW=150+(10*@skillLv);
            .@dmg=AdjustAttackpower(.@PW);
            .@RG=1+(@skillLv/3);
            areaharm(@skillTarget, .@RG, .@dmg, HARM_PHYS, Ele_Neutral);
            GetManaExp(@skillId, rand2(1,3));
            break;
        ////////////////////////////////
        // XXX: Brawling Class
        case TMW2_BRAWLING:
            // 75x3 = 225
            .@PW=70+(5*@skillLv);
            // Using a shield, so power is halved
            if (getequipid(EQI_HAND_L) > 0)
                .@PW=.@PW/2;
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            sleep2(10);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            sleep2(10);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            break;
        case TMW2_BEARSTRIKE:
            // 60x5 = 300
            .@PW=55+(5*@skillLv);
            // Using a shield, so power is halved
            if (getequipid(EQI_HAND_L) > 0)
                .@PW=.@PW/2;
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            sleep2(10);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            sleep2(10);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            sleep2(10);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            sleep2(10);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            break;
        case TMW2_ALLINONE:
            // 45x8 = 360
            .@PW=40+(5*@skillLv);
            // Using a shield, so power is halved
            if (getequipid(EQI_HAND_L) > 0)
                .@PW=.@PW/2;
            //harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Neutral);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Fire);
            sleep2(10);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Water);
            sleep2(10);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Earth);
            sleep2(10);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Wind);
            sleep2(10);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Holy);
            sleep2(10);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Shadow);
            sleep2(10);
            harm(@skillTarget, AdjustAttackpower(.@PW), HARM_PHYS, Ele_Ghost);
            sleep2(10);
            // The main elemental-less blast hits all in same square,
            // and also hits behind (and on your square)
            rectharm(@skillTarget, 0, 1, AdjustAttackpower(.@PW/2), HARM_PHYS, Ele_Neutral);
            break;

        ////////////////////////////////
        // CLASS_OTHER
        case TMW2_PARUM:
            SK_parum();
            break;
        case TMW2_DEMURE:
            SK_Demure();
            break;
        case TMW2_DRAGOKIN:
            SK_Dragokin();
            break;
        // Summons which never fail
        case TMW2_ZARKOR:
            alignment_cansummon();
            SummonMagic(@skillId, CaveMaggot, 2, @skillLv);
            GetManaExp(@skillId, 1);
            break;
        // Summons which may fail
        case TMW2_KALWULF:
            SK_summon(Wolvern, 4, any(3,4));
            break;
        case TMW2_KALBOO:
            SK_summon(Mouboo, 4, any(2,3));
            break;
        case TMW2_KALSPIKE:
            SK_summon(PoisonSpikyMushroom, 4, any(2,3));
            break;
        case TMW2_CUTEHEART:
            SK_summon(Fluffy, 4, any(2,3));
            break;
        // Slightly more complex summons
        case TMW2_LIMERIZER:
            SK_summon(any(GreenSlime,AzulSlime,RedSlime,AngryYellowSlime), 2, any(3,4));
            break;
        case TMW2_FAIRYKINGDOM:
            SK_summon(any(FireFairy, EarthFairy, WaterFairy, WindFairy, PoisonFairy), 4, any(3,4));
            break;
        case TMW2_FAIRYEMPIRE:
            SK_summon(any(VanityPixie, HolyPixie, ShadowPixie, NulityPixie), 5, any(4,5));
            break;
        // More complex summons
        case TMW2_KALMURK:
            .@mobId=Maggot;
            if (abizit() > 4 &&
                GHMEMO[GHQ_GetQuestIDByMonsterID(Maggot)] >= 10000 &&
                MAGIC_LVL >= 3)
            {
                .@mobId=any(Maggot, Maggot, Maggot, Maggot, GiantMaggot);
            }
            SK_summon(.@mobId, (.@mobId == Maggot ? 2 : 4), any(1,2));
            break;
        case TMW2_HALHISS:
            .@mobId=Snake;
            if (abizit() > 3 &&
                GHMEMO[GHQ_GetQuestIDByMonsterID(MountainSnake)] >= 10000 &&
                rand2(1,3) == 2)
            {
                .@mobId=MountainSnake;
            }
            SK_summon(.@mobId, 4, any(3,4));
            break;
        case TMW2_FROZENHEART:
            .@mobId=Moggun;
            if (rand2(6,12) < (abizit()*2)+1)
            {
                .@mobId=Yeti;
            }
            SK_summon(.@mobId, 4, any(3,4));
            break;
        case TMW2_STONEHEART:
            .@mobId=Terranite;
            if (rand2(9,12) < (abizit()*2)+1 &&
                BaseLevel > 80)
            {
                .@mobId=TerraniteProtector;
            }
            SK_summon(.@mobId, 4, any(4,5));
            break;
        case TMW2_DUCKY:
            .@mobId=Duck;
            .@q=getq(LilitQuest_PiratesOfSARAH);
            if (!alignment_cansummon())
                break;
            if (abizit() > 4 &&
                .@q > 2 &&
                MAGIC_LVL >= 3)
            {
                // GHQ Complete: 33% chances
                // Otherwise: 8% chances
                if (GHMEMO[GHQ_GetQuestIDByMonsterID(Duck)] >= 10000)
                    .@mobId=any(Duck, Duck, EliteDuck);
                else
                    .@mobId=any(Duck, Duck, Duck, Duck,
                                Duck, Duck, Duck, Duck,
                                Duck, Duck, Duck, EliteDuck);
            }
            SummonMagic(@skillId, .@mobId, 2);
            GetManaExp(@skillId, 1);
            break;

        // Special exception
        case TMW2_TRANSMIGRATION:
            doevent("sk#mkpot::OnCall");
            break;

        // Experience only
        case KN_AUTOCOUNTER:
        case SN_SHARPSHOOTING:
        case HW_MAGICPOWER:
        case SM_PROVOKE:
        case SN_WINDWALK:
        case SO_FIREWALK:
        case TF_BACKSLIDING:
        case MG_FIREWALL:
        case ALL_FULL_THROTTLE:
        case GC_DARKILLUSION:
        case NV_TRICKDEAD:
            GetManaExp(@skillId, rand2(1,3));
            break;
    }

    // Debug
    if ($@GM_OVERRIDE)
        debugmes "Cast skill %d on level %d - Target %d",
                  @skillId, @skillLv, @skillTarget;

    // Cleanup (double-safe)
    @skillTarget = 0;
    return;

}




// When you kill a player, some special care is needed
// Only a few maps will give you experience for PK: Tulimshar's Guards Arena,
// Frostia Imperial PVP Arena, Call Of Dusty, Arena Quirino Voraz.
// HUB_PvP ( ) - killedrid must be set
function	script	HUB_PvP	{
    // Update global PK count
    $PLAYERS_KILLED+=1;

    // Prepare local variables
    .@atk=get_BR(getcharid(3));
    .@def=get_BR(killedrid);
    .@honor=calc_HR(getcharid(3), killedrid);
    .@bxp=max(readparam(BaseLevel, killedrid), .@def);
    .@jxp=readparam(JobLevel, killedrid);
    .@m$=getmap();
    .@gm=getgroupid(killedrid);

    // This is an official PVP Map
    if (ispvpmap(.@m$)) {
        // Honorable Death
        if (.@honor >= 0) {
            HONOR+=.@honor;
        } else {
            // Dishonorable... But... Legit?
            if (is_bandit(killedrid) || getmap() == "001-8")
                .@honor=1;
            HONOR+=.@honor; // It's negative.
        }

        // PvP, and a GM was slain
        if (.@gm >= 80) {
            rentitem MurdererCrown, (86400*7); // 1 week
            kamibroadcast(strcharinfo(0)+" killed Game Master \""+strcharinfo(0, "", killedrid)+"\", and now may wear a "+getitemlink(MurdererCrown)+" for a week.");
        }

    // It was a duel!
    } else {
        // Honorable Duel: HONOR +30%
        if (.@honor > 0)
            HONOR+=max(1, .@honor*3/10);
        else if (.@honor < 0)
            HONOR+=1;
        // ^ Dishonorable duel, but was a duel!
    }

    // Report about honor
    dispbottom l("%d vs %d: Honor (%d)", .@atk, .@def, .@honor);

    // TODO: Start using readparam2() to read if the opponent was worthy
    // That is, read total attack, defense, HP, evasion and hit chance
    // And compare with your own readparam2(), then use a % and a table
    // based on your (assassin's) level.
    if (compare(.@m$, "001-8")) {
        // Quirino Voraz PVP Arena
        // You get 5 times killed player level, and 1 time job level
        getexp .@bxp*5, .@jxp;
    } else if (compare(.@m$, "ARENA") || compare(.@m$, "003-13")) {
        // Tulimshar Duel Arena
        // You get 3 times killed player level, and 2 times job level
        getexp .@bxp*3, .@jxp*2;
    } else if (compare(.@m$, "001-10")) {
        // Call Of Dusty
        // You get 3 times killed player level, and 3 times job level
        getexp .@bxp*3, .@jxp*3;
    } else if (compare(.@m$, "001-10-1")) {
        // Call Of Dusty Boss Room
        // You _may_ get a Bottled Dusty at random, but dead player status affect
        if (.@def > .@atk/10) {
            if (rand2(0,250) < readparam2(bLuk)+readparam2(bLuk, killedrid))
                getitem BottledDust, any(1,1,2);
        }
    } else {
        // Anywhere else
        // You get 0.5 times killed player level, and 0 times job level
        getexp (.@bxp/2), 0;
    }
    return;
}



// HUB_PCBonus ()
function	script	HUB_PCBonus	{
    /* Rebirth Traits */
    if (PCBONUS & PCB_ATKBONUS) {
        bonus bAtk, 25;
    }
    if (PCBONUS & PCB_MATKBONUS) {
        bonus bMatk, 25;
    }
    if (PCBONUS & PCB_DEFBONUS) {
        bonus bDef, 20;
    }
    if (PCBONUS & PCB_MDEFBONUS) {
        bonus bMdef, 20;
    }
    if (PCBONUS & PCB_EVDBONUS) {
        bonus bFlee, 20;
    }
    if (PCBONUS & PCB_HITBONUS) {
        bonus bHit, 25;
    }
    if (PCBONUS & PCB_CRITBONUS) {
        bonus bCritical, 5;
    }
    if (PCBONUS & PCB_DOUBLEATK) {
        bonus bDoubleAddRate, 5;
    }
    if (PCBONUS & PCB_ALLSTATS) {
        bonus bAllStats, 1;
    }
    if (PCBONUS & PCB_HPBONUS) {
        bonus bMaxHP, 500;
    }
    if (PCBONUS & PCB_MPBONUS) {
        bonus bMaxSP, 200;
    }
    if (PCBONUS & PCB_ASPDBONUS) {
        bonus bAspd, 10;
    }
    if (PCBONUS & PCB_WSPDBONUS) {
        bonus bSpeedAddRate, 5;
    }
    if (PCBONUS & PCB_WEIGHTBONUS) {
        bonus bAddMaxWeight, 1000;
    }
    if (PCBONUS & PCB_EXPBONUS) {
        bonus2 bExpAddRace, RC_All, 10;
    }
    if (PCBONUS & PCB_NOKNOCKBACK) {
        bonus bNoKnockback, 1;
    }
    if (PCBONUS & PCB_SPLASHMASTER) {
        bonus bSplashRange, 1;
    }
    if (PCBONUS & PCB_RANGEMASTER) {
        bonus bAtkRange, 1;
    }
    if (Class != Savior && !(PCBONUS & PCB_LEGENDARY)) {
        bonus2 bCriticalAddRace, RC_Legendary, -25;
        bonus2 bSPDrainValueRace, RC_Legendary, -5;
        bonus2 bAddRace, RC_Legendary, -40;
        bonus2 bMagicAddRace, RC_Legendary, -20;
    }
    if (PCBONUS & PCB_LEGENDARY) {
        bonus bDefRatioAtkRace, RC_Legendary;
    }
    /* Passive Skills */
    bonus2 bSubRace, RC_Legendary, getskilllv(AL_DP)-10;
    return;
}