gref
New Member
- Reaction score
- 33
Controlled Random Weather v1.12 by gref
Description:
This will create a believable weather system in one line in your map.
Leakless: Yes.
Lagless: Yes.
Multi-Instanceable: Yes
Jass/Gui: Jass (Gui can use.)
Screenshots:
Readme
Code:
Purpose of the system:
To create a random weather system that allows developers a simple way to create and manipulate
believable and easily customized weather over multiple areas, to make maps better, and to make
mapmaking easier.
Any weather system can be created, paused or destroyed in one function call, and the system is multi-instanceable so that different weather systems can be created, manipulated and destroyed at any point.
Weather effects:
-Sandstorm
-Heavy wind
-Light wind
-Sunlight
-Moonlight
-Cloud cover
-Fog
-Light Rain
-Light Snow
-Heavy Rain
-Heavy Snow
-Storm
-Blizzard
Changelog:
v1.00
Initial release
v1.10
Remade readme.
Code slightly restructured.
Pause, Unpause, Destroy, and Create_Weather_Permanent added.
Better demonstration added.
v1.11
Realised Create_Weather_Permanent was useless. Removed it.
v1.12
Optimized IsNumberBetween
Made function names "less ugly"
Implemented struct based attachment in CreateEffect and CreateWeatherEffect
Removed GetAttachedWeatherEffect
If you find leaks, want to give me a suggestion, or comment, then feel free to pm me here, or send me an email at [email protected]
Description:
This will create a believable weather system in one line in your map.
Leakless: Yes.
Lagless: Yes.
Multi-Instanceable: Yes
Jass/Gui: Jass (Gui can use.)
Screenshots:
Sandstorm:
Storm:
Blizzard:
Moonlit:
Storm:
Blizzard:
Moonlit:
Readme
|======================================================================|
| Controlled Random Weather 1.12 by gref |
|======================================================================|
The purpose of this system is to allow developers a simple way to create and manipulate
believable and easily customized weather over multiple areas, to make maps better, and to make
mapmaking easier.
Table of Contents:
Credits
Functions
General Implementation
Weather Thresholds
How to use in GUI
Possible Uses
Notes for Customization
============================================>
Credits:
Vexorian for CSCache
xPheRe for his snippet which gave me the idea.
============================================>
Functions:
1.) weather_CreateWeather
weather_Create_Weather(rect Area, real Minimum Temperature, real Maximum Temperature, real
Minimum Pressure, real Maximum Pressure, real Time between updates,
boolean Feedback)
Returns integer Handle
This function is the standard function for creating weather. It can be called from any trigger
and gives you an integer Handle which can be used to pause, unpause and destroy the weather
created.
Argument explanation:
rect Area: The area you want the weather to appear over. For a standard world editor defined
region put gg_rct_ before the name and replace any spaces with underscores. ie.
gg_rct_Region_1
real Minimum Temperature: The absolute lowest point the temperature will reach. Temperature
and pressure have direct bearing on what weather occurs, and when. To see a list of
thresholds and weather types, scroll down.
real Maximum Temperature: The absolute highest point the temperature will reach.
real Minimum Pressure: The absolute lowest point the pressure will go to. 800.0 is the
minimum value
real Maximum Pressure: The absolute highest point the pressure will go to. 1200.0 is the
maximum value
real Time between updates: The amount of time the system waits before incrementing itself and
possibly changing the weather. 1.00 is the expected value. Anything less than 0.1
has a chance of causing lag, depending on pc's and what else is running in wc3.
boolean Feedback: If this is true, all players will see the weather name, region number,
temperature and pressure of a weather system when it changes weather. Useful for
testing if the weather is appropriate in a map.
2.) weather_PauseWeather
weather_Pause_Weather(integer Handle, boolean Pause)
If Pause it true, pauses the weather system given by Handle.
Otherwise unpauses it.
Pause means the the weather system will not change from its current weather, but does not mean
that the weather itself will stop as it is.
3.) weather_DestroyWeather
weather_Destroy_Weather(integer Handle)
Destroys the weather system given by Handle and all its effects.
============================================>
Implementation:
Step 1 vJass:
To run this system you need an editor that supports vJass. If you do, read on. If you don't,
here are some:
World Editor Unlimited - http://www.wc3campaigns.net/showthread.php?t=81731 (Updates the
normal world editor)
Jass NewGen Pack - http://www.wc3campaigns.net/showthread.php?t=90999 (Another editor)
Step 2 CSCache:
This system requires a recent version of CSCache. If you don't have it, or have an older
version then copy the CSCache trigger into your map.
Step 3 Weather:
This system obviously requires the weather trigger...
Copy it into your map.
Done.
============================================>
Weather Thresholds: (What displays when)
Thresholds: Pressure Temperature Time
-Sandstorm >1195 Any Any
-Heavy wind <=1195, >1185 Any Any
-Light wind <=1185, >1160 Any Any
-Sunlight <=1160, >1080 Any Day
-Moonlight <=1160, >1080 Any Night
-Clouds <=1080, >1000* Any Any
-Fog <=1000, > 970 <18, >3 Any
-Light Rain <= 970, > 870 >0 Any
-Light Snow <= 970, > 870 <=0 Any
-Heavy Rain <= 870, > 830 >0 Any
-Heavy Snow <= 870, > 830 <=0 Any
-Storm <= 830 >0 Any
-Blizzard <= 830 <=0 Any
*If fog does not occur due to temperature, then cloud will occur between 1000 and 970.
============================================>
How to use in GUI:
Creating Permanent weather:
-In the trigger you want to start the weather system with, add a new Action.
-Scroll down to Custom Script.
-Enter "call weather_CreateWeather(Region, Minimum Temperature, Maximum
Temperature, Minimum Pressure, Maximum Pressure, Rate of Change, Enable Feedback)"
-Replace the values with your choice in the brackets with your settings.
Creating Weather that can be paused:
-Create a integer variable by pressing X in your trigger editor (I will call the variable
"Var Name" for this)
-In the trigger you want to start the weather system with, add a new Action.
-Scroll down to Custom Script.
-Enter "set udg_Var_Name = call weather_CreateWeather(Region, Minimum Temperature, Maximum
Temperature, Minimum Pressure, Maximum Pressure, Rate of Change, Enable Feedback)"
-Replace the values with your choice in the brackets with your settings, and Var Name with
the name of your variable. (Remember to change spaces to underscores and put udg_ in front)
Pausing Weather:
-In the trigger you want to pause the weather system with, add a new Action.
-Scroll down to Custom Script.
-Enter "call weather_PauseWeather(udg_Var_Name, true)"
-Replace Var Name with the name of your integer variable that you stored the original weather
in.(Remember to change spaces to underscores and put udg_ in front)
Unpausing Weather:
-In the trigger you want to unpause the weather system with, add a new Action.
-Scroll down to Custom Script.
-Enter "call weather_PauseWeather(udg_Var_Name, false)"
-Replace Var Name with the name of your integer variable that you stored the original weather
in.(Remember to change spaces to underscores and put udg_ in front)
Destroying Weather:
-In the trigger you want to destroy the weather system with, add a new Action.
-Scroll down to Custom Script.
-Enter "call weather_DestroyWeather(udg_Var_Name)"
-Replace Var Name with the name of your integer variable that you stored the original weather
in.(Remember to change spaces to underscores and put udg_ in front)
============================================>
Possible Uses:
A dark and stormy island: weather_CreateWeather(whichRegion, 2.0, 10.0, 800.0, 825.0, false)
=> The island will permanently be stormed on
A continent: weather_CreateWeather(GetWorldBounds(), -10.0, 15.0, 800.0, 1200.0, false)
=> Will experience every type of weather.
A sunny island: weather_CreateWeather(whichRegion, 2.0, 25.0, 1000.0, 1150.0, false)
=> Will experience only sun, moonlight and clouds
A desert: weather_CreateWeather(whichRegion, 2.0, 25.0, 1160.0, 1200.0, false)
=> Will experience light to sandstorm level dry winds.
A frozen wasteland: weather_CreateWeather(whichRegion, -25.0, -2.0, 800.0, 970.0, false)
=> Will experience light to blizzard level snow.
A swamp: weather_CreateWeather(whichRegion, 4.0, 10.0, 850.0, 1050.0, false)
=> Will have light rain, heavy rain, fog and clouds
============================================>
Notes for Customization:
There are many constants available for manipulation that will greatly affect the behaviour of
all weather. I've tried to make almost every useful value easily manipulatable in the constants
area of the library.
Not currently easily manipulatable are the threshold levels of weather effects, however these
can be editted further into the system. I have avoided placing constants for them as I believe
the system is probably currently setup in as believable a manner as it will get. If you disagree
let me know or just go nuts.
There are many, many comments throughout the system, they should help you know where you are and
what you're doing.
Finally,
If you find leaks, need to contact me for assistance in relation to the system or anything else
pm me at WC3Campaigns or TheHelper as gref, or send me an email at [email protected]
| Controlled Random Weather 1.12 by gref |
|======================================================================|
The purpose of this system is to allow developers a simple way to create and manipulate
believable and easily customized weather over multiple areas, to make maps better, and to make
mapmaking easier.
Table of Contents:
Credits
Functions
General Implementation
Weather Thresholds
How to use in GUI
Possible Uses
Notes for Customization
============================================>
Credits:
Vexorian for CSCache
xPheRe for his snippet which gave me the idea.
============================================>
Functions:
1.) weather_CreateWeather
weather_Create_Weather(rect Area, real Minimum Temperature, real Maximum Temperature, real
Minimum Pressure, real Maximum Pressure, real Time between updates,
boolean Feedback)
Returns integer Handle
This function is the standard function for creating weather. It can be called from any trigger
and gives you an integer Handle which can be used to pause, unpause and destroy the weather
created.
Argument explanation:
rect Area: The area you want the weather to appear over. For a standard world editor defined
region put gg_rct_ before the name and replace any spaces with underscores. ie.
gg_rct_Region_1
real Minimum Temperature: The absolute lowest point the temperature will reach. Temperature
and pressure have direct bearing on what weather occurs, and when. To see a list of
thresholds and weather types, scroll down.
real Maximum Temperature: The absolute highest point the temperature will reach.
real Minimum Pressure: The absolute lowest point the pressure will go to. 800.0 is the
minimum value
real Maximum Pressure: The absolute highest point the pressure will go to. 1200.0 is the
maximum value
real Time between updates: The amount of time the system waits before incrementing itself and
possibly changing the weather. 1.00 is the expected value. Anything less than 0.1
has a chance of causing lag, depending on pc's and what else is running in wc3.
boolean Feedback: If this is true, all players will see the weather name, region number,
temperature and pressure of a weather system when it changes weather. Useful for
testing if the weather is appropriate in a map.
2.) weather_PauseWeather
weather_Pause_Weather(integer Handle, boolean Pause)
If Pause it true, pauses the weather system given by Handle.
Otherwise unpauses it.
Pause means the the weather system will not change from its current weather, but does not mean
that the weather itself will stop as it is.
3.) weather_DestroyWeather
weather_Destroy_Weather(integer Handle)
Destroys the weather system given by Handle and all its effects.
============================================>
Implementation:
Step 1 vJass:
To run this system you need an editor that supports vJass. If you do, read on. If you don't,
here are some:
World Editor Unlimited - http://www.wc3campaigns.net/showthread.php?t=81731 (Updates the
normal world editor)
Jass NewGen Pack - http://www.wc3campaigns.net/showthread.php?t=90999 (Another editor)
Step 2 CSCache:
This system requires a recent version of CSCache. If you don't have it, or have an older
version then copy the CSCache trigger into your map.
Step 3 Weather:
This system obviously requires the weather trigger...
Copy it into your map.
Done.
============================================>
Weather Thresholds: (What displays when)
Thresholds: Pressure Temperature Time
-Sandstorm >1195 Any Any
-Heavy wind <=1195, >1185 Any Any
-Light wind <=1185, >1160 Any Any
-Sunlight <=1160, >1080 Any Day
-Moonlight <=1160, >1080 Any Night
-Clouds <=1080, >1000* Any Any
-Fog <=1000, > 970 <18, >3 Any
-Light Rain <= 970, > 870 >0 Any
-Light Snow <= 970, > 870 <=0 Any
-Heavy Rain <= 870, > 830 >0 Any
-Heavy Snow <= 870, > 830 <=0 Any
-Storm <= 830 >0 Any
-Blizzard <= 830 <=0 Any
*If fog does not occur due to temperature, then cloud will occur between 1000 and 970.
============================================>
How to use in GUI:
Creating Permanent weather:
-In the trigger you want to start the weather system with, add a new Action.
-Scroll down to Custom Script.
-Enter "call weather_CreateWeather(Region, Minimum Temperature, Maximum
Temperature, Minimum Pressure, Maximum Pressure, Rate of Change, Enable Feedback)"
-Replace the values with your choice in the brackets with your settings.
Creating Weather that can be paused:
-Create a integer variable by pressing X in your trigger editor (I will call the variable
"Var Name" for this)
-In the trigger you want to start the weather system with, add a new Action.
-Scroll down to Custom Script.
-Enter "set udg_Var_Name = call weather_CreateWeather(Region, Minimum Temperature, Maximum
Temperature, Minimum Pressure, Maximum Pressure, Rate of Change, Enable Feedback)"
-Replace the values with your choice in the brackets with your settings, and Var Name with
the name of your variable. (Remember to change spaces to underscores and put udg_ in front)
Pausing Weather:
-In the trigger you want to pause the weather system with, add a new Action.
-Scroll down to Custom Script.
-Enter "call weather_PauseWeather(udg_Var_Name, true)"
-Replace Var Name with the name of your integer variable that you stored the original weather
in.(Remember to change spaces to underscores and put udg_ in front)
Unpausing Weather:
-In the trigger you want to unpause the weather system with, add a new Action.
-Scroll down to Custom Script.
-Enter "call weather_PauseWeather(udg_Var_Name, false)"
-Replace Var Name with the name of your integer variable that you stored the original weather
in.(Remember to change spaces to underscores and put udg_ in front)
Destroying Weather:
-In the trigger you want to destroy the weather system with, add a new Action.
-Scroll down to Custom Script.
-Enter "call weather_DestroyWeather(udg_Var_Name)"
-Replace Var Name with the name of your integer variable that you stored the original weather
in.(Remember to change spaces to underscores and put udg_ in front)
============================================>
Possible Uses:
A dark and stormy island: weather_CreateWeather(whichRegion, 2.0, 10.0, 800.0, 825.0, false)
=> The island will permanently be stormed on
A continent: weather_CreateWeather(GetWorldBounds(), -10.0, 15.0, 800.0, 1200.0, false)
=> Will experience every type of weather.
A sunny island: weather_CreateWeather(whichRegion, 2.0, 25.0, 1000.0, 1150.0, false)
=> Will experience only sun, moonlight and clouds
A desert: weather_CreateWeather(whichRegion, 2.0, 25.0, 1160.0, 1200.0, false)
=> Will experience light to sandstorm level dry winds.
A frozen wasteland: weather_CreateWeather(whichRegion, -25.0, -2.0, 800.0, 970.0, false)
=> Will experience light to blizzard level snow.
A swamp: weather_CreateWeather(whichRegion, 4.0, 10.0, 850.0, 1050.0, false)
=> Will have light rain, heavy rain, fog and clouds
============================================>
Notes for Customization:
There are many constants available for manipulation that will greatly affect the behaviour of
all weather. I've tried to make almost every useful value easily manipulatable in the constants
area of the library.
Not currently easily manipulatable are the threshold levels of weather effects, however these
can be editted further into the system. I have avoided placing constants for them as I believe
the system is probably currently setup in as believable a manner as it will get. If you disagree
let me know or just go nuts.
There are many, many comments throughout the system, they should help you know where you are and
what you're doing.
Finally,
If you find leaks, need to contact me for assistance in relation to the system or anything else
pm me at WC3Campaigns or TheHelper as gref, or send me an email at [email protected]
Code:
JASS:
//===============================================================
// Controlled Random Weather 1.12 by gref
//===============================================================
library weather initializer InitWeather requires CSCache
globals
//===============================================================
// CONSTANTS
//===============================================================
//Blizzard and Lightning effects
private constant boolean effects_on = true
//Relative temperatures at times of day
private constant real max_time = 14.00 //Maximum at 2.00 pm
private constant real min_time = 4.00 //Minimum at 4.00 am
private constant real average_variation = 15.0 // The difference in degrees between
//max and min normally. If you want the average temperature to be between 5 and 25,
// you would set it 20 etc.
private constant real max_allowed_pressure = 1200
private constant real min_allowed_pressure = 800
private constant real seconds_in_day = 480.0
private constant real dawn = 6.0
private constant real dusk = 18.0
//Determines how large the change in temperature and pressure per second can grow to
private constant real max_temp_delta_variation = 0.2
private constant real max_mmHg_delta_variation = 25.0
//Determines the factor of decay back towards 0 of change in pressure
private constant real mmHg_decay = 0.9
//Names and values in array of the various weather effects
private constant integer sun = 039;LRaa039;
private constant integer cloud = 039;FDwl039;
private constant integer rain = 039;RAlr039;
private constant integer storm = 039;RAhr039;
private constant integer snow = 039;SNls039; //Rain & less than 0 degrees
private constant integer blizzard = 039;SNbs039; //Storm & less than 0 degrees
private constant integer moon = 039;LRma039; //Clear at night
private constant integer heavysnow = 039;SNhs039; //Heavy rain & less than 0
private constant integer heavyrain = 039;RLhr039;
private constant integer fog = 039;FDwh039;
private constant integer wind = 039;WOlw039;
private constant integer heavywind = 039;WOcw039;
private constant integer sandstorm = 039;WNcw039;
private constant string sun_name = "Sunlit"
private constant string cloud_name = "Overcast"
private constant string rain_name = "Light Rain"
private constant string storm_name = "Storm"
private constant string snow_name = "Light Snow"
private constant string blizzard_name = "Blizzard"
private constant string moon_name = "Moonlit"
private constant string heavysnow_name = "Heavy Snow"
private constant string heavyrain_name = "Heavy Rain"
private constant string fog_name = "Fog"
private constant string wind_name = "Light Wind"
private constant string heavywind_name = "Heavy Wind"
private constant string sandstorm_name = "Sandstorm"
//Lightning and Blizzard Effects
private constant real lightning_min = 0.25 //Smallest time between lightning strikes
private constant real lightning_max = 2.00 //Max time between lightning strikes
private constant real blizzard_min = 0.25 //Smallest time between ice shards
private constant real blizzard_max = 1.00 //Max time between ice shards
private constant string lightning_effect_strike = "Doodads\\Cinematic\\Lightningbolt\\Lightningbolt.mdl"
private constant string lightning_effect_impact = "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl"
private constant string blizzard_effect = "Abilities\\Spells\\Human\\Blizzard\\BlizzardTarget.mdl"
private constant string lightning_sound_effect = "Abilities\\Spells\\Orc\\LightningBolt\\LightningBolt.wav"
//===============================================================
// VARIABLES
//===============================================================
private integer array weather_id
private real array delta_temperature
private string array weather_name
endglobals
//Weather conditions data type
struct weather_conditions
integer current // current weather index (What the actualy weather is now)
integer previous
string w_name // the name of the current weather
string temperature
string pressure
// Tells you the region, weather, temperature and pressure when it changes.
boolean feedback_on
boolean change_weather
boolean enable_weather
rect weather_rect // the rect in which the weath occurs
timer effects_timer //The timer that ticks lightning effects
timer main_timer // The timer that ticks the entire system
timer weather_timer //The timer that ticks the weather effects
real max //maximum temperature
real min //minimum temperature
real min_pressure //minimum pressure
real max_pressure //maximum pressure
real rate_of_change //time between each update of the weather
real temp // temperature
real temp_delta
real temp_delta_i
real mmHg // atmospheric pressure
real mmHg_delta //change in atmospheric pressure
real mmHg_delta_i //stimulus for chance in atmospheric pressure
static method create takes nothing returns weather_conditions
local weather_conditions w = weather_conditions.allocate()
set w.effects_timer = CreateTimer()
set w.main_timer = CreateTimer()
set w.change_weather = true
set w.enable_weather = false
return w
endmethod
method onDestroy takes nothing returns nothing
local WeatherEffectStruct w_effect = GetAttachedInt(.weather_timer, "weath_effect")
call PauseTimer(.main_timer)
call PauseTimer(.effects_timer)
call PauseTimer(.weather_timer)
call WeatherEffectStruct.destroy(w_effect)
call CleanAttachedVars(.main_timer)
call CleanAttachedVars(.effects_timer)
call CleanAttachedVars(.weather_timer)
call DestroyTimer(.main_timer)
call DestroyTimer(.effects_timer)
call DestroyTimer(.weather_timer)
endmethod
endstruct
struct EffectStruct
effect e
method onDestroy takes nothing returns nothing
call DestroyEffect(.e)
endmethod
endstruct
struct WeatherEffectStruct takes nothing returns nothing
weathereffect e
method onDestroy takes nothing returns nothing
call EnableWeatherEffect(.e, false)
call RemoveWeatherEffect(.e)
endmethod
endstruct
//===============================================================
// RUNTIME FUNCTIONS
//===============================================================
private function RemoveEffect takes nothing returns nothing
local timer t = GetExpiredTimer()
call EffectStruct.destroy(GetAttachedInt(t, "effect"))
call CleanAttachedVars(t)
call DestroyTimer(t)
set t = null
endfunction
private function CreateEffect takes string model, real x, real y, real duration returns nothing
local timer t = CreateTimer()
local EffectStruct e = EffectStruct.create()
set e.e = AddSpecialEffect(model, x, y)
call AttachInt(t, "effect", e)
call TimerStart(t, duration, false, function RemoveEffect)
set t = null
endfunction
private function LightningBolt takes nothing returns nothing
local timer t = GetExpiredTimer()
local weather_conditions w = GetAttachedInt(t, "w")
local real x = GetRandomReal(GetRectMinX(w.weather_rect), GetRectMaxX(w.weather_rect))
local real y = GetRandomReal(GetRectMinY(w.weather_rect), GetRectMaxY(w.weather_rect))
local sound s = CreateSound(lightning_sound_effect,false, true, false, 5, 5, "SpellsEAX")
call CreateEffect(lightning_effect_strike, x, y, 0.50)
call CreateEffect(lightning_effect_impact, x, y, 1.00)
call SetSoundPosition(s, x, y, 0)
call SetSoundVolume(s, 127)
call StartSound(s)
call KillSoundWhenDone(s)
call TimerStart(GetExpiredTimer(), GetRandomReal(lightning_min, lightning_max), false, function LightningBolt)
set t = null
set s = null
endfunction
private function IceShard takes nothing returns nothing
local timer t = GetExpiredTimer()
local weather_conditions w = GetAttachedInt(t, "w")
local real x = GetRandomReal(GetRectMinX(w.weather_rect), GetRectMaxX(w.weather_rect))
local real y = GetRandomReal(GetRectMinY(w.weather_rect), GetRectMaxY(w.weather_rect))
call CreateEffect(blizzard_effect, x, y, 1.00)
call TimerStart(GetExpiredTimer(), GetRandomReal(blizzard_min, blizzard_max), false, function IceShard)
set t = null
endfunction
private function TimedEffects takes weather_conditions w returns nothing
//Makes pretty effects when there is a blizzard or storm
if(w.current == 3) then
call CleanAttachedVars(w.effects_timer)
call AttachInt(w.effects_timer, "w", w)
call TimerStart(w.effects_timer, GetRandomReal(lightning_min, lightning_max), false, function LightningBolt)
else
call CleanAttachedVars(w.effects_timer)
call AttachInt(w.effects_timer, "w", w)
call TimerStart(w.effects_timer, GetRandomReal(blizzard_min, blizzard_max), false, function IceShard)
endif
endfunction
private function ChangeWeatherEffect takes nothing returns nothing
//Recycles timer, makes and destroys effects on weather change.
local timer t = GetExpiredTimer()
local WeatherEffectStruct w_effect = GetAttachedInt(t, "weath_effect")
local weather_conditions w = GetAttachedInt(t, "w")
if(w.change_weather == true) then
call EnableWeatherEffect(w_effect.e, false)
call RemoveWeatherEffect(w_effect.e)
call CleanAttachedVars(t)
set w_effect.e = AddWeatherEffect(w.weather_rect, weather_id[w.current])
call AttachInt(t, "w", w)
call AttachInt(t, "weath_effect", w_effect)
call TimerStart(t, .05, false, function ChangeWeatherEffect)
set w.change_weather = false
else
call EnableWeatherEffect(w_effect.e, true)
call TimerStart(t, w.rate_of_change, false, function ChangeWeatherEffect)
endif
set t = null
endfunction
private function StartWeatherEffect takes weather_conditions w returns nothing
//Starts the weather changing process
local WeatherEffectStruct w_effect = WeatherEffectStruct.create()
set w_effect.e = AddWeatherEffect(w.weather_rect, weather_id[w.current])
set w.weather_timer = CreateTimer()
call AttachInt(w.weather_timer, "w", w)
call AttachInt(w.weather_timer, "weath_effect", w_effect)
call TimerStart(w.weather_timer, 0.05, false, function ChangeWeatherEffect)
set w.change_weather = false
endfunction
private function ShowWeather takes weather_conditions w returns nothing
set w.previous = w.current
// saves the previous effect, so we know if there was a change in weather this cycle
//Determine current weather
if (w.mmHg > 1195) then //Practically a Sandstorm
set w.current = 12
elseif (w.mmHg > 1185) then //Heavy Wind (Dry)
set w.current = 11
elseif (w.mmHg > 1160) then // Light Wind (Dry)
set w.current = 10
elseif (w.mmHg > 1080) then // Sun
if(GetFloatGameState(GAME_STATE_TIME_OF_DAY)<dawn)or(GetFloatGameState(GAME_STATE_TIME_OF_DAY)>dusk) then
set w.current = 6 //Moon
else //Sun
set w.current = 0
endif
elseif (w.mmHg > 1000) then // Cloud
set w.current = 1
elseif (w.mmHg > 970) then // Heavy Fog or Cloud
if(w.temp < 18)and(w.temp > 3) then
set w.current = 9
else
set w.current = 1
endif
elseif(w.mmHg > 870) then
if(w.temp > 0) then //Rain
set w.current = 2
else //Snow
set w.current = 4
endif
elseif(w.mmHg > 830) then
if(w.temp > 0) then //Heavy Rain
set w.current = 7
else //Heavy Snow
set w.current = 8
endif
else
if(w.temp > 0) then //Storm
set w.current = 3
else //Blizzard
set w.current = 5
endif
endif
//Update Weather Data
set w.w_name = weather_name[w.current]
set w.temperature = I2S(R2I(w.temp))
set w.pressure = I2S(R2I(w.mmHg))
//Show Weather Effects
if(w.current != w.previous) then
//Checks if weather is different, if so change it.
if (w.feedback_on == true ) then
call DisplayTextToPlayer(GetLocalPlayer(),0,0, "Region: "+I2S(w)+", Weather: "+w.w_name+", Temperature: "+w.temperature+", Pressure: "+w.pressure)
endif
call PauseTimer(w.effects_timer) //Stops effects in blizzard and storm
if((w.current == 3)or(w.current == 5))and(effects_on == true) then
//If blizzard or storm, then start effects
call TimedEffects(w)
endif
set w.change_weather = true //Tells Change_Weather_Effect to remove old effect and
// make new one
if(w.enable_weather == false) then
set w.enable_weather = true
call StartWeatherEffect(w)
//Starts the weather at creation
endif
endif
endfunction
private function WeatherIncrement takes nothing returns nothing
//Increments the weather system at rate of change intervals
//Gets temperature via randomness + time of day
//Gets atmospheric pressure via randomness and delta mmHg
//Uses data to apply weather changes.
local timer t = GetExpiredTimer()
local weather_conditions w = GetAttachedInt(t, "weather_var")
local real temp_factor = (24/(seconds_in_day*GetTimeOfDayScale()))*w.rate_of_change
//Every 20 seconds (By Default) = 1 hour, so adjust temperature change to occur at one unit per game hour
//Rate of Change impacts.
//Affect rates of change
set w.temp_delta_i = (delta_temperature[R2I(GetFloatGameState(GAME_STATE_TIME_OF_DAY))] + GetRandomReal(-0.5, 0.5))*temp_factor
set w.temp_delta = w.temp_delta+w.temp_delta_i
//Ensures that change in temperature is within max variation
if(w.temp_delta > max_temp_delta_variation)then
set w.temp_delta = max_temp_delta_variation
endif
if(w.temp_delta < (0-max_temp_delta_variation))then
set w.temp_delta = (0-max_temp_delta_variation)
endif
//Set new temperature
set w.temp = w.temp + w.temp_delta
if(w.temp > w.max)then
set w.temp = w.max
endif
if(w.temp < w.min)then
set w.temp = w.min
endif
//Affect rates of change
set w.mmHg_delta_i = w.mmHg_delta_i/2 + GetRandomReal(-2.5, 2.5)
set w.mmHg_delta = (w.mmHg_delta + w.mmHg_delta_i)*mmHg_decay
//Ensures that change in pressure is within max variation
if(w.mmHg_delta > max_mmHg_delta_variation)then
set w.mmHg_delta = max_mmHg_delta_variation
endif
if(w.mmHg_delta < (0-max_mmHg_delta_variation))then
set w.mmHg_delta = (0-max_mmHg_delta_variation)
endif
//Set new pressure
set w.mmHg = w.mmHg + w.mmHg_delta
if(w.mmHg > w.max_pressure)then
set w.mmHg = w.max_pressure
endif
if(w.mmHg < w.min_pressure)then
set w.mmHg = w.min_pressure
endif
call ShowWeather(w) //Displays the changes
set t = null
endfunction
public function PauseWeather takes weather_conditions w, boolean enable returns nothing
if(enable == true) then
call PauseTimer(w.main_timer)
else
call ResumeTimer(w.main_timer)
endif
endfunction
public function DestroyWeather takes weather_conditions w returns nothing
call weather_conditions.destroy(w)
endfunction
public function CreateWeather takes rect whichRect, real min_temp, real max_temp, real min_mmHg, real max_mmHg, real rate, boolean feedback returns integer
//Starts the weather system, uses a repeating timer to update the weather at rate_of_change intervals
local weather_conditions w = weather_conditions.create()
set w.current = 0
set w.feedback_on = feedback
set w.rate_of_change = rate // How fast the weather changes
set w.weather_rect = whichRect
//User Error checking:
if(min_temp > max_temp) then
set min_temp = max_temp
endif
if(min_mmHg > max_mmHg) then
set min_mmHg = max_mmHg
endif
if (min_mmHg < min_allowed_pressure) then //Absolute minimum pressure
set w.min_pressure = min_allowed_pressure
else
set w.min_pressure = min_mmHg
endif
if (max_mmHg > max_allowed_pressure) then //Absolute maximum pressure
set w.max_pressure = max_allowed_pressure
else
set w.max_pressure = max_mmHg
endif
set w.min = min_temp //Absolute minimum temperature
set w.max = max_temp //Absolute maximum temperature
//End User Error checking.
set w.mmHg_delta_i = GetRandomReal(-4.0, 4.0)
set w.mmHg_delta = GetRandomReal(0-max_mmHg_delta_variation, max_mmHg_delta_variation)
set w.mmHg = GetRandomReal(min_mmHg, max_mmHg)
set w.temp_delta_i = GetRandomReal(-4.0, 4.0)
set w.temp_delta = GetRandomReal(0-max_temp_delta_variation, max_temp_delta_variation)
set w.temp = GetRandomReal(min_temp, max_temp)
call ShowWeather(w)
call AttachInt(w.main_timer, "weather_var", w)
call TimerStart(w.main_timer, w.rate_of_change, true, function WeatherIncrement)
return w
endfunction
//===============================================================
// INITIALIZATION
//===============================================================
private function IsNumberBetween takes integer a, integer b, integer c returns boolean
//called by Initialize_delta_temperatures
if (a > b) then
return (a>c and c>b)
else
return (b>c and c>a)
endif
endfunction
private function InitializeDeltaTemperature takes nothing returns nothing
// Makes an approximation of the rate of change of temperature at various times of day
// Based on globals min_time, max_time, difference.
local integer i = 0
local integer gap
local integer minimum = R2I(min_time)
local integer maximum = R2I(max_time)
local real rate_per_hour
local real ratio
local integer distance_to_max
local integer distance_to_min
loop
exitwhen i == 24
if (IsNumberBetween(minimum, maximum, i) == true) then
set gap = IAbsBJ(minimum - maximum)
else
set gap = 24 - IAbsBJ(minimum - maximum)
endif
set distance_to_max = IAbsBJ(maximum - i)
if(distance_to_max > 12) then
set distance_to_max = 24 - distance_to_max
endif
set distance_to_min = IAbsBJ(minimum - i)
if(distance_to_min > 12) then
set distance_to_min = 24 - distance_to_min
endif
set rate_per_hour = (average_variation)/I2R(gap)
set ratio = (I2R(IAbsBJ(distance_to_min))/I2R(gap))
if(ratio > .5) then
set delta_temperature<i> = (I2R(IAbsBJ(distance_to_max))/I2R(gap))*4*rate_per_hour
else
set delta_temperature<i> = ratio*4*rate_per_hour
endif
if(IsNumberBetween(minimum, maximum, i) == true) then
if(i < minimum) then
set delta_temperature<i> = 0 - delta_temperature<i>
endif
else
if(maximum > minimum) then
set delta_temperature<i> = 0 - delta_temperature<i>
endif
endif
set i = i + 1
endloop
endfunction
private function InitWeather takes nothing returns nothing
//Initialize Variables
call InitializeDeltaTemperature()
set weather_name[0] = sun_name
set weather_name[1] = cloud_name
set weather_name[2] = rain_name
set weather_name[3] = storm_name
set weather_name[4] = snow_name
set weather_name[5] = blizzard_name
set weather_name[6] = moon_name
set weather_name[7] = heavyrain_name
set weather_name[8] = heavysnow_name
set weather_name[9] = fog_name
set weather_name[10] = wind_name
set weather_name[11] = heavywind_name
set weather_name[12] = sandstorm_name
set weather_id[0] = sun
set weather_id[1] = cloud
set weather_id[2] = rain
set weather_id[3] = storm
set weather_id[4] = snow
set weather_id[5] = blizzard
set weather_id[6] = moon
set weather_id[7] = heavyrain
set weather_id[8] = heavysnow
set weather_id[9] = fog
set weather_id[10] = wind
set weather_id[11] = heavywind
set weather_id[12] = sandstorm
endfunction
endlibrary
</i></i></i></i></i></i>
Purpose of the system:
To create a random weather system that allows developers a simple way to create and manipulate
believable and easily customized weather over multiple areas, to make maps better, and to make
mapmaking easier.
Any weather system can be created, paused or destroyed in one function call, and the system is multi-instanceable so that different weather systems can be created, manipulated and destroyed at any point.
Weather effects:
-Sandstorm
-Heavy wind
-Light wind
-Sunlight
-Moonlight
-Cloud cover
-Fog
-Light Rain
-Light Snow
-Heavy Rain
-Heavy Snow
-Storm
-Blizzard
Changelog:
v1.00
Initial release
v1.10
Remade readme.
Code slightly restructured.
Pause, Unpause, Destroy, and Create_Weather_Permanent added.
Better demonstration added.
v1.11
Realised Create_Weather_Permanent was useless. Removed it.
v1.12
Optimized IsNumberBetween
Made function names "less ugly"
Implemented struct based attachment in CreateEffect and CreateWeatherEffect
Removed GetAttachedWeatherEffect
If you find leaks, want to give me a suggestion, or comment, then feel free to pm me here, or send me an email at [email protected]