#include "dark.hpp"
void Plr_dark::update_shoot(float dt) {
  update_main_shoot(dt);
  update_side_shoot(dt);
  update_back_shoot(dt);
} // shoot
void Plr_dark::update_side_shoot(float dt) {
  using namespace a83;
  constexpr auto lo_en_mul = 1.0f / 5.0f; // замедление при нехватке энергии
  info_cast(info);
  // выстрелы по сторонам
  if (Game::input.test(KEY_SHOOT_SIDE) and shoot_side_cldwn()) {
    shoot_side_cldwn.reset_all();
    plr_jolt += 1.1f;
  // огонь выстрела:
    cauto len = (a83::frand_fast() * 7.0f) + 3.0f;
    Vec pos_(len + 3.5f, len - 5.5f);
    if (left_side)
      pos_.x = -pos_.x;
    pos_ = pos_.get_rotate_deg(phys.pos, 90.0f - phys.deg);
    cauto deg_ = phys.deg + (left_side ? 135.0f : 45.0f) - 90.f;
    if (auto p = add_prt(PRT_SHOOT_1); p) {
      p->phys = Phys(pos_, deg_, 0.01f);
      p->phys.add_vec(phys);
      p->phys.set_deg2(deg_);
      p->phys.rst = 0.001f;
      p->frame_timer = TFC(2.5f);
      p->flags |= EF_LRU;
      p->light = Light(0.4f, TFC(6), (sfrand_fast() * 20.0f) + 22.0f);
    }
  // быстрая тяжёлая пуля:
    if (auto p = add_blt(BLT_FAST_HEAVY); p) {
      p->phys = Phys(pos_, deg_, 0, 3600.0f);
      p->phys.add_vec(phys);
      p->phys.set_deg2(deg_);
      p->flags |= EF_R_FRAME_ANY | EF_DMG_ENEMY | EF_DMG_BULLET
        | EF_IGNORE_MASTER | EF_NO_SCATTER;
      p->flags &= ~EF_DMG_PLAYER;
      p->master = this;
      p->expl = expl_bank::player_side;
      p->pf0 = &Enity::kill_by_collide;
    }
    left_side = !left_side; // меняем сторону выстрела
    en.sub(info->side_cost);
  } // shoot side
  shoot_side_cldwn.update(en.val >= info->side_cost ? dt : dt * lo_en_mul);
} // update_side_shoot
void Plr_dark::update_back_shoot(float dt) {
  using namespace a83;
  constexpr auto lo_en_mul = 1.0f / 4.0f; // замедление при нехватке энергии
  info_cast(info);
  // медленные взрывные пули (ELIPS)
  if (Game::input.test(KEY_SHOOT_BACK) and shoot_back_cldwn()) {
    shoot_back_cldwn.reset_all();
    Vec v_pos[2] = {Vec(15.f, 14.5f), Vec(-15.f, 14.5f)};
    v_pos[0] = v_pos[0].get_rotate_deg({}, 90.0f - phys.deg);
    v_pos[1] = v_pos[1].get_rotate_deg({}, 90.0f - phys.deg);
    constexpr float v_deg[2] = {315.0f, 225.0f};
    const float v_deg_smoke[2] = { // для частиц выстрела
      phys.deg + 135.0f - 90.f,
      phys.deg + 45.0f - 90.f};
    FOR (i, 2) {
      if (auto p = add_blt(BLT_ELIPS); p) {
        p->phys = Phys(v_pos[i], v_deg[i] + (phys.deg - 90.0f),
          0.5f, 300.0f);
        p->phys.add_vec(phys);
        p->frame_timer = TFC(2);
        p->flags |= EF_R_DEG | EF_DMG_ENEMY | EF_DMG_BULLET | EF_IGNORE_MASTER;
        p->flags &= ~EF_DMG_PLAYER;
        p->master = this;
        p->expl = expl_bank::sphere;
        p->pf0 = &Enity::kill_by_timer;
        p->data0.f0 = 5; // смерть через 5 сек
        p->light = Light(1.f, 0, 17.5f, LF_RAND | LF_INFINITY);
      }
      // дым от выстрела
      if (auto p = add_prt(PRT_SMOKE_2); p) {
        p->phys = phys;
        p->phys.pos = v_pos[i];
        p->phys.set_deg2(v_deg_smoke[i]);
        p->phys.rst = 0.01f;
        p->frame_timer = 0.05f;
      }
    } // if KEY_SHOOT_BACK && shoot_back_cldwn
    en.sub(info->back_cost);
  } // if shoot back
  shoot_back_cldwn.update(en.val >= info->back_cost ? dt : dt * lo_en_mul);
} // update_back_shoot
void Plr_dark::update_main_shoot(float dt) {
  using namespace a83;
  info_cast(info);
  constexpr auto lo_en_mul = 1.0f / 5.0f; // замедление при нехватке энергии
  if (Game::input.test(KEY_SHOOT)) {
    if (check_ext())
      make_main_shoot_ext();
    if (shoot_cldwn()) { // быстрые пули
      shoot_cldwn.reset_all();
      if (Game::input.test(KEY_FOCUS))
        make_main_shoot(7.f, sfrand() * 1.5f);
      else
        make_main_shoot(7.f, sfrand() * 10.f);
      en.sub(info->main_cost);
    }
  }
  shoot_cldwn.update(en.val >= info->main_cost ? dt : dt * lo_en_mul);
} // update_main_shoot
void Plr_dark::make_main_shoot(float dist, float deg_add) {
  using namespace a83;
  Phys phys_shoot;
  phys_shoot.set_deg(phys.deg + deg_add);
  phys_shoot.set_pos(phys.pos + phys_shoot.dir * dist);
  phys_shoot.set_spd(2500.f + frand() * 2500.0f);
  if (auto p = add_blt(BLT_SPIKE_OUT); p) {
    p->phys = phys_shoot;
    p->phys.add_vec(phys);
    p->phys.deg = phys_shoot.deg;
    p->flags |= EF_IGNORE_SELF_ID | EF_DMG_ENEMY | EF_DMG_BULLET
      | EF_IGNORE_MASTER | EF_R_FRAME_ANY | EF_NO_SCATTER;
    p->flags &= ~EF_DMG_PLAYER;
    p->master = this;
    p->expl = expl_bank::spike_expl_plr;
    p->pf0 = &Enity::kill_by_collide;
    p->light = Light(1, 0, 17, LF_RSIZE | LF_STAR | LF_INFINITY | LF_RAND);
  }
  // частицы от выстрела
  if (auto p = add_prt(
    (irand_fast() & 1)
    ? PRT_MICRO_EXPL
    : PRT_BULLET_CRUSH
  ); p) {
    p->phys = Phys(phys_shoot.pos, rand_deg(), 0.5f, frand_fast() * 200.0f);
    p->phys.add_vec(phys);
    p->flags |= EF_R_DEG | EF_LRU;
    p->frame_timer = TFC(2.5f);
    p->haze = Haze(TFC(2.5f), 1, 1, 12, 16);
  }
} // make_main_shoot
void Plr_dark::make_main_shoot_ext() {
  info_cast(info);
  const float ext_val = en.val - info->en_ext;
  const float ext_max = en.size - info->en_ext;
  cauto power = ext_val / ext_max;
// рассыпные выстрелы
  const uint blt_count = 55 * power;
  // TODO добавь в пули передачу функции-спавнера дамажащих частиц
  if (Game::input.test(KEY_FOCUS)) {
    FOR (i, blt_count)
      make_main_shoot(8.f + a83::frand() * 8.f, a83::sfrand() * 10.0f);
  } else {
    FOR (i, blt_count)
      make_main_shoot(8.f + a83::frand() * 8.f, a83::sfrand() * 50.0f);
  }
  plr_jolt += 23.0f * power;
  en.sub(ext_val + 1.0f);
} // make_main_shoot_ext