//------------------------------------------------------------------------------ // checkForTargetHit() -- check to see if we hit anything //------------------------------------------------------------------------------ bool Bullet::checkForTargetHit() { Player* ownship = getLaunchVehicle(); Player* tgt = getTargetPlayer(); if (ownship != nullptr && tgt != nullptr) { osg::Vec3 osPos = tgt->getPosition(); // For all active bursts ... for (int i = 0; i < nbt; i++) { if (bursts[i].bStatus == Burst::ACTIVE) { // Check if we're within range of the target osg::Vec3 rPos = bursts[i].bPos - osPos; LCreal rng = rPos.length(); if (rng < 10.0) { // Yes -- it's a hit! bursts[i].bStatus = Burst::HIT; setHitPlayer(tgt); setLocationOfDetonation(); tgt->processDetonation(rng,this); } } } } // if we are just flying along, check our range to the nearest player and tell him we killed it else { //osg::Vec3 old = getEulerAngles(); osg::Vec3 myPos = getPosition(); osg::Vec3 tgtPos; osg::Vec3 vecPos; //LCreal az = 0; //LCreal el = 0; LCreal range = 0; //LCreal diffAz = 0; //LCreal diffEl = 0; LCreal maxRange = 1; // close range of detonation Simulation* sim = getSimulation(); if (sim != nullptr) { Basic::PairStream* players = sim->getPlayers(); if (players != nullptr) { Basic::List::Item* item = players->getFirstItem(); while (item != nullptr) { Basic::Pair* pair = static_cast<Basic::Pair*>(item->getValue()); if (pair != nullptr) { Player* player = dynamic_cast<Player*>(pair->object()); if (player != nullptr && player != ownship && player->isMajorType(LIFE_FORM) && !player->isDestroyed()) { // ok, calculate our position from this guy tgtPos = player->getPosition(); vecPos = tgtPos - myPos; //az = lcAtan2(vecPos.y(), vecPos.x()); range = (vecPos.x() * vecPos.x() + vecPos.y() * vecPos.y()); range = std::sqrt(range); if (range < maxRange) { // tell this target we hit it player->processDetonation(range, this); } } } item = item->getNext(); } players->unref(); players = nullptr; } } } return false; }
//------------------------------------------------------------------------------ // weaponGuidance() -- default guidance; using Robot Aircraft (RAC) guidance //------------------------------------------------------------------------------ void Missile::weaponGuidance(const LCreal dt) { // --- // Control velocity: During burn time, accel to max velocity, // after burn time, deaccelerate to min velocity. // --- if (isEngineBurnEnabled()) cmdVelocity = vpMax; else cmdVelocity = vpMin; // --- // If the target's already dead, // then don't go away mad, just go away. // --- const Player* tgt = getTargetPlayer(); const Track* trk = getTargetTrack(); if (trk != 0) tgt = trk->getTarget(); if (tgt != 0 && !tgt->isActive()) return; osg::Vec3 los; // Target Line of Sight osg::Vec3 vel; // Target velocity // --- // Basic guidance // --- { // --- // Get position and velocity vectors from the target/track // --- osg::Vec3 posx; calculateVectors(tgt, trk, &los, &vel, &posx); // compute range to target LCreal trng0 = trng; trng = los.length(); // compute range rate, LCreal trdot0 = trdot; if (dt > 0) trdot = (trng - trng0)/dt; else trdot = 0; // Target total velocit LCreal totalVel = vel.length(); // compute target velocity parallel to LOS, LCreal vtplos = (los * vel/trng); // --- // guidance - fly to intercept point // --- // if we have guidance ... if ( isGuidanceEnabled() && trng > 0) { // get missile velocity (must be faster than target), LCreal v = vpMax; if (v < totalVel) v = totalVel + 1; // compute target velocity normal to LOS squared, LCreal tgtVp = totalVel; LCreal vtnlos2 = tgtVp*tgtVp - vtplos*vtplos; // and compute missile velocity parallex to LOS. LCreal vmplos = lcSqrt( v*v - vtnlos2 ); // Now, use both velocities parallel to LOS to compute // closure rate. LCreal vclos = vmplos - vtplos; // Use closure rate and range to compute time to intercept. LCreal dt1 = 0; if (vclos > 0) dt1 = trng/vclos; // Use time to intercept to extrapolate target position. osg::Vec3 p1 = (los + (vel * dt1)); // Compute missile commanded heading and cmdHeading = lcAtan2(p1.y(),p1.x()); // commanded pitch. LCreal grng = lcSqrt(p1.x()*p1.x() + p1.y()*p1.y()); cmdPitch = -lcAtan2(p1.z(),grng); } } // --- // fuzing logic (let's see if we've scored a hit) // (compute range at closest point and compare to max burst radius) // (use target truth data) // --- { // --- // Get position and velocity vectors from the target (truth) // (or default to the values from above) // --- if (tgt != 0) { calculateVectors(tgt, 0, &los, &vel, 0); } // compute range to target LCreal trng0 = trngT; trngT = los.length(); // compute range rate, LCreal trdot0 = trdotT; if (dt > 0) trdotT = (trngT - trng0)/dt; else trdotT = 0; // when we've just passed the target ... if (trdotT > 0 && trdot0 < 0 && !isDummy() && getTOF() > 2.0f) { bool missed = true; // assume the worst // compute relative velocity vector. osg::Vec3 velRel = (vel - getVelocity()); // compute missile velocity squared, LCreal vm2 = velRel.length2(); if (vm2 > 0) { // relative range (dot) relative velocity LCreal rdv = los * velRel; // interpolate back to closest point LCreal ndt = -rdv/vm2; osg::Vec3 p0 = los + (velRel*ndt); // range squared at closest point LCreal r2 = p0.length2(); // compare to burst radius squared if (r2 <= (getMaxBurstRng()*getMaxBurstRng()) ) { // We've detonated missed = false; setMode(DETONATED); setDetonationResults( DETONATE_ENTITY_IMPACT ); // compute location of the detonation relative to the target osg::Vec3 p0n = -p0; if (tgt != 0) p0n = tgt->getRotMat() * p0n; setDetonationLocation(p0n); // Did we hit anyone? checkDetonationEffect(); // Log the event LCreal detRange = getDetonationRange(); if (isMessageEnabled(MSG_INFO)) { std::cout << "DETONATE_ENTITY_IMPACT rng = " << detRange << std::endl; } if (getAnyEventLogger() != 0) { TabLogger::TabLogEvent* evt = new TabLogger::LogWeaponActivity(2, getLaunchVehicle(), this, getTargetPlayer(), DETONATE_ENTITY_IMPACT, detRange); // type 2 for "detonate" getAnyEventLogger()->log(evt); evt->unref(); } } } // Did we miss the target? if (missed) { // We've detonated ... setMode(DETONATED); setDetonationResults( DETONATE_DETONATION ); // because we've just missed the target setTargetPlayer(0,false); setTargetTrack(0,false); // Log the event LCreal detRange = trngT; if (isMessageEnabled(MSG_INFO)) { std::cout << "DETONATE_OTHER rng = " << detRange << std::endl; } if (getAnyEventLogger() != 0) { TabLogger::TabLogEvent* evt = new TabLogger::LogWeaponActivity(2, getLaunchVehicle(), this, getTargetPlayer(), DETONATE_DETONATION, getDetonationRange()); // type 2 for "detonate" getAnyEventLogger()->log(evt); evt->unref(); } } } } }