/*
 * FireWorks module
 */

OPT MODULE

MODULE 'games','games/games','*llist'

EXPORT SET FW_NODRAW,   -> Ignored
           FW_KILLME,   -> Kill this spark asap
           FW_MULTIHUE, -> Explosion will be multi-hued
           FW_MASSIVE,  -> *BIG* explosion
           FW_SMALL,    -> Little explosion, quick death
           FW_HGRAV,    -> Heavy Gravity
           FW_BIGSPARK, -> Sparks are 3x usual size
           FW_IMAGE,    -> Explode into image, negates many other flags
           FW_KEEPFLAGS -> Children get the same flags, use with care.

EXPORT OBJECT firework OF node
  x:LONG,y:LONG     -> X,Y position
  xv:LONG,yv:LONG   -> X and Y velocities
  gd:LONG     -> Gravity delay
  gc:LONG     -> Gravity count
  color:LONG  -> Color base
  bg:LONG     -> Background color at current point
  count:LONG  -> Count until death
  ocount:LONG -> Death delay
  excount:LONG -> If greater than 0, this firework will explode on death,
               -> and the children will recieve self.excount-1
  flags:LONG  -> Firework flags
  iw,ih:LONG  -> Image HALF width/height
  ip:PTR TO CHAR  -> Pointer to expimage
ENDOBJECT

CONST S_BOTTOM=185

PROC draw(scn,buf) OF firework
/*
 * Draw the pixel into the display
 */

  DEF c,c2

  c:=self.color+3-((self.count*4)/self.ocount)
  c2:=self.color+3

  Draw_Pixel(scn,buf,self.x,self.y,c)

  IF (self.flags AND FW_BIGSPARK)
      Draw_Pixel(scn,buf,self.x+1,self.y,c2)
      Draw_Pixel(scn,buf,self.x-1,self.y,c2)
      Draw_Pixel(scn,buf,self.x,self.y+1,c2)
      Draw_Pixel(scn,buf,self.x,self.y-1,c2)
  ENDIF
ENDPROC

PROC clear(scn,buf) OF firework
/*
 * Blank the firework
 */
  Draw_Pixel(scn,buf,self.x,self.y,self.bg)

  IF (self.flags AND FW_BIGSPARK)
      Draw_Pixel(scn,buf,self.x+1,self.y,self.bg)
      Draw_Pixel(scn,buf,self.x-1,self.y,self.bg)
      Draw_Pixel(scn,buf,self.x,self.y+1,self.bg)
      Draw_Pixel(scn,buf,self.x,self.y-1,self.bg)
  ENDIF
ENDPROC

PROC new(x,y,xv,yv,gd,color,bg,count,excount,flags,ix=NIL,iy=NIL,ip=NIL) OF firework
/*
 * Initialise new firework
 */

  self.prev:=NIL
  self.next:=NIL

  self.x:=x
  self.y:=y
  self.xv:=xv
  self.yv:=yv
  self.gd:=gd
  self.gc:=0
  self.color:=color
  self.bg:=bg
  self.count:=count
  self.ocount:=count
  self.excount:=excount
  self.flags:=flags

  self.iw:=ix
  self.ih:=iy
  self.ip:=ip

ENDPROC

PROC update(flist) OF firework
/*
 * Update firework
 */

DEF fw:PTR TO firework,xn,yn,exsize,n,b=NIL,c,s,fl=NIL,g,yv

  self.x:=self.x+self.xv
  self.y:=self.y-self.yv

  IF Rnd(5)=2 THEN self.x:=self.x+Rnd(2)-1

  b:=(self.y>1) AND (self.y<S_BOTTOM) AND (self.x>1) AND (self.x<319)

  IF ((self.count>0) AND b)

    IF self.gc>self.gd
      self.gc:=0
      self.yv:=self.yv-1
    ELSE
      self.gc:=self.gc+1
    ENDIF

    self.count:=self.count-1

  ELSE

    IF b AND (self.excount>0)

      exsize:=Rnd(10)+25

      IF (self.flags AND FW_MASSIVE)=NIL
        IF self.excount=1 
          n:=Rnd(2)+1
        ELSE
          n:=1  -> So that multi-explos don't get too big
        ENDIF
      ELSE
        self.excount:=1
        n:=5
      ENDIF

      IF (self.flags AND FW_SMALL)<>FALSE 
        n:=1
      ENDIF
  
      IF (self.flags AND FW_KEEPFLAGS)<>FALSE THEN fl:=self.flags

      IF (self.flags AND FW_IMAGE)=FALSE

        FOR yn:=-n TO n  
          FOR xn:=-n TO n
  
            IF (self.flags AND FW_MULTIHUE) THEN c:=(Rnd(6)*4)+8 ELSE c:=self.color
            IF (self.flags AND FW_SMALL)=FALSE 
              s:=exsize+((Rnd(3)-1)*10)
            ELSE
              s:=10
            ENDIF
            IF (self.flags AND FW_HGRAV)
              g:=1
              yv:=yn+Rnd(3)-2
            ELSE
              g:=Rnd(3)*6+1
              yv:=yn+self.yv+Rnd(3)-1
            ENDIF

            NEW fw.new(self.x,self.y,
                       xn+self.xv+Rnd(3)-1,
                       yv,
                       g,
                       c,
                       self.bg,
                       s,
                       self.excount-1,
                       fl)

            self.add(fw)

          ENDFOR
        ENDFOR
      ELSE
        FOR yn:=-self.ih TO self.ih
          FOR xn:=-self.iw TO self.iw

            c:=(self.ip[((((self.iw*2)+2)*((-yn)+self.ih))+(xn+self.iw))])

            IF c>0
  
              c:=self.color

              s:=exsize+((Rnd(3)-1)*10)
              g:=2*6+1
              yv:=yn

              NEW fw.new(self.x,self.y,
                       xn+self.xv,
                       yv,
                       g,
                       c,
                       self.bg,
                       s,
                       self.excount-1,
                       fl)

              self.add(fw)

            ENDIF

          ENDFOR
        ENDFOR
      ENDIF

    ENDIF

    IF flist=self THEN flist:=self.next
    self.del()
    self.flags:=FW_KILLME

  ENDIF

ENDPROC flist
