After these changes, the 2 functions look like attached, with the also attached differences.
static void proj_InFlightDirectFunc( PROJECTILE *psProj ) { /* we want a delay between Las-Sats firing and actually hitting in multiPlayer magic number but that's how long the audio countdown message lasts! */ const unsigned int LAS_SAT_DELAY = 8; int timeSoFar; int distancePercent; /* How far we are 0..100 */ float distanceRatio; /* How far we are, 1.0==at target */ float distanceExtensionFactor; /* Extended lifespan */ Vector3i move; unsigned int i; // Projectile is missile: bool bMissile = false; WEAPON_STATS *psStats;
CHECK_PROJECTILE(psProj); timeSoFar = gameTime - psProj->born; psStats = psProj->psWStats; ASSERT( psStats != NULL, "proj_InFlightDirectFunc: Invalid weapon stats pointer" ); /* we want a delay between Las-Sats firing and actually hitting in multiPlayer magic number but that's how long the audio countdown message lasts! */ if ( bMultiPlayer && psStats->weaponSubClass == WSC_LAS_SAT && timeSoFar < LAS_SAT_DELAY * GAME_TICKS_PER_SEC ) { return; } /* Calculate extended lifespan where appropriate */ switch (psStats->weaponSubClass) { case WSC_MGUN: case WSC_COMMAND: distanceExtensionFactor = 1.2f; break; case WSC_CANNON: case WSC_BOMB: case WSC_ELECTRONIC: case WSC_EMP: case WSC_FLAME: case WSC_ENERGY: case WSC_GAUSS: distanceExtensionFactor = 1.5f; break; case WSC_AAGUN: // No extended distance distanceExtensionFactor = 1.0f; break; case WSC_ROCKET: case WSC_MISSILE: case WSC_SLOWROCKET: case WSC_SLOWMISSILE: bMissile = true; // Take the same extended targetDistance as artillery case WSC_COUNTER: case WSC_MORTARS: case WSC_HOWITZERS: case WSC_LAS_SAT: distanceExtensionFactor = 1.5f; break; default: // NUM_WEAPON_SUBCLASS and INVALID_SUBCLASS break; } /* Do movement */ { unsigned int targetDistance, currentDistance; /* Calculate movement vector: */ if ( psStats->movementModel == MM_HOMINGDIRECT && psProj->psDest ) { /* If it's homing and it has a target (not a miss)... */ move.x = psProj->psDest->pos.x - psProj->startX; move.y = psProj->psDest->pos.y - psProj->startY; move.z = psProj->psDest->pos.z - psProj->srcHeight; } else { move.x = psProj->tarX - psProj->startX; move.y = psProj->tarY - psProj->startY; move.z = psProj->altChange; } targetDistance = sqrtf( move.x*move.x + move.y*move.y ); currentDistance = timeSoFar * psStats->flightSpeed / GAME_TICKS_PER_SEC; // Prevent div by zero: if ( targetDistance == 0 ) targetDistance = 1; distanceRatio = (float)currentDistance / targetDistance; distancePercent = PERCENT(currentDistance, targetDistance); { /* Calculate next position */ Vector3uw nextPos = { psProj->startX + (distanceRatio * move.x), psProj->startY + (distanceRatio * move.y), psProj->srcHeight + (distanceRatio * move.z) }; /* impact if about to go off map else update coordinates */ if ( !worldOnMap( nextPos.x, nextPos.y ) ) { psProj->state = PROJ_IMPACT; setProjectileDestination(psProj, NULL); debug( LOG_NEVER, "**** projectile off map - removed ****\n" ); return; } /* Update position */ psProj->pos = nextPos; } } for (i = 0; i < numProjNaybors; i++) { BASE_OBJECT *psTempObj = asProjNaybors[i].psObj; CHECK_OBJECT(psTempObj); if ( psTempObj == psProj->psDamaged ) { // Dont damage one target twice continue; } if ( psTempObj->died ) { // Do not damage dead objects further continue; } if ( psTempObj->type == OBJ_PROJECTILE && !( bMissile || ((PROJECTILE *)psTempObj)->psWStats->weaponSubClass == WSC_COUNTER ) ) { // A projectile should not collide with another projectile unless it's a counter-missile weapon continue; } if ( psTempObj->type == OBJ_FEATURE && !((FEATURE *)psTempObj)->psStats->damageable ) { // Ignore oil resources, artifacts and other pickups continue; } if ( psTempObj->player == psProj->player || aiCheckAlliances(psTempObj->player, psProj->player) ) { // No friendly fire continue; } if ( psStats->surfaceToAir == SHOOT_IN_AIR && ( psTempObj->type == OBJ_STRUCTURE || psTempObj->type == OBJ_FEATURE || ( psTempObj->type == OBJ_DROID && !vtolDroid((DROID *)psTempObj) ) ) ) { // AA weapons should not hit buildings and non-vtol droids continue; } { // FIXME HACK Needed since we got those ugly Vector3uw floating around in BASE_OBJECT... Vector3i posProj = { psProj->pos.x, psProj->pos.y, psProj->pos.z }, posTemp = { psTempObj->pos.x, psTempObj->pos.y, psTempObj->pos.z }; Vector3i diff = Vector3i_Sub(posProj, posTemp); unsigned int targetHeight = establishTargetHeight(psTempObj); unsigned int targetRadius = establishTargetRadius(psTempObj); /* Height is always positive */ diff.z = abs(diff.z); /* We hit! */ if ( diff.z < targetHeight && (diff.x*diff.x + diff.y*diff.y) < targetRadius * targetRadius ) { setProjectileDestination(psProj, psTempObj); /* Buildings cannot be penetrated and we need a penetrating weapon */ if ( psTempObj->type == OBJ_DROID && psStats->penetrate ) { WEAPON asWeap = { psStats - asWeaponStats, 0, 0, 0, 0 }; // Determine position to fire a missile at // (must be at least 0 because we don't use signed integers // this shouldn't be larger than the height and width of the map either) Vector3i newDest = { psProj->startX + move.x * distanceExtensionFactor, psProj->startY + move.y * distanceExtensionFactor, psProj->srcHeight + move.z * distanceExtensionFactor }; newDest.x = clip(newDest.x, 0, world_coord(mapWidth - 1)); newDest.y = clip(newDest.y, 0, world_coord(mapHeight - 1)); //Watermelon:just assume we damaged the chosen target setProjectileDamaged(psProj, psTempObj); proj_SendProjectile( &asWeap, (BASE_OBJECT*)psProj, psProj->player, newDest, NULL, true, -1 ); } psProj->state = PROJ_IMPACT; return; } } } if ( distanceRatio > distanceExtensionFactor || /* We've traveled our maximum range */ !mapObjIsAboveGround( (BASE_OBJECT *) psProj ) ) /* trying to travel through terrain */ { /* Miss due to range or height */ psProj->state = PROJ_IMPACT; setProjectileDestination(psProj, NULL); /* miss registered if NULL target */ return; } /* Paint effects if visible */ if ( gfxVisible(psProj) ) { switch (psStats->weaponSubClass) { case WSC_FLAME: { Vector3i pos = { psProj->pos.x, psProj->pos.z-8, psProj->pos.y }; effectGiveAuxVar(distancePercent); addEffect(&pos,EFFECT_EXPLOSION,EXPLOSION_TYPE_FLAMETHROWER,false,NULL,0); } break; case WSC_COMMAND: case WSC_ELECTRONIC: case WSC_EMP: { Vector3i pos = { psProj->pos.x, psProj->pos.z-8, psProj->pos.y }; effectGiveAuxVar(distancePercent/2); addEffect(&pos,EFFECT_EXPLOSION,EXPLOSION_TYPE_LASER,false,NULL,0); } break; case WSC_ROCKET: case WSC_MISSILE: case WSC_SLOWROCKET: case WSC_SLOWMISSILE: { Vector3i pos = { psProj->pos.x, psProj->pos.z+8, psProj->pos.y }; addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0); } break; default: /* add smoke trail to indirect weapons firing directly */ if ( !proj_Direct(psStats) ) { Vector3i pos = { psProj->pos.x, psProj->pos.z+4, psProj->pos.y }; addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0); } /* Otherwise no effect */ break; } } }
static void proj_InFlightIndirectFunc( PROJECTILE *psProj ) { /* NOTE Main differences to direct projectiles: - Movement vector / pitch update - No extended radius - Some optimisations by leaving out tests which are never true (homing, AA, counter-missile, lassat) */ int timeSoFar; int distancePercent; /* How far we are 0..100 */ float distanceRatio; /* How far we are, 1.0==at target */ float distanceExtensionFactor; /* Extended lifespan */ Vector3i move; unsigned int i; WEAPON_STATS *psStats; CHECK_PROJECTILE(psProj); timeSoFar = gameTime - psProj->born; psStats = psProj->psWStats; ASSERT( psStats != NULL, "proj_InFlightIndirectFunc: Invalid weapon stats pointer" ); /* Calculate extended lifespan where appropriate */ distanceExtensionFactor = 1.2f; /* Do movement */ { unsigned int targetDistance, currentDistance; /* Calculate movement vector: */ move.x = psProj->tarX - psProj->startX; move.y = psProj->tarY - psProj->startY; move.z = (psProj->vZ - (timeSoFar * ACC_GRAVITY / (GAME_TICKS_PER_SEC * 2))) * timeSoFar / GAME_TICKS_PER_SEC; // '2' because we reach our highest point in the mid of flight, when "vZ is 0". targetDistance = sqrtf( move.x*move.x + move.y*move.y ); currentDistance = timeSoFar * psProj->vXY / GAME_TICKS_PER_SEC; // FIXME ARTILLERY // Prevent div by zero: if ( targetDistance == 0 ) targetDistance = 1; distanceRatio = (float)currentDistance / targetDistance; distancePercent = PERCENT(currentDistance, targetDistance); { /* Calculate next position */ Vector3uw nextPos = { psProj->startX + (distanceRatio * move.x), psProj->startY + (distanceRatio * move.y), psProj->srcHeight + move.z }; /* impact if about to go off map else update coordinates */ if ( !worldOnMap( nextPos.x, nextPos.y ) ) { psProj->state = PROJ_IMPACT; setProjectileDestination(psProj, NULL); debug( LOG_NEVER, "**** projectile off map - removed ****\n" ); return; } /* Update position */ psProj->pos = nextPos; } } /* Update pitch */ { float fVVert = psProj->vZ - (timeSoFar * ACC_GRAVITY / GAME_TICKS_PER_SEC); psProj->pitch = rad2degf(atan2f(fVVert, psProj->vXY)); } for (i = 0; i < numProjNaybors; i++) { BASE_OBJECT *psTempObj = asProjNaybors[i].psObj; CHECK_OBJECT(psTempObj); if ( psTempObj == psProj->psDamaged ) { // Dont damage one target twice continue; } if ( psTempObj->died ) { // Do not damage dead objects further continue; } if ( psTempObj->type == OBJ_PROJECTILE ) { // A projectile should not collide with another projectile unless it's a counter-missile weapon // FIXME Indirectly firing weapons are never counter-missiles? continue; } if ( psTempObj->type == OBJ_FEATURE && !((FEATURE *)psTempObj)->psStats->damageable ) { // Ignore oil resources, artifacts and other pickups continue; } if ( psTempObj->player == psProj->player || aiCheckAlliances(psTempObj->player, psProj->player) ) { // No friendly fire continue; } { // FIXME HACK Needed since we got those ugly Vector3uw floating around in BASE_OBJECT... Vector3i posProj = { psProj->pos.x, psProj->pos.y, psProj->pos.z }, posTemp = { psTempObj->pos.x, psTempObj->pos.y, psTempObj->pos.z }; Vector3i diff = Vector3i_Sub(posProj, posTemp); unsigned int targetHeight = establishTargetHeight(psTempObj); unsigned int targetRadius = establishTargetRadius(psTempObj); /* Height is always positive */ diff.z = abs(diff.z); /* We hit! */ if ( diff.z < targetHeight && (diff.x*diff.x + diff.y*diff.y) < targetRadius * targetRadius ) { setProjectileDestination(psProj, psTempObj); /* Buildings cannot be penetrated and we need a penetrating weapon */ if ( psTempObj->type == OBJ_DROID && psStats->penetrate ) { WEAPON asWeap = { psStats - asWeaponStats, 0, 0, 0, 0 }; // Determine position to fire a missile at // (must be at least 0 because we don't use signed integers // this shouldn't be larger than the height and width of the map either) Vector3i newDest = { psProj->startX + move.x * distanceExtensionFactor, psProj->startY + move.y * distanceExtensionFactor, psProj->srcHeight + move.z * distanceExtensionFactor }; newDest.x = clip(newDest.x, 0, world_coord(mapWidth - 1)); newDest.y = clip(newDest.y, 0, world_coord(mapHeight - 1)); //Watermelon:just assume we damaged the chosen target setProjectileDamaged(psProj, psTempObj); proj_SendProjectile( &asWeap, (BASE_OBJECT*)psProj, psProj->player, newDest, NULL, true, -1 ); } psProj->state = PROJ_IMPACT; return; } } } if ( distanceRatio > distanceExtensionFactor || /* We've traveled our maximum range */ !mapObjIsAboveGround( (BASE_OBJECT *) psProj ) ) /* trying to travel through terrain */ { /* Miss due to range or height */ psProj->state = PROJ_IMPACT; setProjectileDestination(psProj, NULL); /* miss registered if NULL target */ return; } /* Paint effects if visible */ if ( gfxVisible(psProj) ) { switch (psStats->weaponSubClass) { case WSC_FLAME: { Vector3i pos = { psProj->pos.x, psProj->pos.z-8, psProj->pos.y }; effectGiveAuxVar(distancePercent); addEffect(&pos,EFFECT_EXPLOSION,EXPLOSION_TYPE_FLAMETHROWER,false,NULL,0); } break; case WSC_COMMAND: case WSC_ELECTRONIC: case WSC_EMP: { Vector3i pos = { psProj->pos.x, psProj->pos.z-8, psProj->pos.y }; effectGiveAuxVar(distancePercent/2); addEffect(&pos,EFFECT_EXPLOSION,EXPLOSION_TYPE_LASER,false,NULL,0); } break; case WSC_ROCKET: case WSC_MISSILE: case WSC_SLOWROCKET: case WSC_SLOWMISSILE: { Vector3i pos = { psProj->pos.x, psProj->pos.z+8, psProj->pos.y }; addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0); } break; default: { Vector3i pos = { psProj->pos.x, psProj->pos.z+4, psProj->pos.y }; addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0); } break; } } }
--- proj_direct.c 2008-05-22 23:25:00.000000000 +0200 +++ proj_indirect.c 2008-05-22 23:24:36.000000000 +0200 @@ -1,16 +1,17 @@ -static void proj_InFlightDirectFunc( PROJECTILE *psProj ) +static void proj_InFlightIndirectFunc( PROJECTILE *psProj ) { - /* we want a delay between Las-Sats firing and actually hitting in multiPlayer - magic number but that's how long the audio countdown message lasts! */ - const unsigned int LAS_SAT_DELAY = 8; + /* NOTE Main differences to direct projectiles: + - Movement vector / pitch update + - No extended radius + - Some optimisations by leaving out tests which are never true (homing, AA, counter-missile, lassat) + */ + int timeSoFar; int distancePercent; /* How far we are 0..100 */ float distanceRatio; /* How far we are, 1.0==at target */ float distanceExtensionFactor; /* Extended lifespan */ Vector3i move; unsigned int i; - // Projectile is missile: - bool bMissile = false; WEAPON_STATS *psStats; CHECK_PROJECTILE(psProj); @@ -19,72 +20,22 @@ psStats = psProj->psWStats; ASSERT( psStats != NULL, - "proj_InFlightDirectFunc: Invalid weapon stats pointer" ); - - /* we want a delay between Las-Sats firing and actually hitting in multiPlayer - magic number but that's how long the audio countdown message lasts! */ - if ( bMultiPlayer && psStats->weaponSubClass == WSC_LAS_SAT && - timeSoFar < LAS_SAT_DELAY * GAME_TICKS_PER_SEC ) - { - return; - } + "proj_InFlightIndirectFunc: Invalid weapon stats pointer" ); /* Calculate extended lifespan where appropriate */ - switch (psStats->weaponSubClass) - { - case WSC_MGUN: - case WSC_COMMAND: - distanceExtensionFactor = 1.2f; - break; - case WSC_CANNON: - case WSC_BOMB: - case WSC_ELECTRONIC: - case WSC_EMP: - case WSC_FLAME: - case WSC_ENERGY: - case WSC_GAUSS: - distanceExtensionFactor = 1.5f; - break; - case WSC_AAGUN: // No extended distance - distanceExtensionFactor = 1.0f; - break; - case WSC_ROCKET: - case WSC_MISSILE: - case WSC_SLOWROCKET: - case WSC_SLOWMISSILE: - bMissile = true; // Take the same extended targetDistance as artillery - case WSC_COUNTER: - case WSC_MORTARS: - case WSC_HOWITZERS: - case WSC_LAS_SAT: - distanceExtensionFactor = 1.5f; - break; - default: - // NUM_WEAPON_SUBCLASS and INVALID_SUBCLASS - break; - } + distanceExtensionFactor = 1.2f; /* Do movement */ { unsigned int targetDistance, currentDistance; /* Calculate movement vector: */ - if ( psStats->movementModel == MM_HOMINGDIRECT && psProj->psDest ) - { - /* If it's homing and it has a target (not a miss)... */ - move.x = psProj->psDest->pos.x - psProj->startX; - move.y = psProj->psDest->pos.y - psProj->startY; - move.z = psProj->psDest->pos.z - psProj->srcHeight; - } - else - { - move.x = psProj->tarX - psProj->startX; - move.y = psProj->tarY - psProj->startY; - move.z = psProj->altChange; - } + move.x = psProj->tarX - psProj->startX; + move.y = psProj->tarY - psProj->startY; + move.z = (psProj->vZ - (timeSoFar * ACC_GRAVITY / (GAME_TICKS_PER_SEC * 2))) * timeSoFar / GAME_TICKS_PER_SEC; // '2' because we reach our highest point in the mid of flight, when "vZ is 0". targetDistance = sqrtf( move.x*move.x + move.y*move.y ); - currentDistance = timeSoFar * psStats->flightSpeed / GAME_TICKS_PER_SEC; + currentDistance = timeSoFar * psProj->vXY / GAME_TICKS_PER_SEC; // FIXME ARTILLERY // Prevent div by zero: if ( targetDistance == 0 ) @@ -98,7 +49,7 @@ Vector3uw nextPos = { psProj->startX + (distanceRatio * move.x), psProj->startY + (distanceRatio * move.y), - psProj->srcHeight + (distanceRatio * move.z) + psProj->srcHeight + move.z }; /* impact if about to go off map else update coordinates */ @@ -115,6 +66,12 @@ } } + /* Update pitch */ + { + float fVVert = psProj->vZ - (timeSoFar * ACC_GRAVITY / GAME_TICKS_PER_SEC); + psProj->pitch = rad2degf(atan2f(fVVert, psProj->vXY)); + } + for (i = 0; i < numProjNaybors; i++) { BASE_OBJECT *psTempObj = asProjNaybors[i].psObj; @@ -133,10 +90,10 @@ continue; } - if ( psTempObj->type == OBJ_PROJECTILE && - !( bMissile || ((PROJECTILE *)psTempObj)->psWStats->weaponSubClass == WSC_COUNTER ) ) + if ( psTempObj->type == OBJ_PROJECTILE ) { // A projectile should not collide with another projectile unless it's a counter-missile weapon + // FIXME Indirectly firing weapons are never counter-missiles? continue; } @@ -154,16 +111,6 @@ continue; } - if ( psStats->surfaceToAir == SHOOT_IN_AIR && - ( psTempObj->type == OBJ_STRUCTURE || - psTempObj->type == OBJ_FEATURE || - ( psTempObj->type == OBJ_DROID && !vtolDroid((DROID *)psTempObj) ) - ) ) - { - // AA weapons should not hit buildings and non-vtol droids - continue; - } - { // FIXME HACK Needed since we got those ugly Vector3uw floating around in BASE_OBJECT... Vector3i @@ -250,14 +197,10 @@ addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0); } break; default: - /* add smoke trail to indirect weapons firing directly */ - if ( !proj_Direct(psStats) ) - { - Vector3i pos = { psProj->pos.x, psProj->pos.z+4, psProj->pos.y }; - addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0); - } - /* Otherwise no effect */ - break; + { + Vector3i pos = { psProj->pos.x, psProj->pos.z+4, psProj->pos.y }; + addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0); + } break; } } }
signature.asc
Description: This is a digitally signed message part.
_______________________________________________ Warzone-dev mailing list Warzone-dev@gna.org https://mail.gna.org/listinfo/warzone-dev