#ifdef PRECOMPILEDHEADERS
	#include "Strategic All.h"
#else
	#include "Strategic Event Handler.h"
	#include "MemMan.h"
	#include "message.h"
	#include "Items.h"
	#include "Handle Items.h"
	#include "LaptopSave.h"
	#include "Tactical Save.h"
	#include "StrategicMap.h"
	#include "Quests.h"
	#include "Soldier Profile.h"
	#include "Game Event Hook.h"
	#include "Game Clock.h"
	#include "Interface Dialogue.h"
	#include "Random.h"
	#include "Overhead.h"
	#include "Strategic Town Loyalty.h"
	#include "Soldier Init List.h"
	#include "SaveLoadMap.h"
	#include "Soldier Create.h"
	#include "Soldier Add.h"
	#include "Renderworld.h"
	#include "Soldier Profile.h"
	#include "email.h"
	#include "strategic.h"
	#include "GameSettings.h"
	#include "history.h"
	#include "Town Militia.h"	// added by Flugente
	#include "Campaign.h"		// added by Flugente
	#include "Strategic AI.h"
	#include "Rebel Command.h"
#endif

#include "Luaglobal.h"
#include "connect.h"
#include "LuaInitNPCs.h"

//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
class SOLDIERTYPE;
extern WorldItems gAllWorldItems;


#define		MEDUNA_ITEM_DROP_OFF_GRIDNO			10959
#define		MEDUNA_ITEM_DROP_OFF_SECTOR_X		3
#define		MEDUNA_ITEM_DROP_OFF_SECTOR_Y		14
#define		MEDUNA_ITEM_DROP_OFF_SECTOR_Z		0


extern INT32 gsRobotGridNo;

UINT32 guiPabloExtraDaysBribed = 0;

UINT8		gubCambriaMedicalObjects;

extern INT8 NumMercsNear( UINT8 ubProfileID, UINT8 ubMaxDist );

extern SECTOR_EXT_DATA	SectorExternalData[256][4];

// WANNE: No more used for the new airport code
//void DropOffItemsInMeduna( UINT8 ubOrderNum );

