/* This file restructured significantly by Rik */

#include "Popcorn:h.Popcorn"

static BOOL check_delete(struct game_object *, int, int);
static union object_flags check_flags(struct game_object *, int, int);
static void animate(struct game_object *);
static void make_coll_slabs(struct object_table *, struct game_object *);

void Popcorn_Process(struct object_table *table, BOOL plot, int moves) {
  register struct game_object *obj;
  int scan, x, y;
  union object_flags reason;

#ifdef MemCheck_MEMCHECK
  moves = 1;
#endif

  if (table->collisions != NULL) table->collisions->entries = 0;

  do {
    scan = 0;
    while (scan != table->max_objects) {
      obj = &(table->object[scan]);

      if (obj->object_id != 0) {
        /* changed by rik - no gravity if no velocity flag */
        if (obj->flags.bits.velocities) {
          if (obj->flags.bits.gravity) {
            obj->xv += table->grav_x;
            obj->yv += table->grav_y;
          }
          obj->x += obj->xv;
          obj->y += obj->yv;
        }
        obj->timer.value -= obj->timer.decrement;

        reason = check_flags(obj, plot, moves);

        if (obj->flags.bits.animate) animate(obj);

        if (obj->handler != NULL && reason.word != 0) /* call the handler */
          (obj->handler)((void*) obj, reason, NULL);
        /* calculate screen x and y positions - plot_offset added by Rik */
        if (obj->flags.bits.plot_offset) {
          x = (obj->x + plot_offset.x) >> 12;
          y = (obj->y + plot_offset.y) >> 12;
        } else {
          x = obj->x >> 12;
          y = obj->y >> 12;
        }
        if (obj->flags.bits.std_plot && plot && moves == 1) {
          if (obj->flags.bits.animate &&
          obj->plot_id.animation->frame[obj->frame].sprite_anchor != NULL) {
            Popcorn_PlotSprite(
              *obj->plot_id.animation->frame[obj->frame].sprite_anchor,
              x - (obj->plot_offset.x), y - (obj->plot_offset.y));
          } else if (obj->plot_id.sprite_anchor != NULL) {
            Popcorn_PlotSprite(*obj->plot_id.sprite_anchor,
              x - (obj->plot_offset.x), y - (obj->plot_offset.y));
          }
        }
        if (check_delete(obj, x, y)) Popcorn_DeleteObject(obj);

        if (obj->flags.bits.collide && table->collisions != NULL &&
            obj->object_id != 0 && moves == 1) make_coll_slabs(table, obj);
      }
      ++scan;
    }
  } while (--moves != 0);
}

/* This was changed by Rik to try and speed     */
/* things up a little. Did it work? Who nose?   */
static BOOL check_delete(struct game_object *obj, int x, int y) {
  if ((obj->flags.bits.kill_timer && obj->timer.value <= 0) ||
    (obj->flags.bits.kill_plotout && Popcorn_FastOutside(x, y, &plot_window)) ||
    (obj->flags.bits.kill_gameout && Popcorn_FastOutside(x, y, &game_window)) ||
    (obj->flags.bits.kill_userout && Popcorn_FastOutside(x, y, &user_window)))
    return TRUE;
  return FALSE;
}

static union object_flags check_flags(struct game_object *obj, int plot, int moves) {
  union object_flags reason;
  reason.word = 0;
  if (obj->flags.bits.attn_every)
    reason.bits.attn_every    = 1;
  if (obj->flags.bits.attn_plot && plot && moves == 1)
    reason.bits.attn_plot     = 1;
  if (obj->flags.bits.attn_timer && obj->timer.value <= 0)
    reason.bits.attn_timer    = 1;
  if (obj->flags.bits.attn_plotout && Popcorn_Outside(obj, &plot_window))
    reason.bits.attn_plotout  = 1;
  if (obj->flags.bits.attn_gameout && Popcorn_Outside(obj, &game_window))
    reason.bits.attn_gameout  = 1;
  if (obj->flags.bits.attn_userout && Popcorn_Outside(obj, &user_window))
    reason.bits.attn_userout  = 1;
  return reason;
}

static void animate(struct game_object *obj) {
  if (obj->flags.bits.yoyo) {
    if (obj->flags.bits.yoyo_dec) {
      if (--obj->frame == -1) {
        ++obj->frame;
        obj->flags.bits.yoyo_dec = FALSE;
      }
    } else {
      if (++obj->frame == obj->plot_id.animation->frames) {
        --obj->frame;
        obj->flags.bits.yoyo_dec = TRUE;
      }
    }
  } else {
    if (++obj->frame == obj->plot_id.animation->frames)
      obj->frame = 0;
  }
  obj->size.x = obj->plot_id.animation->frame[obj->frame].size_x;
  obj->size.y = obj->plot_id.animation->frame[obj->frame].size_y;
  obj->plot_offset.x=obj->plot_id.animation->frame[obj->frame].centre_x;
  obj->plot_offset.y=obj->plot_id.animation->frame[obj->frame].centre_y;
}

static void make_coll_slabs(struct object_table *table, struct game_object *obj) {
  table->collisions->collision[table->collisions->entries].x0
   = (obj->x>>12) - obj->plot_offset.x;
  table->collisions->collision[table->collisions->entries].y0
   = (obj->y>>12) - obj->plot_offset.y;
  table->collisions->collision[table->collisions->entries].x1
   = table->collisions->collision[table->collisions->entries].x0
    + obj->size.x;
  table->collisions->collision[table->collisions->entries].y1
   = table->collisions->collision[table->collisions->entries].y0
    + obj->size.y;
  table->collisions->collision[table->collisions->entries].back_ptr
   = obj;
  ++table->collisions->entries;
}
