////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 RWS Inc, All Rights Reserved
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of version 2 of the GNU General Public License as published by
// the Free Software Foundation
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
// toolbar.cpp
// Project: Nostril (aka Postal)
//
// This module augments the CDude class, which used to be soley responsible for 
// updating player and weapon status.  It currently graphically manages the
// toolbars and sound reactions.  (Still need to add sounds)
////////////////////////////////////////////////////////////////////////////////
//
// History:
//
//		08/06/97 JRD	Started.  Set bars to load in the realm
//
//		08/08/97 JRD	Changed methodology to a proprietary data format and abandoning
//							attempts of a one to one interface with postal.  Tollbar will 
//							update an internal map of the weapon states based on events
//							passed.
//
//		08/08/97	JRD	Completely revamped and finalized the class structure.
//							Added the first hook to draw the entire bar.
//							Added aliased functions to reduce header dependencies.
//		08/09/97	JRD	Added all functionality except a hook to refresh on event.
//
//		08/10/97	JRD	Added two deferred update modes.  One limits updates to a 
//							given time interval, and the other only updates when a 
//							change of value or state has occurred.  All this occurs
//							without any interaction with the app.
//
//		08/10/97	JRD	Added hook so powerup values resetting due to time would
//							be a valid draw event.
//
//		08/10/97	JRD	Based on Steve Wik's opinion, I set health and vest to 
//							show well over 100%.  Since people liked it, it was actually
//							my opinion and I shall keep it.
//
//		08/10/97	JRD	Added a dangerous cross file help to poor old score in order
//							to easily color map the top toolbar.  Poor score.  Set to Steve
//							colors.  If you think their cool, then I too agreed with Steve. 
//							If not, then Steve forced me to use them.
//
//		08/12/97	JRD	Changed the class o the Mac can deal with it.
//
//		08/29/97	JRD	Patched Render to not display amount of bullets.
//
//		09/27/99	JMI	Eliminated boolean performance warnings.
//
////////////////////////////////////////////////////////////////////////////////
#include "RSPiX.h"
#include "dude.h"
#include "StockPile.h"
#include "hood.h"
#include "toolbar.h"
#include "ORANGE/color/colormatch.h"
#include "ORANGE/color/dithermatch.h"
////////////////////////////////////////////////////////////////////////////////
// TOOLBAR Graphic parameters:
////////////////////////////////////////////////////////////////////////////////


#include "pvr.h"


//=================== toolbar templates (loaded each level) ====================

//=====================  General Toolbar Parameters  ===========================
#define	TB_BAR_X	0				// where to draw the entire bar
#define	TB_BAR_Y	440

#define	TB_TWEAK_FONT_Y		-5
#define	TB_TWEAK_FONT_X		-3

#define  TB_SMALL_FONT			11		// pixel height for ammo font
#define	TB_LARGE_FONT			15		// for health and armour

#define	TB_AMMOW_LOW	3			// ammo changes color as warning
#define	TB_MILLI_TO_LITE	3000	// after you get a powerup.

//#ifdef MOBILE
#if 1
#define TB_MILLI_INTERVAL_TIME	100 //500ms lag is pretty annoying!
#else
#define	TB_MILLI_INTERVAL_TIME	500	// maximum update rate, unless forced
#endif

#define CALC_ALPHA(input)	 				\
	switch	(input.m_eState) {				\
		case Full:							\
			alpha = .5f;					\
			break;							\
		case FullSel:						\
			alpha = 1.0f;					\
			break;							\
		default:							\
			alpha = 0.f;					\
		break;								\
	}

#define DRAW_ITEM(input, layer) \
	sItemX = sDstX + (input.m_rImage.sX - sIconOffset); \
	/* Fully visible */ \
	if (sItemX >= sDstX && sItemX + input.m_rImage.sW <= sDstX + sWidth + 10) \
	{\
		g_pvrRenderer->DrawQuadDirect( tex, 0, input.m_fStartU,	input.m_fStartV, input.m_fEndU,	input.m_fEndV, sItemX, sDstY + input.m_rImage.sY,\
		 input.m_rImage.sW, input.m_rImage.sH, layer + cLayerOffset, alpha, PACK_ARGB8888(uint8_t(255.f * alpha), R, G, B));\
	}\
	else /* Partially visible */ \
	{\
		int16_t sItemEndX = sItemX + input.m_rImage.sW; \
		int16_t sWindowEndX = sDstX + sWidth; \
		if (sItemX < sDstX && sItemEndX > sDstX) {\
			int16_t sDiff = sDstX - sItemX;\
			sItemX += sDiff + 10;\
			int16_t d = (sItemEndX - sItemX);	\
			if (sItemX>sDstX && d > 0)\
			{\
			float startU = rspFastDiv((input.m_fEndU * 1024.f) - d, 1024.f);\
			g_pvrRenderer->DrawQuadDirect( tex, 0, startU,	input.m_fStartV, input.m_fEndU,	input.m_fEndV, sItemX, sDstY + input.m_rImage.sY,\
		 		d, input.m_rImage.sH, layer + cLayerOffset, alpha, PACK_ARGB8888(uint8_t(255.f * alpha), R, G, B));\
			}\
		}\
		if (sItemX-10 < sWindowEndX && sItemEndX +10 >sWindowEndX) \
		{\
			int16_t sDiff = sItemEndX - sWindowEndX;\
			sItemEndX -= sDiff;\
			int16_t d = (sWindowEndX - sItemX) + 10;	\
			if (d > 0)\
			{\
			float endU = rspFastDiv((input.m_fStartU * 1024.f) + d, 1024.f);\
			g_pvrRenderer->DrawQuadDirect( tex, 0, input.m_fStartU, input.m_fStartV, endU, input.m_fEndV, sItemX, sDstY + input.m_rImage.sY,\
		 		d, input.m_rImage.sH, layer + cLayerOffset, alpha, PACK_ARGB8888(uint8_t(255.f * alpha), R, G, B));\
			}\
		}\
	}

	

extern RFont g_fontBig;	// I hope this one is OK....

typedef	struct { uint8_t r; uint8_t g; uint8_t b; } MatchColor;

MatchColor	gmcSmallFont = { 255,255,0 };	// yellow
MatchColor	gmcLargeFont = { 255,255,0 };	// yellow
MatchColor	gmcWarningFont = { 255,0,0 };	// red
MatchColor	gmcAmmoGoneFont = { 96,0,0 };	// dark red
MatchColor	gmcAttentionFont = { 255,255,128 };	// saturated yellow

//------------------ Top Bar:
MatchColor	gmcSolidScore = { 40,34,13 };	// saturated yellow
MatchColor	gmcShadowScore = { 138,123,65 };	// saturated yellow

//------------------ So Score can access these:
int16_t gsStatusFontForeIndex	=	251;
int16_t gsStatusFontBackIndex	=	0;
int16_t gsStatusFontShadowIndex	=	0;
int16_t gsStatusFontForeDeadIndex = 252;