/*
// WANNE: Dieser Code wird nicht mehr ausgeführt. Es gibt jetzt das PostalService.cpp::DeliverShipment()
// In der Methode DeliverShipment() fehlt eine ganze Menge (PABLO Quests, ...)
void BobbyRayPurchaseEventCallback( UINT8 ubOrderID )
{
	UINT8	i,j;
	UINT16	usItem;
	INT16 sMapPos, sStandardMapPos;
	UINT16 usNumberOfItems;
	BOOLEAN	fSectorLoaded = FALSE;
	UINT16	usTotalNumberOfItemTypes;
	UINT32	uiCount = 0,uiStolenCount = 0;
	static UINT8 ubShipmentsSinceNoBribes = 0;
	UINT32	uiChanceOfTheft;
	BOOLEAN		fPablosStoleSomething = FALSE;
	BOOLEAN		fPablosStoleLastItem = FALSE;
	OBJECTTYPE	*pObject=NULL;
	OBJECTTYPE	*pStolenObject=NULL;
	BOOLEAN			fThisShipmentIsFromJohnKulba = FALSE;	//if it is, dont add an email
	UINT8		ubItemsDelivered;
	UINT8		ubTempNumItems;
	UINT8		ubItemsPurchased;

	sStandardMapPos = BOBBYR_SHIPPING_DEST_GRIDNO;

	// Haydent
	if(gpNewBobbyrShipments[ ubOrderID ].fActive && is_client)
	{
		DropOffItemsInSector( ubOrderID );//hayden
		return;
	}


	// if the delivery is for meduna, drop the items off there instead
	if( gpNewBobbyrShipments[ ubOrderID ].fActive && gpNewBobbyrShipments[ ubOrderID ].ubDeliveryLoc == BR_MEDUNA )
	{
		DropOffItemsInMeduna( ubOrderID );
		return;
	}

	if (CheckFact( FACT_NEXT_PACKAGE_CAN_BE_LOST, 0 ))
	{
		SetFactFalse( FACT_NEXT_PACKAGE_CAN_BE_LOST );
		if (Random( 100 ) < 50)
		{
			// lose the whole shipment!
			gpNewBobbyrShipments[ ubOrderID ].fActive = FALSE;
			SetFactTrue( FACT_LAST_SHIPMENT_CRASHED );
			return;
		}

	}
	else if (CheckFact( FACT_NEXT_PACKAGE_CAN_BE_DELAYED, 0 ))
	{
		// shipment went to wrong airport... reroute all items to a temporary
		// gridno to represent the other airport (and damage them)
		SetFactTrue( FACT_LAST_SHIPMENT_WENT_TO_WRONG_AIRPORT );
		sStandardMapPos = LOST_SHIPMENT_GRIDNO;
		SetFactFalse( FACT_NEXT_PACKAGE_CAN_BE_DELAYED );
	}
	else if ( (gTownLoyalty[ DRASSEN ].ubRating < 20) || StrategicMap[ CALCULATE_STRATEGIC_INDEX( 13, MAP_ROW_B ) ].fEnemyControlled )
	{
		// loss of the whole shipment
		gpNewBobbyrShipments[ ubOrderID ].fActive = FALSE;

		SetFactTrue( FACT_AGENTS_PREVENTED_SHIPMENT );
		return;
	}

	//Get the number of item types
	usTotalNumberOfItemTypes = gpNewBobbyrShipments[ ubOrderID ].ubNumberPurchases;

	//Must get the total number of items ( all item types plus how many of each item type ordered )
	usNumberOfItems = 0;
	for(i=0; i<gpNewBobbyrShipments[ ubOrderID ].ubNumberPurchases; i++)
	{
		// Count how many items were purchased
		usNumberOfItems += gpNewBobbyrShipments[ ubOrderID ].BobbyRayPurchase[i].ubNumberPurchased;

		//if any items are AutoMags
		if( gpNewBobbyrShipments[ ubOrderID ].BobbyRayPurchase[i].usItemIndex == AUTOMAG_III )
		{
			//This shipment is from John Kulba, dont add an email from bobby ray
			fThisShipmentIsFromJohnKulba = TRUE;
		}
	}

	// determine if the sector is loaded
	if( ( gWorldSectorX == BOBBYR_SHIPPING_DEST_SECTOR_X ) && ( gWorldSectorY == BOBBYR_SHIPPING_DEST_SECTOR_Y ) && ( gbWorldSectorZ == BOBBYR_SHIPPING_DEST_SECTOR_Z ) )
		fSectorLoaded = TRUE;
	else
		fSectorLoaded = FALSE;

	// set crate to closed!
	if ( fSectorLoaded )
	{
		SetOpenableStructureToClosed( BOBBYR_SHIPPING_DEST_GRIDNO, 0 );
	}
	else
	{
		ChangeStatusOfOpenableStructInUnloadedSector( BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z, BOBBYR_SHIPPING_DEST_GRIDNO, FALSE );
	}

	//if we are NOT currently in the right sector
	if( !fSectorLoaded )
	{
		//build an array of objects to be added
		pObject = new OBJECTTYPE[ usNumberOfItems ];
		pStolenObject = new OBJECTTYPE[ usNumberOfItems ];
		if( pObject == NULL || pStolenObject == NULL)
			return;
	}

	// WDS - Option to turn off stealing
	// check for potential theft
	if (gGameExternalOptions.fStealingDisabled ||
		CheckFact( FACT_PABLO_WONT_STEAL, 0 ))
	{
		uiChanceOfTheft = 0;
	}
	else if (CheckFact( FACT_PABLOS_BRIBED, 0 ))
	{
		// Since Pacos has some money, reduce record of # of shipments since last bribed...
		ubShipmentsSinceNoBribes /= 2;
		uiChanceOfTheft = 0;
	}
	else
	{
		ubShipmentsSinceNoBribes++;
		// this chance might seem high but it's only applied at most to every second item
		uiChanceOfTheft = 12 + Random( 4 * ubShipmentsSinceNoBribes );
	}

	uiCount=0;
	for ( i=0; i<gpNewBobbyrShipments[ ubOrderID ].ubNumberPurchases; i++ )
	{
		//Get the item
		usItem = gpNewBobbyrShipments[ ubOrderID ].BobbyRayPurchase[i].usItemIndex;

		//Create the item
		CreateItem( usItem, gpNewBobbyrShipments[ ubOrderID ].BobbyRayPurchase[i].bItemQuality, &gTempObject );

		// if it's a gun
		if (Item [ usItem ].usItemClass == IC_GUN )
		{
			// Empty out the bullets put in by CreateItem().	We now sell all guns empty of bullets.	This is done for BobbyR
			// simply to be consistent with the dealers in Arulco, who must sell guns empty to prevent ammo cheats by players.
			gTempObject[0]->data.gun.ubGunShotsLeft = 0;
		}

		ubItemsDelivered = 0;

		//add all the items that were purchased
		ubItemsPurchased = gpNewBobbyrShipments[ ubOrderID ].BobbyRayPurchase[i].ubNumberPurchased;
		for( j=0; j < ubItemsPurchased; j++)
		{
			// Pablos might steal stuff but only:
			// - if it's one of a group of items
			// - if he didn't steal the previous item in the group (so he never steals > 50%)
			// - if he has been bribed, he only sneaks out stuff which is cheap
			if( fSectorLoaded )
			{
				// add ubItemsPurchased to the chance of theft so the chance increases when there are more items of a kind being ordered
				if ( !fPablosStoleLastItem && uiChanceOfTheft > 0 && Random( 100 ) < (uiChanceOfTheft + ubItemsPurchased) )
				{
					uiStolenCount++;
					sMapPos = PABLOS_STOLEN_DEST_GRIDNO; // off screen!
					fPablosStoleSomething = TRUE;
					fPablosStoleLastItem = TRUE;
				}
				else
				{
					sMapPos = sStandardMapPos;
					fPablosStoleLastItem = FALSE;

					if (sStandardMapPos == LOST_SHIPMENT_GRIDNO)
					{
						// damage the item a random amount!
						gTempObject[0]->data.objectStatus = (INT8) ( ( (70 + Random( 11 )) * (INT32) gTempObject[0]->data.objectStatus ) / 100 );
						// make damn sure it can't hit 0
						if (gTempObject[0]->data.objectStatus == 0)
						{
							gTempObject[0]->data.objectStatus = 1;
						}
						AddItemToPool( sMapPos, &gTempObject, -1, 0, 0, 0 );
					}
					else
					{
						// record # delivered for later addition...
						ubItemsDelivered++;
					}
				}
			}
			else
			{
				if ( j > 1 && !fPablosStoleLastItem && uiChanceOfTheft > 0 && Random( 100 ) < (uiChanceOfTheft + j) )
				{
					pStolenObject[ uiStolenCount ] = gTempObject;
					uiStolenCount++;
					fPablosStoleSomething = TRUE;
					fPablosStoleLastItem = TRUE;
				}
				else
				{
					fPablosStoleLastItem = FALSE;

					//else we are not currently in the sector, so we build an array of items to add in one lump
					//add the item to the item array

					if (sStandardMapPos == LOST_SHIPMENT_GRIDNO)
					{
						// damage the item a random amount!
						gTempObject[0]->data.objectStatus = (INT8) ( ( (70 + Random( 11 )) * (INT32) gTempObject[0]->data.objectStatus ) / 100 );
						// make damn sure it can't hit 0
						if (gTempObject[0]->data.objectStatus == 0)
						{
							gTempObject[0]->data.objectStatus = 1;
						}
						pObject[ uiCount ] = gTempObject;
						uiCount++;
					}
					else
					{
						ubItemsDelivered++;
					}
				}
			}
		}

		if ( gpNewBobbyrShipments[ ubOrderID ].BobbyRayPurchase[i].ubNumberPurchased == 1 && ubItemsDelivered == 1 )
		{
			// the item in gTempObject will be the item to deliver
			if( fSectorLoaded )
			{
				AddItemToPool( sStandardMapPos, &gTempObject, -1, 0, 0, 0 );
			}
			else
			{
				pObject[ uiCount ] = gTempObject;
				uiCount++;
			}
		}
		else
		{
			while ( ubItemsDelivered )
			{
				// treat 0s as 1s :-)
				ubTempNumItems = __min( ubItemsDelivered, ItemSlotLimit(&gTempObject, STACK_SIZE_LIMIT) );
				CreateItems( usItem, gpNewBobbyrShipments[ ubOrderID ].BobbyRayPurchase[i].bItemQuality, ubTempNumItems, &gTempObject );

				// stack as many as possible
				if( fSectorLoaded )
				{
					AddItemToPool( sStandardMapPos, &gTempObject, -1, 0, 0, 0 );
				}
				else
				{
					pObject[ uiCount ] = gTempObject;
					uiCount++;
				}

				ubItemsDelivered -= ubTempNumItems;
			}
		}
	}

	//if we are NOT currently in the sector
	if( !fSectorLoaded )
	{
		//add all the items from the array that was built above
		sMapPos = PABLOS_STOLEN_DEST_GRIDNO;
		//The item are to be added to the Top part of Drassen, grid loc's	10112, 9950
		if( !AddItemsToUnLoadedSector( BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z, sStandardMapPos, uiCount, pObject, 0, 0, 0, -1, FALSE ) )
		{
			//Error adding the items
			//return;
		}
		if (uiStolenCount > 0)
		{
			if( !AddItemsToUnLoadedSector( BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z, PABLOS_STOLEN_DEST_GRIDNO, uiStolenCount, pStolenObject, 0, 0, 0, -1, FALSE ) )
			{
				//Error adding the items
				//return;
			}
		}
		delete[] pObject ;
		delete[]( pStolenObject );
		pObject = NULL;
		pStolenObject = NULL;
	}

	if (fPablosStoleSomething)
	{
		SetFactTrue( FACT_PABLOS_STOLE_FROM_LATEST_SHIPMENT );
	}
	else
	{
		SetFactFalse( FACT_PABLOS_STOLE_FROM_LATEST_SHIPMENT );
	}

	SetFactFalse( FACT_PLAYER_FOUND_ITEMS_MISSING );

	SetFactFalse( FACT_LARGE_SIZED_OLD_SHIPMENT_WAITING );

	if ( CheckFact( FACT_NEXT_PACKAGE_CAN_BE_DELAYED, 0 ) )
	{
		SetFactFalse( FACT_MEDIUM_SIZED_SHIPMENT_WAITING );
		SetFactFalse( FACT_LARGE_SIZED_SHIPMENT_WAITING );
		SetFactFalse( FACT_REALLY_NEW_BOBBYRAY_SHIPMENT_WAITING );
	}
	else
	{
		if (usNumberOfItems - uiStolenCount <= 5)
		{
			SetFactFalse( FACT_MEDIUM_SIZED_SHIPMENT_WAITING );
			SetFactFalse( FACT_LARGE_SIZED_SHIPMENT_WAITING );
		}
		else if (usNumberOfItems - uiStolenCount <= 15)
		{
			SetFactTrue( FACT_MEDIUM_SIZED_SHIPMENT_WAITING );
			SetFactFalse( FACT_LARGE_SIZED_SHIPMENT_WAITING );
		}
		else
		{
			SetFactFalse( FACT_MEDIUM_SIZED_SHIPMENT_WAITING );
			SetFactTrue( FACT_LARGE_SIZED_SHIPMENT_WAITING );
		}

		// this shipment isn't old yet...
		SetFactTrue( FACT_REALLY_NEW_BOBBYRAY_SHIPMENT_WAITING );

		// set up even to make shipment "old"
		AddSameDayStrategicEvent( EVENT_SET_BY_NPC_SYSTEM, GetWorldMinutesInDay() + 120, FACT_REALLY_NEW_BOBBYRAY_SHIPMENT_WAITING );
	}

	//We have received the shipment so fActice becomes fALSE
	gpNewBobbyrShipments[ ubOrderID ].fActive = FALSE;

	//Stop time compression the game
	StopTimeCompression( );

	//if the shipment is NOT from John Kulba, send an email
	if( !fThisShipmentIsFromJohnKulba )
	{
		//Add an email from Bobby r telling the user the shipment 'Should' be there
		AddEmail( BOBBYR_SHIPMENT_ARRIVED, BOBBYR_SHIPMENT_ARRIVED_LENGTH, BOBBY_R, GetWorldTotalMin(), -1 );
	}
	else
	{
		//if the shipment is from John Kulba

		//Add an email from kulba telling the user the shipment is there
		AddEmail( JOHN_KULBA_GIFT_IN_DRASSEN, JOHN_KULBA_GIFT_IN_DRASSEN_LENGTH, JOHN_KULBA, GetWorldTotalMin(), -1 );
	}
}
*/


