void DDDFrigateAttack(Ship *ship,SpaceObjRotImpTarg *target,real32 maxdist) { ShipStaticInfo *shipstatic = (ShipStaticInfo *)ship->staticinfo; DDDFrigateStatics *dddstatics = (DDDFrigateStatics *)shipstatic->custstatinfo; DDDFrigateSpec *spec = (DDDFrigateSpec *)ship->ShipSpecifics; vector trajectory; real32 range; bool inRange = FALSE; aishipGetTrajectory(ship,target,&trajectory); range = RangeToTarget(ship,target,&trajectory); if (range > dddstatics->attackRange) { // too far away, so fly in aishipFlyToShipAvoidingObjsWithVel(ship,target,AISHIP_FirstPointInDirectionFlying+AISHIP_PointInDirectionFlying+AISHIP_CarTurn+AISHIP_FastAsPossible,0.0f,&target->posinfo.velocity); } else if (range > dddstatics->tooCloseRange) { // about right range aishipFlyToShipAvoidingObjsWithVel(ship,target,AISHIP_FirstPointInDirectionFlying+AISHIP_PointInDirectionFlying+AISHIP_CarTurn+AISHIP_FastAsPossible,0.0f,&target->posinfo.velocity); inRange = TRUE; } else { // too close aitrackZeroVelocity(ship); inRange = TRUE; } if ((inRange) && (spec->DDDstate == DDDSTATE_ALLINSIDE)) { DDDFrigateSpecialActivate(ship); } }
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); } } }
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); }
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); }
bool refuelRepairShips(Ship *ship, SelectAnyCommand *targets,real32 rangetoRefuel) { //remove unwantedships from this selection //optimize by doing only once for this ship SelectCommand selectOne; sdword i; SpaceObjRotImpTarg *target,*targettemp; vector trajectory,curheading; real32 range,dotprod; CommandToDo *targetCommand; //filter target list for unrepairable ships! for(i=0;i<targets->numTargets;) { if(targets->TargetPtr[i]->objtype != OBJ_ShipType) { targets->numTargets--; targets->TargetPtr[i] = targets->TargetPtr[targets->numTargets]; continue; } targetCommand = getShipAndItsCommand(&universe.mainCommandLayer,(Ship *)targets->TargetPtr[i]); if(targetCommand != NULL) { if(targetCommand->ordertype.order == COMMAND_DOCK) { //remove docking ships from the list if(((Ship *)targets->TargetPtr[i])->dockingship != NULL) { //only if in final stages targets->numTargets--; targets->TargetPtr[i] = targets->TargetPtr[targets->numTargets]; continue; } } } //object is a ship if((((Ship *)targets->TargetPtr[i])->staticinfo->shipclass != CLASS_Fighter && ((Ship *)targets->TargetPtr[i])->staticinfo->shipclass != CLASS_Corvette) || ((Ship *)targets->TargetPtr[i])->playerowner != ship->playerowner) { if(ship->staticinfo->repairBeamCapable) { //repair corvette can repair capital ships! //class doesn't matter if(((Ship *)targets->TargetPtr[i])->playerowner == ship->playerowner) { //ship is not a fighter or a corvette, but is ours, so we can fix it! i++; continue; } } targets->numTargets--; targets->TargetPtr[i] = targets->TargetPtr[targets->numTargets]; } else { i++; } } if (targets->numTargets <= 0) { return TRUE; } target = targets->TargetPtr[0]; //need to add //repairBeamCapable // real32 healthPerSecond,CapitalDistanceRepairStart; // real32 CapitalDistanceRepairStart2; if(ship->staticinfo->repairBeamCapable) { //assume target is a ship!!!! //targets might be a capital ship if(((Ship *)target)->staticinfo->shipclass != CLASS_Fighter) { //target is such that it should be BEAM repaired! //so lets fly upto it and ZAP repair it! real32 range1,range2; aishipGetTrajectory(ship,target,&trajectory); range = RangeToTarget(ship,target,&trajectory); vecNormalize(&trajectory); aitrackHeading(ship,&trajectory,0.999f); if(((Ship *)target)->shiptype == Mothership) { range1 = 2*ship->staticinfo->CapitalDistanceRepairStart; range2 = 2*ship->staticinfo->CapitalDistanceRepairStart2; } else { range1 = ship->staticinfo->CapitalDistanceRepairStart; range2 = ship->staticinfo->CapitalDistanceRepairStart2; } //we add 300 to the range checker for a sort of hysterysis! if(range > range1) { aishipFlyToShipAvoidingObjs(ship,target,AISHIP_PointInDirectionFlying + AISHIP_FastAsPossible,0.0f); if(range > range2) { //far enough away to stop the effect and ONLY fly towards ship if(ship->rceffect != NULL) { //turn off ships effect stopRepairEffect(ship); } return FALSE; } } else { aitrackZeroVelocity(ship); } //in range to repair this li'l ship matGetVectFromMatrixCol3(curheading,ship->rotinfo.coordsys); dotprod = vecDotProduct(trajectory,curheading); if(!areAllHealthy(ship,targets)) { if(dotprod > ship->staticinfo->AngleDotProdThreshold) { //within angle of 'repair beam' if(ship->rceffect == NULL) { //turn on effect if we should! startRepairEffect(ship,target,&trajectory,range); } else { //fix up effect ModifyRepairEffect(ship->rceffect,ship,&trajectory,range, target); } target->health+=ship->staticinfo->healthPerSecond*universe.phystimeelapsed; if(((Ship *)target)->health > ((Ship *)target)->staticinfo->maxhealth) { if(ship->rceffect != NULL) { //turn off ships effect stopRepairEffect(ship); } target->health = ((Ship *)target)->staticinfo->maxhealth; //fix this in a bit targettemp = targets->TargetPtr[0]; for(i=0;i<(targets->numTargets-1);i++) { targets->TargetPtr[i]=targets->TargetPtr[i+1]; } targets->TargetPtr[targets->numTargets-1] = targettemp; //if(targets->numTargets <= 0) // return TRUE; //targets->TargetPtr[0] = targets->TargetPtr[targets->numTargets]; return FALSE; } } else { //not pointing at ship, turn off effect and other //needed things! if(ship->rceffect != NULL) { //turn off ships effect stopRepairEffect(ship); } } } else { if(ship->rceffect != NULL) { //turn off ships effect stopRepairEffect(ship); } } return FALSE; } } aishipGetTrajectory(ship,target,&trajectory); aishipFlyToShipAvoidingObjs(ship,target,AISHIP_PointInDirectionFlying + AISHIP_FastAsPossible +AISHIP_FirstPointInDirectionFlying,0.0f); range = RangeToTarget(ship,target,&trajectory); if(range <= rangetoRefuel) { //within repair range selectOne.numShips = 1; selectOne.ShipPtr[0] = (Ship *) target; if(target->objtype == OBJ_ShipType) { ((Ship *)target)->fuel += 300.0f; //??? appropriate ammount? if(((Ship *)target)->fuel > ((Ship *)target)->staticinfo->maxfuel) ((Ship *)target)->fuel = ((Ship *)target)->staticinfo->maxfuel; //"speech event? Switching to Emergency Docking Fuel Supply? //cldock clDock(&universe.mainCommandLayer,&selectOne,DOCK_AT_SPECIFIC_SHIP,ship); } targets->numTargets--; if(targets->numTargets <= 0) return TRUE; targets->TargetPtr[0] = targets->TargetPtr[targets->numTargets]; } return FALSE; }
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; } */ }