• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • Vote for the theme of Hive's HD Modeling Contest #7! Click here to vote! - Please only vote if you plan on participating❗️

Weather System!

Level 11
Joined
Jun 20, 2017
Messages
380
I didn't want to bump his thread! So I made this one!
Could someone draft me an example on Triggers to make a weather system that changes per timed event?

I want a similar random weather system that has 4 seasons and works with the middle clock (time of day), the clock must be fully turned to day or night (which is 240 seconds I think, at 06/18) for the weather to change again (must start from spring). And the tileset and trees should also be changed.
Note, I only want those bases to change their terrain and the trees, outside should not change!
All these bases can be changed from spring to winter.

For example,
When it's spring, the wind blows and tornadoes, with green grass tileset. (losing ms/as)
When it's summer, the weather is clear, with thick grass tileset. (burning causing to lose mana/armor)
Note, for the summer I want 2 weathers, daylight in the morning and moonlight at night.

When it's autumn, it rains and thunders, with red grass tileset. (damaging over time losing hp)
When it's winter, it snows, with snow tileset. (losing ms/as)

How can I do this?
 
Last edited:

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
Here's an example map to get you started.

I didn't implement any of the Aura/Dummy stuff but I have all of the triggers in place for adding them. I also didn't rely on the in-game clock mechanic but instead used a Timer. But you should be able to sync what I did to the clock by changing the timer's interval, starting time of day, and the number of Days in a Season to match the clock settings. Personally, I think it's unnecessary to rely on time of day for the seasons and will prevent you from taking full advantage of day/night.

The Seasons start on specific Days and remain active for a set number of days. The Days are tracked in an Integer array variable which increases periodically. A year has 360 days and works like this:

Day 1 - 90 = Spring
Day 91 - 180 = Summer
Day 181 - 270 = Fall
Day 271 - 360 = Winter

So Spring starts on Day 1 and ends on Day 91 (when Summer starts).

For the damaging weather, you can create temporary Dummy units and order them to cast Tornado / Monsoon randomly within your player's region. The map has variables that tell you a player's current Season so you can always check for it in your other triggers. IE: Every 10 seconds -> If Season Equal to Spring -> Create 1 Tornado Dummy.

I designed everything to be MPI, meaning each Player can have their own Days/Seasons without conflicting with one another.
 

Attachments

  • Weather System.w3m
    26 KB · Views: 19
Last edited:
Level 11
Joined
Jun 20, 2017
Messages
380
Oh my God, thank you so much and may God bless you!

More idea
There is very little chance that a random structure or trees will catch fire in summer!
If a unit or structure is struck by lightning dealing damage, else destroying trees but the root must remain!
There is very little chance that a random structure or units will freeze in winter!

At 32:58 the screen turns red when a werewolf kills a human, how can I do this?
I saw a video of this map where the screen goes black and it thunders! But I can't find it!
 
Last edited:

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
Relying on the Time of Day events has caused problems for me in the past. It's generally a bad idea to check the exact value of a Real due to their imprecision. But my issues may have been because I adjusted the Speed of the time of day, perhaps using the default speed is fine.

Tornadoes:
You can add the Tornadoes to a Unit Group when they enter the map and periodically check for Trees around them using the usual Every X seconds -> Pick every unit in group design that we use elsewhere. The rest sounds like the default behavior of the Tornado ability.

Random fire/lightning/freeze:
Can be done with Dummy units again. Every X seconds -> Create Dummy unit -> Add X ability -> Order to use X ability.
You could use Acid Bomb for Fire, Storm Bolt for Lightning, Storm Bolt for Freeze. Set the Missile Speed to 0 and modify the AoE as needed.

The screen effects are called Filters which you can find in the Cinematic category of the Trigger Editor.

Here's a fixed Tornado trigger:
  • Tornado
    • Events
      • Time - Every 10.00 seconds of game time
    • Conditions
    • Actions
      • Player Group - Pick every player in Spring_Player_Group and do (Actions)
        • Loop - Actions
          • Set VariableSet WS_Player (Picked player)
          • Set VariableSet WS_PN = (Player number of WS_Player)
          • For each (Integer A) from 1 to 3, do (Actions)
            • Loop - Actions
              • Set VariableSet WS_Point[1] = (Random point in WS_Regions[WS_PN])
              • Unit - Create 1 [Dummy] Weather for Neutral Hostile at WS_Point[1] facing Default building facing degrees
              • Set VariableSet WS_Dummy = (Last created unit)
              • Unit - Add Tornado [Custom] to WS_Dummy
              • Unit - Add a 15.00 second Generic expiration timer to WS_Dummy
              • Unit - Order WS_Dummy to Neutral Sea Witch - Tornado WS_Point[1]
              • Custom script: call RemoveLocation( udg_WS_Point[1] )
