Jump to content
Sign in to follow this  
meatball

Creating Dynamic Weather in Arma 3

Recommended Posts

As I'm testing there seem to be a few tricky parts left. Weather has become so much more complicated in Arma 3. My first goal is to release the DynamicWeatherEffects scripts for Arma 3 and have it work at least like the one for Arma 2. Then I will consider new Arma 3 stuff like waves and lightning etc in future releases. My guess is that BI has some weather updates on their TODO list too... Thanks for all the helpful info in this thread btw! Hope to be back with a working weather script in a few days!

Share this post


Link to post
Share on other sites

Engima, from what I can tell, waves are automatic based off of current wind and lightning is based off of overcast. So if you can figure out how to handle overcast, rain, fog and wind, I think you're most of the way there. At least until BI comes up with updates to it.

Share this post


Link to post
Share on other sites

not sure if this is what you are looking for, but if you want to look into editing the weather classes too you will be able to draw some usefull conclusions about some of the parameters in the cfg 1:1 fromt this video

Share this post


Link to post
Share on other sites

Wanted to post my latest version of the multiplayer random weather script I'm using. _Seems_ to be working correctly player hosted or dedicated missions so far. This script will set initial weather based on a players choice in parameters (defaults to Clear), then every 15 minutes it will randomly adjust the weather a small amount and attempt to keep the server and all clients in synch. It's kludgey, but it seems to work.

/*  
randomWeather.sqf v 0.8
- Multiplayer Mission Random Weather Generator
- By Meatball

Script Requirements:

1) Put this code/script in a file named "randomWeather.sqf" in root mission folder.

2) Create a call in init.sqf that will run for the server and all clients.
   execVM "randomWeather.sqf";

3) Have the following code in the "class Params" section of your description.ext to create weather as a selectable parameter for the players.  

class Params
{
// paramsArray[0]
   class initialWeather {
       title = "Initial Weather (Bugged/Not Working When Hosted on a Dedicated Server)";
       values[] = {1,2,3,4,5,6,7};
       texts[] = {"Clear","Overcast","Light Rain","Heavy Rain","Light Fog","Heavy Fog","Random"};
       default = 1;
   }; 
}; 

*/

// Initial Server Weather Setup

if(isServer) then {

// Set initial weather values based on parameter choice.  Make sure the # in the select below matches what # in the order of parameters (starting with 0) your initialWeather class is defined in the description.ext
initialWeather = (paramsArray select 0);  
switch (initialWeather) do{
   case 1: {forecastOvercast = 0;forecastRain = 0;forecastFog = 0;forecastWindE = 1;forecastWindN = 1;};            // Clear
   case 2: {forecastOvercast = .45;forecastRain = .45;forecastFog = 0;forecastWindE = 2;forecastWindN = 2;};    // Overcast
   case 3: {forecastOvercast = .70;forecastRain = .70;forecastFog = .05;forecastWindE = 3;forecastWindN = 3;};    // Light Rain
   case 4: {forecastOvercast = 1;forecastRain = 1;forecastFog = .05;forecastWindE = 4;forecastWindN = 4;};        // Heavy Rain
   case 5: {forecastOvercast = .75;forecastRain = .10;forecastFog = .30;forecastWindE = 1;forecastWindN = 1;};    // Light Fog
   case 6: {forecastOvercast = .85;forecastRain = .20;forecastFog = .50;forecastWindE = 0;forecastWindN = 0;};    // Heavy Fog
   case 7: {forecastOvercast = random(1);forecastRain = random(1);forecastFog = random(.20);forecastWindE = (random(14)-7);forecastWindN = (random(14)-7);};    // Random
};

// Set up variable to track server weather updates.
   serverWeather = 0;

// Broadcast initial weather settings that were set based on parameter choice.   
   publicVariable "forecastOvercast";
   publicVariable "forecastRain";
   publicVariable "forecastFog";
   publicVariable "forecastWindE";
   publicVariable "forecastWindN";
   publicVariable "serverWeather";
};

