void SetAIVecHeading(Ship *ship, SpaceObjRotImpTarg *target, vector *trajectory)
{
    //real32 range;
    ShipStaticInfo *shipstaticinfo = (ShipStaticInfo *)ship->staticinfo;
    vector tmpvec;
    udword target_class;
    real32 randegf;
    sdword randeg;
    matrix tmpmat;
    vector targetheading;
    MinelayerCorvetteSpec *spec = (MinelayerCorvetteSpec *)ship->ShipSpecifics;
    MinelayerCorvetteStatics *minelayercorvettestatics;
    minelayercorvettestatics = (MinelayerCorvetteStatics *) ((ShipStaticInfo *)(ship->staticinfo))->custstatinfo;
    matGetVectFromMatrixCol3(targetheading,target->rotinfo.coordsys)

    if(target != NULL)
    {
        if(target->objtype == OBJ_ShipType)
            target_class = ((Ship *)target)->staticinfo->shipclass;
        else
            target_class = CLASS_NonCombat;
    }

    if (vecDotProduct(targetheading,*trajectory) > 0)
    {   //Attack accross front of ship :)
        vecAddTo(spec->aivec,targetheading);
        vecAddTo(spec->aivec,*trajectory);
        vecScalarMultiply(spec->aivec,spec->aivec,minelayercorvettestatics->FlyAwayDist[target_class]);
    }
    else
    {    //test
        if(randombetween(1,2) & 1)
        {
            vecCrossProduct(spec->aivec,*trajectory, targetheading);
        }
        else
        {
            vecCrossProduct(spec->aivec, targetheading, *trajectory);
        }
        vecAddTo(spec->aivec, *trajectory);
        vecScalarMultiply(spec->aivec,spec->aivec,minelayercorvettestatics->FlyAwayDist[target_class]);
    }
    if(!(target->posinfo.isMoving & ISMOVING_MOVING))
    {    //if target isn't moving, randomize trajectory
        randeg = randombetween(5,30);
        randegf = (real32) ((randeg & 1) ? randeg : -randeg);
        randegf = (real32) randeg;
        randegf = DEG_TO_RAD(randegf);

        matMakeRotAboutZ(&tmpmat,(real32)cos(randegf),(real32)sin(randegf));
        matMultiplyMatByVec(&tmpvec,&tmpmat,&spec->aivec);
        spec->aivec = tmpvec;
    }
    vecAddTo(spec->aivec,target->posinfo.position);

    //need change
    aishipFlyToPointAvoidingObjs(ship,&spec->aivec,AISHIP_FastAsPossible | AISHIP_PointInDirectionFlying,INTERCEPTORBREAK_MINVELOCITY);

}
void DefenseFighterAttack(Ship *ship,SpaceObjRotImpTarg *target,real32 maxdist)
{
    vector trajectory;
    real32 range;

    aishipGetTrajectory(ship,target,&trajectory);
    range = RangeToTarget(ship,target,&trajectory);

    if (range < 1000.0f)
    {
        aitrackZeroVelocity(ship);
        vecNormalize(&trajectory);
        aitrackHeading(ship,&trajectory,0.9999f);
    }
    else
    {
        aishipFlyToPointAvoidingObjs(ship,&target->posinfo.position,AISHIP_PointInDirectionFlying,0.0f);
    }
}
//this function flies the ship to within range of the desired target location and
//orients itself to fire.  Returns true when in position
bool flytoBurstPosition(Ship *ship)
{
    HeavyCorvetteSpec *spec = (HeavyCorvetteSpec *)ship->ShipSpecifics;
    vector heading;
    bool ready = FALSE;
    //maybe track to within gun gimbleness
    vecSub(heading,spec->burstFireVector,ship->posinfo.position);
    vecNormalize(&heading);
    if(aitrackHeadingWithFlags(ship,&heading,0.99f,AITRACKHEADING_IGNOREUPVEC))
    {
        ready = TRUE;
    }

    if(!MoveReachedDestinationVariable(ship,&spec->burstFireVector,burstRange))
    {
        aishipFlyToPointAvoidingObjs(ship,&spec->burstFireVector,AISHIP_FastAsPossible,0.0f);
        return(FALSE);
    }
    aitrackZeroVelocity(ship);
    return(ready);
}
void MineLayerAttackRun(Ship *ship,SpaceObjRotImpTarg *target,AttackSideStep *attacksidestep,AttackSideStepParameters *parameters)
{
    vector trajectory;
    //real32 dist;
    real32 range;
    //real32 temp;
//    bool didshoot;
    ShipStaticInfo *shipstaticinfo = (ShipStaticInfo *)ship->staticinfo;
    Gun *gun;
    udword numGuns,target_class;
    GunInfo *guninfo = ship->gunInfo;
    //vector tmpvec;
    //real32 randegf;
    //sdword randeg;
    //matrix tmpmat;
    //vector targetheading;
    MinelayerCorvetteSpec *spec = (MinelayerCorvetteSpec *)ship->ShipSpecifics;
    MinelayerCorvetteStatics *minelayercorvettestatics;
    minelayercorvettestatics = (MinelayerCorvetteStatics *) ((ShipStaticInfo *)(ship->staticinfo))->custstatinfo;

    numGuns = guninfo->numGuns;

    gun = &guninfo->guns[0];
    if(target != NULL)
    {
        if(target->objtype == OBJ_ShipType)
            target_class = ((Ship *)target)->staticinfo->shipclass;
        else
            target_class = CLASS_NonCombat;
    }

    switch (ship->aistateattack)
    {
        case ATTACK_INIT:
        case APPROACH:
#ifdef DEBUG_ATTACK
            dbgMessagef("\nShip %x MINELAYER_ATTACK_APPROACH",(udword)ship);
#endif
            aishipGetTrajectory(ship,target,&trajectory);
            aishipFlyToShipAvoidingObjs(ship,target,AISHIP_PointInDirectionFlying,0.0f);
            range = RangeToTarget(ship,target,&trajectory);

			//lets check if we want to force drop...
			if(target->objtype == OBJ_ShipType)
			{
				if(((Ship *)target)->shiptype == Mothership)
				{
					//its a mothership
					vector tempvec;
					real32 tempreal;
					vecSub(tempvec,target->collInfo.collPosition,ship->collInfo.collPosition);
					tempreal = vecMagnitudeSquared(tempvec);
					if(tempreal < mothershipDistSqr)
					{
						//we're within range of force dropping!
						ship->aistateattack = DROP_MOTHERSHIP;
					}
					break;
				}

			}


            if (range < minelayercorvettestatics->breakInAwayDist)
            {
                ship->aistateattack = BREAKPOSITION;
                spec->aivec.x = 0.0f;
                spec->aivec.y = 0.0f;
                spec->aivec.z = 0.0f;
            }

            break;
		case DROP_MOTHERSHIP:
			{
				vector tempvec;
				real32 tempreal;
				vecSub(tempvec,ship->collInfo.collPosition,target->collInfo.collPosition);
				tempreal = vecMagnitudeSquared(tempvec);
				vecNormalize(&tempvec);
				if(tempreal > mothershipDistSqr2)
				{
					ship->aistateattack = ATTACK_INIT;
				}
				if(aitrackHeadingWithFlags(ship,&tempvec,0.97f,AITRACKHEADING_IGNOREUPVEC))
				{
					if(MinelayerCorvetteStaticMineDrop(ship,target))		//problem...there will be other targets...bah..lets see..
					{
						MinelayerCorvetteOrderChangedCleanUp(ship);
					}
				}
				break;
			}
        case BREAKPOSITION:
#ifdef DEBUG_ATTACK
        dbgMessagef("\nShip %x BREAKPOSITION",(udword)ship);
#endif

            aishipGetTrajectory(ship,target,&trajectory);
            range = RangeToTarget(ship,target,&trajectory);
            vecNormalize(&trajectory);

            SetAIVecHeading(ship,target,&trajectory);

            ship->aistateattack = BREAK1;

        case BREAK1:
#ifdef DEBUG_ATTACK
    dbgMessagef("\nShip %x BREAK1",(udword)ship);
#endif

            aishipGetTrajectory(ship,target,&trajectory);
            range = RangeToTarget(ship,target,&trajectory);


            //aishipFlyToPointAvoidingObjs(ship,&spec->aivec,AISHIP_FastAsPossible | AISHIP_PointInDirectionFlying,INTERCEPTORBREAK_MINVELOCITY);
            aishipFlyToPointAvoidingObjs(ship,&target->posinfo.position,AISHIP_FastAsPossible | AISHIP_PointInDirectionFlying,INTERCEPTORBREAK_MINVELOCITY);
            if(range < minelayercorvettestatics->DropRange)
            {
                //temp
                vecNormalize(&trajectory);
                SetAIVecHeading(ship,target,&trajectory);
                //temp

                ship->aistateattack = KILL;    //within mining range so start dropping
                spec->aispheretime=0.0f;            //reset time;
            }

            break;
        case KILL:
#ifdef DEBUG_ATTACK
    dbgMessagef("\nShip %x KILL",(udword)ship);
#endif
            aishipGetTrajectory(ship,target,&trajectory);
            range = RangeToTarget(ship,target,&trajectory);

            spec->aispheretime += universe.phystimeelapsed;

            if(gunCanShoot(ship, gun))
            {
                if(gun->numMissiles > 0)
                {
                   spec->mineaistate = MINE_DROP_ATTACK;
                   MinelayerCorvetteFire(ship,target);
                 }
            }
            if(range > minelayercorvettestatics->DropStopRange)
            {   //out of range....
                ship->aistateattack = BREAK2;
            }
            if(spec->aispheretime > minelayercorvettestatics->Break2SphereizeFreq)
            {    //time to sphereize;
                spec->aivec.x =0.0f;
                spec->aivec.y =0.0f;
                spec->aivec.z =0.0f;
                spec->aispheretime = -1000000.0f;     // Reset, and never do again till next attack pass...
                vecNormalize(&trajectory);
                SetAIVecHeading(ship,target,&trajectory);

#ifdef DEBUG_ATTACK
    dbgMessagef("\nShip %x KILL: Adjust for Break2 Sphereizing Godliness Maneuver :)",(udword)ship);
#endif

            }

            aishipFlyToPointAvoidingObjs(ship,&spec->aivec,AISHIP_FastAsPossible | AISHIP_PointInDirectionFlying,INTERCEPTORBREAK_MINVELOCITY);
            break;
        case BREAK2:
#ifdef DEBUG_ATTACK
    dbgMessagef("\nShip %x BREAK2",(udword)ship);
#endif

            aishipGetTrajectory(ship,target,&trajectory);
            range = RangeToTarget(ship,target,&trajectory);
            aishipFlyToPointAvoidingObjs(ship,&spec->aivec,AISHIP_FastAsPossible | AISHIP_PointInDirectionFlying,INTERCEPTORBREAK_MINVELOCITY);
            if(range > minelayercorvettestatics->FlyAwayDist[target_class] ||
               (MoveReachedDestinationVariable(ship,&spec->aivec,minelayercorvettestatics->FlyAwayTolerance)))
            {    //turn around and start over
                ship->aistateattack = APPROACH;
            }
            break;
        default:
            dbgAssert(FALSE);
            break;
    }

}
void doKamikazeAttack(Ship *ship,SpaceObjRotImpTarg *target)
{
    real32 mag,dist,range,shipvel;
    vector destination,trajectory,heading,shipheading,EinsteinVelocity;
    ShipStaticInfo *shipstaticinfo = ship->staticinfo;

    vecSub(trajectory,target->collInfo.collPosition,ship->posinfo.position);
    mag = vecMagnitudeSquared(trajectory);
    dist = fsqrt(mag);

    destination = trajectory;
    vecNormalize(&destination);
    heading = destination;

    //this hokey fudge factor is needed so the kamikaze ship doesn't
    //slow down as it reaches its destination
    mag = dist + 500.0f;
    vecScalarMultiply(destination,destination,mag);
    vecAddTo(destination,target->collInfo.collPosition);

    range = RangeToTargetGivenDist(ship,target,dist);

    switch(ship->kamikazeState)
    {
    case K_Start:
        //if within a threshold range
        bitClear(ship->specialFlags,SPECIAL_KamikazeCrazyFast);
        if(range < 500.0f)
        {
            //calculate flyby dist
            matGetVectFromMatrixCol3(shipheading, ship->rotinfo.coordsys);
            vecScalarMultiply(shipheading,shipheading,kamikazeFlyByDist);
            vecAdd(ship->kamikazeVector,shipheading,target->collInfo.collPosition);
            ship->kamikazeState = K_TurnAround;
        }
        ship->kamikazeState = K_Ram;

        break;

    case K_Ram:
        if (range < 400.0f)
        {
            ship->kamikazeState = K_Yell;
        }
    case K_Ram2:
        //lets use...mmmmm..twister theor...no...relativity
        vecSub(EinsteinVelocity,ship->posinfo.velocity,target->posinfo.velocity);
        shipvel = fsqrt(vecMagnitudeSquared(EinsteinVelocity));
        if(ship->shiptype == MinelayerCorvette)
        {
            ((MinelayerCorvetteSpec *)(ship->ShipSpecifics))->mineaistate = MINE_DROP_ATTACK;
        }
        else if (ship->shiptype == DefenseFighter)
        {
            goto dontshoot;
        }

        if (isShipStaticInterceptor(shipstaticinfo))
        {
            if (range < shipstaticinfo->bulletRange[ship->tacticstype])
            {
                GenericInterceptorStatics *interceptorstat = (GenericInterceptorStatics *)shipstaticinfo->custstatinfo;
                uword targetIndex;

                if (target->objtype == OBJ_ShipType)
                {
                    targetIndex = (uword)((ShipStaticInfo *)target->staticinfo)->shipclass;
                }
                else
                {
                    targetIndex = (uword)NUM_CLASSES;
                }

                if (GenericInterceptorCanFire(ship,target,&trajectory,interceptorstat->triggerHappy[ship->tacticstype][targetIndex]))
                {
                    ship->staticinfo->custshipheader.CustShipFire(ship,target);
                }
            }
        }
        else
        {
            gunShootGunsAtTarget(ship,target,range,&trajectory);
        }
dontshoot:
        aishipFlyToPointAvoidingObjs(ship,&destination,AISHIP_PointInDirectionFlying | AISHIP_FirstPointInDirectionFlying | AISHIP_FastAsPossible,0.0f);
        if(range < 1500.0f)
        {
            bitSet(ship->specialFlags,SPECIAL_KamikazeCrazyFast);
        }
        else
        {
            bitClear(ship->specialFlags,SPECIAL_KamikazeCrazyFast);
        }

/*
        if(range < 400.0f && (shipvel < ship->staticinfo->staticheader.maxvelocity*0.7f ||
                   vecDotProduct(trajectory,heading) < 0))
        {
            //ship is inside 400.0f, and isn't faceing ship, or isn't
            //going fast enough

            //calculate flyby dist
            matGetVectFromMatrixCol3(shipheading, ship->rotinfo.coordsys);
            vecScalarMultiply(shipheading,shipheading,kamikazeFlyByDist);
            vecAdd(ship->kamikazeVector,shipheading,target->posinfo.position);
            ship->kamikazeState = K_TurnAround;
        }
*/
        break;
    case K_TurnAround:
        bitClear(ship->specialFlags,SPECIAL_KamikazeCrazyFast);
        aishipFlyToPointAvoidingObjs(ship,&ship->kamikazeVector,AISHIP_PointInDirectionFlying | AISHIP_FirstPointInDirectionFlying | AISHIP_FastAsPossible,0.0f);
        if(MoveReachedDestinationVariable(ship,&ship->kamikazeVector,300.0f))
            ship->kamikazeState = K_TurnAround2;
        break;
    case K_TurnAround2:
        bitClear(ship->specialFlags,SPECIAL_KamikazeCrazyFast);
        if(aitrackHeadingWithFlags(ship,&heading,0.90f,AITRACKHEADING_IGNOREUPVEC))
            ship->kamikazeState = K_Ram;
        break;
    case K_Yell:
//      speechEvent(ship, COMM_LInt_Kamikaze, 0);
        battleChatterAttempt(SOUND_EVENT_DEFAULT, BCE_Kamikaze, ship, SOUND_EVENT_DEFAULT);
        ship->kamikazeState = K_Ram2;
        break;
    }

        //fire guns here...
    //
    //
    //Sound note:   Could put in kamikaze state change here after
    //              getting to within a certain distance of target
    //
    //          ask bryce how to...
}