summaryrefslogblamecommitdiff
path: root/npc/functions/hub.txt
blob: 8b2241148616b131becf20f9bc867bf6f5a44850 (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_ATTACK|PCBLOCK_SKILL|PCBLOCK_USEITEM|PCBLOCK_MOVE, 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);
    }
    // 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_ATTACK|PCBLOCK_SKILL|PCBLOCK_USEITEM|PCBLOCK_COMMANDS, 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);
    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 "Caster: %s", strcharinfo(0);
        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)
        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_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_BURNING, 2500, 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_BURNING, 2500, 1, 2200, 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, 3000, SC_BURNING, BL_MOB|BL_PC|BL_HOM|BL_MER, "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, "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, "filter_hostile");
            // Maybe filter_notme() would work better, indeed
            GetManaExp(TMW2_NILFHEIM, 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

        // FIXME: Windwalker (1MSP?), Last Standing Man (2 MSP?)

        // 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;




        // XXX: Earth Class (DEF effects)
        case TMW2_METEORSTRIKE:
            .@dmg=AdjustSpellpower(150);
            harm(@skillTarget, .@dmg, HARM_MAGI, Ele_Earth);
            break;
        case TMW2_METEORSHOWER:
            .@dmg=AdjustSpellpower(150);
            .@RG=3+(@skillLv/5);
            areaharm(@skillTarget, .@RG, .@dmg, HARM_MAGI, Ele_Earth);
            break;
        case TMW2_GAIABREAK:
            // TODO: DEF UP+
            .@dmg=AdjustSpellpower(200);
            .@dsub=AdjustSpellpower(120);
            harm(@skillTarget, .@dmg, HARM_MAGI, Ele_Earth);
            rectharm(@skillTarget, 2, 5, .@dsub, HARM_MAGI, Ele_Earth);
            break;

        // TODO Assassin skill
        // Higher chance of success if monster HP+ATK < your own HP
        // (Maybe put level on that?) Never works on boss
        case TMW2_ASSASSINATE:
            // SC_COMA TODO
            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;

        // 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: 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 SM_BASH:
        case MC_MAMMONITE:
        case AC_SHOWER:
        case KN_AUTOCOUNTER:
        case ASC_METEORASSAULT:
        case SN_SHARPSHOOTING:
        case AL_HEAL:
        case HW_MAGICPOWER:
        case SM_PROVOKE:
        case AB_HIGHNESSHEAL:
        case SN_WINDWALK:
        case MG_FIREBALL:
        case AL_HOLYLIGHT:
        case MG_SOULSTRIKE:
        case MG_NAPALMBEAT:
        case SO_FIREWALK:
        case WZ_FROSTNOVA:
        case MG_LIGHTNINGBOLT:
        case TF_BACKSLIDING:
        case MG_FIREWALL:
        case ALL_FULL_THROTTLE:
        case GC_DARKILLUSION:
        case NV_TRICKDEAD:
        case AC_CHARGEARROW:
            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))
                HONOR+=1;
            else
                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;
}