12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100 |
- //******************************************************************************************
- //
- // group.cpp - This file contains the MoverGroup Class header
- //
- // MechCOmmander 2
- //
- //---------------------------------------------------------------------------//
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- //===========================================================================//
- #ifndef MCLIB_H
- #include "mclib.h"
- #endif
- #ifndef GROUP_H
- #include "group.h"
- #endif
- #ifndef GAMEOBJ_H
- #include "gameobj.h"
- #endif
- #ifndef MOVER_H
- #include "mover.h"
- #endif
- #ifndef OBJMGR_H
- #include "objmgr.h"
- #endif
- #ifndef GVEHICL_H
- #include "gvehicl.h"
- #endif
- #ifndef UNITDESG_H
- #include "unitdesg.h"
- #endif
- #ifndef TACORDR_H
- #include "tacordr.h"
- #endif
- #ifndef MOVE_H
- #include "move.h"
- #endif
- //---------------------------------------------------------------------------
- extern float DelayedOrderTime;
- extern long tileMulMAPCELL_DIM[MAX_MAP_CELL_WIDTH];
- //#define MAX_GROUPMOVE_OFFSETS 4
- /*
- long GroupMoveOffsetsIndex[MAX_GROUPMOVE_OFFSETS] = {0, 1, 3, 6};
- float GroupMoveOffsets[10][2] = {
- // 2-member Group
- {180.0, 50.0},
- // 3-member Group
- {-135.0, 50.0},
- {135.0, 50.0},
- // 4-member Group
- {-135.0, 50.0},
- {135.0, 50.0},
- {180.0, 50.0},
- // 5-member Group
- {-135.0, 50.0},
- {135.0, 50.0},
- {180.0, 50.0},
- {180.0, 75.0}
- };
- */
- extern char OverlayIsBridge[NUM_OVERLAY_TYPES];
- extern PriorityQueuePtr openList;
- GoalMapNode* MoverGroup::goalMap = NULL;
- //***************************************************************************
- // MOVERGROUP class
- //***************************************************************************
- void* MoverGroup::operator new (size_t ourSize) {
- void* result = systemHeap->Malloc(ourSize);
- return(result);
- }
- //---------------------------------------------------------------------------
- void MoverGroup::operator delete (void* us) {
- systemHeap->Free(us);
- }
- //---------------------------------------------------------------------------
- void MoverGroup::destroy (void) {
- }
- //---------------------------------------------------------------------------
- bool MoverGroup::add (MoverPtr mover) {
- if (numMovers == MAX_MOVERGROUP_COUNT) {
- Fatal(0, " MoverGroup.add: Group too big ");
- //----------------------------------------
- // Should we choose to remove the fatal...
- return(false);
- }
- moverWIDs[numMovers++] = mover->getWatchID();
- mover->setGroupId(id, true);
- return(true);
- }
- //---------------------------------------------------------------------------
- bool MoverGroup::remove (MoverPtr mover) {
- GameObjectWatchID moverWID = mover->getWatchID();
- if (moverWID == pointWID) {
- disband();
- return(true);
- }
- else {
- for (long i = 0; i < numMovers; i++)
- if (moverWIDs[i] == moverWID) {
- mover->setGroupId(-1, true);
- moverWIDs[i] = moverWIDs[numMovers - 1];
- moverWIDs[numMovers - 1] = 0;
- numMovers--;
- return(true);
- }
- }
- return(false);
- }
- //---------------------------------------------------------------------------
- bool MoverGroup::isMember (MoverPtr mover) {
- if (!mover)
- return(false);
- GameObjectWatchID moverWID = mover->getWatchID();
- for (long i = 0; i < numMovers; i++)
- if (moverWIDs[i] == moverWID)
- return(true);
- return(false);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::disband (void) {
- for (long i = 0; i < numMovers; i++) {
- MoverPtr mover = getMover(i);
- mover->setGroupId(-1, true);
- }
- #ifdef USE_IFACE
- if (pointHandle)
- theInterface->setPoint(pointHandle, false);
- #endif
- pointWID = 0;
- numMovers = 0;
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::setPoint (MoverPtr mover) {
- if (isMember(mover)) {
- #ifdef USE_IFACE
- if (pointHandle)
- theInterface->setPoint(pointHandle, false);
- #endif
- pointWID = mover->getWatchID();
- #ifdef USE_IFACE
- theInterface->setPoint(mover->getPartId(), true);
- #endif
- }
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- MoverPtr MoverGroup::getPoint (void) {
- return(dynamic_cast<MoverPtr>(ObjectManager->getByWatchID(pointWID)));
- }
- //---------------------------------------------------------------------------
- MoverPtr MoverGroup::getMover (long i) {
- MoverPtr mover = dynamic_cast<MoverPtr>(ObjectManager->getByWatchID(moverWIDs[i]));
- if (!mover)
- Fatal(0, " MoverGroup.getMover: NULL mover ");
- return(mover);
- }
- //---------------------------------------------------------------------------
- MoverPtr MoverGroup::selectPoint (bool excludePoint) {
- for (long i = 0; i < numMovers; i++)
- if (!excludePoint || (moverWIDs[i] != pointWID)) {
- MoverPtr mover = getMover(i);
- MechWarriorPtr pilot = mover->getPilot();
- if (pilot && pilot->alive()) {
- //----------------------------------------
- // Found a legitimate point, so set him...
- setPoint(mover);
- return(mover);
- }
- }
- //-----------------------
- // No legitimate point...
- setPoint(NULL);
- return(NULL);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::getMovers (MoverPtr* moverList) {
- if (numMovers > 0)
- for (long i = 0; i < numMovers; i++)
- moverList[i] = getMover(i);
- return(numMovers);
- }
- //---------------------------------------------------------------------------
- MechWarriorPtr MoverGroup::getPointPilot (void) {
- if (pointWID)
- return(ObjectManager->getByWatchID(pointWID)->getPilot());
- return(NULL);
- }
- //---------------------------------------------------------------------------
- void MoverGroup::statusCount (long* statusTally) {
- for (long i = 0; i < numMovers; i++) {
- MoverPtr mover = getMover(i);
- MechWarriorPtr pilot = mover->getPilot();
- if (!mover->getExists())
- statusTally[8]++;
- else if (!mover->getAwake())
- statusTally[7]++;
- else if (pilot && (pilot->getStatus() == WARRIOR_STATUS_WITHDRAWN))
- statusTally[6]++;
- else
- statusTally[mover->getStatus()]++;
- }
- }
- //---------------------------------------------------------------------------
- void MoverGroup::addToGUI (bool visible) {
- #ifdef USE_IFACE
- for (long i = 0; i < numMovers; i++)
- theInterface->AddMech(movers[i]->getPartId(), id, movers[i]->getAwake(), visible);
- #endif
- }
- //---------------------------------------------------------------------------
- inline bool inMapBounds (long r, long c, long mapHeight, long mapWidth) {
- return((r >= 0) && (r < mapHeight) && (c >= 0) && (c < mapWidth));
- }
- //---------------------------------------------------------------------------
- #define JUMPMAP_TILE_DIM 3
- #define JUMPMAP_CELL_DIM MAPCELL_DIM * JUMPMAP_TILE_DIM
- char CellSpiralIncrement[JUMPMAP_CELL_DIM * JUMPMAP_CELL_DIM * 2] = {
- -1, 0,
- 0, 1,
- 1, 0,
- 1, 0,
- 0, -1,
- 0, -1,
- -1, 0,
- -1, 0,
- -1, 0,
- 0, 1,
- 0, 1,
- 0, 1,
- 1, 0,
- 1, 0,
- 1, 0,
- 1, 0,
- 0, -1,
- 0, -1,
- 0, -1,
- 0, -1,
- -1, 0,
- -1, 0,
- -1, 0,
- -1, 0,
- -1, 0,
- 0, 1,
- 0, 1,
- 0, 1,
- 0, 1,
- 0, 1,
- 1, 0,
- 1, 0,
- 1, 0,
- 1, 0,
- 1, 0,
- 1, 0,
- 0, -1,
- 0, -1,
- 0, -1,
- 0, -1,
- 0, -1,
- 0, -1,
- -1, 0,
- -1, 0,
- -1, 0,
- -1, 0,
- -1, 0,
- -1, 0,
- -1, 0,
- 0, 1,
- 0, 1,
- 0, 1,
- 0, 1,
- 0, 1,
- 0, 1,
- 0, 1,
- 1, 0,
- 1, 0,
- 1, 0,
- 1, 0,
- 1, 0,
- 1, 0,
- 1, 0,
- 1, 0,
- 0, -1,
- 0, -1,
- 0, -1,
- 0, -1,
- 0, -1,
- 0, -1,
- 0, -1,
- 0, -1,
- -1, 0,
- -1, 0,
- -1, 0,
- -1, 0,
- -1, 0,
- -1, 0,
- -1, 0,
- -1, 0
- };
- //---------------------------------------------------------------------------
- void MoverGroup::sortMovers (long numMoversInGroup, MoverPtr* moverList, Stuff::Vector3D destination) {
- Mover::sortList->clear();
- for (long i = 0; i < numMoversInGroup; i++) {
- long index = -1;
- float dist = (float)3.48E+37;
- if (moverList[i]) {
- index = i;
- Stuff::Vector3D resultVector;
- resultVector.Subtract(moverList[i]->getPosition(), destination);
- dist = resultVector.GetLength();
- }
- Mover::sortList->setId(i, index);
- Mover::sortList->setValue(i, dist);
- }
- Mover::sortList->sort(false);
- for (i = 0; i < numMoversInGroup; i++) {
- long moverIndex = Mover::sortList->getId(i);
- if (moverIndex != -1)
- moverList[moverIndex]->selectionIndex = i;
- }
- }
- //---------------------------------------------------------------------------
- #define GOALMAP_DIM 61
- long MoverGroup::calcMoveGoals (Stuff::Vector3D goal, long numMovers, Stuff::Vector3D* goalList) {
- if ( !numMovers ) // 07/24/HKG: crashes if no movers
- return 0;
- if (!goalMap) {
- goalMap = (GoalMapNode*)systemHeap->Malloc(sizeof(GoalMapNode) * GOALMAP_DIM * GOALMAP_DIM);
- if (!goalMap)
- Fatal(0, " MoverGroup.calcMoveGoals: unable to malloc goalMap ");
- }
- long goalRow, goalCol;
- land->worldToCell(goal, goalRow, goalCol);
- long topLeftRow = goalRow - GOALMAP_DIM / 2;
- long topLeftCol = goalCol - GOALMAP_DIM / 2;
- for (long r = 0; r < GOALMAP_DIM; r++)
- for (long c = 0; c < GOALMAP_DIM; c++) {
- if (!inMapBounds(topLeftRow + r, topLeftCol + c, GameMap->height, GameMap->width))
- continue;
- long index = r * GOALMAP_DIM + c;
- goalMap[index].cost = GameMap->getPassable(topLeftRow + r, topLeftCol + c) ? 100 : COST_BLOCKED;
- goalMap[index].flags = GOALFLAG_AVAILABLE + GOALFLAG_NO_NEIGHBORS;
- goalMap[index].g = 0;
- }
- //-----------------------------------------------
- // If we haven't already, create the OPEN list...
- if (!openList) {
- openList = new PriorityQueue;
- gosASSERT(openList != NULL);
- openList->init(5000);
- }
- long curRow = GOALMAP_DIM / 2;
- long curCol = GOALMAP_DIM / 2;
-
- GoalMapNode* curMapNode = &goalMap[curRow * GOALMAP_DIM + curCol];
- //-----------------------------------------------------------------
- // Put the START (the goal, in this case) on the empty OPEN list...
- PQNode initialVertex;
- initialVertex.key = curMapNode->g;
- initialVertex.id = curRow * GOALMAP_DIM + curCol;
- initialVertex.row = curRow;
- initialVertex.col = curCol;
- openList->clear();
- openList->insert(initialVertex);
- curMapNode->setFlag(GOALFLAG_OPEN);
- long numGoalsFound = 0;
- while (!openList->isEmpty()) {
- //----------------------
- // Grab the best node...
- PQNode bestPQNode;
- openList->remove(bestPQNode);
- curRow = bestPQNode.row;
- curCol = bestPQNode.col;
- GoalMapNode* bestMapNode = &goalMap[curRow * GOALMAP_DIM + curCol];
- bestMapNode->clearFlag(GOALFLAG_OPEN);
- //----------------------------
- // Now, close the best node...
- bestMapNode->setFlag(GOALFLAG_CLOSED);
- bool markNeighbors = false;
- //------------------------------
- // Have we found a valid goal...
- if (bestMapNode->cost < COST_BLOCKED)
- if (bestMapNode->flags & GOALFLAG_NO_NEIGHBORS)
- if (bestMapNode->flags & GOALFLAG_AVAILABLE) {
- bestMapNode->clearFlag(GOALFLAG_AVAILABLE);
- land->cellToWorld(topLeftRow + curRow, topLeftCol + curCol, goalList[numGoalsFound++]);
- markNeighbors = true;
- }
- if (numGoalsFound == numMovers)
- break;
- if (markNeighbors) {
- static long cellShift[8][2] = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}};
- for (long i = 0; i < 8; i++) {
- long nRow = curRow + cellShift[i][0];
- long nCol = curRow + cellShift[i][1];
- if (inMapBounds(nRow, nCol, GOALMAP_DIM, GOALMAP_DIM))
- goalMap[nRow * GOALMAP_DIM + nCol].clearFlag(GOALFLAG_NO_NEIGHBORS);
- }
- }
- long bestNodeG = bestMapNode->g;
- for (long dir = 0; dir < 4; dir++) {
- //------------------------------------------------------------
- // First, make sure this is a legit direction to go. We do NOT
- // move diagonally, when checking these cells...
- //------------------------------------------------------------
- // Now, process this direction. First, calc the cell to check,
- // offset from the current cell...
- static long cellShift[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
- long succRow = curRow + cellShift[dir][0];
- long succCol = curCol + cellShift[dir][1];
- //--------------------------------
- // If it's on the map, check it...
- if (inMapBounds(succRow, succCol, GOALMAP_DIM, GOALMAP_DIM)) {
- GoalMapNode* succMapNode = &goalMap[succRow * GOALMAP_DIM + succCol];
- if (succMapNode->cost < COST_BLOCKED) {
- long succNodeG = bestNodeG + succMapNode->cost;
- if ((succMapNode->flags & (GOALFLAG_OPEN + GOALFLAG_CLOSED)) == 0) {
- //-------------------------------------------------
- // This node is neither OPEN nor CLOSED, so toss it
- // into the OPEN list...
- //succMapNode->parent = dirToParent;
- succMapNode->g = succNodeG;
- PQNode succPQNode;
- succPQNode.key = succMapNode->g;
- succPQNode.id = succRow * GOALMAP_DIM + succCol;
- succPQNode.row = succRow;
- succPQNode.col = succCol;
- openList->insert(succPQNode);
- succMapNode->setFlag(MOVEFLAG_OPEN);
- }
- }
- }
- }
- }
- return(numGoalsFound);
- }
- //---------------------------------------------------------------------------
- #define DEBUGJUMPGOALS TRUE
- long MoverGroup::calcJumpGoals (Stuff::Vector3D goal, long numMovers, Stuff::Vector3D* goalList, GameObjectPtr DFATarget) {
- long numJumping = 0;
- //-----------------------------
- // First, build the jump map...
- long jumpMap[JUMPMAP_CELL_DIM][JUMPMAP_CELL_DIM];
- //------------------------------------------------------------
- // The initial goal tile is placed at the center of the map...
- long goalCell[2] = {0, 0};
- land->worldToCell(goal, goalCell[0], goalCell[1]);
- long mapCellUL[2] = {0, 0};
- mapCellUL[0] = goalCell[0] - JUMPMAP_CELL_DIM / 2;
- mapCellUL[1] = goalCell[1] - JUMPMAP_CELL_DIM / 2;
- // -1 = OPEN
- // -2 = BLOCKED
- // 0 thru # = already selected for that # mover in the group
- for (long r = 0; r < JUMPMAP_CELL_DIM; r++)
- for (long c = 0; c < JUMPMAP_CELL_DIM; c++) {
- long cellRow = mapCellUL[0] + r;
- long cellCol = mapCellUL[1] + c;
- if (GameMap->inBounds(cellRow, cellCol)) {
- MapCellPtr mapCell = GameMap->getCell(cellRow, cellCol);
- //-----------------------
- // Tile (terrain) type...
- //long tileType = curTile.getTileType();
- if (!mapCell->getPassable())
- jumpMap[r][c] = -2;
- else
- jumpMap[r][c] = -1;
- #ifdef USE_OVERLAYS_IN_MC2
- long overlay = mapCell->getOverlay();
- if (OverlayIsBridge[overlay]) {
- switch (overlay) {
- case OVERLAY_WATER_BRIDGE_NS:
- case OVERLAY_RAILROAD_WATER_BRIDGE_NS:
- jumpMap[row][col] = -2;
- jumpMap[row][col + 2] = -2;
- jumpMap[row + 1][col] = -2;
- jumpMap[row + 1][col + 2] = -2;
- jumpMap[row + 2][col] = -2;
- jumpMap[row + 2][col + 2] = -2;
- break;
- case OVERLAY_WATER_BRIDGE_EW:
- case OVERLAY_RAILROAD_WATER_BRIDGE_EW:
- jumpMap[row][col] = -2;
- jumpMap[row][col + 1] = -2;
- jumpMap[row][col + 2] = -2;
- jumpMap[row + 2][col] = -2;
- jumpMap[row + 2][col + 1] = -2;
- jumpMap[row + 2][col + 2] = -2;
- break;
- case OVERLAY_WATER_BRIDGE_NS_DESTROYED:
- case OVERLAY_RAILROAD_WATER_BRIDGE_NS_DESTROYED:
- case OVERLAY_WATER_BRIDGE_EW_DESTROYED:
- case OVERLAY_RAILROAD_WATER_BRIDGE_EW_DESTROYED:
- jumpMap[row][col] = -2;
- jumpMap[row][col + 1] = -2;
- jumpMap[row][col + 2] = -2;
- jumpMap[row + 1][col] = -2;
- jumpMap[row + 1][col + 1] = -2;
- jumpMap[row + 1][col + 2] = -2;
- jumpMap[row + 2][col] = -2;
- jumpMap[row + 2][col + 1] = -2;
- jumpMap[row + 2][col + 2] = -2;
- break;
- }
- }
- #endif
- }
- else
- jumpMap[r][c] = -2;
- }
- long moverCount = ObjectManager->getNumMovers();
- for (long i = 0; i < moverCount; i++) {
- MoverPtr mover = ObjectManager->getMover(i);
- if ((mover->getObjectClass() != ELEMENTAL) && (mover != DFATarget) && !mover->isDisabled()) {
- long mapCellRow, mapCellCol;
- mover->getCellPosition(mapCellRow, mapCellCol);
- mapCellRow -= mapCellUL[0];
- mapCellCol -= mapCellUL[1];
- if (inMapBounds(mapCellRow, mapCellCol, JUMPMAP_CELL_DIM, JUMPMAP_CELL_DIM))
- jumpMap[mapCellRow][mapCellCol] = -2;
- }
- }
- #ifdef _DEBUG
- #if DEBUGJUMPGOALS
- char debugStr[256];
- sprintf(debugStr, "GROUP JUMP(%.2f,%.2f,%.2f)--UL = %d,%d: ", goal.x, goal.y, goal.z,mapCellUL[0], mapCellUL[1]);
- #endif
- #endif
- //-----------------------------------------------------------------
- // Now, for each jumper, select a closest cell to the goal, mark it
- // as theirs and close it...
- for (i = 0; i < numMovers; i++) {
- //long startCellRow = 0;
- //long startCellCol = 0;
- long curCellRow = goalCell[0] - mapCellUL[0];
- long curCellCol = goalCell[1] - mapCellUL[1];
- bool notFound = true;
- long spiralIndex = 0;
- while (notFound) {
- if (jumpMap[curCellRow][curCellCol] == -1) {
- // Should check to see if the cell is within range...
- //----------------------------------
- // Found an open cell, so take it...
- jumpMap[curCellRow][curCellCol] = i;
- land->cellToWorld(mapCellUL[0] + curCellRow, mapCellUL[1] + curCellCol, goalList[i]);
- numJumping++;
- notFound = false;
- #ifdef _DEBUG
- #if DEBUGJUMPGOALS
- char s[30];
- sprintf(s, "[%d,%d] ", curCellRow, curCellCol);
- strcat(debugStr, s);
- #endif
- #endif
- }
- else {
- //-------------------------------------
- // Go to the next cell in our search...
- do {
- if (spiralIndex == (JUMPMAP_CELL_DIM * JUMPMAP_CELL_DIM * 2)) {
- goalList[i].x = -99999.0;
- goalList[i].y = -99999.0;
- goalList[i].z = -99999.0;
- notFound = false;
- break;
- }
- curCellRow += CellSpiralIncrement[spiralIndex++];
- curCellCol += CellSpiralIncrement[spiralIndex++];
- } while (!inMapBounds(curCellRow, curCellCol, JUMPMAP_CELL_DIM, JUMPMAP_CELL_DIM));
- }
- }
- }
- return(numJumping);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::calcJumpGoals (Stuff::Vector3D goal, Stuff::Vector3D* goalList, GameObjectPtr DFATarget) {
- return(calcJumpGoals(goal, numMovers, goalList, DFATarget));
- }
- //---------------------------------------------------------------------------
- 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);
- }
- //---------------------------------------------------------------------------
- // TAC ORDERS
- //---------------------------------------------------------------------------
- long MoverGroup::orderMoveToPoint (bool setTacOrder, long origin, Stuff::Vector3D location, unsigned long params) {
- long result = TACORDER_FAILURE;
- for (long i = 0; i < numMovers; i++) {
- Assert(getMover(i) != NULL, 0, " MoverGroup.orderMoveToPoint: NULL mover ");
- MechWarriorPtr pilot = getMover(i)->getPilot();
- if (pilot)
- result = pilot->orderMoveToPoint(true, setTacOrder, origin, location, -1, params);
- }
- return(result);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::orderMoveToObject (bool setTacOrder, long origin, GameObjectPtr target, long fromArea, unsigned long params) {
- long result = TACORDER_FAILURE;
- for (long i = 0; i < numMovers; i++) {
- Assert(getMover(i) != NULL, 0, " MoverGroup.orderMoveToObject: NULL mover ");
- MechWarriorPtr pilot = getMover(i)->getPilot();
- if (pilot)
- result = pilot->orderMoveToObject(true, setTacOrder, origin, target, fromArea, -1, params);
- }
- return(result);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::orderTraversePath (long origin, WayPathPtr wayPath, unsigned long params) {
- long result = TACORDER_FAILURE;
- for (long i = 0; i < numMovers; i++) {
- Assert(getMover(i) != NULL, 0, " MoverGroup.orderTraversePath: NULL mover ");
- MechWarriorPtr pilot = getMover(i)->getPilot();
- if (pilot)
- result = pilot->orderTraversePath(true, true, origin, wayPath, params);
- }
- return(result);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::orderPatrolPath (long origin, WayPathPtr wayPath) {
- long result = TACORDER_FAILURE;
- for (long i = 0; i < numMovers; i++) {
- Assert(getMover(i) != NULL, 0, " MoverGroup.orderPatrolPath: NULL mover ");
- MechWarriorPtr pilot = getMover(i)->getPilot();
- if (pilot)
- result = pilot->orderPatrolPath(true, true, origin, wayPath);
- }
- return(result);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::orderPowerDown (long origin) {
- long result = TACORDER_FAILURE;
- for (long i = 0; i < numMovers; i++) {
- Assert(getMover(i) != NULL, 0, " MoverGroup.orderPowerDown: NULL mover ");
- MechWarriorPtr pilot = getMover(i)->getPilot();
- if (pilot)
- result = pilot->orderPowerDown(true, origin);
- }
- return(result);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::orderPowerUp (long origin) {
- long result = TACORDER_FAILURE;
- for (long i = 0; i < numMovers; i++) {
- Assert(getMover(i) != NULL, 0, " MoverGroup.orderPowerUp: NULL mover ");
- MechWarriorPtr pilot = getMover(i)->getPilot();
- if (pilot)
- result = pilot->orderPowerUp(true, origin);
- }
- return(result);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::orderAttackObject (long origin, GameObjectPtr target, long attackType, long attackMethod, long attackRange, long aimLocation, long fromArea, unsigned long params) {
- long result = TACORDER_FAILURE;
- for (long i = 0; i < numMovers; i++) {
- Assert(getMover(i) != NULL, 0, " MoverGroup.orderAttackObject: NULL mover ");
- MechWarriorPtr pilot = getMover(i)->getPilot();
- if (pilot)
- result = pilot->orderAttackObject(true, origin, target, attackType, attackMethod, attackRange, aimLocation, fromArea, params);
- }
- return(result);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::orderWithdraw (long origin, Stuff::Vector3D location) {
- long result = TACORDER_FAILURE;
- for (long i = 0; i < numMovers; i++) {
- Assert(getMover(i) != NULL, 0, " MoverGroup.orderWithdraw: NULL mover ");
- MechWarriorPtr pilot = getMover(i)->getPilot();
- if (pilot)
- result = pilot->orderWithdraw(true, origin, location);
- }
- return(result);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::orderEject (long origin) {
- long result = TACORDER_FAILURE;
- for (long i = 0; i < numMovers; i++) {
- Assert(getMover(i) != NULL, 0, " MoverGroup.orderEject: NULL mover ");
- MechWarriorPtr pilot = getMover(i)->getPilot();
- if (pilot)
- result = pilot->orderEject(true, true, origin);
- }
- return(result);
- }
- //---------------------------------------------------------------------------
- // COMBAT EVENTS
- //---------------------------------------------------------------------------
- void MoverGroup::triggerAlarm (long alarmCode, unsigned long triggerId) {
- for (long i = 0; i < numMovers; i++) {
- MechWarriorPtr pilot = getMover(i)->getPilot();
- if (pilot)
- pilot->triggerAlarm(alarmCode, triggerId);
- }
- }
- //---------------------------------------------------------------------------
- long MoverGroup::handleMateCrippled (unsigned long mateWID) {
- triggerAlarm(PILOT_ALARM_FRIENDLY_VEHICLE_CRIPPLED, mateWID);
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::handleMateDisabled (unsigned long mateWID) {
- //triggerAlarm(PILOT_ALARM_DEATH_OF_MATE, mateId);
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::handleMateDestroyed (unsigned long mateWID) {
- triggerAlarm(PILOT_ALARM_DEATH_OF_MATE, mateWID);
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- long MoverGroup::handleMateEjected (unsigned long mateWID) {
- //triggerAlarm(PILOT_ALARM_DEATH_OF_MATE, mateId);
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- void MoverGroup::handleMateFiredWeapon (unsigned long mateWID) {
- triggerAlarm(PILOT_ALARM_MATE_FIRED_WEAPON, mateWID);
- }
- //***************************************************************************
- void MoverGroup::copyTo (MoverGroupData &data)
- {
- data.id = id;
- data.numMovers = numMovers;
- memcpy(data.moverWIDs,moverWIDs,sizeof(GameObjectWatchID) * MAX_MOVERGROUP_COUNT);
- data.pointWID = pointWID;
- data.disbandOnNoPoint = disbandOnNoPoint;
- }
- //***************************************************************************
- void MoverGroup::init (MoverGroupData &data)
- {
- id = data.id;
- numMovers = data.numMovers;
- memcpy(moverWIDs,data.moverWIDs,sizeof(GameObjectWatchID) * MAX_MOVERGROUP_COUNT);
- pointWID = data.pointWID;
- disbandOnNoPoint = data.disbandOnNoPoint;
- }
- //***************************************************************************
|