void EarthlingCruiserMk3::calculate() { STACKTRACE; Ship::calculate(); double track_angle = 0; double track_min = PI2; double d_a; SpaceObject *tgt = 0; //!!! pos += unit_vector(angle) * 28; int i; for (i=0; i < targets->N; i++) { tgt = targets->item[i]; if ((tgt != this) && (!tgt->sameShip(this)) && (!tgt->sameTeam(this)) && (!tgt->isInvisible()) && (distance(tgt) <= 1.2*(weaponRange + abs(vel)*game->shot_relativity))) { d_a = trajectory_angle(tgt); double s = unit_vector(d_a + PI/2).dot(tgt->get_vel() - vel * game->shot_relativity) / weaponVelocity; if (fabs(s) > 0.99) track_angle = 0; else { s = atan(s/sqrt(1-s*s)); s = normalize(s + d_a - angle - turn_step, PI2); if (s > PI) s -= PI2; if (fabs(s) <= weaponTrackingAngle) { d_a = s - launch_angle; if (tgt == target) { track_angle = s; break; } if (fabs(d_a) < track_min) { track_angle = s; track_min = fabs(d_a); } } } } } //!!! pos -= unit_vector(angle) * 28; d_a = track_angle - launch_angle; double ta = weaponTrackingRate * frame_time; if (fabs(d_a) < ta) ta = fabs(d_a); if (d_a > 0) launch_angle += ta; else launch_angle -= ta; }
void AutoGun::calculate() { STACKTRACE; BigShipPartDevice::calculate(); if (!(ownerpart && !ownerpart->isdisabled())) return; // find the closest target Query a; SpaceObject *oclosest; double R; oclosest = 0; R = 1E99; double da_track; da_track = -a_track; // forces to go back into default position for (a.begin(this, OBJECT_LAYERS, 0.75*shotrange); a.current != 0; a.next()) { SpaceObject *o; o = a.currento; if (!o->isObject()) continue; if (o->sameShip(this) || o->sameTeam(this)) continue; if (o->isPlanet()) continue; if (o->isInvisible()) continue; double L = 0; L = distance(o); if (!oclosest || L < R) { // this is a possible candidate but, is it also within the view angle ? double a, b, da; a = trajectory_angle(o); // check relative to the gun's neutral position b = ownerpart->get_angle() + a_center; da = a - b; while (da < -PI) da += PI2; while (da > PI) da -= PI2; if (da > -a_view && da < a_view) { // okay! it's close, within dist-range, and it's within angle-range oclosest = o; R = L; // required movement is relative to the gun's current position // note that at this moment, you cannot use the value of "angle" // which is overridden by the call to AyronShipPart::calculate; so, // use "b" instead. b += a_track; da_track = a - b; while (da_track < -PI) da_track += PI2; while (da_track > PI) da_track -= PI2; } } } // track the target (or go back to neutral position) // max tracking speed per second (0.1 circles / second). // this tracking angle is relative to the neutral angle of the gun. double da; da = 100 * PI2 * frame_time * 1E-3; if (da_track > da) da_track = da; if (da_track < -da) da_track = -da; a_track += da_track; if (a_track < -a_view) a_track = -a_view; if (a_track > a_view) a_track = a_view; // absolute angle of the gun angle = ownerpart->get_angle() + a_center + a_track; sprite_index = get_index(angle); // fire the weapon ? if (oclosest && ownerpart->ship && ownerpart->ship->batt > shotdrain && !shotbusy) { Shot *s; s = new Shot(this, Vector2(0,0), angle, shotvel, shotdamage, shotrange, shotarmour, this, sprshot, 0); s->set_depth(DEPTH_SHIPS + 0.1); game->add( s ); shotbusy = shotperiod; ownerpart->ship->handle_fuel_sap(this, shotdrain); } if (shotbusy > 0) shotbusy -= frame_time * 1E-3; else shotbusy = 0; }