/*checks through the target players list of structures and droids to see if any support a counter battery sensor*/ void counterBatteryFire(BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget) { BASE_OBJECT *psViewer; /*if a null target is passed in ignore - this will be the case when a 'miss' projectile is sent - we may have to cater for these at some point*/ // also ignore cases where you attack your own player // Also ignore cases where there are already 1000 missiles heading towards the attacker. if (psTarget == NULL || (psAttacker != NULL && psAttacker->player == psTarget->player) || aiObjectIsProbablyDoomed(psAttacker)) { return; } CHECK_OBJECT(psTarget); for (psViewer = apsSensorList[0]; psViewer; psViewer = psViewer->psNextFunc) { if (aiCheckAlliances(psTarget->player, psViewer->player)) { if ((psViewer->type == OBJ_STRUCTURE && !structCBSensor((STRUCTURE *)psViewer)) || (psViewer->type == OBJ_DROID && !cbSensorDroid((DROID *)psViewer))) { continue; } const int sensorRange = objSensorRange(psViewer); // Check sensor distance from target const int xDiff = psViewer->pos.x - psTarget->pos.x; const int yDiff = psViewer->pos.y - psTarget->pos.y; if (xDiff * xDiff + yDiff * yDiff < sensorRange * sensorRange) { // Inform viewer of target if (psViewer->type == OBJ_DROID) { orderDroidObj((DROID *)psViewer, DORDER_OBSERVE, psAttacker, ModeImmediate); } else if (psViewer->type == OBJ_STRUCTURE) { ((STRUCTURE *)psViewer)->psTarget[0] = psAttacker; } } } } }
/*checks through the target players list of structures and droids to see if any support a counter battery sensor*/ void counterBatteryFire(BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget) { BASE_OBJECT *psViewer; /*if a null target is passed in ignore - this will be the case when a 'miss' projectile is sent - we may have to cater for these at some point*/ // also ignore cases where you attack your own player // Also ignore cases where there are already 1000 missiles heading towards the attacker. if ((psTarget == NULL) || ((psAttacker != NULL) && (psAttacker->player == psTarget->player)) || aiObjectIsProbablyDoomed(psAttacker)) { return; } CHECK_OBJECT(psTarget); gridStartIterate(psTarget->pos.x, psTarget->pos.y, PREVIOUS_DEFAULT_GRID_SEARCH_RADIUS); for (psViewer = gridIterate(); psViewer != NULL; psViewer = gridIterate()) { STRUCTURE *psStruct; DROID *psDroid; SDWORD sensorRange = 0; if (psViewer->player != psTarget->player) { //ignore non target players' objects continue; } if (psViewer->type == OBJ_STRUCTURE) { psStruct = (STRUCTURE *)psViewer; //check if have a sensor of correct type if (structCBSensor(psStruct) || structVTOLCBSensor(psStruct)) { sensorRange = psStruct->pStructureType->pSensor->range; } } else if (psViewer->type == OBJ_DROID) { psDroid = (DROID *)psViewer; //must be a CB sensor if (cbSensorDroid(psDroid)) { sensorRange = asSensorStats[psDroid->asBits[COMP_SENSOR]. nStat].range; } } //check sensor distance from target if (sensorRange) { SDWORD xDiff = (SDWORD)psViewer->pos.x - (SDWORD)psTarget->pos.x; SDWORD yDiff = (SDWORD)psViewer->pos.y - (SDWORD)psTarget->pos.y; if (xDiff*xDiff + yDiff*yDiff < sensorRange * sensorRange) { //inform viewer of target if (psViewer->type == OBJ_DROID) { orderDroidObj((DROID *)psViewer, DORDER_OBSERVE, psAttacker, ModeImmediate); } else if (psViewer->type == OBJ_STRUCTURE) { ((STRUCTURE *)psViewer)->psTarget[0] = psAttacker; } } } } }
/** Search the global list of sensors for a possible target for psObj. */ static BASE_OBJECT *aiSearchSensorTargets(BASE_OBJECT *psObj, int weapon_slot, WEAPON_STATS *psWStats, UWORD *targetOrigin) { int longRange = proj_GetLongRange(psWStats); int tarDist = longRange * longRange; BOOL foundCB = false; int minDist = psWStats->minRange * psWStats->minRange; BASE_OBJECT *psSensor, *psTarget = NULL; if (targetOrigin) { *targetOrigin = ORIGIN_UNKNOWN; } for (psSensor = apsSensorList[0]; psSensor; psSensor = psSensor->psNextFunc) { BASE_OBJECT *psTemp = NULL; bool isCB = false; bool isRD = false; if (!aiCheckAlliances(psSensor->player, psObj->player)) { continue; } else if (psSensor->type == OBJ_DROID) { DROID *psDroid = (DROID *)psSensor; ASSERT_OR_RETURN(false, psDroid->droidType == DROID_SENSOR, "A non-sensor droid in a sensor list is non-sense"); psTemp = psDroid->psTarget; isCB = cbSensorDroid(psDroid); isRD = objRadarDetector((BASE_OBJECT *)psDroid); } else if (psSensor->type == OBJ_STRUCTURE) { STRUCTURE *psCStruct = (STRUCTURE *)psSensor; // skip incomplete structures if (psCStruct->status != SS_BUILT) { continue; } psTemp = psCStruct->psTarget[0]; isCB = structCBSensor(psCStruct); isRD = objRadarDetector((BASE_OBJECT *)psCStruct); } if (!psTemp || aiObjectIsProbablyDoomed(psTemp) || !validTarget(psObj, psTemp, 0) || aiCheckAlliances(psTemp->player, psObj->player)) { continue; } if (aiObjHasRange(psObj, psTemp, weapon_slot) && visibleObject(psSensor, psTemp, false)) { int distSq = objPosDiffSq(psTemp->pos, psObj->pos); // Need to be in range, prefer closer targets or CB targets if ((isCB > foundCB || (isCB == foundCB && distSq < tarDist)) && distSq > minDist) { tarDist = distSq; psTarget = psTemp; if (targetOrigin) { *targetOrigin = ORIGIN_SENSOR; } if (isCB) { if (targetOrigin) { *targetOrigin = ORIGIN_CB_SENSOR; } foundCB = true; // got CB target, drop everything and shoot! } else if (isRD) { if (targetOrigin) { *targetOrigin = ORIGIN_RADAR_DETECTOR; } } } } } return psTarget; }