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; }
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; } */ }