// // GoToNextPoint // void SquadMoveTogether::GoToNextPoint(SquadObj::ListNode *node) { // We are attempting to go to the next point NPoint *p = points[node->data]; node->data++; node->completed = TRUE; point = Max(point, node->data); ASSERT(node->Alive()) UnitObj *unit = node->GetData(); if (p) { // Mark the time a unit attempts to move to this point if (p->timestamp) { // The squad will need to wait for me to catch up if (GameTime::SimCycle() - p->timestamp > timeDiffMax) { // LOG_DIAG(("Detected that we're [%d] way behind at this point, changing to waiting state", node->Id())) NextState(0xCC45C48B); // "Waiting" } } else { p->timestamp = GameTime::SimCycle(); // Since we're the first unit to this point we // should check to make sure that no units are // more than two points behind. If there are, // then we'll have to wait here for them SquadObj::UnitList::Iterator i(&subject->GetList()); for (!i; *i; i++) { if ( (*i)->Alive() && ((*i)->data + pointDiffMax < point) ) { // LOG_DIAG(("We're [%d] first to this point [%d] and detected that [%d] is way behind", node->Id(), node->data, (*i)->Id())) NextState(0xCC45C48B); // "Waiting" return; } } } // Find the closest point to that point that we can go to U32 x, z; // Use the formation slot offset for this unit Vector location(WorldCtrl::CellToMetresX(p->x), 0.0f, WorldCtrl::CellToMetresZ(p->z)); F32 dir = p->direction + node->slot.direction; VectorDir::FixU(dir); F32 orient = p->direction + node->slot.orientation; VectorDir::FixU(orient); Vector offset; offset.x = (F32) cos(dir); offset.y = 0.0f; offset.z = (F32) sin(dir); offset *= node->slot.distance; offset += location; // Make sure the point is on the map WorldCtrl::ClampMetreMap(offset.x, offset.z); x = WorldCtrl::MetresToCellX(offset.x); z = WorldCtrl::MetresToCellZ(offset.z); if (PathSearch::FindClosestCell(unit->MapType()->GetTractionIndex(unit->MapType()->GetDefaultLayer()), x, z, x, z, meetingRange)) { node->completed = FALSE; unit->PrependTask(new Tasks::UnitMove(unit, offset)); } else { // Cound not find a cell, go to the next point GoToNextPoint(node); } } }
// // StateInit // void SquadBoard::StateInit() { // Get each of the units in the squad to board transports SquadObj::UnitList::Iterator u(&subject->GetList()); // We could enhance this to use units which are closest to transports etc. // Clear the squad's completed flags for (!u; *u; u++) { (*u)->completed = FALSE; (*u)->task = 0; } // Reset squad iterator !u; for (TransportObjList::Iterator t(&transports); *t; t++) { if ((*t)->Alive()) { TransportObj *transport = **t; U32 slots = transport->TransportType()->GetSpaces(); U32 added = 0; while (slots--) { UnitObjPtr *unitPtr = *u; if (unitPtr) { ASSERT(unitPtr->Alive()) UnitObj *unit = *unitPtr; if (unit->CanEverMove()) { // Tell the unit to board unit->FlushTasks(Tasks::UnitBoard::GetConfigBlockingPriority()); Task *task; // Is this a telepad if (TaskCtrl::PromoteIdle<Tasks::TransportPad>(transport)) { unit->PrependTask(task = new Tasks::UnitMove(unit, transport), GetFlags()); } else { unit->PrependTask(task = new Tasks::UnitBoard(unit, transport), GetFlags()); } (*u)->task = task->GetTaskId(); added++; } else { // This unit can't move so complete it (*u)->completed = TRUE; } } else { break; } // Increment iterator u++; } if (!added) { // No units were added break; } } } // Complete those units which missed out for (; *u; u++) { (*u)->completed = TRUE; } NextState(0x09E5F977); // "Boarding" }