Skip to content

Weather and Climate System

Tom-Strooper edited this page Oct 16, 2023 · 14 revisions

ClimateController

The ClimateController is a class that contains all of the climate information for the GameArea. It manages so called WeatherEvents, which occur periodically, or as a result of completing certain in-game quests.

ClimateController instances will be properties of GameAreas rather than the ServiceLocator, as the climate should only affect entities of the given GameArea.

Handling WeatherEvents

The ClimateController keeps track of a List of WeatherEvents, representing WeatherEvents that are either currently happening, or scheduled to happen within a finite amount of time.

Of the WeatherEvents that are active at any given moment, only one will occur at a given time (this WeatherEvent is referenced by the private member variable currentWeatherEvent). The currentWeatherEvent will modify the game environment in some way, as determined by the type and severity of the event (see section on the WeatherEvent class below).

Random Weather Events

Random WeatherEvents by default have a chance to occur once every in-game day. Every in-game day the addDailyEvent() method is called, determining whether or not an event should be added. The stats and the type of the event are also randomly generated. There is a 93% chance every in-game day that an event will be created. Given that an event is generated, it has a 40% chance of being a RainStormEvent, a 30% chance of being a BlizzardEvent, a 20% chance of being a SolarSurgeEvent, and a 10% chance of being an AcidShowerEvent. The stats of the event will also be randomly generated, as detailed below:

  • numHoursUntil will be a random integer in the range [1, 20]
  • duration will be a random integer in the range [1, 4]
  • priority will be a random integer in the range [0, 3]
  • severity will be a random float in the range [0.0f, 1.2f)

Adding Weather Events

A WeatherEvent can be added by calling the ClimateController’s addWeatherEvent() method passing in an instance of WeatherEvent.

Updating Weather Events

All tracked WeatherEvents will be updated every hour using their updateTime() method. Then, for each active WeatherEvents, the ClimateController will determine which has the highest priority, and assign this WeatherEvent to be the currentWeatherEvent (in the case where 2 events have the same priority, the event added to the ClimateController first will be made the currentWeatherEvent). Note that all tracked WeatherEvents will be updated every hour, regardless of which WeatherEvents are active or occurring.

Climate’s Effects

When a WeatherEvent is the currentWeatherEvent, its startEffect() method will be triggered. At the end of the hour (i.e., when updateWeatherEvent() is called again), its stopEffect() method will be triggered (if the currentWeatherEvent has not yet expired, and remains the currentWeatherEvent after all WeatherEvents are updated, then startEffect() will be triggered again).

Game Mechanic Effects

The ClimateController has an EventHandler, which can be accessed through the getEvents() method. This EventHandler will be used by certain WeatherEvents to trigger miscellaneous in-game effects (see the section on WeatherEvents for more information). Hence, other components and entities may provide event listeners to this EventHandler in order to trigger miscellaneous changes to their state based on certain WeatherEvents.

For instance, AcidShowerEvents will periodically damage plants in the world. This is achieved by having PlantComponent add a listener to the "damagePlants" event on the ClimateController’s EventHandler, which will be cause damage to itself.

Lighting Effects

In addition to affecting the game mechanics, certain WeatherEvents may trigger changes in global lighting. A global brightness multiplier can be set from each event's respective startEffect() and stopEffect() methods, but the ClimateController also provides a way for WeatherEvents to add periodic dynamic lighting changes (e.g., to simulate lightning strikes or to simulate an aurora during a solar surge).

This is achieved via triggering an event added to the ClimateController's EventHandler by default, called "lightingEffect". The event listener for this event is the method setLightingEffect(), which takes in a float duration and a Function<Float, Color> colourGradient. The duration represents the duration of the lighting effect in seconds. The colourGradient is a function that accepts a float in the range [0.0f, 1.0f], and returns a Color representing the colour offset at that time.

While a lighting effect is active (i.e., the time elapsed since setLightingEffect() was called is less than duration seconds), the ClimateController will update the global ambient lighting by the specified colourGradient. The lighting effect is updated every frame the game is not paused, along with the ClimateController's EventHandler (using the EventHandler's update() method) in the updateClimate() method.

