summaryrefslogblamecommitdiff
path: root/npc/functions/weather.txt
blob: 497d0ab6a63ffe2c8a7a48ac13bd41a2c6fe6053 (plain) (tree)
1
2
3
4
5
6
7
8
9





                                                                 
                      
                                         
                                                              




                                    
      




                                    

                                                             
                         
                       


                                                       



                                                                      

 


                                                    








                                            
  
 
       
                              
                
                                   
                                                   

           






                                                           
                                                           
                                                            












                                                                          
                                     

                
                                       
                                        
                                        




                                       
                                       
                                       



                                       
                                       
                                       


                                      
                                      
                                      
                                      
                                      

                                      
                                      
                                      
                                      
                                      
 

                                      
                                      

 
                                                               




                                                   


                                                                         



                                          
                                                 

                      
 

                                                                                  


                                             









                                     

                                 


                                       
                                                                               



                                                   



                                                           
                                    
                               
                                         

                                           
                          
                                    



                                                       
                                    

                                          
                         
                                    
                               
                                    
 












                                                                   
                
                                                                                           
                                                                             

         



                                

                                
                            
                         
                                                
                                          

                                                     
                                             
         

                     
                                           
 
                                      
                                     



                                       
                                                                                     
      



                                                                      
                             
                                              
                   
                                  











                                                                              
                                 
                                                       
                                         
                                      
                                                             
                                 

                                                                             
                                                        
                        
         
                                                                
                                                        
                                                       

                                                  
                                         
                                                       
                                         
                                      
                                                             
                                 

                                                                                  
                                                      
                        
         
                                                                
                                                        
                                                       

                                                  
     
 
                             

                                                  

        
                              
                                  










                                                                                                
                                          


               

                                                   
                             


        
                                  


        
                             


        
                              


        
                                    

        



















                                                                                                 
                         

                               














                                                                 
                                  


        
// TMW2 scripts.
// Authors:
//    Jesusalva
// Description:
//    Controls world seasons. RESPECT MASK_* VARS ON CONSTANTS DB

// is_night(set=False)
function	script	is_night	{
    // If we're not configuring, retrieve the variable (cache)
    // It is more efficient this way
    .@set=getarg(0, false);
    if (!.@set)
        return $@WEATHER_NIGHT;

    /*
    // Night time depends on season.
    // Summer: Day > Night
    // Winter: Night > Day
    // Autumn/Spring: Day = Night
    //
    // But we have TWO SUNS, meaning night is always smaller.
    //
    // 2 = GETTIME_MINUTE
    // 3 = GETTIME_HOUR
    // Summer: 5h day. 1h night. (4 cycles, 8 updates)
    // Others: 3h day. 1h night. (6 cycles, 12 updates)
    // Winter: 2h day. 1h night. (8 cycles, 16 updates)
    */
    // NEW Unified Rule: Day last 3 hours. Night lasts 1 hour. Always.
    .@t=(season() == SUMMER ? 6 : (season() == WINTER ? 3 : 4));
    return (gettime(3) % .@t == 1);
}

000-0,0,0,0	script	#WeatherCore	NPC_HIDDEN,{
    end;

/*
 * removemapflag("<map name>", <flag>)
 * setmapflag("<map name>", <flag>{, <val>})
 * getmapflag("<map name>", <flag>)

	mf_snow:               16

	mf_jexp:               39
	mf_bexp:               40
*/