// todo: clean up
extern PVR::cRenderMgr *g_pvrRenderer;

//=====================================================================
//===========  INTERNAL VISUAL STOCKPILE CONTROLS  ====================
//=====================================================================

// I am abandoning the previous idea of linking my own definition
// of weapons and ammo to postal's, as they are too incompatible
// for a direct interface.  I am therefor switching to a proprietary one.

// Local definition of a "WEAPON":  Does NOT have an associated number
// Local definition of an "AMMO":	Has a number amount.

// Proprietary formats:
typedef	enum
	{
	NotWeapon = 0,
	MachineGun,
	ShotGun,
	SprayCannon,
	MissileLauncher,
	NapalmLauncher,
	FlameThrower,
	NumberOfWeapons
	}	ToolWeaponType;


typedef	enum
	{
	NotAmmo = 0,
	Health,
	KevlarVest,
	Bullets,
	Shells,
	Spray,		// proprietary = Bullets
	Grenades,
	Rockets,
	HeatSeekers,// proprietary = Heatseekers
	Cocktails,
	Napalm,
	Fuel,
	ProximityMine, // all three alias to the same amount of mines!
	TimedMine, 
	BouncingBettyMine,
	NumberOfAmmos
	}	ToolAmmoType;

// NOTE: The concept is that, in general, you select an AMMO, and the weapon
// highlights dependently.
//
class	CToolItem
	{
public:
	//----------------------------------------------------------------------
	typedef enum { Uninitialized = 0, Weapon , Ammo } Type;
	typedef enum { Bar = 0, BarSel = 1, Full = 2, FullSel = 3 } State;
	typedef enum { Small = 0, Large } Size;
	//----------------------------------------------------------------------
	Type	m_eType;
	bool	m_bExists;		// bar or full?
	bool	m_bSelected;	// selected or not?
	bool	m_bTreasure;	// found in a power up
	int32_t	m_lMilli;		// relative time in milliseconds for timing stuff
	State	m_eState;		// short cut for applying state
	State	m_ePrevState;	// Stored for event triggering
	double	m_dValue;		// if ammo
	double	m_dPrevValue;	// if ammo
	double	m_dLow;			// value change
	Size	m_eFontType;	// for color and display
	RRect	m_rImage;		// location of icon, if applicable
	RRect 	m_rText;		// location of text, if applicable
	float 	m_fStartU;
	float 	m_fStartV;
	float 	m_fEndU;
	float 	m_fEndV;

	//----------------------------------------------------------------------
	CToolItem*	m_pWeapon;	// Links to associated weapon
	CToolItem*	m_pAmmo1;	// Links to associated ammo for drawing order
	CToolItem*	m_pAmmo2;	// Links to associated ammo for drawing order
	//----------------------------------------------------------------------
	ToolWeaponType			m_eWeaponType;
	ToolAmmoType			m_eAmmoType;
	CDude::WeaponType		m_eStockPile;	// Postal app equivalent from Dude.h
	//----------------------------------------------------------------------
	static CToolItem* ms_aWeapons; // [NumberOfWeapons];
	static CToolItem* ms_aAmmo; //[NumberOfAmmos];
	static	RFont*	ms_pfntTool;		// General font and print
	static	RPrint	ms_pntTool;
	static	int16_t		ms_sSmallFontColor;	// color index
	static	int16_t		ms_sLargeFontColor;
	static	int16_t		ms_sWarningColor;
	static	int16_t		ms_sAmmoGoneColor;
	static	int16_t		ms_sAttentionColor;	
	static	int32_t		ms_lLastTime;	
	static  uint32_t	ms_ulPlayerIndicator;
	static  int16_t		ms_sPlayerNum;
	//----------------------------------------------------------------------
	CToolItem()
		{
		m_eType = Uninitialized;
		m_bExists = false;
		m_bSelected = false;
		m_bTreasure = false;
		m_lMilli = 0;
		m_eState = Bar;
		m_dValue = 0.0;
		m_dPrevValue = 0.0;
		m_dLow = 0;
		m_eFontType = Small;
		m_pWeapon = m_pAmmo1 = m_pAmmo2 = NULL;
		m_eWeaponType = NotWeapon;
		m_eAmmoType = NotAmmo;
		m_eStockPile = CDude::NoWeapon;
		m_fStartU = m_fStartV = m_fEndU = m_fEndV = 0.f;
		}

	~CToolItem()	
		{ 
		}

	// This sets most members in a generic way for a weapon
	// It can add members if more differentiation is needed
	void	ArrangeWeapon(
		ToolWeaponType eType,
		CDude::WeaponType eStock,
		const RRect &prImage,
		float fStartU,
		float fStartV,
		float fEndU,
		float fEndV,
		CToolItem*	pAmmo1,
		CToolItem*	pAmmo2 = NULL,
		CToolItem*	pAmmo3 = NULL)
		{
		m_eWeaponType = eType;
		m_eStockPile = eStock;
		m_rImage = prImage;
		m_fStartU = fStartU;
		m_fStartV = fStartV;
		m_fEndU = fEndU;
		m_fEndV = fEndV;
		m_pWeapon = pAmmo1;
		m_pAmmo1 = pAmmo2;
		m_pAmmo2 = pAmmo3;
		//-------------------- Weapon specific:
		m_eType = Weapon;
		}

	void	ArrangeAmmo(
		ToolAmmoType eType,
		CDude::WeaponType eStock,
		const RRect &prImage,
		float fStartU,
		float fStartV,
		float fEndU,
		float fEndV,
		int16_t sTextX,
		int16_t sTextY,
		CToolItem*	pWeapon,
		Size		eSize = Small)
		{
		m_eAmmoType = eType;
		m_eStockPile = eStock;
		m_rImage = prImage;
		m_fStartU = fStartU;
		m_fStartV = fStartV;
		m_fEndU = fEndU;
		m_fEndV = fEndV;
		m_pWeapon = pWeapon;
		m_rText.sX = sTextX;
		m_rText.sY = sTextY;
		m_eFontType = eSize;
		//-------------------- Weapon specific:
		m_eType = Ammo;
		m_dLow = 3.0;	// General state for alert point
		}

	//=======================================================================
	static int16_t	Init(CHood* pHood)	// do color matching & asset loading
		{
		// Use the current hood palette to color match the text indicies
		ms_sSmallFontColor = rspMatchColorRGB(
		gmcSmallFont.r,gmcSmallFont.g,gmcSmallFont.b,10,236,
		g_pvrRenderer->m_pPaletteDefault->Red(),
		g_pvrRenderer->m_pPaletteDefault->Green(),
		g_pvrRenderer->m_pPaletteDefault->Blue(),4);

		ms_sLargeFontColor = rspMatchColorRGB(
		gmcLargeFont.r,gmcLargeFont.g,gmcLargeFont.b,10,236,
		g_pvrRenderer->m_pPaletteDefault->Red(),
		g_pvrRenderer->m_pPaletteDefault->Green(),
		g_pvrRenderer->m_pPaletteDefault->Blue(),4);

		ms_sWarningColor = rspMatchColorRGB(
		gmcWarningFont.r,gmcWarningFont.g,gmcWarningFont.b,10,236,
		g_pvrRenderer->m_pPaletteDefault->Red(),
		g_pvrRenderer->m_pPaletteDefault->Green(),
		g_pvrRenderer->m_pPaletteDefault->Blue(),4);

		ms_sAmmoGoneColor = rspMatchColorRGB(
		gmcAmmoGoneFont.r,gmcAmmoGoneFont.g,gmcAmmoGoneFont.b,10,236,
		g_pvrRenderer->m_pPaletteDefault->Red(),
		g_pvrRenderer->m_pPaletteDefault->Green(),
		g_pvrRenderer->m_pPaletteDefault->Blue(),4);

		ms_sAttentionColor = rspMatchColorRGB(
		gmcAttentionFont.r,gmcAttentionFont.g,gmcAttentionFont.b,10,236,
		g_pvrRenderer->m_pPaletteDefault->Red(),
		g_pvrRenderer->m_pPaletteDefault->Green(),
		g_pvrRenderer->m_pPaletteDefault->Blue(),4);

		//----------------------------- Match Top bar stuff:
		gsStatusFontForeIndex = rspMatchColorRGB(
		gmcSolidScore.r,gmcSolidScore.g,gmcSolidScore.b,10,236,
		g_pvrRenderer->m_pPaletteDefault->Red(),
		g_pvrRenderer->m_pPaletteDefault->Green(),
		g_pvrRenderer->m_pPaletteDefault->Blue(),4);

		gsStatusFontShadowIndex = rspMatchColorRGB(
		gmcShadowScore.r,gmcShadowScore.g,gmcShadowScore.b,10,236,
		g_pvrRenderer->m_pPaletteDefault->Red(),
		g_pvrRenderer->m_pPaletteDefault->Green(),
		g_pvrRenderer->m_pPaletteDefault->Blue(),4);

		ms_pfntTool = &g_fontBig;

		ms_pntTool.SetFont(TB_SMALL_FONT,ms_pfntTool);
		ms_pntTool.SetColumn(0,0,640,480);
		
		return SUCCESS;
		}

	
	// Assume the entire bar needs to be redrawn.
	static void	RenderBar(CHood* pHood, int16_t sDstX, int16_t sDstY, bool bMinimal, int8_t cLayerOffset = 0)
		{							
		uint8_t R = uint8_t(255.f * g_pvrRenderer->m_fGlobalRScale);
		uint8_t G = uint8_t(255.f * g_pvrRenderer->m_fGlobalGScale);
		uint8_t B = uint8_t(255.f * g_pvrRenderer->m_fGlobalBScale);		
		uint32_t baseColour = 0xFFFFFFFF;
		int16_t sWidth = 640;
		float alpha = 1.f;
		float fStartU = 0.f;
		float fEndU = 0.271f;
		float fUVOffset = 0.f;
		int16_t sItemX = 0;
		int16_t sIconOffset = 0;		
		int16_t sAmmoOffsets[NumberOfAmmos] = {0};

		// todo: This is all messy as hell

		if (g_pvrRenderer->m_fGlobalRScale != 1.0f || g_pvrRenderer->m_fGlobalGScale != 1.f || g_pvrRenderer->m_fGlobalBScale != 1.f)
		{
			baseColour = PACK_ARGB8888(255, R, G, B);
		}

		// Toolbar background
		PVR::cTexture *tex = g_pvrRenderer->m_TextureRepository.Get(PVR_TEXTURE_TOOLBAR);

		if (bMinimal)
		{						
			sIconOffset = 109;

			if (g_cPlayerCount == 2)
			{								
				sWidth = 310;				
			}

			if (g_cPlayerCount == 3)
			{								
				sWidth = 203;									
			}

			if (g_cPlayerCount == 4)
			{								
				sWidth = 150;										
			}

			sDstX += (sWidth * ms_sPlayerNum) + (10 * ms_sPlayerNum);

			if (g_cPlayerCount == 3 && ms_sPlayerNum == 2)
			{												
				sWidth = 204;
			}

			fStartU = 0.115f;
			fEndU = fStartU + rspFastDiv(float(sWidth), 1024.f);
		}		

		// Toolbar underlay
		g_pvrRenderer->DrawQuadDirect(
			uint32_t(PACK_ARGB8888(255,0,0,0)),
			sDstX,
			sDstY, 
			640, 
			40,
			33 + cLayerOffset
		);			

		if (!bMinimal)		
		{
			// Full-length toolbar
			g_pvrRenderer->DrawQuadDirect(
				tex, 
				0, 
				0.0, 
				0.0, 
				0.625, 
				0.625, 
				sDstX,
				sDstY, 
				sWidth, 
				40,
				34,
				1.f, baseColour);

			// Health
			if (ms_aAmmo[Health].m_eState == Full)
			{
				g_pvrRenderer->DrawQuadDirect(
					tex, 0, 
					ms_aAmmo[Health].m_fStartU,
					ms_aAmmo[Health].m_fStartV,
					ms_aAmmo[Health].m_fEndU,
					ms_aAmmo[Health].m_fEndV,
					sDstX + ms_aAmmo[Health].m_rImage.sX,
					sDstY + ms_aAmmo[Health].m_rImage.sY,
					ms_aAmmo[Health].m_rImage.sW,
					ms_aAmmo[Health].m_rImage.sH,
					35,
					1.f, baseColour
				);				
			}

			// Armor
			if (ms_aAmmo[KevlarVest].m_eState == Full)
			{
				g_pvrRenderer->DrawQuadDirect(
					tex, 0, 
					ms_aAmmo[KevlarVest].m_fStartU,
					ms_aAmmo[KevlarVest].m_fStartV,
					ms_aAmmo[KevlarVest].m_fEndU,
					ms_aAmmo[KevlarVest].m_fEndV,
					sDstX + ms_aAmmo[KevlarVest].m_rImage.sX,
					sDstY + ms_aAmmo[KevlarVest].m_rImage.sY,
					ms_aAmmo[KevlarVest].m_rImage.sW,
					ms_aAmmo[KevlarVest].m_rImage.sH,
					35, 1.f, baseColour
				);
			}
		}
		else
		{			
			// Character colour		
			g_pvrRenderer->DrawQuadDirect(
				ms_ulPlayerIndicator,
				sDstX,
				sDstY, 
				10, 
				40,
				38 + cLayerOffset
			);
												
			ms_pntTool.SetFont(TB_SMALL_FONT, ms_pfntTool);
			ms_pntTool.m_bColourFixed = false;

			if (g_pvrRenderer->m_fGlobalRScale != 1.0f || g_pvrRenderer->m_fGlobalGScale != 1.f || g_pvrRenderer->m_fGlobalBScale != 1.f)
			{				
				ms_pntTool.SetColorRGB(
					uint8_t(255.f * g_pvrRenderer->m_fGlobalRScale),
					uint8_t(255.f * g_pvrRenderer->m_fGlobalGScale),
					uint8_t(255.f * g_pvrRenderer->m_fGlobalBScale));					
			}
			else
			{
				ms_pntTool.SetColorRGB(255, 255, 255);
			}
			
			ms_pntTool.offsetX = sDstX + 3;			
			ms_pntTool.printPVR(
				0,
				449,
				"P\n%d",
				ms_sPlayerNum + 1
			);

			if (g_cPlayerCount == 2)
			{			
				if (ms_aAmmo[Cocktails].m_eState == FullSel ||
				 ms_aWeapons[NapalmLauncher].m_eState == FullSel || ms_aWeapons[FlameThrower].m_eState == FullSel || ms_aAmmo[BouncingBettyMine].m_eState == FullSel ||
				ms_aAmmo[ProximityMine].m_eState == FullSel ||
				ms_aAmmo[TimedMine].m_eState == FullSel)
				{
					fUVOffset = 0.195f;
					sIconOffset += 199;
				}
			}


			if (g_cPlayerCount == 3)
			{															
				if (ms_aWeapons[MissileLauncher].m_eState == FullSel || ms_aAmmo[Cocktails].m_eState == FullSel)
				{
					fUVOffset = 0.148f;
					sIconOffset += 151;					
				}
							
				if (ms_aWeapons[NapalmLauncher].m_eState == FullSel)
				{
					fUVOffset = 0.291f;
					sIconOffset += 297;
				}
								
				if (ms_aWeapons[FlameThrower].m_eState == FullSel || ms_aAmmo[BouncingBettyMine].m_eState == FullSel ||
				ms_aAmmo[ProximityMine].m_eState == FullSel ||
				ms_aAmmo[TimedMine].m_eState == FullSel)
				{
					fUVOffset = 0.311f;
					sIconOffset += 318;
				}	
			}

			if (g_cPlayerCount == 4)
			{					
				if (ms_aWeapons[MachineGun].m_eState == FullSel ||
					ms_aWeapons[ShotGun].m_eState == FullSel)
				{				
					fUVOffset = 0.0f;
					sIconOffset = 109;					
				}
				
				if (ms_aWeapons[SprayCannon].m_eState == FullSel ||
				 	ms_aAmmo[Grenades].m_eState == FullSel)
				{				
					fUVOffset = 0.053f;
					sIconOffset += 55;											
				}

				if (ms_aWeapons[MissileLauncher].m_eState == FullSel)
				{
					fUVOffset = 0.148f;
					sIconOffset += 152;					
				}
			
				if (ms_aAmmo[Cocktails].m_eState == FullSel ||
				 ms_aWeapons[NapalmLauncher].m_eState == FullSel)
				{
					fUVOffset = 0.253f;
					sIconOffset += 258;
				}

				if (ms_aWeapons[FlameThrower].m_eState == FullSel)
				{
					fUVOffset = 0.341f;
					sIconOffset += 349;
				}

				if (ms_aAmmo[BouncingBettyMine].m_eState == FullSel ||
				ms_aAmmo[ProximityMine].m_eState == FullSel ||
				ms_aAmmo[TimedMine].m_eState == FullSel)
				{
					fUVOffset = 0.363f;
					sIconOffset += 371;
				}
			}
								
			// Partial toolbar
			g_pvrRenderer->DrawQuadDirect(
				tex, 0, 
				fStartU + fUVOffset, 0.f,
				fEndU + fUVOffset, 0.625f,
				sDstX + 10,	sDstY, 
				sWidth, 40,
				34 + cLayerOffset,
				1.f, baseColour
			);
		}
		
		// Machine gun		
		CALC_ALPHA(ms_aWeapons[MachineGun]);
		DRAW_ITEM(ms_aWeapons[MachineGun], 35);
						
		// bullets
		CALC_ALPHA(ms_aAmmo[Bullets]);		
		DRAW_ITEM(ms_aAmmo[Bullets], 36);

		// Shotgun
		CALC_ALPHA(ms_aWeapons[ShotGun]);
		DRAW_ITEM(ms_aWeapons[ShotGun], 35);

		// shells 1		
		CALC_ALPHA(ms_aAmmo[Shells]);
		DRAW_ITEM(ms_aAmmo[Shells], 36);		
		sAmmoOffsets[Shells] = sIconOffset - sDstX;
		
		// Spray cannon
		CALC_ALPHA(ms_aWeapons[SprayCannon]);
		DRAW_ITEM(ms_aWeapons[SprayCannon], 35);
				
		// Spray		
		CALC_ALPHA(ms_aAmmo[Spray]);
		DRAW_ITEM(ms_aAmmo[Spray], 36);		
		sAmmoOffsets[Spray] = sIconOffset - sDstX;

		// Grenade					
		CALC_ALPHA(ms_aAmmo[Grenades]);
		DRAW_ITEM(ms_aAmmo[Grenades], 36);		
		sAmmoOffsets[Grenades] = sIconOffset - sDstX;
	
		// Rocket launcher
		CALC_ALPHA(ms_aWeapons[MissileLauncher]);
		DRAW_ITEM(ms_aWeapons[MissileLauncher], 35);
				
		// Rocket 1		
		CALC_ALPHA(ms_aAmmo[Rockets]);
		DRAW_ITEM(ms_aAmmo[Rockets], 36);
		sAmmoOffsets[Rockets] = sIconOffset - sDstX;

		// Heatseekers		
		CALC_ALPHA(ms_aAmmo[HeatSeekers]);
		DRAW_ITEM(ms_aAmmo[HeatSeekers], 36);
		sAmmoOffsets[HeatSeekers] = sIconOffset - sDstX;
		
		// Molotov		
		CALC_ALPHA(ms_aAmmo[Cocktails]);
		DRAW_ITEM(ms_aAmmo[Cocktails], 36);
		sAmmoOffsets[Cocktails] = sIconOffset - sDstX;
	
		// Napalm launcher			
		CALC_ALPHA(ms_aWeapons[NapalmLauncher]);
		DRAW_ITEM(ms_aWeapons[NapalmLauncher], 35);

		// Napalm		
		CALC_ALPHA(ms_aAmmo[Napalm]);
		DRAW_ITEM(ms_aAmmo[Napalm], 36);
		sAmmoOffsets[Napalm] = sIconOffset - sDstX;

		// Flame thrower		
		CALC_ALPHA(ms_aWeapons[FlameThrower]);
		DRAW_ITEM(ms_aWeapons[FlameThrower], 35);
		
		// Fuel		
		CALC_ALPHA(ms_aAmmo[Fuel]);
		DRAW_ITEM(ms_aAmmo[Fuel], 36);
		sAmmoOffsets[Fuel] = sIconOffset - sDstX;

		// Mines
		CALC_ALPHA(ms_aAmmo[BouncingBettyMine]);
		DRAW_ITEM(ms_aAmmo[BouncingBettyMine], 36);
		sAmmoOffsets[BouncingBettyMine] = sIconOffset - sDstX;
	
		CALC_ALPHA(ms_aAmmo[ProximityMine]);
		DRAW_ITEM(ms_aAmmo[ProximityMine], 36);
		sAmmoOffsets[ProximityMine] = sIconOffset - sDstX;

		CALC_ALPHA(ms_aAmmo[TimedMine]);
		DRAW_ITEM(ms_aAmmo[TimedMine], 36);
		sAmmoOffsets[TimedMine] = sIconOffset - sDstX;		

		// Text
		// Finally, print all the values...
		for (int16_t i = NotAmmo + 1; i < NumberOfAmmos; i++)
			{
			int16_t sFontSize;
			int16_t	sFontColor;

			if (i == ProximityMine || i == TimedMine)
			{				
				continue;
			}

			// choose the correct font.
			if (ms_aAmmo[i].m_eFontType == Small)
				{
				sFontSize = TB_SMALL_FONT;
				sFontColor = ms_sSmallFontColor;
				}
			else
				{
				sFontSize = TB_LARGE_FONT;
				sFontColor = ms_sLargeFontColor;
				}

			// Update the attention color time:
		   if (ms_aAmmo[i].m_bTreasure)
				{
				if ( (rspGetMilliseconds() - ms_aAmmo[i].m_lMilli) >
					TB_MILLI_TO_LITE)
					{
					// no longer highlighted:
					ms_aAmmo[i].m_bTreasure = false;
					}
				}

			// check for special color conditions:
			if (ms_aAmmo[i].m_dValue <= 0.1) sFontColor = ms_sAmmoGoneColor;
			else if (ms_aAmmo[i].m_bTreasure) sFontColor = ms_sAttentionColor;
			else if (ms_aAmmo[i].m_dValue <= ms_aAmmo[i].m_dLow)
					sFontColor = ms_sWarningColor;

			// select the correct font and draw the amount:
			ms_pntTool.SetFont(sFontSize,ms_pfntTool);
			ms_pntTool.m_bColourFixed = false;
			
			if (ms_aAmmo[i].m_bSelected || (i == BouncingBettyMine && (ms_aAmmo[ProximityMine].m_bSelected || ms_aAmmo[TimedMine].m_bSelected)))
			{			
				ms_pntTool.SetColor(250);
			}
			else
			{
				ms_pntTool.SetColor(sFontColor);
			}
			
			if (bMinimal)
			{													
				if (i != Bullets && i > 2)
				{											
					if (ms_aAmmo[i].m_rImage.sX - sAmmoOffsets[i] > sDstX &&
						((ms_aAmmo[i].m_rImage.sX + ms_aAmmo[i].m_rImage.sW) - sAmmoOffsets[i]) <= sDstX + sWidth + 10)					
					{
						ms_pntTool.offsetX = -sAmmoOffsets[i];
						ms_pntTool.m_cLayerOffset = -4;	// Push the text back
						ms_pntTool.printPVR(
							//sItemX,							
							ms_aAmmo[i].m_rText.sX,
							ms_aAmmo[i].m_rText.sY,
							"%3ld",
							int32_t(ms_aAmmo[i].m_dValue)
						);
						ms_pntTool.m_cLayerOffset = 0;
					}				
				}
				else if (i == Bullets && ms_aAmmo[i].m_bSelected)
				{	
					g_pvrRenderer->DrawQuadDirect(
						g_pvrRenderer->m_TextureRepository.Get(PVR_TEXTURE_TOOLBAR),
						0, 
						0.107421875f,
						0.90625f, 
						0.1171875f,
						1.f,																
						sDstX + 44,
						466,
						10, 6,
						40 + cLayerOffset, 
						alpha, 
						PACK_ARGB8888(255, R, G, B)
					);												
				}
			}
			else
			{			
				if (i != Bullets)	// nolonger print the amount of bullets...			
				{	
					ms_pntTool.offsetX = 0;							
					ms_pntTool.printPVR(
						ms_aAmmo[i].m_rText.sX,
						ms_aAmmo[i].m_rText.sY,
						"%3ld",
						int32_t(ms_aAmmo[i].m_dValue)
					);
				}
				else 
				{	
					if (ms_aAmmo[i].m_bSelected)			
					g_pvrRenderer->DrawQuadDirect(
						g_pvrRenderer->m_TextureRepository.Get(PVR_TEXTURE_TOOLBAR),
						0, 
						0.107421875f,
						0.90625f, 
						0.1171875f,
						1.f,
						//sItemX,
						ms_aAmmo[i].m_rText.sX + 6,
						ms_aAmmo[i].m_rText.sY + 4,					
		 				10, 6,
						35 + cLayerOffset, 
						alpha, 
						PACK_ARGB8888(255, R, G, B)
					);
				}
			}
		}
	}

	// Handle dude events, including graphical updates
	// Wil return true if a change of state has occurred
	static bool	UpdateStatus(CDude* pDude)
		{
		// Fist, try to get all the status possible from the CDude:
		// Use the stockpile for most:
		int16_t i;
			
		// Get the current values from the stockpile:
		// Because GetWeaponInfo goes by weapon to recieve ammo,
		// we need to check ammo directly:

		//==========================================================================
		// Save the old ammo amounts and ammo state:
		for (i = NotAmmo + 1; i < NumberOfAmmos; i++)
			{
			// do this to catch powerups or ammot changes:
			ms_aAmmo[i].m_dPrevValue = ms_aAmmo[i].m_dValue;
			ms_aAmmo[i].m_ePrevState = ms_aAmmo[i].m_eState;
			}

		// Save the states of all the weapons:
		for (i = NotWeapon + 1; i < NumberOfWeapons; i++)
			{
			// do this to catch powerups or ammot changes:
			ms_aWeapons[i].m_ePrevState = ms_aWeapons[i].m_eState;
			}
		//==========================================================================

		// Hit points must be translated into a percentage of the whole:
		ms_aAmmo[Health].m_dValue = rspSlowDiv(float(pDude->m_stockpile.m_sHitPoints) * 100.f, pDude->m_sOrigHitPoints);

		if ( (ms_aAmmo[Health].m_dValue > 0.0) && (ms_aAmmo[Health].m_dValue < 1.0) )
		{
			ms_aAmmo[Health].m_dValue = 1.0;
		}

		if (pDude->IsDead()) ms_aAmmo[Health].m_dValue = 0.0;

		ms_aAmmo[KevlarVest].m_dValue = rspSlowDiv(float(pDude->m_stockpile.m_sKevlarLayers), 5.0f);
		//if (ms_aAmmo[KevlarVest].m_dValue > 100.0) ms_aAmmo[KevlarVest].m_dValue = 100.0;

		ms_aAmmo[Bullets].m_dValue = pDude->m_stockpile.m_sNumBullets;
		ms_aAmmo[Shells].m_dValue = pDude->m_stockpile.m_sNumShells;
		ms_aAmmo[Spray].m_dValue = pDude->m_stockpile.m_sNumShells;
		ms_aAmmo[Grenades].m_dValue = pDude->m_stockpile.m_sNumGrenades;
		ms_aAmmo[Rockets].m_dValue = pDude->m_stockpile.m_sNumMissiles;
		ms_aAmmo[HeatSeekers].m_dValue = pDude->m_stockpile.m_sNumHeatseekers;
		ms_aAmmo[Cocktails].m_dValue = pDude->m_stockpile.m_sNumFireBombs;
		ms_aAmmo[Napalm].m_dValue = pDude->m_stockpile.m_sNumNapalms;
		// todo: fast divide?
		ms_aAmmo[Fuel].m_dValue = double(pDude->m_stockpile.m_sNumFuel)/2.50;
		ms_aAmmo[ProximityMine].m_dValue = pDude->m_stockpile.m_sNumMines;
		ms_aAmmo[TimedMine].m_dValue = pDude->m_stockpile.m_sNumMines;
		ms_aAmmo[BouncingBettyMine].m_dValue = pDude->m_stockpile.m_sNumMines;

		// Which weapons do I have?
		ms_aWeapons[MachineGun].m_bExists = (pDude->m_stockpile.m_sMachineGun) ? true : false;
		ms_aWeapons[ShotGun].m_bExists = (pDude->m_stockpile.m_sShotGun) ? true : false;
		ms_aWeapons[SprayCannon].m_bExists = (pDude->m_stockpile.m_sSprayCannon) ? true : false;
		ms_aWeapons[MissileLauncher].m_bExists = (pDude->m_stockpile.m_sMissileLauncher) ? true : false;
		ms_aWeapons[NapalmLauncher].m_bExists = (pDude->m_stockpile.m_sNapalmLauncher) ? true : false;
		ms_aWeapons[FlameThrower].m_bExists = (pDude->m_stockpile.m_sFlameThrower) ? true : false;

		// Mark those ammos that have gone up
		for (i = NotAmmo + 1; i < NumberOfAmmos; i++)
			{
			// do this to catch powerups or ammot changes:
			if (ms_aAmmo[i].m_dPrevValue < ms_aAmmo[i].m_dValue)
				{
				ms_aAmmo[i].m_bTreasure = true;
				ms_aAmmo[i].m_lMilli = rspGetMilliseconds();
				}
			}

		// Note that throwing ammo exists if ammo is not zero

		for (i = NotAmmo + 1; i < NumberOfAmmos; i++)
			{
			ms_aAmmo[i].m_bExists = (ms_aAmmo[i].m_dValue > 0.01);
			ms_aAmmo[i].m_bSelected = FALSE;	// initializing
			}

		// Clear out all selections:
		for (i = NotWeapon + 1; i < NumberOfWeapons; i++)
			{
			ms_aWeapons[i].m_bSelected = FALSE;
			}

		// Which weapon is currently selected?
		// (I guess this is a scheme)
		CDude::WeaponType CurWeapon = pDude->GetCurrentWeapon();

		switch (CurWeapon)
			{
			case CDude::SemiAutomatic:
				ms_aWeapons[MachineGun].m_bSelected = true;
				ms_aAmmo[Bullets].m_bSelected = true;
				break;
			case CDude::ShotGun:
				ms_aWeapons[ShotGun].m_bSelected = true;
				ms_aAmmo[Shells].m_bSelected = true;
				break;
			case CDude::SprayCannon:
				ms_aWeapons[SprayCannon].m_bSelected = true;
				ms_aAmmo[Spray].m_bSelected = true;
				break;
			case CDude::Grenade:
				ms_aAmmo[Grenades].m_bSelected = true;
				break;
			case CDude::Rocket:
				ms_aWeapons[MissileLauncher].m_bSelected = true;
				ms_aAmmo[Rockets].m_bSelected = true;
				break;
			case CDude::Heatseeker:
				ms_aWeapons[MissileLauncher].m_bSelected = true;
				ms_aAmmo[HeatSeekers].m_bSelected = true;
				break;
			case CDude::FireBomb:
				ms_aAmmo[Cocktails].m_bSelected = true;
				break;
			case CDude::Napalm:
				ms_aWeapons[NapalmLauncher].m_bSelected = true;
				ms_aAmmo[Napalm].m_bSelected = true;
				break;
			case CDude::FlameThrower:
				ms_aWeapons[FlameThrower].m_bSelected = true;
				ms_aAmmo[Fuel].m_bSelected = true;
				break;
			case CDude::ProximityMine:
				ms_aAmmo[ProximityMine].m_bSelected = true;
				break;
			case CDude::TimedMine:
				ms_aAmmo[TimedMine].m_bSelected = true;
				break;
			case CDude::BouncingBettyMine:
				ms_aAmmo[BouncingBettyMine].m_bSelected = true;
				break;
			case CDude::DeathWad:
				ms_aWeapons[MachineGun].m_bSelected = true;
				ms_aWeapons[ShotGun].m_bSelected = true;
				ms_aWeapons[SprayCannon].m_bSelected = true;
				ms_aWeapons[MissileLauncher].m_bSelected = true;
				ms_aWeapons[NapalmLauncher].m_bSelected = true;
				ms_aWeapons[FlameThrower].m_bSelected = true;
				ms_aAmmo[Bullets].m_bSelected = true;
				ms_aAmmo[Shells].m_bSelected = true;
				ms_aAmmo[Spray].m_bSelected = true;
				ms_aAmmo[Grenades].m_bSelected = true;
				ms_aAmmo[Rockets].m_bSelected = true;
				ms_aAmmo[HeatSeekers].m_bSelected = true;
				ms_aAmmo[Cocktails].m_bSelected = true;
				ms_aAmmo[Napalm].m_bSelected = true;
				ms_aAmmo[Fuel].m_bSelected = true;
				break;
			case CDude::DoubleBarrel:
				ms_aWeapons[ShotGun].m_bSelected = true;
				ms_aAmmo[Shells].m_bSelected = true;
				break;
			}


		// Light everything that would be selected by this "scheme"
		// Now set all the situation codes for drawing!
		for (i = NotAmmo + 1; i < NumberOfAmmos; i++)
			{
			if (!ms_aAmmo[i].m_bExists && !ms_aAmmo[i].m_bSelected) 
				ms_aAmmo[i].m_eState = Bar;
			else if (!ms_aAmmo[i].m_bExists && ms_aAmmo[i].m_bSelected) 
				ms_aAmmo[i].m_eState = BarSel;
			else if (ms_aAmmo[i].m_bExists && !ms_aAmmo[i].m_bSelected) 
				ms_aAmmo[i].m_eState = Full;
			else if (ms_aAmmo[i].m_bExists && ms_aAmmo[i].m_bSelected) 
				ms_aAmmo[i].m_eState = FullSel;
			}

		for (i = NotWeapon + 1; i < NumberOfWeapons; i++)
			{
			if (!ms_aWeapons[i].m_bExists && !ms_aWeapons[i].m_bSelected) 
				ms_aWeapons[i].m_eState = Bar;
			else if (!ms_aWeapons[i].m_bExists && ms_aWeapons[i].m_bSelected) 
				ms_aWeapons[i].m_eState = BarSel;
			else if (ms_aWeapons[i].m_bExists && !ms_aWeapons[i].m_bSelected) 
				ms_aWeapons[i].m_eState = Full;
			else if (ms_aWeapons[i].m_bExists && ms_aWeapons[i].m_bSelected) 
				ms_aWeapons[i].m_eState = FullSel;
			}

		//======================== CHECK FOR CHANGE IN AMMO OR STATUS:
		bool bChange = false;

		for (i = NotAmmo + 1; i < NumberOfAmmos; i++)
			{
			if (ms_aAmmo[i].m_eState != ms_aAmmo[i].m_ePrevState)
				{
				bChange = true;
				break;
				}

			if (ms_aAmmo[i].m_dValue != ms_aAmmo[i].m_dPrevValue)
				{
				bChange = true;
				break;
				}
	
			// This hook is when the tellow numbers become white.
			if (ms_aAmmo[i].m_bTreasure)
				{
				if ( (rspGetMilliseconds() - ms_aAmmo[i].m_lMilli) >
					TB_MILLI_TO_LITE)
					{
					// no longer highlighted:
					bChange = true;
					}
				}

			}

		if (bChange == false)
			{
			for (i = NotWeapon + 1; i < NumberOfWeapons; i++)
				{
				if (ms_aWeapons[i].m_eState != ms_aWeapons[i].m_ePrevState)
					{
					bChange = true;
					break;
					}
				}
			}

		ms_sPlayerNum = pDude->m_sDudeNum;

		if (g_sActivePlayers > PLAYER_1)
		{
			int8_t R,G,B;
			switch (pDude->m_sTextureIndex)
			{

				case 0:	// Black
					R = 27;
					G = 19;
					B = 32;					
					break;
				case 1:	// Green
					R = 28;
					G = 53;
					B = 56;					
					break;
				case 2: // Blue
					R = 22;
					G = 27;
					B = 64;				
					break;
				case 3: // Grey
					R = G = B = 64;					
					break;
				case 4: // Brown
					R = 76;
					G = 37;
					B = 27;					
					break;
				case 5: // Red
					R = 109;
					G = 37;
					B = 40;					
					break;
				case 6: // Tan
					R = 132;
					G = 96;
					B = 60;					
					break;
				case 7:	// Purple
					R = 63;
					G = 57;
					B = 79;					
					break;	
			}
			
			if (g_pvrRenderer->m_fGlobalRScale != 1.0f || g_pvrRenderer->m_fGlobalGScale != 1.f || g_pvrRenderer->m_fGlobalBScale != 1.f)
			{								
				R = uint8_t(R * g_pvrRenderer->m_fGlobalRScale);
				G = uint8_t(G * g_pvrRenderer->m_fGlobalGScale);
				B = uint8_t(B * g_pvrRenderer->m_fGlobalBScale);
			}

			ms_ulPlayerIndicator = PACK_ARGB8888(255, R, G, B);

		}


		return bChange;
		}

	};
