//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... }