/*
 *  Storm module for GBlanker
 *
 *  Storm (c) 1994-95 David Kinder
 *  GBlanker (c) 1994 Michael D. Bayne
 *
 */

#include <time.h>
#include "Includes.h"

#define RAIN_NONE     0
#define RAIN_LIGHT   20
#define RAIN_HEAVY   40
#define RAIN_TORRENT 70
#define LIGHT_STEP   30

#define RAIN 0
#define FREQ 2
#define MODE 4

static const UBYTE VersTag[] = "$VER:Storm 38.2 (7.1.95)";

static USHORT Colours[4] = { 0x0000,0x04CF,0x0FF0,0x0000 };
SHORT RainPos[RAIN_TORRENT][2];
SHORT Width, Height, RainType, RainLen, RainSpeed;
struct RastPort *Rast;

void DrawRain(SHORT x, y, pen);
void DrawLight(SHORT x, y);
SHORT LightRand(SHORT range);

void Defaults(PrefObject *Prefs)
{
  Prefs[RAIN].po_Level = 2;
  Prefs[FREQ].po_Level = 5;
  Prefs[MODE].po_ModeID = getTopScreenMode();
}

LONG Blank(PrefObject *Prefs)
{
struct Screen *Scr;
struct Window *Wnd;
LONG ToFrontCount = 0, RetVal = OK, FlashSeq = 0, FlashTime = 0, i;
SHORT RainSpeed1, RainSpeed2, LightX1, LightX2, LightY;
clock_t trigger;

  Scr = OpenScreenTags(0L,SA_Depth,2,
			  SA_Overscan,OSCAN_STANDARD,
			  SA_DisplayID,Prefs[MODE].po_ModeID,
			  SA_Quiet,TRUE,
			  SA_Behind,TRUE,TAG_DONE);
  if (Scr)
  {
    LoadRGB4(&(Scr->ViewPort),Colours,4);
    Wnd = BlankMousePointer(Scr);
    Rast = &(Scr->RastPort);
    Width = Scr->Width;
    Height = Scr->Height;
    RainLen = Height/10;
    SetRast(Rast,0);
    ScreenToFront(Scr);

    switch (Prefs[RAIN].po_Level)
    {
      case 0:
	RainType = RAIN_NONE;
	break;
      case 1:
	RainType = RAIN_LIGHT;
	RainSpeed1 = RainLen/2;
	RainSpeed2 = RainSpeed1;
	break;
      case 2:
	RainType = RAIN_HEAVY;
	RainSpeed1 = (RainLen/3)*2;
	RainSpeed2 = RainLen/2;
	break;
      case 3:
	RainType = RAIN_TORRENT;
	RainSpeed1 = (RainLen/4)*3;
	RainSpeed2 = (RainLen/3)*2;
	break;
    }
    if (RainType != RAIN_NONE)
    {
      for (i = 0; i < RainType; i++)
      {
	RainPos[i][0] = RangeRand(Width);
	RainPos[i][1] = RangeRand(Height + RainLen) - RainLen;
      }
    }
    if (Prefs[FREQ].po_Level != 0) FlashTime = 300/(Prefs[FREQ].po_Level);
    trigger = clock();

    while (RetVal == OK)
    {
      WaitBOVP(&(Scr->ViewPort));
      if (FlashTime != 0)
      {
	switch (FlashSeq)
	{
	  case 7:
	    do
	    {
	      LightX1 = RangeRand(Width);
	      LightX2 = RangeRand(Width/2);
	      if (LightX1 < Width/2) LightX2 = Width-LightX2;
	    }
	    while (abs(LightX2-LightX1) < Width/4);
	    LightX2 = (LightX2-LightX1)/LIGHT_STEP;
	    LightY = Height/LIGHT_STEP;
	    SetAPen(Rast,2);
	    Move(Rast,LightX1,0);
	    for (i = 1; i <= LIGHT_STEP+3; i++)
	      DrawLight(LightX1+(LightX2*i)+LightRand(LightX2),
	      (LightY*i)+LightRand(LightY));
	    break;
	  case 3:
	    SetRGB4(&(Scr->ViewPort),0,15,15,15);
	    break;
	  case 1:
	    SetRGB4(&(Scr->ViewPort),0,0,0,0);
	    SetAPen(Rast,0);
	    Rast->Mask = 2;
	    Move(Rast,LightX1,0);
	    RectFill(Rast,0,0,Width-1,Height-1);
	    Rast->Mask = ~0;
	    break;
	  case 0:
	    if (clock() - trigger > FlashTime)
	    {
	      trigger = clock();
	      if (RangeRand(10) > 5) FlashSeq = 8;
	    }
	    break;
	}
      }
      if (FlashSeq != 0) FlashSeq--;
      for (i = 0, RainSpeed = RainSpeed1; i < RainType; i++)
      {
	if (i == RainType/2) RainSpeed = RainSpeed2;
	DrawRain(RainPos[i][0],RainPos[i][1],0);
	DrawRain(RainPos[i][0],RainPos[i][1]+RainLen,1);
	if ((RainPos[i][1] += RainSpeed) >= Height + RainSpeed)
	{
	  RainPos[i][0] = RangeRand(Width);
	  RainPos[i][1] = RainLen*-1;
	}
      }
      RetVal = ContinueBlanking();
    }
    UnblankMousePointer(Wnd);
    CloseScreen(Scr);
  }
  else RetVal = FAILED;
  return (RetVal);
}

void DrawRain(SHORT x, y, pen)
{
SHORT end_y;

  if (y < 0) y = 0;
  else if (y >= Height) y = Height-1;

  if ((end_y = y + RainSpeed) < 0) end_y = 0;
  else if (end_y >= Height) end_y = Height-1;

  if (y != end_y)
  {
    SetAPen(Rast,pen);
    Move(Rast,x,y);
    Draw(Rast,x,end_y);
  }
}

void DrawLight(SHORT x, y)
{
  if (x < 0) x = 0;
  else if (x >= Width) x = Width-1;
  if (y >= Height)
  {
    if (Rast->cp_y == Height-1) return;
    y = Height-1;
  }
  Draw(Rast,x,y);
}

SHORT LightRand(SHORT range)
{
  if (range <= 0) range = 1-range;
  return (RangeRand(range)-(range/2));
}
