/* basic-tank.m,
 *
 * 'Basic-tank' features common tank things like turrets, firing, animations,
 * etc.  It is designed to be used as a base class.
 */

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


@implementation BasicTank
	/* Initialization. */
- init
{
    [super init];

    rotatable_unit = YES;

    /* Animations. */
    move_animation.frame = 0;
    move_animation.tics  = move_animation.delay = 0;
    move_animation.loop  = YES;

    flags |= FLAG_FIRING_ENABLED;
    return self;
}

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

- (void) die
{
    [super die];

    spawn_debris([TankDebri class], x, y, FLOOR_LAYER);

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

- (id) setAngle:(double)theta { turret_angle = theta; return [super setAngle:theta]; }

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

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

	/* Update. */
- (BOOL) readyToActivate
{
    if ([super readyToActivate]) {
	turret_angle = ANGLE_TO_CLOSEST_ALLY(x, y);
	return YES;
    }
    else
	return NO;
}

- (int) update
{
    if (not (game_flags & FLAG_PLAYERS_ALIVE)) {
	desired_turret_angle = angle;
	flags &=~FLAG_FIRING_ENABLED;
    }
    else if (!target || !(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_turret_angle = atan2(deltay, deltax);
    }

    /* Rotate turret. */
    limited_rotate(&turret_angle, desired_turret_angle, deg2rad(2.0));
    simplify_angle(&turret_angle);

    return [super update];
}

- (void) move
{
    if (travel_range <= 0)
        return;

    /* We want to update the animation in here so that not yet moving units
       will not animate. */  
    if (move_animation.anim &&
	animate(&move_animation))
	sprite = [move_animation.anim getFrame:move_animation.frame];
    travel_range -= speed;

    /* Spawn a track? */
    if (tracks &&
	SQ(last_track_x - x) + SQ(last_track_y - y) >= SQ(track_separation)) {
	last_track_x = x;
	last_track_y = y;

	[spawn_debris(tracks, x, y, FLOOR_LAYER) setAngle:angle];
    }

    return [super move];
}

- (void) fire
{
    if (not projectile || --fire_tics > 0)
        return;

    [spawn_projectile(projectile, x, y, NO) setAngle:turret_angle];
    fire_tics = shot_delay;
}

- (int) collisionLists { return COLLIDES_WITH_PROJECTILES_AND_NUKES; }

	/* Load/Save.  Format: travel_range;activate_y;x;y;a[;flags] */
- (void) importUnitProperties:(char *)str
{
    char str2[1024];
    double a;
    int b;

    sscanf(str, "%lf;%d;%s", &a, &b, str2);
    [super importUnitProperties:str2];
    travel_range = a;
    activate_y = b;
}

- (char *) exportUnitProperties:(char *)str
{
    char str2[1024] = "\0";

    [super exportUnitProperties:str2];
    snprintf(str, sizeof(str2), "%g;%d;%s", travel_range, activate_y, str2);
    return str;
}

	/* 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);
}

- (void) drawMapEditorExtras:(BITMAP *)dest
{
    [super drawMapEditorExtras:dest];
    draw_activation_line(dest, x, y, activate_y);
    draw_travel_range(dest, x, y, angle, travel_range);
}

	/* Protocol stuff. */
- derive_setActivationLine;
- derive_setTravelRange(travel_range);
@end
