
#include "includes.h"

////////////////////////////////////////////////////////////////////////////////

OBJECT * create_object()
{
	OBJECT * o = (OBJECT *)malloc(sizeof(OBJECT));	
	
	if (o)
	{
		memset(o, 0, sizeof(OBJECT));
	}
	
	o->alive=true;
	o->w=16;
	o->h=16;
	
	return o;
}

////////////////////////////////////////////////////////////////////////////////

void destroy_object(OBJECT * o)
{
	if (o)
	{
		if (o->free_bmp)
		{
			if (o->bmp)
			{
				destroy_bitmap(o->bmp);
			}
			
			if (o->mask)
			{
				destroy_pmask(o->mask);
			}
		}
		free(o);
	}
}

////////////////////////////////////////////////////////////////////////////////

int new_object()
{
	int c=-1;
	for (int i=0; i<100; i++)
	{
		if (obj[i]==NULL)
		{
			c=i;
			i=100;
		}
		else
		if (!obj[i]->alive)
		{
			destroy_object(obj[i]);
			obj[i]=NULL;
			c=i;
			i=100;
		}
	}
	
	if (c>=0)
	{
		obj[c]=create_object();
	}
	return(c);
}

////////////////////////////////////////////////////////////////////////////////

void create_staircase(int id, int x, int y, int lvl, int dir)
{
	int i=new_object();
	if (i==-1){return;}
	
	if (dir==A_UP)
	{
		obj[i]->type=3; //Up Stair Case
		sprintf(obj[i]->text, "Go Up to Level %d?", lvl);
		obj[i]->bmp=tiles[26];
	}
	else
	{
		obj[i]->type=2; //Down Stair Case
		sprintf(obj[i]->text, "Go Down to Level %d?", lvl);
		obj[i]->bmp=tiles[25];
	}
	
	if (lvl==0)
	{
		sprintf(obj[i]->text, "Go Up To Town?");
			
	}
	
	obj[i]->id=id;
	obj[i]->x=x;
	obj[i]->y=y;
	obj[i]->free_bmp=false;
	obj[i]->state[0]=180; //3 seconds...
	obj[i]->state[1]=lvl;
	
	obj[i]->passable=true;
	obj[i]->mask = create_allegro_pmask(obj[i]->bmp);
	obj[i]->w=16;
	obj[i]->h=16;
	
	return;	
}

////////////////////////////////////////////////////////////////////////////////

void create_house(int id, int x, int y, char * text)
{
	int i=new_object();
	if (i==-1){return;}
	
	obj[i]->type=1; //House
	obj[i]->id=id;
	obj[i]->x=x;
	obj[i]->y=y;
	sprintf(obj[i]->text, "%s", text);
	
	obj[i]->bmp=create_bitmap(32,32);
	if (obj[i]->bmp==NULL)
	{
		destroy_object(obj[i]);
		obj[i]=NULL;
		return;
	}
	obj[i]->free_bmp=true;
	
	if (tiles[5]) { blit(tiles[5], obj[i]->bmp, 0, 0, 0, 0, 16, 16); }
	if (tiles[6]) { blit(tiles[6], obj[i]->bmp, 0, 0, 16, 0, 16, 16); }
	if (tiles[15]) { blit(tiles[15], obj[i]->bmp, 0, 0, 0, 16, 16, 16); }
	if (tiles[16]) { blit(tiles[16], obj[i]->bmp, 0, 0, 16, 16, 16, 16); }
	obj[i]->passable=false;
	obj[i]->mask = create_box_pmask(obj[i]->bmp);
	obj[i]->w=32;
	obj[i]->h=32;
	
	return;
}

////////////////////////////////////////////////////////////////////////////////

void create_chain(int x, int y, int length, int speed, int delay)
{
	for (int j=1; j<length; j++)
	{
		int i=new_object();
		if (i>=0)
		{
			obj[i]->type=4; //chain
			obj[i]->x=x-(j*16);
			obj[i]->y=y;
			obj[i]->state[1]=speed;
			obj[i]->state[2]=x+8;
			obj[i]->state[3]=y+8;
			obj[i]->state[4]=192;
			obj[i]->state[5]=j*16;
			obj[i]->state[7]=delay;
			obj[i]->state[8]=41+(rand()%3);
			
			obj[i]->bmp=tiles[obj[i]->state[8]]; //53];
			obj[i]->mask = create_box_pmask(obj[i]->bmp);
			obj[i]->passable=true;
			obj[i]->free_bmp=false;
			obj[i]->alive=true;
			obj[i]->rotates=true;
		}
	}
}