When it become Spring time for a Player you would Add them to the Spring_Player_Group. Then Remove them once Spring ends. This way you can easily interact with all of the Players that are experiencing the Spring season. Do the same for the other 3 seasons.

Note that this design really only makes sense if you're giving each Player their own Seasons. If Seasons are shared then you don't need these Season-specific Player Groups and you don't need the Day/Season variables to be Arrays. You could probably get rid of the WS_PN variable as well and design things to be more simple. IE: Pick every player in ALL players -> Do stuff based on the game's current season. And/or just toggle some triggers on/off that are specific to a season.
 
Last edited:
Level 11
Joined
Jun 20, 2017
Messages
380
Relying on the Time of Day events has caused problems for me in the past. It's generally a bad idea to check the exact value of a Real due to their imprecision. But my issues may have been because I adjusted the Speed of the time of day, perhaps using the default speed is fine.
I don't know how to detect it then!
I tried to use condition instead but I got lag!
(In-game time of day) Greater than or equal to 6.00

In my map, the seasons are shared so that everyone can experience the same weather.

Acid Bomb/Storm Bolt targets a unit, not a point, so if it's not a unit, can it target trees?
 
Last edited:

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
The system I made was designed to be MPI, meaning each Player has their own Days/Seasons. You do NOT need this since you're sharing everything. So almost everything in my map is unnecessary and you shouldn't be using it. However, the CONCEPTS are still useful to you, so you should to try to adapt them to your map.

So just keep it simple:

1) Have an Integer variable that represents the current Season. Increase it whenever a Season changes, add an If Then Else to make sure it resets back to 1 once it reaches 5 (Winter -> Spring).
  • Set Variable Season = (Season + 1)
  • If all conditions are true then do (Actions)
    • If - Conditions
      • Season Equal to 5
    • Then - Actions
      • Set Variable Season = 1
    • Else - Actions
2) Adding to #1, have triggers that run whenever a Season changes (previous season ended, new season started). You could keep using the Trigger array design that I was using in my WS Setup trigger. That will help keep the trigger nice and organized:
  • Trigger - Run Season_Ended_Trigger[Season] (ignoring conditions)
  • Set Variable Season = (Season + 1)
  • If all conditions are true then do (Actions)
    • If - Conditions
      • Season Equal to 5
    • Then - Actions
      • Set Variable Season = 1
    • Else - Actions
  • Trigger - Run Season_Started_Trigger[Season] (ignoring conditions)
3) Your Season Ended trigger will remove everything from the previous Season:
  • Fall Ended
    • Events
    • Conditions
    • Actions
      • -------- This is the END of Fall (3) ---------
      • Environment - Destroy Season_Weather[1]
      • Unit - Remove Season_Dummy[1] from the game
      • Trigger - Turn off Fall Periodic Weather
Your Season Started trigger will create everything necessary for the new Season:
  • Winter Started
    • Events
    • Conditions
    • Actions
      • -------- This is the START of Winter (4) ---------
      • Environment - Create at (Playable map area) the weather effect Snow (Heavy)
      • Set Variable Season_Weather[1] = (Last created weather effect)
      • Environment - Create at (Playable map area) the weather effect Wind (Heavy)
      • Set Variable Season_Weather[2] = (Last created weather effect)
      • Unit - Create 1 Winter (Slow Aura) for Neutral Hostile at (Center of (Playable map area))
      • Set Variable Season_Dummy[1] = (Last created unit)
      • Trigger - Turn on Winter Periodic Weather
With this design you can easily manage the Seasons. This example goes from Season 3 (Fall) to Season 4 (Winter). The Fall Ended trigger would run first, removing all Fall related stuff, then the Winter Started trigger would run second, creating all Winter related stuff. So you would have 2 main triggers per Season, Season Started and Season Ended.


I don't know how to detect it then!
I tried to use condition instead but I got lag!
(In-game time of day) Greater than or equal to 6.00
If it works then there's no issue. But if your Events aren't firing then I suggest using a custom Time Of Day system.

