void CTransportCAI::UnloadUnits_Drop(Command& c, CTransportUnit* transport) { //called repeatedly for each unit till units are unloaded if(lastCall==gs->frameNum) //avoid infinite loops return; lastCall=gs->frameNum; if(((CTransportUnit*)owner)->transported.empty() ){ FinishCommand(); return; } float3 pos(c.params[0],c.params[1],c.params[2]); float radius=c.params[3]; bool canUnload = false; //at the start of each user command if (isFirstIteration ) { dropSpots.clear(); startingDropPos = pos; approachVector = startingDropPos-owner->pos; approachVector.Normalize(); canUnload = FindEmptyDropSpots(pos, pos + approachVector*max(16.0f,radius), dropSpots); } else if (!dropSpots.empty() ) { //make sure we check current spot infront of us each unload pos = dropSpots.back(); //take last landing pos as new start spot canUnload = dropSpots.size() > 0; } if( canUnload ){ if(SpotIsClear(dropSpots.back(),((CTransportUnit*)owner)->transported.front().unit)) { float3 pos = dropSpots.back(); Command c2; c2.id=CMD_UNLOAD_UNIT; c2.params.push_back(pos.x); c2.params.push_back(pos.y); c2.params.push_back(pos.z); c2.options=c.options | INTERNAL_ORDER; commandQue.push_front(c2); SlowUpdate(); isFirstIteration = false; return; } else { dropSpots.pop_back(); } } else { startingDropPos = float3(-1,-1,-1); isFirstIteration=true; dropSpots.clear(); FinishCommand(); } }
void CTransportCAI::UnloadUnits_Drop(Command& c, CTransportUnit* transport) { // called repeatedly for each unit till units are unloaded if (lastCall == gs->frameNum) { // avoid infinite loops return; } lastCall = gs->frameNum; const auto& transportees = transport->GetTransportedUnits(); if (transportees.empty()) { FinishCommand(); return; } bool canUnload = false; // at the start of each user command if (isFirstIteration) { dropSpots.clear(); startingDropPos = c.GetPos(0); approachVector = (startingDropPos - owner->pos).Normalize(); canUnload = FindEmptyDropSpots(startingDropPos, startingDropPos + approachVector * std::max(16.0f, c.params[3]), dropSpots); } else if (!dropSpots.empty() ) { // make sure we check current spot in front of us each // unload, take last landing pos as new start spot // pos = dropSpots.back(); canUnload = !dropSpots.empty(); } if (canUnload) { if (SpotIsClear(dropSpots.back(), (transportees.front()).unit)) { Command c2(CMD_UNLOAD_UNIT, c.options | INTERNAL_ORDER, dropSpots.back()); commandQue.push_front(c2); SlowUpdate(); isFirstIteration = false; return; } else { dropSpots.pop_back(); } } else { startingDropPos = -OnesVector; isFirstIteration = true; dropSpots.clear(); FinishCommand(); } }
void CTransportCAI::UnloadUnits_Drop(Command& c, CTransportUnit* transport) { // called repeatedly for each unit till units are unloaded if (lastCall == gs->frameNum) { // avoid infinite loops return; } lastCall = gs->frameNum; if (static_cast<CTransportUnit*>(owner)->GetTransportedUnits().empty()) { FinishCommand(); return; } float3 pos = c.GetPos(0); float radius = c.params[3]; bool canUnload = false; // at the start of each user command if (isFirstIteration) { dropSpots.clear(); startingDropPos = pos; approachVector = startingDropPos - owner->pos; approachVector.Normalize(); canUnload = FindEmptyDropSpots(pos, pos + approachVector * std::max(16.0f,radius), dropSpots); } else if (!dropSpots.empty() ) { // make sure we check current spot infront of us each unload pos = dropSpots.back(); // take last landing pos as new start spot canUnload = !dropSpots.empty(); } if (canUnload) { if (SpotIsClear(dropSpots.back(), static_cast<CTransportUnit*>(owner)->GetTransportedUnits().front().unit)) { const float3 pos = dropSpots.back(); Command c2(CMD_UNLOAD_UNIT, c.options | INTERNAL_ORDER, pos); commandQue.push_front(c2); SlowUpdate(); isFirstIteration = false; return; } else { dropSpots.pop_back(); } } else { startingDropPos = float3(-1.0f, -1.0f, -1.0f); isFirstIteration = true; dropSpots.clear(); FinishCommand(); } }
bool CTransportCAI::FindEmptyDropSpots(float3 startpos, float3 endpos, std::list<float3>& dropSpots) { //should only be used by air CTransportUnit* transport=(CTransportUnit*)owner; //dropSpots.clear(); float gap = 25.5; //TODO - set tag for this? float3 dir = endpos - startpos; dir.Normalize(); float3 nextPos = startpos; float3 pos; list<CTransportUnit::TransportedUnit>::iterator ti = transport->transported.begin(); dropSpots.push_front(nextPos); //first spot if (ti!=transport->transported.end()) { //float3 p = nextPos; //test to make intended land spots visible //inMapDrawer->CreatePoint(p,ti->unit->unitDef->name); //p.z +=transport->transportCapacityUsed*5; nextPos += dir*(gap + ti->unit->radius); ti++; } //remaining spots if (dynamic_cast<CTAAirMoveType*>(owner->moveType)) { while (ti != transport->transported.end() && startpos.distance(nextPos) < startpos.distance(endpos)) { nextPos += dir*(ti->unit->radius); nextPos.y = ground->GetHeight(nextPos.x, nextPos.z); //check landing spot is ok for landing on if (!SpotIsClear(nextPos,ti->unit)) continue; dropSpots.push_front(nextPos); //float3 p = nextPos; //test to make intended land spots visible //inMapDrawer->CreatePoint(p,ti->unit->unitDef->name); //p.z +=transport->transportCapacityUsed*5; nextPos += dir*(gap + ti->unit->radius); ti++; } return true; } return false; }
bool CTransportCAI::FindEmptyDropSpots(float3 startpos, float3 endpos, std::list<float3>& dropSpots) { //should only be used by air CTransportUnit* transport = static_cast<CTransportUnit*>(owner); //dropSpots.clear(); float gap = 25.5; // TODO - set tag for this? float3 dir = endpos - startpos; dir.Normalize(); float3 nextPos = startpos; float3 pos; std::list<CTransportUnit::TransportedUnit>::const_iterator ti = transport->GetTransportedUnits().begin(); dropSpots.push_front(nextPos); // first spot if (ti != transport->GetTransportedUnits().end()) { nextPos += dir * (gap + ti->unit->radius); ++ti; } // remaining spots if (dynamic_cast<CHoverAirMoveType*>(owner->moveType)) { while (ti != transport->GetTransportedUnits().end() && startpos.SqDistance(nextPos) < startpos.SqDistance(endpos)) { nextPos += dir * (ti->unit->radius); nextPos.y = ground->GetHeightAboveWater(nextPos.x, nextPos.z); // check landing spot is ok for landing on if (!SpotIsClear(nextPos,ti->unit)) continue; dropSpots.push_front(nextPos); nextPos += dir * (gap + ti->unit->radius); ++ti; } return true; } return false; }
// should only be used by air bool CTransportCAI::FindEmptyDropSpots(float3 startpos, float3 endpos, std::list<float3>& dropSpots) { const float gap = 25.5f; // TODO - set tag for this? const float3 dir = (endpos - startpos).Normalize(); float3 nextPos = startpos; dropSpots.push_front(nextPos); if (dynamic_cast<CHoverAirMoveType*>(owner->moveType) == NULL) return false; const auto& transportees = static_cast<CTransportUnit*>(owner)->GetTransportedUnits(); auto ti = transportees.begin(); // first spot if (ti != transportees.end()) { nextPos += (dir * (gap + ti->unit->radius)); ++ti; } // remaining spots while (ti != transportees.end() && startpos.SqDistance(nextPos) < startpos.SqDistance(endpos)) { nextPos += (dir * (ti->unit->radius)); nextPos.y = CGround::GetHeightAboveWater(nextPos.x, nextPos.z); // check landing spot is ok for landing on if (!SpotIsClear(nextPos, ti->unit)) continue; dropSpots.push_front(nextPos); nextPos += (dir * (gap + ti->unit->radius)); ++ti; } return true; }