Example #1
0
void PasteSmartBrokenWall( INT32 iMapIndex )
{
	UINT16 usNewWallIndex;

	LEVELNODE *pWall;
	UINT32 uiTileType;
	UINT16 usWallType;
	UINT16 usIndex;
	UINT16 usWallOrientation;

	pWall = GetVerticalWall( iMapIndex );
	if( pWall )
	{
		GetTileType( pWall->usIndex, &uiTileType );
		usWallType = (UINT16)uiTileType;
		if( uiTileType >= FIRSTDOOR && uiTileType <= LASTDOOR )
		{
			usWallType = SearchForWallType( iMapIndex );
		}
		GetWallOrientation( pWall->usIndex, &usWallOrientation );
		usIndex = CalcSmartBrokenWallIndex( usWallOrientation );
		if( usIndex == 0xffff )
		{
			AddToUndoList( iMapIndex );
			RemoveStruct( iMapIndex, pWall->usIndex );
		}
		else
		{
			AddToUndoList( iMapIndex );
			GetTileIndexFromTypeSubIndex( usWallType, usIndex, &usNewWallIndex );
			ReplaceStructIndex( iMapIndex, pWall->usIndex, usNewWallIndex );
		}
	}
	pWall = GetHorizontalWall( iMapIndex );
	if( pWall )
	{
		GetTileType( pWall->usIndex, &uiTileType );
		usWallType = (UINT16)uiTileType;
		if( uiTileType >= FIRSTDOOR && uiTileType <= LASTDOOR )
		{
			//We want to be able to replace doors with a window, however, the doors do not
			//contain the wall type, so we have to search for the nearest wall to extract it.
			usWallType = SearchForWallType( iMapIndex );
		}
		GetWallOrientation( pWall->usIndex, &usWallOrientation );
		usIndex = CalcSmartBrokenWallIndex( usWallOrientation );
		if( usIndex == 0xffff )
		{
			AddToUndoList( iMapIndex );
			RemoveStruct( iMapIndex, pWall->usIndex );
		}
		else
		{
			AddToUndoList( iMapIndex );
			GetTileIndexFromTypeSubIndex( usWallType, usIndex, &usNewWallIndex );
			ReplaceStructIndex( iMapIndex, pWall->usIndex, usNewWallIndex );
		}
		//Calculate the new graphic for the window type selected.
	}
}
Example #2
0
void PasteSmartDoor( INT32 iMapIndex )
{
	LEVELNODE *pWall = NULL;
	UINT16 usTileIndex;
	UINT16 usDoorType;
	UINT16 usIndex;
	UINT16 usWallOrientation;

	if( pWall = GetVerticalWall( iMapIndex ) )
	{
		GetWallOrientation( pWall->usIndex, &usWallOrientation );
		usIndex = CalcSmartDoorIndex( usWallOrientation );
		usDoorType = CalcSmartDoorType();
		AddToUndoList( iMapIndex );
		GetTileIndexFromTypeSubIndex( usDoorType, usIndex, &usTileIndex );
		ReplaceStructIndex( iMapIndex, pWall->usIndex, usTileIndex );
	}
	if( pWall = GetHorizontalWall( iMapIndex ) )
	{
		GetWallOrientation( pWall->usIndex, &usWallOrientation );
		usIndex = CalcSmartDoorIndex( usWallOrientation );
		usDoorType = CalcSmartDoorType();
		AddToUndoList( iMapIndex );
		GetTileIndexFromTypeSubIndex( usDoorType, usIndex, &usTileIndex );
		ReplaceStructIndex( iMapIndex, pWall->usIndex, usTileIndex );
	}
}
Example #3
0
//This will automatically update obsolete map versions to the new ones.	This will even
//work in the game itself, but would require conversion to happen every time.	This is completely
//transparent to the rest of the game, but in the editor, obsolete versions will be updated upon
//loading and won't be permanently updated until the map is saved, regardless of changes.
void UpdateOldVersionMap()
{
#if 0 //This code is no longer needed since the major version update from 1.0 to 4.0
    //However, I am keeping it in for reference.
    SOLDIERINITNODE *curr;
    INT32 i;
    LEVELNODE *pStruct;
    //VERSION 0 -- obsolete November 14, 1997
    if( gMapInformation.ubMapVersion == 0 )
    {
        //Soldier information contained two fixable bugs.
        gMapInformation.ubMapVersion++;
        curr = gSoldierInitHead;
        while( curr )
        {
            //Bug #01)	Nodes without detailed slots weren't initialized.
            if( !curr->pBasicPlacement->fDetailedPlacement )
                curr->pDetailedPlacement = NULL;
            //Bug #02)	The attitude variable was accidentally being generated like attributes
            //					which put it completely out of range.
            if( curr->pBasicPlacement->bAttitude > 7 )
                curr->pBasicPlacement->bAttitude = (INT8)Random(8);
            //go to next node
            curr = curr->next;
        }
    }
    //VERSION 1 -- obsolete January 7, 1998
    if( gMapInformation.ubMapVersion == 1 )
    {
        gMapInformation.ubMapVersion++;
        //Bug #03)	Removing all wall decals from map, because of new changes to the slots
        //					as well as certain decals found commonly in illegal places.
        for( i = 0; i < WORLD_MAX; i++ )
        {
            RemoveAllStructsOfTypeRange( i, FIRSTWALLDECAL, LASTWALLDECAL );
            RemoveAllStructsOfTypeRange( i, FIFTHWALLDECAL, SIXTHWALLDECAL );
        }
    }
    //VERSION 2 -- obsolete February 3, 1998
    if( gMapInformation.ubMapVersion == 2 )
    {
        gMapInformation.ubMapVersion++;
        curr = gSoldierInitHead;
        while( curr )
        {
            //Bug #04)	Assign enemy mercs default army color code if applicable
            if( curr->pBasicPlacement->bTeam == ENEMY_TEAM && !curr->pBasicPlacement->ubSoldierClass )
            {
                if( !curr->pDetailedPlacement )
                {
                    curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ARMY;
                }
                else if( curr->pDetailedPlacement && curr->pDetailedPlacement->ubProfile == NO_PROFILE )
                {
                    curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ARMY;
                    curr->pDetailedPlacement->ubSoldierClass = SOLDIER_CLASS_ARMY;
                }
            }
            curr = curr->next;
        }
    }
    //VERSION 3 -- obsolete February 9, 1998
    if( gMapInformation.ubMapVersion == 3 )
    {
        gMapInformation.ubMapVersion++;
        //Bug #05)	Move entry points down if necessary.
        ValidateEntryPointGridNo( &gMapInformation.sNorthGridNo );
        ValidateEntryPointGridNo( &gMapInformation.sEastGridNo );
        ValidateEntryPointGridNo( &gMapInformation.sSouthGridNo );
        ValidateEntryPointGridNo( &gMapInformation.sWestGridNo );
    }
    //VERSION 4 -- obsolete February 25, 1998
    if( gMapInformation.ubMapVersion == 4 )
    {
        gMapInformation.ubMapVersion++;
        //6)	Change all doors to FIRSTDOOR
        for( i = 0; i < WORLD_MAX; i++ )
        {
            //NOTE:	Here are the index values for the various doors
            //DOOR		OPEN		CLOSED
            //FIRST		916			912
            //SECOND	936		932
            //THIRD		956		952
            //FOURTH	976		972
            pStruct = gpWorldLevelData[ i ].pStructHead;
            while( pStruct )
            {
                //outside topleft
                if( pStruct->usIndex == 932 || pStruct->usIndex == 952 || pStruct->usIndex == 972 )
                {
                    ReplaceStructIndex( i, pStruct->usIndex, 912 );
                    break;
                }
                else if( pStruct->usIndex == 936 || pStruct->usIndex == 956 || pStruct->usIndex == 976 )
                {
                    ReplaceStructIndex( i, pStruct->usIndex, 916 );
                    break;
                }
                //outside topright
                else if( pStruct->usIndex == 927 || pStruct->usIndex == 947 || pStruct->usIndex == 967 )
                {
                    ReplaceStructIndex( i, pStruct->usIndex, 907 );
                    break;
                }
                else if( pStruct->usIndex == 931 || pStruct->usIndex == 951 || pStruct->usIndex == 971 )
                {
                    ReplaceStructIndex( i, pStruct->usIndex, 911 );
                    break;
                }
                //inside topleft
                else if( pStruct->usIndex == 942 || pStruct->usIndex == 962 || pStruct->usIndex == 982 )
                {
                    ReplaceStructIndex( i, pStruct->usIndex, 922 );
                    break;
                }
                else if( pStruct->usIndex == 946 || pStruct->usIndex == 966 || pStruct->usIndex == 986 )
                {
                    ReplaceStructIndex( i, pStruct->usIndex, 926 );
                    break;
                }
                //inside topright
                else if( pStruct->usIndex == 937 || pStruct->usIndex == 957 || pStruct->usIndex == 977 )
                {
                    ReplaceStructIndex( i, pStruct->usIndex, 917 );
                    break;
                }
                else if( pStruct->usIndex == 941 || pStruct->usIndex == 961 || pStruct->usIndex == 981 )
                {
                    ReplaceStructIndex( i, pStruct->usIndex, 921 );
                    break;
                }
                pStruct = pStruct->pNext;
            }
        }
    }
    //VERSION 5 -- obsolete March 4, 1998
    if( gMapInformation.ubMapVersion == 5 )
    {
        gMapInformation.ubMapVersion++;
        //Bug 7)	Remove all exit grids (the format has changed)
        for( i = 0; i < WORLD_MAX; i++ )
            RemoveExitGridFromWorld( i );
    }
    //VERSION 6 -- obsolete March 9, 1998
    if( gMapInformation.ubMapVersion == 6 )
    {   //Bug 8)	Change droppable status of merc items so that they are all undroppable.
        gMapInformation.ubMapVersion++;
        curr = gSoldierInitHead;
        while( curr )
        {
            //Bug #04)	Assign enemy mercs default army color code if applicable
            if( curr->pDetailedPlacement )
            {
                for( i = 0; i < curr->pDetailedPlacement->Inv.size(); i++ )
                {   //make all items undroppable, even if it is empty.	This will allow for
                    //random item generation, while empty, droppable slots are locked as empty
                    //during random item generation.
                    curr->pDetailedPlacement->Inv[ i ].fFlags |= OBJECT_UNDROPPABLE;
                }
            }
            curr = curr->next;
        }
    }
    //VERSION 7 -- obsolete April 14, 1998
    if( gMapInformation.ubMapVersion == 7 )
    {
        gMapInformation.ubMapVersion++;
        //Bug 9)	Priority placements have been dropped in favor of splitting it into two categories.
        //				The first is Detailed placements, and the second is priority existance.	So, all
        //				current detailed placements will also have priority existance.
        curr = gSoldierInitHead;
        while( curr )
        {
            if( curr->pDetailedPlacement )
            {
                curr->pBasicPlacement->fPriorityExistance = TRUE;
            }
            curr = curr->next;
        }
    }

    if( gMapInformation.ubMapVersion == 14 )
    {   //Toast all of the ambiguous road pieces that ended up wrapping the byte.
        LEVELNODE *pStruct, *pStruct2;
        INT32 i;
        for( i = 0; i < WORLD_MAX; i++ )
        {
            pStruct = gpWorldLevelData[ i ].pObjectHead;
            if( pStruct && pStruct->usIndex == 1078 && i < WORLD_MAX-2 && i >= 320 )
            {   //This is the only detectable road piece that we can repair.
                pStruct2 = gpWorldLevelData[ i+1 ].pObjectHead;
                if( pStruct2 && pStruct2->usIndex == 1081 )
                {
                    RemoveObject( i, pStruct->usIndex );
                    RemoveObject( i+1, pStruct->usIndex+1 );
                    RemoveObject( i+2, pStruct->usIndex+2 );
                    RemoveObject( i-160, pStruct->usIndex-160 );
                    RemoveObject( i-159, pStruct->usIndex-159 );
                    RemoveObject( i-158, pStruct->usIndex-158 );
                    RemoveObject( i-320, pStruct->usIndex-320 );
                    RemoveObject( i-319, pStruct->usIndex-319 );
                    RemoveObject( i-318, pStruct->usIndex-318 );
                    AddObjectToTail( i, 1334 );
                    AddObjectToTail( i-160, 1335 );
                    AddObjectToTail( i-320, 1336 );
                    AddObjectToTail( i+1, 1337 );
                    AddObjectToTail( i-159, 1338 );
                    AddObjectToTail( i-319, 1339 );
                    AddObjectToTail( i+2, 1340 );
                    AddObjectToTail( i-158, 1341 );
                    AddObjectToTail( i-318, 1342 );
                }
            }
            else if( pStruct && pStruct->usIndex >= 1079 && pStruct->usIndex < 1115 )
            {
                RemoveObject( i, pStruct->usIndex );
            }
        }
    }

    if( gMapInformation.ubMapVersion <= 7 )
    {
        if( gfEditMode )
        {
#ifdef JA2TESTVERSION
            ScreenMsg( FONT_MCOLOR_RED, MSG_ERROR, L"Currently loaded map is corrupt!	Allowing the map to load anyway!" );
#endif
        }
        else
        {
            if( gbWorldSectorZ )
            {
                AssertMsg( 0, String( "Currently loaded map (%c%d_b%d.dat) is invalid -- less than the minimum supported version.", gWorldSectorY + 'A' - 1, gWorldSectorX, gbWorldSectorZ ) );
            }
            else if( !gbWorldSectorZ )
            {
                AssertMsg( 0, String( "Currently loaded map (%c%d.dat) is invalid -- less than the minimum supported version.", gWorldSectorY + 'A' - 1, gWorldSectorX ) );
            }
        }
    }
    //VERSION 8 -- obsolete April 18, 1998
    if( gMapInformation.ubMapVersion == 8 )
    {
        gMapInformation.ubMapVersion++;
        //Bug 10) Padding on detailed placements is uninitialized.	Clear all data starting at
        //				fKillSlotIfOwnerDies.
        curr = gSoldierInitHead;
        while( curr )
        {
            if( curr->pDetailedPlacement )
            {
                //The size 120 was hand calculated.	The remaining padding was 118 bytes
                //and there were two one byte fields cleared, fKillSlotIfOwnerDies and ubScheduleID
                memset( &curr->pDetailedPlacement->fKillSlotIfOwnerDies, 0, 120 );
            }
            curr = curr->next;
        }
    }
    //Version 9 -- Kris -- obsolete April 27, 1998
    if( gMapInformation.ubMapVersion == 9 )
    {
        gMapInformation.ubMapVersion++;
        curr = gSoldierInitHead;
        while( curr )
        {
            //Bug 11) Convert all wheelchaired placement bodytypes to cows.	Result of change in the animation database.
            if( curr->pDetailedPlacement && curr->pDetailedPlacement->bBodyType == CRIPPLECIV )
            {
                curr->pDetailedPlacement->bBodyType = COW;
                curr->pBasicPlacement->bBodyType = COW;
            }
            curr = curr->next;
        }
    }
    if( gMapInformation.ubMapVersion < 12 )
    {
        gMapInformation.ubMapVersion = 12;
        gMapInformation.sCenterGridNo = -1;
    }
    if( gMapInformation.ubMapVersion < 13 )
    {   //replace all merc ammo inventory slots status value with the max ammo that the clip can hold.
        INT32 i, cnt;
        OBJECTTYPE *pItem;
        gMapInformation.ubMapVersion++;
        //Bug 10) Padding on detailed placements is uninitialized.	Clear all data starting at
        //				fKillSlotIfOwnerDies.
        curr = gSoldierInitHead;
        while( curr )
        {
            if( curr->pDetailedPlacement )
            {
                for ( i = 0; i < curr->pDetailedPlacement->Inv.size(); i++ )
                {
                    pItem = &curr->pDetailedPlacement->Inv[ i ];
                    if( Item[ pItem->usItem ].usItemClass & IC_AMMO )
                    {
                        for( cnt = 0; cnt < pItem->ubNumberOfObjects; cnt++ )
                        {
                            pItem->shots.ubShotsLeft[ cnt ] = Magazine[ Item[ pItem->usItem ].ubClassIndex ].ubMagSize;
                        }
                    }
                }
            }
            curr = curr->next;
        }
    }
    if( gMapInformation.ubMapVersion < 14 )
    {
        gMapInformation.ubMapVersion++;
        if( !gfCaves && !gfBasement )
        {
            ReplaceObsoleteRoads();
        }
    }
    if( gMapInformation.ubMapVersion < 15 )
    {   //Do nothing.	The object layer was expanded from 1 byte to 2 bytes, effecting the
        //size of the maps.	This was due to the fact that the ROADPIECES tileset contains
        //over 300 pieces, hence requiring a size increase of the tileset subindex for this
        //layer only.
    }
#endif //end of MAJOR VERSION 3.0 obsolete code
    if( gMapInformation.ubMapVersion < 15 )
    {
        AssertMsg( 0, "Map is less than minimum supported version." );
    }
    if( gMapInformation.ubMapVersion < 16 )
    {
        gMapInformation.ubMapVersion = 16;
        gMapInformation.sIsolatedGridNo = -1;
    }
    if( gMapInformation.ubMapVersion < 17 )
    {
        gMapInformation.ubMapVersion = 17;
        //EliminateObjectLayerRedundancy();
    }
    if( gMapInformation.ubMapVersion < 18 )
    {
        // replace useless crowbars with proper ones
        UINT32 i;
        gMapInformation.ubMapVersion = 18;
        for ( i = 0; i < guiNumWorldItems; i++ )
        {
            if ( gWorldItems[ i ].object.usItem == JAR_ELIXIR )
            {
                gWorldItems[ i ].object.usItem = CROWBAR;
            }
        }
    }
    if( gMapInformation.ubMapVersion < 19 )
    {
        //Do nothing, this is used to force regenerate the map edgepoints in map edgepoints.c
        gMapInformation.ubMapVersion = 19;
    }
    if( gMapInformation.ubMapVersion < 20 )
    {
        //validate the map entry points as the world boundaries have changed.
        gMapInformation.ubMapVersion = 20;
        ValidateEntryPointGridNo( &gMapInformation.sNorthGridNo );
        ValidateEntryPointGridNo( &gMapInformation.sEastGridNo );
        ValidateEntryPointGridNo( &gMapInformation.sSouthGridNo );
        ValidateEntryPointGridNo( &gMapInformation.sWestGridNo );
        ValidateEntryPointGridNo( &gMapInformation.sCenterGridNo );
        ValidateEntryPointGridNo( &gMapInformation.sIsolatedGridNo );
    }
    if( gMapInformation.ubMapVersion < 21 )
    {
        SOLDIERINITNODE *curr;
        //override any item slots being locked if there is no item in that slot.
        //Laymen terms:	If any items slots are locked to be empty, make them empty but available
        //for random item generation.
        gMapInformation.ubMapVersion = 21;
        curr = gSoldierInitHead;
        while( curr )
        {
            if( curr->pDetailedPlacement )
            {
                for( UINT32 i = 0; i < curr->pDetailedPlacement->Inv.size(); i++ )
                {
                    if( !curr->pDetailedPlacement->Inv[ i ].usItem )
                    {
                        if( curr->pDetailedPlacement->Inv[ i ].fFlags & OBJECT_UNDROPPABLE )
                        {
                            if( curr->pDetailedPlacement->Inv[ i ].fFlags & OBJECT_NO_OVERWRITE )
                            {
                                curr->pDetailedPlacement->Inv[ i ].fFlags &= ~OBJECT_NO_OVERWRITE;
                            }
                        }
                    }
                }
            }
            curr = curr->next;
        }
    }
    if( gMapInformation.ubMapVersion < 22 )
    {   //Allow map edgepoints to be regenerated as new system has been reenabled.
        gMapInformation.ubMapVersion = 22;
    }
    if( gMapInformation.ubMapVersion < 23 )
    {   //Allow map edgepoints to be regenerated as new system has been reenabled.
        SOLDIERINITNODE *curr;
        gMapInformation.ubMapVersion = 23;
        if( giCurrentTilesetID == 1 ) //cave/mine tileset only
        {   //convert all civilians to miners which use uniforms and more masculine body types.
            curr = gSoldierInitHead;
            while( curr )
            {
                if( curr->pBasicPlacement->bTeam == CIV_TEAM && !curr->pDetailedPlacement )
                {
                    curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_MINER;
                    curr->pBasicPlacement->bBodyType = -1;
                }
                curr = curr->next;
            }
        }
    }
    if( gMapInformation.ubMapVersion < 25 )
    {
        gMapInformation.ubMapVersion = 25;
        if( gfCaves )
        {
            LightSetBaseLevel( 13 );
        }
    }
    if( gMapInformation.ubMapVersion < 26 )
    {   //Allow map edgepoints to be regenerated as new system has been reenabled.
        gMapInformation.ubMapVersion = 26;
    }
    if( gMapInformation.ubMapVersion < 27 )
    {   //Allow map edgepoints to be regenerated as new system has been reenabled.
        gMapInformation.ubMapVersion = 27;
    }
    if( gMapInformation.ubMapVersion < 29 )
    {
        gMapInformation.ubMapVersion = 29;
    }
}
Example #4
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 );
}