bool ship_is_moving(Ship *ship) { CommandToDo *commy = getShipAndItsCommand(&universe.mainCommandLayer,ship); if(commy != NULL) { if(commy->ordertype.order == COMMAND_MOVE) { return TRUE; } } return FALSE; /* if(isBetweenInclusive(ship->posinfo.velocity.x,NOTMOVINGNEG,NOTMOVINGPOS)) { if(isBetweenInclusive(ship->posinfo.velocity.y,NOTMOVINGNEG,NOTMOVINGPOS)) { if(isBetweenInclusive(ship->posinfo.velocity.z,NOTMOVINGNEG,NOTMOVINGPOS)) { return(FALSE); } } } return(TRUE); */ }
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); } } }
void ResearchShipDied(Ship *ship) { ResearchShipSpec *spec = (ResearchShipSpec *)ship->ShipSpecifics; Node *shipnode = universe.ShipList.head; Ship *obj; MaxSelection selection; //need to slow down/stop first research ship and turn it into a new master! if(ship->dockvars.reserveddocking != -1) { sdword dockpointindex; CommandToDo *command = getShipAndItsCommand(&universe.mainCommandLayer,ship); if(command != NULL) { if(command->ordertype.order == COMMAND_DOCK) { if(command->dock.dockType != DOCK_FOR_RETIRE) { dockpointindex = ship->dockvars.dockstaticpoint->dockindex; dbgAssertOrIgnore(ship->dockvars.reserveddocking == (sbyte)dockpointindex); ship->dockvars.reserveddocking = -1; if(spec->dockwith != NULL) { dbgAssertOrIgnore(spec->dockwith->dockInfo->dockpoints[dockpointindex].thisDockBusy > 0); spec->dockwith->dockInfo->dockpoints[dockpointindex].thisDockBusy--; } } } } } if(spec->dockwith != NULL) { if(ship->shiprace == R1) { ((ResearchShipSpec *)spec->dockwith->ShipSpecifics)->seed = TRUE; //set correct seeding ((ResearchShipSpec *)spec->dockwith->ShipSpecifics)->done = FALSE; } else { ((ResearchShipSpec *)spec->dockwith->ShipSpecifics)->seed = TRUE; //set correct seeding ((ResearchShipSpec *)spec->dockwith->ShipSpecifics)->done = FALSE; } } selection.numShips = 0; if(ship->flags & SOF_Slaveable) { //ship is slaved if(ship->slaveinfo->flags & SF_MASTER) { //ship is a master //ship that died is a master! no worries while(shipnode != NULL) { obj = (Ship *) listGetStructOfNode(shipnode); if(obj->shiptype == ResearchShip) { if(obj->playerowner == ship->playerowner) { if(!bitTest(obj->flags,SOF_Slaveable)) { if(obj != ship) { CommandToDo *command = getShipAndItsCommand(&universe.mainCommandLayer,obj); if(command != NULL && command->ordertype.order == COMMAND_DOCK && (command->dock.dockType & DOCK_FOR_RETIRE||command->dock.dockType & DOCK_PERMANENTLY)) { //don't reorder a dock for research } else if(obj->flags & SOF_Dead) { } else if(!bitTest(obj->flags,SOF_Dead)) { //as long as ship isn't considered dead //need better method CleanResearchShip(obj); selection.ShipPtr[selection.numShips] = obj; selection.numShips++; } } } } } shipnode = shipnode->next; } } else { //ship that died isn't a master } } else { while(shipnode != NULL) { obj = (Ship *) listGetStructOfNode(shipnode); if(obj->shiptype == ResearchShip) { if(obj->playerowner == ship->playerowner) { if(obj != ship) { if(((ResearchShipSpec *) obj->ShipSpecifics)->dockordernumber > spec->dockordernumber) { CommandToDo *command = getShipAndItsCommand(&universe.mainCommandLayer,obj); if(command != NULL && command->ordertype.order == COMMAND_DOCK && (command->dock.dockType & DOCK_FOR_RETIRE||command->dock.dockType & DOCK_PERMANENTLY)) { //don't reorder a dock for research } else if(obj->flags & SOF_Dead) { } else { if(obj->dockvars.reserveddocking != -1) { sdword dockpointindex; dockpointindex = obj->dockvars.dockstaticpoint->dockindex; dbgAssertOrIgnore(obj->dockvars.reserveddocking == (sbyte)dockpointindex); obj->dockvars.reserveddocking = -1; //dbgAssertOrIgnore(((ResearchShipSpec *) obj->ShipSpecifics)->dockwith->dockInfo->dockpoints[dockpointindex].thisDockBusy > 0); if (((ResearchShipSpec *) obj->ShipSpecifics)->dockwith) // Bryce did I fix this right by putting in this check dockwith != NULL ((ResearchShipSpec *) obj->ShipSpecifics)->dockwith->dockInfo->dockpoints[dockpointindex].thisDockBusy = 0; } CleanResearchShip(obj); dbgAssertOrIgnore(selection.numShips < COMMAND_MAX_SHIPS); selection.ShipPtr[selection.numShips] = obj; selection.numShips++; //ship->dockInfo->dockpoints[shippointindex].thisDockBusy = 0; //artificially busy point //selection.ShipPtr[selection.numShips] = obj; //selection.numShips++; } } } } } shipnode = shipnode->next; } } if(selection.numShips >= 1) { clDock(&universe.mainCommandLayer, (SelectCommand *)&selection, DOCK_FOR_RESEARCH, NULL); } }
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; }