////////////////////////////////////////////////////////////////////////////////

void draw_object(int cx, int cy, OBJECT * o)
{
	if (!o){return;}
	if (!o->alive){return;}
	
	if (!o->rotates)
	{
		draw_sprite(apage, o->bmp, o->x-cx, o->y-cy);
	}
	else
	{
		o->dir &= 255;
		rotate_sprite(apage, o->bmp, o->x-cx, o->y-cy, itofix(o->dir));	
	}
}

////////////////////////////////////////////////////////////////////////////////

void do_objects()
{
	int max=0;
	for (int i=0; i<100; i++)
	{
		if (obj[i])
		{
			if (obj[i]->alive)
			{
				max=i;
				
				//reset collisions
				for (int k=0; k<101; k++)
				{
					obj[i]->collision[k]=false;
				}
				obj[i]->colls=false;
					
				//set collisions
				if (obj[i]->passable)
					{
						for (int j=0; j<100; j++)
						{
							if (npc[j])
							{
								if (npc[j]->alive)
								{
									if (actor_object_collision(npc[j], obj[i]))
									{
										obj[i]->collision[j]=true;
										obj[i]->colls=true;	
									}
								}
							}
						}
					
						if (actor_object_collision(player, obj[i]))
						{obj[i]->collision[100]=true; obj[i]->colls=true;}
				}
				else
				{
						int wox, woy;
						wox=obj[i]->x;
						woy=obj[i]->y;
						
						for (int j=0; j<100; j++)
						{
							if (npc[j])
							{
								if (npc[j]->alive)
								{
									for (int ox=-1; ox<2; ox++)
									{
										for (int oy=-1; oy<2; oy++)
										{
											obj[i]->x=wox+ox;
											obj[i]->y=woy+oy;
										
											if (actor_object_collision(npc[j], obj[i]))
											{
												obj[i]->collision[j]=true;
												obj[i]->colls=true;
											}
										}
									}
								}
							}
						}
					
						for (int ox=-1; ox<2; ox++)
						{
							for (int oy=-1; oy<2; oy++)
							{
								obj[i]->x=wox+ox;
								obj[i]->y=woy+oy;
								if (actor_object_collision(player, obj[i]))
								{obj[i]->collision[100]=true; obj[i]->colls=true; ox=2; oy=2;}
							}
						}
						
						obj[i]->x=wox;
						obj[i]->y=woy;
				}
			}
			else
			{
				destroy_object(obj[i]);
				obj[i]=NULL;
			}
		}
	}
	
	for (int i=0; i<=max; i++)
	{
		if (obj[i])
		{
			if (obj[i]->alive)
			{
				object_logic(obj[i]);
			}
		}
	}
}

////////////////////////////////////////////////////////////////////////////////