WeatherEvent

A WeatherEvent is an abstract class representing any form of weather event. Implementations of this class include AcidShowerEvent, BlizzardEvent, RainStormEvent, and SolarSurgeEvent.

WeatherEvents have the following properties, which are initialised when a WeatherEvent is created:

  • numHoursUntil - The number of hours until the WeatherEvent becomes active
  • duration - The duration of the WeatherEvent once it becomes active. Note that a WeatherEvent’s duration will decrease while it is active, even if it is not occurring
  • priority - An integer representing the importance of the WeatherEvent. For instance, if there are 3 active WeatherEvents, the WeatherEvent with the highest priority integer value will occur. In the instance where at least 2 WeatherEvents are active simultaneously, the WeatherEvent added to the ClimateController first will occur
  • severity - A float representing how 'severe' the WeatherEvent is (this will be used in the specific implementations for a variety of in-game effects). This float should be in the range [0.0f, 1.5f].

WeatherEvents also have the following publicly accessible methods which can be invoked by the ClimateController (not counting getters for each of the above properties):

  • updateTime() - Will decrement the numHoursUntil property if the WeatherEvent is inactive, or decrement the duration property
  • isActive() - Returns a boolean value representing whether the WeatherEvent is active (i.e., numHoursUntil is 0, but duration is greater than 0)
  • isExpired() - Returns a boolean value representing whether the WeatherEvent has expired (i.e., numHoursUntil and duration are less than or equal to 0)
  • startEffect() (abstract) - This starts a WeatherEvent's in-game effects, and should include triggering sound effects, lighting changes, and game mechanic effects
  • stopEffect() (abstract) - This stops a WeatherEvent's in-game effects, and should include stopping sound effects, reverting lighting changes, and stopping game mechanic effects

Acid Shower Events

An AcidShowerEvent is a WeatherEvent that periodically causes an acid burn, which damages plants and causes animals to panic

Game Mechanic Effects

The following in-game effects occur when an AcidShowerEvent occurs:

  • All open flames (from placeable lights) are doused
  • The rate at which crop tiles dry decreases. The least severe AcidShowerEvents have no effect on the dry rate, while the most severe AcidShowerEvents result in crop tiles being watered at a rate equal to their typical dry rate

Additionally, every 2 to 4 seconds (2 seconds for the most severe AcidShowerEvents, 4 seconds for the least severe), an "acidBurn" will trigger. When an "acidBurn" triggers, all plants take 1 point of damage, and animals panic (by starting the PanicTask).

Lighting Effects

A global lighting multiplier is applied, with a value in the range [0.75f, 0.95f] (higher severity AcidShowerEvents result in a lower multiplier), which darkens the screen.

Particle Effects

Using the particle system, a rain effect is added to the screen.

Sound Effects

A rolling storm sound effect is started, which loops for the duration of the AcidShowerEvent. Additionally, each time the "acidBurn" is triggered, a hissing sound effect plays to signify an acid burn.

Blizzard Events

An AcidShowerEvent is a WeatherEvent that slows the player and decreases the effectiveness of plant AOE effects.

Game Mechanic Effects

