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); }
void startRepairEffect(Ship *ship,SpaceObjRotImpTarg *target,vector *trajectory,real32 distance) { ShipStaticInfo *shipstatic = (ShipStaticInfo *)ship->staticinfo; RepairNozzleStatic *repnozzlestatic = shipstatic->repairNozzleStatic; //TURN ON EFFECT HERE // //Use ship->rceffect, since ship isn't a resource collector, //the pointer isn't being used etglod *etgLOD = etgSpecialPurposeEffectTable[EGT_REPAIR_BEAM]; etgeffectstatic *stat; sdword LOD; udword intLength; udword intWidth; matrix coordsys; real32 targetRadius = target->staticinfo->staticheader.staticCollInfo.collspheresize; vector repairBeamPosition; matMultiplyMatByVec(&repairBeamPosition,&ship->rotinfo.coordsys,&repnozzlestatic->position); matCreateCoordSysFromHeading(&coordsys,trajectory); intLength = TreatAsUdword(distance); intWidth = TreatAsUdword(targetRadius); vecAddTo(repairBeamPosition,ship->posinfo.position); //create an effect for bullet, if applicable if (etgLOD != NULL) { LOD = ship->currentLOD; if (LOD >= etgLOD->nLevels) { stat = NULL; } else { stat = etgLOD->level[LOD]; } } else { stat = NULL; } #if ETG_DISABLEABLE if (stat != NULL && etgEffectsEnabled && !etgFrequencyExceeded(stat)) #else if (stat != NULL && !etgFrequencyExceeded(stat)) #endif { ship->rceffect = etgEffectCreate(stat, ship, &repairBeamPosition, &ship->posinfo.velocity, &coordsys, 1.0f, EAF_Velocity | EAF_NLips, 2, intLength, intWidth); } else { ship->rceffect = NULL; //play no effect } }
/*----------------------------------------------------------------------------- Name : navLightBillboardEnable Description : setup modelview matrix for rendering billboarded sprites Inputs : s - ship to obtain coordinate system from nls - NAV Light static info Outputs : Return : ----------------------------------------------------------------------------*/ void navLightBillboardEnable(Ship *s, NAVLightStatic *nls) { vector src, dst; //object -> worldspace src = nls->position; matMultiplyMatByVec(&dst, &s->rotinfo.coordsys, &src); vecAddTo(dst, s->posinfo.position); //setup billboarding glPushMatrix(); rndBillboardEnable(&dst); glDisable(GL_CULL_FACE); }
bool madLinkInGetDoorInfo(Ship *ship, matrix *coordsys, vector *position) { sdword madIndex, gunIndex; vector positiont; matrix coordsyst; madIndex = madBindingIndexFindByName(ship->staticinfo->madStatic->header, "Hangardoor"); gunIndex = madGunBindingIndexFindByName(ship->staticinfo, "Hangardoor"); dbgAssertOrIgnore(madIndex != -1); dbgAssertOrIgnore(gunIndex != -1); madAnimBindingMatrix(&coordsyst,&positiont,ship,gunIndex, madIndex); matMultiplyMatByMat(coordsys,&ship->rotinfo.coordsys,&coordsyst); //matMultiplyVecByMat(position,&positionSS,&ship->rotinfo.coordsys); matMultiplyMatByVec(position,&ship->rotinfo.coordsys,&positiont); vecAddTo(*position,ship->posinfo.position); return TRUE; }
//to OPTIMIZE THIS: ONLY CALCULATE SLAVED SHIPS AVERAGE POSITION when slaves are added! void toFakeOneShip(Ship *ship, vector *oldpos, real32 *oldradius) { Node *slavenode; Ship *slave; vector newcenter; real32 newradius,tempreal; if(!(ship->flags & SOF_Slaveable)) return; dbgAssertOrIgnore(ship->slaveinfo->flags & SF_MASTER); //must be a master slavenode = ship->slaveinfo->slaves.head; newcenter = ship->collInfo.collPosition; while(slavenode != NULL) { //add all slaves positions together slave = (Ship *) listGetStructOfNode(slavenode); vecAddTo(newcenter,slave->collInfo.collPosition); slavenode = slavenode->next; } vecDivideByScalar(newcenter,(float) ship->slaveinfo->slaves.num+1,tempreal); //take average of slavemaster position if(ship->shiprace == R1) { newradius = ship->staticinfo->staticheader.staticCollInfo.approxcollspheresize*2.5f; } else { //Must be R2 newradius = (float) ship->slaveinfo->slaves.num+1; newradius = ship->staticinfo->staticheader.staticCollInfo.approxcollspheresize*(newradius/4.0f)*1.25f; } *oldpos = ship->collInfo.collPosition; *oldradius = ship->staticinfo->staticheader.staticCollInfo.approxcollspheresize; ship->staticinfo->staticheader.staticCollInfo.approxcollspheresize = newradius; ship->collInfo.collPosition = newcenter; }
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 DefenseFighterHouseKeep(Ship *ship) { DefenseFighterSpec *spec = (DefenseFighterSpec *)ship->ShipSpecifics; DefenseFighterStatics *defensefighterstatics; Node *bulletnode; Node *tempnode; DefenseStruct *defensestruct; vector seperationvector; vector tempvec,rot_vector; GunStatic *gunstatic; Gun *gun; vector positionInWorldCoordSys; gun = &ship->gunInfo->guns[0]; gunstatic = gun->gunstatic; defensefighterstatics = (DefenseFighterStatics *) ((ShipStaticInfo *)(ship->staticinfo))->custstatinfo; bulletnode = spec->DefenseList.head; while (bulletnode != NULL) { //as long as theres a bullet to deal with defensestruct = (DefenseStruct *)listGetStructOfNode(bulletnode); /* if (defensestruct->bullet) dbgMessagef("DS: %d %f %d %f %d %d", universe.univUpdateCounter, defensestruct->bullet->collOptimizeDist, defensestruct->laser ? 1:0, defensestruct->CoolDownTime, defensestruct->CoolDown ? 1:0, defensestruct->LaserDead ? 1:0); else dbgMessagef("DS: %d N %d %f %d %d", universe.univUpdateCounter, defensestruct->laser ? 1:0, defensestruct->CoolDownTime, defensestruct->CoolDown ? 1:0, defensestruct->LaserDead ? 1:0);*/ if(!defensestruct->CoolDown) { //laser cannon isn't cooling down, so continue tracking if (defensestruct->bullet == NULL || defensestruct->bullet->damage <= 0) { //bullet is already dead...don't kill it again defensestruct->bullet = NULL; //destroy pointer... if (defensestruct->laser != NULL) { defensestruct->laser->timelived =10000.0f; //kill laser } defensestruct->LaserDead = TRUE; //set killed flag defensestruct->laser=NULL; defensestruct->CoolDown = TRUE; //begin laser cooldown defensestruct->CoolDownTime = 0.0f; //reset to 0 for cooldown count bulletnode=bulletnode->next; continue; } if((universe.univUpdateCounter & defensefighterstatics->DamageRate) == 0) { // Time to do damage... //Do damage to bullet defensestruct->bullet->damage = (defensestruct->bullet->damage - frandombetween(defensefighterstatics->DamageReductionLow,defensefighterstatics->DamageReductionHigh)); if(defensestruct->bullet->damage <= 0) { //bullet is destroyed DefenseFighterDestroyedABullet(ship, defensestruct->bullet, defensestruct->laser); defensestruct->bullet->damage = 0; //cap at 0; defensestruct->bullet = NULL; //destroy pointer... //dbgMessagef("Defense Fighter Destroyed A Bullet."); if (defensestruct->laser != NULL) { defensestruct->laser->timelived =10000.0f; //kill laser } defensestruct->LaserDead = TRUE; //set killed flag if(defensestruct->laser->effect != NULL) { univRemoveObjFromRenderList((SpaceObj *) defensestruct->laser->effect); } defensestruct->laser=NULL; defensestruct->CoolDown = TRUE; //begin laser cooldown defensestruct->CoolDownTime = 0.0f; //reset to 0 for cooldown count } } if(defensestruct->laser != NULL) { //check if bullet is still in range and infront... if((universe.univUpdateCounter & defensefighterstatics->RangeCheckRate) == 0) { //time to check if in front vecSub(seperationvector, ship->posinfo.position, defensestruct->bullet->posinfo.position); if(vecMagnitudeSquared(seperationvector) > ship->staticinfo->bulletRangeSquared[ship->tacticstype]) { //bullet is out of range defensestruct->laser->timelived =10000.0f; //kill laser defensestruct->LaserDead = TRUE; //set killed flag if(defensestruct->laser->effect != NULL) { univRemoveObjFromRenderList((SpaceObj *) defensestruct->laser->effect); } defensestruct->laser=NULL; //dbgMessagef("Bullet out of range."); bitClear(defensestruct->bullet->SpecialEffectFlag,0x0002); defensestruct->CoolDown = TRUE; //begin laser cooldown defensestruct->bullet = NULL; //set target to NULL so it isn't referenced again! defensestruct->CoolDownTime = 0.0f; //reset to 0 for cooldown count } else if(!defensefighterCheckInFront(ship, defensestruct->bullet)) { //if bullet ISN'T in front defensestruct->laser->timelived =10000.0f; //kill laser defensestruct->LaserDead = TRUE; //set killed flag if(defensestruct->laser->effect != NULL) { univRemoveObjFromRenderList((SpaceObj *) defensestruct->laser->effect); } defensestruct->laser=NULL; //dbgMessagef("Bullet Not infront anymore...stop tracking."); if(defensefighterstatics->MultipleTargettingofSingleBullet) { bitClear(defensestruct->bullet->SpecialEffectFlag,0x0002); } defensestruct->CoolDown = TRUE; //begin laser cooldown defensestruct->bullet = NULL; //set target to NULL so it isn't referenced again! defensestruct->CoolDownTime = 0.0f; //reset to 0 for cooldown count } } } //This code is for the sake of the visual effect which STILL won't work //properly!!! So it is temperary only! if(defensestruct->laser != NULL) { //update bullent info...for visual effect dbgAssertOrIgnore(defensestruct->bullet != NULL); matMultiplyMatByVec(&positionInWorldCoordSys,&ship->rotinfo.coordsys,&gunstatic->position); vecAdd(defensestruct->laser->posinfo.position,positionInWorldCoordSys,ship->posinfo.position); vecSub(defensestruct->laser->lengthvec, defensestruct->bullet->posinfo.position, defensestruct->laser->posinfo.position); // heading tempvec = defensestruct->laser->lengthvec; vecNormalize(&tempvec); //matMultiplyMatByVec(&gunheadingInWorldCoordSys, &ship->rotinfo.coordsys, &tempvec); //laser->bulletheading = gunheadingInWorldCoordSys; defensestruct->laser->bulletheading = tempvec; matCreateCoordSysFromHeading(&defensestruct->laser->rotinfo.coordsys,&tempvec); if(defensestruct->laser->effect != NULL) { //adjust length ((real32 *)defensestruct->laser->effect->variable)[ETG_LengthVariable] = fsqrt(vecMagnitudeSquared(defensestruct->laser->lengthvec)); } } } else { //this laser cannon is cooling, so cool it defensestruct->CoolDownTime += universe.phystimeelapsed; if(defensestruct->CoolDownTime > defensefighterstatics->CoolDownTimePerLaser) { //Laser Terminal has cooled down...so free it up tempnode = bulletnode->next; listDeleteNode(bulletnode); //dbgMessagef("Deleting defense node in CoolDown."); bulletnode = tempnode; continue; } } bulletnode = bulletnode->next; } if (spec->DefenseList.num == 0) { soundEventBurstStop(ship, gun); } //do special rotation if neccessary if(bitTest(ship->dontrotateever,1)) { //matGetVectFromMatrixCol3(rot_vector,ship->rotinfo.coordsys); vecSet(rot_vector,100.0f,0.0f,0.0f); vecAddTo(ship->rotinfo.torque, rot_vector); vecCapVectorSloppy(&ship->rotinfo.rotspeed, defensefighterstatics->max_rot_speed ); spec->rotate_time_counter -= universe.phystimeelapsed; if(spec->rotate_time_counter <= 0.0f) { bitClear(ship->dontrotateever,1); spec->DefenseFighterCanNowRotate = FALSE; } } else if (spec->DefenseFighterCanNowRotate == FALSE) { spec->rotate_time_counter += universe.phystimeelapsed; if(spec->rotate_time_counter >= defensefighterstatics->rotate_recover_time) { spec->DefenseFighterCanNowRotate = TRUE; spec->rotate_time_counter = defensefighterstatics->rotate_time; } } }
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; } }
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; }