Value controlled rain code
This shows how to use Eduke to create a nice rain effect, allowing you to spawn and retain a certain amount of rain within a map. The way this works, is we create both rain, and a spawner for the rain. The "rain spawner" can then be given a hitag by the mapper, equal to the amount of rain they want to spawn. The rain itself spawns in a limited area, but "spreads out", allowing you to easily modify overall density.
First we will create the rain actor itself:
These are afew gamevars we will need in the course of this code:
gamevar TEMP 0 2 gamevar RAND_DIST 0 2 gamevar COUNTER 0 2 gamevar MHITAG 0 2 gamevar ORIGRAINPOSX 0 2 gamevar ORIGRAINPOSY 0 2
Of course, then we need actor tile definitions. Change these appropriately:
define RAIN1 3890 define RAINRIPPLE 3880
Here's our relevant move commands (remember, positive verticle values mean downward motion):
move RAINDOWN 0 800 move RAINSKY 800 0
And here are our actions, including a 5 frame splash:
action INIT 0 1 1 1 1 action RAINDROP 0 1 1 1 1 action RAINSPLASH 1 5 1 1 5
And now on to the actual actor code:
useractor notenemy RAIN1 0
ifaction 0
{
cstat 32768
action INIT
getactor[THISACTOR].x ORIGRAINPOSX
getactor[THISACTOR].y ORIGRAINPOSY
}
You probably noticed we used "ifaction 0". This allows us to do things on what is basically actor intialization, and without wasting an action. You may have noticed we saved the original x/y of the actor.
sizeat 10 40
This sets the size of the sprite. In this case I wanted it taller than it is wide. Adjust accordingly.
ifaction INIT
{
cstat 32768
ifoutside { }
else { setactor[THISACTOR].x ORIGRAINPOSX setactor[THISACTOR].y ORIGRAINPOSY }
move RAINSKY geth randomangle
ifrnd 96 { action RAINDROP }
}
else ifaction RAINDROP
{
ifoutside { }
else { setactor[THISACTOR].x ORIGRAINPOSX setactor[THISACTOR].y ORIGRAINPOSY }
You probably noticed this last statement above as well. Incase the rain goes indoors, this will reset to it's original position. This is seen later as well.
cstat 2 move 0 fall move 0
This makes the rain transparent, and stops any horizontal movement.
move RAINDOWN getv
iffloordistl 4
{
sizeat 20 20
action RAINSPLASH
move 0 fall
}
}
else ifaction RAINSPLASH
{
sizeat 20 20
This sizeat command alters the size of the sprite to account for the fact that it is now a "splash".
cstat 2
ifactioncount 5
{
cstat 32768
ifonwater { espawn RAINRIPPLE }
getsector[THISACTOR].ceilingz TEMP
setactor[THISACTOR].z TEMP
action INIT
}
}
enda
You may have realized, I coded to account for the fact that the rain may end up on water, in which case it will spawn a ripple. Here's some quick code for that:
action RIPPLING 0 9 1 1 4
useractor notenemy RAINRIPPLE 0
ifaction 0
{
sizeat 20 20
cstat 34
action RIPPLING
move 0 fall
}
ifactioncount 9 { killit }
iffloordistl 4 { } else { killit }
enda
Now comes the part where we make the rain spawner. First we can make a quick state to handle where the rain spawns.
state spawnrain
cstat 32768
ifvarvare MHITAG COUNT { setvar COUNT 0 killit }
else
{
addvar COUNT 1
espawn RAIN1
getactor[THISACTOR].pal TEMP
setactor[RETURN].pal TEMP
ifrnd 64
{
getactor[RETURN].x TEMP
randvar RAND_DIST 2048
addvar RAND_DIST 2048
addvarvar TEMP RAND_DIST
setactor[RETURN].x TEMP
}
ifrnd 64
{
getactor[RETURN].x TEMP
randvar RAND_DIST -2048
subvar RAND_DIST 2048
addvarvar TEMP RAND_DIST
setactor[RETURN].x TEMP
}
ifrnd 64
{
getactor[RETURN].y TEMP
randvar RAND_DIST 2048
addvar RAND_DIST 2048
addvarvar TEMP RAND_DIST
setactor[RETURN].y TEMP
}
ifrnd 64
{
getactor[RETURN].y TEMP
randvar RAND_DIST -2048
subvar RAND_DIST 2048
addvarvar TEMP RAND_DIST
setactor[RETURN].y TEMP
}
}
ends
You may have noticed I cleverly added a bit of code at the beginning to cause the rain to be the same palette as the spawner. This would allow you to create, for instance, a rainbow colored rainfall, or that of blood, if you so choose, all while using the same rain actor. The range I used is (as you could probably tell), 2048x2048x2048. You can change this as you wish, but this is a good number.
And the actor itself:
action NORSPAWN 0 1 1 1 1
useractor notenemy RSPAWN 0 RNOT 0
ifaction 0
{
getactor[THISACTOR].hitag MHITAG
setvar TEMP 0
setactor[THISACTOR].hitag TEMP
action NORSPAWN
}
state spawnrain
enda
The advantages of this method are quite obvious, in that it lowers the amount of potential actors that will be in the map (the only time it would increase beyond what you defined is if the rain hits water, which should have a negligable effect), and makes it quite easy to edit the rain in a map. Also, rain is prevented from going indoors, except at the edges, limiting potential bugs, while providing a realistic effect.
Try it yourself.