void HandleDelayedItemsArrival( UINT32 uiReason )
{

//	LuaHandleDelayedItemsArrival( uiReason, 0);

	// This function moves all the items that Pablos has stolen
	// (or items that were delayed) to the arrival location for new shipments,
	INT32			sStartGridNo;
	UINT8			ubLoop;

	if (uiReason == NPC_SYSTEM_EVENT_ACTION_PARAM_BONUS + NPC_ACTION_RETURN_STOLEN_SHIPMENT_ITEMS )
	{
		if ( gMercProfiles[ PABLO ].bMercStatus == MERC_IS_DEAD )
		{
			// nothing arrives then!
			return;
		}
		// update some facts...
		SetFactTrue( FACT_PABLO_RETURNED_GOODS );
		SetFactFalse( FACT_PABLO_PUNISHED_BY_PLAYER );
		sStartGridNo = PABLOS_STOLEN_DEST_GRIDNO;

		// add random items

		for (ubLoop = 0; ubLoop < 2; ubLoop++)
		{
			switch( Random( 10 ) )
			{
				case 0:
					// 1 in 10 chance of a badly damaged gas mask
					CreateItem( GASMASK, (INT8) (20 + Random( 10 )), &gTempObject );
					break;
				case 1:
				case 2:
					// 2 in 10 chance of a battered Desert Eagle
					CreateItem( DESERTEAGLE, (INT8) (40 + Random( 10 )), &gTempObject );
					break;
				case 3:
				case 4:
				case 5:
					// 3 in 10 chance of a stun grenade
					CreateItem( STUN_GRENADE, (INT8) (70 + Random( 10 )), &gTempObject );
					break;
				case 6:
				case 7:
				case 8:
				case 9:
					// 4 in 10 chance of two 38s!
					CreateItems( SW38, (INT8) (90 + Random( 10 )), 2, &gTempObject );
					break;
			}
			if ( ( gWorldSectorX == BOBBYR_SHIPPING_DEST_SECTOR_X ) && ( gWorldSectorY == BOBBYR_SHIPPING_DEST_SECTOR_Y ) && ( gbWorldSectorZ == BOBBYR_SHIPPING_DEST_SECTOR_Z ) )
			{
				AddItemToPool( BOBBYR_SHIPPING_DEST_GRIDNO, &gTempObject, -1, 0, 0, 0 );
			}
			else
			{
				AddItemsToUnLoadedSector( BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z, BOBBYR_SHIPPING_DEST_GRIDNO, 1, &gTempObject, 0, 0, 0, -1, FALSE );
			}
		}
	}
	else if (uiReason == FACT_PACKAGE_DAMAGED)
	{
		sStartGridNo = LOST_SHIPMENT_GRIDNO;
	}
	else
	{
		return;
	}

	// If the Drassen airport sector is already loaded, move the item pools...
	if ( ( gWorldSectorX == BOBBYR_SHIPPING_DEST_SECTOR_X ) && ( gWorldSectorY == BOBBYR_SHIPPING_DEST_SECTOR_Y ) && ( gbWorldSectorZ == BOBBYR_SHIPPING_DEST_SECTOR_Z ) )
	{
		// sector is loaded!
		// just move the hidden item pool
		MoveItemPools( sStartGridNo, BOBBYR_SHIPPING_DEST_GRIDNO, 0, 0 );
	}
	else
	{
		// otherwise load the saved items from the item file and change the records of their locations
		std::vector<WORLDITEM> pTemp;
		UINT32 uiNumWorldItems = 0;

		const auto ii = FindWorldItemSector(BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z);
		if (ii != -1)
		{
			uiNumWorldItems = gAllWorldItems.NumItems[ii];
			pTemp = gAllWorldItems.Items[ii];
		}
		
		for (UINT32 uiLoop = 0; uiLoop < uiNumWorldItems; uiLoop++)
		{
			if (pTemp[uiLoop].sGridNo == PABLOS_STOLEN_DEST_GRIDNO)
			{
				pTemp[uiLoop].sGridNo = BOBBYR_SHIPPING_DEST_GRIDNO;
			}
		}
		AddWorldItemsToUnLoadedSector( BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z, 0, uiNumWorldItems, pTemp, TRUE );
	}
}

void AddSecondAirportAttendant( void )
{

//LetLuaHandleEarlyMorningEvents(2);
//#if 0
	// add the second airport attendant to the Drassen airport...
	gMercProfiles[99].sSectorX = BOBBYR_SHIPPING_DEST_SECTOR_X;
	gMercProfiles[99].sSectorY = BOBBYR_SHIPPING_DEST_SECTOR_Y;
	gMercProfiles[99].bSectorZ = BOBBYR_SHIPPING_DEST_SECTOR_Z;
//#endif
}

void SetPabloToUnbribed( void )
{
//	LetLuaHandleEarlyMorningEvents(3);
//#if 0
	if (guiPabloExtraDaysBribed > 0)
	{
		// set new event for later on, because the player gave Pablo more money!
		AddFutureDayStrategicEvent( EVENT_SET_BY_NPC_SYSTEM, GetWorldMinutesInDay(), FACT_PABLOS_BRIBED, guiPabloExtraDaysBribed );
		guiPabloExtraDaysBribed = 0;
	}
	else
	{
		SetFactFalse( FACT_PABLOS_BRIBED );
	}
//#endif
}

void HandlePossiblyDamagedPackage( void )
{
//	LetLuaHandleEarlyMorningEvents(1);
//#if 0
	if (Random( 100 ) < 70)
	{
		SetFactTrue( FACT_PACKAGE_DAMAGED );
		HandleDelayedItemsArrival( FACT_PACKAGE_DAMAGED );
	}
	else
	{
		// shipment lost forever!
		SetFactTrue( FACT_PACKAGE_LOST_PERMANENTLY );
	}
	// whatever happened, the shipment is no longer delayed
	SetFactFalse( FACT_SHIPMENT_DELAYED_24_HOURS );
//#endif
}

