/* laser.m,
 *
 * Lasers penetrate through an enemy if it has the strength, killing
 * as many units in its path as possible.  An ally projectile.
 */

#include <math.h>
#include "common.h"
#include "debris/line-spark.h"
#include "debris/spark.h"
#include "projectiles/laser.h"
#include "seborrhea/seborrhea.h"
#include "sound.h"
#include "unit.h"


#define LEVEL0_DAMAGE	9
#define LEVEL1_DAMAGE	6	/* Note that 2 are fired. */
#define LEVEL2_DAMAGE	15


static Sebum<SebSample> *fire_sample;


@implementation Laser
+ initialize
{
    fire_sample = (Sebum<SebSample> *)[base_sebum getSebumByName:"weapon/laser-snd"];
    return self;
}

- init
{
    [super init];

    health = LEVEL0_DAMAGE;
    speed = 14.0;
    angle = M_PI_2;

    sprite = (Sebum<SebImage> *)[base_sebum getSebumByName:"weapon/laser"];
    w = [sprite width] + 4;		/* Slightly wider */
    h = [sprite height];

    return self;
}

- (void) die
{
    int i;

    health -= 2;
    spawn_debris([Spark class], x, y, MEDIUM_LAYER);

    /* Slow down when penetrating an enemy. */
    speed = MAX(8.0, speed - 1.8);
    recalculate_velocity = YES;

    /* Some extra sparks. */
    for (i = 0; i < 2*debri_amount; i++)
	[spawn_debris([LineSpark class], x, y, HIGH_LAYER)
		     setAngle:deg2rad(rnd(-180, 0))];
}

+ (enum DAMAGE_TYPE) damageType { return DAMAGE_TYPE_LASER; }
- (int) damage { return MIN(health, 2); }
@end

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

@implementation LaserMedium
- init
{
    [super init];
    health = LEVEL1_DAMAGE;
    return self;
}
@end

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

@implementation LaserHigh
- init
{
    [super init];

    health = LEVEL2_DAMAGE;

    sprite = (Sebum<SebImage> *)[base_sebum getSebumByName:"weapon/laser-fat"];
    w = [sprite width] + 4;
    h = [sprite height];

    return self;
}

- (void) die
{
    if (health > 10 && health-2 <= 10) {
	sprite = (Sebum<SebImage> *)[base_sebum getSebumByName:"weapon/laser-high"];
	w -= 5;			/* 25px -> 20px. */
	h -= 20;		/* 80px -> 60px. */
    }
    else if (health > 5 && health-2 <= 5) {
	sprite = (Sebum<SebImage> *)[base_sebum getSebumByName:"weapon/laser"];
	w -= 10;		/* 20px -> 10px. */
	h -= 20;		/* 60px -> 40px. */
    }

    [super die];
}
@end

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

void fireLaser(double x, double y, int level, int *reload, int pid)
{
#define SPAWN_ALLY_PROJ(class,x,y)		[(Laser *)spawn_projectile(class,x,y,YES) setParentID:pid]

    /* Level 0: 1 x  9 hp/shot * 50/13 shots/sec = 34.6 hp/sec.
       Level 1: 2 x  6 hp/shot * 50/14 shots/sec = 42.9 hp/sec.
       Level 2: 1 x 15 hp/shot * 50/15 shots/sec = 50.0 hp/sec.
    */

    y -= 10;
    if (level == 0) {
	SPAWN_ALLY_PROJ([Laser class], x, y);
    }
    elif (level == 1) {
	/* Angle away slightly. */
	[SPAWN_ALLY_PROJ([LaserMedium class], x-16, y) setAngle:deg2rad(91.5)];
	[SPAWN_ALLY_PROJ([LaserMedium class], x+16, y) setAngle:deg2rad(89.5)];
    }
    else {
	SPAWN_ALLY_PROJ([LaserHigh class], x, y);
    }

    *reload = 13 + level;
    play_voice_on_channels(fire_sample, x, 192, PRIMARY_WEAPON_CHANNELS);

#undef SPAWN_ALLY_PROJ
}
