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.