/*
 *  acm : an aerial combat simulator for X
 *  Copyright (C) 1991-1994,1997  Riley Rainey
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software Foundation,
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */

#include <math.h>
#include "pm.h"
#include <stdio.h>
#include <string.h>

int       select_aim9m(craft *);
int       display_aim9m(craft *, craftType *, viewer *, int *, int *);
int       update_aim9m(craft *);
int       fire_aim9m(craft *);
int       getIRTarget(craft * c, VPoint * t, double scanSlope);
extern int fireMissile(craft * c, int ind);
extern FILE *acm_fopen(char *, char *);

weaponDesc aim9mDesc =
{
	WK_AIM9M,
	select_aim9m,				/* select */
	update_aim9m,				/* update */
	display_aim9m,				/* display procedure */
	fire_aim9m,					/* fire */
	(int (*)(craft *)) NULL,	/* fire button release */
};

int       hasFired[MAXPLAYERS];
static int count[MAXPLAYERS];

/*
 *  aim9m selection function
 *
 *  A selection function normally determines whether there are any weapons
 *  of this type on-board.  If so, and the weapon system is functional
 *  (in other words, undamaged) then return 1; otherwise return 0.
 */

/*ARGSUSED */
int
select_aim9m(craft * c)
{

	hasFired[c->pIndex] = 0;
	count[c->pIndex] = countOrdinance(c, "aim9m");
	return 1;

}

/*ARGSUSED */
int
update_aim9m(craft * c)
{

	register int i;

	/*
	 *  Missile won't fire if we have "Weight on wheels"
	 */

	if ((c->flags & FL_GND_CONTACT) == 0) {
		if (hasFired[c->pIndex] && count[c->pIndex] > 0) {
			i = readyStation(c, "aim9m");
			if (i < 0)
				fprintf(stderr, "Oops. Can't find an AIM-9\n");
			else {

				/*
				 *  In arcadde mode, we never run out of ammunition
				 */

				if (arcadeMode == 0) {
					c->station[i].type = "";
					count[c->pIndex]--;
				}
				fireMissile(c, i);
				playSound(c, SoundMissileLaunch);
			}
			hasFired[c->pIndex] = 0;
		}
	}
	return 1;
}

/*ARGSUSED */
int
fire_aim9m(craft * c)
{

	hasFired[c->pIndex] = 1;
	return 1;
}

/*
 *  aim9m display function
 *
 *  Update the HUD display strings associated with this weapon system.
 *
 *  This code may be called by drones.  Return a nonzero value if
 *  have a reasonable chance of scoring a kill.
 */

/*ARGSUSED */
int
display_aim9m(craft * c, craftType * w, viewer * u, int *i1, int *i2)
{

	char      s[16];
	double    d, a1, v, r, root1, root2, n, t;
	VPoint    tmp;
	int       target, result = 0;

	sprintf(s, "%d AIM-9M", count[c->pIndex]);
	strcpy(c->leftHUD[3], s);

	v = mag(c->Cg);
	a1 = (w->maxThrust - 0.5 * c->rho * w->CDOrigin * v * v)
		/ (w->emptyWeight + w->maxFuel) * earth_g;

	if (c->curRadarTarget >= 0 && a1 >= 0.0) {

		d = c->targetDistance;
		r = c->targetClosure;

		n = r * r + 2.0 * a1 * d;
		if (n > 0) {
			n = sqrt(n);
			root1 = (-r + n) / a1;
			root2 = (-r - n) / a1;
			if (root1 >= 0.0)
				if (root2 >= 0.0)
					if (root1 < root2)
						t = root1;
					else
						t = root2;
				else
					t = root1;
			else if (root2 >= 0.0)
				t = root2;
			else
				t = -1.0;
		}
		else
			t = -1.0;
	}

	else
		t = -1.0;

/*
 *  See if the missiles can lock onto any target.  We'll constrain getIRTarget()
 *  so that it will only select target's in a twenty degree boresight cone.
 */

	if (count[c->pIndex] > 0) {
		target = getIRTarget(c, &tmp, 0.17633);
	}
	else {
		target = -1;
	}

	if (target >= 0 && t <= 15.0)
		sprintf(s, "LOCKED   %d", (int) (t + 0.5));
	else if (t < 0.0)
		sprintf(s, "ARM      --");
	else if (t <= 15.0)
		sprintf(s, "IN RANGE %d", (int) (t + 0.5));
	else
		sprintf(s, "ARM      %d", (int) (t + 0.5));

/*
 *  Set result equal to one if we are recommending a missile shot
 */

	if (target >= 0 && t <= 10.0 && t > (w->armDelay + 0.5)) {
		result = 1;
	}

	strcpy(c->leftHUD[2], s);

	strcpy(c->leftHUD[4], "");

	return result;
}

extern craftType *newCraft(void);

void
initaim9(void)
{

	craftType *c;
	FILE     *f;
	dis_entity_type em1 =
	{2, 1, 225, 1, 1, 3, 0};
	dis_entity_type em2 =
	{2, 1, 222, 1, 2, 1, 0};

	c = newCraft();
	c->name = strdup("aim-9m");

	c->entityType = em1;
	c->altEntityType = em2;

	wtbl[0] = aim9mDesc;
	wtbl[0].w = c;

	c->CDOrigin = 0.04;			/* 5" radius of body */
	c->CDFactor = -2.56694;

	c->CDBOrigin = 0.0;
	c->CDBFactor = 0.0;

	VIdentMatrix(&(c->I));
	c->I.m[0][0] = 0.0;
	c->I.m[1][1] = 0.0;
	c->I.m[2][2] = 0.0;
	c->cmSlope = -1.88;
	c->cmFactor = -1.00;

	c->wingS = 1.0;

/*
 *  Assume 150.0 lbs of weight is fuel and that it burns for about 4 seconds.
 *  That yields a fuel burn rate of 40 lbs/second.
 */

	c->emptyWeight = 90.0;
	c->maxFuel = 100.0;
	c->maxThrust = 4000.0;
	c->spFuelConsump = 40;

/*
 *  Three second arming delay
 */

	c->armDelay = 1.0;

	c->groundingPoint.x = 0.0;
	c->groundingPoint.y = 0.0;
	c->groundingPoint.z = 0.0;

	c->viewPoint.x = 0.0;
	c->viewPoint.y = 0.0;
	c->viewPoint.z = 0.0;

	c->muStatic = 0.0;
	c->muKinetic = 0.0;
	c->muBStatic = 0.0;
	c->muBKinetic = 0.0;

	c->maxNWDef = 0.0;
	c->NWIncr = 0.0;
	c->maxNWS = 0.0;
	c->gearD1 = 0.0;
	c->gearD2 = 0.0;

	f = acm_fopen("aim9.obv", "r");
	c->object = VReadObject(f);
	fclose(f);

}