Acid Bomb/Storm Bolt targets a unit, not a point, so if it's not a unit, can it target trees?
Try it out? I know Storm Bolt can target Destructables or at least could at one point.
 
Last edited:

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
Like I said earlier, you need to get rid of the MPI stuff. You're not interacting with multiple Players anymore. Also, you seem to have combined all of the triggers, you have two Day variables for some reason. Just think about the concept in simple terms:

Increase the Day variable every so often -> Check the Day variable after increasing it -> Change the Season if necessary -> Run the associated Season triggers if necessary
 
Level 11
Joined
Jun 20, 2017
Messages
380
I found your TOD system in this thread
Is there a way to make a player team sleep like creeps do?
But how can I replace this
Game - The in-game time of day becomes Equal to 5.50
With this
Game - TOD_Event becomes Equal to 1.00

I used these abilities for buffs which works, but is there a better way?
Brilliance Aura/Devotion Aura for losing mana/armor
Unholy Aura/Command Aura for losing hp/damage
 
Last edited:

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
I wouldn't use that TOD system, just continue using what you had already, there was nothing wrong with it as far as I could tell.

Auras are fine.

You can set the life of a destructable, so just set the tree's life to (life - 100.00) or whatever amount of damage you want to deal.
 
Last edited:
Level 11
Joined
Jun 20, 2017
Messages
380
Why doesn't this work? How can I make it work?
I want to create a special effect and then deal damage and remove the special effect after x amount of time.
  • WS Summer Periodic Weather
    • Events
      • Time - Every 2.00 seconds of game time
    • Conditions
      • WS_Season Equal to WS_Summer
    • Actions
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • Set VariableSet WS_Player = (Picked player)
          • Set VariableSet WS_PN = (Player number of WS_Player)
          • -------- --------
          • -------- Setup Dummy --------
          • For each (Integer A) from 1 to 5, do (Actions)
            • Loop - Actions
              • Set VariableSet WS_Point[1] = (Random point in WS_Regions[WS_PN])
              • Unit - Create 1 [Dummy] Weather for Neutral Hostile at WS_Point[1] facing Default building facing degrees
              • Set VariableSet WS_DummyWeatherEffects[2] = (Last created unit)
              • Unit - Add Acid Bomb [Custom] to WS_DummyWeatherEffects[2]
              • -------- --------
              • -------- --------
              • Set VariableSet WS_PointA = (Position of WS_DummyWeatherEffects[2])
              • Custom script: set bj_wantDestroyGroup = true
              • Unit Group - Pick every unit in (Units within 200.00 of WS_PointA.) and do (Actions)
                • Loop - Actions
                  • Set VariableSet WS_FireUnit = (Picked unit)
                  • Set VariableSet WS_PointB = (Position of WS_FireUnit)
                  • -------- --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (WS_FireUnit is alive) Equal to True
                      • (WS_FireUnit is A structure) Equal to True
                    • Then - Actions
                      • Special Effect - Create a special effect at WS_PointB using Environment\LargeBuildingFire\LargeBuildingFire1.mdl
                      • Set VariableSet WS_FireSp[1] = (Last created special effect)
                      • Special Effect - Create a special effect attached to the origin of WS_FireUnit using Environment\LargeBuildingFire\LargeBuildingFire2.mdl
                      • Set VariableSet WS_FireSp[2] = (Last created special effect)
                      • Countdown Timer - Start WS_FireTimer as a One-shot timer that will expire in 2.00 seconds
                    • Else - Actions
                  • -------- --------
                  • Custom script: call RemoveLocation(udg_WS_PointB)
              • -------- --------
              • Unit - Add a 5.00 second Generic expiration timer to WS_DummyWeatherEffects[2]
              • Custom script: call RemoveLocation(udg_WS_Point[1])
              • -------- --------
              • -------- --------
              • Destructible - Pick every destructible within 200.00 of WS_PointA and do (Actions)
                • Loop - Actions
                  • Set VariableSet WS_FireTree = (Picked destructible)
                  • Set VariableSet WS_PointC = (Position of WS_FireTree)
                  • -------- --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (WS_FireTree is alive) Equal to True
                      • (Destructible-type of WS_FireTree) Equal to WS_TreeTypes[0]
                    • Then - Actions
                      • Special Effect - Create a special effect at WS_PointC using Environment\LargeBuildingFire\LargeBuildingFire1.mdl
                      • Set VariableSet WS_FireSp[3] = (Last created special effect)
                      • Countdown Timer - Start WS_FireTimer as a One-shot timer that will expire in 2.00 seconds
                    • Else - Actions
                  • -------- --------
                  • Custom script: call RemoveLocation(udg_WS_PointC)
              • -------- --------
              • Custom script: call RemoveLocation(udg_WS_PointA)
  • Untitled Trigger 002
    • Events
      • Time - WS_FireTimer expires
    • Conditions
    • Actions
      • Unit - Order WS_DummyWeatherEffects[2] to Neutral Alchemist - Acid Bomb WS_FireUnit
      • Destructible - Set life of WS_FireTree to 0.00
      • Special Effect - Destroy WS_FireSp[1]
      • Special Effect - Destroy WS_FireSp[2]
      • Special Effect - Destroy WS_FireSp[3]
 

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
You're breaking a lot of trigger rules here.