// Server and Client weather set based on initial weather parameter values.

waitUntil {!isnil "serverWeather"};
   skiptime -24;
   86400 setOvercast forecastOvercast;
   86400 setFog forecastFog;
   86400 setRain forecastRain;
   setWind [forecastWindE,forecastWindN,true];
   skipTime 24;
   simulWeatherSync;  

// Debug Hint
//hint "Initial Weather Setup";

// Server Loop to create a new weather forecast every 15 minutes.    
if(isServer) then {
   while {serverWeather >= 0} do {  // This will always be true and it will run as long as server runs.

randOCorRain = random (2);  // Pick a random number between 0 and 2 to update Overcast or Rain this cycle since you can't to both.  If random value is Less than or equal to 1 Overcast will be updated this cycle, if value is greater than 1, update rain this cycle.

 // Configure weather settings on server to match next 15 minute weather forecast.
       900 setFog forecastFog;
       if (randOCorRain <= 1) then {
       900 setOvercast forecastOvercast;} else {
       900 setRain forecastRain;};
       sleep 900;
       setWind [forecastWindE,forecastWindN,true];

// Create random numbers for next forecast.
   _randOvercast = (round((random(0.2)-0.1)*100))/100;
   _randRain = (round((random(0.2)-0.1)*100))/100;
   _randFog = (round((random(0.1)-0.05)*100))/100;
   _randWindE = (round((random(1)-0.5)*100))/100;
   _randWindN = (round((random(1)-0.5)*100))/100;

// Create next random overcast level and keep it between 0 and 1
   forecastOvercast = forecastOvercast + _randOvercast;
   if (forecastOvercast > 1) then {forecastOvercast = forecastOvercast - (2*_randOvercast)};
   if (forecastOvercast < 0) then {forecastOvercast = forecastOvercast + (abs(2*_randOvercast))};

// Create next random rain level and keep it between 0 and 1
   forecastRain = forecastRain + _randRain;
   if (forecastRain > 1) then {forecastRain = forecastRain - (2*_randRain)};
   if (forecastRain < 0) then {forecastRain = forecastRain + (abs(2*_randRain))};

// Create next random fog level and keep between 0 and 0.5
   forecastFog = forecastFog + _randFog;
   if (forecastFog > 0.5) then {forecastFog = forecastFog - (2*_randFog)};
   if (forecastFog < 0) then {forecastFog = forecastFog + (abs(2*_randFog))};

// Create next random E-W Wind level and keep between -10 and 10
   forecastWindE = forecastWindE + _randWindE;
   if (forecastWindE > 10) then {forecastWindE = forecastWindE - (2*_randWindE)};
   if (forecastWindE < -10) then {forecastWindE = forecastWindE + (abs(2*_randWindE))};

// Create next random N-S Wind level and keep between -10 and 10
   forecastWindN = forecastWindN + _randWindN;
   if (forecastWindN > 10) then {forecastWindN = forecastWindN - (2*_randWindN)};
   if (forecastWindN < -10) then {forecastWindN = forecastWindN + (abs(2*_randWindN))};

// Increment variable to track updates to server weather
   serverWeather = serverWeather + 1;

// Debug Hint - Show Current and Forecast Overcast, Humidity, Fog and Wind Levels on the Server.
// hint format ["Updating Server Forecast # %1 CO: %2 | CH: %3 | CR: %4 | CF: %5 |CW: %6 | FO: %7 | FH: %8 | FR: %9 | FF: %10 | FW: %11,%12 | OCorRain: %13",serverWeather,Overcast,Humidity,Rain,Fog,wind,forecastOvercast,forecastHumidity,forecastRain,forecastFog,forecastWindE,forecastWindN,randOCorRain];

// Broadcast server weather forecast information to clients.
   publicVariable "forecastOvercast";
   publicVariable "forecastRain";
   publicVariable "forecastFog";
   publicVariable "forecastWindE";
   publicVariable "forecastWindN";
   publicVariable "serverWeather";
   publicVariable "randOCorRain";
   };
};