OnInit:
    // This is weather startup
    .@init=true;
    $@WEATHER_NIGHT=is_night(true);
    array_pad($@PLAYER_ACTIVITY, 96, $HIST_ONLINE);
    .tpc=0;
    .tcl=0;
    // Bind commands
    bindatcmd "wsnow", "#WeatherCore::OnSnow", 80, 80, 1;
    bindatcmd "wrain", "#WeatherCore::OnRain", 80, 80, 1;
    bindatcmd "wsand", "#WeatherCore::OnSand", 80, 80, 1;
    bindatcmd "wevil", "#WeatherCore::OnEvil", 80, 80, 1;
    bindatcmd "wnight", "#WeatherCore::OnNight", 80, 80, 1;
    bindatcmd "wclear", "#WeatherCore::OnClear", 80, 80, 1;
    bindatcmd "wreset", "#WeatherCore::OnReset", 99, 99, 1;
    bindatcmd "wset",   "#WeatherCore::OnManual", 99, 99, 1;


    // Determine which maps are subject to weather, and how weather works:
    // eg. it will never snow on a desert, or a sandstorm on icelands.
    .wcore = htnew;

    // Deserts
    htput(.wcore, "003-1", "desert");
    htput(.wcore, "004-1", "desert");
    htput(.wcore, "004-2", "desert");
    htput(.wcore, "009-1", "desert");
    htput(.wcore, "010-1", "desert");
    htput(.wcore, "010-2", "desert");
    htput(.wcore, "032-1", "desert");

    // Woodlands
    htput(.wcore, "001-4", "woodland");
    htput(.wcore, "001-11", "woodland");
    htput(.wcore, "001-12", "woodland");
    htput(.wcore, "005-1", "woodland");
    htput(.wcore, "012-1", "woodland");
    htput(.wcore, "014-1", "woodland");
    htput(.wcore, "014-2", "woodland");
    htput(.wcore, "014-3", "woodland");
    htput(.wcore, "014-4", "woodland");
    htput(.wcore, "014-5", "woodland");
    htput(.wcore, "017-1", "woodland");
    htput(.wcore, "018-1", "woodland");
    htput(.wcore, "018-2", "woodland");
    htput(.wcore, "018-4", "woodland");
    htput(.wcore, "018-5", "woodland");
    htput(.wcore, "027-1", "woodland");

    // Icelands
    htput(.wcore, "001-7", "iceland");
    htput(.wcore, "019-1", "iceland");
    htput(.wcore, "019-2", "iceland");
    htput(.wcore, "019-3", "iceland");
    htput(.wcore, "019-4", "iceland");
    htput(.wcore, "019-5", "iceland");
    htput(.wcore, "019-6", "iceland");
    htput(.wcore, "020-1", "iceland");
    htput(.wcore, "022-1", "iceland");
    htput(.wcore, "024-1", "iceland");
    htput(.wcore, "031-1", "iceland");

    // Special
    htput(.wcore, "011-3", "special");
    htput(.wcore, "011-4", "special");


    consoleinfo "[Weather.sys] Total Maps = " + htsize(.wcore);
    // No "end" here, so server starts with weather
