Stuff::Vector3D Team::calcEscapeVector(MoverPtr mover, float threatRange) { static float distance[100]; static Stuff::Vector3D delta[100]; Stuff::Vector3D escapeVector; escapeVector.Zero(); //------------------------------ // Get the initial delta info... int32_t shortest = 0; int32_t longest = 0; for(size_t i = 0; i < rosterSize; i++) { GameObjectPtr obj = ObjectManager->getByWatchID(roster[i]); if(obj) { float distanceToObj = mover->distanceFrom(obj->getPosition()); if(distanceToObj <= threatRange) { delta[i].Subtract(mover->getPosition(), obj->getPosition()); distance[i] = distanceToObj; if(distance[i] > longest) longest = i; if(distance[i] < shortest) shortest = i; } else distance[i] = -999.0; } else distance[i] = -999.0; } //----------------------------------------------------------------- // Now, find the furthest enemy and scale the deltas accordingly... for(i = 0; i < rosterSize; i++) if(distance[i] >= 0.0) { float scale = distance[longest] / distance[i]; delta[i] *= scale; escapeVector += delta[i]; } //-------------------------------------------------------------------------------- // We don't care about the length, just the direction (we assume you want to go as // FAR as necessary)... escapeVector.Normalize(escapeVector); return(escapeVector); }
long MoverGroup::handleTacticalOrder (TacticalOrder tacOrder, long priority, Stuff::Vector3D* jumpGoalList, bool queueGroupOrder) { if (numMovers == 0) return(NO_ERR); if (queueGroupOrder) tacOrder.pack(NULL, NULL); //bool processOrder = true; bool isJump = false; bool isMove = false; Stuff::Vector3D goalList[MAX_MOVERGROUP_COUNT]; Stuff::Vector3D location = tacOrder.getWayPoint(0); //MoverPtr pointVehicle = getPoint(); if (tacOrder.code == TACTICAL_ORDER_ATTACK_OBJECT) if (tacOrder.attackParams.method == ATTACKMETHOD_DFA) { //------------------------------------------------- // Let's just make it a move/jump order, for now... tacOrder.code = TACTICAL_ORDER_JUMPTO_OBJECT; tacOrder.moveParams.wait = false; tacOrder.moveParams.wayPath.mode[0] = TRAVEL_MODE_SLOW; GameObjectPtr target = ObjectManager->getByWatchID(tacOrder.targetWID); Assert(tacOrder.targetWID != 0, 0, " DFA AttackObject WID is 0 "); if (!target) return(NO_ERR); tacOrder.setWayPoint(0, target->getPosition()); } if (tacOrder.code == TACTICAL_ORDER_JUMPTO_OBJECT) { tacOrder.code = TACTICAL_ORDER_JUMPTO_POINT; GameObjectPtr target = ObjectManager->get(tacOrder.targetWID); Assert(tacOrder.targetWID != 0, 0, " DFA AttackObject WID is 0 "); if (!target) return(NO_ERR); tacOrder.setWayPoint(0, target->getPosition()); } //vector_3d offsetTable[MAX_GROUPMOVE_OFFSETS]; //long numOffsets = 0; switch (tacOrder.code) { case TACTICAL_ORDER_WAIT: break; case TACTICAL_ORDER_MOVETO_POINT: case TACTICAL_ORDER_MOVETO_OBJECT: { Fatal(0, "Need to support jumpGoalList (and goalList) for MOVETO as well in mc2 "); isMove = true; //----------------------------------------------------------- // Sort by distance to destination. Their selectionIndex will // be set to modify this goal... SortListPtr list = Mover::sortList; if (list) { list->clear(false); long moverCount = 0; for (long i = 0; i < numMovers; i++) { MoverPtr mover = getMover(i); Assert(mover != NULL, moverWIDs[i], " MoverGroup.handleTacticalOrder: NULL mover "); if (!mover->isDisabled()) { list->setId(moverCount, i); list->setValue(moverCount, mover->distanceFrom(location)); moverCount++; } } list->sort(false); //-------------------------------- // Let's build the offset table... /* numOffsets = moverCount - 1; if (numOffsets > MAX_GROUPMOVE_OFFSETS) numOffsets = MAX_GROUPMOVE_OFFSETS; long offsetsStart = GroupMoveOffsetsIndex[numOffsets - 1]; for (i = 0; i < numOffsets; i++) offsetTable[i] = relativePositionToPoint(location, GroupMoveOffsets[offsetsStart + i][0], GroupMoveOffsets[offsetsStart + i][1], RELPOS_FLAG_PASSABLE_START); */ //----------------------------------- // Now, calc the order of movement... long curIndex = 1; for (i = 0; i < moverCount; i++) { MoverPtr mover = getMover(list->getId(i)); if (mover->getWatchID() == pointWID) mover->selectionIndex = 0; else mover->selectionIndex = curIndex++; } } } break; case TACTICAL_ORDER_JUMPTO_POINT: case TACTICAL_ORDER_JUMPTO_OBJECT: { //----------------------------------------------------------- // Sort by distance to destination. Their selectionIndex will // be set to modify this goal... isJump = true; //------------------------------------------------------------------------- // We can assume that all movers in this group are jump-capable. Otherwise, // the group wouldn't be allowed to jump by the interface. In addition, // we KNOW that all movers in this group can jump to the selected // goal (of course, they won't due to terrain and crowding)... GameObjectPtr target = ObjectManager->getByWatchID(tacOrder.targetWID); if (jumpGoalList) for (long j = 0; j < numMovers; j++) goalList[j] = jumpGoalList[j]; else calcJumpGoals(tacOrder.getWayPoint(0), goalList, target); for (long i = 0; i < numMovers; i++) { MoverPtr mover = getMover(i); bool canJump = (goalList[i].x > -99000.0); if (canJump) mover->selectionIndex = 0; else mover->selectionIndex = -2; } } break; case TACTICAL_ORDER_TRAVERSE_PATH: case TACTICAL_ORDER_PATROL_PATH: case TACTICAL_ORDER_ESCORT: case TACTICAL_ORDER_FOLLOW: case TACTICAL_ORDER_GUARD: case TACTICAL_ORDER_STOP: case TACTICAL_ORDER_POWERUP: case TACTICAL_ORDER_POWERDOWN: case TACTICAL_ORDER_WAYPOINTS_DONE: case TACTICAL_ORDER_EJECT: case TACTICAL_ORDER_ATTACK_OBJECT: case TACTICAL_ORDER_ATTACK_POINT: case TACTICAL_ORDER_HOLD_FIRE: case TACTICAL_ORDER_WITHDRAW: case TACTICAL_ORDER_CAPTURE: case TACTICAL_ORDER_LOAD_INTO_CARRIER: case TACTICAL_ORDER_REFIT: case TACTICAL_ORDER_RECOVER: case TACTICAL_ORDER_GETFIXED: break; default: { char s[256]; sprintf(s, "Unit::handleTacticalOrder->Bad TacOrder Code (%d)", tacOrder.code); Assert(false, tacOrder.code, s); return(1); } } tacOrder.unitOrder = true; for (long i = 0; i < numMovers; i++) { MoverPtr mover = getMover(i); if (mover && !mover->isDisabled()) { if (mover->selectionIndex == -2) { mover->selectionIndex = -1; continue; } tacOrder.selectionIndex = mover->selectionIndex; if (tacOrder.selectionIndex != -1) { if (isMove) tacOrder.setWayPoint(0, location); else if (isJump) tacOrder.setWayPoint(0, goalList[i]); tacOrder.delayedTime = scenarioTime + (mover->selectionIndex * DelayedOrderTime); } switch (tacOrder.origin) { case ORDER_ORIGIN_PLAYER: if (queueGroupOrder) mover->getPilot()->addQueuedTacOrder(tacOrder); else { if (mover->getPilot()->getNumTacOrdersQueued()) //This is a hack to simply trigger the execution of //the queued orders. The current order is ignored (and //is simply used for this trigger)... mover->getPilot()->executeTacOrderQueue(); else mover->getPilot()->setPlayerTacOrder(tacOrder); } break; case ORDER_ORIGIN_COMMANDER: mover->getPilot()->setGeneralTacOrder(tacOrder); break; case ORDER_ORIGIN_SELF: mover->getPilot()->setAlarmTacOrder(tacOrder, priority); break; } mover->selectionIndex = -1; } } return(NO_ERR); }