/* ============== SetPortalState doors explicitly close off portals when shut ============== */ void idRenderWorldLocal::SetPortalState( qhandle_t portal, int blockTypes ) { if ( portal == 0 ) { return; } if ( portal < 1 || portal > numInterAreaPortals ) { common->Error( "SetPortalState: bad portal number %i", portal ); } int old = doublePortals[portal-1].blockingBits; if ( old == blockTypes ) { return; } doublePortals[portal-1].blockingBits = blockTypes; // leave the connectedAreaGroup the same on one side, // then flood fill from the other side with a new number for each changed attribute for ( int i = 0 ; i < NUM_PORTAL_ATTRIBUTES ; i++ ) { if ( ( old ^ blockTypes ) & ( 1 << i ) ) { connectedAreaNum++; FloodConnectedAreas( &portalAreas[doublePortals[portal-1].portals[1]->intoArea], i ); } } if ( session->writeDemo ) { session->writeDemo->WriteInt( DS_RENDER ); session->writeDemo->WriteInt( DC_SET_PORTAL_STATE ); session->writeDemo->WriteInt( portal ); session->writeDemo->WriteInt( blockTypes ); } }
/* ============= FloodConnectedAreas ============= */ void idRenderWorldLocal::FloodConnectedAreas( portalArea_t *area, int portalAttributeIndex ) { if ( area->connectedAreaNum[portalAttributeIndex] == connectedAreaNum ) { return; } area->connectedAreaNum[portalAttributeIndex] = connectedAreaNum; for ( portal_t *p = area->portals ; p ; p = p->next ) { if ( !(p->doublePortal->blockingBits & (1<<portalAttributeIndex) ) ) { FloodConnectedAreas( &portalAreas[p->intoArea], portalAttributeIndex ); } } }
/* ===================== idRenderWorldLocal::ClearPortalStates ===================== */ void idRenderWorldLocal::ClearPortalStates() { int i, j; // all portals start off open for ( i = 0 ; i < numInterAreaPortals ; i++ ) { doublePortals[i].blockingBits = PS_BLOCK_NONE; } // flood fill all area connections for ( i = 0 ; i < numPortalAreas ; i++ ) { for ( j = 0 ; j < NUM_PORTAL_ATTRIBUTES ; j++ ) { connectedAreaNum++; FloodConnectedAreas( &portalAreas[i], j ); } } }