if (!isServer) then {
// Client Weather forecast loop.

// Set up counter on client to compare local client weather serverWeather counter.
   clientWeather = 0;

// Run a continuous loop on the client to look for updated weather values from the server every 10 seconds.
   while {clientWeather >= 0} do {
       sleep 10;

    // If client Weather is older than the server weather, set client 15 minute weather forecast to match server.
       if (clientWeather < serverWeather) then {

    // Set clientWeather counter to match serverWeather counter so local client weather will not update until next server weather update.
       clientWeather = clientWeather + 1;

    // Debug Hint - Show Current and Forecast Overcast, Humidity, Fog and Wind Levels on the Client
    // hint format ["Updated Client Forecast # %1 - CO: %2 | CH: %3 | CR: %4 | CF: %5 |CW: %6 | FO: %7 | FH: %8 | FR: %9 | FF: %10 | FW: %11,%12 | OCorRain: %13",clientWeather,Overcast,Humidity,Rain,Fog,wind,forecastOvercast,forecastHumidity,forecastRain,forecastFog,forecastWindE,forecastWindN,randOCorRain];

    // Set 15 minute forecast for the client.
       900 setFog forecastFog;
	if (randOCorRain <= 1) then {
       900 setOvercast forecastOvercast;} else {
       900 setRain forecastRain;};
       sleep 900;
       setWind [forecastWindE,forecastWindN,true];
       };
   };
};  

Edited by Meatball

Share this post


Link to post
Share on other sites

Hi,

firstable thanks for your great script.

I have nearly no knowledge in Arma scripting but i'm programmer in some other programming languages and i got a question in my mind bwhile reading your script. You raise the counters serverWeather and clientWeather time by time and i thought what will happened when the mission will be very long. Everytime the counter variables will reaches there end (overflow). May be it's better to reset the counters to zero when reaching this end line or raise it on first step and lower it on next step?

Hope it will help you. Greets

Share this post


Link to post
Share on other sites
Hi,

firstable thanks for your great script.

I have nearly no knowledge in Arma scripting but i'm programmer in some other programming languages and i got a question in my mind bwhile reading your script. You raise the counters serverWeather and clientWeather time by time and i thought what will happened when the mission will be very long. Everytime the counter variables will reaches there end (overflow). May be it's better to reset the counters to zero when reaching this end line or raise it on first step and lower it on next step?

Hope it will help you. Greets

Hadn't really considered that since the counter will only go up at most, once every 15 minutes. So for a server that's up 24 hours, that's 96 counter increments, a month would be 2,880. I agree it's not the best method, but it's the simplest way I could think of keeping Client/Server weather in synch. I'm still relatively new to Arma scripting as well, so I'm up for any suggestions :)

Share this post


Link to post
Share on other sites

My missions run 3-5 hours long. Seems to work just fine. I use random (the whole point of this, otherwise you can just set in Editor). I have client/host checking every 2 minutes or so, not every x seconds to stay in sync. Its not 100%, but very close; close enough to not really notice. The weather change is set for every hour or so. I'm running this in every Map/Mission. Keep it brother. :)

Share this post


Link to post
Share on other sites

Hi,

May be someone can help me by my problem. I want to make a really stormy sea in my mission but without rain (like paracell storm in bf4). I've tested a little bit around in the editor an set the waves to 100, both wind to 100, rain and lightning to zero. I set the same values in forecast and test it. The waves are nice but not like a really storm. Do i something wrong, or is it possible to set higher waves by script?

Thx forward.

Share this post


Link to post
Share on other sites

Min/Max slider should be min/max script, gagagu. Also I think rain is bound to overcast, i.e. you cannot prevent ArmA to let it rain when full overcast. (I can be wrong here).

Meatball, has anything substancially changed on the ArmA side? Because I really had no more fun in developing the weather script to be more flexible/ and on single player side and as an Addon, because simply the possible weather transitions are not useful at all. The transition arguments (first arguments) in the weather commands were simply not doing what they promise and after all, only either abrupt weather changes or loooooong transitions or transitions at specific times (half hour cycles) are possible.

