;/*
sc Fireworks.c IGNORE=73 DATA=FAR NMINC STRMERGE NOSTKCHK IGNORE=73 STRUCTUREEQUIVALENCE NOSTDIO
Slink from LIB:c.o Fireworks.o to //Clients/Fireworks LIB LIB:scm.lib LIB:sc.lib LIB:amiga.lib /lib/client.lib SC SD NOICONS STRIPDEBUG
delete Fireworks.o
quit

 Fireworks 1.2  (Client for BServer)

 Copyright © 1994 by Stefano Reksten of 3AM - The Three Amigos!!!
 All rights reserved.
*/

#include <exec/types.h>
#include <exec/memory.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/alib_protos.h>
#include <time.h>
#include <math.h>

#include "/include/client.h"

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

struct DisplayIDInformation *dinfo;

struct Screen *scr1, *scr2;

#define MAXFWKS 10
#define BITSPERFWK 10
#define TOTALFWKS MAXFWKS * BITSPERFWK
#define SCRDEPTH 3

struct Fire {
	WORD X, Y;
	WORD OldX, OldY;
	WORD VelX;
	WORD VelY;
	BOOL Active;
	UWORD ExpTime;
	BOOL Exploded;
	UBYTE Color;
	} Fireworks[TOTALFWKS];

extern ULONG RangeSeed;
UWORD swidth, sheight, maxw, maxh;
BOOL lace;


void SetAllFireworks( void )
{
register UBYTE n;

for ( n = 0; n < TOTALFWKS; n++ )
	{
	Fireworks[n].X = 0;
	Fireworks[n].Y = 0;
	Fireworks[n].Active = FALSE;
	}
}


void MoveAllFireworks( struct Screen *scr )
{
register UBYTE n, m;
register struct RastPort *rp;
register UBYTE color;

rp = &(scr->RastPort);

for ( n = 0; n < TOTALFWKS; n += BITSPERFWK )
	{
	if ( !(Fireworks[n].Active) )
		{
		Fireworks[n].OldX = Fireworks[n].X;
		Fireworks[n].OldY = Fireworks[n].Y;
		Fireworks[n].X = RangeRand( maxw );
		Fireworks[n].Y = maxh - 1;
		Fireworks[n].VelX = ( RangeRand( 17 ) - 8 );
		Fireworks[n].VelY = ( lace ? -30-RangeRand(45) : -20-RangeRand(40) );
		Fireworks[n].Active = TRUE;
		Fireworks[n].Exploded = FALSE;
		Fireworks[n].ExpTime = RangeRand( 15 ) + 15;
		Fireworks[n].Color = RangeRand( 3 ) + 1;
		}
	}

for ( n = 0; n < TOTALFWKS; n++ )
	{
	if ( Fireworks[n].Active )
		{
		Move( rp, Fireworks[n].X >> 3, Fireworks[n].Y >> 3 );
		Fireworks[n].X += Fireworks[n].VelX;
		Fireworks[n].Y += Fireworks[n].VelY;
		Fireworks[n].VelY++;

		if ( Fireworks[n].X < 0 || Fireworks[n].X >= maxw )
			Fireworks[n].Active = FALSE;

		if ( Fireworks[n].Y < 0 || Fireworks[n].Y >= maxh )
			Fireworks[n].Active = FALSE;

		if ( Fireworks[n].Active )
			{
			if ( !Fireworks[n].Exploded || Fireworks[n].ExpTime % 5 )
				{
				SetAPen( rp, Fireworks[n].Color );
				Draw( rp, Fireworks[n].X >> 3, Fireworks[n].Y >> 3 );
				}

			if ( !Fireworks[n].Exploded )
				{
				if ( --Fireworks[n].ExpTime == 0 )
					{
					Fireworks[n].Exploded = TRUE;
					color = RangeRand( 3 ) + 1;
					Fireworks[n].Color = color;
					for ( m = 1; m < BITSPERFWK; m++ )
						{
						Fireworks[n+m].X = Fireworks[n].X;
						Fireworks[n+m].Y = Fireworks[n].Y;
						Fireworks[n+m].VelX = Fireworks[n].VelX + RangeRand( 15 ) - 7;
						Fireworks[n+m].VelY = Fireworks[n].VelY + RangeRand( 7 ) - 3;
						Fireworks[n+m].Exploded = TRUE;
						Fireworks[n+m].Active = TRUE;
						Fireworks[n+m].Color = color;
						Fireworks[n+m].ExpTime = m;
						}
					}
				}
			else
				{
				if ( RangeRand( ++Fireworks[n].ExpTime ) >= 70 )
					Fireworks[n].Active = FALSE;
				}
			}
		}
	}

WaitTOF();
ScreenToFront( scr );
SpritesOff();
SetRast( (scr == scr1 ? &(scr2->RastPort) : &(scr1->RastPort)), 0 );
}


void Blank( void )
{
BOOL success = FALSE;
UBYTE n, r, g, b;
struct Screen *activescr;

struct Rectangle *rect;

rect = GETTXTOSCANRECT(dinfo);

swidth = RECTANGLEWIDTH(rect);
sheight = RECTANGLEHEIGHT(rect);
maxw = swidth << 3;
maxh = sheight << 3;
lace = DISPLAYID(dinfo) & LACE;

scr1 = scr2 = NULL;

if ( (scr1 = OpenScreenTags( NULL,
		SA_Width, swidth,
		SA_Height, sheight,
		SA_Depth, SCRDEPTH,
		SA_Type, CUSTOMSCREEN,
		SA_Quiet, TRUE,
		SA_DisplayID, DISPLAYID(dinfo),
		SA_Overscan, OSCAN_TEXT,
		TAG_END ) ) &&
 (scr2 = OpenScreenTags( NULL,
		SA_Width, swidth,
		SA_Height, sheight,
		SA_Depth, SCRDEPTH,
		SA_Type, CUSTOMSCREEN,
		SA_Quiet, TRUE,
		SA_DisplayID, DISPLAYID(dinfo),
		SA_Overscan, OSCAN_TEXT,
		TAG_END ) ) )
	{
	success = TRUE;
	activescr = scr1;

	SetRGB4( &scr1->ViewPort, 0, 0, 0, 0 );
	SetRGB4( &scr2->ViewPort, 0, 0, 0, 0 );
	for ( n = 1; n < 2<<SCRDEPTH; n++ )
		{
		r = RangeRand( 16 - n ) + n;
		g = RangeRand( 16 - n ) + n;
		b = RangeRand( 16 - n ) + n;
		SetRGB4( &scr1->ViewPort, n, r, g, b );
		SetRGB4( &scr2->ViewPort, n, r, g, b );
		}

	SetAllFireworks();

	while( STILL_BLANKING )
		{
		MoveAllFireworks( activescr );
		activescr = ( activescr == scr1 ? scr2 : scr1 );
		}

	SpritesOn();
	}
if ( scr1 )
	CloseScreen( scr1 );
if ( scr2 )
	CloseScreen( scr2 );
if ( !success )
	SendClientMsg( ACTION_FAILED );
}

void __main( char *line )
{
if ( IntuitionBase = (struct IntuitionBase *)OpenLibrary( "intuition.library", 37L ) )
	{
	if ( GfxBase = (struct GfxBase *)OpenLibrary( "graphics.library", 37L ) )
		{
		if ( dinfo = OpenCommunication() )
			{
			RangeSeed = time( NULL );
			Blank();
			CloseCommunication( dinfo );
			}
		CloseLibrary( (struct Library *)GfxBase );
		}
	CloseLibrary( (struct Library *)IntuitionBase );
	}
}
