void TeronBuilder::calculate_fire_weapon() { STACKTRACE; if ( fire_weapon && !fire_special && (thrust || turn_left || turn_right) ) { if ( weapon_recharge > 0 ) return; if ( thrust ) { if ( select_all ) { select_all = false; current_drone = NULL; message.out( "All drones deselected" ); } else { select_all = true; message.out( "All drones selected" ); } } else if ( turn_right ) { select_all = false; TeronDrone* first_drone = NULL; TeronDrone* next_drone = NULL; Query q; for( q.begin( this, bit(LAYER_SHIPS), selectRange ); q.currento; q.next() ) { if ( !next_drone && sameShip( q.currento ) && q.currento->get_sprite() == data->TERON_DRONE_SPRITE ) { next_drone = (TeronDrone*)q.currento; if ( !first_drone ) first_drone = (TeronDrone*)q.currento; } if ( q.currento == current_drone ) { next_drone = NULL; } } q.end(); if ( next_drone ) current_drone = next_drone; else current_drone = first_drone; message.out( "Next drone selected" ); } else if ( turn_left ) { select_all = false; TeronDrone* prev_drone = NULL; Query q; for( q.begin( this, bit(LAYER_SHIPS), selectRange ); q.currento; q.next() ) { if ( q.currento == current_drone ) { if ( prev_drone ) break; } if ( sameShip( q.currento ) && q.currento->get_sprite() == data->TERON_DRONE_SPRITE ) { prev_drone = (TeronDrone*)q.currento; } } q.end(); current_drone = prev_drone; message.out( "Prev drone selected" ); } weapon_recharge += weapon_rate; play_sound2(data->sampleWeapon[weapon_sample]); } }
void TauMCTorpedo::animateExplosion() { STACKTRACE; if (exploded) return; exploded = true; if (old_range < blast_range) { Query q; double r, d; for (q.begin(this, OBJECT_LAYERS, blast_range); q.currento; q.next()) { if (!q.current->isObject()) continue; r = distance(q.currento) / blast_range; if (r > 1) r = 1; d = blast_damage * (1 - r*r); //r = sqrt(r); //dam = (int)ceil(d * (1-r)); //ddam = (int)ceil(d * r); //q.currento->handle_damage(this, dam, ddam); q.currento->handle_damage(this, d, 0); } explosionSprite = data->spriteWeaponExplosion; damage_factor = blast_damage; explosionFrameCount = 10; explosionFrameSize = 50; } HomingMissile::animateExplosion(); }
int EarthlingCruiserMk3::activate_special() { STACKTRACE; bool fire = false;; SpaceObject *o; double rng = 1e40; SpaceObject *tgt = NULL; //!!! pos -= unit_vector(angle) * 6; Query q; for (q.begin(this, bit(LAYER_SHIPS) + bit(LAYER_SHOTS) + bit(LAYER_SPECIAL) + bit(LAYER_CBODIES), specialRange); q.current; q.next()) { o = q.currento; if (!o->isInvisible() && !o->sameTeam(this) && (o->collide_flag_anyone&bit(LAYER_LINES)) && (distance(o) < rng)) { tgt = o; rng = distance(o); } } q.end(); //!!! pos += unit_vector(angle) * 6; if (tgt) { game->add(new EarthlingCruiserMk3Beam(this, Vector2(0,-6), specialRange, specialDamage, specialDamageShots, specialFrames, tgt)); play_sound(data->sampleSpecial[0]); fire = true; } return(fire); }
int EarthlingCruiser2::activate_special() { STACKTRACE; int fire = FALSE; SpaceObject *o; Query q; for (q.begin(this, bit(LAYER_SHIPS) + bit(LAYER_SHOTS) + bit(LAYER_SPECIAL) + bit(LAYER_CBODIES), specialRange); q.current; q.next()) { o = q.currento; if (!o->isInvisible() && !o->sameTeam(this) && (o->collide_flag_anyone&bit(LAYER_LINES))) { SpaceLocation *l = new PointLaser(this, pallete_color[specialColor], 1, specialFrames, this, o, Vector2(0.0,0.0)); add(l); if (l->exists()) { fire = TRUE; l->set_depth(LAYER_EXPLOSIONS); } } } q.end(); if (fire) sound.play((SAMPLE *)(melee[MELEE_BOOM + 0].dat)); return(fire); }
void GobPlanet::calculate () { STACKTRACE; SpaceObject::calculate(); SpaceObject *o; Query a; a.begin(this, OBJECT_LAYERS, gravity_range); for (;a.currento;a.next()) { o = a.currento; if (o->mass > 0) { bool roswell = false; for (int i = 0; i < gobgame->gobplayers; i++) { if (o->ship == gobgame->gobplayer[i]->ship && gobgame->gobplayer[i]->upgrade_list[UpgradeIndex::roswelldevice]->num) roswell = true; } if (roswell) continue; double r = distance(o); if (r < gravity_mindist) r = gravity_mindist; double sr = 1; //gravity_power rounded up here if (gravity_power < 0) { r /= 40 * 5; for (int i = 0; i < -gravity_power; i += 1) sr *= r; o->accelerate(this, trajectory_angle(o) + PI, frame_time * gravity_force / sr, MAX_SPEED); } else { r = 1 - r/gravity_range; for (int i = 0; i < gravity_power; i += 1) sr *= r; o->accelerate(this, trajectory_angle(o) + PI, frame_time * gravity_force * sr, MAX_SPEED); } } } }
void TeronDrone::collect_resources() { STACKTRACE; if ( !ship ) { assist_building(); if ( target ) return; } SpaceObject* ast = NULL; double d = TERON_DRONE_SIGHT_RANGE; Query q; for( q.begin( this, bit(LAYER_CBODIES), TERON_DRONE_SIGHT_RANGE ); q.currento; q.next() ) { if ( q.currento->isAsteroid() ) { double i = distance( q.currento ); if ( i < d ) { ast = q.currento; d = i; } } } q.end(); if ( ast ) { control->target = ast; target = ast; if ( goal != collect ) roger(); goal = collect; if ( docked ) leave_dock(); } }
void DaktaklakpakMine::calculate() { AnimatedShot::calculate(); if (!mineactive) { mineArming -= frame_time; if (mineArming <= 0) { mineactive = TRUE; v = 0; vel = 0; } } else { SpaceObject *o, *t = NULL; double oldrange = 999999; Query a; for (a.begin(this, bit(LAYER_SHIPS),(missileRange *.9)); a.current; a.next()) { o = a.currento; if (!o->sameTeam(this) && (distance(o) < oldrange) && !(o->isAsteroid() || o->isPlanet())) { t = o; oldrange = distance(o); } } if (t) { add(new Missile(this,0,(trajectory_angle(t)), missileVelocity,missileDamage,missileRange,missileArmour, this,data->spriteExtra)); play_sound2(data->sampleExtra[0]); destroy(); } } }
int VelronCruiser::fire_def_shot(double lowAngle, double highAngle, double defaultAngle) { STACKTRACE; SpaceObject *o; double distance2, bestDistance2 = 99999999; double angleShift, relativeAngle; double firingAngle = defaultAngle; angleShift = ((double)(random()%2001-1000)/1000.0) * specialLaunchAngleDeflectionRange; Query a; for (a.begin(this, OBJECT_LAYERS, specialRange); a.current; a.next()) { o = a.currento; if ( (!o->isInvisible()) && !o->sameTeam(this) && (o->collide_flag_anyone & bit(LAYER_SHOTS))) { distance2 = distance(o); relativeAngle = get_aim(o, lowAngle, highAngle); if ((distance2 < bestDistance2) && (relativeAngle > -1000)) { bestDistance2 = distance2; firingAngle = relativeAngle; } } } add(new VelronCrDefShot(this, 0.0, 0.0, normalize(angle + firingAngle + angleShift, PI2), specialVelocity, specialDamage, specialRange, specialArmour, data->spriteSpecial, specialRelativity)); return(TRUE); }
void TauMCMissile::calculate() { STACKTRACE; Missile::calculate(); if (state == 0) return; if (target) if ((!target->exists()) || (fabs(get_aim(target)) > track_angle)) target = NULL; if (!target) { Query q; double a_a, a0 = -1e20; for (q.begin(this, OBJECT_LAYERS, range - d); q.currento; q.next()) { if (!q.current->isObject()) continue; if ( (!q.currento->sameTeam(this)) && (q.currento->collide_flag_anyone&bit(layer)) && !q.currento->isPlanet() ) { a_a = fabs(get_aim(q.currento)); if (a_a < 0) continue; if (a_a < track_angle) { a_a = (track_angle - a_a) * ((range - d) - distance(q.currento)) * (1 + (q.currento->isShip()?w_ship:0) + (q.currento->isShot()?w_shot:0) ); if (a_a > a0) { target = q.currento; a0 = a_a; } } } } } if (target && !target->isInvisible()) { double d_a = get_aim(target); double ta = turn_rate * frame_time; if (fabs(d_a) < ta) ta = fabs(d_a); if (d_a > 0) turn_step += ta; else turn_step -= ta; while(fabs(turn_step) > 5.625/2) { if (turn_step < 0.0) { angle -= 5.625; turn_step += 5.625; } else if (turn_step > 0.0) { angle += 5.625; turn_step -= 5.625; } } angle = normalize(angle, 360); } // ? // sprite_index = (int)(angle / 5.625) + 16; // sprite_index &= 63; sprite_index = get_index(angle); //vx = v * cos(angle * ANGLE_RATIO); //vy = v * sin(angle * ANGLE_RATIO); vel = v * unit_vector(angle); }
void EarthlingCruiserMk3Beam::calculate() { STACKTRACE; if (!(lpos && lpos->exists())) { lpos = 0; state = 0; } if ((frame < frame_count) && (lpos && lpos->exists())) { pos = lpos->normal_pos() + rotate(rel_pos, lpos->get_angle() - PI/2); vel = lpos->get_vel(); SpaceLine::calculate(); frame += frame_time; } else state = 0; if ((!target) && (switch_counter <= 0)) { SpaceObject *o; double rng = 1e40; SpaceObject *tgt = NULL; Query a; for (a.begin(this, bit(LAYER_SHIPS) + bit(LAYER_SHOTS) + bit(LAYER_SPECIAL) + bit(LAYER_CBODIES), base_length); a.current; a.next()) { o = a.currento; if (!o->isInvisible() && !o->sameTeam(this) && (o->collide_flag_anyone&bit(LAYER_LINES)) && (distance(o) < rng)) { tgt = o; rng = distance(o); } } if (tgt) { target = tgt; // switch_counter = 55; got_spark = false; } } if (target && (distance(target) <= base_length)) { length = base_length; if (target->exists() && canCollide(target) && target->canCollide(this)) { angle = trajectory_angle(target); } if (!target->exists()) target = NULL; } else { target = NULL; if (switch_counter <= 0) // die(); length = 0; else switch_counter -= frame_time; } color = tw_makecol(100+tw_random()%105,100+tw_random()%105,255); }
void GobDefender::calculate() { STACKTRACE; SpaceObject::calculate(); if (!ship) { die(); return; } if (!(random(3))) { if (next_shoot_time < gobgame->game_time) { SpaceObject *target = NULL; Query q; if (advanced) q.begin(this, OBJECT_LAYERS, 330 ); else q.begin(this, OBJECT_LAYERS &~ bit(LAYER_SHIPS), 290 ); while (q.currento && !target) { if (!q.currento->sameTeam(ship) && (q.currento->get_team() != gobgame->station_team) && !q.currento->isPlanet()) { SpaceLine *l = new PointLaser ( this, palette_color[7], 2 + advanced, 40, this, q.currento ); add(l); if (l->exists()) target = q.currento; } q.next(); } q.end(); if (target) { if (advanced) next_shoot_time = gobgame->game_time + 360; else next_shoot_time = gobgame->game_time + 560; } } } double a = base_phase + (gobgame->game_time % 120000) * ( PI2 / 1000.0) / 6; angle = normalize(a,PI2); pos = normalize(ship->normal_pos() + 270 * unit_vector ( angle )); return; }
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 RainbowRift::calculate() { STACKTRACE; while (game->game_time > next_time) { next_time += 25; squiggle(); } if (spawn_counter > 0) { spawn_counter -= frame_time; return; } while (game->game_time > next_time2) { STACKTRACE; next_time2 += random() % 3000; Query q; for (q.begin(this, bit(LAYER_SHIPS), 48); q.current; q.next()) { GobPlayer *p = gobgame->get_player(q.currento); if (!p) continue; if (q.currento == p->ship) { STACKTRACE; int i = 0; gobgame->pause(); i = p->control->choose_ship(game->window, "You found the Rainbow Rift!\n(select your current ship type to hunt for resources instead of a new ship)", reference_fleet); game->log_int(p->channel, i); if (i == -1) i = random(reference_fleet->getSize()); if (reference_fleet->getShipType(i) == p->ship->type) { times_found += 1; p->starbucks += random((times_found+2) * 9); p->buckazoids += random((times_found+2) * 6); pos = random(map_size); //game->add(new RainbowRift()); } else { p->starbucks += random() % (1+p->value_starbucks); p->buckazoids += random() % (1+p->value_buckazoids); p->new_ship(reference_fleet->getShipType(i)); pos = random(map_size); gobgame->station[0]->station_screen(p); } gobgame->unpause(); game->redraw(); spawn_counter = random(90000 + times_found * 15000); } } Planet *planet = nearest_planet(); while (planet && distance(planet) < planet->gravity_range) { pos = random(map_size); planet = nearest_planet(); } } return; }
void JurgathaPortal::calculate() { STACKTRACE; Animation::calculate(); Query a; for (a.begin(this, bit(LAYER_SHIPS) + bit(LAYER_SHOTS) + bit(LAYER_SPECIAL), sprite->width()/2); a.current; a.next()) { if (!a.currento->sameTeam(this) && !(a.currento->isAsteroid() || a.currento->isPlanet() ) ) { //a.currento->directDamage++; a.currento->handle_damage(this, 0, 1); } } }
void SpaceStation::calculate() { STACKTRACE; //Healing beam code Query a; SpaceObject *o; for (a.begin(this, bit(LAYER_SHIPS), 200.); a.current; a.next()) { o = a.currento; if (!o->isInvisible()) { game->add(new PointLaser(this, 0x0000ffff, -1, 10, this, o, Vector2(0.0, 10.0))); } } }
void BoggCenturion::calculate() { STACKTRACE; Ship::calculate(); if ((fire_weapon) && !( (batt < weapon_drain) || slowing_down) ) { if (startup_time > 0) gun_speed += frame_time / (double)startup_time; else gun_speed = 1.0; } else { slowing_down = true; gun_full_speed = false; delay_count = 0; if (slowdown_time > 0) gun_speed -= frame_time / (double)slowdown_time; else gun_speed = 0; } if (gun_speed >= 1.0) { gun_full_speed = true; gun_speed = 1.0; if (delay_count < startup_delay) delay_count += frame_time; } else if ((gun_speed <= 0) && (slowing_down)) { gun_speed = 0; slowing_down = false; } gun_position += frame_time*gun_speed/weapon_rate; while (gun_position >= 1) gun_position -= 1; old_gun_phase = gun_phase; gun_phase = (int)floor(gun_position * 8); flame_count -= frame_time; Query q; links_num = 0; BoggCenturion* bro; for (q.begin(this, bit(LAYER_SHIPS), share_range); q.currento; q.next()) if (q.currento->getID() == BOGEI_CENTURION_ID) { bro = (BoggCenturion*)q.currento; if (bro->exists()) links_num += 1; if (links_num == 2) break; } }
int BoggCenturion::handle_damage(SpaceLocation *source, double normal, double direct) //void BoggCenturion::handle_damage(SpaceLocation *source) { STACKTRACE; if (source == this) { return Ship::handle_damage(source, normal, direct); } double tot = normal + direct; Query q; int ln = 0; BoggCenturion* bro; for (q.begin(this, bit(LAYER_SHIPS), share_range); q.currento; q.next()) if (q.currento->getID() == BOGEI_CENTURION_ID) { bro = (BoggCenturion*)q.currento; if (bro->exists()) { ln += 1; link[ln] = bro; } if (links_num == max_links) break; } if (ln) { double d = tot; if (ln < 2) d *= 0.75; else d *= 0.5; tot = (int)floor(d); d -= tot; residual_damage += d; int dx = (int)floor(residual_damage); tot += dx; residual_damage -= dx; } Ship::handle_damage(source, tot); return 0; }
Error Context::beginQuery(GLenum target, GLuint query) { Query *queryObject = getQuery(query, true, target); ASSERT(queryObject); // begin query Error error = queryObject->begin(); if (error.isError()) { return error; } // set query as active for specified target only if begin succeeded mState.setActiveQuery(target, queryObject); return Error(GL_NO_ERROR); }
void TeronDrone::assist_building() { STACKTRACE; Query q; for( q.begin( this, bit(LAYER_SPECIAL), TERON_DRONE_SIGHT_RANGE ); q.currento; q.next() ) { if ( sameShip( q.currento )) { TeronBuildPlatform* platform = ((TeronBuildPlatform*)q.currento); control->target = platform; target = platform; goal = build; if ( docked ) leave_dock(); roger(); break; } } q.end(); }
void TeronBuilder::animate( Frame* space ) { STACKTRACE; Ship::animate( space ); if ( select_all ) { Query q; for( q.begin( this, bit(LAYER_SHIPS), selectRange ); q.currento; q.next() ) { if ( sameShip( q.currento ) && q.currento->get_sprite() == data->TERON_DRONE_SPRITE ) { data->TERON_SELECTION_SPRITE->animate( q.currento->normal_pos(), selection_sprite_index, space ); } } q.end(); }else if ( current_drone ) data->TERON_SELECTION_SPRITE->animate( current_drone->normal_pos(), selection_sprite_index, space ); }
int VirtaoLimb::activate_special() { STACKTRACE; int fire = FALSE; Query q; for (q.begin(this, ALL_LAYERS, specialRange);q.current;q.next()) { if (q.current->canCollide(this)) { double a = trajectory_angle(q.current); q.current->translate(specialPower * unit_vector(a)); fire = TRUE; } } q.end(); if (fire) play_sound((SAMPLE *)(melee[MELEE_BOOM + 0].dat)); return(fire); }
void ChmmrZapSat::calculate() { STACKTRACE; SpaceObject::calculate(); if (!(ship && ship->exists())) { ship = 0; state = 0; return; } // x = ship->normal_x() + (cos(angle) * 100.0); // y = ship->normal_y() + (sin(angle) * 100.0); pos = ship->normal_pos() + unit_vector(angle) * 100.0; double da = 0.002; angle += da * frame_time; // vx = (ship->normal_x() + (cos(angle) * 100.0) - x) / frame_time; // vy = (ship->normal_y() + (sin(angle) * 100.0) - y) / frame_time; vel = (ship->normal_pos() + unit_vector(angle) * 100.0 - pos) / frame_time; if (angle >= PI2) angle -= PI2; sprite_index = get_index(angle); if (lRecharge > 0) { lRecharge -= frame_time; return; } Query q; for (q.begin(this, OBJECT_LAYERS &~ bit(LAYER_CBODIES), lRange); q.currento; q.next()) { if (!q.currento->isInvisible() && !q.currento->sameTeam(this) && (q.currento->collide_flag_anyone&bit(LAYER_LINES))) { add(new PointLaser(this, pallete_color[lColor], 1, lFrames, this, q.currento, Vector2(0.0, 0.0) )); sound.play((SAMPLE *)(melee[MELEE_BOOM + 0].dat)); lRecharge += lRechargeRate; break; } } return; }
void AktunComSat::calculate() { STACKTRACE; if (!(ship && ship->exists())) { state = 0; return; } SpaceObject::calculate(); sprite_index++; if (sprite_index == 40) sprite_index = 0; if (lRecharge > 0) { lRecharge -= frame_time; return; } vel *= 1 - .0005 * frame_time; if (magnitude_sqr(vel) < 0.05 * 0.05) { vel = 0; } Query q; for (q.begin(this, OBJECT_LAYERS &~ bit(LAYER_CBODIES), lRange); q.currento; q.next()) { if (!q.currento->isInvisible() && !q.currento->sameTeam(this)) { SpaceLocation *l; l = new PointLaser(this, tw_get_palete_color(lColor), 1, lFrames, this, q.currento, 0); game->add(l); if (l->exists()) { sound.play(ship->data->sampleExtra[0]); lRecharge += lRechargeRate; break; } else l->state = 0; } } return; }
NaroolPoison::NaroolPoison(NaroolGas *gas, int nduration, float poison, Ship *nship, SpaceSprite *osprite) : SpaceObject (gas, nship->normal_pos(), 0.0, osprite), oship(nship), poison(poison), duration(nduration) { STACKTRACE; target = oship; id |= NAROOL_POISON_ID; layer = LAYER_HOTSPOTS; start = TRUE; collide_flag_anyone = 0; Query q; for (q.begin(oship, bit(LAYER_HOTSPOTS), 10); q.current; q.next()) { if ((q.current->getID() == getID()) && (((NaroolPoison*)q.current)->oship == oship)) { ((NaroolPoison*)q.current)->duration = duration; state = 0; } } q.end(); }
void Sun::calculate() { STACKTRACE; SpaceObject::calculate(); SpaceObject *o; Query a; a.begin(this, OBJECT_LAYERS, gravity_range); for (;a.currento;a.next()) { o = a.currento; if (o->mass > 0) { double r = distance(o); if (r < gravity_mindist) r = gravity_mindist; double sr = 1; //gravity_power truncated here if (gravity_power > 0) { r /= 40 * 4; for (int i = 0; i < gravity_power; i += 1) sr *= r; o->accelerate(this, trajectory_angle(o) + PI, frame_time * gravity_force / sr, MAX_SPEED); } else { r = 1 - r/gravity_range; for (int i = 0; i < -gravity_power; i += 1) sr *= r; o->accelerate(this, trajectory_angle(o) + PI, frame_time * gravity_force * sr, MAX_SPEED); } } } /*for (;a.currento;a.next()) { o = a.currento; if (o->mass > 0) { double r = distance(o); if (r < gravity_mindist) r = gravity_mindist; r = 1 - r / gravity_range; o->accelerate(this, trajectory_angle(o) + PI, frame_time * gravity_force * r / 40000., GLOBAL_MAXSPEED); } }*/ // return; }
void TeronBuilder::calculate() { STACKTRACE; if ( selection_sprite_step < 0 ) { selection_sprite_step += TERON_SELECTION_ANIM_RATE; selection_sprite_index++; if ( selection_sprite_index == data->TERON_SELECTION_SPRITE->frames() ) selection_sprite_index = 0; }else selection_sprite_step -= frame_time; if ( collecting ) { if ( !collecting->exists() ) { //fuel_sap -= asteroid_value; //handle_damage( this ); handle_fuel_sap(this, -asteroid_value); } collecting = NULL; } else { if ( collect_step <= 0 && collectRange ) { Query q; for( q.begin( this, bit(LAYER_CBODIES), collectRange ); q.currento; q.next() ) { if ( q.currento->isAsteroid() ) { collecting = q.currento; game->add( new Laser( this, trajectory_angle( collecting ), pallete_color[TERON_COLLECT_BEAM_COLOR], distance( collecting ), TERON_COLLECT_BEAM_DAMAGE, time_ratio, this, 0, false )); collect_step = TERON_BUILDER_COLLECT_RATE; break; } } q.end(); } else { collect_step -= frame_time; } } if ( !(current_drone && current_drone->exists()) ) current_drone = NULL; Ship::calculate(); }
int TeronBuilder::activate_special() { STACKTRACE; if ( current_option == option_build_drone ) { if ( batt < drone_cost ) { special_low = true; return false; } else batt -= drone_cost; TeronDrone* drone = new TeronDrone( this, //x+100*cos(angle*ANGLE_RATIO), y+100*sin(angle*ANGLE_RATIO), pos + 100 * unit_vector(angle), angle, data->TERON_DRONE_SPRITE ); TeronBuildPlatform* platform = drone->get_build_platform(); game->add( platform ); #ifdef TERON_SHIPS_TARGETABLE target->add( platform ); #endif } else if ( current_option == option_build_turret ) { if ( batt < turret_cost ) { special_low = true; return false; }else batt -= turret_cost; TeronTurret* turret = new TeronTurret( this, //x+100*cos(angle*ANGLE_RATIO), y+100*sin(angle*ANGLE_RATIO), pos + 100 * unit_vector(angle), angle, data->TERON_TURRET_SPRITE ); TeronBuildPlatform* platform = turret->get_build_platform(); game->add( platform ); #ifdef TERON_SHIPS_TARGETABLE target->add( platform ); #endif } else if ( current_option == option_build_fighter ) { if ( batt < fighter_cost ) { special_low = true; return false; }else batt -= fighter_cost; TeronFighter* fighter = new TeronFighter( this, //x+100*cos(angle*ANGLE_RATIO), y+100*sin(angle*ANGLE_RATIO), pos + 100 * unit_vector(angle), angle, data->TERON_FIGHTER_SPRITE ); TeronBuildPlatform* platform = fighter->get_build_platform(); game->add( platform ); #ifdef TERON_SHIPS_TARGETABLE target->add( platform ); #endif } else if ( !select_all && current_option == option_order_assist_building ) { if ( current_drone ) current_drone->assist_building(); } else if ( !select_all && current_option == option_order_collect_resources ) { if ( current_drone ) current_drone->collect_resources(); } else if ( !select_all && current_option == option_order_return_to_dock ) { if ( current_drone ) current_drone->return_to_dock(); } else { Query q; for( q.begin( this, bit(LAYER_SHIPS), selectRange ); q.currento; q.next() ) { if ( sameShip( q.currento ) && q.currento->get_sprite() == data->TERON_DRONE_SPRITE ) { if ( current_option == option_order_assist_building ) { ((TeronDrone*)q.currento)->assist_building(); } else if ( current_option == option_order_collect_resources ) { ((TeronDrone*)q.currento)->collect_resources(); } else if ( current_option == option_order_return_to_dock ) { ((TeronDrone*)q.currento)->return_to_dock(); } } } q.end(); } return true; }
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; }