307 lines
14 KiB
C++
307 lines
14 KiB
C++
#include "freighter.h"
|
|
|
|
// ZFW Entry
|
|
void distribute(fPayloadData_t* const targetPayload, const FuelData_t* const fuel, const double ZFWTarget, const bool isImperial, const bool isER) {
|
|
// Find payload, num pax and extra cargo
|
|
double payload = ZFWTarget - targetPayload->empty - targetPayload->pilot - targetPayload->firstOfficer - targetPayload->engineer -
|
|
targetPayload->leftAux - targetPayload->rightAux;
|
|
unsigned int cargo = round(payload);
|
|
|
|
distribute(targetPayload, fuel, cargo, isImperial, isER);
|
|
}
|
|
|
|
// SimBrief Entry
|
|
void distribute(fPayloadData_t* const targetPayload, const FuelData_t* const fuel, unsigned int cargo, const bool isImperial, const bool isER) {
|
|
// Clear
|
|
targetPayload->stations.upper1 = targetPayload->stations.upper2 = targetPayload->stations.upper3 = targetPayload->stations.upper4 =
|
|
targetPayload->stations.total = 0;
|
|
targetPayload->lowerForward = targetPayload->lowerRear = 0;
|
|
|
|
unsigned short _cargo = 0;
|
|
unsigned int count = MAX_UPPER_CARGO(isImperial) * 4 + MAX_FRONT_CARGO(isImperial) + MAX_REAR_CARGO(isImperial, isER);
|
|
// Initial distributiob
|
|
while (cargo > 0 && count > 0) {
|
|
if (cargo >= 6) {
|
|
if (targetPayload->stations.upper1 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper1++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->stations.upper2 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper2++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->stations.upper3 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper3++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->stations.upper4 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper4++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->lowerForward < MAX_FRONT_CARGO(isImperial)) {
|
|
targetPayload->lowerForward++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->lowerRear < MAX_REAR_CARGO(isImperial, isER)) {
|
|
targetPayload->lowerRear++;
|
|
_cargo++;
|
|
}
|
|
} else if (cargo == 5) {
|
|
if (targetPayload->stations.upper1 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper1++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->stations.upper2 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper2++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->stations.upper3 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper3++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->stations.upper4 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper4++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->lowerForward < MAX_FRONT_CARGO(isImperial)) {
|
|
targetPayload->lowerForward++;
|
|
_cargo++;
|
|
}
|
|
}
|
|
else if (cargo == 4) {
|
|
if (targetPayload->stations.upper1 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper1++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->stations.upper2 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper2++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->stations.upper3 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper3++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->stations.upper4 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper4++;
|
|
_cargo++;
|
|
}
|
|
}
|
|
else if (cargo == 3) {
|
|
if (targetPayload->stations.upper1 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper1++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->stations.upper2 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper2++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->stations.upper3 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper3++;
|
|
_cargo++;
|
|
}
|
|
}
|
|
else if (cargo == 2) {
|
|
if (targetPayload->stations.upper1 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper1++;
|
|
_cargo++;
|
|
}
|
|
if (targetPayload->stations.upper2 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper2++;
|
|
_cargo++;
|
|
}
|
|
}
|
|
else if (cargo == 1) {
|
|
if (targetPayload->stations.upper1 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper1++;
|
|
_cargo++;
|
|
}
|
|
}
|
|
cargo -= _cargo;
|
|
targetPayload->stations.total += _cargo;
|
|
|
|
_cargo = 0;
|
|
|
|
count--;
|
|
}
|
|
// Refinement
|
|
count = MAX_UPPER_CARGO(isImperial) * 4 + MAX_FRONT_CARGO(isImperial) + MAX_REAR_CARGO(isImperial, isER);
|
|
while (count > 0) {
|
|
generatePayload(targetPayload, isImperial);
|
|
calculateCGs(targetPayload, fuel, &targetPayload->ZFWCG, &targetPayload->TOCG, isImperial);
|
|
|
|
// in front of target
|
|
if (targetPayload->ZFWCG < targetPayload->CGTarget - CG_TOLERANCE) {
|
|
if (targetPayload->stations.upper1 > 0) {
|
|
targetPayload->stations.upper1--;
|
|
}
|
|
else if (targetPayload->stations.upper2 > 0) {
|
|
targetPayload->stations.upper2--;
|
|
}
|
|
else if (targetPayload->stations.upper3 > 0) {
|
|
targetPayload->stations.upper3--;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
|
|
if (targetPayload->stations.upper4 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper4++;
|
|
}
|
|
else if (targetPayload->stations.upper3 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper3++;
|
|
}
|
|
else if (targetPayload->stations.upper2 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper2++;
|
|
}
|
|
else {
|
|
targetPayload->stations.upper1++;
|
|
}
|
|
}
|
|
// behind target
|
|
else if (targetPayload->ZFWCG > targetPayload->CGTarget + CG_TOLERANCE) {
|
|
if (targetPayload->stations.upper4 > 0) {
|
|
targetPayload->stations.upper4--;
|
|
}
|
|
else if (targetPayload->stations.upper3 > 0) {
|
|
targetPayload->stations.upper3--;
|
|
}
|
|
else if (targetPayload->stations.upper2 > 0) {
|
|
targetPayload->stations.upper2--;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
|
|
if (targetPayload->stations.upper1 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper1++;
|
|
}
|
|
else if (targetPayload->stations.upper2 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper2++;
|
|
}
|
|
else if (targetPayload->stations.upper3 < MAX_UPPER_CARGO(isImperial)) {
|
|
targetPayload->stations.upper3++;
|
|
}
|
|
else {
|
|
targetPayload->stations.upper4++;
|
|
}
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
|
|
count--;
|
|
}
|
|
// Refinement cargo
|
|
count = MAX_FRONT_CARGO(isImperial) + MAX_REAR_CARGO(isImperial, isER);
|
|
while (count > 0) {
|
|
generatePayload(targetPayload, isImperial);
|
|
calculateCGs(targetPayload, fuel, &targetPayload->ZFWCG, &targetPayload->TOCG, isImperial);
|
|
|
|
// in front of target
|
|
if (targetPayload->ZFWCG < targetPayload->CGTarget - CG_TOLERANCE) {
|
|
if (targetPayload->lowerForward > 0 && targetPayload->lowerRear < MAX_REAR_CARGO(isImperial, isER)) {
|
|
targetPayload->lowerForward--;
|
|
targetPayload->lowerRear++;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
// behind target
|
|
else if (targetPayload->ZFWCG > targetPayload->CGTarget + CG_TOLERANCE) {
|
|
if (targetPayload->lowerRear > 0 && targetPayload->lowerForward < MAX_FRONT_CARGO(isImperial)) {
|
|
targetPayload->lowerRear--;
|
|
targetPayload->lowerForward++;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
|
|
count--;
|
|
}
|
|
}
|
|
|
|
// Updates pax stations with their respective weights
|
|
// Used internally and used for Station Entry (pax only, cargo is set directly)
|
|
void generatePayload(fPayloadData_t* const targetPayload, const bool isImperial) {
|
|
targetPayload->upper1Left = targetPayload->upper1Right = (targetPayload->stations.upper1 / 2.0);
|
|
targetPayload->upper2Left = targetPayload->upper2Right = (targetPayload->stations.upper2 / 2.0);
|
|
targetPayload->upper3Left = targetPayload->upper3Right = (targetPayload->stations.upper3 / 2.0);
|
|
targetPayload->upper4Left = targetPayload->upper4Right = (targetPayload->stations.upper4 / 2.0);
|
|
targetPayload->total = targetPayload->empty + targetPayload->pilot + targetPayload->firstOfficer + targetPayload->engineer + targetPayload->upper1Left +
|
|
targetPayload->upper1Right + targetPayload->upper2Left + targetPayload->upper2Right + targetPayload->upper3Left +
|
|
targetPayload->upper3Right + targetPayload->upper4Left + targetPayload->upper4Right + targetPayload->lowerForward +
|
|
targetPayload->lowerRear + targetPayload->leftAux + targetPayload->rightAux;
|
|
}
|
|
|
|
// Normalise to Pounds
|
|
// MANDATORY BEFORE SETTING WEIGHTS
|
|
// USE ON COPY OF GLOBAL STATE ONLY
|
|
void normalisePayload(fPayloadData_t* const targetPayload, const bool isImperial) {
|
|
targetPayload->empty = TO_POUNDS(isImperial, targetPayload->empty);
|
|
targetPayload->pilot = TO_POUNDS(isImperial, targetPayload->pilot);
|
|
targetPayload->firstOfficer = TO_POUNDS(isImperial, targetPayload->firstOfficer);
|
|
targetPayload->engineer = TO_POUNDS(isImperial, targetPayload->engineer);
|
|
targetPayload->upper1Left = TO_POUNDS(isImperial, targetPayload->upper1Left);
|
|
targetPayload->upper1Right = TO_POUNDS(isImperial, targetPayload->upper1Right);
|
|
targetPayload->upper2Left = TO_POUNDS(isImperial, targetPayload->upper2Left);
|
|
targetPayload->upper2Right = TO_POUNDS(isImperial, targetPayload->upper2Right);
|
|
targetPayload->upper3Left = TO_POUNDS(isImperial, targetPayload->upper3Left);
|
|
targetPayload->upper3Right = TO_POUNDS(isImperial, targetPayload->upper3Right);
|
|
targetPayload->upper4Left = TO_POUNDS(isImperial, targetPayload->upper4Left);
|
|
targetPayload->upper4Right = TO_POUNDS(isImperial, targetPayload->upper4Right);
|
|
targetPayload->lowerForward = TO_POUNDS(isImperial, targetPayload->lowerForward);
|
|
targetPayload->lowerRear = TO_POUNDS(isImperial, targetPayload->lowerRear);
|
|
targetPayload->leftAux = TO_POUNDS(isImperial, targetPayload->leftAux);
|
|
targetPayload->rightAux = TO_POUNDS(isImperial, targetPayload->rightAux);
|
|
}
|
|
|
|
void calculateCGs(const fPayloadData_t* const targetPayload, const FuelData_t* const fuel, double* const ZFWCG, double* const TOCG, const bool isImperial) {
|
|
fPayloadData_t localPayload = {};
|
|
memcpy(&localPayload, targetPayload, sizeof(localPayload));
|
|
normalisePayload(&localPayload, isImperial);
|
|
|
|
double totalMoment = localPayload.empty * ARM_EMPTY + localPayload.pilot * ARM_PILOT + localPayload.firstOfficer * ARM_FIRST_OFFICER +
|
|
localPayload.engineer * ARM_ENGINEER + localPayload.upper1Left * ARM_F_UPPER1_LEFT + localPayload.upper1Right * ARM_F_UPPER1_RIGHT +
|
|
localPayload.upper2Left * ARM_F_UPPER2_LEFT + localPayload.upper2Right * ARM_F_UPPER2_RIGHT + localPayload.upper3Left * ARM_F_UPPER3_LEFT +
|
|
localPayload.upper3Right * ARM_F_UPPER3_RIGHT + localPayload.upper4Left * ARM_F_UPPER4_LEFT + localPayload.upper4Right * ARM_F_UPPER4_RIGHT +
|
|
localPayload.lowerForward * ARM_FORWARD_CARGO + localPayload.lowerRear * ARM_REAR_CARGO + localPayload.leftAux * ARM_LEFT_AUX +
|
|
localPayload.rightAux * ARM_RIGHT_AUX;
|
|
|
|
double totalWeight = localPayload.empty + localPayload.pilot + localPayload.firstOfficer + localPayload.engineer + localPayload.upper1Left +
|
|
localPayload.upper1Right + localPayload.upper2Left + localPayload.upper2Right + localPayload.upper3Left + localPayload.upper3Right +
|
|
localPayload.upper4Left + localPayload.upper4Right + localPayload.lowerForward + localPayload.lowerRear + localPayload.leftAux +
|
|
localPayload.rightAux;
|
|
|
|
*ZFWCG = TO_PERCENT_MAC(totalMoment / totalWeight);
|
|
|
|
totalMoment += fuel->main1 * ARM_MAIN1 + fuel->main3 * ARM_MAIN3 + fuel->main2 * ARM_MAIN2 + fuel->upperAux * ARM_UPPER_AUX +
|
|
fuel->lowerAux * ARM_LOWER_AUX + fuel->main1Tip * ARM_MAIN1_TIP + fuel->main3Tip * ARM_MAIN3_TIP +
|
|
fuel->tail * ARM_TAIL + fuel->forwardAux1 * ARM_FORWARD_AUX1 + fuel->forwardAux2 * ARM_FORWARD_AUX2;
|
|
|
|
totalWeight += fuel->total;
|
|
|
|
*TOCG = TO_PERCENT_MAC(totalMoment / totalWeight);
|
|
}
|
|
|
|
void load(const fPayloadData_t* const targetPayload, const HANDLE simConnect, const bool isImperial) {
|
|
fPayloadData_t localPayload = {};
|
|
memcpy(&localPayload, targetPayload, sizeof(localPayload));
|
|
normalisePayload(&localPayload, isImperial);
|
|
|
|
SimConnect_SetDataOnSimObject(simConnect, DATA_DEFINITION_PAYLOAD_F, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(fPayloadDataSet_t), &localPayload);
|
|
}
|
|
|
|
void unloadF(const HANDLE simConnect, const bool isER) {
|
|
fPayloadData_t localPayload = {};
|
|
|
|
localPayload.leftAux = localPayload.rightAux = isER ? AUX_WEIGHT(true) : 0;
|
|
localPayload.pilot = localPayload.firstOfficer = localPayload.engineer = PILOT_WEIGHT(true);
|
|
|
|
SimConnect_SetDataOnSimObject(simConnect, DATA_DEFINITION_PAYLOAD_F, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(fPayloadDataSet_t), &localPayload);
|
|
}
|