Value controlled rain code

From EDukeWiki
Revision as of 16:26, 1 March 2005 by Mblackwell (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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.