The following in-game effects occur when a BlizzardEvent occurs:

  • All placed lights are ignited, even if it is daytime
  • A round of fireflies spawn if it is not currently nighttime. These fireflies will remain until the blizzard event stops (unless the blizzard ends while it is still nighttime)
  • The rate at which crop tiles dry increases. The least severe BlizzardEvents have no effect on the dry rate, while the most severe BlizzardEvents double the rate at which crop tiles dry
  • The Aoe effects of plants decrease in effectiveness by 1 point for BlizzardEvents of severity less than or equal to 0.75f, or by 2 points for more severe events. That is, the healing aura of Hammer Plants heal 1 or 2 fewer points each time its effect is triggered, the poison aura of Deadly Nightshades deal 1 or 2 points less damage each time its effect is triggered, and the damage caused by plant decay is 1 or 2 points greater each time the effect is triggered
  • The player movement speed is reduced to between 0.45f and 0.95f (the most severe BlizzardEvents reduce the player's speed the most)

Lighting Effects

A global lighting multiplier is applied, with a value in the range [0.5f, 0.7f] (higher severity BlizzardEvents result in a lower multiplier), which darkens the screen.

Particle Effects

Using the particle system, a snow effect is added to the screen.

Sound Effects

A gentle rumble with occasional whistles of wind sound effect is started, which loops for the duration of the BlizzardEvent.

Rain Storm Events

A RainStormEvent is a WeatherEvent that waters plants, and periodically triggers a lighning strike.

Game Mechanic Effects

The following in-game effects occur when a RainStormEvent occurs:

  • All open flames (from placeable lights) are doused
  • Crop tiles will be watered. The least severe RainStormEvents result in crop tiles not drying at all, while the most severe RainStormEvents result in crop tiles being watered at a rate equal to 4x their typical dry rate

Additionally, a "lightningStrike" will trigger in random intervals. The bounds of these intervals are determined by the severity of the event. The bounds are (higher severities are on the lower ends of these bounds):

  • Lower bound: [2.0f, 5.0f]
  • Upper bound: [6.0f, 14.0f]

When a "lightningStrike" occurs, animals panic.

Lighting Effects

A global lighting multiplier is applied, with a value in the range [0.6f, 0.9f] (higher severity RainStormEvents result in a lower multiplier), which darkens the screen.

Particle Effects

Using the particle system, a rain effect is added to the screen. Additionally, each time the "lightningStrike" is triggered, a global colour offset is added to brighten the screen briefly (simulating a lightning strike). The duration for which the screen is brightened is a random number, with a range determined by the severity of the event. The upper and lower bounds for this random duration are (higher severities are on the upper ends of these bounds):

  • Lower bound: [0.2f, 0.4f]
  • Upper bound: [0.8f, 1.2f]

Sound Effects

A rolling storm sound effect is started, which loops for the duration of the RainStormEvent. Additionally, each time the "lightningStrike" is triggered, a rumbling thunder sound effect plays.

Solar Surge Events

A SolarSurgeEvent is a WeatherEvent that dries out plants, and periodically damages them (if the severity is high enough).

Game Mechanic Effects

The following in-game effects occur when a SolarSurgeEvent occurs:

  • The rate at which crop tiles dry increases. The least severe SolarSurgeEvents double the drying rate, while the most severe SolarSurgeEvents result in crop tiles being dried at 20x their regular rate
  • The Aoe effects of plants increase in effectiveness by 1 point for SolarSurgeEvents of severity less than or equal to 0.75f, or by 2 points for more severe events. That is, the healing aura of Hammer Plants heal 1 or 2 more points each time its effect is triggered, the poison aura of Deadly Nightshades deal 1 or 2 points more damage each time its effect is triggered, and the damage caused by plant decay is 1 or 2 points greater each time the effect is triggered

Additionally, every 2 to 4 seconds (2 seconds for the most severe AcidShowerEvents, 4 seconds for the least severe), a "surge" will trigger. When an "surge" triggers, if the event has a severity greater than 1.2f, all plants take 1 point of damage, and animals panic.

Lighting Effects

A global lighting multiplier of 0 is applied, and a lighting effect is triggered. This lighting effect alters the red, green and blue channels of the global colour offset in a sinusoidal pattern (each channel is randomly offset, and changes at different rates).

Particle Effects

SolarSurgeEvents do not spawn associated particle effects.

Sound Effects

A rolling static and phaser sound effect is started, which loops for the duration of the SolarSurgeEvent. Additionally, each time a "surge" is triggered, a phaser sound effect plays to indicate to the player that a surge is occurring.

UML Diagram

Below is a UML overview of the core classes in the system (ignoring specific implementations).

weatherSystemUML

Clone this wiki locally