/* robot.m,
 *
 * Little ally ships that follow the player around and fire lots.
 * They are considered as a tertiary weapon.
 */

#include <math.h>
#include "common.h"
#include "debris/spark.h"
#include "nuke.h"
#include "projectiles/laser.h"
#include "projectiles/toothpaste.h"
#include "projectiles/vulcan.h"
#include "seborrhea/seborrhea.h"
#include "units/robot.h"


#define MAX_KAMIKAZE_DISTANCE	60


@implementation Robot
- init
{
    [super init];

    health = 15;

    sprite = [[SebAnimator new] setAnimation:(SebAnimation *)[base_sebum getSebumByName:"robot/body"]];
    shadow = [base_sebum getSebumByName:"robot/shadow"];
    w = 20;
    h = 20;

    /* Start invincible when coming from bottom of screen. */
    flags |= FLAG_INVINCIBLE;
    return self;
}

- (id) setParent:(Player *)p { parent = p; pid = [parent playerID]; return self; }

- (id) setDisplacementX:(int)x_ Y:(int)y_
{
    x_displacement = x_;
    y_displacement = y_;
    return self;
}

- (void) spawnDyingExplosions
{
    if (rnd(0, 2 * health) == 0)
	spawn_debris([Spark class], x, y, HIGH_LAYER);
}

- (void) die
{
    if (not (flags & FLAG_DYING)) {
	/* Go on a kamikaze after death. */
	health = 1.0;
	kamikaze_distance = MAX_KAMIKAZE_DISTANCE;
	yv = -1.0;
	flags |= FLAG_DYING;

	if (parent) {
	    [parent disownChild:self];
	    parent = nil;
	}
    }
}

- (int) update
{
    if (health <= 2)
        [self spawnDyingExplosions];

    if (flags & FLAG_DYING) {
        [self moveKamikaze];

        if (health <= 0) {
	    [spawn_nuke(x, y, pid) setNukeRadius:75];
            return THING_DEAD;
	}
    }
    else {
        [self move];

        if (--fire_tics <= 0)
            [self fire];
    }

    return THING_NORMAL;
}

- (void) move
{
    if (parent) {
	double dest_x, dest_y;
	[parent getX:&dest_x Y:&dest_y];
	x += (dest_x + x_displacement - x) / 10;
	y += (dest_y + y_displacement - y) / 10;

	if (ABS(dest_y - y) < ABS(y_displacement*2))
	    flags &=~FLAG_INVINCIBLE;
    }
}

- (void) moveKamikaze
{
    /* Kamikaze!  (Bonzai!) */
    yv -= 0.1;
    x += 0.5 * ((x_displacement < 0) ? -1 : 1);
    y += yv;

    if (--kamikaze_distance <= 0)
	health = 0.0;
}

- (void) fire
{
#define SPAWN_ALLY_PROJ(c,x,y)	[(AllyProjectile *)spawn_projectile([c class],x,y,YES) setParentID:pid]

    int primary_weapon;

    /* Laser:   1 x 6 hp/shot * 50/20 shots/sec = 15.0 hp/sec
       'Paste:  1 x 3 hp/shot * 50/12 shots/sec = 12.5 hp/sec
       Vulcan:  2 x 2 hp/shot * 50/16 shots/sec = 14.3 hp/sec

       Note that these values are for _each_ robot. */

    if (not parent || not [parent isFiring])
	return;

    primary_weapon = [parent weaponType:PRIMARY_WEAPON];

    if (primary_weapon == PRIMARY_WEAPON_LASER) {
	/* Note: LaserMedium is weaker than Laser. */
        SPAWN_ALLY_PROJ(LaserMedium, x, y-5);
        fire_tics = 22;
    }
    else if (primary_weapon == PRIMARY_WEAPON_TOOTHPASTE) {
        SPAWN_ALLY_PROJ(Toothpaste, x, y-5);
        fire_tics = 12;
    }
    else {
        SPAWN_ALLY_PROJ(Vulcan, x-3, y-5);
        SPAWN_ALLY_PROJ(Vulcan, x+3, y-5);
        fire_tics = 14;
    }

#undef SPAWN_ALLY_PROJ
}

- (int) collisionLists { return ACTIVE_AIR_LIST|COLLIDES_WITH_PROJECTILES; }
@end
