I convert the global pos of the attaching ship to flattop local. If the ship is in range I create an attach point at the local x,z but snap it to the y of the deck. It is created with a losose connection so that the ship stays pointed in the direction it came in at. This does cause a few problems during saves and loads because you have to detach all the ships and then reattach them.
It is limited to 10 attach points.
Here is the attach code.
void QJFlat::AttachShip(DWORD inx_in){
VECTOR3 gaph, gpship, ourship;
// VECTOR3 aphpos, aphdir, aphrot;
ATTACHMENTHANDLE hAtt;
//find a free deck point
for(i=0;i<25;i++){
if(!GetAttachmentStatus(APDeck[i])) break;
}
if(i>23) return;
double grab_distance = 500.0, freeAP=0.0;
// get our position
oapiGetGlobalPos (GetHandle(), &ourship);
//I now know were we are so lets find the another ship
OBJHANDLE hV = oapiGetVesselByIndex(inx_in); //get requestor handle
oapiGetGlobalPos (hV, &gpship); // get global postion of requestor and put into gpship
// Make sure that the requestor is close enough to us
if (dist(gpship, ourship) < grab_distance) {
VESSEL *v = oapiGetVesselInterface (hV);
DWORD nAttach = v->AttachmentCount (true); //Get attachment count. I do this because there may be more than one child point.
if (nAttach > 0){ // Only continue if ship has a child attach point
for (DWORD j = 0; j < nAttach; j++) { // now scan all attachment points of the candidate
hAtt = v->GetAttachmentHandle (true, j);
// this allows me to filter out all but Fleet attach points.
const char *id = v->GetAttachmentId (hAtt);
Global2Local (gpship, gaph);
gaph.y = 52.549; //this is the top of the deck
SetAttachmentParams(APDeck[i], gaph, _V( 0, 0, 1), _V( 0, 1, 0)); //Set the attach point X and Z to the same place as the requesting ship.
if(!strncmp (id, "VAP", 3))AttachChild (hV, APDeck[i], hAtt);
if(!strncmp (id, "APR", 3))AttachChild (hV, APDeck[i], hAtt);
if(!strncmp (id, "APC", 3))AttachChild (hV, APDeck[i], hAtt);
if(!strncmp (id, "APW", 3))AttachChild (hV, APDeck[i], hAtt);
}
}
}
return;
}
Here is the save:
void QJFlat::clbkSaveState (FILEHANDLE scn)
{
char cbuf[256];
char cbuf2[25];
// default vessel parameters
VESSEL2::clbkSaveState (scn);
// custom parameters
sprintf (cbuf, "%0.4f", hdf_amt);
oapiWriteScenario_string (scn, "HDF", cbuf);
sprintf (cbuf, "%0.4f", fs_factor);
oapiWriteScenario_string (scn, "FSEN", cbuf);
sprintf (cbuf, "%0.4f", gs_factor);
oapiWriteScenario_string (scn, "GSEN", cbuf);
sprintf (cbuf, "%0.4f", wfxd);
oapiWriteScenario_string (scn, "WFXD", cbuf);
sprintf (cbuf, "%0.4f", djd);
oapiWriteScenario_string (scn, "DJD", cbuf);
sprintf (cbuf, "%d %0.4f", door_status, door_proc);
oapiWriteScenario_string (scn, "DOOR", cbuf);
for(i=0; i<10;i++){
if (GetAttachmentStatus(APDeck[i])){
oapiGetObjectName (GetAttachmentStatus(APDeck[i]), cbuf, 50);
sprintf (cbuf2, "AD%d%", i);
oapiWriteScenario_string (scn, cbuf2, cbuf);
}
}
DetachShips();
}
Here is the reattach code on load
void QJFlat::clbkLoadStateEx (FILEHANDLE scn, void *vs)
{
char *line;
sprintf (apdname0, "");
sprintf (apdname1, "");
sprintf (apdname2, "");
sprintf (apdname3, "");
sprintf (apdname4, "");
sprintf (apdname5, "");
sprintf (apdname6, "");
sprintf (apdname7, "");
sprintf (apdname8, "");
sprintf (apdname9, "");
// VECTOR3 apdpos, apddir, apdrot;
while (oapiReadScenario_nextline (scn, line)) {
if (!_strnicmp (line, "HDF", 3)) {
sscanf (line+3, "%lf", &hdf_amt);
} else if (!_strnicmp (line, "FSEN", 4)) {
sscanf (line+4, "%lf", &fs_factor);
} else if (!_strnicmp (line, "GSEN", 4)) {
sscanf (line+4, "%lf", &gs_factor);
} else if (!_strnicmp (line, "WFXD", 4)) {
sscanf (line+4, "%lf", &wfxd);
} else if (!_strnicmp (line, "DJD", 3)) {
sscanf (line+3, "%lf", &djd);
} else if (!_strnicmp (line, "DOOR", 4)) {
sscanf (line+4, "%d%lf", &door_status, &door_proc);
} else if (!_strnicmp (line, "AD0", 3)) {
sscanf (line+3, "%s", &apdname0);
} else if (!_strnicmp (line, "AD1", 3)) {
sscanf (line+3, "%s", &apdname1);
} else if (!_strnicmp (line, "AD2", 3)) {
sscanf (line+3, "%s", &apdname2);
} else if (!_strnicmp (line, "AD3", 3)) {
sscanf (line+3, "%s", &apdname3);
} else if (!_strnicmp (line, "AD4", 3)) {
sscanf (line+3, "%s", &apdname4);
} else if (!_strnicmp (line, "AD5", 3)) {
sscanf (line+3, "%s", &apdname5);
} else if (!_strnicmp (line, "AD6", 3)) {
sscanf (line+3, "%s", &apdname6);
} else if (!_strnicmp (line, "AD7", 3)) {
sscanf (line+3, "%s", &apdname7);
} else if (!_strnicmp (line, "AD8", 3)) {
sscanf (line+3, "%s", &apdname8);
} else if (!_strnicmp (line, "AD9", 3)) {
sscanf (line+3, "%s", &apdname9);
} else {
ParseScenarioLineEx (line, vs);
// unrecognised option - pass to Orbiter's generic parser
}
}
SetAnimation (anim_door, door_proc);
if (fs_factor <= 0.0) fs_factor = 0.25;
if (gs_factor <= 0.0) gs_factor = 10.0;
if (djd <= 0.0) djd = DEFAULT_JUMP_DISTANCE;
}
void QJFlat::clbkPostCreation ()
{
MyID=ConnectToOrbiterSoundDLL3(GetHandle());
RequestLoadVesselWave3(MyID,HDBUILD, "Sound\\QJBay\\HDBUILD.wav", INTERNAL_ONLY);
RequestLoadVesselWave3(MyID,HDSTOP, "Sound\\QJBay\\HDSTOP.wav", INTERNAL_ONLY);
RequestLoadVesselWave3(MyID,FFSYNC, "Sound\\QJBay\\FFSYNC.wav", INTERNAL_ONLY);
APDeckHandle[0] = oapiGetVesselByName(apdname0);
APDeckHandle[1] = oapiGetVesselByName(apdname1);
APDeckHandle[2] = oapiGetVesselByName(apdname2);
APDeckHandle[3] = oapiGetVesselByName(apdname3);
APDeckHandle[4] = oapiGetVesselByName(apdname4);
APDeckHandle[5] = oapiGetVesselByName(apdname5);
APDeckHandle[6] = oapiGetVesselByName(apdname6);
APDeckHandle[7] = oapiGetVesselByName(apdname7);
APDeckHandle[8] = oapiGetVesselByName(apdname8);
APDeckHandle[9] = oapiGetVesselByName(apdname9);
for(i=0;i<10;i++){
for (DWORD the_inx = 0; the_inx < oapiGetVesselCount(); the_inx++){
if(oapiGetVesselByIndex (the_inx) == APDeckHandle[i]){
AttachShip(the_inx);
break; //Got index so bail out of for loop
}
}
}