//----------------------------------------------------------------------

// I am hoping that before any instance of a class
// exists, that the staic members must also exist.
CToolItem* CToolItem::ms_aWeapons = NULL;
CToolItem* CToolItem::ms_aAmmo = NULL;
RFont*	CToolItem::ms_pfntTool = NULL;		// General font and print
RPrint	CToolItem::ms_pntTool;
int16_t		CToolItem::ms_sSmallFontColor	=	255;	// color index
int16_t		CToolItem::ms_sLargeFontColor =	255;
int16_t		CToolItem::ms_sWarningColor	=	255;
int16_t		CToolItem::ms_sAmmoGoneColor	=	255;
int16_t		CToolItem::ms_sAttentionColor	=	255;
int32_t		CToolItem::ms_lLastTime = 0;
uint32_t	CToolItem::ms_ulPlayerIndicator = 0;
int16_t		CToolItem::ms_sPlayerNum = 0;

// Time to arrange the basic bar relationhips:
class	CInitToolBar
	{
public:
	CInitToolBar()
		{
		// arrange the patterns of weapons and ammo:
		CToolItem::ms_aWeapons = new CToolItem[NumberOfWeapons];
		CToolItem::ms_aAmmo = new CToolItem[NumberOfAmmos];

		//************* WEAPONS **************
		CToolItem::ms_aWeapons[MachineGun].ArrangeWeapon(
			MachineGun,CDude::SemiAutomatic,
			RRect(127,5,42,21),
			0.124f, 0.671f,
			0.165f, 1.f,
			&CToolItem::ms_aAmmo[Bullets]);

		CToolItem::ms_aWeapons[ShotGun].ArrangeWeapon(
			ShotGun,CDude::ShotGun,
			RRect(178,7,35,13),
			0.174f, 0.796f,
			0.208f, 1.f,
			&CToolItem::ms_aAmmo[Shells]);

		CToolItem::ms_aWeapons[SprayCannon].ArrangeWeapon(
			SprayCannon,CDude::SprayCannon,
			RRect(225,3,38,21),
			0.22f, 0.69f,
			0.257f, 1.f,
			&CToolItem::ms_aAmmo[Spray]);

		CToolItem::ms_aWeapons[MissileLauncher].ArrangeWeapon(
			MissileLauncher,CDude::Rocket,
			RRect(310,3,47,20),
			0.303f, 0.686f,
			0.348f, 1.f,
			&CToolItem::ms_aAmmo[Rockets],
			&CToolItem::ms_aAmmo[HeatSeekers]); // double whammy

		CToolItem::ms_aWeapons[NapalmLauncher].ArrangeWeapon(
			NapalmLauncher,CDude::Napalm,
			RRect(422,3,34,22),
			0.412f, 0.656f,
			0.445f, 1.f,
			&CToolItem::ms_aAmmo[Napalm]);

		CToolItem::ms_aWeapons[FlameThrower].ArrangeWeapon(
			FlameThrower,CDude::FlameThrower,
			RRect(471,3,43,21),
			0.46f, 0.671f,
			0.501f, 1.f,
			&CToolItem::ms_aAmmo[Fuel]);

		//************** AMMO ****************
		CToolItem::ms_aAmmo[Health].ArrangeAmmo(
			Health,CDude::NoWeapon,
			RRect(1,0,48,40),
			0.633f,0.f, 
			0.679f,0.625f,
			23,457,
			NULL,
			CToolItem::Large);

		CToolItem::ms_aAmmo[KevlarVest].ArrangeAmmo(
			KevlarVest,CDude::NoWeapon,
			RRect(49,0,59,40),
			0.68f,0.f, 
			0.737f,0.625f,
			47,457,
			NULL,
			CToolItem::Large);
		//-------------------------------------
		CToolItem::ms_aAmmo[Bullets].ArrangeAmmo(
			Bullets,CDude::SemiAutomatic,
			RRect(130,22,15,14),
			0.0f, 0.781f,
			0.013f, 1.f,
			149,467,
			&CToolItem::ms_aWeapons[MachineGun],
			CToolItem::Small);

		CToolItem::ms_aAmmo[Shells].ArrangeAmmo(
			Shells,CDude::ShotGun,
			RRect(182,23,16,14),
			0.018f, 0.781f,
			0.033f, 1.f,
			102,467,
			&CToolItem::ms_aWeapons[ShotGun],
			CToolItem::Small);

		CToolItem::ms_aAmmo[Spray].ArrangeAmmo(
			Spray,CDude::SprayCannon,
			RRect(227,23,16,14),
			0.036f, 0.781f,
			0.051f, 1.f,
			124,467,
			&CToolItem::ms_aWeapons[SprayCannon],
			CToolItem::Small);

		CToolItem::ms_aAmmo[Grenades].ArrangeAmmo(
			Grenades,CDude::Grenade,
			RRect(271,3,17,18),
			0.266f, 0.686f,
			0.281f, 1.f,
			139,467,
			NULL,
			CToolItem::Small);

		CToolItem::ms_aAmmo[Rockets].ArrangeAmmo(
			Rockets,CDude::Rocket,
			RRect(295,23,23,14),
			0.055f, 0.781f,
			0.077f, 1.f,
			160,467,
			&CToolItem::ms_aWeapons[MissileLauncher],
			CToolItem::Small);

		CToolItem::ms_aAmmo[HeatSeekers].ArrangeAmmo(
			HeatSeekers,CDude::Heatseeker,
			RRect(338,23,22,14),
			0.08f, 0.781f,
			0.101f, 1.f,
			180,467,
			&CToolItem::ms_aWeapons[MissileLauncher],
			CToolItem::Small);

		CToolItem::ms_aAmmo[Cocktails].ArrangeAmmo(
			Cocktails,CDude::FireBomb,
			RRect(391,3,21,22),
			0.382f, 0.656f,
			0.402f, 1.f,
			198,467,
			NULL,
			CToolItem::Small);

		CToolItem::ms_aAmmo[Napalm].ArrangeAmmo(
			Napalm,CDude::Napalm,
			RRect(417,23,24,14),
			0.616f, 0.781f,
			0.643f, 1.f,
			222,467,			
			&CToolItem::ms_aWeapons[NapalmLauncher],
			CToolItem::Small);

		CToolItem::ms_aAmmo[Fuel].ArrangeAmmo(
			Fuel,CDude::FlameThrower,
			RRect(479,22,10,16),
			0.65f, 0.77f,
			0.659f, 1.f,
			248,467,
			&CToolItem::ms_aWeapons[FlameThrower],
			CToolItem::Small);
		//----------------------------------------
		CToolItem::ms_aAmmo[BouncingBettyMine].ArrangeAmmo(
			ProximityMine,CDude::BouncingBettyMine,
			RRect(542,3,20,22),
			0.53f, 0.656f,
			0.548f, 1.f,
			290,467,
			NULL,
			CToolItem::Small);

		CToolItem::ms_aAmmo[TimedMine].ArrangeAmmo(
			TimedMine,CDude::TimedMine,
			RRect(600,3,24,22),
			0.586f, 0.656f,
			0.609f, 1.f,
			270,467, // redundantly repeated
			NULL,
			CToolItem::Small);

		CToolItem::ms_aAmmo[ProximityMine].ArrangeAmmo(
			BouncingBettyMine,CDude::ProximityMine,
			RRect(570,3,22,22),
			0.557f, 0.656f,
			0.578f, 1.f,
			575,467, // redundantly repeated
			NULL,
			CToolItem::Small);
		
		// Now, factor out the bar location from all the coordinates:
		int16_t i;

		for (i = NotWeapon + 1; i < NumberOfWeapons; i++)
		{			
			CToolItem::ms_aWeapons[i].m_rText.sY += TB_TWEAK_FONT_Y;
			CToolItem::ms_aWeapons[i].m_rText.sX += TB_TWEAK_FONT_X;
		}

		for (i = NotAmmo + 1; i < NumberOfAmmos; i++)
		{			
			CToolItem::ms_aAmmo[i].m_rText.sY += TB_TWEAK_FONT_Y;
			CToolItem::ms_aAmmo[i].m_rText.sX += TB_TWEAK_FONT_X;
		}

		// Set differect "low" values for each item:
		CToolItem::ms_aAmmo[Health].m_dLow = 20.0;
		CToolItem::ms_aAmmo[KevlarVest].m_dLow = 9.0;
		CToolItem::ms_aAmmo[Shells].m_dLow = 3.0;
		CToolItem::ms_aAmmo[Spray].m_dLow = 15.0;
		CToolItem::ms_aAmmo[Grenades].m_dLow = 2.0;
		CToolItem::ms_aAmmo[Rockets].m_dLow = 2.0;
		CToolItem::ms_aAmmo[HeatSeekers].m_dLow = 2.0;
		CToolItem::ms_aAmmo[Cocktails].m_dLow = 2.0;
		CToolItem::ms_aAmmo[Napalm].m_dLow = 2.0;
		CToolItem::ms_aAmmo[Fuel].m_dLow = 10.0;
		CToolItem::ms_aAmmo[ProximityMine].m_dLow = 2.0;
		CToolItem::ms_aAmmo[BouncingBettyMine].m_dLow = 2.0;
		CToolItem::ms_aAmmo[TimedMine].m_dLow = 1.0;
		}

	~CInitToolBar() 
		{		
		delete [] CToolItem::ms_aWeapons;
		delete [] CToolItem::ms_aAmmo;	
		}

	} DoInitToolBar;

/////////////////////////////////////////
// aliased functions "for her pleasure."
/////////////////////////////////////////
int16_t	ToolBarInit(CHood* pHood)
	{
	return CToolItem::Init(pHood);
	}

bool ToolBarRender(CHood* pHood,int16_t sDstX,int16_t sDstY, CDude* pDude, bool bMinimal,
						int8_t cLayerOffset)
{
	bool bRender = true;

	if (pDude == NULL) 
	{	
		TRACE("ToolBarRender: Dude doesn't exist!\n"); 
		return false;
	}

	CToolItem::UpdateStatus(pDude);
	CToolItem::RenderBar(pHood, sDstX, sDstY, bMinimal, cLayerOffset); // don't care about update
	
	return bRender;
}

////////////////////////////////////////////////
// Use events which change the state of the bar
////////////////////////////////////////////////
