void RemoveBullet( INT32 iBullet ) { CHECKV( iBullet < NUM_BULLET_SLOTS ); //afp-start // remove any tail first if exists for (int i = 0; i < BULLET_TRACER_MAX_LENGTH; i++) if (gBullets[iBullet].pNodes[i] != NULL) { RemoveStructFromLevelNode(gBullets[ iBullet ].sGridNo, gBullets[iBullet].pNodes[i]); gBullets[iBullet].pNodes[i] = NULL; } //afp-end // decrease soldier's bullet count if (gBullets[ iBullet ].fReal) { // set to be deleted at next update gBullets[ iBullet ].fToDelete = TRUE; // decrement reference to bullet in the firer // gBullets[ iBullet ].pFirer->bBulletsLeft--; // DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Ending bullet, bullets left %d", gBullets[ iBullet ].pFirer->bBulletsLeft ) ); // DebugAttackBusy( String( "Deleting a bullet for %d. Total count now %d\n", gBullets[ iBullet].ubFirerID, gBullets[ iBullet ].pFirer->bBulletsLeft) ); // Nah, just decrement the attack busy count and be done with it DebugAttackBusy( String( "Deleting a bullet for %d.\n", gBullets[ iBullet].ubFirerID ) ); // HEADROCK HAM 5: Fragments do not need reducing. if (gBullets[iBullet].fFragment == false) { ReduceAttackBusyCount( ); } // if ( gBullets[ iBullet ].usFlags & ( BULLET_FLAG_KNIFE ) ) // { // Delete ani tile if ( gBullets[ iBullet ].pAniTile != NULL ) { DeleteAniTile( gBullets[ iBullet ].pAniTile ); gBullets[ iBullet ].pAniTile = NULL; } // Delete shadow // if ( gBullets[ iBullet ].usFlags & ( BULLET_FLAG_KNIFE ) ) // { if ( gBullets[ iBullet ].pShadowAniTile != NULL ) { DeleteAniTile( gBullets[ iBullet ].pShadowAniTile ); gBullets[ iBullet ].pShadowAniTile = NULL; } // } // } } else { // delete this fake bullet right away! gBullets[ iBullet ].fAllocated = FALSE; RecountBullets(); } }
void DeleteAniTile( ANITILE *pAniTile ) { ANITILE *pAniNode = NULL; ANITILE *pOldAniNode = NULL; TILE_ELEMENT *TileElem; pAniNode = pAniTileHead; while( pAniNode!= NULL ) { if ( pAniNode == pAniTile ) { // OK, set links // Check for head or tail if ( pOldAniNode == NULL ) { // It's the head pAniTileHead = pAniTile->pNext; } else { pOldAniNode->pNext = pAniNode->pNext; } if ( !(pAniNode->uiFlags & ANITILE_EXISTINGTILE ) ) { // Delete memory assosiated with item switch( pAniNode->ubLevelID ) { case ANI_STRUCT_LEVEL: RemoveStructFromLevelNode( pAniNode->sGridNo, pAniNode->pLevelNode ); break; case ANI_SHADOW_LEVEL: RemoveShadowFromLevelNode( pAniNode->sGridNo, pAniNode->pLevelNode ); break; case ANI_OBJECT_LEVEL: RemoveObject( pAniNode->sGridNo, pAniNode->usTileIndex ); break; case ANI_ROOF_LEVEL: RemoveRoof( pAniNode->sGridNo, pAniNode->usTileIndex ); break; case ANI_ONROOF_LEVEL: RemoveOnRoof( pAniNode->sGridNo, pAniNode->usTileIndex ); break; case ANI_TOPMOST_LEVEL: RemoveTopmostFromLevelNode( pAniNode->sGridNo, pAniNode->pLevelNode ); break; } if ( ( pAniNode->uiFlags & ANITILE_CACHEDTILE ) ) { RemoveCachedTile( pAniNode->sCachedTileID ); } if ( pAniNode->uiFlags & ANITILE_EXPLOSION ) { // Talk to the explosion data... RemoveExplosionData( pAniNode->uiUserData3 ); if ( !gfExplosionQueueActive ) { // turn on sighting again // the explosion queue handles all this at the end of the queue gTacticalStatus.uiFlags &= (~DISALLOW_SIGHT); } // Freeup attacker from explosion DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Reducing attacker busy count..., EXPLOSION effect gone off") ); ReduceAttackBusyCount( (UINT8)pAniNode->ubUserData2, FALSE ); } if ( pAniNode->uiFlags & ANITILE_RELEASE_ATTACKER_WHEN_DONE ) { // First delete the bullet! RemoveBullet( pAniNode->uiUserData3 ); DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - miss finished animation") ); FreeUpAttacker( (UINT8) pAniNode->ubAttackerMissed ); } } else { TileElem = &( gTileDatabase[ pAniNode->usTileIndex ] ); // OK, update existing tile usIndex.... Assert( TileElem->pAnimData != NULL ); pAniNode->pLevelNode->usIndex = TileElem->pAnimData->pusFrames[ pAniNode->pLevelNode->sCurrentFrame ]; // OK, set our frame data back to zero.... pAniNode->pLevelNode->sCurrentFrame = 0; // Set some flags to write to Z / update save buffer // pAniNode->pLevelNode->uiFlags |=( LEVELNODE_LASTDYNAMIC | LEVELNODE_UPDATESAVEBUFFERONCE ); pAniNode->pLevelNode->uiFlags &= ~( LEVELNODE_DYNAMIC | LEVELNODE_USEZ | LEVELNODE_ANIMATION ); if (pAniNode->uiFlags & ANITILE_DOOR) { // unset door busy! DOOR_STATUS * pDoorStatus; pDoorStatus = GetDoorStatus( pAniNode->sGridNo ); if (pDoorStatus) { pDoorStatus->ubFlags &= ~(DOOR_BUSY); } if ( GridNoOnScreen( pAniNode->sGridNo ) ) { SetRenderFlags(RENDER_FLAG_FULL); } } } MemFree( pAniNode ); return; } pOldAniNode = pAniNode; pAniNode = pAniNode->pNext; } }