Jump to content
Sign in to follow this  
meatball

Creating Dynamic Weather in Arma 3

Recommended Posts

There's a couple of threads floating around about weather, but I thought it'd be good to pull everything into one location. Sorry for the long post, but trying to pull together some things from multiple posts. Since we can't use Engima's old DynamicWeatherEffects.sqf I've been trying to pull together a script that will do the following.

  1. Allow players to choose initial ingame weather conditions that will synch will server and clients.
  2. Dynamically change the weather randomly on the server at a recurring interval and synch the updates with all the clients.
  3. Be able to synch current weather conditions for JIP players and loop them into the recurring random server updates.

After banging my head on the script for a while and trying to figure how to make it work, I think the following is accurate (but could be wrong):

  1. setOvercast does not create clouds. All it does is 'darken' the amount of sun that appears to be reaching the ground.
  2. simulSetHumidity actually creates the clouds and the rain, but appears to rely on it being overcast enough (not sure of the minimum level) for rain to occur.
  3. setOvercast appears to need the 'skipTime -24' / 'skipTime 24' trick to set the Overcast level correctly at mission start, setHumidity does not.
  4. You need both setOvercast and simulSetHumidity to be high for it to actually rain.
  5. You can still use setRain, but without the overcast/humidity it doesn't appear to do anything.
  6. There does not appear to be a way to transition in overcast over a short period of time. I ran a test and had a radio trigger setOvercast to 1 from 0 and after a minute it had climbed up to 0.0167569. Which means, even with "0 setOvercast 1;", it will take an hour to reach 1. Setting from 1 to 0 and it goes even slower counting down.
  7. On the flip side, you can't slowly transition humidity (clouds) at all. When you simulSetHumidity it goes immediately to the value which is really jarring. Only thing I can think of to mitigate that is to use smaller jumps/drops in humidity, but update them more frequently.

Some Examples:

  • Overcast 0, Humidity 0 will be bright and sunny on the ground and have no clouds in the sky.
  • Overcast 1, Humidity 0 will appear very dark on the ground and the sky will be hazy, but there won't be a cloud in the sky.
  • Overcast 0, Humidity 1 will appear very sunny on the ground, but the sky will be loaded with clouds.
  • Overcast 1, Humidity 1 will appear dark on the ground, the sky will be loaded with clouds, and it will start to rain after about 10 seconds.

So, my first attempt seems to work for what I wanted to do, but it was pretty limited in that it was only updating the weather 3 times at one hour intervals. I wanted to create a script that would just keep spitting out random weather updates as long as the server was running, and at shorter intervals.

I started mostly from scratch (so may have screwed up something along the way) and worked up the following. Seems to work in certain cases, but for some reason, I can't for the life of me get it to work when using a dedicated server. The server code block seems to work fine if I host the game locally, but as soon as I put the mission on a ded server and connect, it doesn't seem to process any of the weather updates/changes. If anyone has any thoughts on what's wrong or places where I can clean up the code, they'd be appreciated!

/*  randomWeather.sqf v 0.3
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 on 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.  

// paramsArray[5]
      class initialWeather {
         title = "Initial Weather";
         values[] = {0,1,2,3,4,5,6};
         texts[] = {"Clear","Overcast","Light Rain","Heavy Rain","Light Fog","Heavy Fog","Random"};
         default = 0;
      }; 

*/

// Server/Server Client/JIP Check
if (!isServer && isNull player) then {isJIP=1;} else {isJIP=0;};

// Set forecast Weather from Parameter options chosen by players.
if(isServer) then {

// Make sure the # in the select below matches what order # in the parameters your initialWeather class is in the description.ext
initialWeather = (paramsArray select 5);  
switch (initialWeather) do{
case 0: {forecastOvercast = 0;forecastHumidity = 0;forecastFog = 0;};							// Clear
case 1: {forecastOvercast = .65;forecastHumidity = .50;forecastFog = 0;};						// Overcast
case 2: {forecastOvercast = .80;forecastHumidity = .80;forecastFog = .05;};						// Light Rain
case 3: {forecastOvercast = 1;forecastHumidity = 1;forecastFog = .05;};							// Heavy Rain
case 4: {forecastOvercast = .75;forecastHumidity = .10;forecastFog = .30;};						// Light Fog
case 5: {forecastOvercast = .85;forecastHumidity = .20;forecastFog = .50;};						// Heavy Fog
case 6: {forecastOvercast = random(1);forecastHumidity = random(1);forecastFog = random(.20);};	// Random
};

// Set up variable to track serverWeather changes.
serverWeather = 0;

publicVariable "forecastOvercast";
publicVariable "forecastHumidity";
publicVariable "forecastFog";
publicVariable "serverWeather";
};

