/* basic-turret.m,
 *
 * A turret that aims at the closest player.
 */

#include <allegro.h>
#include <math.h>
#include "common.h"
#include "debri.h"
#include "map.h"
#include "projectile.h"
#include "rotate.h"
#include "seborrhea/seborrhea.h"
#include "unit-seeking.h"
#include "units/basic-turret.h"


@implementation BasicTurret
	/* Initialization. */
- init
{
    [super init];
    flags |= FLAG_FIRING_ENABLED;
    return self;
}

- free
{
    if ([turret conformsTo:@protocol(UniqueSebum)])
	turret = [turret free];
    if (gun)
	gun = [gun free];
    return [super free];
}

- (void) die
{
    [super die];

    if (base_debri) {
	spawn_debris(base_debri, x, y, LOW_LAYER);
	base_debri = nil;
    }

    if ((debri_amount >= 2) &&
	turret_debri && rnd(0,4) == 0) {
	[spawn_debris(turret_debri, x, y, MEDIUM_LAYER) setAngle:angle];
	turret_debri = nil;
    }
}

	/* Drawing */
- (void) draw:(BITMAP *)dest
{
    if (sprite)
	[super draw:dest];
    if (turret)
	[self drawTurret:dest];
}

- (void) drawTurret:(BITMAP *)dest
{
    [turret drawTo:dest X:x-offsetX Y:y-offsetY Angle:angle];
}

	/* Update. */
- (BOOL) readyToActivate
{
    BOOL ret = [super readyToActivate];

    if (ret)
	angle = ANGLE_TO_CLOSEST_ALLY(x, y);

    return ret;
}

- (int) update
{
    if (not (game_flags & FLAG_PLAYERS_ALIVE)) {
	flags &=~FLAG_FIRING_ENABLED;
	desired_angle = deg2rad(-90.0);
    }
    else if (not target || not (unit_exists(target, ALLY_LIST)))
	target = find_closest_unit(x, y, ALLY_LIST);
    else {
	double x_, y_, deltax, deltay;

	/* Relocate the target and rotate towards it. */
	[target getX:&x_ Y:&y_];
	deltax = x_-x;
	deltay = y-y_+25;	 /* Aim higher to compensate for scrolling. */
	desired_angle = atan2(deltay, deltax);
    }

    /* Rotate turret. */
    limited_rotate(&angle, desired_angle, deg2rad(2.0));
    simplify_angle(&angle);

    return [super update];
}

- (void) fire
{
    if (gun)
	[gun fireFromX:x Y:y angle:angle];
    else
	flags &=~FLAG_FIRING_ENABLED;
}

- (int) collisionLists { return COLLIDES_WITH_PROJECTILES_AND_NUKES; }

	/* For use in map editor only! */
- (void) drawTo:(BITMAP *)dest at:(int)x_ :(int)y_
{
    BITMAP *tmp = create_bitmap([sprite width], [sprite height]);

    [sprite drawTo:tmp X:0 Y:0 W:tmp->w H:tmp->h];

    if (turret)
	[turret drawTo:tmp X:tmp->w/2 Y:tmp->h/2 Angle:0];

    stretch_sprite(dest, tmp, x_, y_, 64, 64);
    destroy_bitmap(tmp);
}
@end
