/* $Id: flyingitems.c,v 1.4 2004/04/03 14:48:43 stpohle Exp $ */

#include "bomberclone.h"
#include "flyingitems.h"
#include "player.h"

_flyingitem flitems [FLITEMS_MAXITEMS];
_flyingitem *flitems_first = NULL;



/* find first free entry */
_flyingitem *flitems_findfree () {
	int i;
	
	for (i = 0; i < FLITEMS_MAXITEMS; i++)
		if (flitems[i].type == FT_nothing) break;
	
	if (i < FLITEMS_MAXITEMS)
		return &flitems[i];
	else
		return NULL;
};


/* reset all items */
void flitems_reset () {
	int i;
	
	for (i = 0; i < FLITEMS_MAXITEMS; i++) {
		flitems[i].type = FT_nothing;
		flitems[i].next = NULL;
	}
	
	flitems_first = NULL;
};	



void flitems_loop () {
	_flyingitem *flitem = flitems_first;
	_flyingitem **old = &flitems_first;   // pointer of the preview next pointer
	
	for (; flitem != NULL; flitem = flitem->next) {
		/* restore the old position */
		stonelist_add (floorf (flitem->pos.x), floorf (flitem->pos.y));
		stonelist_add (floorf (flitem->pos.x), floorf (flitem->pos.y)+1);
		stonelist_add (floorf (flitem->pos.x)+1, floorf (flitem->pos.y));
		stonelist_add (floorf (flitem->pos.x)+1, floorf (flitem->pos.y)+1);
		
		flitem->step += (2*timediff);
		if (flitem->type == FT_nothing || flitem->step >= 1.0f) { 
			/* finished delete element and put it on the right place */
			if (map.field[(int)flitem->to.x][(int)flitem->to.y].type == FT_nothing)
				map.field[(int)flitem->to.x][(int)flitem->to.y].type = flitem->type;
			else
				map.field[(int)flitem->to.x][(int)flitem->to.y].special = flitem->type;
	
			stonelist_add ((int)flitem->to.x, (int)flitem->to.y);
			*old = flitem->next; /* set the preview next pointer to the next element */
			flitem->type = FT_nothing;
			flitem->next = NULL;
		}
		else { /* still moving draw item */
			flitem->pos.x = (1.0f - flitem->step) * (flitem->from.x - flitem->to.x) + flitem->to.x;
			flitem->pos.y = (1.0f - flitem->step) * (flitem->from.y - flitem->to.y) + flitem->to.y;
			flitems_draw (flitem);
			old = &flitem->next;
		}
	}
};


/* add this item into the drop list */
_flyingitem *flitems_additem (_pointf from, _point to, signed char type) {
	_flyingitem *flitem = flitems_findfree ();
	
	if (flitem == NULL || type == FT_nothing) {
		d_fatal ("flitems_additem: couldn't get any free flyitem \n");
		return NULL;
	}
	
	/* set the pointers */
	flitem->next = flitems_first;
	flitems_first = flitem;
	
	flitem->from = from;
	flitem->to.x = (float) to.x;
	flitem->to.y = (float) to.y;
	flitem->step = 0.0f;
	flitem->type = type;
	flitem->pos = from;
	
	return flitem;
};


/* give us a good position on the field */
_point flitems_randompos (int p_nr) {
	int radius = 2, try = 0, maxtry = 0, check;
	_point to = { -1, -1 };
	
	do {
		/* check that we won't end up in a infinite loop */
		try++;
		maxtry++;
		if (try > 10) {
			radius++;
			try = 0;
		}

		/* get a random position */		
		if (p_nr == -1) { 	/* get a position on the field */
			to.x = s_random (map.size.x -2) + 1;
			to.y = s_random (map.size.y -2) + 1;
		}
		else { 				/* get a good position for the 
							 * destination of the element */
			to.x = s_random (radius*2 + 1) - radius + (int) players[p_nr].pos.x;
			to.y = s_random (radius*2 + 1) - radius + (int) players[p_nr].pos.y;
		}
		
		/* check if the field is good */
		check = (to.x > 0 && to.y > 0 && to.x < map.size.x-1 && to.y < map.size.y-1 
				&& flitems_checkfreepos (to)
				&& (map.field[to.x][to.y].type == FT_nothing
					|| (map.field[to.x][to.y].type == FT_stone && map.field[to.x][to.y].special == FT_nothing))
				&& map.bfield[to.x][to.y] == 0);
	} while ( !check && maxtry < 200);

	if (!check) {
		to.x = -1;
		to.y = -1;
	}
	
	return to;
};

/* a player dropped these items */
void flitems_dropitems (int p_nr, _pointf from, int cnt_speed, int cnt_bombs, int cnt_range) {
	int i, lpos = 0;
	_point to;
	_flyingitem *fiptr[MAX_BOMBS+MAX_RANGE+50];
	
	
	
	for (i = 0; i < cnt_speed; i++) {
		to = flitems_randompos (p_nr);
		if (to.x != -1)
			fiptr[lpos++] = flitems_additem (from, to, FT_shoe);
		else
			d_printf ("flitems_dropitems: (FT_shoe) item could not been set\n");
	}
	
	for (i = 0; i < cnt_bombs; i++) {
		to = flitems_randompos (p_nr);
		if (to.x != -1)
			fiptr[lpos++] = flitems_additem (from, to, FT_bomb);
		else
			d_printf ("flitems_dropitems: (FT_bomb) item could not been set\n");
	}
	
	for (i = 0; i < cnt_range; i++) {
		to = flitems_randompos (p_nr);
		if (to.x != -1)
			fiptr[lpos++] = flitems_additem (from , to, FT_fire);
		else
			d_printf ("flitems_dropitems: (FT_fire) item could not been set\n");
	}
	
	fiptr[lpos] = NULL;
	
	if (GT_MP)
		net_game_send_dropitems (p_nr, fiptr, lpos);
};


void flitems_draw (_flyingitem *flitem) {	
	SDL_Rect src, dest;
	SDL_Surface *srci;
	

	if (flitem == NULL || (flitem->type != FT_shoe && flitem->type != FT_fire && flitem->type != FT_bomb))
		return;

    src.w = dest.w = gfx.block.x;
    src.h = dest.h = gfx.block.y;

	src.x = 0;
	src.y = 0;
	
	dest.x = gfx.offset.x + (gfx.block.x * flitem->pos.x);
	dest.y = gfx.offset.y + (gfx.block.y * flitem->pos.y);
	
	srci = gfx.field[flitem->type].image;
	gfx_blit (gfx.powerup[0].image, &src, gfx.screen, &dest, (((int)flitems->pos.y + 1.0)*256) + 255);
	gfx_blit (srci, &src, gfx.screen, &dest, (((int)flitems->pos.y + 1.0)*256) + 256);
};


/* check if not a flying item is going to this position */
int flitems_checkfreepos (_point to) {
	_flyingitem *item = flitems_first;
	
	while (item != NULL && ((int)item->to.x != to.x || (int)item->to.y != to.y))
		item = item->next;

	return (item == NULL);
};