void object_logic(OBJECT * o)
{
	//putpixel(o->bmp, rand() % o->bmp->w, rand() % o->bmp->h, rand()% 15);
	
	////////////////////////////////////////////////////////////////////////////
	if (o->type==1)	//House
	{
		if (o->colls)
		{
			if (o->collision[100])
			{
				if (player->y>o->y+16)
				{
					
					if (((player->x+8)>=(o->x)) && ((player->x+8)<(o->x+o->w)))
					{
						if (player->dir==A_UP)
						{	
							current_menu=create_menu(20, o->text, -1, -1, 200, 100);
							current_menu->state[0]=true;
							current_menu->state[1]=A_DN;
							
							sprintf(current_menu->text[0]," REST ");
							sprintf(current_menu->text[1]," SAVE ");
							sprintf(current_menu->text[2]," SAVE AND EXIT ");
							current_menu->text[3][0]=0;
							
							
							display_menu=true;
							while (control(BTN_ANY));
							tmcLogic=0;
						}	
					}
				}
			}
		}	
	}
	////////////////////////////////////////////////////////////////////////////
	else if (o->type==2 || o->type==3) //Stairway (up || down)
	{
		if (o->state[0]>0){o->state[0]--;}
		if (o->colls)
		{
			if (o->collision[100])
			{	
				if ((o->state[0]<1))
				{
					current_menu=create_menu(2, o->text, -1, -1, 200, 50);
					sprintf(current_menu->text[0], " NO ");
					sprintf(current_menu->text[1], " YES ");
					current_menu->state[1]=o->state[1];
					display_menu=true;
					o->state[0]=180;  //3 seconds
				
					while (control(BTN_ANY));
					tmcLogic=0;
				}
			}
		}
	}
	////////////////////////////////////////////////////////////////////////////
	else if (o->type==4) //chain
	{
			//obj[i]->state[1]=speed;
			//obj[i]->state[2]=x+8;
			//obj[i]->state[3]=y+8;
			//obj[i]->state[4]=192;
			//obj[i]->state[5]=length;
			
			//o->bmp=tiles[41+(rand()%3)];
			o->dir = rand() % 256;
			
			o->state[6]++;
			if (o->state[6]>=o->state[7])
			{
				o->state[8]++;
				int b=o->state[8];
				if (b==44){b=42;}
				if (b==45)
				{b=o->state[8]=41;}
				o->bmp=tiles[b];
				
				o->state[6]=0;
				o->state[4] += o->state[1];
				o->state[4] &= 255;
				
				o->x=(int)(((double)o->state[2])+(X_LOOK[o->state[4]]*(double)o->state[5]));
				o->y=(int)(((double)o->state[3])+(Y_LOOK[o->state[4]]*(double)o->state[5]));
				o->x-=8;
				o->y-=8;
			}
			
			if (o->colls)
			{
				if (o->collision[100])
				{
					if (plr_blinky<1)
					{
						hurt_actor(player, player->x-o->x, player->y-o->y);
						player->hp-=(7*dungeon_level);
					}
				}
			}
	}
	////////////////////////////////////////////////////////////////////////////
	else if (o->type==10) // Spinning Projectiles / Projectiles
	{
		//o->state[1]=speed
		//o->state[2]=dir;
		//o->state[3]=distance in pixels
		//o->state[4]=owner's team (to prevent friendly fire)
		//o->state[5]=rotation speed
		//o->state[6]=damage
		
		if (o->colls)
		{
			for (int i=0; i<100; i++)
			{
				if (o->collision[i])
				{
					if (npc[i])
					{
						if ((npc[i]->alive) && (npc[i]->team!=o->state[4]))	
						{
							npc[i]->hp-=o->state[6];
							o->alive=false;
							hurt_actor(npc[i], (npc[i]->x+8)-(o->x+8), (npc[i]->y+8)-(o->y+8));
						}
					}
				}
			}
			
			if (o->collision[100])
			{
				if (player->team !=	o->state[4])
				{
					if (plr_blinky<1)
					{
						player->hp-=o->state[6];
						o->alive=false;
					
						hurt_actor(player, (player->x+8)-(o->x+8), (player->y+8)-(o->y+8));
						
						plr_blinky=120;
					}
				}
			}
		}
		
		o->x+=dir_x[o->state[2]]*o->state[1];
		o->y+=dir_y[o->state[2]]*o->state[1];
		o->state[3]-=o->state[1];
		
		if (o->state[3]<1)
		{
			o->alive=false;	
		}
		
		o->dir+=o->state[5];
		
		if (object_collision_with_wall(o))
		{
			o->alive=false;
		}
		
		if (!o->alive)
		{
			explode(o->x, o->y, 2, 16, o->state[10], o->state[11], o->state[12], o->state[13]);
		}
	}
	////////////////////////////////////////////////////////////////////////////
}

////////////////////////////////////////////////////////////////////////////////

