void VectorFromShipAngle(float *xr, float *yr, float *zr)
{
/*
	float h, p, b;
	matrix x, y, z;
	vector v = {0.0f, 1.0f, 0.0f}, r;

	h = *xr;
	p = *yr;
	b = *zr;

	matMakeRotAboutX(&x, (float)cos(h), (float)sin(h));
	matMakeRotAboutY(&y, (float)cos(p), (float)sin(p));
	matMakeRotAboutZ(&z, (float)cos(b), (float)sin(b));

	matMultiplyMatByVec(&r, &z, &v);
	matMultiplyMatByVec(&v, &x, &r);
	matMultiplyMatByVec(&r, &y, &v);

	*xr = r.x;
	*yr = r.y;
	*zr = r.z;
*/
    matrix mat;
    vector rotVector = {*xr, *yr, *zr};
    nisShipEulerToMatrix(&mat, &rotVector);
    matGetVectFromMatrixCol2(rotVector, mat);
    *xr = rotVector.x;
    *yr = rotVector.y;
    *zr = rotVector.z;
}
示例#2
0
void P2MultiBeamFrigateAttackDoAttack(Ship *ship,SpaceObjRotImpTarg *target,real32 maxdist,bool PassiveAttack)

{
    ShipStaticInfo *shipstaticinfo = (ShipStaticInfo *)ship->staticinfo;

    P2MultiBeamFrigateStatics *frigstat = (P2MultiBeamFrigateStatics *)shipstaticinfo->custstatinfo;
    P2MultiBeamFrigateSpec    *spec     = (P2MultiBeamFrigateSpec *)ship->ShipSpecifics;

    vector trajectory;
    vector shipRightVec;
    real32 range;

        spec->aiattacklast = universe.totaltimeelapsed;
    ship->autostabilizeship = FALSE;

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

    if (range > frigstat->MultiBeamRange[ship->tacticstype])
    {
        //not in range
        if(!PassiveAttack)
        {
            //do aiship fly to stuff here

            //if not in range...fly to the ship
            //else track zero velocity
                aishipFlyToShipAvoidingObjs(ship,target,AISHIP_PointInDirectionFlying + AISHIP_CarTurn,0.0f);
        }
        return;
    }

    //we are in range

    vecNormalize(&trajectory);
    if(!PassiveAttack)
	{
		aitrackZeroVelocity(ship);
	}
    matGetVectFromMatrixCol2(shipRightVec,ship->rotinfo.coordsys);

    aitrackHeadingAndUp(ship,&trajectory,&shipRightVec,0.9999f);

    
	if(vecMagnitudeSquared(ship->rotinfo.rotspeed) > frigstat->AttackRotationSpeed)
    {
		if(aitrackHeadingWithFlags(ship,&trajectory,0.99f,AITRACKHEADING_IGNOREUPVEC|AITRACK_DONT_ZERO_ME))
		{
			//rotation speed reached
			//lets fire guns if we can
			P2MultiBeamFrigateFire(ship,target);
		}
    }
}
/*-----------------------------------------------------------------------------
    Name        : nisShipEulerToMatrix
    Description : Builds a coordinate system matrix from a heading,pitch,bank
                    triplicate.
    Inputs      : rotVector - vectror whose members represent the heading, pitch and bank
    Outputs     : coordsys - where to store the matrix
    Return      :
----------------------------------------------------------------------------*/
void nisShipEulerToMatrix(matrix *coordsys, vector *rotVector)
{
    matrix rotation, tempMatrix;
    vector rotateAbout = {-1.0f, 0.0f, 0.0f};

    *coordsys = IdentityMatrix;
    //rotate about up vector (heading)
    nisRotateAboutVector((real32 *)&rotation, &rotateAbout, rotVector->x);
    matMultiplyMatByMat(&tempMatrix, &rotation, coordsys);
    *coordsys = tempMatrix;
    //rotate about heading vector (pitch in lightwave, bank actually)
    matGetVectFromMatrixCol3(rotateAbout, *coordsys);
    nisRotateAboutVector((real32 *)&rotation, &rotateAbout, rotVector->y);
    matMultiplyMatByMat(&tempMatrix, &rotation, coordsys);
    *coordsys = tempMatrix;
    //rotate about heading vector (bank in lightwave, pitch actually)
    matGetVectFromMatrixCol2(rotateAbout, *coordsys);
    nisRotateAboutVector((real32 *)&rotation, &rotateAbout, -rotVector->z);
    matMultiplyMatByMat(&tempMatrix, &rotation, coordsys);
    *coordsys = tempMatrix;
}
bool MinelayerCorvetteStaticMineDrop(Ship *ship,SpaceObjRotImpTarg *target)
{
    MinelayerCorvetteStatics *minelayercorvettestatics;
    MinelayerCorvetteSpec *spec = (MinelayerCorvetteSpec *)ship->ShipSpecifics;
    sdword flag;
    GunInfo *guninfo = ship->gunInfo;
    Gun *gun0,*gun1;
    real32 time;
    sdword maxmis;

    minelayercorvettestatics = (MinelayerCorvetteStatics *) ((ShipStaticInfo *)(ship->staticinfo))->custstatinfo;
    gun0 = ((Gun *) &(ship->gunInfo->guns[0]));

    maxmis = gun0->gunstatic->maxMissiles;

    if(ship->gunInfo->numGuns > 1)
    {    //ship has 2 guns (race 1)

        gun1 = ((Gun *) &(ship->gunInfo->guns[1]));

        if(gun0->numMissiles == 0 && gun1->numMissiles == 0)
            return FALSE;

        if((universe.totaltimeelapsed - gun1->lasttimefired) < minelayercorvettestatics->gunReFireTime
           && (universe.totaltimeelapsed - gun0->lasttimefired) < minelayercorvettestatics->gunReFireTime)
        {
            return(FALSE);
        }
        maxmis += gun1->gunstatic->maxMissiles;
    }
    else
    {
        if(gun0->numMissiles == 0)
            return FALSE;

        if((universe.totaltimeelapsed - gun0->lasttimefired) < minelayercorvettestatics->gunReFireTime)
            return(FALSE);
    }


    switch(spec->MiningStatus)
    {
    case FIRST_OFF:
        //////////////////////
        //speech event for forcedropped mines
        //event num: COMM_MLVette_ForceDrop
        //use battle chatter
        if(ship->playerowner->playerIndex == universe.curPlayerIndex)
        {
            if (battleCanChatterAtThisTime(BCE_COMM_MLVette_ForceDrop, ship))
            {
                battleChatterAttempt(SOUND_EVENT_DEFAULT, BCE_COMM_MLVette_ForceDrop, ship, SOUND_EVENT_DEFAULT);
            }
        }
        /////////////////////////

        spec->MiningStatus = FIRST_OFF2;
    case FIRST_OFF2:
        if(aitrackZeroRotationAnywhere(ship))
        {
            flag = 2;
        }

        if(aitrackZeroVelocity(ship))
        {
            if(flag == 2)
            {   //we're ready for next step
                MineFormationInfo *mineformationinfo;
                aitrackForceSteadyShip(ship);           //stop movement, stop rotation
                spec->MiningStatus = BEGIN_WALL_DROP_RIGHT;
                spec->MiningSideMax = 1;
                spec->MiningSideCount = 0;
                matGetVectFromMatrixCol1(spec->formation_up,ship->rotinfo.coordsys);
                matGetVectFromMatrixCol2(spec->formation_right,ship->rotinfo.coordsys);
                vecScalarMultiply(spec->formation_up, spec->formation_up, minelayercorvettestatics->MineSpacing);
                vecScalarMultiply(spec->formation_down, spec->formation_up, -1.0f);
                vecScalarMultiply(spec->formation_right,spec->formation_right,minelayercorvettestatics->MineSpacing);
                vecScalarMultiply(spec->formation_left,spec->formation_right,-1.0f);
                matGetVectFromMatrixCol3(spec->formation_heading,ship->rotinfo.coordsys);
                vecScalarMultiply(spec->formation_heading,spec->formation_heading,-minelayercorvettestatics->MineDropDistance);

                //Create Formation Entity Here

                mineformationinfo = memAlloc(sizeof(MineFormationInfo),"MineFormationInfo",NonVolatile);
                listAddNode(&universe.MineFormationList,&(mineformationinfo->FormLink),mineformationinfo);
                listInit(&mineformationinfo->MineList);
                mineformationinfo->playerowner = ship->playerowner;
                mineformationinfo->FULL = FALSE;
                mineformationinfo->wallstate = PULSE_START;
                mineformationinfo->effect = NULL;
                spec->mineforminfo = mineformationinfo;
                time = 29.0;
                spec->mineforminfo->waittime = time;     //set wait time for each pulse

                spec->formation_number_X = 0;
                spec->formation_number_Y = 0;

                vecAdd(spec->formation_position,ship->posinfo.position,spec->formation_heading);
                spec->mineaistate = MINE_DROP_FORMATION;
                MinelayerCorvetteFire(ship,target);
                spec->MineDropNumber = 1;
            }
        }
        break;
    case BEGIN_WALL_DROP_RIGHT:
        vecAddTo(spec->formation_position,spec->formation_right);
        spec->mineaistate = MINE_DROP_FORMATION;

        MinelayerCorvetteFire(ship,target);
        spec->MineDropNumber++;
        spec->formation_number_X++;
        spec->MiningSideCount++;
        if(spec->MiningSideCount == spec->MiningSideMax)
        {
            spec->MiningSideCount = 0;
            spec->MiningStatus = BEGIN_WALL_DROP_UP;
        }
        break;
    case BEGIN_WALL_DROP_UP:
        vecAddTo(spec->formation_position,spec->formation_up);
        spec->mineaistate = MINE_DROP_FORMATION;
        MinelayerCorvetteFire(ship,target);
        spec->MineDropNumber++;
        spec->formation_number_Y++;
        spec->MiningSideCount++;
        if(spec->MiningSideCount == spec->MiningSideMax)
        {
            spec->MiningSideMax++;
            spec->MiningSideCount = 0;
            spec->MiningStatus = BEGIN_WALL_DROP_LEFT;
        }
        break;
    case BEGIN_WALL_DROP_LEFT:
        vecAddTo(spec->formation_position,spec->formation_left);
        spec->mineaistate = MINE_DROP_FORMATION;
        MinelayerCorvetteFire(ship,target);
        spec->MineDropNumber++;
        spec->formation_number_X--;
        spec->MiningSideCount++;
        if(spec->MiningSideCount == spec->MiningSideMax)
        {
            spec->MiningSideCount = 0;
            spec->MiningStatus = BEGIN_WALL_DROP_DOWN;
        }
        break;
    case BEGIN_WALL_DROP_DOWN:
        vecAddTo(spec->formation_position,spec->formation_down);
        spec->mineaistate = MINE_DROP_FORMATION;
         MinelayerCorvetteFire(ship,target);
        spec->MineDropNumber++;
        spec->formation_number_Y--;
        spec->MiningSideCount++;
        if(spec->MiningSideCount == spec->MiningSideMax)
        {
            spec->MiningSideMax++;
            spec->MiningSideCount = 0;
            spec->MiningStatus = BEGIN_WALL_DROP_RIGHT;
        }
        break;
    case DONE_WAIT:
        spec->mineaistate = MINE_DROP_ATTACK;
        return TRUE;
        break;
    }
    if(spec->MineDropNumber == minelayercorvettestatics->NumMinesInSide*minelayercorvettestatics->NumMinesInSide)
    {
        if(spec->mineforminfo != NULL)
        {
            spec->mineforminfo->FULL = TRUE;
            spec->mineforminfo = NULL;
        }
        spec->mineaistate=MINE_DROP_ATTACK;
        spec->MiningStatus = DONE_WAIT;
        spec->MineDropNumber = 0;
        return(TRUE);                               //finished Wall
    }

    return(FALSE);
}
void GenericDefenderAttack(Ship *ship,SpaceObjRotImpTarg *target,real32 maxdist)
{
    ShipStaticInfo *shipstaticinfo = (ShipStaticInfo *)ship->staticinfo;
    GenericDefenderStatics *defenderstat = (GenericDefenderStatics *)shipstaticinfo->custstatinfo;
    real32 newrange;
    //newrange = maxdist - defenderstat->gunRange;
    //newrange = defenderstat->gunRange - newrange;
    //newrange = defenderstat->gunRange - maxdist + defenderstat->gunRange;
    //could do check if maxdist == gunRange, then don't do calcs, just use
    //max dist

    vector trajectory;
    real32 dist;
    real32 range;
    real32 temp;
    real32 rightvelocity;
    vector right;

    newrange = (defenderstat->gunRange[ship->tacticstype]*2) - maxdist;
    if(newrange < 0.0f)
        newrange = defenderstat->tooCloseRange[ship->tacticstype] + 100.0f;
    else if(newrange > defenderstat->gunRange[ship->tacticstype])
    {
        newrange = defenderstat->gunRange[ship->tacticstype];
    }

    switch (ship->aistateattack)
    {
        case 0:
            ship->aistateattack = DEFENDER_APPROACH;
            // fall through to DEFENDER_APPROACH

        case DEFENDER_APPROACH:
            aishipGetTrajectory(ship,target,&trajectory);
            dist = fsqrt(vecMagnitudeSquared(trajectory));
            range = RangeToTargetGivenDist(ship,target,dist);
            if (range > newrange)
            {
                aishipFlyToShipAvoidingObjsWithVel(ship,target,AISHIP_FastAsPossible|AISHIP_PointInDirectionFlying,0.0f,&target->posinfo.velocity);
                break;
            }
#ifdef DEBUG_DEFENDER
            dbgMessagef("\n%x Changing to circle",ship);
#endif
            ship->aistateattack = DEFENDER_CIRCLE;
            goto circleAlreadyCalculatedTrajectory;

        case DEFENDER_CIRCLE:
            aishipGetTrajectory(ship,target,&trajectory);
            dist = fsqrt(vecMagnitudeSquared(trajectory));
            range = RangeToTargetGivenDist(ship,target,dist);
            if (range > newrange)
            {
#ifdef DEBUG_DEFENDER
            dbgMessagef("\n%x Changing back to approach",ship);
#endif
                ship->aistateattack = DEFENDER_APPROACH;
                break;
            }
circleAlreadyCalculatedTrajectory:

            vecDivideByScalar(trajectory,dist,temp);

            aitrackHeading(ship,&trajectory,FLYSHIP_ATTACKACCURACY);

            matGetVectFromMatrixCol2(right,ship->rotinfo.coordsys);
            rightvelocity = vecDotProduct(right,ship->posinfo.velocity);

            if (rightvelocity < defenderstat->CIRCLE_RIGHT_VELOCITY)
            {
                physApplyForceToObj((SpaceObj *)ship,ship->nonstatvars.thruststrength[TRANS_RIGHT]*defenderstat->CIRCLE_RIGHT_THRUST,TRANS_RIGHT);
            }

            if (range < defenderstat->tooCloseRange[ship->tacticstype])
            {
                aitrackZeroForwardVelocity(ship);
            }

            if (ship->attackvars.multipleAttackTargets)
            {
                gunShootGunsAtMultipleTargets(ship);
            }
            else
            {
                gunShootGunsAtTarget(ship,target,range,&trajectory);
            }

            break;

        default:
            dbgAssert(FALSE);
            break;
    }

//    attackStraightForward(ship,target,newrange,defenderstat->tooCloseRange[ship->tacticstype]);
}
void P2MultiBeamFrigateAttackDoAttack(Ship *ship,SpaceObjRotImpTarg *target,real32 maxdist,bool PassiveAttack)

