/* elephant.m,
 *
 * A very heavily armoured tank with a fixed turret.  Note that for
 * ElephantReverse, the gun is antiparallel to its angle.
 */

#include <math.h>
#include "common.h"
#include "map.h"
#include "debris/tank-debri.h"
#include "debris/tank-track.h"
#include "projectiles/plasma.h"
#include "seborrhea/seborrhea.h"
#include "units/all-units.h"
#include "units/elephant.h"


static SebFile *elephant_sebum;
static SebAnimation *move_anim, *fire_anim, *move_animr, *fire_animr;

/*------------------------------------------------------------*/

@interface ElephantTrack: TankTrack
@end

@interface ElephantTrackCCW: ElephantTrack
@end

/*------------------------------------------------------------*/

@implementation Elephant
+ (BOOL) loadPrerequisites { return LOAD_PROJECTILE_DATA_FOR(Plasma); }

+ (BOOL) loadData
{
    if (elephant_sebum)			/* Don't load twice. */
	return YES;

    elephant_sebum = [SebFile new];
    if (not [elephant_sebum loadSebumDirectory:"data/elephant"])
	return NO;

    move_anim  = (SebAnimation *)[elephant_sebum getSebumByName:"move-anim"];
    fire_anim  = (SebAnimation *)[elephant_sebum getSebumByName:"fire-anim"];
    move_animr = (SebAnimation *)[elephant_sebum getSebumByName:"move-animr"];
    fire_animr = (SebAnimation *)[elephant_sebum getSebumByName:"fire-animr"];
    return YES;
}

+ (void) shutdown
{
    FREE_SEBFILE(elephant_sebum);
    move_anim  = nil;
    fire_anim  = nil;
    move_animr = nil;
    fire_animr = nil;
}

- init
{
    [super init];

    health = 30;
    speed = 0.60;
    the_way = (SebSpline *)[elephant_sebum getSebumByName:"path"];
    activate_y = 0;

    animation.anim = move_anim;
    animation.tics = animation.delay = 7;

    sprite = [animation.anim getFrame:0];
    w = [sprite width];
    h = [sprite height];
    rotatable_unit = YES;

    gun = [[[[OffcentreWeapon new]
		setProjectile:[Plasma class]]
	       setShotDelay:55]
	      setXDisplacement:25 YDisplacement:0];

    flags |= FLAG_FIRING_ENABLED;
    chunk_colours = CHUNK_COFFEE;
    return self;
}

- free
{
    if (gun)
	gun = [gun free];
    return [super free];
}

- (void) die
{
    [super die];

    /* This is a big tank.  Spawn lots of debri. */
    spawn_debris([TankDebri class], x,    y-10, FLOOR_LAYER);
    spawn_debris([TankDebri class], x+10, y,    FLOOR_LAYER);
    spawn_debris([TankDebri class], x-10, y+10, FLOOR_LAYER);
}

- (void) move
{
    /* Spawn a track? */
    if (SQ(last_track_x - x) + SQ(last_track_y - y) >= SQ(11.0)) {
	BOOL cw = NO;

	if ((angle < 0  && not mirror_path) ||
	    (angle < M_PI_2 && mirror_path))
	    cw = YES;

	if (cw)
	    [spawn_debris([ElephantTrack class], x, y, FLOOR_LAYER) setAngle:angle];
	else
	    [spawn_debris([ElephantTrackCCW class], x, y, FLOOR_LAYER) setAngle:angle];

	last_track_x = x;
	last_track_y = y;
    }

    [super move];
}

- (void) fire
{
    if ([gun fireFromX:x Y:y angle:angle]) {
	animation.anim = fire_anim;
	animation.tics = animation.delay;
	animation.loop = NO;
	animation.frame = 0;
	sprite = [animation.anim getFrame:0];
    }
    else if (animation.anim == fire_anim && animation.tics == 0 &&
	     animation.frame == [animation.anim numFrames]-1) {
	animation.anim = move_anim;
	animation.tics = animation.delay;
	animation.loop = YES;
	animation.frame = 0;
	sprite = [animation.anim getFrame:0];
    }
}

- (id) setX:(double)x_ Y:(double)y_
{
    /* This is really just to look good in the map editor. */
    if (x_ < screen_w/2)
	angle = 0;
    else
	angle = M_PI;

    return [super setX:x_ Y:y_];
}
@end

/*------------------------------------------------------------*/

@implementation ElephantReverse
- init
{
    [super init];

    angle = M_PI_2;
    the_way = (SebSpline *)[elephant_sebum getSebumByName:"path2"];
    activate_y = -80;

    animation.anim = move_animr;
    sprite = [animation.anim getFrame:0];

    return self;
}

- (void) move
{
    if (the_way)
	[super move];
    else {
	animation.loop = NO;

	if (y > offsetY + screen_h + 50)
	    [self delete];
    }
}

- (void) fire
{
    if ([gun fireFromX:x Y:y angle:angle + M_PI]) {
	animation.anim = fire_animr;
	animation.tics = animation.delay;
	animation.loop = NO;
	animation.frame = 0;
	sprite = [animation.anim getFrame:0];
    }
    else if (the_way &&
	     animation.anim == fire_animr && animation.tics == 0 &&
	     animation.frame == [animation.anim numFrames]-1) {
	animation.anim = move_animr;
	animation.tics = animation.delay;
	animation.loop = YES;
	animation.frame = 0;
	sprite = [animation.anim getFrame:0];
    }
}

- (id) setX:(double)x_ Y:(double)y_
{
    /* This is really just to look good in the map editor. */
    [super setX:x_ Y:y_];
    angle = M_PI_2;
    return self;
}

	/* Data sharing tweaks. */
+ (BOOL) loadData { return LOAD_UNIT_DATA_FOR(Elephant, NO); }
+ (void) shutdown {}
@end

/*------------------------------------------------------------*/

@implementation ElephantTrack
- init
{
    [super init];

    /* This is a HEAVY tank.  Make near-permanant marks! */
    health = max_track_life = 500;
    sprite = [elephant_sebum getSebumByName:"tracks"];

    return self;
}
@end

@implementation ElephantTrackCCW
- init
{
    [super init];
    sprite = [elephant_sebum getSebumByName:"tracks2"];
    return self;
}
@end
