Need to make clear when TowerPlaneRecs do or don't get deleted in RemoveFromCircuitList etc. (MINOR until I misuse it - then CRITICAL!)
FGTower::RemoveAllUserDialogOptions() really ought to be replaced by an ATCDialog::clear_entries() function. (MINOR - efficiency).
+
+At the moment planes in the lists are not guaranteed to always have a sensible ETA - it should be set as part of AddList functions, and lists should only be accessed this way. (FAIRLY MAJOR).
*******************************************/
FGTower::FGTower() {
}
trns += ConvertRwyNumToSpokenString(activeRwy);
if(_display) {
- globals->get_ATC_display()->RegisterSingleMessage(trns, 0);
+ //globals->get_ATC_display()->RegisterSingleMessage(trns, 0);
+ pending_transmission = trns;
+ Transmit();
} else {
//cout << "Not displaying, trns was " << trns << '\n';
}
string trns = t->plane.callsign;
trns += " hold position";
if(_display) {
- globals->get_ATC_display()->RegisterSingleMessage(trns, 0);
+ //globals->get_ATC_display()->RegisterSingleMessage(trns, 0);
+ pending_transmission = trns;
+ Transmit();
}
// TODO - add some idea of what traffic is blocking him.
}
t->clearedToLand = false;
}
if(_display && disp) {
- globals->get_ATC_display()->RegisterSingleMessage(trns);
+ //globals->get_ATC_display()->RegisterSingleMessage(trns);
+ pending_transmission = trns;
+ Transmit();
}
t->finalAcknowledged = true;
} else if(t->rwyVacatedReported && !(t->rwyVacatedAcknowledged)) {
int a = 0; // Count of preceding planes on approach
bool cf = false; // conflicting traffic on final
bool cc = false; // preceding traffic in circuit
+ TowerPlaneRec* tc = NULL;
for(tower_plane_rec_list_iterator twrItr = circuitList.begin(); twrItr != circuitList.end(); twrItr++) {
if((*twrItr)->plane.callsign == responseID) break;
+ tc = *twrItr;
++i;
}
if(i > 1) { cc = true; }
doThresholdETACalc();
- TowerPlaneRec* tt;
+ TowerPlaneRec* tf = NULL;
for(tower_plane_rec_list_iterator twrItr = appList.begin(); twrItr != appList.end(); twrItr++) {
if((*twrItr)->eta < (t->eta + 45)) {
a++;
- tt = *twrItr;
+ tf = *twrItr;
cf = true;
// This should set the flagged plane to be the last conflicting one, and hence the one to follow.
// It ignores the fact that we might have problems slotting into the approach traffic behind it -
trns += ConvertNumToSpokenDigits(i + a);
// This assumes that the number spoken is landing position, not circuit position, since some of the traffic might be on straight-in final.
trns += " ";
+ TowerPlaneRec* tt = NULL;
if((i == 1) && (!rwyList.size()) && (t->nextOnRwy) && (!cf)) { // Unfortunately nextOnRwy currently doesn't handle circuit/straight-in ordering properly at present, hence the cf check below.
trns += "Cleared to land"; // TODO - clear for the option if appropriate
t->clearedToLand = true;
if(!t->isUser) t->planePtr->RegisterTransmission(7);
} else if((i+a) > 1) {
+ //First set tt to point to the correct preceding plane - final or circuit
+ if(tc && tf) {
+ tt = (tf->eta < tc->eta ? tf : tc);
+ } else if(tc) {
+ tt = tc;
+ } else if(tf) {
+ tt = tf;
+ } else {
+ // We should never get here!
+ SG_LOG(SG_ATC, SG_ALERT, "ALERT - Logic error in FGTower::ProcessDownwindReport");
+ return;
+ }
trns += "Follow the ";
string s = tt->plane.callsign;
int p = s.find('-');
s = s.substr(0,p);
trns += s;
if((tt->opType) == CIRCUIT) {
- if(tt->planePtr->GetLeg() == FINAL) {
+ PatternLeg leg;
+ if(t->isUser) {
+ leg = tt->leg;
+ } else {
+ leg = tt->planePtr->GetLeg();
+ }
+ if(leg == FINAL) {
trns += " on final";
- } else if(tt->planePtr->GetLeg() == TURN4) {
+ } else if(leg == TURN4) {
trns += " turning final";
- } else if(tt->planePtr->GetLeg() == BASE) {
+ } else if(leg == BASE) {
trns += " on base";
- } else if(tt->planePtr->GetLeg() == TURN3) {
+ } else if(leg == TURN3) {
trns += " turning base";
}
} else {
}
}
if(_display) {
- globals->get_ATC_display()->RegisterSingleMessage(trns);
+ //globals->get_ATC_display()->RegisterSingleMessage(trns);
+ pending_transmission = trns;
+ Transmit();
}
if(t->isUser) {
if(t->opType == TTT_UNKNOWN) t->opType = CIRCUIT;
void FGTower::ProcessRunwayVacatedReport(TowerPlaneRec* t) {
//cout << "Processing rwy vacated...\n";
- current_atcdialog->remove_entry(ident, USER_REPORT_GOING_AROUND, TOWER);
+ if(t->isUser) current_atcdialog->remove_entry(ident, USER_REPORT_GOING_AROUND, TOWER);
string trns = t->plane.callsign;
if(separateGround) {
trns += " Contact ground on ";
}
//cout << "trns = " << trns << '\n';
if(_display) {
- globals->get_ATC_display()->RegisterSingleMessage(trns);
+ //globals->get_ATC_display()->RegisterSingleMessage(trns);
+ pending_transmission = trns;
+ Transmit();
}
+ RemoveFromRwyList(t->plane.callsign);
+ AddToVacatedList(t);
// Maybe we should check that the plane really *has* vacated the runway!
}
timeSinceLastDeparture = 0.0;
}
if(_display) {
- globals->get_ATC_display()->RegisterSingleMessage(trns, 0);
+ //globals->get_ATC_display()->RegisterSingleMessage(trns, 0);
+ pending_transmission = trns;
+ Transmit();
}
//cout << "Done ClearHoldingPlane " << endl;
}
//cout << " ho = " << ho << " abs(ho = " << abs(ho) << '\n';
// TODO FIXME - get the wind and convert this to track, or otherwise use track somehow!!!
// If it's gusty might need to filter the value, although we are leaving 30 degrees each way leeway!
- if(abs(ho) < 30) {
+ if(fabs(ho) < 30) {
// could be either takeoff, climbout or landing - check orthopos.y
//cout << "tortho.y = " << tortho.y() << '\n';
if((tortho.y() < 0) || (t->leg == TURN4) || (t->leg == FINAL)) {
}
}
}
- } else if(abs(ho) < 60) {
+ } else if(fabs(ho) < 60) {
// turn1 or turn 4
// TODO - either fix or doublecheck this hack by looking at heading and pattern direction
if((t->leg == CLIMBOUT) || (t->leg == TURN1)) {
t->leg = TURN4;
//cout << "Turn4\n";
}
- } else if(abs(ho) < 120) {
+ } else if(fabs(ho) < 120) {
// crosswind or base
// TODO - either fix or doublecheck this hack by looking at heading and pattern direction
if((t->leg == TURN1) || (t->leg == CROSSWIND)) {
t->leg = BASE;
//cout << "Base\n";
}
- } else if(abs(ho) < 150) {
+ } else if(fabs(ho) < 150) {
// turn2 or turn 3
// TODO - either fix or doublecheck this hack by looking at heading and pattern direction
if((t->leg == CROSSWIND) || (t->leg == TURN2)) {
t->planePtr->RegisterTransmission(13);
}
} else if(!t->clearedToLand) {
- if(t->nextOnRwy) {
+ // The whip through the appList is a hack since currently t->nextOnRwy doesn't always work
+ // TODO - fix this!
+ bool cf = false;
+ for(tower_plane_rec_list_iterator twrItr = appList.begin(); twrItr != appList.end(); twrItr++) {
+ if((*twrItr)->eta < t->eta) {
+ cf = true;
+ }
+ }
+ if(t->nextOnRwy && !cf) {
if(!rwyList.size()) {
string trns = t->plane.callsign;
trns += " Cleared to land";
//cout << "Size of rwylist was " << rwyList.size() << '\n';
//cout << "Size of vacatedList was " << vacatedList.size() << '\n';
RemoveFromRwyList(t->plane.callsign);
- vacatedList.push_back(t);
+ AddToVacatedList(t);
//cout << "Size of rwylist is " << rwyList.size() << '\n';
//cout << "Size of vacatedList is " << vacatedList.size() << '\n';
// At the moment we wait until Runway Vacated is reported by the plane before telling to contact ground etc.
} else {
// TODO - set/update the position if it's an AI plane
}
+ doThresholdETACalc(); // We need this here because planes in the lists are not guaranteed to *always* have the correct ETA
//cout << "eta is " << t->eta << ", rwy is " << (rwyList.size() ? "occupied " : "clear ") << '\n';
if(t->eta < 12 && rwyList.size() && !(t->instructedToGoAround)) {
// TODO - need to make this more sophisticated
// TODO - add Go-around ack to comm options,
// remove report rwy vacated. (possibly).
}
- }
- if(t->nextOnRwy && !(t->clearedToLand) && !(t->instructedToGoAround)) {
- // check distance away and whether runway occupied
- // and schedule transmission if necessary
+ } else if(t->eta < 90 && !t->clearedToLand) {
+ //doThresholdETACalc();
+ doThresholdUseOrder();
+ // The whip through the appList is a hack since currently t->nextOnRwy doesn't always work
+ // TODO - fix this!
+ bool cf = false;
+ for(tower_plane_rec_list_iterator twrItr = appList.begin(); twrItr != appList.end(); twrItr++) {
+ if((*twrItr)->eta < t->eta) {
+ cf = true;
+ }
+ }
+ if(t->nextOnRwy && !cf) {
+ if(!rwyList.size()) {
+ string trns = t->plane.callsign;
+ trns += " Cleared to land";
+ pending_transmission = trns;
+ Transmit();
+ //if(t->isUser) cout << "Transmitting cleared to Land!!!\n";
+ t->clearedToLand = true;
+ if(!t->isUser) {
+ t->planePtr->RegisterTransmission(7);
+ }
+ }
+ } else {
+ //if(t->isUser) cout << "Not next\n";
+ }
}
// Check for landing...
return(conflict);
}
+// Add to vacated list only if not already present
+void FGTower::AddToVacatedList(TowerPlaneRec* t) {
+ tower_plane_rec_list_iterator twrItr;
+ bool found = false;
+ for(twrItr = vacatedList.begin(); twrItr != vacatedList.end(); twrItr++) {
+ if((*twrItr)->plane.callsign == t->plane.callsign) {
+ found = true;
+ }
+ }
+ if(found) return;
+ vacatedList.push_back(t);
+}
+
// Calculate the eta of a plane to the threshold.
// For ground traffic this is the fastest they can get there.
int check = 0; // If mes gets overflowed the while loop can go infinite
while ( strchr(&mes[0], crej) != NULL ) { // ie. loop until no more occurances of crej ('@') found
pos = strchr( &mes[0], crej );
- bcopy(pos, &tag[0], 3);
+ memmove(&tag[0], pos, 3);
tag[3] = '\0';
int i;
len = 0;