{
    ShipStaticInfo *shipstaticinfo = (ShipStaticInfo *)ship->staticinfo;

    P2MultiBeamFrigateStatics *frigstat = (P2MultiBeamFrigateStatics *)shipstaticinfo->custstatinfo;
    P2MultiBeamFrigateSpec    *spec     = (P2MultiBeamFrigateSpec *)ship->ShipSpecifics;

    vector trajectory;
    vector shipRightVec;
    real32 range;

        spec->aiattacklast = universe.totaltimeelapsed;
    ship->autostabilizeship = FALSE;

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

    if (range > frigstat->MultiBeamRange[ship->tacticstype])
    {
        //not in range
        if(!PassiveAttack)
        {
            //do aiship fly to stuff here

            //if not in range...fly to the ship
            //else track zero velocity
                aishipFlyToShipAvoidingObjs(ship,target,AISHIP_PointInDirectionFlying + AISHIP_CarTurn,0.0f);
        }
        return;
    }

    //we are in range

    vecNormalize(&trajectory);
    if(!PassiveAttack)
	{
		aitrackZeroVelocity(ship);
	}
    matGetVectFromMatrixCol2(shipRightVec,ship->rotinfo.coordsys);

    aitrackHeadingAndUp(ship,&trajectory,&shipRightVec,0.9999f);

    
	if(vecMagnitudeSquared(ship->rotinfo.rotspeed) > frigstat->AttackRotationSpeed)
    {
		if(aitrackHeadingWithFlags(ship,&trajectory,0.99f,AITRACKHEADING_IGNOREUPVEC|AITRACK_DONT_ZERO_ME))
		{
			//rotation speed reached
			//lets fire guns if we can
			P2MultiBeamFrigateFire(ship,target);
		}
    }

/*  OLD SCHOOL CODE  */

    /*
    switch (ship->aistateattack)
    {
        case STATE_INIT:
            // deliberatly fall through to state_approach
//            spec->steady = FALSE;
            ship->aistateattack=STATE_APPROACH;
        case STATE_APPROACH:
#ifdef DEBUG_FRIGATEATTACK
            dbgMessagef("\nShip %x STATE_APPROACH", (udword)ship);
#endif
            if (spec->spining)
            {
                ship->aistateattack = STATE_SPINDOWN;
                break;
            }

            aishipGetTrajectory(ship, target, &trajectory);

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

            if (range < frigstat->MultiBeamRange[ship->tacticstype] || PassiveAttack)
            {
                temp = trajectory;
                temp.z+=5;
                temp.y+=5;
                temp.x+=5;

                //vecCrossProduct(heading,trajectory,temp);

                //vecNormalize(&heading);
                vecNormalize(&trajectory);

				if(!PassiveAttack)
				{
					aitrackZeroVelocity(ship);
				}


                if (aitrackHeadingWithFlags(ship,&trajectory,0.99f,AITRACKHEADING_IGNOREUPVEC))
                {
                    ship->aistateattack = STATE_SPINUP;
                    //get up vector
                    matGetVectFromMatrixCol1(temp,ship->rotinfo.coordsys);
                    aitrackForceHeading(ship,&trajectory,&temp);
                }
            }
            else
            {
				aishipFlyToShipAvoidingObjs(ship,target,AISHIP_PointInDirectionFlying + AISHIP_CarTurn,0.0f);
			}
            break;
        case STATE_SPINUP:
#ifdef DEBUG_FRIGATEATTACK
            dbgMessagef("\nShip %x STATE_SPINUP", (udword)ship);
#endif
            desiredrotspeed = frigstat->AttackRotationSpeed;

			if(!PassiveAttack)
			{
				aitrackZeroVelocity(ship);
			}
            aitrackHeadingAndUp(ship,&heading,&shipRightVec,0.99f);

			if (aitrackRotationSpeed(ship,desiredrotspeed,ROT_ABOUTZCCW))
            {
                ship->aistateattack = STATE_FIRE;
                spec->spining = TRUE;
                spec->aifirestarttime = universe.totaltimeelapsed + frigstat->BeamFireTime;
            }

            break;
        case STATE_FIRE:
#ifdef DEBUG_FRIGATEATTACK
            dbgMessagef("\nShip %x STATE_FIRE", (udword)ship);
#endif
            shipstaticinfo->custshipheader.CustShipFire(ship, target);

            if(!PassiveAttack)
			{
				aitrackZeroVelocity(ship);
			}
			aishipGetTrajectory(ship,target,&trajectory);

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

            if (range > frigstat->MultiBeamRange[ship->tacticstype])
                ship->aistateattack = STATE_INIT;

            temp = trajectory;
            temp.z+=5;
            temp.y+=5;
            temp.x+=5;

            vecCrossProduct(heading,trajectory,temp);

            vecNormalize(&heading);
            vecNormalize(&trajectory);

            //if (aitrackHeadingWithFlags(ship,&heading,0.99f,AITRACKHEADING_IGNOREUPVEC))
          //  {
        //        ship->aistateattack = STATE_INIT;
      //      }
            desiredrotspeed = frigstat->AttackRotationSpeed;
            aitrackRotationSpeed(ship,desiredrotspeed,ROT_ABOUTZCCW);

			if(universe.totaltimeelapsed > spec->aifirestarttime)
			{
                //fire time up!  start spindown
				ship->aistateattack = STATE_SPINDOWN;
				spec->aifirestarttime = universe.totaltimeelapsed + frigstat->fireDownTime;
			}
            break;
        case STATE_SPINDOWN:
#ifdef DEBUG_FRIGATEATTACK
            dbgMessagef("\nShip %x STATE_SPINDOWN", (udword)ship);
#endif
            desiredrotspeed = 0;

            if(!PassiveAttack)
			{
				aitrackZeroVelocity(ship);
			}
			if (aitrackRotationSpeed(ship,desiredrotspeed,ROT_ABOUTZCCW) &&
				universe.totaltimeelapsed > spec->aifirestarttime)
            {
                ship->aistateattack = STATE_INIT;
                spec->spining = FALSE;
            }
            break;
    }
    */
}