/* basic-follower.m, 
 *
 * 'Basic-follower' follows the path given by an array of waypoint_t's, such as
 * from articulated splines.  It has animations, but no firing routines.  It is
 * designed to be used as a base class.
 */

#include <allegro.h>
#include <math.h>
#include "common.h"
#include "map.h"
#include "seborrhea/seborrhea-spline.h"
#include "seborrhea/seborrhea.h"
#include "units/basic-follower.h"


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

    speed = 99.0;
    the_way = nil;

    /* Animations. */
    animation.anim  = nil;
    animation.frame = 0;
    animation.loop  = YES;

    return self;
}

- (id) setX:(double)x_ Y:(double)y_
{
    mirror_path = (x_ <= screen_w / 2) ? NO : YES;
    path_x_displacement = mirror_path ? screen_w - x_: x_;

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

- (BOOL) readyToActivate
{
    if ([super readyToActivate]) {
	/* This current y value is the vertical origin of our path. */
        path_y_displacement = y;
	return YES;
    }
    else
	return NO;
}

- (int) update
{
    if (animation.anim) {
	if (animate(&animation))
            sprite = [animation.anim getFrame:animation.frame];
    }

    return [super update];
}

- (void) move
{
    if (the_way) {
	int ret;

        /* We need to scroll the path and unit with the map. */
        path_y_displacement += [current_map scrollRate];
	y += [current_map scrollRate];

        /* Just pretend our path is not mirrored for a tic. */
        if (mirror_path)
            x = screen_w - x;

	ret = [the_way follow:&path_progress :&x :&y :speed
		       :path_x_displacement :path_y_displacement];

        /* Now reflect the unit back across the centre of the screen. */
        if (mirror_path)
            x = screen_w - x;

	if (ret == PATH_ENDED)
	    the_way = nil;
	else if (ret == PATH_REACHED_WAYPOINT) {
	    angle = [the_way angleBetween:path_progress-1 :path_progress];
	    if (mirror_path)
		angle = M_PI - angle;
	}
    }
    else
	[super delete];
}

	/* For use in map editor only! */
- (void) drawMapEditorExtras:(BITMAP *)dest
{
    if (the_way) {
	int pink = makecol(0xff, 0x80, 0x80);
	int gray = makecol(0x40, 0x40, 0x40);
	unsigned int progress = 0;
	double x_ = x, y_ = y, deltax;

	deltax = path_x_displacement;
	
	if (mirror_path) x_ = screen_w - x_;
	while ([the_way follow:&progress :&x_ :&y_ :speed :deltax :y] != PATH_ENDED) {
	    if (mirror_path) x_ = screen_w - x_;

	    putpixel(dest, x_-offsetX,   y_-offsetY,   pink);
	    putpixel(dest, x_-offsetX-1, y_-offsetY,   gray);
	    putpixel(dest, x_-offsetX+1, y_-offsetY,   gray);
	    putpixel(dest, x_-offsetX,   y_-offsetY-1, gray);
	    putpixel(dest, x_-offsetX,   y_-offsetY+1, gray);

	    if (mirror_path) x_ = screen_w - x_;
	}
    }

    [super drawMapEditorExtras:dest];
}

- derive_fixedAngle;
- derive_alwaysInfluenceGameplay;
@end

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

@implementation BasicGroundFollower
- (void) move
{
    double yy;

    /* We want to scroll with the map. */
    yy = [current_map scrollRate];
    y -= yy;
    path_y_displacement -= yy;

    /* Normal follower move routines. */
    [super move];
}

- (int) collisionLists { return COLLIDES_WITH_PROJECTILES_AND_NUKES; }
@end
