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 UpdateBullets( ) { UINT32 uiCount; LEVELNODE *pNode; BOOLEAN fDeletedSome = FALSE; for ( uiCount = 0; uiCount < guiNumBullets; uiCount++ ) { if ( gBullets[ uiCount ].fAllocated) { if (gBullets[ uiCount ].fReal && !( gBullets[ uiCount ].usFlags & BULLET_STOPPED ) ) { // there are duplicate checks for deletion in case the bullet is deleted by shooting // someone at point blank range, in the first MoveBullet call in the FireGun code if ( gBullets[ uiCount ].fToDelete ) { // Remove from old position gBullets[ uiCount ].fAllocated = FALSE; fDeletedSome = TRUE; continue; } //if ( !( gGameSettings.fOptions[ TOPTION_HIDE_BULLETS ] ) ) { // ALRIGHTY, CHECK WHAT TYPE OF BULLET WE ARE if ( gBullets[ uiCount ].usFlags & ( BULLET_FLAG_CREATURE_SPIT | BULLET_FLAG_KNIFE | BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME /*| BULLET_FLAG_TRACER*/ ) ) { } else { RemoveStruct( gBullets[ uiCount ].sGridNo, BULLETTILE1 ); RemoveStruct( gBullets[ uiCount ].sGridNo, BULLETTILE2 ); } } //afp-start // remove old tail first if exists FIXEDPT lastX = gBullets[uiCount].qCurrX; FIXEDPT lastY = gBullets[uiCount].qCurrY; FIXEDPT lastZ = gBullets[uiCount].qCurrZ; for (int i = 0; i < BULLET_TRACER_MAX_LENGTH; i++) if (gBullets[uiCount].pNodes[i] != NULL) { RemoveStructFromLevelNode(gBullets[ uiCount ].sGridNo, gBullets[uiCount].pNodes[i]); gBullets[uiCount].pNodes[i] = NULL; } //afp-end MoveBullet( uiCount ); if ( gBullets[ uiCount ].fToDelete ) { // Remove from old position gBullets[ uiCount ].fAllocated = FALSE; fDeletedSome = TRUE; continue; } if ( gBullets[ uiCount ].usFlags & BULLET_STOPPED ) { continue; } // Display bullet //if ( !( gGameSettings.fOptions[ TOPTION_HIDE_BULLETS ] ) ) { if ( gBullets[ uiCount ].usFlags & ( BULLET_FLAG_KNIFE ) ) { if ( gBullets[ uiCount ].pAniTile != NULL ) { gBullets[ uiCount ].pAniTile->sRelativeX = (INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrX ); gBullets[ uiCount ].pAniTile->sRelativeY = (INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrY ); gBullets[ uiCount ].pAniTile->pLevelNode->sRelativeZ = (INT16) CONVERT_HEIGHTUNITS_TO_PIXELS( FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrZ ) ); if ( gBullets[ uiCount ].usFlags & ( BULLET_FLAG_KNIFE ) ) { gBullets[ uiCount ].pShadowAniTile->sRelativeX = (INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrX ); gBullets[ uiCount ].pShadowAniTile->sRelativeY = (INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrY ); } } } // Are we a missle? else if ( gBullets[ uiCount ].usFlags & ( BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT ) ) { } /* else if ( gBullets[ uiCount ].usFlags & ( BULLET_FLAG_TRACER ) ) { ManLooksForOtherTeams(gBullets[ uiCount ].pFirer); } */ /* else if (fTracer == TRUE) { ManLooksForOtherTeams(gBullets[ uiCount ].pFirer); } */ else { pNode = AddStructToTail( gBullets[ uiCount ].sGridNo, BULLETTILE1 ); pNode->ubShadeLevel=DEFAULT_SHADE_LEVEL; pNode->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL; pNode->uiFlags |= ( LEVELNODE_USEABSOLUTEPOS | LEVELNODE_IGNOREHEIGHT ); pNode->sRelativeX = (INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrX ); pNode->sRelativeY = (INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrY ); pNode->sRelativeZ = (INT16) CONVERT_HEIGHTUNITS_TO_PIXELS( FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrZ ) ); //afp-start - add new tail /tracer // HEADROCK HAM 5: No tail for fragments. if (gGameSettings.fOptions[TOPTION_ALTERNATE_BULLET_GRAPHICS] && gBullets[ uiCount ].fFragment == false) { if ((lastX != 0) || (lastY != 0)) { // qIncrX can be used to calculate slope and make the tracer longer if necessary PointsPath((INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrX), (INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrY), (INT16) FIXEDPT_TO_INT32( lastX), (INT16) FIXEDPT_TO_INT32( lastY)); // compute valid points allong the fire line int pointsCount = 0; for (int i = 0; i < BULLET_TRACER_MAX_LENGTH; i++) { pointsCount = i; if (gXPATH[i] == 0) if (gYPATH[i] == 0) break; } if (pointsCount <= 0) pointsCount = 30; for (int i = 0; i < BULLET_TRACER_MAX_LENGTH; i++) { if (gXPATH[i] == 0) if (gYPATH[i] == 0) break; // add all points along the path between bullets as bullets pNode = AddStructToTail( gBullets[ uiCount ].sGridNo, BULLETTILE1 ); pNode->ubShadeLevel=DEFAULT_SHADE_LEVEL; pNode->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL; pNode->uiFlags |= ( LEVELNODE_USEABSOLUTEPOS | LEVELNODE_IGNOREHEIGHT ); pNode->sRelativeX = gXPATH[i]; pNode->sRelativeY = gYPATH[i]; FIXEDPT relativeZ = lastZ - ((i + 1) * ((gBullets[ uiCount ].qCurrZ - lastZ) / (pointsCount))); pNode->sRelativeZ = (INT16) CONVERT_HEIGHTUNITS_TO_PIXELS( FIXEDPT_TO_INT32( relativeZ)); // store structure pointer to clear image at the next bullet position gBullets[uiCount].pNodes[i] = pNode; } } } //afp-end // Display shadow // afp - no more shadow if tracer enabled if (!gGameSettings.fOptions[TOPTION_ALTERNATE_BULLET_GRAPHICS]) { pNode = AddStructToTail( gBullets[ uiCount ].sGridNo, BULLETTILE2 ); pNode->ubShadeLevel=DEFAULT_SHADE_LEVEL; pNode->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL; pNode->uiFlags |= ( LEVELNODE_USEABSOLUTEPOS | LEVELNODE_IGNOREHEIGHT ); pNode->sRelativeX = (INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrX ); pNode->sRelativeY = (INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrY ); pNode->sRelativeZ = (INT16)gpWorldLevelData[ gBullets[ uiCount ].sGridNo ].sHeight; } } } } else { if ( gBullets[ uiCount ].fToDelete ) { gBullets[ uiCount ].fAllocated = FALSE; fDeletedSome = TRUE; } } } } if ( fDeletedSome ) { 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; } }