HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Random weather script

09-12-2008, 02:12 AM#1
moyack
Random weather script
By moyack. 2008.

I did this as a request: a code that changes randomly the weather from normal to a rainy day. Due to its configurability and easy to use (just copy it to your map and it will work) I'll post it to the public. Now the current version allows multiple types of weathers and with a few functions you can achieve very nice weather effect transitions.


How the script works?

The script initializes a timer with a random duration (configurable via globals), and it will change from no weather to a weather environment. if you use the minimalistic version, it will turn on and off in a random way the specified weather. If you use the Standard version, it will do the same but with a set of weathers configured previously. this preconfiguration can be done at map init or at game time... there's no limitation.


Credits and Acknowledgments

Greetings to Syntic_Arrow for doing the request.
Credits to Ammorth for the suggestion of weights to implement randomness
Gives credits when you use it...


How to install:
  1. Create a new trigger
  2. Call it whatever you want
  3. Convert it to custom text
  4. Delete all the content of that trigger
  5. Paste this trigger code and voila!!!

Standard version:
The standard version offers the possibility to setup the kind of weathers you want to see in your map and their chances to appear. To start a set of weathers, you just have to add a code like this:

Collapse Sample code:
function StartWeather takes nothing returns nothing // This function can run at map init...
    call CleanWeatherWeights() // Prepares and clean the Weather script...
    call SetWeatherWeight(Northrend_Blizzard, 3.) // adds a weather type and its weight.
    call SetWeatherWeight(Rays_Of_Light, 5.)
    call SetWeatherWeight(Wind_Heavy, 8.)
    // if a weather has a higher weight, it will have more chances to happen than others.
    // this value is arbitrary...
endfunction

If you need to change the weather weights, or types, you must clean them with CleanWeatherWeights() and then reset the values with SetWeatherWeight(...) command.

Collapse Random Weather Script - Standard version:
// Random weather changer, by moyack. 2008.
library RandomWeather initializer init
// Configuration section
globals
    private constant real    MinDur = 5. // minimum time that we have to wait between weathers
    private constant real    MaxDur = 15. // maximum time that we have to wait between weathers
endglobals
// End configuration section
globals
    // Weather Type Constants
    constant integer Ashenvale_Rain_Heavy    = 'RAhr'
    constant integer Ashenvale_Rain_Light    = 'RAlr'
    constant integer Dalaran_Shield          = 'MEds'
    constant integer Dungeon_Blue_Fog_Heavy  = 'FDbh'
    constant integer Dungeon_Blue_Fog_Light  = 'FDbl'
    constant integer Dungeon_Green_Fog_Heavy = 'FDgh'
    constant integer Dungeon_Green_Fog_Light = 'FDgl'
    constant integer Dungeon_Red_Fog_Heavy   = 'FDrh'
    constant integer Dungeon_Red_Fog_Light   = 'FDrl'
    constant integer Dungeon_White_Fog_Heavy = 'FDwh'
    constant integer Dungeon_White_Fog_Light = 'FDwl'
    constant integer Lordaeron_Rain_Heavy    = 'RLhr'
    constant integer Lordaeron_Rain_Light    = 'RLlr'
    constant integer Northrend_Blizzard      = 'SNbs'
    constant integer Northrend_Snow_Heavy    = 'SNhs'
    constant integer Northrend_Snow_Light    = 'SNls'
    constant integer Outland_Wind_Heavy      = 'WOcw'
    constant integer Outland_Wind_Light      = 'WOlw'
    constant integer Rays_Of_Light           = 'LRaa'
    constant integer Rays_Of_Moonlight       = 'LRma'
    constant integer Wind_Heavy              = 'WNcw'
    // End Weather type Constants...
    private boolean IsWeather = false
endglobals

private struct Weather // this is the struct that manages all the weather behavior
    private static rect R
    private static real total = 0.
    private static integer index = 0
    weathereffect w
    integer id
    real weight
    real chance
    
    private method onDestroy takes nothing returns nothing
        call RemoveWeatherEffect(.w)
    endmethod
    
    static method Clean takes nothing returns nothing
        local integer i = 1
        local Weather W
        loop
            exitwhen i > Weather.index
            set W = Weather(i)
            call W.destroy()
            set i = i+1
        endloop
        set Weather.index = 0
    endmethod
    
    static method Add takes integer id, real w returns nothing
        local integer i = 1
        local Weather W = Weather.allocate()
        set W.id = id
        set W.weight = w
        set W.w = AddWeatherEffect(Weather.R, id)
        call EnableWeatherEffect(W.w, false)
        set Weather.total = Weather.total + w
        set Weather.index = integer(W)
        loop
            exitwhen i > Weather.index
            set W = Weather(i)
            set W.chance = W.weight / Weather.total
            set i = i+1
        endloop
    endmethod
    
    static method Start takes nothing returns nothing
        local integer i = 1
        local real r = GetRandomReal(0,1)
        local real s = 0.
        local Weather W
        loop
            exitwhen i > Weather.index
            set W = Weather(i)
            exitwhen s <= r and r < s+W.chance
            set s = s+W.chance
            set i = i+1
        endloop
        call EnableWeatherEffect(W.w, true)
    endmethod
    
    static method Stop takes nothing returns nothing
        local integer i = 1
        local Weather W
        loop
            exitwhen i > Weather.index
            set W = Weather(i)
            call EnableWeatherEffect(W.w, false)
            set i = i+1
        endloop
    endmethod
    
    private static method onInit takes nothing returns nothing
        set Weather.R = GetWorldBounds()
    endmethod
