void KoloryFlamer :: calculate () { // check if the weapons exist weapon1 = flamer1 && flamer1->exists(); weapon2 = flamer2 && flamer2->exists(); // update the flamer pointers if (!weapon1) flamer1 = 0; if (!weapon2) flamer2 = 0; flame_active = weapon1 | weapon2; Ship::calculate(); // regardless of whether the flames are activated or not: if ( this->fire_special ) { // DEFENSIVE MODE // double HalfTime = 1000.0 * 0.5; // 0.5 second to half the speed. // is nearly 1 slowdownfactor = exp(-frame_time*1E-3 / specialHalfTime); } else { slowdownfactor = 1.0; } int layers = bit(LAYER_SHIPS) + bit(LAYER_SHOTS) + bit(LAYER_SPECIAL) + bit(LAYER_CBODIES); double passiveRange = 1000.0;// outside this area, gravity doesn't do anything Query a; for (a.begin(this, layers, passiveRange); a.current; a.next()) { if (!a.current->isObject()) continue; SpaceObject *o = a.currento; if (!(o->isPlanet()) && o != ship ) { // the special introduces drag around the ship, depending on distance o->vel *= slowdownfactor; if ( o->isShot() ) { // shot/missiles/homing-missiles have a different existtime/physics Shot *s = ((Shot*)o); double timeleft = (s->range - s->d) / s->v; s->v *= slowdownfactor; // express in lifetime instead of range s->range = s->d + s->v * timeleft; } } } }
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; }