int StartGrid=mapRegions->StartGrid(source.x,source.y);
int line_of_sight(int s, Coord_cl &source, Coord_cl &target, int checkfor){/*Char (source.x, source.y, source.z) is the char(pc/npc), Target (target.x, target.y, target.z) is the target.s is for pc's, in case a message needs to be sent.the checkfor is what is checked for along the line of sight.Look at uox3.h to see options. Works like npc magic.#define TREES_BUSHES 1 // Trees and other large vegetaion in the way#define WALLS_CHIMNEYS 2	// Walls, chimineys, ovens, etc... in the way#define DOORS 4 // Doors in the way#define ROOFING_SLANTED 8	// So can't tele onto slanted roofs, basically#define FLOORS_FLAT_ROOFING 16	// For attacking between floors#define LAVA_WATER 32	// Don't know what all to use this for yet  Just or (|) the values for the diff things together to get what to search for.So put in place of the paramater checkfor for example	if (line_of_sight(s, source.x, source.y, source.z, target.x, target.y, target.z, WALLS_CHIMNEYS | DOORS | ROOFING_SLANTED))	  		This whole thing is based on the Pythagorean Theorem.  What I have done istaken the coordinates from both chars and created a right triange with thehypotenuse as the line of sight.  Then by sectioning off side "a" into a numberof equal lengths and finding the other sides lengths according to that one,  Ihave been able to find the coordinates of the tiles that lie along the line ofsight(line "c").  Then these tiles are searched from an item that would blockthe line of sight.*/		int a, b;	// Lengths of sides a & b	int zcheck=source.z, prexcheck=-128, preycheck=-128, prezcheck=-128;	short int xcheck = source.x, ycheck = source.y;	double c;	// Length of side c, Line of sight	float asquared, bsquared, csquared;	// Squares of a, b, c	double a_divide;	// this is how many times the entire line is checked	double a1_incrament= .1;	// the line is checked by this length incrament, can be chenged, the larger the num less checks, more misses	double a2_incrament= a1_incrament;	double c1_incrament, c2_incrament;	// c/a_divide, this give the length incrament along c	double b1_incrament, b2_incrament, aplus=0, bplus=0, a2plus=0, b2plus=0;	// the length of b1 at a1,c1	int checkcount;	char blocked=0;					// could potentially replace returning a char with a bool... you either see it or you don't (Abaddon)	char not_blocked=1;	double a2, b2, c2;	UOXFile *mfile;	st_multi multi;	map_st map1;	SI32 length, i,j;	/////what is checked for	int checkitemcount=0;	int checkthis[ITEM_TYPE_CHOICES];	int checkthistotal;	int itemtype;	/////item cahcing until item lookup is implimented	vector<P_ITEM> loscache;	if( ( source.x <= 200 && source.y<= 200 ) || ( target.x <= 200 && target.y <= 200 ) ) return not_blocked;	if( source.distance(target) > 18 ) return blocked;	///////////////////////////////////////////////////////////	///////////////// These next lines initialize arrays	/*	This function has to search the items array a number of times which	caused a bit of lag. I made this item cache to be used instead.	The items array is only search once for items in a 40 tile area.	if an item is found, it is put into the cache, which is then used	by the rest of the function. This way it doesn't have to check the	entire array each time.	*/	// - Tauriel's region stuff 3/6/99	int StartGrid=mapRegions->StartGrid(source.x,source.y);	unsigned long loopexit=0;		// - This needs to use a pointer/array to cut down on walking lag...	cRegion::RegionIterator4Items ri(source);	for (ri.Begin(); ri.GetData() != ri.End(); ri++)	{		P_ITEM mapitem = ri.GetData();		if (mapitem != NULL)		{			if (				(mapitem->pos.x<= source.x +20)&&				(mapitem->pos.x>= source.x -20)&&				(mapitem->pos.y<= source.y +20)&&				(mapitem->pos.y>= source.y -20)				)			{				loscache.push_back(mapitem);			}		}	}	for (i=0;i<ITEM_TYPE_CHOICES; i++) checkthis[i] = 0 ; //Null is for pointer types	// Zippy moved ----^ to main for initalization.			////////////End Initilzations	//////////////////////////////////////////////////////////////	/*	char(player/npc)	1 2  *_____a_____	1      \          |	2        \        |	c      b   x -->	\    |   y  ^	\  |      |	\|	*	target	*/		if ((target.x==65535)&&(target.y==65535)) return not_blocked;	// target cancled			a=abs(source.x-target.x)+1;	// length of side a	b=abs(source.y-target.y)+1;	// length of side b	asquared = static_cast<float>((a * a));	bsquared = static_cast<float>((b * b));	csquared=(asquared + bsquared);	c=sqrt(csquared);// length of c(hypotenuse==line of sight)		a_divide = (a / a1_incrament);	c1_incrament = (c / a_divide);		if(a==1)	{		c1_incrament=1;		a1_incrament=0;		a_divide = b;	}		b1_incrament=sqrt(fabs((c1_incrament*c1_incrament)-(a1_incrament*a1_incrament)));	if (b==1)	{		a1_incrament=1;		a_divide=a;		b1_incrament=0;	}	//////////////////////////////////////////////////////////	// X position	if (target.x == source.x) // Target has same x value	{		a1_incrament = 0; //(a1_incrament * 0); // sets x incraments to zero, no incrament	}	else if (target.x > source.x) // Target has greater x value	{		//a1_incrament = (a1_incrament * 1); // sets x incrament positive	}	else // Target has lesser x value	{		a1_incrament *= -1; //(a1_incrament * -1); // sets x incrament negative, postitive initially	}		// Y position	if (target.y == source.y) // Target has same y value	{		b1_incrament = 0; //(b1_incrament * 0); // sets y incrament to zero, no incrament	}	else if (target.y > source.y) // Target has greater y value	{		//b1_incrament = (b1_incrament * 1); // sets y incraments positive	}	else if (target.y < source.y) // Target has lesser y value	{		b1_incrament *= -1; //(b1_incrament * -1);	// sets y incrament negative, it's positive initially	}	//////////////////////////////////////////////////////////////////////////////	/*	To find the tiles along the z axis another right triangle is formed. This triangle	is formed along the line of sight between Char1 & Target, where the length of that line	is the length of the base of the triange. The hiegth of the triangle is the targets z	position. We now have two sides, and to find the third we use the pathagorean theorem	again, and that gives us the true line of sight in 3 dimentions: X, Y, Z.		*/	a2=c;	// length of base	b2=abs(target.z-source.z)+1;	// hieght of side	asquared = static_cast<float>((a2 * a2));	bsquared = static_cast<float>((b2 * b2));	csquared=(asquared + bsquared);	c2=sqrt(csquared); // length of true line of sight 3D		a_divide = (a2 / a2_incrament);	c2_incrament = (c2 / a_divide);	b2_incrament=sqrt(fabs((c2_incrament*c2_incrament)-(a2_incrament*a2_incrament)));		if (source.z>target.z) // going down	{		b2_incrament = (b2_incrament * -1);	}	else if (source.z==target.z) // level ground	{		b2_incrament = 0;	}		aplus = a1_incrament;	bplus = b1_incrament;	b2plus = b2_incrament; // going up or down	////////////////////////////////////////////////////////	//////////////// This determines what to check for	i = 0;	itemtype = 1;	checkthistotal = 0;	loopexit = 0;	while ( (checkfor) && (++loopexit < MAXLOOPS) )	{		if ( ( checkfor >= itemtype ) && ( checkfor < ( itemtype * 2 ) ) && ( checkfor ) )		{			checkthis[i] = itemtype;			i++;			checkfor = (checkfor - itemtype);			checkthistotal++;			itemtype = 1;		}		else			if ( checkfor )			{				itemtype = (itemtype * 2);			}	}	///////////////////////////////////////////////////////////////////////////	//////////////////// This next stuff is what searches each tile for things	for (checkcount = 1; checkcount <= a_divide; checkcount++)	{		if (xcheck != target.x) xcheck = int(source.x + aplus); // x coord to check		if (ycheck != target.y) ycheck = int(source.y + bplus); // y coord to check		if (zcheck != target.z) zcheck = int(source.z + b2plus); // z coord to check		if ((xcheck!=prexcheck)||(ycheck!=preycheck)||(zcheck!=prezcheck))		{			// Texture mapping			//source.xcheck=xcheck/8; // Block			//source.ycheck=ycheck/8;			//xoff=(xcheck-(source.xcheck*8)); // Offset			//yoff=(ycheck-(y1check*8));			map1 = Map->SeekMap0( xcheck, ycheck );			if (map1.id!=2)			{				if ( // Mountain walls					((map1.id>=431)&&(map1.id<=432))||					((map1.id>=467)&&(map1.id<=475))||					((map1.id>=543)&&(map1.id<=560))||					((map1.id>=1754)&&(map1.id<=1757))||					((map1.id>=1787)&&(map1.id<=1789))||					((map1.id>=1821)&&(map1.id<=1824))||					((map1.id>=1851)&&(map1.id<=1854))||					((map1.id>=1881)&&(map1.id<=1884))					)				{					//sysmessage(s, "There seems to be something in the way!");					return blocked;				}			}						// Statics			MapStaticIterator msi(xcheck, ycheck);			tile_st tile;			staticrecord *stat;			loopexit=0;			while ( (stat = msi.Next()) && (++loopexit < MAXLOOPS) )			{				msi.GetTile(&tile);				if ( (zcheck >= stat->zoff ) && ( zcheck <= ( stat->zoff + tile.height ) ) )				{#ifdef CORREA_LOS_OPTIMIZATION					if (cMapStuff::DoesTileBlock( tile ))						return blocked;					else					{						itemids[checkitemcount]=stat->itemid;						checkitemcount++;					}#else					itemids[checkitemcount]=stat->itemid;					checkitemcount++;#endif				}// if			}						// Items			for (i = 0; i < loscache.size(); i++)			{				P_ITEM pi = loscache[i];				if (pi->id1<0x40)				{ // Dynamic items					if ( (pi->pos.x==xcheck) && (pi->pos.y==ycheck) && (zcheck >= pi->pos.z) && (pi->visible==0)) // Seek file only when necessary					{						Map->SeekTile(pi->id(), &tile);						if ( ( zcheck <= ( pi->pos.z + tile.height ) ) )						{#ifdef CORREA_LOS_OPTIMIZATION							if (cMapStuff::DoesTileBlock( tile ))								return blocked;							else							{								itemids[checkitemcount] = pi->id();								checkitemcount++;							}#else							itemids[checkitemcount] = pi->id();							checkitemcount++;#endif						}					}				}				else				{// Multi's					if ((abs(source.x-target.x)<=BUILDRANGE)&&(abs(source.y-target.y)<=BUILDRANGE))					{						Map->SeekMulti(pi->id()-0x4000, &mfile, &length);						length=length/sizeof(st_multi);						if (length == -1 || length>=17000000)//Too big... bug fix hopefully (Abaddon 13 Sept 1999)							//							if (length == -1)						{							clConsole.send("LoS - Bad length in multi file. Avoiding stall.\n");							length = 0;						}						for (j=0;j<length;j++)						{							mfile->get_st_multi(&multi);							if ((multi.visible)&&								(pi->pos.x+multi.x == xcheck)&&								(pi->pos.y+multi.y == ycheck))							{								//pos=mfile->tell();								Map->SeekTile(multi.tile, &tile);								//mfile->seek(pos, SEEK_SET);								if ((zcheck>=pi->pos.z+multi.z)&&									(zcheck<=(pi->pos.z+multi.z + tile.height)))								{									itemids[checkitemcount]=multi.tile;									checkitemcount++;								}							}						}					}				}// end else			} // for			if ((xcheck==target.x)&&(ycheck==target.y)&&(zcheck==target.z)) checkcount=int(a_divide+1);			prexcheck=xcheck;			preycheck=ycheck;			prezcheck=zcheck;		} // if statment		if (xcheck!=target.x) aplus=aplus+a1_incrament;		if (ycheck!=target.y) bplus=bplus+b1_incrament;		if (zcheck!=target.z) b2plus=b2plus+b2_incrament;	} // for loop 	for (i=0;i<checkitemcount;i++)	{		for (j=0;j<checkthistotal;j++)		{			switch(checkthis[j])			{			case 1 : // Trees, Shrubs, bushes				if (isTree_Bushe(itemids[i]))				{//					sysmessage(s, "You can't see the forest for the trees!");					return blocked;				}				break;			case 2 : // Walls, Chimneys, ovens, not fences				if (isWall_Chimney(itemids[i]))				{//					sysmessage(s, "There seems to be some sort of wall in the way!");					return blocked;				}				break;			case 4 : // Doors, not gates				if (isDoor(itemids[i]))				{//					sysmessage(s, "Only ghosts do things through doors!");					return blocked;				}				break;			case 8 : // Roofing Slanted				if (isRoofing_Slanted(itemids[i]))				{//					sysmessage(s, "The roof is too steep!");					return blocked;				}				break;			case 16 : // Floors & Flat Roofing (Attacking through floors Roofs)				if (isFloor_Flat_Roofing(itemids[i]))				{					if (source.z==target.z) // in case of char and target on same roof					{						return not_blocked;					}					else					{//						sysmessage(s, "You would love to do that, but the is a floor in the way!");						return blocked;					}				}				break;			case 32 :	// Lava, water				if (isLavaWater(itemids[i]))				{//					sysmessage(s, "Yah, you wish!");					return blocked;				}				break;			default:				clConsole.send("ERROR: Fallout of switch statement without default. LoS.cpp, line_of_sight()"); //Morrolan				return not_blocked;			} // switch		} //for	} //for	return not_blocked;} //function