/* railgun.m,
 *
 * Railgun used by Miniboss0 (tank).  Near instantaneous.  You have 4
 * tics to dodge the shot after it shoots.  Good luck!
 */

#include <allegro.h>
#include <math.h>
#include "colour-conv.h"
#include "common.h"
#include "map.h"
#include "projectiles/railgun.h"
#include "seborrhea/container-animation.h"
#include "seborrhea/seborrhea-allegro.h" /* XXX */


static SebFile *railgun_sebum;
static SebAnimation *trail_anim;


static inline void swap(double *alpha, double *beta)
{
    double gamma = *alpha;
    *alpha = *beta, *beta = gamma;
}


@implementation Railgun
+ initialize { REGISTER_PROJECTILE(self); return self; }

+ (BOOL) loadData
{
    railgun_sebum = [SebFile new];
    if (not [railgun_sebum loadSebumDirectory:"data/proj-railgun"])
	return NO;

    trail_anim = (SebAnimation *)[railgun_sebum getSebumByName:"trail"];
    return YES;
}

+ (void) shutdown
{
    FREE_SEBFILE(railgun_sebum);
    trail_anim = nil;
}

- init
{
    [super init];
    health = 5;			/* 4 tics before actually zapping. */
    drawn = NO;

    return self; 
}

- (int) update
{
    if (health > 1) {
	health--;
	return THING_NORMAL;
    }
    if (health != 0 && not drawn)
	return THING_NORMAL;
    return THING_DEAD;
}

- (void) draw:(BITMAP *)dest
{
    (void)dest;

    /* Only draw once. */
    if (not drawn) {
	int i;
	double deltax, deltay, xx, yy;

	deltax = 15*cos(angle);
	deltay = 15*sin(angle);
	xx = x;
	yy = y;

	/* Spawn some railgun trails. */
	for (i = 0; i < 33; i++) {
	    RailgunTrail *t = [spawn_debris([RailgunTrail class], xx, yy, HIGH_LAYER)
					   setAngle:angle];
	    [t setYV:trail_velocity];

	    xx += deltax;
	    yy -= deltay;
	}

	drawn = YES;
    }
}

- (BOOL) collidesWith:(Thing<DetectsCollision> *)object
{
    double x2, y2, thetamin, thetamax;
    int w2, h2;

    /* A few tics delay before actually hurting the player. */
    if (health > 1)
	return NO;

    [object getX:&x2 Y:&y2 W:&w2 H:&h2];

    thetamin = atan2(y - y2, (x2 - w2/2 - 10) - x);
    thetamax = atan2(y - y2, (x2 + w2/2 + 10) - x);

    if (thetamin > thetamax)
	swap(&thetamin, &thetamax);

    return (angle >= thetamin && angle <= thetamax);
}

- (void) setRailgunTrailVelocity:(double)v_ { trail_velocity = v_; }
@end

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

@implementation RailgunTrail
- init
{
    [super init];

    speed = 0;
    frame = 1;
    sprite = [trail_anim getFrame:frame];

    return self;
}

- (int) update
{
    frame = [trail_anim nextFrame:frame];
    if (frame != 0)
	sprite = [trail_anim getFrame:frame];
    else 
	return THING_DEAD;

    return [super update];
}

- (void) draw:(BITMAP *)dest
{
    if (sprite)
	pivot_sprite(dest, [(SebImageAllegro *)sprite bitmap],
		     x-offsetX, y-offsetY, 7, 5, rad2fix(angle));
}

- (void) setYV:(double)v_ { yv = v_; recalculate_velocity = NO; }
@end