OnMinute00:
OnMinute15:
OnMinute30:
OnMinute45:
    // Update the online average activity
    .@idx = (gettime(GETTIME_HOUR) * 4) + (gettime(GETTIME_MINUTE) / 15);
    $@PLAYER_ACTIVITY[.@idx] = getusers(1);
    // There is no weather in test servers
    if (debug && !$@GM_OVERRIDE)
        end;

    //debugmes "[Weather.sys] Starting to regen";
    .tpc+=getusers(1);
    .tcl+=1;

    .@hti = htiterator(.wcore);
    for(.@key$ = htinextkey(.@hti); hticheck(.@hti); .@key$ = htinextkey(.@hti)) {
        // Local variables: .@key$ .@type .@r
        .@type$=htget(.wcore, .@key$);
        .@r=rand(0,10000);

        // Clear weather map masks
        .@mk=getmapmask(.@key$);

        if (.@mk & MASK_RAIN)
            .@mk=.@mk^MASK_RAIN;
        if (.@mk & MASK_SANDSTORM)
            .@mk=.@mk^MASK_SANDSTORM;
        if (.@mk & MASK_SNOW)
            .@mk=.@mk^MASK_SNOW;
        if (.@mk & MASK_NIGHT)
            .@mk=.@mk^MASK_NIGHT;
        if (.@mk & MASK_EVILSANCTUM)
            .@mk=.@mk^MASK_EVILSANCTUM;

        // Monster King Sieges (can be weird, siege last 10mn and mask last 15)
        if ($@MK_SCENE)
            .@mk=.@mk|MASK_EVILSANCTUM;
        if (.@mk & (MASK_MATTACK|MASK_EVILSANCTUM))
            .@mk=.@mk^MASK_EVILSANCTUM;

        // Remove all current masks, and add rain/snow/sand
        if (.@type$ == "desert") {
            if (.@r < 10)
                .@mk=.@mk|MASK_RAIN;
            else if (.@r < 300)
                .@mk=.@mk|MASK_SANDSTORM;

        } else if (.@type$ == "woodland") {
            if (.@r < 300)
                .@mk=.@mk|MASK_RAIN;

            if ($EVENT$ == "Christmas")
                .@mk=.@mk|MASK_SNOW;
            else if (season() == WINTER && .@r >= 9250)
                .@mk=.@mk|MASK_SNOW;

        } else if (.@type$ == "iceland") {
            if (.@r < 30)
                .@mk=.@mk|MASK_RAIN;
            else if (.@r < 300)
                .@mk=.@mk|MASK_SNOW;

        } else if (.@type$ == "special") {
            // This biom is too hot for snow. But it may rain.
            if (.@r < 300)
                .@mk=.@mk|MASK_RAIN;

            // Fog? (Evil Sanctum and Monster Attack) Or Sandstorm?
            if (.@r % 4 == 2)
                .@mk=.@mk|MASK_EVILSANCTUM;
            else if (.@r % 4 == 1)
                .@mk=.@mk|MASK_SANDSTORM;
            else if (.@r % 4 == 3)
                .@mk=.@mk|MASK_MATTACK;

        } else {
            consolebug "Warning warning, blame Saulc! Weather system error on map "+.@key$;
            announce("ERROR BLAME SAULC! WEATHER SYSTEM CORRUPTED.", bc_all);
        }

        // Bugfix
        if (!(.@mk & MASK_NONE))
            .@mk=.@mk|MASK_NONE;

        setmapmask .@key$, .@mk;

        // Is it night time?
        if (is_night()) {
            setmapflag(.@key$, mf_nightenabled);
            addmapmask .@key$, MASK_NIGHT;
        } else if (getmapmask(.@key$) & MASK_NIGHT) {
            removemapflag(.@key$, mf_nightenabled);
            removemapmask .@key$, MASK_NIGHT;
        }
    }
    htidelete(.@hti);
    //debugmes "[Weather.sys] Regenerated";

    // Hardcore: Skip day/night cycles
    if ($HARDCORE || $@GM_OVERRIDE) {
        $@WEATHER_NIGHT=is_night(true);
        end;
    }

    // During night, normal monsters respawn 30% faster. (Bifs and Bosses are immune)
    //
    // Also, announce to players about day/night cycle changes
    // The fastest you'll get is 30 minutes for night cycle.
    // It's 2 messages every 3 hours. (r7.5)
    // Player might be on cave, and this will help them tracking time.
    .@current=is_night(true);
    .@update = (.@current != $@WEATHER_NIGHT);
    if (.@update) {
        $@WEATHER_NIGHT=.@current;
        if (.tcl > 0) {
            .tpc = .tpc / .tcl;
            // Monsters spawn faster based on average player count of previous
            // cycle, 2% faster per player, capped at 2/3 of the lowest rate
            // Default lowest is 70%, so it can go down up to 45% reduction
            // For a total of (70-45 = 25%) or monsters spawning 4× faster
            // when server is at "full" load (22 players or so)
            .@bon = min(.tpc * 2, min($BCONFN_SPAWN, $BCONFD_SPAWN) * 2 / 3);
        }
        .tpc=0;
        .tcl=0;
    }
    if (is_night() && .@update) {
        .@c = getunits(BL_PC, .@players, MAX_CYCLE_PC);
        for (.@i = 0; .@i < .@c; .@i++) {
            attachrid(.@players[.@i]);
            callfunc("SC_Bonus", 180, SC_INCMHPRATE, 10, 10);
            percentheal 100, 100;
            callfunc("SC_Bonus", 60, SC_INCFLEERATE, 40, 40); // Night Wishes
            message(.@players[.@i], "Night wishes: Evasion up!");
            message(.@players[.@i], "The night falls.");
            detachrid();
        }
        setbattleflag("mob_spawn_delay", $BCONFN_SPAWN - .@bon);
        setbattleflag("monster_hp_rate", $BCONFN_MOBHP);
        //charcommand("@reloadbattleconf"); // Careful!
        donpcevent("@exprate::OnInheirtedReload");
        //donpcevent("@droprate::OnReload");
    } else if (!is_night() && .@update) {
        .@c = getunits(BL_PC, .@players, MAX_CYCLE_PC);
        for (.@i = 0; .@i < .@c; .@i++) {
            attachrid(.@players[.@i]);
            callfunc("SC_Bonus", 180, SC_INCMHPRATE, 10, 10);
            percentheal 100, 100;
            callfunc("SC_Bonus", 60, SC_ATTHASTE_POTION3, 15, 15); // Morning Rush
            message(.@players[.@i], "Morning rush: Attack speed up!");
            message(.@players[.@i], "The day rises.");
            detachrid();
        }
        setbattleflag("mob_spawn_delay", $BCONFD_SPAWN - .@bon);
        setbattleflag("monster_hp_rate", $BCONFD_MOBHP);
        //charcommand("@reloadbattleconf"); // Careful!
        donpcevent("@exprate::OnInheirtedReload");
        //donpcevent("@droprate::OnReload");
    }

    callfunc "FYE_Normalize";
    if (debug || $@GM_OVERRIDE)
        debugmes "[Weather.sys] Weather reloaded";
    end;

    // Function to check stuff
    // WeatherSwitch ( MASK, MAP )
    function WeatherSwitch {
        // Get map
        getmapxy(.@key$,.@a,.@b,0);

        // Sanitize
        .@m$ = htget(.wcore, .@key$, "Not found");

        // Change Weather or abort
        if (.@m$ == "Not found")
            dispbottom l("Command not permitted on this map! Check npc/functions/weather.conf");
        else
            addmapmask(.@key$, getarg(0));
        return;
    }

