Ejemplo n.º 1
0
void ReplaceBuildingWithNewRoof( INT32 iMapIndex )
{
	UINT16 usRoofType;
	ROOFNODE *curr;
	//Not in normal editor mode, then can't do it.
	if( gfBasement || gfCaves )
		return;
	//if we don't have a floor here, then we can't replace the roof!
	if( !FloorAtGridNo( iMapIndex ) )
		return;
	//Extract the selected roof type.
	usRoofType = (UINT16)SelSingleNewRoof[ iCurBank ].uiObject;

	//now start building a linked list of all nodes visited -- start the first node.
	gpRoofList = (ROOFNODE*)MemAlloc( sizeof( ROOFNODE ) );
	Assert( gpRoofList );
	gpRoofList->iMapIndex = iMapIndex;
	gpRoofList->next = 0;
	RebuildRoofUsingFloorInfo( iMapIndex, usRoofType );

	//Use recursion to process the remainder.
	ReplaceRoof( iMapIndex - WORLD_COLS, usRoofType );
	ReplaceRoof( iMapIndex + WORLD_COLS, usRoofType );
	ReplaceRoof( iMapIndex - 1, usRoofType );
	ReplaceRoof( iMapIndex + 1, usRoofType );

	//Done, so delete the list.
	while( gpRoofList )
	{
		curr = gpRoofList;
		gpRoofList = gpRoofList->next;
		MemFree( curr );
	}
	gpRoofList = NULL;
}
Ejemplo n.º 2
0
void ReplaceRoof( INT32 iMapIndex, UINT16 usRoofType )
{
	ROOFNODE *curr;
	//First, validate the gridno
	if( iMapIndex < 0 && iMapIndex >= WORLD_COLS*WORLD_ROWS )
		return;
	//Now, check if there is a floor here
	if( !FloorAtGridNo( iMapIndex ) )
		return;
	//Now, check to make sure this gridno hasn't already been processed.
	curr = gpRoofList;
	while( curr )
	{
		if( iMapIndex == curr->iMapIndex )
			return;
		curr = curr->next;
	}
	//Good, it hasn't, so process it and add it to the head of the list.
	curr = (ROOFNODE*)MemAlloc( sizeof( ROOFNODE ) );
	Assert( curr );
	curr->iMapIndex = iMapIndex;
	curr->next = gpRoofList;
	gpRoofList = curr;

	RebuildRoofUsingFloorInfo( iMapIndex, usRoofType );

	//Use recursion to process the remainder.
	ReplaceRoof( iMapIndex - WORLD_COLS, usRoofType );
	ReplaceRoof( iMapIndex + WORLD_COLS, usRoofType );
	ReplaceRoof( iMapIndex - 1, usRoofType );
	ReplaceRoof( iMapIndex + 1, usRoofType );
}
Ejemplo n.º 3
0
//Specialized function that will delete only the TOP_RIGHT oriented wall in the gridno to the left
//and the TOP_LEFT oriented wall in the gridno up one as well as the other building information at this
//gridno.
void EraseFloorOwnedBuildingPieces( UINT32 iMapIndex )
{	
	LEVELNODE	*pStruct = NULL;
	UINT32 uiTileType;
	UINT16 usWallOrientation;

	if( !gfBasement && !FloorAtGridNo( iMapIndex ) )
	{	//We don't have ownership issues if there isn't a floor here.
		return;
	}
	EraseBuilding( iMapIndex );
	//FIRST, SEARCH AND DESTROY FOR A LEFT NEIGHBORING TILE WITH A TOP_RIGHT ORIENTED WALL
	pStruct = gpWorldLevelData[ iMapIndex - 1 ].pStructHead;
	while( pStruct != NULL )
	{
		if ( pStruct->usIndex != NO_TILE )
		{
			GetTileType( pStruct->usIndex, &uiTileType );
			if ( uiTileType >= FIRSTWALL && uiTileType <= LASTWALL ||
					 uiTileType >= FIRSTDOOR && uiTileType <= LASTDOOR )
			{
				GetWallOrientation( pStruct->usIndex, &usWallOrientation );
				if( usWallOrientation == INSIDE_TOP_RIGHT || usWallOrientation == OUTSIDE_TOP_RIGHT )
				{
					AddToUndoList( iMapIndex - 1 );
					RemoveStruct( iMapIndex - 1, pStruct->usIndex );
					RemoveAllShadowsOfTypeRange( iMapIndex - 1, FIRSTWALL, LASTWALL );
					break; //otherwise, it'll crash because pStruct is toast.
				}
			}
		}
		pStruct = pStruct->pNext;
	}
	//FINALLY, SEARCH AND DESTROY FOR A TOP NEIGHBORING TILE WITH A TOP_LEFT ORIENTED WALL
	pStruct = gpWorldLevelData[ iMapIndex - WORLD_COLS ].pStructHead;
	while( pStruct != NULL )
	{
		if ( pStruct->usIndex != NO_TILE )
		{
			GetTileType( pStruct->usIndex, &uiTileType );
			if ( uiTileType >= FIRSTWALL && uiTileType <= LASTWALL ||
					 uiTileType >= FIRSTDOOR && uiTileType <= LASTDOOR )
			{
				GetWallOrientation( pStruct->usIndex, &usWallOrientation );
				if( usWallOrientation == INSIDE_TOP_LEFT || usWallOrientation == OUTSIDE_TOP_LEFT )
				{
					AddToUndoList( iMapIndex - WORLD_COLS );
					RemoveStruct( iMapIndex - WORLD_COLS , pStruct->usIndex );
					RemoveAllShadowsOfTypeRange( iMapIndex - WORLD_COLS, FIRSTWALL, LASTWALL );
					break; //otherwise, it'll crash because pStruct is toast.
				}
			}
		}
		pStruct = pStruct->pNext;
	}
}
Ejemplo n.º 4
0
void RebuildRoofUsingFloorInfo( INT32 iMapIndex, UINT16 usRoofType )
{
	UINT16 usRoofIndex, usTileIndex;
	BOOLEAN fTop = FALSE, fBottom = FALSE, fLeft = FALSE, fRight = FALSE;
	if( !usRoofType )
	{
		usRoofType = SearchForRoofType( iMapIndex );
	}
	if( usRoofType == 0xffff )
		return;  //no roof type around, so don't draw one.
	//Analyse the mapindex for walls and set the flags.
	//NOTE:  There is no support for more than 2 side on a roof, so if there is, draw TOPLEFT
	AddToUndoList( iMapIndex );
	EraseRoof( iMapIndex );

	fTop = FloorAtGridNo( iMapIndex - WORLD_COLS ) ? FALSE : TRUE;
	fLeft = FloorAtGridNo( iMapIndex - 1 ) ? FALSE : TRUE;
	fBottom = FloorAtGridNo( iMapIndex + WORLD_COLS ) ? FALSE : TRUE;
	fRight = FloorAtGridNo( iMapIndex + 1 ) ? FALSE : TRUE;
	if( fTop && fLeft )						usRoofIndex = TOPLEFT_ROOF_INDEX;
	else if( fTop && fRight)			usRoofIndex = TOPRIGHT_ROOF_INDEX;
	else if( fBottom && fLeft )		usRoofIndex = BOTTOMLEFT_ROOF_INDEX;
	else if( fBottom && fRight )	usRoofIndex = BOTTOMRIGHT_ROOF_INDEX;
	else if( fTop )								usRoofIndex = TOP_ROOF_INDEX;
	else if( fBottom )						usRoofIndex = BOTTOM_ROOF_INDEX;
	else if( fLeft )							usRoofIndex = LEFT_ROOF_INDEX;
	else if( fRight )							usRoofIndex = RIGHT_ROOF_INDEX;
	else													usRoofIndex = CENTER_ROOF_BASE_INDEX + ( rand() % CENTER_ROOF_VARIANTS );
	GetTileIndexFromTypeSubIndex( usRoofType, usRoofIndex, &usTileIndex );
	AddRoofToHead( iMapIndex, usTileIndex );
	//if the editor view roofs is off, then the new roofs need to be hidden.
	if( !fBuildingShowRoofs )
	{
		HideStructOfGivenType( iMapIndex, usRoofType, TRUE );
	}
}
Ejemplo n.º 5
0
void AddBuildingSectionToWorld( SGPRect *pSelectRegion )
{
	INT32 top, left, right, bottom, x, y;
	UINT32 iMapIndex;
	UINT16 usFloorType, usWallType, usRoofType;
	UINT16 usTileIndex;
	BOOLEAN fNewBuilding;
	BOOLEAN fSlantRoof = FALSE;
	BOOLEAN fVertical;
	BOOLEAN fFloor;
	top = pSelectRegion->iTop;
	left = pSelectRegion->iLeft;
	right = pSelectRegion->iRight;
	bottom = pSelectRegion->iBottom;

	//Special case scenario:
	//If the user selects a floor without walls, then it is implied that the user wishes to 
	//change the floor for say a kitchen which might have a different floor type.
	usWallType = GetRandomIndexByRange( FIRSTWALL, LASTWALL );
	usFloorType = GetRandomIndexByRange( FIRSTFLOOR, LASTFLOOR );
	if( usWallType == 0xffff && usFloorType != 0xffff )
	{ //allow user to place floors
		for( y = top; y <= bottom; y++ ) for( x = left; x <= right; x++ )
		{
			iMapIndex = y * WORLD_COLS + x;
			EraseFloor( iMapIndex );
			GetTileIndexFromTypeSubIndex( usFloorType, 1, &usTileIndex );
			AddLandToHead( iMapIndex, (UINT16)( usTileIndex + Random( FLOOR_VARIANTS ) ) );
		}
		//we are done!
		return;
	}

	//1ST PASS:  Determine if there are any floor tiles in this region.  If there are, then
	//  that signifies that we are concantenating this building to an existing one.  Otherwise,
	//  we are just drawing an individual building.  If we find a floor, extract the type so
	//  we know how to draw it later.
	fNewBuilding = TRUE;
	for( y = top; y <= bottom; y++ ) for( x = left; x <= right; x++ )
	{
		iMapIndex = y * WORLD_COLS + x;
		if( FloorAtGridNo( iMapIndex ) )
		{
			LEVELNODE *pFloor;
			UINT32 uiTileType;
			//If a floor is found, then we are adding to an existing structure.
			fNewBuilding = FALSE;
			//Extract the floor type.  We already checked if there was a floor here, so it is assumed.
			pFloor = gpWorldLevelData[ iMapIndex ].pLandHead;
			while( pFloor )
			{
				GetTileType( pFloor->usIndex, &uiTileType );
				if( uiTileType >= FIRSTFLOOR && uiTileType <= LASTFLOOR )
				{	
					usFloorType = (UINT16)uiTileType;
					break;
				}
			}
			usWallType = SearchForWallType( iMapIndex );
			usRoofType = SearchForRoofType( iMapIndex );
			if( usWallType != 0xffff && usRoofType != 0xffff && usFloorType !=0xffff )
			{	//we have extracted all of the information we need, so we can break out.
				y = bottom;
				break;
			}
		}
	}
	
	if( fNewBuilding )
	{
		//if( gfBasement )
		//	return;
		//Get materials via selection window method.
		usWallType = GetRandomIndexByRange( FIRSTWALL, LASTWALL );
		usFloorType = GetRandomIndexByRange( FIRSTFLOOR, LASTFLOOR );
		usRoofType = GetRandomIndexByRange( FIRSTROOF, LASTROOF );
		if( usRoofType == 0xffff )
		{
			usRoofType = GetRandomIndexByRange( FIRSTSLANTROOF, LASTSLANTROOF );
			if( usRoofType != 0xffff )
			{
				if( !gfBasement )
					fSlantRoof = TRUE;
				else
					usRoofType = FIRSTROOF;
			}
		}
		if( usWallType == 0xffff )
			return;
	}

	//2ND PASS:  Remove all walls in the region that border no floor tile, or simply walls
	//  that are considered exterior walls.  That way, it won't wreck the inside of a building
	//  if you select too much interior.  Also, gridnos that delete walls will also delete the 
	//  floor and roof tiles there.  That signifies that the floorless parts will be resmoothed, 
	//  and rebuilt in the third pass.
	for( y = top; y <= bottom; y++ ) for( x = left; x <= right; x++ )
	{
		iMapIndex = y * WORLD_COLS + x;
		if( gfBasement )
		{
			EraseBuilding( iMapIndex );			
		}
		else if( FloorAtGridNo( iMapIndex ) && !fNewBuilding) 
		{
			if( y >= top && !FloorAtGridNo( iMapIndex - WORLD_COLS ) )
			{
				EraseHorizontalWall( iMapIndex - WORLD_COLS );
				EraseFloor( iMapIndex );
				EraseRoof( iMapIndex );
			}
			if( y <= bottom && !FloorAtGridNo( iMapIndex + WORLD_COLS ) )
			{
				EraseHorizontalWall( iMapIndex );
				EraseFloor( iMapIndex );
				EraseRoof( iMapIndex );
			}
			if( x >= left && !FloorAtGridNo( iMapIndex - 1 ) )
			{
				EraseVerticalWall( iMapIndex - 1 );
				EraseFloor( iMapIndex );
				EraseRoof( iMapIndex );
			}
			if( x <= right && !FloorAtGridNo( iMapIndex + 1 ) )
			{
				EraseVerticalWall( iMapIndex );
				EraseFloor( iMapIndex );
				EraseRoof( iMapIndex );
			}
		}
		else	//we will be building outside of this structure, so bulldoze the nature -- trees, rocks, etc.
		{
			BulldozeNature( iMapIndex );
		}
	}
	//3RD PASS:  Process the region, and all walls of floorless tiles are rebuilt from interior perspective.
	for( y = top; y <= bottom; y++ ) for( x = left; x <= right; x++ )
	{
		iMapIndex = y * WORLD_COLS + x;
		if( !FloorAtGridNo( iMapIndex ) ) 
		{
			if( y == top && !GetHorizontalWall( iMapIndex - WORLD_COLS ) )
			{
				fFloor = FloorAtGridNo( iMapIndex - WORLD_COLS );
				if( gfBasement == fFloor )
					BuildWallPiece( iMapIndex, INTERIOR_TOP, usWallType);
			}
			if( y == bottom && !GetHorizontalWall( iMapIndex ) )
			{
				fFloor = FloorAtGridNo( iMapIndex + WORLD_COLS );
				if( gfBasement == fFloor )
					BuildWallPiece( iMapIndex, INTERIOR_BOTTOM, usWallType );
			}
			if( x == left && !GetVerticalWall( iMapIndex - 1 ) )
			{
				fFloor = FloorAtGridNo( iMapIndex - 1 );
				if( gfBasement == fFloor )
					BuildWallPiece( iMapIndex, INTERIOR_LEFT, usWallType );
			}
			if( x == right && !GetVerticalWall( iMapIndex ) )
			{
				fFloor = FloorAtGridNo( iMapIndex + 1 );
				if( gfBasement == fFloor )
					BuildWallPiece( iMapIndex, INTERIOR_RIGHT, usWallType );
			}
		}
	}

	//If we are dealing with slant roofs then build the whole thing now.
	//Slant roofs always have a width or height of 8 tiles.
	if( fSlantRoof )
	{
		fVertical = (bottom - top == 7) ? FALSE : TRUE;
		BuildSlantRoof( left, top, right, bottom, usWallType, usRoofType, fVertical ); 
	}

	//4TH PASS:  Process the region, and all floorless tiles get new roofs and floors.
	for( y = top; y <= bottom; y++ ) for( x = left; x <= right; x++ )
	{
		iMapIndex = y * WORLD_COLS + x;
		if( !FloorAtGridNo( iMapIndex ) ) 
		{
			if( !fSlantRoof )
				RebuildRoof( iMapIndex, usRoofType );
			if( usFloorType != 0xffff && !gfBasement )
			{
				GetTileIndexFromTypeSubIndex( usFloorType, 1, &usTileIndex );
				AddLandToHead( iMapIndex, (UINT16)( usTileIndex + Random( FLOOR_VARIANTS ) ) );
			}
		}
	}
}
Ejemplo n.º 6
0
//When the user removes a section from a building, it will not only erase the 
//entire highlighted area, it'll repair the building itself so there are no
//outside walls missing from the new building. 
void RemoveBuildingSectionFromWorld( SGPRect *pSelectRegion )
{
	UINT32 top, left, right, bottom, x, y;
	UINT32 iMapIndex;
	UINT16 usTileIndex;
	UINT16 usFloorType;
	BOOLEAN fFloor;

	top = pSelectRegion->iTop;
	left = pSelectRegion->iLeft;
	right = pSelectRegion->iRight;
	bottom = pSelectRegion->iBottom;

	//1ST PASS:  Erase all building owned by the floor tile if there is one.
	for( y = top; y <= bottom; y++ ) for( x = left; x <= right; x++ )
	{
		iMapIndex = y * WORLD_COLS + x;
		EraseFloorOwnedBuildingPieces( iMapIndex ); //Erase possible top and left walls in bordering tiles.
	}
	//2ND PASS:  Build new walls whereever there are neighboring floor tiles.
	for( y = top; y <= bottom; y++ ) for( x = left; x <= right; x++ )
	{
		iMapIndex = y * WORLD_COLS + x;
		//NOTE:  Top and bottom walls MUST be placed first -- it minimizes the number of special cases.
		if( y == top )
		{
			fFloor = FloorAtGridNo( iMapIndex - WORLD_COLS );
			if( gfBasement && !fFloor || !gfBasement && fFloor && !GetHorizontalWall( iMapIndex - WORLD_COLS ) )
				BuildWallPiece( iMapIndex, EXTERIOR_TOP, 0 );
		}
		if( y == bottom )
		{
			fFloor = FloorAtGridNo( iMapIndex + WORLD_COLS );
			if( gfBasement && !fFloor || !gfBasement && fFloor && !GetHorizontalWall( iMapIndex ) )
				BuildWallPiece( iMapIndex, EXTERIOR_BOTTOM, 0 );
		}
		if( x == left )
		{
			fFloor = FloorAtGridNo( iMapIndex - 1 );
			if( gfBasement && !fFloor || !gfBasement && fFloor && !GetVerticalWall( iMapIndex - 1 ) )
				BuildWallPiece( iMapIndex, EXTERIOR_LEFT, 0 );
		}
		if( x == right )
		{
			fFloor = FloorAtGridNo( iMapIndex + 1);
			if( gfBasement && !fFloor || !gfBasement && fFloor && !GetVerticalWall( iMapIndex ) ) 
				BuildWallPiece( iMapIndex, EXTERIOR_RIGHT, 0 );
		}
	}
	//3RD PASS:  Go around the outside of the region, and rebuild the roof.
	if( gfBasement )
	{
		usFloorType = GetRandomIndexByRange( FIRSTFLOOR, LASTFLOOR );
		if( usFloorType == 0xffff ) 
			usFloorType = FIRSTFLOOR;
		for( y = top; y <= bottom; y++ ) for( x = left; x <= right; x++ )
		{
			iMapIndex = y * WORLD_COLS + x;
			GetTileIndexFromTypeSubIndex( usFloorType, 1, &usTileIndex );
			AddLandToHead( iMapIndex, (UINT16)( usTileIndex + Random( FLOOR_VARIANTS ) ) );
		}
	}
	for( y = top - 1; y <= bottom + 1; y++ ) for( x = left - 1; x <= right + 1; x++ )
	{
		iMapIndex = y * WORLD_COLS + x;
		if( y == top - 1 || y == bottom + 1 || x == left - 1 || x == right + 1 )
		{
			if( !gfBasement && FloorAtGridNo( iMapIndex ) || gfBasement && !FloorAtGridNo( iMapIndex ) )
			{
				RebuildRoof( iMapIndex, 0 );
			}
		}
	}
}
Ejemplo n.º 7
0
//From a given gridNo and perspective (wallpiece), it will calculate the new piece, and 
//where to place it as well as handle the special cases.
//NOTE:  Placing top and left pieces are placed relative to the gridno, and the gridNo will
// shift accordingly to place the piece.  Pretend you are the floor, and you want to place a piece to
// the left.  You pass your position, and INTERIOR_LEFT, with interior meaning from the inside of a 
// building.  If you were outside the building, you would call EXTERIOR_LEFT.  The left tile will be 
// placed on gridNo - 1!  Up tiles will be placed on gridNo - 160.
//NOTE:  Passing NULL for usWallType will force it to calculate the closest existing wall type, and
//  use that for building this new wall.  It is necessary for restructuring a building, but not for
//  adding on to an existing building, where the type is already known.
void BuildWallPiece( UINT32 iMapIndex, UINT8 ubWallPiece, UINT16 usWallType )
{
	INT16 sIndex;
	UINT16 usTileIndex;
	UINT16 ubWallClass;
	LEVELNODE *pStruct;
	if( !usWallType )
	{
		usWallType = SearchForWallType( iMapIndex );
	}
	switch( ubWallPiece )
	{
		case EXTERIOR_TOP:
			iMapIndex -= WORLD_COLS;
			//exterior bottom left corner generated
			if ( !gfBasement && GetVerticalWall( iMapIndex - 1) && !GetVerticalWall( iMapIndex + WORLD_COLS - 1) )
			{	//Special case where a shadow has to be created as it now is a bottom corner and
				//must contribute to the bottom shadow.
				AddToUndoList( iMapIndex - 1 );
				GetTileIndexFromTypeSubIndex( usWallType, INTERIOR_BOTTOMEND_SHADOW_INDEX, &usTileIndex );
				AddExclusiveShadow( iMapIndex - 1, usTileIndex );
			}
			if ( pStruct = GetVerticalWall( iMapIndex ) ) //right corner
			{	//Special case where placing the new wall will generate a corner to the right, so replace 
				//the vertical piece with a bottomend.
				sIndex = PickAWallPiece( EXTERIOR_BOTTOMEND );
				AddToUndoList( iMapIndex );
				GetTileIndexFromTypeSubIndex( usWallType, sIndex, &usTileIndex );
				ReplaceStructIndex( iMapIndex, pStruct->usIndex, usTileIndex );
			}
			ubWallClass = EXTERIOR_L;
			if( !gfBasement )
			{
				//All exterior_l walls have shadows.
				GetTileIndexFromTypeSubIndex( usWallType, EXTERIOR_L_SHADOW_INDEX, &usTileIndex );
				AddExclusiveShadow( iMapIndex, usTileIndex );
			}
			break;
		case EXTERIOR_BOTTOM:
			ubWallClass = INTERIOR_L;
			if( (pStruct = GetVerticalWall( iMapIndex + WORLD_COLS - 1 )) && !GetVerticalWall( iMapIndex - 1) )
			{
				sIndex = PickAWallPiece( INTERIOR_EXTENDED );
				AddToUndoList( iMapIndex + WORLD_COLS - 1 );
				GetTileIndexFromTypeSubIndex( usWallType, sIndex, &usTileIndex );
				ReplaceStructIndex( iMapIndex + WORLD_COLS - 1, pStruct->usIndex, usTileIndex );
			}
			break;
		case EXTERIOR_LEFT:
			iMapIndex--;
			ubWallClass = EXTERIOR_R;
			if( GetHorizontalWall( iMapIndex ) )
			{	//Special case where placing the new wall will generate a corner.  This piece
				//becomes an exterior bottomend, but nothing else is effected.
				ubWallClass = EXTERIOR_BOTTOMEND;
			}
			if( GetHorizontalWall( iMapIndex - WORLD_COLS + 1 ) )
			{
				if( ubWallClass == EXTERIOR_BOTTOMEND )
					ubWallClass = EXTERIOR_EXTENDED_BOTTOMEND;
				else
					ubWallClass = EXTERIOR_EXTENDED;
			}
			break;
		case EXTERIOR_RIGHT:
			ubWallClass = INTERIOR_R;
			if( GetHorizontalWall( iMapIndex - WORLD_COLS + 1 ) && !GetHorizontalWall( iMapIndex - WORLD_COLS ) )
			{
				ubWallClass = INTERIOR_EXTENDED;
			}
			else if( GetHorizontalWall( iMapIndex ) && !GetVerticalWall( iMapIndex + WORLD_COLS ) )
			{
				ubWallClass = INTERIOR_BOTTOMEND;
			}
			break;
		case INTERIOR_TOP:
			iMapIndex -= WORLD_COLS;
			ubWallClass = INTERIOR_L;
			//check for a lower left corner.
			if( pStruct = GetVerticalWall( iMapIndex + WORLD_COLS - 1 ) )
			{	//Replace the piece with an extended piece.
				sIndex = PickAWallPiece( INTERIOR_EXTENDED );
				AddToUndoList( iMapIndex + WORLD_COLS - 1 );
				GetTileIndexFromTypeSubIndex( usWallType, sIndex, &usTileIndex );
				ReplaceStructIndex( iMapIndex + WORLD_COLS - 1, pStruct->usIndex, usTileIndex );
				//NOTE:  Not yet checking for interior extended bottomend!
			}
			if( pStruct = GetVerticalWall( iMapIndex ) )
			{
				sIndex = PickAWallPiece( INTERIOR_BOTTOMEND );
				AddToUndoList( iMapIndex );
				GetTileIndexFromTypeSubIndex( usWallType, sIndex, &usTileIndex );
				ReplaceStructIndex( iMapIndex, pStruct->usIndex, usTileIndex );
			}
			break;
		case INTERIOR_BOTTOM:
			ubWallClass = EXTERIOR_L;
			if( pStruct = GetVerticalWall( iMapIndex ) ) //right corner
			{	//Special case where placing the new wall will generate a corner to the right, so replace 
				//the vertical piece with a bottomend.
				sIndex = PickAWallPiece( EXTERIOR_BOTTOMEND );
				AddToUndoList( iMapIndex );
				GetTileIndexFromTypeSubIndex( usWallType, sIndex, &usTileIndex );
				ReplaceStructIndex( iMapIndex, pStruct->usIndex, usTileIndex );
			}
			if( (pStruct = GetVerticalWall( iMapIndex + WORLD_COLS - 1 )) && !GetVerticalWall( iMapIndex - 1) )
			{
				sIndex = PickAWallPiece( EXTERIOR_EXTENDED );
				AddToUndoList( iMapIndex + WORLD_COLS - 1 );
				GetTileIndexFromTypeSubIndex( usWallType, sIndex, &usTileIndex );
				ReplaceStructIndex( iMapIndex + WORLD_COLS - 1, pStruct->usIndex, usTileIndex );
			}
			if( !gfBasement )
			{
				//All exterior_l walls have shadows.
				GetTileIndexFromTypeSubIndex( usWallType, EXTERIOR_L_SHADOW_INDEX, &usTileIndex );
				AddExclusiveShadow( iMapIndex, usTileIndex );
			}
			break;
		case INTERIOR_LEFT:
			iMapIndex--;
			ubWallClass = INTERIOR_R;
			if( GetHorizontalWall( iMapIndex ) )
			{
				ubWallClass = INTERIOR_BOTTOMEND;
			}
			if( !gfBasement && GetHorizontalWall( iMapIndex + 1 ) )
			{
				AddToUndoList( iMapIndex );
				GetTileIndexFromTypeSubIndex( usWallType, INTERIOR_BOTTOMEND_SHADOW_INDEX, &usTileIndex );
				AddExclusiveShadow( iMapIndex, usTileIndex );
			}
			if( GetHorizontalWall( iMapIndex - WORLD_COLS + 1 ) )
			{
				if( ubWallClass == INTERIOR_BOTTOMEND )
					ubWallClass = INTERIOR_EXTENDED_BOTTOMEND;
				else
					ubWallClass = INTERIOR_EXTENDED;
			}
			break;
		case INTERIOR_RIGHT:
			ubWallClass = EXTERIOR_R;
			if( GetHorizontalWall( iMapIndex ) )
			{	//Special case where placing the new wall will generate a corner.  This piece
				//becomes an exterior bottomend, but nothing else is effected.
				ubWallClass = EXTERIOR_BOTTOMEND;
			}
			if( GetHorizontalWall( iMapIndex - WORLD_COLS + 1 ) )
			{
				if( ubWallClass == EXTERIOR_BOTTOMEND )
					ubWallClass = EXTERIOR_EXTENDED_BOTTOMEND;
				else
					ubWallClass = EXTERIOR_EXTENDED;
			}
			if( !gfBasement && GetHorizontalWall( iMapIndex + 1 ) && !GetHorizontalWall( iMapIndex ) 
				  && !FloorAtGridNo( iMapIndex + WORLD_COLS ) )
			{
				GetTileIndexFromTypeSubIndex( usWallType, INTERIOR_BOTTOMEND_SHADOW_INDEX, &usTileIndex );
				AddExclusiveShadow( iMapIndex, usTileIndex );
			}
			break;
	}
	sIndex = PickAWallPiece( ubWallClass );
	GetTileIndexFromTypeSubIndex( usWallType, sIndex, &usTileIndex );
	AddToUndoList( iMapIndex );
	AddWallToStructLayer( iMapIndex, usTileIndex, FALSE );
}
Ejemplo n.º 8
0
//This is a very difficult function to document properly.	The reason being is that it is sooo
//subliminal by nature.	I have thought up of priorities and choose the best piece to draw based
//on the surrounding conditions.	Here are the priorities which are referenced below via comments:
//A)	If there is currently a bottom piece and a right piece, immediately exit.
//B)	We are currently over a bottom piece.	Now, we don't automatically want to draw a right piece here
//		for multiple reasons.	First, the UI will be too quick and place bottom and right pieces for every
//		place the user clicks, which isn't what we want.	Therefore, we look to see if there is a right
//	piece in the y-1 gridno.	It would then make sense to place a right piece down here.	Regardless,
//		if we encounter a bottom piece here, we will exit.
//C)	This is the counterpart to B, but we are looking at a current right piece, and are determining if
//		we should place a bottom piece based on another bottom piece existing in the x-1 gridno.
//D)	Now, we analyse the neighboring tiles and determine the orientations that would add weight to the
//	current tile either towards drawing a horizontal piece or a vertical piece.
//E)	Now that we have the information, we give the highest priority to any weights that match the current
//		wall piece type selected by the user.	Based on that, we will only consider the best match of the
//		type and use it.	If there are no matches on type, we continue.
//F)	We failed to find weights matching the current wall type, but before we give up using the user's wall
//		type, there are two more cases.	When there is a bottom wall in the y+1 position or a right wall in
//		the x+1 position.	If there are matching walls, there, then we draw two pieces to connect the current
//		gridno with the respective position.
void PasteSmartWall( INT32 iMapIndex )
{
	static BOOLEAN fWallAlone = FALSE;
	static UINT32 iAloneMapIndex = 0x80000000;
	UINT16 usWallType;

	//These are the counters for the walls of each type
	UINT16 usNumV[4]={0,0,0,0}; //vertical wall weights
	UINT16 usNumH[4]={0,0,0,0}; //horizontal wall weights

	//*A* See above documentation
	if( GetVerticalWall( iMapIndex ) && GetHorizontalWall( iMapIndex ) )
		return;
	//*B* See above documentation
	usWallType = GetHorizontalWallType( iMapIndex );
	if( usWallType )
	{
		if( usWallType == gubWallUIValue )
		{
			usWallType = GetVerticalWallType( iMapIndex - WORLD_COLS );
			if( usWallType == gubWallUIValue )
			{
				if( FloorAtGridNo( iMapIndex + 1 ) )
					BuildWallPiece( iMapIndex, EXTERIOR_RIGHT, gubWallUIValue );
				else
					BuildWallPiece( iMapIndex, INTERIOR_RIGHT, gubWallUIValue );
				return;
			}
			usWallType = GetHorizontalWallType( iMapIndex - WORLD_COLS );
			if( usWallType == gubWallUIValue )
			{
				if( FloorAtGridNo( iMapIndex + 1 ) )
				{
					BuildWallPiece( iMapIndex, EXTERIOR_RIGHT, gubWallUIValue );
					if( !GetHorizontalWall( iMapIndex - WORLD_COLS + 1 ) )
						ChangeVerticalWall( iMapIndex, INTERIOR_EXTENDED );
				}
				else
				{
					BuildWallPiece( iMapIndex, INTERIOR_RIGHT, gubWallUIValue );
					if( !GetHorizontalWall( iMapIndex - WORLD_COLS + 1 ) )
						ChangeVerticalWall( iMapIndex, EXTERIOR_EXTENDED );
				}
			}
		}
		return;
	}
	//*C* See above documentation
	usWallType = GetVerticalWallType( iMapIndex );
	if( usWallType )
	{
		if( usWallType == gubWallUIValue )
		{
			usWallType = GetHorizontalWallType( iMapIndex - 1 );
			if( usWallType == gubWallUIValue )
			{
				if( FloorAtGridNo( iMapIndex + WORLD_COLS ) )
					BuildWallPiece( iMapIndex, EXTERIOR_BOTTOM, gubWallUIValue );
				else
					BuildWallPiece( iMapIndex, INTERIOR_BOTTOM, gubWallUIValue );
			}
		}
		return;
	}
	//*D* See above documentation
	//Evaluate left adjacent tile
	if( usWallType = GetVerticalWallType( iMapIndex - 1 ) )
		usNumH[ usWallType - FIRSTWALL ]++;
	if( usWallType = GetHorizontalWallType( iMapIndex - 1 ) )
		usNumH[ usWallType - FIRSTWALL ]++;
	//Evaluate right adjacent tile
	if( usWallType = GetHorizontalWallType( iMapIndex + 1 ) )
		usNumH[ usWallType - FIRSTWALL ]++;
	//Evaluate upper adjacent tile
	if( usWallType = GetVerticalWallType( iMapIndex - WORLD_COLS ) )
		usNumV[ usWallType - FIRSTWALL ]++;
	if( usWallType = GetHorizontalWallType( iMapIndex - WORLD_COLS ) )
		usNumV[ usWallType - FIRSTWALL ]++;
	//Evaluate lower adjacent tile
	if( usWallType = GetVerticalWallType( iMapIndex + WORLD_COLS ) )
		usNumV[ usWallType - FIRSTWALL ]++;
	//*E* See above documentation
	if( usNumV[gubWallUIValue - FIRSTWALL] | usNumH[gubWallUIValue - FIRSTWALL] )
	{
		if( usNumV[gubWallUIValue - FIRSTWALL] >= usNumH[gubWallUIValue - FIRSTWALL] )
		{
			if( FloorAtGridNo( iMapIndex + 1 ) )
			{ //inside
				BuildWallPiece( iMapIndex, EXTERIOR_RIGHT, gubWallUIValue );
				//Change to extended piece if it is a new top right corner to cover the end part.
				if( GetHorizontalWall( iMapIndex - WORLD_COLS ) && !GetHorizontalWall( iMapIndex - WORLD_COLS + 1 )
						&& !GetVerticalWall( iMapIndex - WORLD_COLS ) )
					ChangeVerticalWall( iMapIndex, INTERIOR_EXTENDED );
				else if( GetHorizontalWall( iMapIndex - WORLD_COLS ) && !GetHorizontalWall( iMapIndex - WORLD_COLS - 1 )
								&& !GetVerticalWall( iMapIndex - WORLD_COLS - 1 ) )
				{
					ChangeVerticalWall( iMapIndex, INTERIOR_EXTENDED );
					EraseHorizontalWall( iMapIndex - WORLD_COLS );
				}
			}
			else
			{	//outside
				BuildWallPiece( iMapIndex, INTERIOR_RIGHT, gubWallUIValue );
				if( GetHorizontalWall( iMapIndex - WORLD_COLS ) && !GetHorizontalWall( iMapIndex - WORLD_COLS + 1 )
						&& !GetVerticalWall( iMapIndex - WORLD_COLS ) )
					ChangeVerticalWall( iMapIndex, EXTERIOR_EXTENDED );
				else if( GetHorizontalWall( iMapIndex - WORLD_COLS ) && !GetHorizontalWall( iMapIndex - WORLD_COLS - 1 )
								&& !GetVerticalWall( iMapIndex - WORLD_COLS - 1 ) )
				{
					ChangeVerticalWall( iMapIndex, EXTERIOR_EXTENDED );
					EraseHorizontalWall( iMapIndex - WORLD_COLS );
				}
			}
		}
		else
		{
			if( GetVerticalWall( iMapIndex - 1 ) && !GetVerticalWall( iMapIndex - WORLD_COLS - 1 )
				&& !GetHorizontalWall( iMapIndex - WORLD_COLS - 1 ) )
				EraseVerticalWall( iMapIndex - 1);
			if( FloorAtGridNo( iMapIndex + WORLD_COLS ) )
			{ //inside
				BuildWallPiece( iMapIndex, EXTERIOR_BOTTOM, gubWallUIValue );
				if( GetVerticalWall( iMapIndex + WORLD_COLS ) )
					ChangeVerticalWall( iMapIndex + WORLD_COLS, INTERIOR_EXTENDED );
				if( GetVerticalWall( iMapIndex + WORLD_COLS - 1 ) && !GetVerticalWall( iMapIndex - 1 ) )
					ChangeVerticalWall( iMapIndex + WORLD_COLS - 1,	INTERIOR_EXTENDED );
				else if( GetVerticalWall( iMapIndex - 1 ) && !GetVerticalWall( iMapIndex + WORLD_COLS - 1 )
								&& FloorAtGridNo( iMapIndex ) )
					ChangeVerticalWall( iMapIndex - 1, INTERIOR_BOTTOMEND );
			}
			else
			{ //outside
				BuildWallPiece( iMapIndex, INTERIOR_BOTTOM, gubWallUIValue );
				if( GetVerticalWall( iMapIndex + WORLD_COLS ) )
					ChangeVerticalWall( iMapIndex + WORLD_COLS, EXTERIOR_EXTENDED );
				if( GetVerticalWall( iMapIndex + WORLD_COLS - 1 ) && !GetVerticalWall( iMapIndex - 1 ) )
					ChangeVerticalWall( iMapIndex + WORLD_COLS - 1,	EXTERIOR_EXTENDED );
				else if( GetVerticalWall( iMapIndex - 1 ) && !GetVerticalWall( iMapIndex + WORLD_COLS - 1 )
								&& FloorAtGridNo( iMapIndex ) )
					ChangeVerticalWall( iMapIndex - 1, EXTERIOR_BOTTOMEND );
			}
		}
		return;
	}
	//*F* See above documentation
	usWallType = GetHorizontalWallType( iMapIndex + WORLD_COLS );
	if( usWallType == gubWallUIValue )
	{
		if( !GetHorizontalWall( iMapIndex + WORLD_COLS - 1 ) )
			EraseHorizontalWall( iMapIndex + WORLD_COLS );
		if( FloorAtGridNo( iMapIndex + 1 ) )
		{ //inside
			BuildWallPiece( iMapIndex + WORLD_COLS, EXTERIOR_RIGHT, gubWallUIValue );
			BuildWallPiece( iMapIndex, EXTERIOR_RIGHT, gubWallUIValue );
			if( !GetVerticalWall( iMapIndex + WORLD_COLS * 2 ) && FloorAtGridNo( iMapIndex + WORLD_COLS * 2 + 1 ) )
				ChangeVerticalWall( iMapIndex + WORLD_COLS, INTERIOR_BOTTOMEND );
			else //override the damn other smoothing.
				ChangeVerticalWall( iMapIndex + WORLD_COLS, INTERIOR_R );
		}
		else
		{ //outside
			BuildWallPiece( iMapIndex + WORLD_COLS, INTERIOR_RIGHT, gubWallUIValue );
			BuildWallPiece( iMapIndex, INTERIOR_RIGHT, gubWallUIValue );
			if( !GetVerticalWall( iMapIndex + WORLD_COLS * 2 ) && !FloorAtGridNo( iMapIndex + WORLD_COLS * 2 + 1 ) )
				ChangeVerticalWall( iMapIndex + WORLD_COLS, EXTERIOR_BOTTOMEND );
			else //override the damn other smoothing.
				ChangeVerticalWall( iMapIndex + WORLD_COLS, EXTERIOR_R );
		}
		return;
	}
	usWallType = GetVerticalWallType( iMapIndex + 1 );
	if( usWallType == gubWallUIValue )
	{
		if(FloorAtGridNo( iMapIndex + WORLD_COLS ) )
		{ //inside
			BuildWallPiece( iMapIndex + 1, EXTERIOR_BOTTOM, gubWallUIValue );
			BuildWallPiece( iMapIndex, EXTERIOR_BOTTOM, gubWallUIValue );
			if( !GetVerticalWall( iMapIndex - WORLD_COLS + 1 ) )
			{
				EraseVerticalWall( iMapIndex + 1 );
				ChangeVerticalWall( iMapIndex + WORLD_COLS + 1, INTERIOR_EXTENDED );
			}
			if( !GetVerticalWall( iMapIndex + WORLD_COLS + 1) )
			{
				if( !GetHorizontalWall( iMapIndex - WORLD_COLS + 1) && !GetVerticalWall( iMapIndex - WORLD_COLS + 1 )
						&& GetHorizontalWall( iMapIndex - WORLD_COLS + 2 ) )
					ChangeVerticalWall( iMapIndex + 1, INTERIOR_EXTENDED );
				else
					ChangeVerticalWall( iMapIndex + 1, INTERIOR_BOTTOMEND );
			}
		}
		else
		{ //outside
			BuildWallPiece( iMapIndex + 1, INTERIOR_BOTTOM, gubWallUIValue );
			BuildWallPiece( iMapIndex, INTERIOR_BOTTOM, gubWallUIValue );
			if( !GetVerticalWall( iMapIndex - WORLD_COLS + 1 ) )
			{
				EraseVerticalWall( iMapIndex + 1 );
				ChangeVerticalWall( iMapIndex + WORLD_COLS + 1, EXTERIOR_EXTENDED );
			}
			if( !GetVerticalWall( iMapIndex + WORLD_COLS + 1) )
			{
				if( !GetHorizontalWall( iMapIndex - WORLD_COLS + 1) && !GetVerticalWall( iMapIndex - WORLD_COLS + 1 )
						&& GetHorizontalWall( iMapIndex - WORLD_COLS + 2 ) )
					ChangeVerticalWall( iMapIndex + 1, EXTERIOR_EXTENDED );
				else
					ChangeVerticalWall( iMapIndex + 1, EXTERIOR_BOTTOMEND );
			}
		}
		return;
	}
	//Check for the highest weight value.
}