/*   Copyright 2005,2006 Paweł Niegowski
*
*    This file is part of Fenrir.
*
*    Fenrir is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    Fenrir is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with Fenrir; if not, write to the Free Software
*    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "monster.h"
#include "particle.h"
#include "player.h"
#include "palette.h"
#include "damage.h"
#include "network.h"
#include "map.h"
#include "combat.h"
#include <math.h>
#define MAX_COLORS 8
#define MONSTER_SPEED 1.3;

#define STUNLOCK_MOD 15

DATAFILE *particlemon = 0;

int color_table[MAX_COLORS] = { 80, 88, 93, 170, 175, 108, 64, 176 };

ParticleMonster::ParticleMonster(int _x, int _y, int _color)
: color(_color)
{
 targetable = true;
 if(color > MAX_COLORS) color = 0;
 fx = net_x = x = _x; fy = net_y = y = _y;
 direction = DIR_DOWN;
 ps = new ParticleSystem(200,color_table[color],6,2);
 ps->x = x;
 ps->y = y;
 ps->set_box_emitter(8,-1,16,16, -0.2,-0.1,0.4,-0.5, 500, 10,40);
 speed = MONSTER_SPEED;
 h = 0.0;
 h_step = rand()%100 * 0.001 + 0.05;
}


void ParticleMonster::think()
{
 _turn_to_target(player);
 if(dead && kill_counter == -1)
 {
  if(objects[obj_num] == this) objects[obj_num] = 0;
  ps->kill_counter = kill_counter = KILL_DELAY;
  ParticleSystem *ps2 = new ParticleSystem(400,color_table[color],6,2);
  ps2->x = x; ps2->y = y;
  ps2->set_box_emitter(4,-5,24,24,-0.5,-1.0,1.0,-4.0, 500, 20, 120);
  ps2->animators.push_back(new RemoveAnimator(10));
  fx = net_x = x; fy = net_y = y;
 }
 if(kill_counter > 0) { kill_counter--; targetable = false; return; }
 if(!kill_counter) { remove = true; return; }
 if(stunlock)
 {
  stunlock--;
  if(kill_counter == -1)
  {
   fx += (net_x-fx)/STUNLOCK_MOD;
   fy += (net_y-fy)/STUNLOCK_MOD;
  }
 } else if(kill_counter == -1)
 {
  if(net_x - x > speed) { fx += speed; direction = DIR_RIGHT; } else
  if(x - net_x > speed) { fx -= speed; direction = DIR_LEFT; } else
   fx = net_x;
  if(net_y - y > speed) { fy += speed; direction = DIR_DOWN; } else
  if(y - net_y > speed) { fy -= speed; direction = DIR_UP; } else
   fy = net_y;
 }
 ps->x = x = (int)fx; ps->y = sort_y = y = (int)fy;
 h += h_step;
}

void ParticleMonster::draw_upper()
{
 if(kill_counter > -1) return;
 if(direction == DIR_DOWN)
  draw_sprite(buf,(BITMAP*)particlemon[color*2].dat,x-cam_x,y-cam_y-8 + (int)(5*sin(h)));/* else*/
 if(direction == DIR_LEFT)
  draw_sprite_h_flip(buf,(BITMAP*)particlemon[color*2+1].dat,x-cam_x,y-cam_y-8 + (int)(5*sin(h)));
 if(direction == DIR_RIGHT)
  draw_sprite(buf,(BITMAP*)particlemon[color*2+1].dat,x-cam_x,y-cam_y-8 +  (int)(5*sin(h)));
}

void ParticleMonster::attack(int target, Packet *attack_data)
{
 _attack(target,attack_data);

 _turn_to_target(objects[target]);
}

void ParticleMonster::combat_hit(int target, Packet *attack_data, int num)
{
 unsigned char *data = attack_data->data+3;
 int hit_y = 1;
 if( ((data[3]>>2)&3) == 1 ) hit_y = 10; else
 if( ((data[3]>>2)&3) == 3 ) hit_y = -10;
 ParticleSystem *p = new ParticleSystem(200,color_table[color],6,2);
 p->x = objects[target]->x;
 p->y = objects[target]->y + hit_y;
 p->set_box_emitter(8,-1,16,16, -0.2,-0.1,0.4,-0.5, 500, 10,40);
 p->lifetime = 3;
 p->show_delay = num * 10;
 //connected
 if(data[1] & (1<<num))
 {
  p = new ParticleSystem(300,color_table[color],10);
  p->x = objects[target]->x+8;
  p->y = objects[target]->y + hit_y;
  p->lifetime = 5;
  p->show_delay = num*10;
  p->set_point_emitter(0, 0, 2.0, -1.0, -4.0, -4.0, 100, 10, 40);
 }
}

void ParticleMonster::get_dmg(unsigned int dmg, int delay, float _vx, float _vy)
{
 Damage *d = new Damage(dmg,140,x+8,y,_vx,_vy);
 d->show_delay = delay;
 d->animators.push_back(new AttachAnimator(this, true));
}


void ParticleMonster::_turn_to_target(Object *o)
{
 int difx, dify;
 difx = x - o->x;
 dify = y - o->y;
 if(ABS(difx) > ABS(dify))
  if(difx > 0)
   direction = DIR_LEFT;
  else
   direction = DIR_RIGHT;
 else
  if(dify > 0)
   direction = DIR_UP;
  else
   direction = DIR_DOWN;

}

void monster_init()
{
 particlemon = load_datafile("gfx/sprites/particlemon.dat");
 if(!particlemon) allegro_message("ERROR: gfx/sprites/particlemon.dat not found.\n");
}

void monster_cleanup()
{
 unload_datafile(particlemon);
}