// Some commands, for GMs manually override weather
OnRain:
    WeatherSwitch(MASK_RAIN);
    end;

OnSand:
    WeatherSwitch(MASK_SANDSTORM);
    end;

OnSnow:
    WeatherSwitch(MASK_SNOW);
    end;

OnNight:
    WeatherSwitch(MASK_NIGHT);
    end;

OnEvil:
    WeatherSwitch(MASK_EVILSANCTUM);
    end;

OnManual:
    if (!.@atcmd_numparameters) {
        dispbottom l("Syntax: @wset <map_mask>");
        end;
    }

    // Never allow negative numbers, or to disable map mask 1 (never, EVER, do such insane thing)
	.@rq = atoi(.@atcmd_parameters$[0]);
    if (.@rq <= 1 || .@rq % 2 == 1) {
        dispbottom l("Invalid map mask");
        end;
    }

    // <Insert a helpful comment here>
    getmapxy(.@key$,.@a,.@b,0);
    .@mk=getmapmask(.@key$);
    .@mk=.@mk^.@rq;
    setmapmask(.@key$, .@mk);
    end;

// Clear works on any map
OnClear:
    getmapxy(.@key$,.@a,.@b,0);
    .@mk=getmapmask(.@key$);
    if (.@mk & MASK_RAIN)
        .@mk=.@mk^MASK_RAIN;
    if (.@mk & MASK_SANDSTORM)
        .@mk=.@mk^MASK_SANDSTORM;
    if (.@mk & MASK_SNOW)
        .@mk=.@mk^MASK_SNOW;
    if (.@mk & MASK_NIGHT)
        .@mk=.@mk^MASK_NIGHT;
    setmapmask(.@key$, .@mk);
    end;

// Reset the whole map, including season, event and weather masks
OnReset:
    getmapxy(.@key$,.@a,.@b,0);
    setmapmask(.@key$, MASK_NONE);
    end;

}