This topic is inspired by
Dyselon, who made a multiplayer map with rain and snow,
here, which he also distributed the files he used to make snow and rain on the map.
It is a good use of an ongoing active visual effect which players can see. They only see it where fog is revealed, and will of course induce somewhat of a performance hit, depending on the map size.
It should work with more then 2 players, although the lag might increase.
Kasyr Lutien map in Winter. Brrr!
First, the game doesn't come with the effects already. Dyselon made them himself. You can get them from the wiki here:
Download Snow and Rain FX
You need to put the files in the respective folders:
Secondly, you'll need the script (a cleaned up version from Dyselon), and change it. This is the script:
import("ScarUtil.scar")
-- Size of the map, as denoted when you create it.
mapsize_x = 256
mapsize_y = 256
-- Volume of the emitter.
emittervolume = 20
-- rain or snow?
eventname = "rain" -- or "snow"
-- density
density = 0.1
-- This will run and set up the map to have the snow/rain run all game
function Inity()
Rule_AddInterval(Rule_Rainy, density)
xmin = mapsize_x / (-2*emittervolume)
xmax = mapsize_x / (2*emittervolume)
ymin = mapsize_y / (-2*emittervolume)
ymax = mapsize_y / (2*emittervolume)
eventpath = "data:Art/Events/" .. eventname
end
-- Required to initialise the SCAR script.
Scar_AddInit(Inity)
-- This will run at intervals to produce the visual effect
function Rule_Rainy()
for i = xmin, xmax do
for j = ymin, ymax do
World_FXEvent(eventpath, Util_ScarPos(i*emittervolume, j*emittervolume))
end
end
endSave it as a SCAR file, under the same filename as your map, in the same directory, eg:
And put the code into it. The SCAR file is a simple text file.
There are a few parts of the SCAR script you can change quick and easily:
Changin these, or altering other parts of the script, you can get the rain or snow exactly how you like.
Dyselon added movement penalties and accuracy penalties during rain, and also the rain wasn't on all the time. This is the script from his map, and note, this wasn't asked permission to post, but the map is freely available online to download:
--------------------------------------------------------------------------
--
-- (map name here)
--
-- A multiplayer map in which the weather changes over time.
-- The weather will affect unit's accuracy and speed.
--
-- (c) 2005 Ian Cox
--
--------------------------------------------------------------------------
-----------
--IMPORTS--
-----------
import("ScarUtil.scar")
-----------
--GLOBALS--
-----------
-- Change the table below to fit your map
_tWeatherSettings =
{
mapsize = 512,
emittervolume = 20,
eventname = "rain",
updatetime = 15
}
-- Add or remove lines below to set up new weather levels
_tIntervalSettings = {}
_tIntervalSettings[1] = {interval = 1.25, name = "light", accuracymod = .9, speedmod = .9}
_tIntervalSettings[2] = {interval = 0.5, name = "med", accuracymod = .75, speedmod = .8}
_tIntervalSettings[3] = {interval = 0.1, name = "heavy", accuracymod = .5, speedmod = .7}
-- Ignore this one
squads = {}
modifiers = {}
--------
--INIT--
--------
function Inity()
--get random first state for rain
tablemax = table.getn(_tIntervalSettings)
currain = World_GetRand(0, tablemax)
-- currain = 3
players=World_GetPlayerCount()
--modifyunits (every second? maybe less)
Rule_AddInterval(Rule_ModifyUnits, 1)
--cleantable (long long interval... maybe oneshot-ed when weather changes?)
--updateweather (oneshot, random time)
Rule_AddInterval(Rule_UpdateWeather, _tWeatherSettings.updatetime)
Rule_UpdateWeather()
--find out the grid min/maxes for the weather effect.
xmin = _tWeatherSettings.mapsize / (-2*_tWeatherSettings.emittervolume)
xmax = _tWeatherSettings.mapsize / (2*_tWeatherSettings.emittervolume)
ymin = _tWeatherSettings.mapsize / (-2*_tWeatherSettings.emittervolume)
ymax = _tWeatherSettings.mapsize / (2*_tWeatherSettings.emittervolume)
--store the full event path for later
eventpath = "data:Art/Events/" .. _tWeatherSettings.eventname
-- Create the modifiers to be applied for later use.
for i=1,tablemax do
modifiers[i] = {}
modifiers[i].acc1 = Modifier_Create(MAT_Squad, "accuracy_ranged_weapon_modifier", MUT_Multiplication, false, _tIntervalSettings[i].accuracymod, "" )
modifiers[i].acc2 = Modifier_Create(MAT_Squad, "accuracy_weapon_modifier", MUT_Multiplication, false, _tIntervalSettings[i].accuracymod, "" )
modifiers[i].speed = Modifier_Create(MAT_Squad, "speed_maximum_modifier", MUT_Multiplication, false, _tIntervalSettings[i].speedmod, "" )
end
end
Scar_AddInit(Inity)
-------------------
--RULES (weather)--
-------------------
-- This rule changes the weather once in a while
function Rule_UpdateWeather()
-- Save the old rain level
lastrain=currain
-- 50/50 chance to get lighter or softer
change=World_GetRand(0, 1)
if(change==1) then
if(currain < tablemax) then
currain=currain+1
end
else
if(currain > 0) then
currain=currain-1
end
end
-- Print the weather change to the console. Comment this out to stop spamming the console
if(currain>0) then
print("Weather is changing to " .. _tIntervalSettings[currain].name)
else
print("Rain has stopped")
end
-- If the old rain rule exists, kill it
if(Rule_Exists(Rule_Rainy)) then
Rule_Remove(Rule_Rainy)
end
-- If it's raining , add the new rain rule (in a second, so SCAR gets a chance to kill the old one first)
if(currain > 0) then
Rule_AddOneShot(Rule_AddRain, 1)
end
end
-- This rule adds the rain effect
function Rule_AddRain()
Rule_AddInterval(Rule_Rainy, _tIntervalSettings[currain].interval)
end
-- This is the rule that actually spawns the rain everywhere
function Rule_Rainy()
for i = xmin, xmax do
for j = ymin, ymax do
World_FXEvent(eventpath, Util_ScarPos(i*_tWeatherSettings.emittervolume, j*_tWeatherSettings.emittervolume))
end
end
end
---------------------
--RULES (modifiers)--
---------------------
function Rule_ModifyUnits()
-- define the local function that will get called to apply and track the modifiers
mody = function(a, b, c)
-- if the table entry doesn't exist
if(not squads[c.id] and currain > 0) then
squads[c.id] = {}
-- change the table to the right level
squads[c.id].rainlevel = currain
-- apply the modifiers
squads[c.id].acc1=Modifier_ApplyToSquad(modifiers[currain].acc1, c)
squads[c.id].acc2=Modifier_ApplyToSquad(modifiers[currain].acc2, c)
squads[c.id].speed=Modifier_ApplyToSquad(modifiers[currain].speed, c)
end
-- if the table entry exists AND it's the wrong level
if(squads[c.id] and squads[c.id].rainlevel ~= currain) then
-- change the table to the right level
squads[c.id].rainlevel = currain
-- remove the old modifiers
if(lastrain>0) then
Modifier_Remove(squads[c.id].acc1)
Modifier_Remove(squads[c.id].acc2)
Modifier_Remove(squads[c.id].speed)
end
-- apply the new modifiers
if(currain > 0) then
squads[c.id].acc1=Modifier_ApplyToSquad(modifiers[currain].acc1, c)
squads[c.id].acc2=Modifier_ApplyToSquad(modifiers[currain].acc2, c)
squads[c.id].speed=Modifier_ApplyToSquad(modifiers[currain].speed, c)
end
end
end
for i=0, players-1 do
PlayerSquads = Player_GetSquads(World_GetPlayerAt(i))
SGroup_ForEach(PlayerSquads, mody)
end
endUse this, and other ideas (why stop at rain or snow in the expansive Warhammer galaxy?) to make effects do that little bit more to help your map look great!