void CheckForKingpinsMoneyMissing( BOOLEAN fFirstCheck )
{

//	LuaCheckForKingpinsMoneyMissing ( fFirstCheck , 0 );
//#if 0
	UINT32				uiLoop;
	UINT32				uiTotalCash = 0;
	BOOLEAN				fKingpinWillDiscover = FALSE, fKingpinDiscovers = FALSE;

	// money in D5b1 must be less than 30k

	for ( uiLoop = 0; uiLoop < guiNumWorldItems; uiLoop++ )
	{
		// loop through all items, look for ownership
		if ( gWorldItems[ uiLoop ].fExists && gWorldItems[ uiLoop ].object.usItem == MONEY )
		{
			uiTotalCash += gWorldItems[uiLoop].object[0]->data.money.uiMoneyAmount;
		}
	}

	// This function should be called every time sector D5/B1 is unloaded!
	if ( fFirstCheck )
	{
		if ( CheckFact( FACT_KINGPIN_WILL_LEARN_OF_MONEY_GONE, 0 ) == TRUE )
		{
			// unnecessary
			return;
		}

		if ( uiTotalCash < 30000 )
		{
			// add history log here
			AddHistoryToPlayersLog( HISTORY_FOUND_MONEY, 0, GetWorldTotalMin(), gWorldSectorX, gWorldSectorY );

			SetFactTrue( FACT_KINGPIN_WILL_LEARN_OF_MONEY_GONE );
		}
	}

	if ( CheckFact( FACT_KINGPIN_DEAD, 0 ) == TRUE )
	{
		return;
	}

	if ( uiTotalCash < 30000 )
	{
		if ( fFirstCheck )
		{
			// add event to make Kingpin aware, two days from now
			fKingpinWillDiscover = TRUE;
		}
		else
		{
			fKingpinDiscovers = TRUE;
		}
	}

	if ( fKingpinWillDiscover )
	{
		// set event for next day to check for real
		AddFutureDayStrategicEvent( EVENT_SET_BY_NPC_SYSTEM, Random( 120 ), FACT_KINGPIN_KNOWS_MONEY_GONE, 1 );

		// the sector is unloaded NOW so set Kingpin's balance and remove the cash
		gMercProfiles[ KINGPIN ].iBalance = - (30000 - (INT32) uiTotalCash);
		// remove all money from map
		for ( uiLoop = 0; uiLoop < guiNumWorldItems; uiLoop++ )
		{
			// loop through all items, look for ownership
			if ( gWorldItems[ uiLoop ].fExists && gWorldItems[ uiLoop ].object.usItem == MONEY )
			{
				// remove!
				gWorldItems[ uiLoop ].fExists = FALSE;
			}
		}
	}
	else if ( fKingpinDiscovers )
	{
		// ok start things up here!
		SetFactTrue( FACT_KINGPIN_KNOWS_MONEY_GONE );

		// set event 2 days from now that if the player has not given Kingpin his money back,
		// he sends email to the player
		AddFutureDayStrategicEvent( EVENT_SET_BY_NPC_SYSTEM, Random( 120 ), FACT_KINGPIN_KNOWS_MONEY_GONE, 2 );
	}
//#endif
}

void HandleNPCSystemEvent( UINT32 uiEvent )
{

//   LetLuaHandleNPCSystemEvent( uiEvent, 0 );
//#if 0
	if (uiEvent < NPC_SYSTEM_EVENT_ACTION_PARAM_BONUS)
	{
		switch( uiEvent )
		{
			case FACT_PABLOS_BRIBED:
				// set Pacos to unbribed
				SetPabloToUnbribed();
				break;

			case FACT_REALLY_NEW_BOBBYRAY_SHIPMENT_WAITING:
				// the shipment is no longer really new
				SetFactFalse( FACT_REALLY_NEW_BOBBYRAY_SHIPMENT_WAITING );
				if (CheckFact( FACT_LARGE_SIZED_SHIPMENT_WAITING, 0 ))
				{
					// set "really heavy old shipment" fact
					SetFactTrue( FACT_LARGE_SIZED_OLD_SHIPMENT_WAITING );
				}
				break;

			case FACT_SHIPMENT_DELAYED_24_HOURS:
			case FACT_24_HOURS_SINCE_DOCTOR_TALKED_TO:
			case FACT_24_HOURS_SINCE_JOEY_RESCUED:
				SetFactTrue( (UINT16) uiEvent );
				break;

			case FACT_KINGPIN_KNOWS_MONEY_GONE:
				// more generally events for kingpin quest
				if ( CheckFact( FACT_KINGPIN_KNOWS_MONEY_GONE, 0 ) == FALSE )
				{
					// check for real whether to start quest
					CheckForKingpinsMoneyMissing( FALSE );
				}
				else if ( CheckFact( FACT_KINGPIN_DEAD, 0 ) == FALSE )
				{
					if ( gubQuest[ QUEST_KINGPIN_MONEY ] == QUESTNOTSTARTED )
					{
						// KP knows money is gone, hasn't told player, if this event is called then the 2
						// days are up... send email

#ifdef JA2UB
// no UB
#else						
						AddEmail( KING_PIN_LETTER, KING_PIN_LETTER_LENGTH, KING_PIN, GetWorldTotalMin(), -1, -1 , TYPE_EMAIL_EMAIL_EDT );
#endif
						StartQuest( QUEST_KINGPIN_MONEY, gMercProfiles[ KINGPIN ].sSectorX, gMercProfiles[ KINGPIN ].sSectorY );
						// add event to send terrorists two days from now
						AddFutureDayStrategicEvent( EVENT_SET_BY_NPC_SYSTEM, Random( 120 ), FACT_KINGPIN_KNOWS_MONEY_GONE, 2 );
					}
					else if ( gubQuest[ QUEST_KINGPIN_MONEY ] == QUESTINPROGRESS )
					{
						// knows money gone, quest is still in progress
						// event indicates Kingpin can start to send terrorists
						SetFactTrue( FACT_KINGPIN_CAN_SEND_ASSASSINS );
						gMercProfiles[ SPIKE ].sSectorX = gModSettings.ubSpikeNewSectorX; //5
						gMercProfiles[ SPIKE ].sSectorY = gModSettings.ubSpikeNewSectorY; //MAP_ROW_C
						gMercProfiles[ SPIKE ].bSectorZ = gModSettings.ubSpikeNewSectorZ; //0
						gTacticalStatus.fCivGroupHostile[ KINGPIN_CIV_GROUP ] = CIV_GROUP_WILL_BECOME_HOSTILE;
					}
				}
				break;
		}
	}
	else
	{
		switch( uiEvent - NPC_SYSTEM_EVENT_ACTION_PARAM_BONUS )
		{
			case NPC_ACTION_RETURN_STOLEN_SHIPMENT_ITEMS:
				HandleDelayedItemsArrival( uiEvent );
				break;
			case NPC_ACTION_SET_RANDOM_PACKAGE_DAMAGE_TIMER:
				HandlePossiblyDamagedPackage();
				break;
			case NPC_ACTION_ENABLE_CAMBRIA_DOCTOR_BONUS:
				SetFactTrue( FACT_WILLIS_HEARD_ABOUT_JOEY_RESCUE );
				break;
			case NPC_ACTION_TRIGGER_END_OF_FOOD_QUEST:
				if ( gMercProfiles[ FATHER ].bMercStatus != MERC_IS_DEAD )
				{
					EndQuest( QUEST_FOOD_ROUTE, 10, MAP_ROW_A );
					SetFactTrue( FACT_FOOD_QUEST_OVER );

					RebelCommand::ShowWebsiteAvailableMessage();
				}
				break;
			case NPC_ACTION_DELAYED_MAKE_BRENDA_LEAVE:
				// silversurfer: reenabled this
				// but only play Brendas quote when we are near enough to hear her
				if ( NumMercsNear( 85, 8 ) > 0 )
					TriggerNPCRecord( 85, 9 );
				SetFactTrue( FACT_BRENDA_PATIENCE_TIMER_EXPIRED );
				break;
			case NPC_ACTION_SET_DELAY_TILL_GIRLS_AVAILABLE:
				HandleNPCDoAction( 107, NPC_ACTION_SET_GIRLS_AVAILABLE, 0 );
				break;

			case NPC_ACTION_READY_ROBOT:
				{
					if ( CheckFact( FACT_FIRST_ROBOT_DESTROYED, 0 ) )
					{
						// second robot ready
						SetFactTrue( FACT_ROBOT_READY_SECOND_TIME );
						// resurrect robot
						gMercProfiles[ ROBOT ].bLife = gMercProfiles[ ROBOT ].bLifeMax;
						gMercProfiles[ ROBOT ].bMercStatus = MERC_OK;
					}
					else
					{
						// first robot ready
						SetFactTrue( FACT_ROBOT_READY );
					}

					gMercProfiles[ ROBOT ].sSectorX = gMercProfiles[ MADLAB ].sSectorX;
					gMercProfiles[ ROBOT ].sSectorY = gMercProfiles[ MADLAB ].sSectorY;
					gMercProfiles[ ROBOT ].bSectorZ = gMercProfiles[ MADLAB ].bSectorZ;


				}
				break;

			case NPC_ACTION_ADD_JOEY_TO_WORLD:
				// If Joey is not dead, escorted, or already delivered
				if ( gMercProfiles[ JOEY ].bMercStatus != MERC_IS_DEAD && !CheckFact( FACT_JOEY_ESCORTED, 0 ) &&
					gMercProfiles[ JOEY ].sSectorX == gModSettings.ubJoeyPrimarySectorX && //4
					gMercProfiles[ JOEY ].sSectorY == gModSettings.ubJoeyPrimarySectorY && //MAP_ROW_D
					gMercProfiles[ JOEY ].bSectorZ == gModSettings.ubJoeyPrimarySectorZ ) //1
				{
					SOLDIERTYPE * pJoey;

					pJoey = FindSoldierByProfileID( JOEY, FALSE );
					if (pJoey )
					{
						// he's in the currently loaded sector...delay this an hour!
						AddSameDayStrategicEvent( EVENT_SET_BY_NPC_SYSTEM, GetWorldMinutesInDay() + 60, NPC_SYSTEM_EVENT_ACTION_PARAM_BONUS + NPC_ACTION_ADD_JOEY_TO_WORLD );
					}
					else
					{
						// move Joey from caves to San Mona
						gMercProfiles[ JOEY ].sSectorX = gModSettings.ubJoeyAlternateSectorX; //5
						gMercProfiles[ JOEY ].sSectorY = gModSettings.ubJoeyAlternateSectorY; //MAP_ROW_C
						gMercProfiles[ JOEY ].bSectorZ = gModSettings.ubJoeyAlternateSectorZ; //0
					}
				}
				break;

			case NPC_ACTION_SEND_ENRICO_MIGUEL_EMAIL:
#ifdef JA2UB
// no UB
#else
				AddEmail( ENRICO_MIGUEL, ENRICO_MIGUEL_LENGTH, MAIL_ENRICO, GetWorldTotalMin(), -1, -1 , TYPE_EMAIL_EMAIL_EDT);
#endif
				break;

			case NPC_ACTION_TIMER_FOR_VEHICLE:
				SetFactTrue( FACT_OK_USE_HUMMER );
				break;

			case NPC_ACTION_FREE_KIDS:
				SetFactTrue( FACT_KIDS_ARE_FREE );
				break;

			default:
				break;
		}
	}
	
//#endif
}