OBJECT * copy_obj(OBJECT * o)
{
	if (!o){return(NULL);}
	if (!o->alive){return(NULL);}
	
	OBJECT * o2=create_object();	
	if (o2)
	{
		memcpy(o2, o, sizeof(OBJECT));
		o2->bmp=NULL;
		o2->mask=NULL;
		
		if (o->free_bmp)
		{
			if (o->bmp)
			{
				o2->bmp=create_bitmap(o->bmp->w, o->bmp->h);
				if (o2->bmp)
				{
					blit(o->bmp, o2->bmp, 0, 0, 0, 0, o->bmp->w, o->bmp->h);
				}
			}
		}
		else
		{
			o2->bmp=o->bmp;	
		}
				
		if (o->mask)
		{
			o2->mask=create_box_pmask(o->bmp);
		}
		
	}
	return(o2);
}

////////////////////////////////////////////////////////////////////////////////

void shoot_bone(int team, int x, int y, int dir)	//dir = shoot directon
{
	int i=new_object();
	if (i>=0)
	{
		obj[i]->type=10;  //projectile
		
		obj[i]->x=x-8;
		obj[i]->y=y-8;	
		obj[i]->free_bmp=false;
		obj[i]->bmp=tiles[73];
		obj[i]->mask=NULL;
		obj[i]->passable=true;
		obj[i]->rotates=true;
		
		obj[i]->state[1]=2;						//throw speed
		obj[i]->state[2]=dir;
		obj[i]->state[3]=80; 					//distance in pixels
		obj[i]->state[4]=team;					//to prevent friendly fire
		obj[i]->state[5]=4;						//rotation speed
		obj[i]->state[6]=5*(dungeon_level);		//damage
		
		obj[i]->state[10]=WHITE;				//colors
		obj[i]->state[11]=GRAY;
		obj[i]->state[12]=WHITE;
		obj[i]->state[13]=GRAY;
	}
}

////////////////////////////////////////////////////////////////////////////////

void shoot_boomberang(int team, int x, int y, int dir)	//dir = shoot directon
{
	int i=new_object();
	if (i>=0)
	{
		obj[i]->type=10;  //projectile
		
		obj[i]->x=x-8;
		obj[i]->y=y-8;	
		obj[i]->free_bmp=false;
		obj[i]->bmp=tiles[63];
		obj[i]->mask=NULL;
		obj[i]->passable=true;
		obj[i]->rotates=true;
		
		obj[i]->state[1]=2;						//throw speed
		obj[i]->state[2]=dir;
		obj[i]->state[3]=80; 					//distance in pixels
		obj[i]->state[4]=team;					//to prevent friendly fire
		obj[i]->state[5]=8;						//rotation speed
		obj[i]->state[6]=5*(dungeon_level);		//damage
		
		obj[i]->state[10]=4;					//colors
		obj[i]->state[11]=14;
		obj[i]->state[12]=4;
		obj[i]->state[13]=14;
		
	}
}

////////////////////////////////////////////////////////////////////////////////

void shoot_sword(int team, int x, int y, int dir)
{
	int i=new_object();
	if (i>=0)
	{
		obj[i]->type=10;  //projectile
		
		obj[i]->x=x-8;
		obj[i]->y=y-8;
		obj[i]->free_bmp=false;
		obj[i]->bmp=tiles[44];
		obj[i]->mask=NULL;
		obj[i]->passable=true;
		obj[i]->rotates=true;

		if (dir==A_UP){obj[i]->dir=0;}
		else if (dir==A_RT){obj[i]->dir=63;}
		else if (dir==A_DN){obj[i]->dir=127;}
		else if (dir==A_LF){obj[i]->dir=191;}
		
		obj[i]->state[1]=2;			//throw speed
		obj[i]->state[2]=dir;
		obj[i]->state[3]=160; 		//distance in pixels
		obj[i]->state[4]=team; 		//to prevent friendly fire
		obj[i]->state[5]=0;			//rotation speed

		obj[i]->state[6]=8+(8*plr_LEVEL);
									//damage
		
		obj[i]->state[10]=WHITE;				//colors
		obj[i]->state[11]=GRAY;
		obj[i]->state[12]=WHITE;
		obj[i]->state[13]=GRAY;
		
	}
}

////////////////////////////////////////////////////////////////////////////////
