bool CWeapon::TryTarget(const float3 &pos,bool userTarget,CUnit* unit) { if (unit && !(onlyTargetCategory & unit->category)) { return false; } if(unit && ((unit->isDead && (modInfo.fireAtKilled==0)) || (unit->crashing && (modInfo.fireAtCrashing==0)))) { return false; } if (weaponDef->stockpile && !numStockpiled) { return false; } float3 dif=pos-weaponMuzzlePos; float heightDiff; // negative when target below owner if (targetBorder != 0 && unit) { float3 diff(dif); diff.Normalize(); // weapon inside target sphere if (dif.SqLength() < unit->sqRadius*targetBorder*targetBorder) { dif -= diff*(dif.Length() - 10); // a hack //logOutput << "inside\n"; } else { dif -= diff*(unit->radius*targetBorder); //logOutput << "outside\n"; } //geometricObjects->AddLine(weaponMuzzlePos, weaponMuzzlePos+dif, 3, 0, 16); heightDiff = (weaponPos.y + dif.y) - owner->pos.y; } else { heightDiff = pos.y - owner->pos.y; } float r; if (!unit || cylinderTargetting < 0.01) { r=GetRange2D(heightDiff*heightMod); } else { if (cylinderTargetting * range > fabs(heightDiff)*heightMod) { r = GetRange2D(0); } else { r = 0; } } if(dif.SqLength2D()>=r*r) return false; if(maxMainDirAngleDif>-0.999f){ dif.Normalize(); float3 modMainDir=owner->frontdir*mainDir.z+owner->rightdir*mainDir.x+owner->updir*mainDir.y; // geometricObjects->AddLine(weaponPos,weaponPos+modMainDir*50,3,0,16); if(modMainDir.dot(dif)<maxMainDirAngleDif) return false; } return true; }
bool CWeapon::TryTarget(const float3& tgtPos, bool /*userTarget*/, CUnit* targetUnit) { if (targetUnit && !(onlyTargetCategory & targetUnit->category)) { return false; } if (targetUnit && ((targetUnit->isDead && (modInfo.fireAtKilled == 0)) || (targetUnit->crashing && (modInfo.fireAtCrashing == 0)))) { return false; } if (weaponDef->stockpile && !numStockpiled) { return false; } float3 targetPos = tgtPos; float3 targetVec = targetPos - weaponMuzzlePos; float3 targetDir = targetVec; float heightDiff = 0.0f; // negative when target below owner float weaponRange = 0.0f; // range modified by heightDiff and cylinderTargetting bool targetDirNormalized = false; if (targetBorder != 0.0f && targetUnit != NULL) { // adjust the length of <targetVec> based on the targetBorder factor targetDirNormalized = AdjustTargetVectorLength(targetUnit, targetPos, targetVec, targetDir); targetPos.y = weaponPos.y + targetVec.y; } heightDiff = targetPos.y - owner->pos.y; if (targetUnit == NULL || cylinderTargetting < 0.01f) { // check range in a sphere (with extra radius <heightDiff * heightMod>) weaponRange = GetRange2D(heightDiff * heightMod); } else { // check range in a cylinder (with height <cylinderTargetting * range>) if ((cylinderTargetting * range) > (math::fabsf(heightDiff) * heightMod)) { weaponRange = GetRange2D(0.0f); } } if (targetVec.SqLength2D() >= (weaponRange * weaponRange)) return false; if (maxMainDirAngleDif > -0.999f) { const float3 targetNormDir = targetDirNormalized? targetDir: targetDir.SafeNormalize(); const float3 modMainDir = owner->frontdir * mainDir.z + owner->rightdir * mainDir.x + owner->updir * mainDir.y; if (modMainDir.dot(targetNormDir) < maxMainDirAngleDif) return false; } return true; }
void CCannon::Init(void) { gravity = weaponDef->myGravity==0 ? mapInfo->map.gravity : -(weaponDef->myGravity); highTrajectory = weaponDef->highTrajectory == 1; if(highTrajectory){ maxPredict=projectileSpeed*2/-gravity; minPredict=projectileSpeed*1.41f/-gravity; } else { maxPredict=projectileSpeed*1.41f/-gravity; } CWeapon::Init(); // initialize range factor rangeFactor = 1; rangeFactor = (float)range/GetRange2D(0); // do not extend range if the modder specified speed too low // for the projectile to reach specified range if (rangeFactor > 1.f || rangeFactor <= 0.f) rangeFactor = 1.f; // some magical (but working) equations // useful properties: if rangeFactor == 1, heightBoostFactor == 1 // TODO find something better? if (heightBoostFactor < 0.f) heightBoostFactor = (2.f - rangeFactor) / math::sqrt(rangeFactor); }
void CCannon::UpdateRange(const float val) { // clamp so as to not extend range if projectile // speed is too low to reach the *updated* range // note: new range can be zero (!) making range // and height factors irrelevant range = val; rangeFactor = Clamp(range / GetRange2D(0.0f, 1.0f), 0.0f, 1.0f); // some magical (but working) equations // useful properties: if rangeFactor == 1, heightBoostFactor == 1 // TODO find something better? if (heightBoostFactor < 0.0f && rangeFactor > 0.0f) { heightBoostFactor = (2.0f - rangeFactor) / math::sqrt(rangeFactor); } }
void CCannon::UpdateRange(float val) { range = val; // initialize range factor rangeFactor = 1.f; rangeFactor = range / GetRange2D(0); // do not extend range if the modder specified speed too low // for the projectile to reach specified range if (rangeFactor > 1.f || rangeFactor <= 0.f) rangeFactor = 1.f; // some magical (but working) equations // useful properties: if rangeFactor == 1, heightBoostFactor == 1 // TODO find something better? if (heightBoostFactor < 0.f) heightBoostFactor = (2.f - rangeFactor) / math::sqrt(rangeFactor); }
float CCannon::GetRange2D(const float yDiff) const { return (GetRange2D(yDiff, rangeFactor)); }