You're sharing a single Timer variable with potentially 100's of destructibles at the same time. You're just starting and restarting the timer over and over again, once per destructible. Then when the timer finally expires you're using global variables which reference whatever they've last been set to. Also, the Timers duration is set to 2.00 seconds and the Periodic Intervals duration is 2.00 seconds meaning that there's a chance the Timer never even gets to expire since you're restarting it at the same exact time that it would expire.

With that in mind, you'll want to look into the concept of global variables, local variables, and using global array variables to manage more complicated systems like these. That should lead you into concepts like Unit Indexing and Dynamic Indexing. This appears to be a case where you may want to rely on Dynamic Indexing. Note: Arrays with Timers, Unit Groups, and Player Groups (+1 more I'm forgetting) need to be manually initialized.

Anyway, the temporary Special Effects issue can be solved easily with a simple technique like this:
Perhaps you could use the above technique to create your own trigger that tracks the sfx, tree, and unit locally.
 
Last edited:
Level 11
Joined
Jun 20, 2017
Messages
380
Thanks, I got it to work with this
  • WS Delayed Destroy Effect
    • Events
    • Conditions
    • Actions
      • Custom script: local effect ws_sfx = GetLastCreatedEffectBJ()
      • Custom script: local destructable ws_tree = udg_WS_FireTree
      • -------- --------
      • Wait WS_Delay seconds
      • -------- --------
      • Unit Group - Pick every unit in WS_FireGroup and do (Actions)
        • Loop - Actions
          • Unit - Order WS_DummyWeatherEffects[2] to Neutral Alchemist - Acid Bomb (Picked unit)
      • -------- --------
      • Custom script: call SetDestructableLife( ws_tree, 0.00 )
      • Custom script: call DestroyEffect ( ws_sfx )
      • Custom script: set ws_sfx = null
Now the season and environment are not working properly!
I edited everything I could think of, but one thing broke another!
Can you check the map please?
 
Last edited:

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
Thanks, I got it to work with this
  • WS Delayed Destroy Effect
    • Events
    • Conditions
    • Actions
      • Custom script: local effect ws_sfx = GetLastCreatedEffectBJ()
      • Custom script: local destructable ws_tree = udg_WS_FireTree
      • -------- --------
      • Wait WS_Delay seconds
      • -------- --------
      • Unit Group - Pick every unit in WS_FireGroup and do (Actions)
        • Loop - Actions
          • Unit - Order WS_DummyWeatherEffects[2] to Neutral Alchemist - Acid Bomb (Picked unit)
      • -------- --------
      • Custom script: call SetDestructableLife( ws_tree, 0.00 )
      • Custom script: call DestroyEffect ( ws_sfx )
      • Custom script: set ws_sfx = null
Now the season and environment are not working properly!
I edited everything I could think of, but one thing broke another!
Can you check the map please?
I'm not too interesting in going much further to be brutally honest. I'll end up making the entire map myself (admittedly I do this sometimes). But more importantly I think it's a good challenge for you and I'm sure you can learn a lot from creating an elaborate system like this, plus I've already laid out most of the foundation.

Also, to reiterate a point, you really don't need anything too technical if you're sharing the Seasons between Players. Most of my original design with the Arrays/Player Groups was there to give each Player their own unique Days/Seasons. But if that's not the case then you can take a step back and get rid of those. In fact, your triggers might not be working because you haven't done this yet. I saw you were still using a Player Group to increase the Days which made no sense, you would increase the Day counter once every interval, not X times every interval based on the number of Players.
 
Last edited:
Top