
//============================================================================
//----------------------------------------------------------------------------
//								   Grease.c
//----------------------------------------------------------------------------
//============================================================================


#include "Externs.h"
#include "Environ.h"
#include "MainWindow.h"
#include "Objects.h"
#include "PLStandardColors.h"
#include "RectUtils.h"
#include "ResolveCachingColor.h"
#include "Room.h"


#define kGreaseIdle			0
#define kGreaseFalling		1
#define kGreaseSpreading	2
#define kGreaseSpiltIdle	3


void BackupGrease (Rect *, short, Boolean);


greasePtr	grease;
short		numGrease;

extern	hotPtr		hotSpots;
extern	savedType	savedMaps[];
extern	Rect		greaseSrcRt[], greaseSrcLf[];


//==============================================================  Functions
//--------------------------------------------------------------  HandleGrease

// Goes through all grease objects currently on screen and handlesÉ
// them.  If they're upright, nothing happens, but if they're inÉ
// the course of falling or spilling, this function will handleÉ
// advancing the spill, etc.

void HandleGrease (void)
{
	Rect		src;
	short		i;
	
	if (numGrease == 0)
		return;
	
	for (i = 0; i < numGrease; i++)
	{
		if (grease[i].mode == kGreaseFalling)
		{
			grease[i].frame++;
			if (grease[i].frame >= 3)		// grease completely tipped
			{
				grease[i].frame = 3;
				grease[i].mode = kGreaseSpreading;
				hotSpots[grease[i].hotNum].action = kSlideIt;
				hotSpots[grease[i].hotNum].isOn = true;
				if (grease[i].isRight)
					QSetRect(&src, 0, -2, 2, 0);
				else
					QSetRect(&src, -2, -2, 0, 0);
				QOffsetRect(&src, -playOriginH, -playOriginV);
				QOffsetRect(&src, grease[i].start, grease[i].dest.bottom);
				hotSpots[grease[i].hotNum].bounds = src;
			}
			
			QSetRect(&src, 0, 0, 32, 27);
			QOffsetRect(&src, 0, grease[i].frame * 27);
			CopyBits((BitMap *)*GetGWorldPixMap(savedMaps[grease[i].mapNum].map), 
					(BitMap *)*GetGWorldPixMap(workSrcMap), 
					&src, &grease[i].dest, 
					srcCopy);
			CopyBits((BitMap *)*GetGWorldPixMap(savedMaps[grease[i].mapNum].map), 
					(BitMap *)*GetGWorldPixMap(backSrcMap), 
					&src, &grease[i].dest, 
					srcCopy);
			
			AddRectToWorkRects(&grease[i].dest);
			if (grease[i].isRight)
				QOffsetRect(&grease[i].dest, 2, 0);
			else
				QOffsetRect(&grease[i].dest, -2, 0);
		}
		else if (grease[i].mode == kGreaseSpreading)
		{
			if (grease[i].isRight)
			{
				QSetRect(&src, 0, -2, 2, 0);
				QOffsetRect(&src, grease[i].start, grease[i].dest.bottom);
				grease[i].start += 2;
				hotSpots[grease[i].hotNum].bounds.right += 2;
			}
			else
			{
				QSetRect(&src, -2, -2, 0, 0);
				QOffsetRect(&src, grease[i].start, grease[i].dest.bottom);
				grease[i].start -= 2;
				hotSpots[grease[i].hotNum].bounds.left -= 2;
			}
			
			{
				PortabilityLayer::ResolveCachingColor blackColorBack = StdColors::Black();
				backSrcMap->FillRect(src, blackColorBack);

				PortabilityLayer::ResolveCachingColor blackColorWork = StdColors::Black();
				workSrcMap->FillRect(src, blackColorWork);
				AddRectToWorkRects(&src);
			}
			
			if (grease[i].isRight)
			{
				if (grease[i].start >= grease[i].stop)
					grease[i].mode = kGreaseSpiltIdle;
			}
			else
			{
				if (grease[i].start <= grease[i].stop)
					grease[i].mode = kGreaseSpiltIdle;
			}
		}
	}
}

//--------------------------------------------------------------  BackupGrease
// This makes copies of the region of the screen the grease is aboutÉ
// to be drawn to.  It is called in the "set up" when a player hasÉ
// just entered a new room.  The "grease jar falling over" animationÉ
// is set up here.

void BackupGrease (Rect *src, short index, Boolean isRight)
{
	Rect		dest;
	short		i;
	
	QSetRect(&dest, 0, 0, 32, 27);
	for (i = 0; i < 4; i++)
	{
		CopyBits((BitMap *)*GetGWorldPixMap(backSrcMap), 
				(BitMap *)*GetGWorldPixMap(savedMaps[index].map), 
				src, &dest, srcCopy);
		
		if (isRight)
		{
			CopyMask((BitMap *)*GetGWorldPixMap(bonusSrcMap), 
					(BitMap *)*GetGWorldPixMap(bonusMaskMap), 
					(BitMap *)*GetGWorldPixMap(savedMaps[index].map), 
					&greaseSrcRt[i], &greaseSrcRt[i], &dest);
			QOffsetRect(src, 2, 0);
		}
		else
		{
			CopyMask((BitMap *)*GetGWorldPixMap(bonusSrcMap), 
					(BitMap *)*GetGWorldPixMap(bonusMaskMap), 
					(BitMap *)*GetGWorldPixMap(savedMaps[index].map), 
					&greaseSrcLf[i], &greaseSrcLf[i], &dest);
			QOffsetRect(src, -2, 0);
		}
		QOffsetRect(&dest, 0, 27);
	}

}

