RDNWiki: DOWFXTool/Tutorials/FXSnowAndRain ...

RDN Wiki Home | Page Index | Recent Changes | Recently Commented | Users | Registration | Login:  Password:  

FX: Snow and Rain


Contents

Introduction


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!

How to 


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
end

Save 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.

Modifying the script


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.

Expanding on the idea


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


end

Use 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!

Links


FX Tutorials
RDN Wiki Home

End of Page

Referring pages: DOWFXTool/Tutorials

There are 2 files on this page. [Display files/form]
There is no comment on this page. [Display comments/form]