EDIT: In the devbranch changelog I do not see anything related. Except the new rain display. I wish quicker and fluid weather changes were possible. I'd immediately make an addon in order to spice up some missions. But I can't because of the PITA. I really do not like this ultra clean "sun is shining in Greece" mission setting.

Edited by tortuosit

Share this post


Link to post
Share on other sites

Yeah, I've not seen any major updates to weather so far from BI other than the updates to the look of rain. Rain does still seem to be tied to overcast level as in, you have to have a minimum overcast level for it to rain (50% I believe), and with high overcast levels the engine might create rain anyways.

I did tweak the weather script a bit to no longer update both overcast and rain at the same time. I think that might have been part of the problem with the earlier versions of the script. I also _believe_ the script should work as is for single player too since even in single player, the player's machine is considered 'server'.

Share this post


Link to post
Share on other sites

900 setFog forecastFog;
[...]
sleep 900;

15 Minutes: will it really work given that only every half and full hour a weather transition can be done? http://forums.bistudio.com/showthread.php?164140-Creating-Dynamic-Weather-in-Arma-3&p=2525929&viewfull=1#post2525929

This and necessity of nextWeatherChange still prevents me from having fun with weather changes.

Share this post


Link to post
Share on other sites

Yes, it will really work, because the transitions during 15 minutes are not going from 0 - 1 or 1 - 0. At most during a 15 minute time frame Overcast and Rain will change up to .1 up or down, Fog will change up to .05 up or down and wind .5 up or down.

Share this post


Link to post
Share on other sites

SPOTREP #15: "Weather is now correctly updated when the time shifts for a briefing (e.g. fixes out-of-place rain during one briefing). Wind and rain are handled better."

I hope they stumble over even more weather problems in their mission making :)

Share this post


Link to post
Share on other sites

Hey.. after going through your script this is what I tried to do. I don't know why it doesn't work.

Local exec for setFog, setOvercast works.. with the workaround of

skiptime -24;

(make weather changes);

skipTime 24;

simulWeatherSync;

Also.. like you mentioned that setOvercast and setFog cannot be used together at the same time, are there any other dependencies or constraints of the same sort?

For e.g. Like setRain works only if Overcast is 0.7 or above.

I am asking because I tried using setRainbow, setLightnings, setWaves assuming that setRainbow and setWaves would require rain and hence overcast...

I am calling the sqf file in init.sqf like this.....

[4, 'fog'] execVM "dynamicWeather.sqf";

private ["_initialWeatherPreset, _weatherOvercastOrFog"];	//_weatherOvercastOrFog - since only one of the two commands setOvercast and setFog work at a given time
private ["_initialFog, _initialOvercast, _initialRain", "_initialWindE", "_initialWindN", "_initialWindDir","_initialWindForce", "_initialWindStr", "_initialGusts", "_initialRainbow", "_initialLightnings", "_initialWaves"];

_initialWeatherPreset	= 	_this select 0;
_weatherOvercastOrFog	=	_this select 1;

dw_dynamicWeatherEventArgs = [];						//Values will be passed through this array to set weather
dw_askServerWeatherChangeEventArgs = [];					//Used to query server for weather changes
dw_serverInitialized = false;							//Used by server to notify clients of its initialization

