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); }
//fires the bursts for the ship bool doBurstFire(Ship *ship) { HeavyCorvetteSpec *spec = (HeavyCorvetteSpec *)ship->ShipSpecifics; GunInfo *gunInfo = ship->gunInfo; sdword numGuns = gunInfo->numGuns; //Gun *gun; sdword done; vector trajectory,heading; real32 range,one_over_range; SpaceObjRotImpTarg dummyTarg; vecSub(trajectory,spec->burstFireVector,ship->posinfo.position); range = vecMagnitudeSquared(trajectory); range = fsqrt(range); one_over_range = 1.0f/range; vecScalarMultiply(trajectory,trajectory,one_over_range); dummyTarg.objtype = OBJ_ShipType; dummyTarg.posinfo.position = spec->burstFireVector; dummyTarg.collInfo.collPosition = spec->burstFireVector; dummyTarg.currentLOD = ship->currentLOD; dummyTarg.collMyBlob = ship->collMyBlob; vecSet(dummyTarg.posinfo.velocity,0.0f,0.0f,0.0f); //track target even more precisely vecSub(heading,spec->burstFireVector,ship->posinfo.position); vecNormalize(&heading); aitrackHeadingWithFlags(ship,&heading,0.9999f,AITRACKHEADING_IGNOREUPVEC); //set special information that needs to be 'transmitted' //to the code in gunshoot. //fix later spec->bulletLifeTime = range*oneOverburstSpeed; bitSet(ship->specialFlags,SPECIAL_BurstFiring); done = gunShootGunsAtTarget(ship,&dummyTarg,0.0f,&trajectory); bitClear(ship->specialFlags,SPECIAL_BurstFiring); if(done == TRUE) { spec->cooldown = TRUE; spec->burstChargeState2 = burstCoolDownTime; } return done; }
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 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... }
void addMonkeyResearchShipChangePosition(Ship *dockwith, Ship *ship,sdword dockindex) { DockStaticPoint *dockwithstaticpoint; vector coneheadingInWorldCoordSysDockWith,DockWithHeading,destination,DockWithUp,destinationoffset; vector desiredHeading,desiredUp,conepositionInWorldCoordSysDockWith,tmpvec; real32 theta; matrix rotmatrix,tmpmat; ResearchShipStatics *resstatics; resstatics = (ResearchShipStatics *) ((ShipStaticInfo *)(ship->staticinfo))->custstatinfo; dbgAssertOrIgnore(dockwith != NULL); //if we're calling this there should be another reserach station available somewhere if(ship->shiprace == R1) { dockwithstaticpoint = &dockwith->staticinfo->dockStaticInfo->dockstaticpoints[dockindex]; matMultiplyMatByVec(&coneheadingInWorldCoordSysDockWith,&dockwith->rotinfo.coordsys,&dockwithstaticpoint->conenormal); matGetVectFromMatrixCol3(DockWithHeading,dockwith->rotinfo.coordsys) destinationoffset.x = coneheadingInWorldCoordSysDockWith.x*resstatics->R1final_dock_distance; destinationoffset.y = coneheadingInWorldCoordSysDockWith.y*resstatics->R1final_dock_distance; destinationoffset.z = coneheadingInWorldCoordSysDockWith.z*resstatics->R1final_dock_distance; vecAdd(destination,dockwith->posinfo.position, destinationoffset); if(((ResearchShipSpec *)ship->ShipSpecifics)->pie_plate_num == 0) { //ship is docking on'a'top so add upwards factor matGetVectFromMatrixCol1(DockWithUp,dockwith->rotinfo.coordsys); vecScalarMultiply(DockWithUp,DockWithUp,resstatics->R1VerticalDockDistance); vecAdd(destination,destination,DockWithUp); } theta = DEG_TO_RAD(60); matMakeRotAboutX(&rotmatrix,(real32) cos(theta),(real32) sin(theta)); matMultiplyMatByMat(&tmpmat, &dockwith->rotinfo.coordsys, &rotmatrix); //share a lot of these things...later... ship->rotinfo.coordsys = tmpmat; ship->posinfo.position = destination; } else { //r2 positioning dockwithstaticpoint = &dockwith->staticinfo->dockStaticInfo->dockstaticpoints[dockindex]; matMultiplyMatByVec(&coneheadingInWorldCoordSysDockWith,&dockwith->rotinfo.coordsys,&dockwithstaticpoint->conenormal); matMultiplyMatByVec(&conepositionInWorldCoordSysDockWith,&dockwith->rotinfo.coordsys,&dockwithstaticpoint->position); vecAddTo(conepositionInWorldCoordSysDockWith,dockwith->posinfo.position); matGetVectFromMatrixCol3(DockWithHeading,dockwith->rotinfo.coordsys) destinationoffset.x = coneheadingInWorldCoordSysDockWith.x*resstatics->R2DockFinalDistance; destinationoffset.y = coneheadingInWorldCoordSysDockWith.y*resstatics->R2DockFinalDistance; destinationoffset.z = coneheadingInWorldCoordSysDockWith.z*resstatics->R2DockFinalDistance; vecAdd(destination,conepositionInWorldCoordSysDockWith, destinationoffset); desiredHeading = coneheadingInWorldCoordSysDockWith; if(dockindex == 0) { matGetVectFromMatrixCol3(desiredUp,dockwith->rotinfo.coordsys); } else if(dockindex == 1) { matGetVectFromMatrixCol3(desiredUp,dockwith->rotinfo.coordsys); } else if(dockindex == 2) { desiredUp = DockWithHeading; } else if(dockindex == 3) { theta = DEG_TO_RAD(60); matMakeRotAboutZ(&rotmatrix,(real32) cos(theta),(real32) sin(theta)); matMultiplyMatByMat(&tmpmat, &dockwith->rotinfo.coordsys, &rotmatrix); matGetVectFromMatrixCol1(desiredUp,tmpmat); } else if(dockindex == 4) { destinationoffset.x = coneheadingInWorldCoordSysDockWith.x*100; destinationoffset.y = coneheadingInWorldCoordSysDockWith.y*100; destinationoffset.z = coneheadingInWorldCoordSysDockWith.z*100; vecAdd(destination,conepositionInWorldCoordSysDockWith, destinationoffset); matGetVectFromMatrixCol1(desiredUp,dockwith->rotinfo.coordsys); vecScalarMultiply(desiredHeading,desiredHeading,-1.0f); } else { dbgAssertOrIgnore(FALSE); //shouldget here. } vecNormalize(&desiredUp); matPutVectIntoMatrixCol1(desiredUp,ship->rotinfo.coordsys); vecCrossProduct(tmpvec,desiredHeading,desiredUp); matPutVectIntoMatrixCol2(tmpvec,ship->rotinfo.coordsys); matPutVectIntoMatrixCol3(desiredHeading,ship->rotinfo.coordsys); ship->posinfo.position = destination; ship->posinfo.velocity.x = 0.0f; ship->posinfo.velocity.y = 0.0f; ship->posinfo.velocity.z = 0.0f; } }
void ResearchShipHouseKeep(Ship *ship) { ResearchShipSpec *spec = (ResearchShipSpec *)ship->ShipSpecifics; SelectCommand selection; vector up,destination,desiredheading,newup; vector univup = {0.0f,0.0f,1.0f}; bool InParadeandMoving = FALSE; matrix rot_matrix,tmpmat,rotmat; real32 radangle; ResearchShipStatics *researchshipstatics; researchshipstatics = (ResearchShipStatics *) ((ShipStaticInfo *)(ship->staticinfo))->custstatinfo; if(bitTest(ship->specialFlags,SPECIAL_StopForResearchDocking)) { vecScalarMultiply(ship->posinfo.velocity,ship->posinfo.velocity,0.94); vecScalarMultiply(ship->rotinfo.rotspeed,ship->rotinfo.rotspeed,0.94); bitSet(ship->dontapplyforceever,1); bitSet(ship->dontrotateever,1); } else { bitClear(ship->dontapplyforceever,1); bitClear(ship->dontrotateever,1); } if(ship->flags & SOF_Slaveable) { if(ship->slaveinfo->flags & SF_MASTER) { CommandToDo *command = getShipAndItsCommand(&universe.mainCommandLayer,ship); if(command != NULL) { //ship may be in parade... if(command->ordertype.order == COMMAND_MILITARY_PARADE) { //ship is in parade CommandToDo *ashipCom = getShipAndItsCommand(&universe.mainCommandLayer,command->militaryParade->aroundShip); if(ashipCom != NULL) { //probably shouldn't be null regardless..should be equal to command..but ohwell if(ashipCom->ordertype.order == COMMAND_MOVE || ashipCom->ordertype.order == COMMAND_ATTACK || ashipCom->ordertype.order == COMMAND_SPECIAL || ashipCom->ordertype.order == COMMAND_MP_HYPERSPACING) { InParadeandMoving = TRUE; spec->rotate_state = ROTATE_WAIT; } } //in parade if(!InParadeandMoving) { if(bitTest(ship->specialFlags,SPECIAL_ParadeNeedTomoveCloser)) { InParadeandMoving = TRUE; spec->rotate_state = ROTATE_WAIT; } } } } } } if(ship->flags & SOF_Slaveable) { //ship is slaveable bitSet(ship->flags,SOF_DontDrawTrails); ship->autostabilizeship = FALSE; // never have univupdate autostabilize research ships if(ship->slaveinfo->flags & SF_MASTER) { //ship is a master if(!InParadeandMoving) { if(ship->shiprace == R1) { //ship is a race 1 MASTER research ship... //i.e. it controls the motion switch(spec->rotate_state) { case ANGLE_ESTABLISH: //establishes the angle at which the station is supposed to rotate at break; case ROTATE_WAIT: //wait to rotate if(ship->slaveinfo->slaves.num >= 5) { //correct # of ships... if(!ship_is_moving(ship)) { if(!spec->prepshipforanother) { //no ships are coming to dock //do up vector tracking! //Later Calculate this vector ONCE at code start up...Let Daly do it //and get as a static value radangle = DEG_TO_RAD(researchshipstatics->RotationAngle); matMakeRotAboutX(&rotmat,(real32) cos(radangle),(real32) sin(radangle)); matMultiplyMatByVec(&newup, &rotmat, &univup); //matGetVectFromMatrixCol3(desiredHeading,ship->rotinfo.coordsys); if(aitrackHeadingWithFlags(ship,&newup,0.96f,AITRACKHEADING_IGNOREUPVEC)) { spec->rotate_state = ROTATE_DO; getRotatePoint(ship, &spec->rotate_point,&spec->rotate_distance); } } } if(!spec->have_removed_from_parade) { spec->have_removed_from_parade = TRUE; selection.numShips = 1; selection.ShipPtr[0] = ship; //RemoveShipsFromDoingStuff(&universe.mainCommandLayer,&selection); //clHalt(&universe.mainCommandLayer,&selection); } } break; case ROTATE_STOP: case ROTATE_STOP_QUICK: case ROTATE_DO: ship->posinfo.isMoving = ISMOVING_MOVING | ISMOVING_ROTATING; make_all_slaves_moving(ship); if(ship->slaveinfo->slaves.num < 5) { //don't rotate anymore because slaves dropped below threhold for whatever reasons! spec->rotate_state = ROTATE_STOP; break; } if(spec->prepshipforanother) { //need to prep ship for a docking ship.. spec->rotate_state = ROTATE_STOP; } else if(ship_is_moving(ship)) { //ship is being moved spec->rotate_state = ROTATE_STOP_QUICK; } else { spec->rotate_state = ROTATE_DO; } //matGetVectFromMatrixCol3(heading,ship->rotinfo.coordsys); matGetVectFromMatrixCol1(up,ship->rotinfo.coordsys); //vecScalarMultiply(rotate_point, heading, -250.0f); //vecAdd(rotate_point,rotate_point, ship->posinfo.position); switch(spec->rotate_state) { case ROTATE_DO: if(spec->theta >= researchshipstatics->max_rotate) spec->theta = researchshipstatics->max_rotate; else spec->theta += researchshipstatics->rotate_acelleration; break; case ROTATE_STOP_QUICK: spec->theta *= researchshipstatics->rotate_slow; spec->theta *= researchshipstatics->rotate_slow; case ROTATE_STOP: if(spec->theta <= 0.00001f) { spec->theta = 0.0f; spec->rotate_state = ROTATE_WAIT; break; } else spec->theta *= researchshipstatics->rotate_slow; break; default: dbgAssertOrIgnore(FALSE); break; } matMakeRotAboutX(&rot_matrix,(real32) cos(spec->theta),(real32) sin(spec->theta)); //matMultiplyMatByMat(&tmpmat, &rot_matrix, &ship->rotinfo.coordsys); matMultiplyMatByMat(&tmpmat, &ship->rotinfo.coordsys, &rot_matrix); //vecSub(tmpvec, ship->posinfo.position, spec->rotate_point); //dist = vecMagnitudeSquared(tmpvec); //dist = fsqrt(dist); matGetVectFromMatrixCol3(desiredheading,tmpmat); vecScalarMultiply(destination, desiredheading, spec->rotate_distance); //old was dist vecAdd(destination,destination,spec->rotate_point); ship->posinfo.position = destination; ship->rotinfo.coordsys = tmpmat; univUpdateObjRotInfo((SpaceObjRot *)ship); break; default: dbgMessagef("Shouldn't Get Here...unknown Research Ship Rotate State"); dbgAssertOrIgnore(FALSE); break; } } else { //Ship is an R2 Master...so rotate differently switch(spec->rotate_state) { case ANGLE_ESTABLISH: break; case ROTATE_WAIT: //wait to rotate if(ship->slaveinfo->slaves.num >= 3) { //correct # of ships... if(!spec->prepshipforanother && !ship_is_moving(ship)) { //no ships are coming to dock radangle = DEG_TO_RAD(researchshipstatics->RotationAngle); matMakeRotAboutX(&rotmat,(real32) cos(radangle),(real32) sin(radangle)); matMultiplyMatByVec(&newup, &rotmat, &univup); if(aitrackHeadingWithFlags(ship,&newup,0.96f,AITRACKHEADING_IGNOREUPVEC)) { spec->rotate_state = ROTATE_DO; } } else { vecSet(ship->rotinfo.rotspeed,0.0f,0.0f,0.0f); vecSet(ship->rotinfo.torque,0.0f,0.0f,0.0f); } } if(ship->slaveinfo->slaves.num >= 1) { //correct # of ships... if(!spec->have_removed_from_parade) { spec->have_removed_from_parade = TRUE; selection.numShips = 1; selection.ShipPtr[0] = ship; //RemoveShipsFromDoingStuff(&universe.mainCommandLayer,&selection); //clHalt(&universe.mainCommandLayer,&selection); } } break; case ROTATE_STOP: case ROTATE_STOP_QUICK: case ROTATE_DO: ship->posinfo.isMoving = ISMOVING_MOVING | ISMOVING_ROTATING; make_all_slaves_moving(ship); if(ship->slaveinfo->slaves.num < 3) { //don't rotate anymore because slaves dropped below threhold for whatever reasons! spec->rotate_state = ROTATE_STOP; break; } if(spec->prepshipforanother) { //need to prep ship for a docking ship.. spec->rotate_state = ROTATE_STOP; } if(ship_is_moving(ship)) { //ship is being moved spec->rotate_state = ROTATE_STOP_QUICK; } switch(spec->rotate_state) { case ROTATE_DO: if(spec->theta >= researchshipstatics->max_rotate) spec->theta = researchshipstatics->max_rotate; else spec->theta += researchshipstatics->rotate_acelleration; break; case ROTATE_STOP_QUICK: spec->theta *= researchshipstatics->rotate_slow; spec->theta *= researchshipstatics->rotate_slow; case ROTATE_STOP: if(spec->theta <= 0.00001f) { spec->theta = 0.0f; spec->rotate_state = ROTATE_WAIT; break; } else spec->theta *= researchshipstatics->rotate_slow; break; default: dbgAssertOrIgnore(FALSE); break; } matMakeRotAboutZ(&rot_matrix,(real32) cos(spec->theta),(real32) sin(spec->theta)); tmpmat = ship->rotinfo.coordsys; matMultiplyMatByMat(&ship->rotinfo.coordsys,&tmpmat,&rot_matrix); univUpdateObjRotInfo((SpaceObjRot *)ship); break; default: dbgMessagef("Shouldn't Get Here...unknown Research Ship Rotate State"); dbgAssertOrIgnore(FALSE); break; } } } } else { vecScalarMultiply(ship->posinfo.velocity,ship->posinfo.velocity, 0.0f); } } }
bool HeavyCorvetteSpecialTarget(Ship *ship, void *custom) { HeavyCorvetteSpec *spec = (HeavyCorvetteSpec *)ship->ShipSpecifics; SelectAnyCommand *targets = (SelectAnyCommand *)custom; real32 tempreal; vector Av; sdword i,flag; if(spec->cooldown) { aitrackSteadyShip(ship); return FALSE; } if (targets->numTargets == 0) { return TRUE; } switch(spec->burstState) { case BURST_Begin: //get average position of targets vecSet(Av,0.0f,0.0f,0.0f); for(i=0;i<targets->numTargets;i++) { vecAddTo(Av,targets->TargetPtr[i]->collInfo.collPosition); } tempreal = 1.0f/((real32)i); vecScalarMultiply(spec->burstFireVector,Av,tempreal); /////////////////////////////// /////burst attack speech event! //event num: COMM_HVette_BurstAttack //use battle chatter if(ship->playerowner->playerIndex == universe.curPlayerIndex) { if(ship->playerowner->playerIndex == universe.curPlayerIndex) { if (battleCanChatterAtThisTime(BCE_COMM_HVette_BurstAttack, ship)) { battleChatterAttempt(SOUND_EVENT_DEFAULT, BCE_COMM_HVette_BurstAttack, ship, SOUND_EVENT_DEFAULT); } } } /////////////////////////////// spec->burstState=BURST_FlyToFirePoint; break; case BURST_FlyToFirePoint: flag = 0; if(doBurstCharging(ship)) { //ship is fully charged flag = 1; } if(flytoBurstPosition(ship)) { //ship is in position fire if(flag == 1) { spec->burstState=BURST_Fire; } } break; case BURST_Fire: if(doBurstFire(ship)) { spec->burstState = BURST_Begin; dbgMessagef("Firing Burst Fire."); } break; default: dbgFatalf(DBG_Loc,"\nUnknown BurstState %d for shiptype %d.",spec->burstState,ship->shiptype); } //perform burst attack AI here... return FALSE; }