static INT32 TakeVolunteers( UINT8 poolRecruitPerc )
{
	INT32 loyalPopulation = 0;

	for ( UINT8 sX = 1; sX < MAP_WORLD_X - 1; ++sX )
	{
		for ( UINT8 sY = 1; sY < MAP_WORLD_Y - 1; ++sY )
		{
			if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( sX, sY )].fEnemyControlled )  // if owned by the Army
			{
				UINT8 ubTownID = StrategicMap[CALCULATE_STRATEGIC_INDEX( sX, sY )].bNameId;
				if ( ubTownID != BLANK_SECTOR )
				{
					// Supposing rebel sentiment population will never be volunteers, Queen's or neutral rating % should be greater
					// than sentiment %. Otherwise there is no volunteer people for sure.
					// So if there are Queen loyal population, take sector population into account.
					INT32 loyalPercent = MAX_LOYALTY_VALUE - gTownLoyalty[ubTownID].ubRating - gubTownRebelSentiment[ubTownID];
					if ( loyalPercent > 0 )
					{
						loyalPopulation += GetSectorPopulation( sX, sY, FALSE ) * loyalPercent / 100;
					}
				}
			}
		}
	}

	return loyalPopulation * poolRecruitPerc / 100;
}

static INT32 TakeRecruitsByForce( UINT8 poolRecruitPerc, INT32 maxToTake )
{
	INT32 recruits = 0;

	if ( poolRecruitPerc != 0 )
	{
		for ( UINT8 sX = 1; sX < MAP_WORLD_X - 1; ++sX )
		{
			if ( recruits >= maxToTake )
				break;

			for ( UINT8 sY = 1; sY < MAP_WORLD_Y - 1; ++sY )
			{
				if ( recruits >= maxToTake )
					break;

				SECTORINFO *pSectorInfo = &( SectorInfo[SECTOR( sX, sY )] );
				if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( sX, sY )].fEnemyControlled && pSectorInfo->ubGarrisonID != NO_GARRISON )
				{
					UINT8 ubTownID = StrategicMap[CALCULATE_STRATEGIC_INDEX( sX, sY )].bNameId;
					if ( ubTownID != BLANK_SECTOR )
					{
						recruits += max( 1, GetSectorPopulation( sX, sY, FALSE ) * poolRecruitPerc / 100 );

						// A possible drawback of forced recruiting is percent of unresting people increases.
						// So increase Player's loyalty on 'poolRecruitPerc' value, but only if Player is known in this town.
						if ( gTownLoyalty[ubTownID].ubRating > 0 )
						{
							gTownLoyalty[ubTownID].ubRating = min( MAX_LOYALTY_VALUE, gTownLoyalty[ubTownID].ubRating + poolRecruitPerc );
						}
					}
				}
			}
		}
	}

	return min( recruits, maxToTake );
}