if(isServer or isJIP == 0) then {
// Set up initial starting weather on server and non-JIP clients.
skipTime -24;
86400 setOvercast forecastOvercast;
86400 setFog forecastFog;
simulSetHumidity forecastHumidity;
skipTime 24;
};

if(isServer) then {
// Begin server loop to create a new weather forecast every 15 minutes.
while {true} do {

// Create random numbers for 15 minute forecasts and keep values within proper limits (Overcast/Humidity: 0 - 1, Fog: 0 - 0.4)
_randOvercast = (round((random(0.5)-0.25)*100))/100;
_randHumidity = (round((random(0.5)-0.25)*100))/100;
_randFog = (round((random(0.2)-0.1)*100))/100;

// Create forecast random overcast level and keep 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 forecast random humidity level and keep between 0 and 1
forecastHumidity = forecastHumidity + _randHumidity;
if (forecastHumidity > 1) then {forecastHumidity = forecastHumidity - (2*_randHumidity)};
if (forecastHumidity < 0) then {forecastHumidity = forecastHumidity + (abs(2*_randHumidity))};

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

// Set up variable to show updated server weather
serverWeather = serverWeather + 1;

// Broadcast server weather forecast information to clients.
publicVariable "forecastOvercast";
publicVariable "forecastHumidity";
publicVariable "forecastFog";
publicVariable "serverWeather";

// Debug Hint - Show Current and Forecast Overcast, Humidity & Fog Levels on the Server.
//hint format ["Updating Server Forecast - CO: %1 | CH: %2 | CF: %3 | FO: %4 | FH: %5 | FF: %6",Overcast,Humidity,Fog,forecastOvercast,forecastHumidity,forecastFog];

// Configure Server weather forecast
900 setOvercast forecastOvercast;
900 setFog forecastFog;
sleep 900;
simulSetHumidity forecastHumidity;
};
};

// Clients wait until server broadcasts first random weather information.
waitUntil {serverWeather >= 1};

// Set up client weather counter to compare to serverWeather.
_clientWeather = 0;

// Run a loop on the client to look for updated weather from the server every 15 seconds.
while {true} do {
	sleep 15;
	hint "Client Weather Loop - Checking";
	if (clientWeather < serverWeather) then {
	900 setOvercast forecastOvercast;
	900 setFog forecastFog;
	sleep 900;
	simulSetHumidity forecastHumidity;
	clientWeather = serverWeather;
	// Debug Hint - Show Current and Forecast Overcast, Humidity & Fog Levels on the Client
	//hint format ["Updated Client Forecast - CO: %1 | CH: %2 | CF: %3 | FO: %4 | FH: %5 | FF: %6",Overcast,Humidity,Fog,forecastOvercast,forecastHumidity,forecastFog];
	};
};
};

Edited by Meatball

Share this post


Link to post
Share on other sites

Slight update. Did a bunch of testing tonight, and my script above seems to work fine if I host a game directly through my game client and allow people to connect to me that way. But when I set up the mission to run on a dedicated server it doesn't work.

Stepping through the code, I know the first "if(isServer)" block that grabs the info from the parameters and broadcasts all that as publicVariable appears to run fine and on the client I can see the broadcasted 'serverWeather' variable set to 0. I also know that the skipTime block that sets up initial weather is working because it changes on both the server/clients. The next if(isServer) block with the while {true} loop is giving me problems. This block creates the random forecast updates on the server, increments the 'serverWeather' variable and broadcasts all that info out to the clients, but that doesn't seem to be working and I never see the serverWeather variable go above 0 on the client. I even tried setting that loop to if(isServer or isDedicated) with no luck.

So close, yet so far :)

