/rain

EQ2Emulator Development forum.

Moderator: Team Members

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: /rain

Post by John Adams » Fri Dec 07, 2012 4:33 pm

I needed a break from home improvements, so I thought I'd tackle adding dynamic weather to the zones. I'm posting this as a review, because I am 99% certain I am forgetting something - or designing this badly. I'm not done yet, but this is the direction I am going.

First, I made 4 new rules, this first one being the ZoneServer Timer for how often to check for weather changes (every minute)

Code: Select all

RULE_INIT(R_Zone, WeatherTimer, "60000");
These rules are the min/max weather severity per zone, along with how often the weather changes and by how much per change interval

Code: Select all

RULE_INIT(R_Zone, MinWeatherSeverity, "0.5");
RULE_INIT(R_Zone, MaxWeatherSeverity, "1.0");
RULE_INIT(R_Zone, WeatherChangeFrequency, "900000");
RULE_INIT(R_Zone, WeatherChangeInterval, "0.1");
RULE_INIT(R_Zone, WeatherChangeChance, "0.5");
For example, it's a sunny day in Commonlands. Weather is checked every minute. At 3:15pm, a WeatherChangeChance is rolled, and if passed, a weather change is triggered. Since MinWeatherSeverity = 0.5, that's where we start out... the clouds roll in. Every 15 mins after that, the weather increases in severity by 0.1 until it reaches MaxWeatherSeverity.

The weather stays at this (max) setting until the WeatherChangeChance tells it to start going in the reverse direction.

In ZoneServer::Process() I added:

Code: Select all

		if(weatherTimer.Check())
			ProcessWeather();
The new function will do all the work:

Code: Select all

void ZoneServer::ProcessWeather()
{
	LogWrite(ZONE__DEBUG, 0, "Zone", "Checking for weather changes in zone '%s' (id: %u)", zone_name, zoneID);

	int32 weather_frequency = rule_manager.GetGlobalRule(R_Zone, WeatherChangeFrequency)->GetInt32();
	LogWrite(ZONE__DEBUG, 0, "Zone", "Weather changes can only occur every %u seconds...", weather_frequency/1000);

	// check frequency first, if it's time to change, then do the Chance roll
	if( GetLastWeatherChange() <= (Timer::GetUnixTimeStamp() - weather_frequency) )
	{
		float weather_chance = rule_manager.GetGlobalRule(R_Zone, WeatherChangeChance)->GetFloat();
		int8 weather_random = MakeRandomInt(0, weather_chance*100);
		LogWrite(ZONE__DEBUG, 0, "Zone", "WeatherChangeChange: %2f, Random Roll: %i", weather_chance, weather_random);
		if( weather_random <= weather_chance )
		{
			LogWrite(ZONE__DEBUG, 0, "Zone", "Changing weather in zone '%s' (id: %u)", zone_name, zoneID);
			float minWeatherSeverity = rule_manager.GetGlobalRule(R_Zone, MinWeatherSeverity)->GetFloat();
			float maxWeatherSeverity = rule_manager.GetGlobalRule(R_Zone, MaxWeatherSeverity)->GetFloat();

			// this will be replaced by incremental weather changes eventually
			float weather_severity = MakeRandomFloat(minWeatherSeverity, maxWeatherSeverity);
			LogWrite(ZONE__DEBUG, 0, "Zone", "Random weather changed to %2f in zone '%s' (id: %u)", weather_severity, zone_name, zoneID);

			this->SetRain(weather_severity);
			SetLastWeatherChanged(Timer::GetUnixTimeStamp());
		}
		else
			LogWrite(ZONE__DEBUG, 0, "Zone", "Random weather change delayed in zone '%s' (id: %u)", zone_name, zoneID);
	}
	else
		LogWrite(ZONE__DEBUG, 0, "Zone", "Not yet time to change weather in zone '%s' (id: %u)", zone_name, zoneID);
}
(right now this is a very simple example, as I have yet to test any of this)

So, my question is --
Since each zone is instantiated separately, does that mean there is 1 weatherTimer.Check() per active zone, thus all the functions in ProcessWeather() will be restricted to that 1 zone? or do I have to start messing with Mutex and lists and crap? If so, this will quickly become above my head.

Wanted to get this out for opinions though. Jab, this is as simple as I could come up with :)

Jabantiz
Lead Developer
Posts: 2912
Joined: Wed Jul 25, 2007 2:52 pm
Location: California

Re: /rain

Post by Jabantiz » Fri Dec 07, 2012 7:11 pm

Yes this will only run for the zone that starts it, so I don't think any mutex will be needed for this as it should only run on the main zone thread and nothing else.

The code looks good the only thing I am not sure of is this

Code: Select all

int8 weather_random = MakeRandomInt(0, weather_chance*100);
if( weather_random <= weather_chance )
This would get a random int from 0 to 50 (.5 * 100) and then compare that int to a float 0.5, so only when weather_random = 0 will the code in the if execute. You could use MakeRandomFloat if you want that low chance. If .5 is suppose to be 50% you can just do MakeRandomInt(0, 100) and compare it to weather_chance * 100

I hope I didn't misunderstand anything, I did have to skim over it really quick and speed type this post but it looks good and should work.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: /rain

Post by John Adams » Sat Dec 08, 2012 9:26 am

Thanks Jab, you found my first bug :) I couldn't figure out why I wasn't ever getting weather to happen, and it's because I had bad math lol. I have the function almost completely done, and much to my surprise everything is working! I'll do more testing today between painting tasks, and commit the code for review.

What I am working on this morning is trying to get the weather to slowly creep up in intensity slowly til it reaches Max, then decrease slowly until Min. For that effect, I am bypassing Chance while weather is in effect.