void HandleEarlyMorningEvents( void )
{
	// Flugente: no reason to put this into LUA
	for ( UINT8 sX = 1; sX < MAP_WORLD_X - 1; ++sX )
	{
		for ( UINT8 sY = 1; sY < MAP_WORLD_Y - 1; ++sY )
		{
			UINT8 sector = SECTOR( sX, sY );

			SECTORINFO *pSectorInfo = &(SectorInfo[sector]);
			
			// A flag prevents us from exploiting the civilian recruitment mechanic. Every x hours, we reset it
			if ( pSectorInfo )
			{
				pSectorInfo->usSectorInfoFlag &= ~SECTORINFO_VOLUNTEERS_RECENTLY_RECRUITED;
			}
		}
	}

	UINT16 poolIncDays = zDiffSetting[gGameOptions.ubDifficultyLevel].iQueenPoolIncrementDaysPerDifficultyLevel;
	if ( !gfUnlimitedTroops && poolIncDays != 0 )
	{
		INT32 poolMaxSize = zDiffSetting[gGameOptions.ubDifficultyLevel].iQueenPoolMaxSizePerDifficultyLevel;
		INT32 poolIncSize = zDiffSetting[gGameOptions.ubDifficultyLevel].iQueenPoolBaseIncrementSizePerDifficultyLevel;
		UINT8 poolRecruitPerc = zDiffSetting[gGameOptions.ubDifficultyLevel].iQueenPoolRecruitPercentPerDifficultyLevel;

		if ( giReinforcementPool < poolMaxSize )
		{
			INT32 newRecruitsTaken = 0;
			INT32 trainingCapacity = 0;  // as first, count up training camps, then multiply it on QueenPoolBaseIncrementSizePerDifficultyLevel

			if ( IsTownUnderCompleteControlByPlayer( ALMA ) == FALSE )
			{
				++trainingCapacity;
			}
			if ( IsTownUnderCompleteControlByPlayer( MEDUNA ) == FALSE )
			{
				++trainingCapacity;
			}

			trainingCapacity *= poolIncSize;

			if ( giTotalRecruitsInTraining < trainingCapacity )
			{
				newRecruitsTaken += min( TakeVolunteers( poolRecruitPerc ), trainingCapacity - giTotalRecruitsInTraining );

				if ( giTotalRecruitsInTraining + newRecruitsTaken < trainingCapacity )
				{
					INT32 maxRecruitsToTake = trainingCapacity - giTotalRecruitsInTraining - newRecruitsTaken;
					newRecruitsTaken += TakeRecruitsByForce( poolRecruitPerc, maxRecruitsToTake );
				}

				if ( newRecruitsTaken > 0 )
				{
					UINT32 endTimeMin = GetWorldTotalMin() + poolIncDays * NUM_MIN_IN_DAY - 1;  // -1 minute: training should end right before a new recruiting session, otherwise we may ignore some training space at moment of EarlyMorningEvent
					AddStrategicEvent( EVENT_ARMY_FINISH_TRAINING, endTimeMin, (UINT32)newRecruitsTaken );
					giTotalRecruitsInTraining += newRecruitsTaken;
				}
			}
		}
	}

#ifdef LUA_STRATEGY_EVENT_HANDLER
	LetLuaHandleEarlyMorningEvents(0);
#else

	UINT32					cnt;
	UINT32					uiAmount;

	// loop through all *NPCs* and reset "default response used recently" flags
	for (cnt = 0; cnt < NUM_PROFILES; ++cnt)
	{
		if ( gMercProfiles[cnt].Type == PROFILETYPE_RPC ||
			gMercProfiles[cnt].Type == PROFILETYPE_NPC ||
			gMercProfiles[cnt].Type == PROFILETYPE_VEHICLE )
		{
			gMercProfiles[cnt].bFriendlyOrDirectDefaultResponseUsedRecently = FALSE;
			gMercProfiles[cnt].bRecruitDefaultResponseUsedRecently = FALSE;
			gMercProfiles[cnt].bThreatenDefaultResponseUsedRecently = FALSE;
			gMercProfiles[cnt].ubMiscFlags2 &= (~PROFILE_MISC_FLAG2_BANDAGED_TODAY);
		}
	}
	// reset Father Walker's drunkenness level!
	gMercProfiles[ FATHER ].bNPCData = (INT8) Random( 4 );
	// set Walker's location
	if ( Random( 2 ) )
	{
		// move the father to the other sector, provided neither are loaded
		if ( ! ( ( gWorldSectorX == 13) && ( ( gWorldSectorY == MAP_ROW_C) || gWorldSectorY == MAP_ROW_D ) && ( gbWorldSectorZ == 0 ) ) )
		{
			gMercProfiles[ FATHER ].sSectorX = 13;
			// swap his location
			if (gMercProfiles[ FATHER ].sSectorY == MAP_ROW_C)
			{
				gMercProfiles[ FATHER ].sSectorY = MAP_ROW_D;
			}
			else
			{
				gMercProfiles[ FATHER ].sSectorY = MAP_ROW_C;
			}
		}
	}

	if( gMercProfiles[ TONY ].ubLastDateSpokenTo > 0 && !( gWorldSectorX == 5 && gWorldSectorY == MAP_ROW_C && gbWorldSectorZ == 0 ) )
	{
		// San Mona C5 is not loaded so make Tony possibly not availableif 
		if (Random( 99 ) < gGameExternalOptions.ubChanceTonyAvailable) // silversurfer/SANDRO
		{
			// Tony IS available
			SetFactFalse( FACT_TONY_NOT_AVAILABLE );
			gMercProfiles[ TONY ].sSectorX = 5;
			gMercProfiles[ TONY ].sSectorY = MAP_ROW_C;
		}
		else
		{
			// Tony is NOT available
			SetFactTrue( FACT_TONY_NOT_AVAILABLE );
			gMercProfiles[ TONY ].sSectorX = 0;
			gMercProfiles[ TONY ].sSectorY = 0;
		}
	}

	if ( gMercProfiles[ DEVIN ].ubLastDateSpokenTo == 0 )
	{
		// Does Devin move?
		gMercProfiles[ DEVIN ].bNPCData++;
		if ( gMercProfiles[ DEVIN ].bNPCData > 3 )
		{
			if ( ! ( (gWorldSectorX == gMercProfiles[ DEVIN ].sSectorX) && (gWorldSectorY == gMercProfiles[DEVIN].sSectorY) && (gbWorldSectorZ == 0) ) )
			{
				// ok, Devin's sector not loaded, so time to move!
				// might be same sector as before, if so, oh well!
				switch( Random( 5 ) )
				{
					case 0:
						gMercProfiles[ DEVIN ].sSectorX = 9;
						gMercProfiles[ DEVIN ].sSectorY = MAP_ROW_G;
						break;
					case 1:
						gMercProfiles[ DEVIN ].sSectorX = 13;
						gMercProfiles[ DEVIN ].sSectorY = MAP_ROW_D;
						break;
					case 2:
						gMercProfiles[ DEVIN ].sSectorX = 5;
						gMercProfiles[ DEVIN ].sSectorY = MAP_ROW_C;
						break;
					case 3:
						gMercProfiles[ DEVIN ].sSectorX = 2;
						gMercProfiles[ DEVIN ].sSectorY = MAP_ROW_H;
						break;
					case 4:
						gMercProfiles[ DEVIN ].sSectorX = 6;
						gMercProfiles[ DEVIN ].sSectorY = MAP_ROW_C;
						break;
				}
			}
		}
	}

	// Does Hamous move?

	// stop moving the truck if Hamous is dead!!
	// stop moving them if the player has the truck or Hamous is hired!
	if ( gMercProfiles[ HAMOUS ].bLife > 0 && FindSoldierByProfileID( HAMOUS, TRUE ) == NULL && FindSoldierByProfileID( PROF_ICECREAM, TRUE ) == NULL && (! ( (gWorldSectorX == gMercProfiles[ HAMOUS ].sSectorX) && (gWorldSectorY == gMercProfiles[HAMOUS].sSectorY) && (gbWorldSectorZ == 0) )) )
	{
		// ok, HAMOUS's sector not loaded, so time to move!
		// might be same sector as before, if so, oh well!
		switch( Random( 5 ) )
		{
			case 0:
				gMercProfiles[ HAMOUS ].sSectorX = 6;
				gMercProfiles[ HAMOUS ].sSectorY = MAP_ROW_G;
				gMercProfiles[ PROF_ICECREAM ].sSectorX = 6;
				gMercProfiles[ PROF_ICECREAM ].sSectorY = MAP_ROW_G;
				break;
			case 1:
				gMercProfiles[ HAMOUS ].sSectorX = 12;
				gMercProfiles[ HAMOUS ].sSectorY = MAP_ROW_F;
				gMercProfiles[ PROF_ICECREAM ].sSectorX = 12;
				gMercProfiles[ PROF_ICECREAM ].sSectorY = MAP_ROW_F;
				break;
			case 2:
				gMercProfiles[ HAMOUS ].sSectorX = 7;
				gMercProfiles[ HAMOUS ].sSectorY = MAP_ROW_D;
				gMercProfiles[ PROF_ICECREAM ].sSectorX = 7;
				gMercProfiles[ PROF_ICECREAM ].sSectorY = MAP_ROW_D;
				break;
			case 3:
				gMercProfiles[ HAMOUS ].sSectorX = 3;
				gMercProfiles[ HAMOUS ].sSectorY = MAP_ROW_D;
				gMercProfiles[ PROF_ICECREAM ].sSectorX = 3;
				gMercProfiles[ PROF_ICECREAM ].sSectorY = MAP_ROW_D;
				break;
			case 4:
				gMercProfiles[ HAMOUS ].sSectorX = 9;
				gMercProfiles[ HAMOUS ].sSectorY = MAP_ROW_D;
				gMercProfiles[ PROF_ICECREAM ].sSectorX = 9;
				gMercProfiles[ PROF_ICECREAM ].sSectorY = MAP_ROW_D;
				break;
		}
	}

	// Does Rat take off?
	if ( gMercProfiles[ RAT ].bNPCData != 0 )
	{
		gMercProfiles[ RAT ].sSectorX = 0;
		gMercProfiles[ RAT ].sSectorY = 0;
		gMercProfiles[ RAT ].bSectorZ = 0;
	}

	// Does John leave country after quest completion?
	if ( gubQuest[ QUEST_ESCORT_TOURISTS ] == QUESTDONE && (gMercProfiles[ JOHN ].sSectorX == 13) &&
		(gMercProfiles[ JOHN ].sSectorY == MAP_ROW_B) && (gMercProfiles[ JOHN ].bSectorZ == 0) )
	{
		gMercProfiles[ JOHN ].sSectorX = 0;
		gMercProfiles[ JOHN ].sSectorY = 0;
		gMercProfiles[ JOHN ].bSectorZ = 0;
	}

	// Does Mary leave country after quest completion?
	if ( gubQuest[ QUEST_ESCORT_TOURISTS ] == QUESTDONE && (gMercProfiles[ MARY ].sSectorX == 13) &&
		(gMercProfiles[ MARY ].sSectorY == MAP_ROW_B) && (gMercProfiles[ MARY ].bSectorZ == 0) )
	{
		gMercProfiles[ MARY ].sSectorX = 0;
		gMercProfiles[ MARY ].sSectorY = 0;
		gMercProfiles[ MARY ].bSectorZ = 0;
	}

	// Empty money from pockets of Vince 69, Willis 80, and Jenny 132
	SetMoneyInSoldierProfile( VINCE, 0 );
	SetMoneyInSoldierProfile( STEVE, 0 ); // Steven Willis
	SetMoneyInSoldierProfile( JENNY, 0 );

	// Vince is no longer expecting money
	SetFactFalse( FACT_VINCE_EXPECTING_MONEY );

	// Reset Darren's balance and money
	gMercProfiles[ DARREN ].iBalance = 0;
	SetMoneyInSoldierProfile( DARREN, 15000 );

	// set Carmen to be placed on the map in case he moved and is waiting off screen
	if (gMercProfiles[ CARMEN ].ubMiscFlags2 & PROFILE_MISC_FLAG2_DONT_ADD_TO_SECTOR)
	{
		gMercProfiles[ CARMEN ].ubMiscFlags2 &= ~(PROFILE_MISC_FLAG2_DONT_ADD_TO_SECTOR);
		// move Carmen to C13
		gMercProfiles[ CARMEN ].sSectorX = 13;
		gMercProfiles[ CARMEN ].sSectorY = MAP_ROW_C;
		gMercProfiles[ CARMEN ].bSectorZ = 0;

		// we should also reset # of terrorist heads and give him cash
		if (gMercProfiles[ CARMEN ].bNPCData2 > 0)
		{
			if (gMercProfiles[ CARMEN ].uiMoney < 10000)
			{
				uiAmount = 0;
			}
			else
			{
				uiAmount = gMercProfiles[ CARMEN ].uiMoney;
			}
			uiAmount += 10000 * gMercProfiles[ CARMEN ].bNPCData2;
			SetMoneyInSoldierProfile( CARMEN, uiAmount );
			gMercProfiles[ CARMEN ].bNPCData2 = 0;

			for ( cnt = HEAD_1; cnt <= HEAD_7; cnt++ )
			{
				RemoveObjectFromSoldierProfile( CARMEN, (UINT8) cnt );
			}

		}
	}
	else
	{
		// randomize where he'll be today... so long as his sector's not loaded

		if ( gMercProfiles[ CARMEN ].sSectorX != gWorldSectorX || gMercProfiles[ CARMEN ].sSectorY != gWorldSectorY )
		{
			switch( Random( 3 ) )
			{
				case 0:
					gMercProfiles[ CARMEN ].sSectorX = 5;
					gMercProfiles[ CARMEN ].sSectorY = MAP_ROW_C;
					break;
				case 1:
					gMercProfiles[ CARMEN ].sSectorX = 13;
					gMercProfiles[ CARMEN ].sSectorY = MAP_ROW_C;
					break;
				case 2:
					gMercProfiles[ CARMEN ].sSectorX = 9;
					gMercProfiles[ CARMEN ].sSectorY = MAP_ROW_G;
					break;
			}
			// he should have $5000... unless the player forgot to meet him
			if (gMercProfiles[ CARMEN ].uiMoney < 5000)
			{
				SetMoneyInSoldierProfile( CARMEN, 5000 );
			}
		}
	}

	if ( PreRandom( 3 ) == 0 )
	{
		SetFactTrue( FACT_DAVE_HAS_GAS );
	}
	else
	{
		SetFactFalse( FACT_DAVE_HAS_GAS );
	}

	if ( gWorldSectorX == gModSettings.ubHospitalSectorX && gWorldSectorY == gModSettings.ubHospitalSectorY && gbWorldSectorZ == gModSettings.ubHospitalSectorZ )
	{
		CheckForMissingHospitalSupplies();
	}
#endif
}