Share this post


Link to post
Share on other sites
someone had suggested to use magical function: BIS_fnc_MP.

Can you expand a bit on that as I'm not sure I follow. The one suggestion I did see about that function was for skipping time, and that's actually working fine on all machines with the script as is. When I checked more into that function, but it didn't look like it would help me as that appears to just be able to push functions out from the server to be executed on clients. The server and all clients should already be launching their own copy of the randomWeather script through the init.sqf call and the code in the script doesn't run any functions I think need to be pushed.

Edited by Meatball

Share this post


Link to post
Share on other sites

make your function can be publishable on the network, then called the update from the server side.

-or-

separate your function in to 2:

- one for server calculation

-one for client fx

Share this post


Link to post
Share on other sites

I'll give it a whirl. Still learning scripting, so I've never messed around with functions before.

Share this post


Link to post
Share on other sites

I've worked through a few kinks and wanted to post up my most recent version I'm running with. There are a few caveats/highlights:

1) This version will not work with Dedicated servers so I've created a section that dumps out of the script if a dedicated server is being used. Even looking at functions, I couldn't see any way to make it work. I think it's actually an overall A3 issue.

2) simulSetHumidity for clouds works, but it's implementation kinda sucks. As mentioned before, it's instantaneous, so the only way I've found to minimize jarring changes to cloud levels is to update it in smaller increments more frequently.

3) Ran a test for 3+ hours with this on a hosted server and a client and found it stayed in synch the whole time, generally within .01/.02 difference between server/client.

4) Script right now will send out updates to weather from the server to clients every 10 minutes.

/*  
randomWeather.sqf v 0.5
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.  

// paramsArray[5]
      class initialWeather {
         title = "Initial Weather";
         values[] = {1,2,3,4,5,6,7};
         texts[] = {"Clear","Overcast","Light Rain","Heavy Rain","Light Fog","Heavy Fog","Random"};
         default = 1;
      }; 

4) Script does not have a 'rain' variable.  Rain will automatically form when humidity/overcast conditions warrant.

5) Note: Due to issues with current A3 weather code, this will NOT work if the server is a dedicated server.

*/

// Dedicated Server Check
if ((isServer) and (isDedicated)) then { // If a Server and Dedicated, set svrDedicated variable to 1 and broadcast it.
svrDedicated = 1;
publicVariable "svrDedicated";
};

if ((isServer) and (!isDedicated)) then { // If a Server and not Dedicated, set svrDedicated variable to 0 and broadcast it.
svrDedicated = 0;
publicVariable "svrDedicated";
};

// Wait for Dedicated server check to be completed and broadcast from server
waitUntil {!isNil "svrDedicated"};

// Exit weather script on server and clients if mission is being hosted on a Dedicated Server
if (svrDedicated == 1)exitWith{};