//--------------------------------------------------------------  ReBackUpGrease
// Just like th eabove function but it is called while the player isÉ
// active in a room and has changed the lighting situation (like turnedÉ
// off or on the lights).  It assumes certain data strucutures areÉ
// already declared from an earlier call to the above funciton.

short ReBackUpGrease (short where, short who, short h, short v)
{
	Rect		src;
	short		i;
	
	for (i = 0; i < numGrease; i++)
	{
		if ((grease[i].where == where) && (grease[i].who == who))
		{
			if ((grease[i].mode == kGreaseIdle) || (grease[i].mode == kGreaseFalling))
			{
				greasePtr greaseItem = &grease[i];
				const short hDelta = h - grease[i].dest.left;
				const short vDelta = v - grease[i].dest.top;
				QOffsetRect(&greaseItem->dest, hDelta, vDelta);
				greaseItem->start += hDelta;
				greaseItem->stop += hDelta;

				src = grease[i].dest;
				BackupGrease(&src, grease[i].mapNum, grease[i].isRight);
			}
			return (i);
		}
	}
	
	return (-1);
}

//--------------------------------------------------------------  AddGrease

// Called when a new room is being set up during a game.  This addsÉ
// another jar of grease to the queue of jars to be handled.

short AddGrease (short where, short who, short h, short v, 
		short distance, Boolean isRight)
{
	Rect		src, bounds;
	short		savedNum;
	
	if (numGrease >= kMaxGrease)
		return (-1);
	
	QSetRect(&src, 0, 0, 32, 27);
	QOffsetRect(&src, h, v);
	
	QSetRect(&bounds, 0, 0, 32, 27 * 4);
	savedNum = BackUpToSavedMap(&bounds, where, who, kDefaultComponent);
	if (savedNum != -1)
	{
		BackupGrease (&src, savedNum, isRight);
		if (isRight)
			QOffsetRect(&src, -8, 0);
		else
			QOffsetRect(&src, 8, 0);
		grease[numGrease].who = who;
		grease[numGrease].where = where;
		grease[numGrease].dest = src;
		grease[numGrease].mapNum = savedNum;
		grease[numGrease].mode = kGreaseIdle;
		grease[numGrease].frame = -1;
		if (isRight)
		{
			grease[numGrease].isRight = true;
			grease[numGrease].start = src.right + 4;
			grease[numGrease].stop = src.right + distance;
		}
		else
		{
			grease[numGrease].isRight = false;
			grease[numGrease].start = src.left - 4;
			grease[numGrease].stop = src.left - distance;
		}
		numGrease++;
		
		return (numGrease - 1);
	}
	else
		return (-1);
}

//--------------------------------------------------------------  SpillGrease

// A player has knocked a jar of grease over - this function flags that.

void SpillGrease (short who, short index)
{
	if (grease[who].mode == kGreaseIdle)
	{
		grease[who].mode = kGreaseFalling;
		grease[who].hotNum = index;
		PlayPrioritySound(kGreaseSpillSound, kGreaseSpillPriority);
	}
}

//--------------------------------------------------------------  RedrawAllGrease
// Called to redraw all the black lines of spilt grease.

void RedrawAllGrease (void)
{
	DrawSurface	*wasCPort;
	Rect		src;
	short		i;
	
	if (numGrease == 0)
		return;
	
	for (i = 0; i < numGrease; i++)
	{
		if (grease[i].mode == kGreaseIdle)
			continue;

		src = hotSpots[grease[i].hotNum].bounds;
		if ((grease[i].where == thisRoomNumber) && 
				((src.bottom - src.top) == 2))
		{
			PortabilityLayer::ResolveCachingColor blackColorBack = StdColors::Black();
			PortabilityLayer::ResolveCachingColor blackColorWork = StdColors::Black();

			QOffsetRect(&src, playOriginH, playOriginV);
			
			wasCPort = GetGraphicsPort();
			
			backSrcMap->FillRect(src, blackColorBack);
			
			workSrcMap->FillRect(src, blackColorWork);
			AddRectToWorkRects(&src);
			
			SetGraphicsPort(wasCPort);
		}
	}
}

void FixupFallenGrease(SInt16 where, SInt16 who, SInt16 h, SInt16 v, Boolean *isDynamic)
{
	short		i;

	for (i = 0; i < numGrease; i++)
	{
		greasePtr greaseItem = grease + i;
		if ((greaseItem->where == where) && (greaseItem->who == who))
		{
			short hDelta = h - greaseItem->dest.left;
			short vDelta = v - greaseItem->dest.top;
			QOffsetRect(&greaseItem->dest, hDelta, vDelta);
			greaseItem->start += hDelta;
			greaseItem->stop += hDelta;
			if (greaseItem->mode != kGreaseIdle)
			{
				hotPtr hotSpot = &hotSpots[greaseItem->hotNum];
				//QOffsetRect(&hotSpot->bounds, hDelta, vDelta);
			}
			*isDynamic = true;
			return;
		}
	}

	*isDynamic = false;
}

void RemapGreaseSavedMap(SInt16 removedItem, SInt16 substituteItem)
{
	for (int i = 0; i < numGrease; i++)
	{
		if (grease[i].mapNum == substituteItem)
		{
			grease[i].mapNum = removedItem;
			return;
		}
	}
}