// Flugente: creature raids
void HandleRaidEventPlanning()
{
	INT32 personnelgain[3];

	// the raid order is bloodcats/zombies/bandits
	for ( int raidtype = 0; raidtype < 3; ++raidtype )
	{
		// reset knowledge of these raids - if the player wants to know, they will have to buy anew
		SetFactFalse( FACT_RAID_KNOWN_BLOODCATS + raidtype );

		personnelgain[raidtype] = 0;

		if ( raidtype == 0 )
		{
			if ( !gGameExternalOptions.gRaid_Bloodcats )
				continue;
			
			// if the lair has been cleared, way less growth
			if ( CheckFact(FACT_BLOODCAT_LAIR_CLEANED, NO_PROFILE) )
				personnelgain[raidtype] += gGameExternalOptions.gRaidReplenish_BaseValue;
			else
				personnelgain[raidtype] += 3 * gGameExternalOptions.gRaidReplenish_BaseValue;
		}
		else if ( raidtype == 1 )
		{
			if ( !gGameExternalOptions.gRaid_Zombies || !gGameSettings.fOptions[TOPTION_ZOMBIES] )
				continue;

			// zombies grow very fast
			personnelgain[raidtype] += 15 * gGameExternalOptions.gRaidReplenish_BaseValue;
		}
		else if ( raidtype == 2 )
		{
			if ( !gGameExternalOptions.gRaid_Bandits )
				continue;

			// bandit growth depends on progress
			personnelgain[raidtype] += gGameExternalOptions.gRaidReplenish_BaseValue * (150 + HighestPlayerProgressPercentage()) / 100;
		}

		std::vector<INT16> attacksectors;

		for ( INT16 sector = 0; sector <= 255; ++sector )
		{
			if ( !StrategicMap[SECTOR_INFO_TO_STRATEGIC_INDEX( sector )].fEnemyControlled )
			{
				if ( ( SectorExternalData[sector][0].usSectorFlagMask & (SECTORFLAG_RAIDPOSSIBLE_BLOODCAT << raidtype ) ) )
				{
					attacksectors.push_back( sector );
				}
			}
		}

		if ( attacksectors.empty() )
			continue;

		int numattacks = gGameExternalOptions.gRaid_MaxAttackPerNight_Bandits;
		if ( raidtype == 0 )
			numattacks = gGameExternalOptions.gRaid_MaxAttackPerNight_Bloodcats;
		else if ( raidtype == 1 )
			numattacks = gGameExternalOptions.gRaid_MaxAttackPerNight_Zombies;

		for ( int attack = 0; attack < numattacks; ++attack )
		{
			UINT32 sector = attacksectors[Random(attacksectors.size())];

			// attack random sector
			if ( raidtype == 0 )
				// bloodcats only attack at night (it is 7:00 now)
				AddStrategicEvent( EVENT_BLOODCAT_ATTACK, GetWorldTotalMin() + 14 * 60 +  Random(10 * 60), sector );
			else
				// other attacks can happen all the time
				AddStrategicEvent( EVENT_BLOODCAT_ATTACK + raidtype, GetWorldTotalMin() + Random( 24 * 60 ), sector );
		}
	}

	// every day we refill our available personnel
	// this also means that at day 1 we have no personnel for raids, forces have to slowly be built up
	AddRaidPersonnel( personnelgain[0], personnelgain[1], personnelgain[2] );
}

void MakeCivGroupHostileOnNextSectorEntrance( UINT8 ubCivGroup )
{
	// if it's the rebels that will become hostile, reduce town loyalties NOW, not later
	if ( ubCivGroup == REBEL_CIV_GROUP && gTacticalStatus.fCivGroupHostile[ ubCivGroup ] == CIV_GROUP_NEUTRAL )
	{
		ReduceLoyaltyForRebelsBetrayed();
	}

	gTacticalStatus.fCivGroupHostile[ ubCivGroup ] = CIV_GROUP_WILL_BECOME_HOSTILE;
}