// On server, set forecast Weather from Parameter options chosen by players.
if(isServer) then {
// Make sure the # in the select below matches what # in the order of parameters your initialWeather class is in the description.ext
initialWeather = (paramsArray select 5);  
switch (initialWeather) do{
case 1: {forecastOvercast = 0;forecastHumidity = 0;forecastFog = 0;forecastWindE = 1;forecastWindN = 1;};							// Clear
case 2: {forecastOvercast = .40;forecastHumidity = .40;forecastFog = 0;forecastWindE = 2;forecastWindN = 2;};						// Overcast
case 3: {forecastOvercast = .70;forecastHumidity = .70;forecastFog = .05;forecastWindE = 3;forecastWindN = 3;};						// Light Rain
case 4: {forecastOvercast = 1;forecastHumidity = 1;forecastFog = .05;forecastWindE = 4;forecastWindN = 4;};							// Heavy Rain
case 5: {forecastOvercast = .75;forecastHumidity = .10;forecastFog = .30;forecastWindE = 1;forecastWindN = 1;};						// Light Fog
case 6: {forecastOvercast = .85;forecastHumidity = .20;forecastFog = .50;forecastWindE = 0;forecastWindN = 0;};						// Heavy Fog
case 7: {forecastOvercast = random(1);forecastHumidity = 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 from parameters.	
publicVariable "forecastOvercast";
publicVariable "forecastHumidity";
publicVariable "forecastFog";
publicVariable "forecastWindE";
publicVariable "forecastWindN";
publicVariable "serverWeather";
};

// Set up initial weather for server and all clients using values from parameters.
waitUntil {!isnil "serverWeather"};
skipTime -24;
86400 setOvercast forecastOvercast;
86400 setFog forecastFog;
simulSetHumidity forecastHumidity;
setWind [forecastWindE,forecastWindN,true];
skipTime 24;

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

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

// Configure weather settings on server to match next 10 minute weather forecast.
600 setOvercast forecastOvercast;
600 setFog forecastFog;
sleep 600;
simulSetHumidity forecastHumidity;
setWind [forecastWindE,forecastWindN,true];

// Create random numbers for next forecast.
_randOvercast = (round((random(0.3)-0.15)*100))/100;
_randHumidity = (round((random(0.3)-0.15)*100))/100;
_randFog = (round((random(0.1)-0.05)*100))/100;
_randWindE = (round((random(1)-.05)*100))/100;
_randWindN = (round((random(1)-.05)*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 humidity level and keep it between 0 and 1
forecastHumidity = forecastHumidity + _randHumidity;
if (forecastHumidity > 1) then {forecastHumidity = forecastHumidity - (2*_randHumidity)};
if (forecastHumidity < 0) then {forecastHumidity = forecastHumidity + (abs(2*_randHumidity))};

// 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 | CF: %4 |CW: %5 | FO: %6 | FH: %7 | FF: %8 | FW: %9,%10",serverWeather,Overcast,Humidity,Fog,wind,forecastOvercast,forecastHumidity,forecastFog,forecastWindE,forecastWindN];

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

sleep 3;
};
};

if (!isServer) then {
// Non Server Weather 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 12 seconds.
while {clientWeather >= 0} do {
	sleep 12;
// If client Weather is older than the server weather, set client 10 minute weather forecast to match server.
	if (clientWeather < serverWeather) then {

	// 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 | CF: %4 |CW: %5 | FO: %6 | FH: %7 | FF: %8 | FW: %9,%10",clientWeather,Overcast,Humidity,Fog,wind,forecastOvercast,forecastHumidity,forecastFog,forecastWindE,forecastWindN];

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

	// Set 10 minute forecast for the client.
	600 setOvercast forecastOvercast;
	600 setFog forecastFog;
	sleep 600;
	simulSetHumidity forecastHumidity;
	setWind [forecastWindE,forecastWindN,true];
	};
};
};

Edited by Meatball

Share this post


Link to post
Share on other sites

Appears the most recent patch removed the 'simulSetHumidity' command, so that's no longer available to set cloud cover and there doesn't appear to be any replacement to add/remove clouds. This of course breaks the script I'm using above. Using just setOvercast/setRain will still cause rain once overcast gets high enough, but it still takes almost an hour for overcast to go from 0 to 1 (goes up ~ .0167/minute) and overcast does not add/remove any clouds, just the 'darkness' of the sky.

http://community.bistudio.com/wiki/simulSetHumidity

Be nice if someone from the BIS side would give us some idea what in the world is going on with weather. I don't see any reference to anything in any patch notes.

---------- Post added at 14:42 ---------- Previous post was at 14:24 ----------

Quick additional note. You can still get clouds in mission, I just don't know what command(s) they are using. If you start up a new mission in the editor, go into Intel and set overcast to 100 at the start the mission will start with the sky loaded with clouds. I just can't find any scripting commands to do the same.

Edited by Meatball

Share this post


Link to post
Share on other sites

Some more strangeness...Start up a test a mission with the following in your init.sqf.

skipTime -24;
86400 setOvercast 1;
86400 setFog 0;
86400 setRain 1;
skipTime 24;

Start up the mission. Not a cloud in the sky (yet it still may start raining) but the sun is definitely muted. Hit escape, click on "Save & Exit" and go to the unit selection screen. Click another unit to come in, launch (it loads from the saved point and only a second or two of actual 'time' has elapsed according to the in game watch) and poof, the sky is full of clouds and it's raining.

Edited by Meatball

Share this post


Link to post
Share on other sites

Updated version of the script. With the most recent patch, this does now appear to work for both hosted MP missions and dedicated server missions with one caveat. Cloud cover does not work correctly at mission start since there's no longer a command to set cloud cover with simulSetHumidity removed. Clouds will begin to show up over time and the script appears to work correctly for all other intents and purposes. Feel free to use it and let me know if you find any issues.

/*  
randomWeather.sqf v 0.7
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.  

// paramsArray[5]
      class initialWeather {
         title = "Initial Weather";
         values[] = {1,2,3,4,5,6,7};
         texts[] = {"Clear","Overcast","Light Rain","Heavy Rain","Light Fog","Heavy Fog","Random"};
         default = 1;
      }; 
4) Note: Due to issues with current A3 weather code, overall weather should work correctly, but clouds if overcast will not appear correctly at mission start.

*/

// On server, set forecast Weather from Parameter options chosen by players.
if(isServer) then {
// Make sure the # in the select below matches what # in the order of parameters your initialWeather class is in the description.ext
initialWeather = (paramsArray select 5);  
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 from parameters.	
publicVariable "forecastOvercast";
publicVariable "forecastRain";
publicVariable "forecastFog";
publicVariable "forecastWindE";
publicVariable "forecastWindN";
publicVariable "serverWeather";
};

// Set up initial weather for server and all clients using values from parameters.
waitUntil {!isnil "serverWeather"};
skiptime -24;
86400 setOvercast forecastOvercast;
86400 setFog forecastFog;
86400 setRain forecastRain;
//	simulSetHumidity forecastRain;
skipTime 24;
setWind [forecastWindE,forecastWindN,true];

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

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

// Configure weather settings on server to match next 10 minute weather forecast.
600 setOvercast forecastOvercast;
600 setFog forecastFog;
600 setRain forecastRain;
sleep 600;
setWind [forecastWindE,forecastWindN,true];

// Create random numbers for next forecast.
_randOvercast = (round((random(0.3)-0.15)*100))/100;
_randRain = (round((random(0.3)-0.15)*100))/100;
_randFog = (round((random(0.1)-0.05)*100))/100;
_randWindE = (round((random(1)-.05)*100))/100;
_randWindN = (round((random(1)-.05)*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",serverWeather,Overcast,Humidity,Rain,Fog,wind,forecastOvercast,forecastHumidity,forecastRain,forecastFog,forecastWindE,forecastWindN];

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

if (!isServer) then {
// Non Server Weather 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 10 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",clientWeather,Overcast,Humidity,Rain,Fog,wind,forecastOvercast,forecastHumidity,forecastRain,forecastFog,forecastWindE,forecastWindN];

	// Set 10 minute forecast for the client.
	600 setOvercast forecastOvercast;
	600 setFog forecastFog;
	600 setRain forecastRain;
	sleep 600;
	setWind [forecastWindE,forecastWindN,true];
	};
};
};

Share this post


Link to post
Share on other sites

Thanks for this!! Weather stuff was a bit weird in the beta most script packs that included it (ie: F3 Framework) had it disabled.

Do you know if it's possible to have thunder and lightning with no or very little overcast?

Share this post


Link to post
Share on other sites

Yeah, that's the issue with the loss of simulSetHumidity. Clouds have no bearing on rain and/or thunder & lightning right now. Overcast on the other hand does. So, setting overcast to 1, you won't see any clouds, but you can have a downpour of rain and thunder/lightning going on. Not sure if you can have thunder/lighting with low overcast though.

Hopefully they link the amount of clouds in the sky back to Overcast like it was in A2...

Share this post


Link to post
Share on other sites

Hi, how can I use this for a single player mission? I added a game logic with "nul = execVM "RandomWeather.sqf";", but well the variables like "forecastovercast" are unknown...

Share this post


Link to post
Share on other sites

There's probably a way to have a single script that can handle everything, but just stripping out the client side stuff and public variable broadcasts _should_ work for SP. I haven't tested this, but this might work.

/*  
spRandomWeather.sqf v 0.1
By Meatball

Script Requirements:

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

2) Create a call in init.sqf
execVM "spRandomWeather.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.  

// paramsArray[5]
      class initialWeather {
         title = "Initial Weather";
         values[] = {1,2,3,4,5,6,7};
         texts[] = {"Clear","Overcast","Light Rain","Heavy Rain","Light Fog","Heavy Fog","Random"};
         default = 1;
      }; 
4) Note: Due to issues with current A3 weather code, overall weather should work correctly, but clouds if overcast will not appear correctly at mission start.

*/

// Make sure the # in the select below matches what # in the order of parameters your initialWeather class is in the description.ext
initialWeather = (paramsArray select 5);  
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;

// Set up initial weather for server and all clients using values from parameters.
waitUntil {!isnil "serverWeather"};
skiptime -24;
86400 setOvercast forecastOvercast;
86400 setFog forecastFog;
86400 setRain forecastRain;
skipTime 24;
setWind [forecastWindE,forecastWindN,true];

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

// Begin loop to create a new weather forecast every 10 minutes.	
while {serverWeather >= 0} do {  // This will always be true and it will run as long as server runs.

// Configure weather settings on server to match next 10 minute weather forecast.
600 setOvercast forecastOvercast;
600 setFog forecastFog;
600 setRain forecastRain;
sleep 600;
setWind [forecastWindE,forecastWindN,true];

// Create random numbers for next forecast.
_randOvercast = (round((random(0.3)-0.15)*100))/100;
_randRain = (round((random(0.3)-0.15)*100))/100;
_randFog = (round((random(0.1)-0.05)*100))/100;
_randWindE = (round((random(1)-.05)*100))/100;
_randWindN = (round((random(1)-.05)*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 Weather Forecast # %1 CO: %2 | CH: %3 | CR: %4 | CF: %5 |CW: %6 | FO: %7 | FH: %8 | FR: %9 | FF: %10 | FW: %11,%12",serverWeather,Overcast,Humidity,Rain,Fog,wind,forecastOvercast,forecastHumidity,forecastRain,forecastFog,forecastWindE,forecastWindN];

};

Share this post


Link to post
Share on other sites

Thank you! I changed line 26 to "initialWeather = ceil(random 7);" which is fine for me (and I had no idea how to pass the argument over), this way I could simply call it via execVM from a game logic without any arguments; it seems to work.

EDIT: Hmm it seems like the weather does not change. I changed the sleep value to 10 seconds to test this. Audibly there was rain, but no rain to see.

EDIT2: OK read your code again and setOvercast etc. syntax and realized that transitions are slow. Problem solved.

Edited by tortuosit

Share this post


Link to post
Share on other sites

Yeah, that's an easy way to pick random starting weather if you don't want to give the player the ability to edit it. As for all those initial weather values and 10 minute adjustment numbers, they are my best guesses about what looks good to me. Certainly change them to whatever you like as well. Just remember that all the weather variables are between 0 and 1 with the exception of wind values. 0 is 0% for that weather variable, .5 being 50%, 1 being 100%.

Wind is actually the value of wind in meters/second in each directions. So a value of 10 is a wind of 10m/sec.

Edited by Meatball

Share this post


Link to post
Share on other sites

This Weather system looks fantastic. Haven't had a chance to play with it yet. (maybe tonight)

Can you confirm the Wind though? I'm working on a Sniper mod, but can not find the Max Wind

if at 100%. I was guessing it was about 20mph, so that's what my math was based on... :raisebrow:

Share this post


Link to post
Share on other sites

Not sure what maxWind in engine is to be honest, but it's not really set on a percentage basis like the other weather variables.

http://community.bistudio.com/wiki/setWind

The numbers are specific meters / second of the wind, so for example, you could set it to 5 m/s, 10, 30, 100, whatever. Just don't know if there's an upper limit the engine takes.

Just a reference point for understanding.

1 meters/second = 3.6 km/hour = 2.2 miles/hour

Share this post


Link to post
Share on other sites
Can you confirm the Wind though? I'm working on a Sniper mod, but can not find the Max Wind if at 100%.

Hold on. Is the ballistic curve already dependent on the wind, or are you working on a mod which will do this (until we see ACE for A3 :D)?

Share this post


Link to post
Share on other sites

@tortuosit

I'm using Zooloo75's for the ballistics mod. I'm working on a kestrel device you can pull

up to check weather/wind so you can adjust and make that long range shot IF you are

using any ballistics-type mod if you're into the more extreme sniper simulation style game.

Share this post


Link to post
Share on other sites

Alright, so I _think_ I figured out the problem with cloud level not being set correctly at mission start. Remember that setOvercast does not control cloud cover directly and the simulSetHumidity used to do that. setOvercast simply adjusts the amount of sunlight that is reaching the ground from the sky. Use setOvercast to 0 and it'll be bright and sunny on the ground, setOvercast 1 and it'll appear dark and dingy on the ground and the sky will appear muted, all regardless of the amount of clouds in the sky.

What appears to be happening though is that the the "Overcast" settings you can configure in the editor in your mission Intel is still creating a cloud level that should match the overcast setting (using simulSetHumidity that was pulled from scripting use perhaps?) you have set in Intel. So, if you try to configure the overcast level using scripting in your init.sqf or through a script like mine, it does tell the engine to change the overcast level, but the cloud level that was set by the Intel overcast setting does not automatically update and you'll have a cloud level at mission start matching the Intel overcast settings, and not the newly updated overcast you set using setOvercast.

I figured it out with a simple test. I created a dummy mission and dumped a player unit in it. I then set the Intel overcast level to 0 for Start, and then created an init.sqf that only contained:

skipTime -24;86400 setOvercast 1;skipTime 24;

When I launched I had a nice dark and gloomy environment, but there wasn't a cloud in the sky. I then did the opposite, setting the mission intel Overcast to 100, and then changed the init.sqf setOvercast value to 0. Started up and everything looked bright and sunny on the ground, even to the point that I saw shadows, yet up in the sky it was loaded with clouds and started raining immediately.

So, no matter what you do scriptwise, the cloud level at the start of your mission will always be at a level that 'matches' the overcast level set in your mission Intel in the editor. Until they fix it, the only thing I can think of is to set the Intel overcast to 40-50 so if your script sets a mission to have any type of cloud level, the players will at least see some clouds at mission start. The downside is if the players pick clear weather, the sky will still be half filled with clouds...

Edited by Meatball

Share this post


Link to post
Share on other sites

I was thinking about the concept. At script start, rain and overcast go well with each other, but then they start cycling between 0 and 1 independently. In the worst case we can see rain with clear sky after a while. I was thinking that overcast and rain (probably wind as well) should be dependent on each other.

With a very simple change "forecastRain = forecastOvercast + _randRain;" I made rain dependent from overcast, rain values will be somewhere close to overcast values, with the variation of _randRain:

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

Still have to look at the wind, because it works a bit different. Maths is more difficult there. Also I think the setFog array could be very interesting... https://community.bistudio.com/wiki/setFog_array

Edited by tortuosit

Share this post


Link to post
Share on other sites
I was thinking about the concept. At script start, rain and overcast go well with each other, but then they start cycling between 0 and 1 independently. In the worst case we can see rain with clear sky after a while. I was thinking that overcast and rain (probably wind as well) should be dependent on each other.

They already are for the most part so you really don't need to worry about that yourself. The game engine will not let it rain unless Overcast is above a certain level. It used to be .7 in Arma 2, so I assume it's the same as the Wiki has not changed, but I've not tested it to find out if it'll rain at lower overcast values. Additionally, setRain really just forces it to rain. I'm pretty sure the weather engine will automatically create rain when the overcast conditions are correct randomly. The reason I use it is to force the issue and make sure everyone in a MP environment sees rain at the same time.

Share this post


Link to post
Share on other sites

I'm not an expert in probability, but doesn't that behavior of moving to the other direction when the border is exceeded (<0 or >1) lead to a probably mediocre behaviour? Say, a variable is 0.9, now it adds 0.15 and because this is >1 it will instead subtract 0.15 from 0.9 -> 0.75. Hmm I'm assuming the probabilities between 0 and 1 are like a gaussian curve... But maybe that is a good idea. Hmm, I'm just thinking loud :D

Share this post


Link to post
Share on other sites

If things haven't changed and i haven't jumped into conclusions at the time i did some tests, 0.5 overcast is suficient to let it rain. (then i was looking to trigger the rainbow not the rain)

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  

×