dw_fnc_SetWeatherLocal = {

private ["_currentFog, _currentOvercast, _currentRain", "_currentWindE", "_currentWindN", "_currentWindDir","_currentWindForce", "_currentWindStr", "_currentGusts", "_currentRainbow", "_currentLightnings", "_currentWaves", "_currentWeatherType"];
private ["_transitionTime"];

_transitionTime		= 86400;					// In secs 

_currentFog 			= _this select 0;
_currentOvercast 		= _this select 1;
_currentRain 			= _this select 2;
_currentWindE 		= _this select 3;
_currentWindN 		= _this select 4;
_currentWindDir 		= _this select 5;
_currentWindForce 	= _this select 6;
_currentWindStr 		= _this select 7;
_currentGusts 		= _this select 8;
_currentRainbow 		= _this select 9;
_currentLightnings 	= _this select 10;
_currentWaves 		= _this select 11;
_currentWeatherType	= _this select 12;


//set new weather
skipTime -24;

if (_currentWeatherType == 'overcast') then {
	_transitionTime	setOvercast	_currentOvercast;
};
if (_currentWeatherType == 'fog') then {
	_transitionTime	setFog		_currentFog;		
};
_transitionTime	setRain		_currentRain;
_transitionTime	setWindDir	_currentWindDir;
_transitionTime	setWindForce	_currentWindForce;
_transitionTime	setWindStr	_currentWindStr;
_transitionTime	setGusts		_currentGusts;
_transitionTime	setRainbow	_currentRainbow;
_transitionTime	setLightnings	_currentLightnings;
_transitionTime	setWaves		_currentWaves;

skipTime 24;
setWind [_currentWindE, _currentWindN, true];	//true for setting this as permanent wind vector.
simulWeatherSync;								//sync simul weather w/ arma weather	
};

//This method is only called by server to broadcast the updated weather values
dw_fnc_SetWeatherGlobal = {
private ["_currentFog, _currentOvercast, _currentRain", "_currentWindE", "_currentWindN", "_currentWindDir","_currentWindForce", "_currentWindStr", "_currentGusts", "_currentRainbow", "_currentLightnings", "_currentWaves", "_currentWeatherType"];
_currentFog 			= _this select 0;
_currentOvercast 		= _this select 1;
_currentRain 			= _this select 2;
_currentWindE 		= _this select 3;
_currentWindN 		= _this select 4;
_currentWindDir 		= _this select 5;
_currentWindForce 	= _this select 6;
_currentWindStr 		= _this select 7;
_currentGusts 		= _this select 8;
_currentRainbow 		= _this select 9;
_currentLightnings 	= _this select 10;
_currentWaves 		= _this select 11;
_currentWeatherType	= _this select 12;

dw_dynamicWeatherEventArgs = [_currentFog, _currentOvercast, _currentRain, _currentWindE, _currentWindN, _currentWindDir,_currentWindForce, _currentWindStr, _currentGusts, _currentRainbow, _currentLightnings, _currentWaves, _currentWeatherType];
publicVariable "dw_dynamicWeatherEventArgs";				//Broadcast weather to all clients
dw_dynamicWeatherEventArgs call dw_fnc_SetWeatherLocal;	//Set weather on server explicitly since broadcasting machine doesn't  get broadcasted value
};


//Client code
if !(isServer) then {
//Listen for broadcasted weather changes from server
"dw_dynamicWeatherEventArgs" addPublicVariableEventHandler {
	dw_dynamicWeatherEventArgs call dw_fnc_SetWeatherLocal;
};

//wait until server is ready
//waitUntil { dw_serverInitialized == true;};

//query server for weather changes
//dw_askServerWeatherChangeEventArgs = [true];
//publicVariable "dw_askServerWeatherChangeEventArgs";
};