void RemoveAssassin( UINT8 ubProfile )
{
	gMercProfiles[ ubProfile ].sSectorX = 0;
	gMercProfiles[ ubProfile ].sSectorY = 0;
	gMercProfiles[ ubProfile ].bLife = gMercProfiles[ ubProfile ].bLifeMax;
}

void CheckForMissingHospitalSupplies( void )
{
	UINT32				uiLoop;
	ITEM_POOL *		pItemPool;
	OBJECTTYPE *	pObj;
	UINT8					ubMedicalObjects = 0;

	for ( uiLoop = 0; uiLoop < guiNumWorldItems; uiLoop++ )
	{
		// loop through all items, look for ownership
		if ( gWorldItems[ uiLoop ].fExists && gWorldItems[ uiLoop ].object.usItem == OWNERSHIP && gWorldItems[ uiLoop ].object[0]->data.owner.ubOwnerCivGroup == DOCTORS_CIV_GROUP )
		{
			GetItemPoolFromGround( gWorldItems[ uiLoop ].sGridNo, &pItemPool ) ;
			while( pItemPool )
			{
				pObj = &( gWorldItems[ pItemPool->iItemIndex ].object );

#ifdef obsoleteCode
				if ( (*pObj)[0]->data.objectStatus > 60 )
				{
					if ( Item[pObj->usItem].firstaidkit || Item[pObj->usItem].medicalkit || pObj->usItem == REGEN_BOOSTER || pObj->usItem == ADRENALINE_BOOSTER )
					{
						ubMedicalObjects++;
					}
				}
#endif//obsoleteCode
				if ( Item[pObj->usItem].firstaidkit || Item[pObj->usItem].medicalkit || pObj->usItem == REGEN_BOOSTER || pObj->usItem == ADRENALINE_BOOSTER )
				{
					for (StackedObjects::iterator iter = pObj->objectStack.begin(); iter != pObj->objectStack.end(); ++iter) {
						if ( iter->data.objectStatus > 60 )
						{
							ubMedicalObjects++;
						}
					}
				}

				pItemPool = pItemPool->pNext;
			}
		}
	}

	if ( CheckFact( FACT_PLAYER_STOLE_MEDICAL_SUPPLIES_AGAIN, 0 ) == TRUE )
	{
		// player returning stuff!	if back to full then can operate
		if ( ubMedicalObjects >= gubCambriaMedicalObjects )
		{
			SetFactFalse( FACT_PLAYER_STOLE_MEDICAL_SUPPLIES_AGAIN );
			SetFactFalse( FACT_PLAYER_STOLE_MEDICAL_SUPPLIES );
			return;
		}
	}

	if ( ubMedicalObjects < gubCambriaMedicalObjects )
	{
		// player's stolen something!
		if ( CheckFact( FACT_PLAYER_STOLE_MEDICAL_SUPPLIES, 0 ) == FALSE )
		{
			SetFactTrue( FACT_PLAYER_STOLE_MEDICAL_SUPPLIES );
		}

		// if only 1/5 or less left, give up the ghost
		if ( ubMedicalObjects * 5 <= gubCambriaMedicalObjects )
		{
			// run out!
			SetFactTrue( FACT_PLAYER_STOLE_MEDICAL_SUPPLIES_AGAIN );
		}
	}

}

// WANNE: No more used for the new airport code
/*
void DropOffItemsInMeduna( UINT8 ubOrderNum )
{
	BOOLEAN	fSectorLoaded = FALSE;
	UINT32	uiCount = 0;
	OBJECTTYPE	*pObject=NULL;
	UINT16	usNumberOfItems=0, usItem;
	UINT8		ubItemsDelivered, ubTempNumItems;
	UINT32	i;

	//if the player doesnt "own" the sector,
	if( StrategicMap[ CALCULATE_STRATEGIC_INDEX( MEDUNA_ITEM_DROP_OFF_SECTOR_X, MEDUNA_ITEM_DROP_OFF_SECTOR_Y ) ].fEnemyControlled )
	{
		//the items disappear
		gpNewBobbyrShipments[ ubOrderNum ].fActive = FALSE;
		return;
	}

	// determine if the sector is loaded
	if( ( gWorldSectorX == MEDUNA_ITEM_DROP_OFF_SECTOR_X ) && ( gWorldSectorY == MEDUNA_ITEM_DROP_OFF_SECTOR_Y ) && ( gbWorldSectorZ == MEDUNA_ITEM_DROP_OFF_SECTOR_Z ) )
		fSectorLoaded = TRUE;
	else
		fSectorLoaded = FALSE;

	// set crate to closed!
	if ( fSectorLoaded )
	{
		SetOpenableStructureToClosed( MEDUNA_ITEM_DROP_OFF_GRIDNO, 0 );
	}
	else
	{
		ChangeStatusOfOpenableStructInUnloadedSector( MEDUNA_ITEM_DROP_OFF_SECTOR_X, MEDUNA_ITEM_DROP_OFF_SECTOR_Y, MEDUNA_ITEM_DROP_OFF_SECTOR_Z, MEDUNA_ITEM_DROP_OFF_GRIDNO, FALSE );
	}


	for(i=0; i<gpNewBobbyrShipments[ ubOrderNum ].ubNumberPurchases; i++)
	{
		// Count how many items were purchased
		usNumberOfItems += gpNewBobbyrShipments[ ubOrderNum ].BobbyRayPurchase[i].ubNumberPurchased;
	}

	//if we are NOT currently in the right sector
	if( !fSectorLoaded )
	{
		//build an array of objects to be added
		pObject = new OBJECTTYPE[ usNumberOfItems ];
		if( pObject == NULL )
			return;
	}


	uiCount = 0;

	//loop through the number of purchases
	for( i=0; i< gpNewBobbyrShipments->ubNumberPurchases; i++)
	{
		ubItemsDelivered = gpNewBobbyrShipments[ ubOrderNum ].BobbyRayPurchase[i].ubNumberPurchased;
		usItem = gpNewBobbyrShipments[ ubOrderNum ].BobbyRayPurchase[i].usItemIndex;

		CreateItem(usItem, 100, &gTempObject);//to get the ItemSlotLimit only!
		while ( ubItemsDelivered )
		{
			// treat 0s as 1s :-)
			ubTempNumItems = __min( ubItemsDelivered, ItemSlotLimit(&gTempObject, STACK_SIZE_LIMIT) );
			CreateItems( usItem, gpNewBobbyrShipments[ ubOrderNum ].BobbyRayPurchase[i].bItemQuality, ubTempNumItems, &gTempObject );

			// stack as many as possible
			if( fSectorLoaded )
			{
				AddItemToPool( MEDUNA_ITEM_DROP_OFF_GRIDNO, &gTempObject, -1, 0, 0, 0 );
			}
			else
			{
				pObject[ uiCount ] = gTempObject;
				uiCount++;
			}

			ubItemsDelivered -= ubTempNumItems;
		}
	}

	//if the sector WASNT loaded
	if( !fSectorLoaded )
	{
		//add all the items from the array that was built above

		//The item are to be added to the Top part of Drassen, grid loc's	10112, 9950
		if( !AddItemsToUnLoadedSector( MEDUNA_ITEM_DROP_OFF_SECTOR_X, MEDUNA_ITEM_DROP_OFF_SECTOR_Y, MEDUNA_ITEM_DROP_OFF_SECTOR_Z, MEDUNA_ITEM_DROP_OFF_GRIDNO, uiCount, pObject, 0, 0, 0, -1, FALSE ) )
		{
			//error
			Assert( 0 );
		}
		delete[]( pObject );
		pObject = NULL;
	}

	//mark that the shipment has arrived
	gpNewBobbyrShipments[ ubOrderNum ].fActive = FALSE;

	//Add an email from kulba telling the user the shipment is there
	AddEmail( BOBBY_R_MEDUNA_SHIPMENT, BOBBY_R_MEDUNA_SHIPMENT_LENGTH, BOBBY_R, GetWorldTotalMin(), -1 );
}
*/
