//!@file реализации дымовых эмитеров и доп функций
#include "smoke.hpp"
#include "game/game-const.hpp"
template <class enity_t>
bool Smoke<enity_t>::operator () (Phys cur_phys) {
  if ( !data.pf)
    return false;
  //! применить offset
  cur_phys.pos += offset.get_rotate_deg({}, 90.f - cur_phys.deg);
  // создать частицу, если её нет
  if ( !p_enity or p_enity->is_dead()) {
    if (p_enity = data.pf(cur_phys); p_enity)
      return true;
    return false;
  }
  /* если объект прошёл дальше, чем data.step,
  то на пройденом пути ставятся частицы */
  bool ret = false;
  auto len = distance(p_enity->phys.pos, cur_phys.pos);
  while (len > data.step) {
    len -= data.step;
    auto phys = cur_phys;
    phys.pos -= phys.dir * len;
    if (p_enity = data.pf(cur_phys); p_enity)
      ret = true;
  }
  return ret;
} // operator()
namespace smoke_bank {
  //! дым с нулевой скоростью
  template<index_t id, int delay, uint flags = 0,
  BM blend_mode = BM::blink, int incs = 0>
  Enity* make_smoke(CN(Phys) cur_phys) {
    if (auto p = add_prt(id); p) {
      p->phys = Phys(cur_phys.pos, cur_phys.deg, 1.1f, 0);
      p->frame_timer = TFC(delay);
      p->flags |= flags;
      p->blend_mode = blend_mode;
      if (incs)
        p->frame_skip(a83::irand() % incs);
      return p;
    }
    return nullptr;
  }
  #define MAKE(FNAME, FUNC) Enity* FNAME(CN(Phys) cur_phys) { return FUNC(cur_phys); }
  MAKE(make_small,     (make_smoke<PRT_SMOKE_3, 2, EF_LRU, BM::blink, 3>))
  MAKE(make_small2,    (make_smoke<PRT_SMOKE_3, 12, EF_LRU, BM::blink, 3>))
  MAKE(make_big,       (make_smoke<PRT_SMOKE_1, 7, EF_R_DEG, BM::past, 3>))
  MAKE(make_big2,      (make_smoke<PRT_SMOKE_1, 7, EF_LRU | EF_R_DEG, BM::past, 3>))
  MAKE(make_big_plr,   (make_smoke<PRT_SMOKE_1, 7, EF_R_DEG, BM::blink, 3>))
  MAKE(make_airbomber, (make_smoke<PRT_SMOKE_1, 8, EF_R_DEG, BM::blink, 3>))
  MAKE(make_flame,     (make_smoke<PRT_MINI_EXPL, 4, EF_LRU | EF_R_DEG, BM::past, 9>))
  #undef MAKE
} // smoke_bank