endstruct

private function Loop takes nothing returns nothing
    local timer t = GetExpiredTimer()
    set IsWeather = not IsWeather
    if IsWeather then
        call Weather.Start()
    else
        call Weather.Stop()
    endif
    call PauseTimer(t)
    call TimerStart(t, GetRandomReal(MinDur, MaxDur), false, function Loop)
    set t = null
endfunction

private function init takes nothing returns nothing
    call TimerStart(CreateTimer(), GetRandomReal(MinDur, MaxDur), false, function Loop)
endfunction
// ==============
// user functions
// ==============
function SetWeatherWeight takes integer wid, real w returns nothing
    call Weather.Add(wid, w)
endfunction

function CleanWeatherWeights takes nothing returns nothing
    call Weather.Clean()
endfunction

endlibrary

Expand Minimalistic version. Only manages one type of weather:

Expand Weather RawCodes:
Attached Images
File type: gifweather.gif (22.8 KB)
09-12-2008, 04:29 AM#2
burningice95
Seems a little simple.....
09-12-2008, 04:30 AM#3
darkwulfv
One thing: I would put where you can find the rawcode of weather (because I sure don't know).

EDIT: That's why this is a script, not a system.
09-13-2008, 01:18 AM#4
Anopob
What darkwulfv said, as adjusting this to snow or fog or whatever (or multiple weathers at random times if so) would be great.
09-13-2008, 05:51 AM#5
grim001
"Random Rain" is a bit misleading since it could work for any kind of weather.

I say add support for all types of weather, enabling/disabling specific weather types, and setting the relative frequency of each.
09-14-2008, 02:47 PM#6
moyack
Ok, I'll add a function which will set the chances that a weather could happen.

call SetWeatherChance('RAhr', 0.15) // it will have a 15% chance that a rain happens...
09-14-2008, 07:08 PM#7
Ammorth
I would instead use a weight, as calling:

Collapse JASS:
call SetWeatherChance('RAIN', 1.00)
call SetWeatherChance('SNOW', 1.00)

wouldn't work out very well.

Collapse JASS:
call SetWeatherChance('RAIN', 8)
call SetWeatherChance('SNOW', 3)

rain = 8/(8+3) = 72.7%
snow = 3/(8+3) = 27.3%
09-15-2008, 12:00 AM#8
moyack
Quote:
Originally Posted by Ammorth
I would instead use a weight, as calling:

Collapse JASS:
call SetWeatherChance('RAIN', 1.00)
call SetWeatherChance('SNOW', 1.00)

wouldn't work out very well.

Collapse JASS:
call SetWeatherChance('RAIN', 8)
call SetWeatherChance('SNOW', 3)

rain = 8/(8+3) = 72.7%
snow = 3/(8+3) = 27.3%
I was thinking to make a code that behaves similar to... the system that the AI editor has to select the hero's chances of being trained. If you set one value, the other values get adjusted, so in the first scenario you proposed, simply the system will impose the snow and will set 0% chances to the other weathers.

I've added the weathers (20 in total) and I'm coding the calculation part. As soon as I have them ready, I'll post the updated version.
09-16-2008, 07:05 AM#9
ADOLF
change of weather with all map (if it big) can cause a lag, i shared a map on regions and create weathereffect timed in each region
09-18-2008, 01:42 AM#10
moyack
Code updated. Comments are appreciated.
09-18-2008, 01:54 AM#11
Ammorth
There is one issue with this script which is not adressed in the setup. The issue is not with the script itself but with the game engine.

Read the bottem of this post for the info: http://www.wc3campaigns.net/showthread.php?t=91176

Quote:
Originally Posted by Ammorth
The one effect rule
There are different types of weather effects: Rain, Shield, Dungeon Fog, Snow, Rays and Wind. Each type of effect can only have one instance of itself per 512 square. This includes disabled weather effects. This means you cannot create Lordaeron Rain and Ashenvale Rain on the same square. The first one created will be viewable, while the other will be non-existent.
09-18-2008, 02:44 AM#12
moyack
Quote:
Originally Posted by Ammorth
There is one issue with this script which is not adressed in the setup. The issue is not with the script itself but with the game engine.

Read the bottem of this post for the info: http://www.wc3campaigns.net/showthread.php?t=91176
Actually (and without noticing) the script takes this situation into account :P, because it lets one period with any of the effects and other period will all the effects off. There's no chance that 2 or more effects gets turned on at the same time (at least with my test).
09-18-2008, 03:44 AM#13
Ammorth
Its not an issue with effects being displayed, it that you can't create 2 effects of the same "style" on the same grid piece. The only way around this is to remove and then create the new style. The problem with this is that it re-introduces lag caused by weather creation.
09-18-2008, 07:36 AM#14
DioD
Link some game affect to weather type (i prefer linked list of linked struct, soo you will able to set more then one effect per weather).

Add preload functions, weather lag a lot on first call.

Also add some way to call weather locally (turn on\off for single player).
09-18-2008, 08:56 PM#15
Vexorian
Yes, turn the thing into a non-minimalist monster.

I think linking to effect is interesting but it raises the scope of the initial idea too much, perhaps for a new system, I actually made that one day for TTOR and reused it in my arena, so I might end up releasing a weather system one day.

Either way, I don't like this idea too much, but as an utility for those guys that want to have random weather in their map, I guess it is fine, approved.