//Server code
if (isServer) then {

//Depending on parameter passed select initial weather preset.
switch (_initialWeatherPreset) do{
	case 0	:	{_initialFog = 0; _initialOvercast = 0; _initialRain = 0; _initialWindE = 1; _initialWindN = 1, _initialWindDir = 100; _initialWindForce = 0.25; _initalWindStr = 0.12; _initialGusts = 0; _initialRainbow = 0; _initialLightnings = 0; _initialWaves = 0;};					//Clear 
	case 1	:	{_initialFog = 0; _initialOvercast = 0.60; _initialRain = 0; _initialWindE = 2; _initialWindN = 2, _initialWindDir = 100; _initialWindForce = 0.45; _initalWindStr = 0.25; _initialGusts = 0.2; _initialRainbow = 0; _initialLightnings = 0; _initialWaves = 0.34;};			//Overcast
	case 2	:	{_initialFog = 0.05; _initialOvercast = 0.71; _initialRain = 0.71; _initialWindE = 3; _initialWindN = 2; _initialWindDir = 155; _initalWindForce = 0.57; _initalWindStr = 0.46; _initialGusts = 0.43; _initialRaibow = 0.59; _initialLightnings = 0; _initialWaves = 0.56;}; 	//Light Rain w/ Rainbow
	case 3	:	{_initialFog = 0.45; _initialOvercast = 0.86; _initialRain = 0.82; _initialWindE = 1.545; _initialWindN = -1.636; _initialWindDir = 225; _initialWindForce = 0.66; _initialWindStr = 0.60; _initialGusts = 0.64; _initialRainbow = 0; _initialLightnings = 0.25; _initialWaves = 0.66;}; //Heavy rain w/ moderate lightning
	case 4	:	{_initialFog = 0.86; _initialOvercast = 0.90; _initialRain = 0.91; _initialWindE = 2.636; _initialWindN = -1.686; _initialWindDir = 290; _initialWindForce = 0.85; _initialWindStr = 0.79; _initialGusts = 0.78; _initialRainbow = 0; _initialLightnings = 0.73; _initialWaves = 0.77;}; //Heavy rain w/ heavy lightning w/ heavy fog
	case 5	:	{_initialFog = random(1); _initialOvercast = random(1); _initialRain = random(1); _initialWindE = (random(14)-7); _initialWindN = random(14)-7); _initialWindDir = random(360.00); _initialWindForce = random(1); _initialWindStr = random(1); _initialGusts = random(1); _initialRainbow = random(1); _initialLightnings = random(1); _initialWaves = random(1);};	//Random
};

dw_dynamicWeatherEventArgs = [_initialFog, _initialOvercast, _initialRain, _initialWindE, _initialWindN, _initialWindDir,_initialWindForce, _initialWindStr, _initialGusts, _initialRainbow, _initialLightnings, _initialWaves, _weatherOvercastOrFog];
publicVariable "dw_dynamicWeatherEventArgs";
dw_dynamicWeatherEventArgs call dw_fnc_SetWeatherLocal;

//Notify all clients that the server is initialized. Now they can query for weather changes
//dw_serverInitialized = true;
//publicVariable "dw_serverInitialized";

//Send clients current weather upon receiving request
/*"dw_askServerWeatherChangeEventArgs" addPublicVariableEventHandler {
	dw_dynamicWeatherEventArgs = [_initialFog, _initialOvercast, _initialRain, _initialWindE, _initialWindN, _initialWindDir,_initialWindForce, _initialWindStr, _initialGusts, _initialRainbow, _initialLightnings, _initialWaves, _weatherOvercastOrFog];
	dw_dynamicWeatherEventArgs call dw_fnc_SetWeatherGlobal;
};*/

//Keep changing weather every 15 mins
While {TRUE} do
{
		sleep					900;					// 15 mins

		//Generate new weather randomly
		_initialFog 			= 	random(1); 
		_initialOvercast 		= 	random(1); 
		_initialRain 			= 	random(1);
		_initialWindE 		= 	(random(14)-7); 
		_initialWindN 		= 	(random(14)-7); 
		_initialWindDir 		= 	random(360.00); 
		_initialWindForce 	= 	random(1); 
		_initialWindStr 		= 	random(1); 
		_initialGusts 		= 	random(1); 
		_initialRainbow 		= 	random(1); 
		_initialLightnings 	= 	random(1); 
		_initialWaves 		= 	random(1);

		//Set newly generated weather
		dw_dynamicWeatherEventArgs = [_initialFog, _initialOvercast, _initialRain, _initialWindE, _initialWindN, _initialWindDir,_initialWindForce, _initialWindStr, _initialGusts, _initialRainbow, _initialLightnings, _initialWaves, _weatherOvercastOrFog];
		publicVariable "dw_dynamicWeatherEventArgs";
		dw_dynamicWeatherEventArgs call dw_fnc_SetWeatherLocal;
};

};





Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×