Edit: Jab, I was going to do the random this way - let me know if you think this is not right?

Code: Select all

		int8 weather_chance = rule_manager.GetGlobalRule(R_Zone, WeatherChangeChance)->GetInt8();
		int8 weather_random = MakeRandomInt(0, 100);
		if( weather_random <= weather_chance )
So if weather_chance is 5, I do a random 0 - 100 and if it's between 1 - 5, I roll a weather change. I was thinking that leaving a 0 (zero) check would also prevent weather from changing. I don't want the RNG to be pooping weather changes too often.

Jabantiz
Lead Developer
Posts: 2912
Joined: Wed Jul 25, 2007 2:52 pm
Location: California

Re: /rain

Post by Jabantiz » Sat Dec 08, 2012 11:03 am

John Adams wrote:So if weather_chance is 5, I do a random 0 - 100 and if it's between 1 - 5, I roll a weather change. I was thinking that leaving a 0 (zero) check would also prevent weather from changing. I don't want the RNG to be pooping weather changes too often.
From the code posted 0 to 5 will cause the code in the if to execute, if you want 0 to not do anything add a "&& weather_random != 0" to the if.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: /rain

Post by John Adams » Sat Dec 08, 2012 11:49 am

Yeah, might as well ignore my first code post. It's completely different today. You know how that goes ;)

Jabantiz
Lead Developer
Posts: 2912
Joined: Wed Jul 25, 2007 2:52 pm
Location: California

Re: /rain

Post by Jabantiz » Sat Dec 15, 2012 10:29 pm

You did a good job with this John.

I played around with this today and it is nice to see clouds and rain for a change.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: /rain

Post by John Adams » Mon Dec 17, 2012 7:40 am

Thank you, it was a lot of fun adding this feature. Thank YOU for finding rain in the first place :)

Btw, the defaults I selected are horrible wrong (check every 15 mins for a 20% chance of change). My server ran 2 days and never got above 0.62 :) I will make adjustments after I watch the world another week or so, trying new settings. Maybe check every 5 mins with a 30% chance...

Btw, soon as I get a second to spare, I'll WIKI EQ2Emu Weather. Just been slammed the past few days.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: /rain

Post by John Adams » Tue Dec 18, 2012 12:23 pm

I think I have a problem with how weather is being processed per-zone. Take a look at these log entries -
11:32:18 D Zone: antonica: Chance to change weather: 30%, rolled: 94% - Change weather: False
11:32:39 D Weather: Commonlands: Processing weather changes
11:32:39 D Zone: Commonlands: Checking for weather changes
11:32:39 D Zone: Commonlands: Chance to change weather: 30%, rolled: 94% - Change weather: False
11:37:18 D Weather: antonica: Processing weather changes
11:37:18 D Zone: antonica: Checking for weather changes
11:37:18 D Zone: antonica: Chance to change weather: 30%, rolled: 5% - Change weather: True
11:37:39 D Weather: Commonlands: Processing weather changes
11:37:39 D Zone: Commonlands: Checking for weather changes
11:37:39 D Zone: Commonlands: Chance to change weather: 30%, rolled: 5% - Change weather: True
11:42:18 D Weather: antonica: Processing weather changes
11:42:18 D Zone: antonica: Checking for weather changes
11:42:18 D Zone: antonica: Chance to change weather: 30%, rolled: 90% - Change weather: False
11:42:40 D Weather: Commonlands: Processing weather changes
11:42:40 D Zone: Commonlands: Checking for weather changes
11:42:40 D Zone: Commonlands: Chance to change weather: 30%, rolled: 90% - Change weather: False
11:47:19 D Weather: antonica: Processing weather changes
11:47:19 D Zone: antonica: Checking for weather changes
11:47:19 D Zone: antonica: Chance to change weather: 30%, rolled: 30% - Change weather: True
11:47:40 D Weather: Commonlands: Processing weather changes
11:47:40 D Zone: Commonlands: Checking for weather changes
11:47:40 D Zone: Commonlands: Chance to change weather: 30%, rolled: 30% - Change weather: True
These are two separate running zones, each with their own timers and variables (or so I thought) yet the Random being rolled seems to match for both zones. How is this possible? No way this is luck. So basically when one zone rolls to change weather, they all do together.

I think I did something wrong. Jab/Scat/LE (if you're lurking :)) any advice?

All the variables are defined in the ZoneServer class as Private, with setters/getters in Public. The values are set by Rules in ZoneServer::InitWeather(), and processed in ZoneServer::ProcessWeather().

Enable ZONE__DEBUG logger at level 3 to see all logging.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: /rain

Post by John Adams » Tue Dec 18, 2012 1:51 pm

Doesn't each zone instantiate a new instance when we do ZoneServer* zone = new ZoneServer(zone_name)?

So each weatherTimer.Start(time) is it's own timer?

And even if the timer's fire at the exact same time (multiple zones startup at once), won't the weather_random rolls be done on a separate thread?

Because when I breakpoint at the int8 weather_random = MakeRandomInt(1,100) I definitely hit it twice. Once for each zone.

Terribly confused now.

Jabantiz
Lead Developer
Posts: 2912
Joined: Wed Jul 25, 2007 2:52 pm
Location: California

Re: /rain

Post by Jabantiz » Wed Apr 22, 2015 4:02 pm

/necro

Thanks to smash discovering what the rain2 element in the char sheet actually is we now have /wind. Basically it take a float, effects the entire zone and changes the direction of the clouds and the rain drops, though the rain drops are barely noticeable. I believe anything after the decimal might be wind strength but I am not sure, may have just been seeing things at that point.

Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests