/** 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; }
/* See if there is a target in range for Sensor objects*/ BOOL aiChooseSensorTarget(BASE_OBJECT *psObj, BASE_OBJECT **ppsTarget) { int sensorRange = objSensorRange(psObj); unsigned int radSquared = sensorRange * sensorRange; bool radarDetector = objRadarDetector(psObj); if (!objActiveRadar(psObj) && !radarDetector) { ASSERT(false, "Only to be used for sensor turrets!"); return false; } /* See if there is something in range */ if (radarDetector) { BASE_OBJECT *psCurr, *psTemp = NULL; int tarDist = SDWORD_MAX; gridStartIterate(psObj->pos.x, psObj->pos.y, PREVIOUS_DEFAULT_GRID_SEARCH_RADIUS); psCurr = gridIterate(); while (psCurr != NULL) { if ((psCurr->type == OBJ_STRUCTURE || psCurr->type == OBJ_DROID) && !aiObjectIsProbablyDoomed(psCurr)) { if (!aiCheckAlliances(psCurr->player,psObj->player) && objActiveRadar(psCurr)) { // See if in twice *their* sensor range const int xdiff = psCurr->pos.x - psObj->pos.x; const int ydiff = psCurr->pos.y - psObj->pos.y; const unsigned int distSq = xdiff * xdiff + ydiff * ydiff; const int targetSensor = objSensorRange(psCurr) * 2; const unsigned int sensorSquared = targetSensor * targetSensor; if (distSq < sensorSquared && distSq < tarDist) { psTemp = psCurr; tarDist = distSq; } } } psCurr = gridIterate(); } if (psTemp) { objTrace(psTemp->id, "Targetted by radar detector %d", (int)psObj->id); objTrace(psObj->id, "Targetting radar %d", (int)psTemp->id); ASSERT(!psTemp->died, "aiChooseSensorTarget gave us a dead target"); *ppsTarget = psTemp; return true; } } else if (psObj->type == OBJ_DROID) { BASE_OBJECT *psTarget = NULL; if (aiBestNearestTarget((DROID *)psObj, &psTarget, 0, NULL) >= 0) { /* See if in sensor range */ const int xdiff = psTarget->pos.x - psObj->pos.x; const int ydiff = psTarget->pos.y - psObj->pos.y; const unsigned int distSq = xdiff * xdiff + ydiff * ydiff; // I do believe this will never happen, check for yourself :-) debug(LOG_NEVER, "Sensor droid(%d) found possible target(%d)!!!", psObj->id, psTarget->id); if (distSq < radSquared) { *ppsTarget = psTarget; return true; } } } else // structure { BASE_OBJECT *psCurr, *psTemp = NULL; int tarDist = SDWORD_MAX; gridStartIterate(psObj->pos.x, psObj->pos.y, PREVIOUS_DEFAULT_GRID_SEARCH_RADIUS); psCurr = gridIterate(); while (psCurr != NULL) { // Don't target features or doomed/dead objects if (psCurr->type != OBJ_FEATURE && !aiObjectIsProbablyDoomed(psCurr)) { if (!aiCheckAlliances(psCurr->player,psObj->player) && !aiObjIsWall(psCurr)) { // See if in sensor range and visible const int xdiff = psCurr->pos.x - psObj->pos.x; const int ydiff = psCurr->pos.y - psObj->pos.y; const unsigned int distSq = xdiff * xdiff + ydiff * ydiff; if (distSq < radSquared && psCurr->visible[psObj->player] && distSq < tarDist) { psTemp = psCurr; tarDist = distSq; } } } psCurr = gridIterate(); } if (psTemp) { ASSERT(!psTemp->died, "aiChooseSensorTarget gave us a dead target"); *ppsTarget = psTemp; return true; } } return false; }
/* See if there is a target in range for Sensor objects*/ bool aiChooseSensorTarget(BASE_OBJECT *psObj, BASE_OBJECT **ppsTarget) { int sensorRange = objSensorRange(psObj); unsigned int radSquared = sensorRange * sensorRange; bool radarDetector = objRadarDetector(psObj); if (!objActiveRadar(psObj) && !radarDetector) { ASSERT(false, "Only to be used for sensor turrets!"); return false; } /* See if there is something in range */ if (psObj->type == OBJ_DROID) { BASE_OBJECT *psTarget = NULL; if (aiBestNearestTarget((DROID *)psObj, &psTarget, 0) >= 0) { /* See if in sensor range */ const int xdiff = psTarget->pos.x - psObj->pos.x; const int ydiff = psTarget->pos.y - psObj->pos.y; const unsigned int distSq = xdiff * xdiff + ydiff * ydiff; // I do believe this will never happen, check for yourself :-) debug(LOG_NEVER, "Sensor droid(%d) found possible target(%d)!!!", psObj->id, psTarget->id); if (distSq < radSquared) { *ppsTarget = psTarget; return true; } } } else // structure { BASE_OBJECT *psTemp = NULL; int tarDist = SDWORD_MAX; static GridList gridList; // static to avoid allocations. gridList = gridStartIterate(psObj->pos.x, psObj->pos.y, objSensorRange(psObj)); for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi) { BASE_OBJECT *psCurr = *gi; // Don't target features or doomed/dead objects if (psCurr->type != OBJ_FEATURE && !psCurr->died && !aiObjectIsProbablyDoomed(psCurr, false)) { if (!aiCheckAlliances(psCurr->player, psObj->player) && !aiObjIsWall(psCurr)) { // See if in sensor range and visible const int xdiff = psCurr->pos.x - psObj->pos.x; const int ydiff = psCurr->pos.y - psObj->pos.y; const unsigned int distSq = xdiff * xdiff + ydiff * ydiff; if (distSq < radSquared && psCurr->visible[psObj->player] == UBYTE_MAX && distSq < tarDist) { psTemp = psCurr; tarDist = distSq; } } } } if (psTemp) { ASSERT(!psTemp->died, "aiChooseSensorTarget gave us a dead target"); *ppsTarget = psTemp; return true; } } return false; }