//Given a gridno, it will erase the current roof, and calculate the new roof piece based on the //wall orientions giving priority to the top and left walls before anything else. //NOTE: passing NULL for usRoofType will force the function to calculate the nearest roof type, // and use that for the new roof. This is needed when erasing parts of multiple buildings simultaneously. void RebuildRoof( UINT32 iMapIndex, UINT16 usRoofType ) { UINT16 usRoofIndex, usTileIndex; BOOLEAN fTop, fBottom, fLeft, fRight; 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 = GetHorizontalWall( iMapIndex - WORLD_COLS ) ? TRUE : FALSE; fLeft = GetVerticalWall( iMapIndex - 1 ) ? TRUE : FALSE; fBottom = GetHorizontalWall( iMapIndex ) ? TRUE : FALSE; fRight = GetVerticalWall( iMapIndex ) ? TRUE : FALSE; 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 ); } }
void ExamineGridNoForSlantRoofExtraGraphic( INT32 sCheckGridNo ) { LEVELNODE *pNode = NULL; STRUCTURE *pStructure, *pBase; UINT8 ubLoop; DB_STRUCTURE_TILE ** ppTile; INT32 sGridNo; UINT16 usIndex; BOOLEAN fChanged = FALSE; // CHECK FOR A SLANTED ROOF HERE.... pStructure = FindStructure( sCheckGridNo, STRUCTURE_SLANTED_ROOF ); if ( pStructure != NULL ) { // We have a slanted roof here ... find base and remove... pBase = FindBaseStructure( pStructure ); // Get LEVELNODE for struct and remove! pNode = FindLevelNodeBasedOnStructure( pBase->sGridNo, pBase ); // Loop through each gridno and see if revealed.... for ( ubLoop = 0; ubLoop < pBase->pDBStructureRef->pDBStructure->ubNumberOfTiles; ubLoop++ ) { ppTile = pBase->pDBStructureRef->ppTile; #if 0//dnl ch83 080114 sGridNo = pBase->sGridNo + ppTile[ ubLoop ]->sPosRelToBase; #else sGridNo = AddPosRelToBase(pBase->sGridNo, ppTile[ubLoop]); #endif if (sGridNo < 0 || sGridNo > WORLD_MAX) { continue; } // Given gridno, // IF NOT REVEALED AND HIDDEN.... if ( !( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) && pNode->uiFlags & LEVELNODE_HIDDEN ) { // Add graphic if one does not already exist.... if ( !TypeExistsInRoofLayer( sGridNo, SLANTROOFCEILING, &usIndex ) ) { // Add AddRoofToHead( sGridNo, SLANTROOFCEILING1 ); fChanged = TRUE; } } // Revealed? if ( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REVEALED ) { ///Remove any slant roof items if they exist if ( TypeExistsInRoofLayer( sGridNo, SLANTROOFCEILING, &usIndex ) ) { RemoveRoof( sGridNo, usIndex ); fChanged = TRUE; } } } } if ( fChanged ) { // DIRTY THE WORLD! InvalidateWorldRedundency(); SetRenderFlags(RENDER_FLAG_FULL ); } }
void BuildSlantRoof( INT32 iLeft, INT32 iTop, INT32 iRight, INT32 iBottom, UINT16 usWallType, UINT16 usRoofType, BOOLEAN fVertical ) { INT32 i; UINT16 usTileIndex; INT32 iMapIndex; if( fVertical ) { iMapIndex = iBottom * WORLD_COLS + iLeft; //This happens to be the only mapindex that needs to be backed up. The rest have already been //done because of the building code before this. AddToUndoList( iMapIndex + 8 ); //Add the closest viewable pieces. There are two aframe walls pieces, and extended aframe roof pieces. GetTileIndexFromTypeSubIndex( usWallType, VWALL_LEFT, &usTileIndex ); AddRoofToHead( iMapIndex + 4, usTileIndex ); GetTileIndexFromTypeSubIndex( usWallType, VWALL_RIGHT, &usTileIndex ); AddRoofToHead( iMapIndex + 8, usTileIndex ); GetTileIndexFromTypeSubIndex( usRoofType, THICK_LEFT, &usTileIndex ); AddRoofToHead( iMapIndex + 3, usTileIndex ); GetTileIndexFromTypeSubIndex( usRoofType, THICK_RIGHT, &usTileIndex ); AddRoofToHead( iMapIndex + 7, usTileIndex ); for( i = iBottom - 1; i > iTop; i-- ) { iMapIndex -= WORLD_COLS; GetTileIndexFromTypeSubIndex( usRoofType, THIN_LEFT, &usTileIndex ); AddRoofToHead( iMapIndex + 3, usTileIndex ); GetTileIndexFromTypeSubIndex( usRoofType, THIN_RIGHT, &usTileIndex ); AddRoofToHead( iMapIndex + 7, usTileIndex ); } iMapIndex -= WORLD_COLS; GetTileIndexFromTypeSubIndex( usRoofType, THICK_LEFT, &usTileIndex ); AddRoofToHead( iMapIndex + 3, usTileIndex ); GetTileIndexFromTypeSubIndex( usRoofType, THICK_RIGHT, &usTileIndex ); AddRoofToHead( iMapIndex + 7, usTileIndex ); } else { iMapIndex = iTop * WORLD_COLS + iRight; //This happens to be the only mapindex that needs to be backed up. The rest have already been //done because of the building code before this. AddToUndoList( iMapIndex + 8*WORLD_COLS ); //Add the closest viewable pieces. There are two aframe walls pieces, and extended aframe roof pieces. GetTileIndexFromTypeSubIndex( usWallType, HWALL_LEFT, &usTileIndex ); AddRoofToHead( iMapIndex + 4*WORLD_COLS, usTileIndex ); GetTileIndexFromTypeSubIndex( usWallType, HWALL_RIGHT, &usTileIndex ); AddRoofToHead( iMapIndex + 8*WORLD_COLS, usTileIndex ); GetTileIndexFromTypeSubIndex( usRoofType, THICK_TOP, &usTileIndex ); AddRoofToHead( iMapIndex + 3*WORLD_COLS, usTileIndex ); GetTileIndexFromTypeSubIndex( usRoofType, THICK_BOTTOM, &usTileIndex ); AddRoofToHead( iMapIndex + 7*WORLD_COLS, usTileIndex ); for( i = iRight - 1; i > iLeft; i-- ) { iMapIndex--; GetTileIndexFromTypeSubIndex( usRoofType, THIN_TOP, &usTileIndex ); AddRoofToHead( iMapIndex + 3*WORLD_COLS, usTileIndex ); GetTileIndexFromTypeSubIndex( usRoofType, THIN_BOTTOM, &usTileIndex ); AddRoofToHead( iMapIndex + 7*WORLD_COLS, usTileIndex ); } iMapIndex--; GetTileIndexFromTypeSubIndex( usRoofType, THICK_TOP, &usTileIndex ); AddRoofToHead( iMapIndex + 3*WORLD_COLS, usTileIndex ); GetTileIndexFromTypeSubIndex( usRoofType, THICK_BOTTOM, &usTileIndex ); AddRoofToHead( iMapIndex + 7*WORLD_COLS, usTileIndex ); } }
ANITILE *CreateAnimationTile( ANITILE_PARAMS *pAniParams ) { ANITILE *pAniNode; ANITILE *pNewAniNode; LEVELNODE *pNode; INT32 iCachedTile=-1; INT16 sGridNo; UINT8 ubLevel; INT16 usTileType; INT16 usTileIndex; INT16 sDelay; INT16 sStartFrame=-1; UINT32 uiFlags; LEVELNODE *pGivenNode; INT16 sX, sY, sZ; UINT8 ubTempDir; // Get some parameters from structure sent in... sGridNo = pAniParams->sGridNo; ubLevel = pAniParams->ubLevelID; usTileType = pAniParams->usTileType; usTileIndex = pAniParams->usTileIndex; sDelay = pAniParams->sDelay; sStartFrame = pAniParams->sStartFrame; uiFlags = pAniParams->uiFlags; pGivenNode = pAniParams->pGivenLevelNode; sX = pAniParams->sX; sY = pAniParams->sY; sZ = pAniParams->sZ; pAniNode = pAniTileHead; // Allocate head pNewAniNode = MemAlloc( sizeof( ANITILE ) ); if ( (uiFlags & ANITILE_EXISTINGTILE ) ) { pNewAniNode->pLevelNode = pGivenNode; pNewAniNode->pLevelNode->pAniTile = pNewAniNode; } else { if ( ( uiFlags & ANITILE_CACHEDTILE ) ) { iCachedTile = GetCachedTile( pAniParams->zCachedFile ); if ( iCachedTile == -1 ) { return( NULL ); } usTileIndex = iCachedTile + TILE_CACHE_START_INDEX; } // ALLOCATE NEW TILE switch( ubLevel ) { case ANI_STRUCT_LEVEL: pNode = ForceStructToTail( sGridNo, usTileIndex ); break; case ANI_SHADOW_LEVEL: AddShadowToHead( sGridNo, usTileIndex ); pNode = gpWorldLevelData[ sGridNo ].pShadowHead; break; case ANI_OBJECT_LEVEL: AddObjectToHead( sGridNo, usTileIndex ); pNode = gpWorldLevelData[ sGridNo ].pObjectHead; break; case ANI_ROOF_LEVEL: AddRoofToHead( sGridNo, usTileIndex ); pNode = gpWorldLevelData[ sGridNo ].pRoofHead; break; case ANI_ONROOF_LEVEL: AddOnRoofToHead( sGridNo, usTileIndex ); pNode = gpWorldLevelData[ sGridNo ].pOnRoofHead; break; case ANI_TOPMOST_LEVEL: AddTopmostToHead( sGridNo, usTileIndex ); pNode = gpWorldLevelData[ sGridNo ].pTopmostHead; break; default: return( NULL ); } // SET NEW TILE VALUES pNode->ubShadeLevel=DEFAULT_SHADE_LEVEL; pNode->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL; pNewAniNode->pLevelNode = pNode; if ( ( uiFlags & ANITILE_CACHEDTILE ) ) { pNewAniNode->pLevelNode->uiFlags |= ( LEVELNODE_CACHEDANITILE ); pNewAniNode->sCachedTileID = (INT16)iCachedTile; pNewAniNode->usCachedTileSubIndex = usTileType; pNewAniNode->pLevelNode->pAniTile = pNewAniNode; pNewAniNode->sRelativeX = sX; pNewAniNode->sRelativeY = sY; pNewAniNode->pLevelNode->sRelativeZ = sZ; } // Can't set relative X,Y,Z IF FLAGS ANITILE_CACHEDTILE set! else if ( (uiFlags & ANITILE_USEABSOLUTEPOS ) ) { pNewAniNode->pLevelNode->sRelativeX = sX; pNewAniNode->pLevelNode->sRelativeY = sY; pNewAniNode->pLevelNode->sRelativeZ = sZ; pNewAniNode->pLevelNode->uiFlags |= ( LEVELNODE_USEABSOLUTEPOS ); } } switch( ubLevel ) { case ANI_STRUCT_LEVEL: ResetSpecificLayerOptimizing( TILES_DYNAMIC_STRUCTURES ); break; case ANI_SHADOW_LEVEL: ResetSpecificLayerOptimizing( TILES_DYNAMIC_SHADOWS ); break; case ANI_OBJECT_LEVEL: ResetSpecificLayerOptimizing( TILES_DYNAMIC_OBJECTS ); break; case ANI_ROOF_LEVEL: ResetSpecificLayerOptimizing( TILES_DYNAMIC_ROOF ); break; case ANI_ONROOF_LEVEL: ResetSpecificLayerOptimizing( TILES_DYNAMIC_ONROOF ); break; case ANI_TOPMOST_LEVEL: ResetSpecificLayerOptimizing( TILES_DYNAMIC_TOPMOST ); break; } // SET FLAGS FOR LEVELNODE pNewAniNode->pLevelNode->uiFlags |= ( LEVELNODE_ANIMATION | LEVELNODE_USEZ | LEVELNODE_DYNAMIC ); if ( ( uiFlags & ANITILE_NOZBLITTER ) ) { pNewAniNode->pLevelNode->uiFlags |= LEVELNODE_NOZBLITTER; } if ( ( uiFlags & ANITILE_ALWAYS_TRANSLUCENT ) ) { pNewAniNode->pLevelNode->uiFlags |= LEVELNODE_REVEAL; } if ( ( uiFlags & ANITILE_USEBEST_TRANSLUCENT ) ) { pNewAniNode->pLevelNode->uiFlags |= LEVELNODE_USEBESTTRANSTYPE; } if ( ( uiFlags & ANITILE_ANIMATE_Z ) ) { pNewAniNode->pLevelNode->uiFlags |= LEVELNODE_DYNAMICZ; } if ( ( uiFlags & ANITILE_PAUSED ) ) { pNewAniNode->pLevelNode->uiFlags |= ( LEVELNODE_LASTDYNAMIC | LEVELNODE_UPDATESAVEBUFFERONCE ); pNewAniNode->pLevelNode->uiFlags &= (~LEVELNODE_DYNAMIC ); } if ( ( uiFlags & ANITILE_OPTIMIZEFORSMOKEEFFECT ) ) { pNewAniNode->pLevelNode->uiFlags |= LEVELNODE_NOWRITEZ; } // SET ANITILE VALUES pNewAniNode->ubLevelID = ubLevel; pNewAniNode->usTileIndex = usTileIndex; if ( ( uiFlags & ANITILE_CACHEDTILE ) ) { pNewAniNode->usNumFrames = gpTileCache[ iCachedTile ].ubNumFrames; } else { Assert( gTileDatabase[ usTileIndex ].pAnimData != NULL ); pNewAniNode->usNumFrames = gTileDatabase[ usTileIndex ].pAnimData->ubNumFrames; } if ( ( uiFlags & ANITILE_USE_DIRECTION_FOR_START_FRAME ) ) { // Our start frame is actually a direction indicator ubTempDir = gOneCDirection[ pAniParams->uiUserData3 ]; sStartFrame = (UINT16)sStartFrame + ( pNewAniNode->usNumFrames * ubTempDir ); } if ( ( uiFlags & ANITILE_USE_4DIRECTION_FOR_START_FRAME ) ) { // Our start frame is actually a direction indicator ubTempDir = gb4DirectionsFrom8[ pAniParams->uiUserData3 ]; sStartFrame = (UINT16)sStartFrame + ( pNewAniNode->usNumFrames * ubTempDir ); } pNewAniNode->usTileType = usTileType; pNewAniNode->pNext = pAniNode; pNewAniNode->uiFlags = uiFlags; pNewAniNode->sDelay = sDelay; pNewAniNode->sCurrentFrame = sStartFrame; pNewAniNode->uiTimeLastUpdate = GetJA2Clock( ); pNewAniNode->sGridNo = sGridNo; pNewAniNode->sStartFrame = sStartFrame; pNewAniNode->ubKeyFrame1 = pAniParams->ubKeyFrame1; pNewAniNode->uiKeyFrame1Code = pAniParams->uiKeyFrame1Code; pNewAniNode->ubKeyFrame2 = pAniParams->ubKeyFrame2; pNewAniNode->uiKeyFrame2Code = pAniParams->uiKeyFrame2Code; pNewAniNode->uiUserData = pAniParams->uiUserData; pNewAniNode->ubUserData2 = pAniParams->ubUserData2; pNewAniNode->uiUserData3 = pAniParams->uiUserData3; //Set head pAniTileHead = pNewAniNode; // Set some special stuff return( pNewAniNode ); }