- Joined
- Apr 14, 2012
- Messages
- 2,585
- Reaction score
- 0
- Points
- 36
Okay, RCS thrusters are up, and I have exhausts working for those too. I finished modelling a nice little support vessel that will carry 2 UCGO cargoes when finished. Big thanks to Jedida for the help identifying the dumb mistake that was causing that to CTD.
Anyways, I believe Ive been able to integrate UCGO, however the HUD displays, which were working previously with UMMU have dissappeared. Does anyone see what the problem is?
Header File
and the CPP
Anyways, I believe Ive been able to integrate UCGO, however the HUD displays, which were working previously with UMMU have dissappeared. Does anyone see what the problem is?
Header File
Code:
#pragma once
#include "Orbitersdk.h"
#include "UMmuSDK.h"
#include "UCGOCargoSDK.h" //UCGO 2.0 copy past this line
// Vessel Parameters
const double EXP_SIZE = 37.4; // mean radius in meters
const VECTOR3 EXP_CS = {95,82,20}; //Shuttle-D cross section in m^2
const VECTOR3 EXP_PMI = {14.00,16.00,2.20}; //Principal Moments of Inertia, normalized, m^2
const double EXP_EMPTYMASS = 16970; //empty vessel mass in kg
const double EXP_FUELMASS = 18000; //max fuel mass in kg
const double EXP_RCS1FUELMASS = 120; //max fuel mass in kg
const double EXP_RCS2FUELMASS = 120; //max fuel mass in kg
const double EXP_RCS3FUELMASS = 120; //max fuel mass in kg
const double EXP_RCS4FUELMASS = 120; //max fuel mass in kg
const double EXP_RCS5FUELMASS = 120; //max fuel mass in kg
const double EXP_RCS6FUELMASS = 120; //max fuel mass in kg
const double EXP_RCS7FUELMASS = 120; //max fuel mass in kg
const double EXP_RCS8FUELMASS = 120; //max fuel mass in kg
const double EXP_RCS9FUELMASS = 120; //max fuel mass in kg
const double EXP_RCS10FUELMASS = 120; //max fuel mass in kg
const double EXP_RCS11FUELMASS = 120; //max fuel mass in kg
const double EXP_RCS12FUELMASS = 120; //max fuel mass in kg
const double EXP_RCS13FUELMASS = 120; //max fuel mass in kg
const double EXP_RCS14FUELMASS = 120; //max fuel mass in kg
const double EXP_RCSRESFUELMASS = 1000; //max fuel mass in kg
const double VACSHD_ISP = 30000; //fuel-specific impulse in m/s
const double NMLSHD_ISP = 25000; //fuel-specific impulse in m/s
const double P_NML = 101.4e3;
const double EXP_MAXMAINTH = 250000;
const double EXP_MAXHOVERTH = 94000;
const double EXP_RCSTH0 = 1200;
const double EXP_RCSTH1 = 1200;
const double EXP_RCSTH2 = 1200;
const double EXP_RCSTH3 = 1200;
const double EXP_RCSTH4 = 1200;
const double EXP_RCSTH5 = 1200;
const double EXP_RCSTH6 = 1200;
const double EXP_RCSTH7 = 1200;
const double EXP_RCSTH8 = 1200;
const double EXP_RCSTH9 = 1200;
const double EXP_RCSTH10 = 1200;
const double EXP_RCSTH11 = 1200;
const double EXP_RCSTH12 = 1200;
const double EXP_RCSTH13 = 1200;
const double EXP_RCSTH14 = 1200;
const double EXP_RCSTH15 = 1200;
const double GEAR_OPERATING_SPEED = 0.10;
const double PLBAYA_OPERATING_SPEED = 0.07;
const double PLBAYB_OPERATING_SPEED = 0.18;
class ShuttleD :public VESSEL3
{
public:
ShuttleD (OBJHANDLE hObj, int fmodel);
MESHHANDLE DVCInterior;
void DefineAnimations();
void clbkSetClassCaps (FILEHANDLE cfg);
void clbkLoadStateEx (FILEHANDLE scn, void *status);
// void clbkDrawHUD (int mode, const HUDPAINTSPEC *hps, HDC hDC, oapi::Sketchpad *skp );
bool clbkDrawHUD (int mode, const HUDPAINTSPEC *hps, HDC hDC, oapi::Sketchpad *skp);
void clbkSaveState (FILEHANDLE scn);
void clbkPostStep (double simtt, double simdt, double mjd);
void RevertGEAR (void);
void RevertPLBAYA (void);
void RevertPLBAYB (void);
void clbkPreStep (double simt, double simdt, double mjd);
void clbkPostCreation(void);
enum GEARStatus { GEAR_UP, GEAR_DOWN, GEAR_RAISING, GEAR_LOWERING } GEAR_status;
enum PLBAYAStatus { PLBAYA_UP, PLBAYA_DOWN, PLBAYA_CLOSING, PLBAYA_OPENING } PLBAYA_status;
enum PLBAYBStatus { PLBAYB_UP, PLBAYB_DOWN, PLBAYB_CLOSING, PLBAYB_OPENING } PLBAYB_status;
enum {CAM_VCPILOT, CAM_VCPSNGR1, CAM_VCPSNGR2, CAM_VCPSNGR3, CAM_VCPSNGR4} campos;
int SHD; // this is your unique Id, it will identify your ship in OrbiterSound.
// enum DoorStatus { DOOR_CLOSED, DOOR_OPEN, DOOR_CLOSING, DOOR_OPENING } gear_status;
int clbkConsumeBufferedKey (DWORD key, bool down, char *kstate);
void clbkVisualCreated (VISHANDLE vis, int refcount);
void clbkMFDMode (int mfd, int mode);
bool clbkLoadVC (int id);
bool clbkVCRedrawEvent (int id, int event, SURFHANDLE surf);
bool clbkVCMouseEvent (int id, int event, VECTOR3 &p);
VCMFDSPEC mfds_left;
// UMMU 2.0 DECLARATION
UMMUCREWMANAGMENT Crew;
int SelectedUmmuMember; // for the SDK demo, select the member to eva
int iActionAreaDemoStep; // this is just to show one feature of action area.
void clbkSetClassCaps_UMMu(void); // our special SetClassCap function just added for more readability
// The HUD display method variable, see PDF doc
char cUmmuHudDisplay[255]; // UMmu hud char variable
double dHudMessageDelay; // UMmu hud display delay
char *SendHudMessage(void); // UMmu hud display function
// THIS IS FOR ADDING CREW SEE PDF doc "Allow user to add crew to your ship
// without scenery editor"
char cAddUMmuToVessel[255];
void AddUMmuToVessel(BOOL bStartAdding=FALSE);
// UCGO SPECIFIC CODE OF CLASS HEADER **********************************
void clbkSetClassCapsUCgo (void); // a custom UCGO clbkSetClassCap just to keep code clear
// UCGO 2.0 CLASS HANDLE FUNCTION AND VARIABLES
UCGO hUcgo; // Cargo class handle
char *SendCargHudMessage(void); // Cargo hud display function
char cCargoHudDisplay[255]; // Cargo hud display char variable
double dCargHudMessageDelay; // Cargo hud display delay
int iSelectedCargo; // for the selection of cargos -1 by default
private:
double myparam;
UINT anim_gear;
UINT anim_PLBAYA;
UINT anim_PLBAYB;
UINT anim_airlock_switch;
double GEAR_proc,PLBAYA_proc,PLBAYB_proc;
//double LIFT_SPEED;
};
HINSTANCE hDLL;
HFONT hFont;
HPEN hPen;
HBRUSH hBrush;
#define AID_MFD1_LBUTTONS 0
#define AID_MFD1_RBUTTONS 1
#define MFD1_LBUTTON1 2
#define MFD1_LBUTTON2 3
#define MFD1_LBUTTON3 4
#define MFD1_LBUTTON4 5
#define MFD1_LBUTTON5 6
#define MFD1_LBUTTON6 7
#define MFD1_RBUTTON1 8
#define MFD1_RBUTTON2 9
#define MFD1_RBUTTON3 10
#define MFD1_RBUTTON4 11
#define MFD1_RBUTTON5 12
#define MFD1_RBUTTON6 13
#define MFD1_BBUTTON1 14
#define MFD1_BBUTTON2 15
#define MFD1_BBUTTON3 16
and the CPP
Code:
// SHD.cpp : Defines the exported functions for the DLL application.
//
#define STRICT
#define ORBITER_MODULE
#include "D9base.h"
#include "orbitersdk.h"
#include <math.h>
#include <stdio.h>
#include "OrbiterSoundSDK35.h"
#define MY500METERSOUND 1 // those are definition so all function will be more clear to read..
#define MYRADARSOUND 2 // because we will know wich sound is concerned by function instead
#define MYEXTERNAL_UFO_FADEDSOUND 3 // of having simple number.
#define GEARUP 4
#define GEARDOWN 5
#define PLBAYAOPEN 6
#define PLBAYACLOSE 7
#define PLBAYBOPEN 8
#define PLBAYBCLOSE 9
//#include "ShuttleDUCGOCargo.h"
HINSTANCE g_hDLL;
VISHANDLE MainExternalMeshVisual = 0;
// ==============================================================
// Airfoil definition
// ==============================================================
void Shuttle_MomentCoeff (double aoa,double M,double Re,double *cl,double *cm,double *cd)
{
int i;
const int nabsc = 7;
static const double AOA[nabsc] = {-180*RAD, -90*RAD,-30*RAD, 0*RAD, 60*RAD,90*RAD,180*RAD};
static const double CL[nabsc] = { 0, 0, -0.004, 0, 0.008, 0, 0};
static const double CM[nabsc] = { 0, 0, 0.0014, 0,-0.0012, 0, 0};
for (i = 0; i < nabsc-1 && AOA[i+1] < aoa; i++);
double f = (aoa-AOA[i]) / (AOA[i+1]-AOA[i]);
*cl = CL[i] + (CL[i+1]-CL[i]) * f; // aoa-dependent lift coefficient
*cm = CM[i] + (CM[i+1]-CM[i]) * f; // aoa-dependent moment coefficient
double saoa = sin(aoa);
double pd = 0.045 + 0.4*saoa*saoa; // profile drag
*cd = pd + oapiGetInducedDrag (*cl, 0.1,0.7) + oapiGetWaveDrag (M, 0.75, 1.0, 1.1, 0.04);
// profile drag + (lift-)induced drag + transonic/supersonic wave (compressibility) drag
}
ShuttleD::ShuttleD (OBJHANDLE hObj, int fmodel)
: VESSEL3 (hObj, fmodel)
{
GEAR_status = GEAR_UP;
GEAR_proc = 0.0;
PLBAYA_status = PLBAYA_UP;
PLBAYA_proc = 0.0;
PLBAYB_status = PLBAYB_UP;
PLBAYB_proc = 0.0;
DefineAnimations();
}
//=========================================================
// Vessel Animations
//=========================================================
void ShuttleD::DefineAnimations()
{
//ANIMATIONCOMPONENT_HANDLE parent;
static UINT gearback[1] = {26};
static MGROUP_ROTATE gear (
0,
gearback,
1,
_V(0,-2.3,-22.9),
_V(1,0,0),
(float)(-90*RAD)
);
static UINT gearfront[1] = {27};
static MGROUP_ROTATE gearf (
0,
gearfront,
1,
_V(0,-2.3,29.8),
_V(1,0,0),
(float)(90*RAD)
);
anim_gear = CreateAnimation (0);
AddAnimationComponent (anim_gear, 0, 1, &gear);
AddAnimationComponent (anim_gear, 0, 1, &gearf);
static UINT PLBAYA[1] = {21};
static MGROUP_ROTATE PLBAYA1 (
0,
PLBAYA,
1,
_V(0.858,-1.721666,0),
_V(0,0,1),
(float)(90*RAD)
);
anim_PLBAYA = CreateAnimation (0);
AddAnimationComponent (anim_PLBAYA, 0, 1, &PLBAYA1);
static UINT PLBAYB[1] = {17};
static MGROUP_ROTATE PLBAYB1 (
0,
PLBAYB,
1,
_V(0,4.513,-23.72),
_V(1,0,0),
(float)(-90*RAD)
);
anim_PLBAYB = CreateAnimation (0);
AddAnimationComponent (anim_PLBAYB, 0, 1, &PLBAYB1);
}
//void ShuttleD::Activategear(DoorStatus action)
//{
// gear_status = action;
//}
void ShuttleD::RevertGEAR (void)
{
GEAR_status = ((GEAR_status == GEAR_UP || GEAR_status == GEAR_RAISING) ?
GEAR_LOWERING : GEAR_RAISING);
}
void ShuttleD::RevertPLBAYA (void)
{
PLBAYA_status = ((PLBAYA_status == PLBAYA_UP || PLBAYA_status == PLBAYA_CLOSING) ?
PLBAYA_OPENING : PLBAYA_CLOSING);
}
void ShuttleD::RevertPLBAYB (void)
{
PLBAYB_status = ((PLBAYB_status == PLBAYB_UP || PLBAYB_status == PLBAYB_CLOSING) ?
PLBAYB_OPENING : PLBAYB_CLOSING);
}
//void ShuttleD::Activategear (DoorStatus action)
// --------------------------------------------------------------
//
// --------------------------------------------------------------
//void ShuttleD::Revertgear ()
//{
// Activategear (gear_status == DOOR_CLOSED || gear_status == DOOR_CLOSING ?
// DOOR_OPENING : DOOR_CLOSING);
//}
char *ShuttleD::SendHudMessage() //<---- Change the class name here
{
dHudMessageDelay=15;
return cUmmuHudDisplay;
}
//=========================================================
// Vessel Capabilities
//=========================================================
void ShuttleD::clbkSetClassCaps (FILEHANDLE cfg)
{
// our call to our custom UCGO clbkSetClassCap
// the only purpose is to keep code clear
clbkSetClassCapsUCgo();
Crew.InitUmmu(GetHandle());
float UMmuVersion=Crew.GetUserUMmuVersion();
// double UMmuVersion=Crew.GetUserUMmuVersion();
Crew.DefineAirLockShape(TRUE,-1,1,-2.94,2.94, 29,32);
Crew.SetMembersPosRotOnEVA(_V(0,-0.837,31.005),_V(0,-180,0));
Crew.SetMaxSeatAvailableInShip(7);
Crew.DeclareActionArea(0,_V(-5,0,0),2.5,TRUE,"action_activated.wav","You are on the left of the ship");
Crew.DeclareActionArea(1,_V(5,0,0),2.5,TRUE, "action_repaired.wav","You are on the right of the ship");
Crew.DeclareActionArea(2,_V(0,0,5),2.5,TRUE, "action_activated.wav","You are in front of the ship");
Crew.DeclareActionArea(3,_V(0,0,-5),2.5,TRUE,"action_activated.wav","You are behind the ship");
iActionAreaDemoStep=0; // this is just to show a feature of action area, see below "DetectActionAreaActivated"
SelectedUmmuMember =0; // our current selected member
// The HUD display method variables, see PDF doc
cUmmuHudDisplay[0] =0; // Initialisation of UMmu hud char variable
dHudMessageDelay =0; // Initialisation of UMmu delay variable
strcpy(SendHudMessage(),"Welcome aboard ! E=EVA 1,2=select UMmu\n A=Open/Close airlock S=info M=add crew");
// The Add mmu without scenery editor variable see PDF doc
cAddUMmuToVessel[0]=0;
THRUSTER_HANDLE th_main, th_hover, th_rcs[14], th_group[4];
DOCKHANDLE Dock0, Dock1;
// vessel caps definitions
AddMesh ("Shuttle-D");
SetMeshVisibilityMode (AddMesh (DVCInterior = oapiLoadMeshGlobal ("ShuttleDVC")), MESHVIS_VC);
SetCameraOffset (_V(0,0.24,0.13));
SetAlbedoRGB (_V(0.77,0.20,0.73));
SetSize (EXP_SIZE);
SetEmptyMass (EXP_EMPTYMASS);
void UpdateEmptyMass(void);
SetPMI (EXP_PMI);
SetCrossSections (EXP_CS);
SetSurfaceFrictionCoeff (0.55, 0.79);
SetRotDrag (_V(0.9, 0.76, 0.2));
EnableTransponder (true);
InitNavRadios (4);
// propellant resources
PROPELLANT_HANDLE hpr = CreatePropellantResource (EXP_FUELMASS);
PROPELLANT_HANDLE RCS1 = CreatePropellantResource (EXP_RCS1FUELMASS);
PROPELLANT_HANDLE RCS2 = CreatePropellantResource (EXP_RCS2FUELMASS);
PROPELLANT_HANDLE RCS3 = CreatePropellantResource (EXP_RCS3FUELMASS);
PROPELLANT_HANDLE RCS4 = CreatePropellantResource (EXP_RCS4FUELMASS);
PROPELLANT_HANDLE RCS5 = CreatePropellantResource (EXP_RCS5FUELMASS);
PROPELLANT_HANDLE RCS6 = CreatePropellantResource (EXP_RCS6FUELMASS);
PROPELLANT_HANDLE RCS7 = CreatePropellantResource (EXP_RCS7FUELMASS);
PROPELLANT_HANDLE RCS8 = CreatePropellantResource (EXP_RCS8FUELMASS);
PROPELLANT_HANDLE RCS9 = CreatePropellantResource (EXP_RCS9FUELMASS);
PROPELLANT_HANDLE RCS10 = CreatePropellantResource (EXP_RCS10FUELMASS);
PROPELLANT_HANDLE RCS11 = CreatePropellantResource (EXP_RCS11FUELMASS);
PROPELLANT_HANDLE RCS12 = CreatePropellantResource (EXP_RCS12FUELMASS);
PROPELLANT_HANDLE RCS13 = CreatePropellantResource (EXP_RCS13FUELMASS);
PROPELLANT_HANDLE RCS14 = CreatePropellantResource (EXP_RCS14FUELMASS);
PROPELLANT_HANDLE RCSRES = CreatePropellantResource (EXP_RCSRESFUELMASS);
// main engine
th_main = CreateThruster (_V(0,0,-31.45), _V(0,0,1), EXP_MAXMAINTH, hpr, VACSHD_ISP, NMLSHD_ISP, P_NML);
CreateThrusterGroup (&th_main, 1, THGROUP_MAIN);
AddExhaust (th_main, 8, 1, _V(0,0.23,-31.45), _V(0,0,-1));
PARTICLESTREAMSPEC contrail_main = {
0, 5.0, 16, 200, 0.15, 1.0, 5, 3.0, PARTICLESTREAMSPEC::DIFFUSE,
PARTICLESTREAMSPEC::LVL_PSQRT, 0, 2,
PARTICLESTREAMSPEC::ATM_PLOG, 1e-4, 1
};
PARTICLESTREAMSPEC exhaust_main = {
0, 2.0, 20, 200, 0.05, 0.1, 8, 1.0, PARTICLESTREAMSPEC::EMISSIVE,
PARTICLESTREAMSPEC::LVL_SQRT, 0, 1,
PARTICLESTREAMSPEC::ATM_PLOG, 1e-5, 0.1
};
AddExhaustStream (th_main, _V(0,0.3,-10), &contrail_main);
AddExhaustStream (th_main, _V(0,0.3,-5), &exhaust_main);
// hover engine
th_hover = CreateThruster (_V(0,-2.94,0), _V(0,1,0), EXP_MAXHOVERTH, hpr, VACSHD_ISP, NMLSHD_ISP, P_NML);
CreateThrusterGroup (&th_hover, 1, THGROUP_HOVER);
AddExhaust (th_hover, 8, 1, _V(0.0,-2.94,-17.09), _V(0,-1,0));
AddExhaust (th_hover, 8, 1, _V(0.0,-2.94,23.62), _V(0,-1,0));
PARTICLESTREAMSPEC contrail_hover = {
0, 5.0, 8, 200, 0.15, 1.0, 5, 3.0, PARTICLESTREAMSPEC::DIFFUSE,
PARTICLESTREAMSPEC::LVL_PSQRT, 0, 2,
PARTICLESTREAMSPEC::ATM_PLOG, 1e-4, 1
};
PARTICLESTREAMSPEC exhaust_hover = {
0, 2.0, 10, 200, 0.05, 0.05, 8, 1.0, PARTICLESTREAMSPEC::EMISSIVE,
PARTICLESTREAMSPEC::LVL_SQRT, 0, 1,
PARTICLESTREAMSPEC::ATM_PLOG, 1e-5, 0.1
};
AddExhaustStream (th_hover, _V(0,-3, 1), &contrail_hover);
AddExhaustStream (th_hover, _V(0,-3,-1), &contrail_hover);
AddExhaustStream (th_hover, _V(0,-2, 1), &exhaust_hover);
AddExhaustStream (th_hover, _V(0,-2,-1), &exhaust_hover);
// RCS engines
th_rcs[0] = CreateThruster (_V( 2,0, 30), _V(0,0,1), EXP_RCSTH0, RCS1, VACSHD_ISP, NMLSHD_ISP, P_NML);//CM FRONT RIGHT SIDE FORWARD
th_rcs[1] = CreateThruster (_V( -2,0,30), _V(0,0,1), EXP_RCSTH1, RCS2, VACSHD_ISP, NMLSHD_ISP, P_NML);//CM FRONT LEFT SIDE FORWARD
th_rcs[2] = CreateThruster (_V(3,0, 30), _V(-1, 0,0), EXP_RCSTH2, RCS3, VACSHD_ISP, NMLSHD_ISP, P_NML);//CM FRONT RIGHT SIDE RIGHT
th_rcs[3] = CreateThruster (_V(-3,0, 30), _V(1,0,0), EXP_RCSTH3, RCS4, VACSHD_ISP, NMLSHD_ISP, P_NML);//CM FRONT LEFT SIDE LEFT
th_rcs[4] = CreateThruster (_V( 2,2,22.20), _V(0, 1,0), EXP_RCSTH4, RCS5, VACSHD_ISP, NMLSHD_ISP, P_NML);//TRUSS FORWARD RIGHT SIDE UP
th_rcs[5] = CreateThruster (_V( -2,2,22.20), _V(0,1,0), EXP_RCSTH5, RCS6, VACSHD_ISP, NMLSHD_ISP, P_NML);//TRUSS FORWARD LEFT SIDE UP
th_rcs[6] = CreateThruster (_V(2,-2,22.20), _V(0,-1,0), EXP_RCSTH6, RCS7, VACSHD_ISP, NMLSHD_ISP, P_NML);//TRUSS FORWARD RIGHT SIDE DOWN
th_rcs[7] = CreateThruster (_V(-2,-2,22.20), _V(0,-1,0), EXP_RCSTH7, RCS8, VACSHD_ISP, NMLSHD_ISP, P_NML);//TRUSS FORWARD LEFT SIDE DOWN
th_rcs[8] = CreateThruster (_V( 2,2, -14), _V(0,1,0), EXP_RCSTH8, RCS9, VACSHD_ISP, NMLSHD_ISP, P_NML);//TRUSS AFT RIGHT SIDE UP
th_rcs[9] = CreateThruster (_V( -2,2, -14), _V( 0,1,0), EXP_RCSTH9, RCS10, VACSHD_ISP, NMLSHD_ISP, P_NML);//TRUSS AFT LEFT SIDE UP
th_rcs[10] = CreateThruster (_V(2,-2,-14), _V(0,-1,0), EXP_RCSTH10, RCS11, VACSHD_ISP, NMLSHD_ISP, P_NML);//TRUSS AFT RIGHT SIDE DOWN
th_rcs[11] = CreateThruster (_V(-2,-2,-14), _V( 0,-1,0), EXP_RCSTH11, RCS12, VACSHD_ISP, NMLSHD_ISP, P_NML);//TRUSS AFT LEFT SIDE DOWN
th_rcs[12] = CreateThruster (_V( 1.59,0.037,-18.595), _V(0,0, -1), EXP_RCSTH12, RCS13, VACSHD_ISP, NMLSHD_ISP, P_NML);//SM BACK RIGHT SIDE BACKWARDS
th_rcs[13] = CreateThruster (_V( -1.59,0.037,-18.595), _V(0,0,-1), EXP_RCSTH13, RCS14, VACSHD_ISP, NMLSHD_ISP, P_NML);//SM BACK LEFT SIDE BACKWARDS
th_rcs[14] = CreateThruster (_V(1.84,0.037,-18.193), _V( -1,0,0), EXP_RCSTH14, RCS12, VACSHD_ISP, NMLSHD_ISP, P_NML);//SM BACK RIGHT SIDE RIGHT
th_rcs[15] = CreateThruster (_V( -1.84,0.037,-18.193), _V(1,0, 0), EXP_RCSTH15, RCS13, VACSHD_ISP, NMLSHD_ISP, P_NML);//SM BACK LEFT SIDE LEFT
AddExhaust (th_rcs[12], 0.6, 0.078, _V( 1.601,0.100, 29.777), _V(0,0,1));
AddExhaust (th_rcs[13], 0.6, 0.078, _V( -1.601,0.100,29.777), _V(0,0,1));
AddExhaust (th_rcs[2], 0.79, 0.103, _V(1.8505,0.100, 29.265), _V(-1, 0,0));
AddExhaust (th_rcs[3], 0.79, 0.103, _V(-1.8505,0.100, 29.265), _V(1,0,0));
AddExhaust (th_rcs[6], 0.6, 0.078, _V( 1.101,2.04,21.208), _V(0, 1,0));
AddExhaust (th_rcs[7], 0.6, 0.078, _V( -1.101,2.04,21.208), _V(0,1,0));
AddExhaust (th_rcs[4], 0.79, 0.103, _V(1.101,-1.736,21.208), _V(0,-1,0));
AddExhaust (th_rcs[5], 0.79, 0.103, _V(-1.101,-1.736,21.208), _V(0,-1,0));
AddExhaust (th_rcs[10], 0.6, 0.078, _V( 1.101,2.04, -11.103), _V(0,1,0));
AddExhaust (th_rcs[11], 0.6, 0.078, _V( -1.101,2.04, -11.103), _V( 0,1,0));
AddExhaust (th_rcs[8], 0.79, 0.103, _V(1.101,-1.736,-11.103), _V(0,-1,0));
AddExhaust (th_rcs[9], 0.79, 0.103, _V(-1.101,-1.736,-11.103), _V( 0,-1,0));
AddExhaust (th_rcs[0], 0.6, 0.078, _V( 1.59,0.037,-18.595), _V(0,0, -1));
AddExhaust (th_rcs[1], 0.6, 0.078, _V( -1.59,0.037,-18.595), _V(0,0,-1));
AddExhaust (th_rcs[14], 0.79, 0.103, _V(1.84,0.037,-18.193), _V( -1,0,0));
AddExhaust (th_rcs[15], 0.79, 0.103, _V( -1.84,0.037,-18.193), _V(1,0, 0));
th_group[0] = th_rcs[4];
th_group[1] = th_rcs[5];
th_group[2] = th_rcs[10];
th_group[3] = th_rcs[11];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_PITCHUP);
th_group[0] = th_rcs[6];
th_group[1] = th_rcs[7];
th_group[2] = th_rcs[8];
th_group[3] = th_rcs[9];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_PITCHDOWN);
th_group[0] = th_rcs[4];
th_group[1] = th_rcs[7];
th_group[2] = th_rcs[8];
th_group[3] = th_rcs[11];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_BANKLEFT);
th_group[0] = th_rcs[5];
th_group[1] = th_rcs[6];
th_group[2] = th_rcs[9];
th_group[3] = th_rcs[10];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_BANKRIGHT);
th_group[0] = th_rcs[4];
th_group[1] = th_rcs[5];
th_group[2] = th_rcs[8];
th_group[3] = th_rcs[9];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_UP);
th_group[0] = th_rcs[6];
th_group[1] = th_rcs[7];
th_group[2] = th_rcs[10];
th_group[3] = th_rcs[11];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_DOWN);
th_group[0] = th_rcs[2];
th_group[1] = th_rcs[15];
CreateThrusterGroup (th_group, 2, THGROUP_ATT_YAWLEFT);
th_group[0] = th_rcs[3];
th_group[1] = th_rcs[14];
CreateThrusterGroup (th_group, 2, THGROUP_ATT_YAWRIGHT);
th_group[0] = th_rcs[2];
th_group[1] = th_rcs[14];
CreateThrusterGroup (th_group, 2, THGROUP_ATT_LEFT);
th_group[0] = th_rcs[3];
th_group[1] = th_rcs[15];
CreateThrusterGroup (th_group, 2, THGROUP_ATT_RIGHT);
th_group[0] = th_rcs[0];
th_group[1] = th_rcs[1];
CreateThrusterGroup (th_group, 2, THGROUP_ATT_FORWARD);
th_group[0] = th_rcs[12];
th_group[1] = th_rcs[13];
CreateThrusterGroup (th_group, 2, THGROUP_ATT_BACK);
Dock0 = CreateDock(_V(0,-0.637,30.455),_V(0,0,1),_V(0,1,0));
Dock1 = CreateDock(_V(0,2.730,-17.498),_V(0,1,0),_V(0,0,1));
}
void ShuttleD::clbkSetClassCapsUCgo (void)
{
//UCGO 2.0 Initialisation, cargo slot pos, rot declaration
hUcgo.Init(GetHandle());
// in contrary of the PDF code we declare 6 slots
// because it's fun :)
hUcgo.DeclareCargoSlot(0,_V(0,2.6,-3.50),_V(0,0,0)); // slot 0
hUcgo.DeclareCargoSlot(1,_V(0,1.3,-3.50),_V(0,0,90)); // slot 1
hUcgo.DeclareCargoSlot(2,_V(0,0,-3.50),_V(0,0,180)); // slot 2
hUcgo.DeclareCargoSlot(3,_V( 0,-1.3,-3.50),_V(0,0,270)); // slot 3
hUcgo.DeclareCargoSlot(4,_V(0,-2.6,-3.50),_V(0,0,0)); // slot 4
hUcgo.DeclareCargoSlot(5,_V( 0,-3.9,-3.50),_V(0,0,0)); // slot 5
// UCGO 2.0 Parameters settings
hUcgo.SetReleaseSpeedInSpace(0.10f); // release speed of cargo in space in m/s
hUcgo.SetMaxCargoMassAcceptable(10000.0); // max cargo mass in kg that your vessel can carry
hUcgo.SetGrappleDistance(50); // grapple distance radius in meter from center of ship
hUcgo.SetSlotGroundReleasePos(0 ,_V(-4,2.6,-3.50));
hUcgo.SetSlotGroundReleasePos(1 ,_V(-4,1.3,-3.50));
hUcgo.SetSlotGroundReleasePos(2 ,_V(-4,0,-3.50));
hUcgo.SetSlotGroundReleasePos(3 ,_V(-4,-1.3,-3.50));
hUcgo.SetSlotGroundReleasePos(4 ,_V(-4,-2.6,-3.50));
hUcgo.SetSlotGroundReleasePos(5 ,_V(-4,-3.9,-3.50));
// UCGO Variables initialisation
cCargoHudDisplay[0]=0; // Cargo hud display char variable
dCargHudMessageDelay=0; // Cargo hud display delay
iSelectedCargo=-1; // for the selection of cargos (-1 mean "default" see header)
// welcome message with keys for users
strcpy(SendCargHudMessage(),"Cargo key: C/SHF+C = grapple/release, 9/SHF+9 = snc editor add cargo, 8=infos on cargos");
}
void ShuttleD::clbkMFDMode (int mfd, int mode)
{
// When an MFD changes mode (either in Panel or VC modes), this call back is
// invoked. Here, it is a general TriggerRedrawArea function used, which can
// be used to redraw MFD's for VC or Panel views. You can just as effectively
// use oapiTriggerVCRedrawArea for this ship, however, as there is no 2D panel.
switch (mfd) {
case MFD_LEFT:
oapiTriggerRedrawArea (0, 0, AID_MFD1_LBUTTONS);
oapiTriggerRedrawArea (0, 0, AID_MFD1_RBUTTONS);
break;
}
}
//-------------------------------------------------------------------------
bool ShuttleD::clbkLoadVC (int id)
{
// VCHUDSPEC hud;
VCMFDSPEC mfd;
mfd.ngroup=15;
mfd.nmesh=1;
oapiVCRegisterMFD(0,&mfd);
mfd.ngroup=16;
mfd.nmesh=1;
oapiVCRegisterMFD(1,&mfd);
static VCHUDSPEC hud_pilot = {1, 14,{0.55,2.04,28.93},1.02};
static VCHUDSPEC hud_copilot = {1, 14,{-0.55,2.04,28.93},1.02};
static VCHUDSPEC hud_fdeckfloor = {1, 14,{0,2.04,28.93},1.02};
// oapiVCRegisterHUD (&hud_pilot); // HUD parameters
mfds_left.nmesh = 1; // The mesh number (the first one loaded, or 0, in this case).
mfds_left.ngroup = 15; // The mesh group that is the MFD screen in the above identified mesh.
SetCameraDefaultDirection(_V(0, 0, 1)); // View angles down so you can see the
// MFD in VC view by default (it is the sine and cosine of 11º in Y and Z, respectively).
SURFHANDLE MFDbuttons1 = oapiGetTextureHandle (DVCInterior,2);
// Get the MFDButtons.dds D texture for redrawing purposes.
int i;
switch (id) {
case 0: // The first VC cockpit view (id 0). Carefull with mixing up id.
// There are more references to id in the code, but what they identify is
// according to the specific callback. For example, in clbkVCMouseEvent,
// id is the identity of the MFD buttons, not the cockpit view.
SetCameraOffset (_V(0.55,2.04,27.93));
oapiVCSetNeighbours (1, -1, -1, 2);
oapiVCRegisterMFD (MFD_LEFT, &mfds_left);
oapiVCRegisterHUD (&hud_pilot); // HUD parameters
oapiVCRegisterArea (AID_MFD1_LBUTTONS, _R( 0, 0, 32, 220), PANEL_REDRAW_USER, PANEL_MOUSE_IGNORE, PANEL_MAP_BACKGROUND, MFDbuttons1);
oapiVCRegisterArea (AID_MFD1_RBUTTONS, _R( 32, 0, 64, 220), PANEL_REDRAW_USER, PANEL_MOUSE_IGNORE, PANEL_MAP_BACKGROUND, MFDbuttons1);
// These area registrations are for redrawing purposes only, and are used by
// the clbkVCRedrawEvent. The _R(X1, Y1, X2, Y2) coordinates pertain to the
// texture coordinates on the MFDButtons.dds texture (in PIXELS), which is the
// dynamic texture that SURFHANDLE MFDbuttons1 gets from the mesh file.
// Note that as the bottom buttons are not ever redrawn, no registration of
// them for texture coords is needed.
// Have a look at the clbkMFDMode and clbkVCRedrawEvent.
// The only areas triggered for redrawing and then redrawn are
// those two registered above (AID_MFD1_LBUTTONS and AID_MFD1_RBUTTONS.
// And have a look at the definitions in the AstroMatiz.h file. You will see their
// id's that are passed to the preprocessor during compile.
// For reference, here are the rectangular area 3D coordinates of the
// left, right and bottom MFD buttons, in MESH coordinates. You WILL need to
// get this info, if you want to make your own VC work properly.
// (Use Meshwizard, or go into the mesh file itself and find them).
// The mesh area of the 6 left buttons of MFD_LEFT
// _V(-0.32f, 0.067f, 0.654f),
// _V(-0.30f, 0.067f, 0.654f),
// _V(-0.32f, -0.080f, 0.643f),
// _V(-0.30f, -0.080f, 0.643f));
// The mesh area of the 6 right buttons of MFD_LEFT
// _V(-0.117f, 0.067f, 0.654f),
// _V(-0.097f, 0.067f, 0.654f),
// _V(-0.117f, -0.080f, 0.643f),
// _V(-0.097f, -0.080f, 0.643f));
// The mesh area of the three bottom buttons of MFD_LEFT
// _V(-0.267f, -0.095f, 0.642f),
// _V(-0.158f, -0.095f, 0.642f),
// _V(-0.267f, -0.114f, 0.641f),
// _V(-0.158f, -0.114f, 0.641f));
for (i = 0; i < 6; i++) {
oapiVCRegisterArea (MFD1_LBUTTON1+i, PANEL_REDRAW_NEVER, PANEL_MOUSE_LBDOWN);
oapiVCSetAreaClickmode_Spherical(MFD1_LBUTTON1+i, _V(-0.31, 0.0547 - (i * 0.0245), 0.649), 0.0123);
oapiVCRegisterArea (MFD1_RBUTTON1+i, PANEL_REDRAW_NEVER, PANEL_MOUSE_LBDOWN);
oapiVCSetAreaClickmode_Spherical(MFD1_RBUTTON1+i, _V(-0.107, 0.0547-(i * 0.0245), 0.649), 0.0123);
}
// Define the area for mouse events on each button of left and right columns.
for (i = 0; i < 3; i++) {
oapiVCRegisterArea (MFD1_BBUTTON1+i, PANEL_REDRAW_NEVER, PANEL_MOUSE_LBDOWN);
oapiVCSetAreaClickmode_Spherical(MFD1_BBUTTON1+i, _V(-0.254 + (i * 0.042), -0.100, 0.641), 0.0123);
}
// Define the area for mouse events on the bottom buttons. Coordinates are in
// mesh 3D coords (see why you needed to get this info?)
campos = CAM_VCPILOT;
break;
case 1: // front left passenger
SetCameraOffset (_V(-0.55,2.04,27.93));
SetCameraMovement (_V(0.2,-0.05,0.3), -10*RAD, 10*RAD, _V(-0.3,0,0), 80*RAD, 0, _V(0.4,0,0), -90*RAD, 0);
oapiVCSetNeighbours (-1, 0, -1, 2);
oapiVCRegisterHUD (&hud_copilot); // HUD parameters
campos = CAM_VCPSNGR1;
break;
case 2: // front right passenger
SetCameraOffset (_V(0,-0.2,27.93));
SetCameraMovement (_V(-0.2,-0.05,0.3), 10*RAD, 10*RAD, _V(-0.4,0,0), 90*RAD, 0, _V(0.3,0,0), -80*RAD, 0);
oapiVCSetNeighbours (1, 0, -1, 3);
oapiVCRegisterHUD (&hud_fdeckfloor); // HUD parameters
campos = CAM_VCPSNGR2;
break;
case 3: // rear left passenger
SetCameraOffset (_V(0.5, 0, 4.4));
SetCameraMovement (_V(0.4,0,0), 0, 0, _V(-0.3,0,0), 70*RAD, 0, _V(0.4,0,0), -90*RAD, 0);
oapiVCSetNeighbours (-1, -1, 2, 4);
campos = CAM_VCPSNGR3;
break;
case 4: // rear right passenger
SetCameraOffset (_V(0, 0.2, -18));
SetCameraMovement (_V(-0.4,0,0), 0, 0, _V(-0.4,0,0), 90*RAD, 0, _V(0.3,0,0), -70*RAD, 0);
oapiVCSetNeighbours (-1, -1, 3, -1);
campos = CAM_VCPSNGR4;
return true;
};
return true;
}
//void ShuttleD::clbkDrawHUD (int mode, const HUDPAINTSPEC *hps, HDC hDC, oapi::Sketchpad *skp)
bool ShuttleD::clbkDrawHUD(int mode, const HUDPAINTSPEC *hps, HDC hDC, oapi::Sketchpad *skp)
{
// draw the default HUD
VESSEL3::clbkDrawHUD (mode, hps, skp);
// UMmu display messages
if(dHudMessageDelay>0)
{
skp->Text(5,hps->H/60*15,cUmmuHudDisplay,strlen(cUmmuHudDisplay));
// dHudMessageDelay-=oapiGetSimStep();
// if(dHudMessageDelay<0)
// dHudMessageDelay=0;
}
// UCGO display messages
if(dCargHudMessageDelay>0)
{
TextOut (hDC,5,hps->H/60*12,cCargoHudDisplay,strlen(cCargoHudDisplay));
dCargHudMessageDelay-=oapiGetSimStep();
if(dCargHudMessageDelay<0)
dCargHudMessageDelay=0;
}
return true;
}
//-------------------------------------------------------------------------
bool ShuttleD::clbkVCMouseEvent (int id, int event, VECTOR3 &p)
{
if ((id) >= MFD1_LBUTTON1 && (id) < MFD1_LBUTTON1 + 12)
{
oapiProcessMFDButton (MFD_LEFT, id - MFD1_LBUTTON1, event);
return true;
}
// Processes the events for mouse clicks on VC view MFD buttons, left and
// right columns, by matching the id of the event to the #defined identifier of
// the button (see AstroMatiz.h file).
if ((id) == MFD1_BBUTTON1)
{
oapiToggleMFD_on (MFD_LEFT);
return true;
}
// The ON / OFF button (left MFD button on the bottom).
if ((id) == MFD1_BBUTTON2)
{
oapiSendMFDKey (MFD_LEFT, OAPI_KEY_F1);
return true;
}
// The MODE button (center MFD button on the bottom).
if ((id) == MFD1_BBUTTON3)
{
oapiSendMFDKey (MFD_LEFT, OAPI_KEY_GRAVE);
return true;
}
// The MENU button (right MFD button on the bottom).
return false;
}
//-------------------------------------------------------------------------
bool ShuttleD::clbkVCRedrawEvent (int id, int event, SURFHANDLE surf)
{
int bt, side;
switch (id) {
const char *label;
case AID_MFD1_LBUTTONS:
case AID_MFD1_RBUTTONS:
side = (id == AID_MFD1_LBUTTONS ? 0: 1);
HDC hDC = oapiGetDC (surf);
SelectObject (hDC, hFont);
SetTextColor (hDC, RGB(250, 250, 100));
SetTextAlign (hDC, TA_CENTER);
SetBkMode (hDC, TRANSPARENT);
for (bt = 0; bt < 6; bt++) {
if (label = oapiMFDButtonLabel (MFD_LEFT, bt+side*6))
TextOut (hDC, 16, 8+36*bt, label, strlen(label));
else break;
}
oapiReleaseDC (surf, hDC);
return true;
}
return false;
// This redraw business is the most complicated thing about making VC's. This is
// where the registered areas AID_MFD1_LBUTTONS and AID_MFD1_RBUTTONS are used.
// This part has absolutely nothing to do with triggering mouse events. It is
// ONLY blitting your MFDButtons texture on the buttons again, but with text on it.
// Important points with this issue are;
// 1. Get your mesh UV coordinates right for the mesh. DON'T get is backwards.
// 2. Make sure your texture is dynamic (just D suffix it in the mesh file).
// 3. Get the texture in the program (in clbkLoadVC) as a SURFHANDLE.
};
//=========================================================
// Vessel Load and Save Parameters
//=========================================================
void ShuttleD::clbkLoadStateEx (FILEHANDLE scn, void *status)
{
char *line;
while (oapiReadScenario_nextline (scn, line))
{
if (!_strnicmp (line, "GEAR", 4)) {
sscanf (line+4, "%d%lf", &GEAR_status, &GEAR_proc);
}
if (!_strnicmp (line, "PLBAYA", 5)) {
sscanf (line+4, "%d%lf", &PLBAYA_status, &PLBAYA_proc);
}
if (!_strnicmp (line, "PLBAYB", 5)) {
sscanf (line+4, "%d%lf", &PLBAYB_status, &PLBAYB_proc);
}
// Load UCGO 2.0 cargo from scenario
if(hUcgo.LoadCargoFromScenario(line)==TRUE) // UCGO load cargo
continue;
if(Crew.LoadAllMembersFromOrbiterScenario(line)==TRUE)
continue;
// Load UCGO 2.0 cargo from scenario
if(hUcgo.LoadCargoFromScenario(line)==TRUE) // UCGO load cargo
continue;
ParseScenarioLineEx (line, status);
}
SetAnimation (anim_gear, GEAR_proc);
}
void ShuttleD::clbkSaveState (FILEHANDLE scn)
{
char cbuf[256];
VESSEL3::clbkSaveState (scn);
sprintf (cbuf, "%d %0.4f", GEAR_status, GEAR_proc);
oapiWriteScenario_string (scn, "GEAR", cbuf);
sprintf (cbuf, "%d %0.4f", PLBAYA_status, PLBAYA_proc);
oapiWriteScenario_string (scn, "PLBAYA", cbuf);
sprintf (cbuf, "%d %0.4f", PLBAYB_status, PLBAYB_proc);
oapiWriteScenario_string (scn, "PLBAYB", cbuf);
Crew.SaveAllMembersInOrbiterScenarios(scn);
// Save UCGO 2.0 cargo in scenario
hUcgo.SaveCargoToScenario(scn);
// Save UCGO 2.0 cargo in scenario
hUcgo.SaveCargoToScenario(scn);
}
//=========================================================
// Animation Template
//=========================================================
void ShuttleD::clbkPostStep(double simt, double simdt, double mjd)
{
int ReturnCode=Crew.ProcessUniversalMMu();
switch(ReturnCode)
{
case UMMU_TRANSFERED_TO_OUR_SHIP:
sprintf(SendHudMessage(),"%s \"%s\" aged %i was transfered to our ship",
Crew.GetCrewMiscIdByName(Crew.GetLastEnteredCrewName()),Crew.GetLastEnteredCrewName()
,Crew.GetCrewAgeByName(Crew.GetLastEnteredCrewName()));
break;
case UMMU_RETURNED_TO_OUR_SHIP:
sprintf(SendHudMessage(),"%s \"%s\" aged %i entered into our ship",
Crew.GetCrewMiscIdByName(Crew.GetLastEnteredCrewName()),
Crew.GetLastEnteredCrewName(),Crew.GetCrewAgeByName(Crew.GetLastEnteredCrewName()));
break;
}
if (GEAR_status >= GEAR_RAISING) {
double da = simdt * GEAR_OPERATING_SPEED;
if (GEAR_status == GEAR_RAISING) {
if (GEAR_proc > 0.0) GEAR_proc = max (0.0, GEAR_proc-da);
else GEAR_status = GEAR_UP;
} else {
if (GEAR_proc < 1.0) GEAR_proc = min (1.0, GEAR_proc+da);
else GEAR_status = GEAR_DOWN;
}
SetAnimation (anim_gear, GEAR_proc);
}
SetTouchdownPoints (_V(0,-4.89+GEAR_proc*0.99,1), _V(-1,-4.89+GEAR_proc*0.99,-1), _V(1,-4.89+GEAR_proc*0.99,-1));
//sprintf(oapiDebugString(),"anim %2.2f", GEAR_proc );
if (PLBAYA_status >= PLBAYA_CLOSING) {
double da = simdt * PLBAYA_OPERATING_SPEED;
if (PLBAYA_status == PLBAYA_CLOSING) {
if (PLBAYA_proc > 0.0) PLBAYA_proc = max (0.0, PLBAYA_proc-da);
else PLBAYA_status = PLBAYA_UP;
} else {
if (PLBAYA_proc < 1.0) PLBAYA_proc = min (1.0, PLBAYA_proc+da);
else PLBAYA_status = PLBAYA_DOWN;
}
SetAnimation (anim_PLBAYA, PLBAYA_proc);
}
if (PLBAYB_status >= PLBAYB_CLOSING) {
double da = simdt * PLBAYB_OPERATING_SPEED;
if (PLBAYB_status == PLBAYB_CLOSING) {
if (PLBAYB_proc > 0.0) PLBAYB_proc = max (0.0, PLBAYB_proc-da);
else PLBAYB_status = PLBAYB_UP;
} else {
if (PLBAYB_proc < 1.0) PLBAYB_proc = min (1.0, PLBAYB_proc+da);
else PLBAYB_status = PLBAYB_DOWN;
}
SetAnimation (anim_PLBAYB, PLBAYB_proc);
}
if (GEAR_status == GEAR_RAISING) {
{if(GEAR_proc > 0.99)
PlayVesselWave3(SHD,GEARDOWN);
}
}
if (GEAR_status == GEAR_LOWERING) {
{if(GEAR_proc < 0.01)
PlayVesselWave3(SHD,GEARUP);
}
}
if (PLBAYA_status == PLBAYA_CLOSING) {
{if(PLBAYA_proc > 0.99)
PlayVesselWave3(SHD,PLBAYACLOSE);
}
}
if (PLBAYA_status == PLBAYA_OPENING) {
{if(PLBAYA_proc < 0.01)
PlayVesselWave3(SHD,PLBAYAOPEN);
}
}
if (PLBAYB_status == PLBAYB_CLOSING) {
{if(PLBAYB_proc > 0.9)
PlayVesselWave3(SHD,PLBAYBCLOSE);
}
}
if (PLBAYB_status == PLBAYB_OPENING) {
{if(PLBAYB_proc < 0.1)
PlayVesselWave3(SHD,PLBAYBOPEN);
}
}
int ActionAreaReturnCode=Crew.DetectActionAreaActivated();
if(ActionAreaReturnCode>-1)
{
// this is just an example, we have four area declared
// action area ID 0 triggered
if(ActionAreaReturnCode==0)
{
// do something cool here
}
// action area ID 1 triggered
else if(ActionAreaReturnCode==1)
{
// As you can edit action area in real time: relocation, sound, text, state
// the possiblity are endless. you can for example order a UMMU to go to an external panel
// and open it, then go to engine exhaust and "repair" it then back to panel to close it etc.
if(iActionAreaDemoStep==0)
{
Crew.SetActionAreaText(1,"You are still on the right but this is 2nd keypress");
iActionAreaDemoStep++;
// do something cool here
}
else if(iActionAreaDemoStep==1)
{
// remember you change action area's parameter for the NEXT keypress of UMMU
Crew.SetActionAreaText(1,"You are still on the right but this is 3rd keypress");
iActionAreaDemoStep++;
// do something cool here
}
else
{
Crew.SetActionAreaText(1,"You are still on the right but this is last keypress");
// and of course you can change sound, location, state, text, here some examples:
//Crew.SetActionAreaPos(1,_V(5,0,5)); // change location
//Crew.SetActionAreaWav(1,"MyAddon\PlayRepaired.wav"); // change sound
//Crew.SetActionAreaWav(1,"MyAddon\DoorClosed.wav"); // change sound
//Crew.SetActionAreaText(1,NULL); // sound or text are not mandatory, here we set no text.
// etc. etc.
}
}
// action area ID 2 triggered
else if(ActionAreaReturnCode==2)
{
// do something cool here
}
// action area ID 3 triggered
else if(ActionAreaReturnCode==3)
{
// do something cool here
}
}
if(GroundContact()==TRUE)
{
// we check vertical speed
int I;
VECTOR3 vHorizonAirspeedVector={0};
GetHorizonAirspeedVector (vHorizonAirspeedVector);
double VertSpeed =vHorizonAirspeedVector.y;
if(VertSpeed<-3)
{
// we touched ground with more than -3 m/s, sorry dude, time to kill you all :(
for(I=0;I<Crew.GetCrewTotalNumber();I++)
{
Crew.SetCrewMemberPulseBySlotNumber(I,0); // set cardiac pulse to zero
}
strcpy(SendHudMessage(),"Oooh no ! Crash - All crew aboard killed");
}
}
AddUMmuToVessel();
Crew.WarnUserUMMUNotInstalled("Shuttle-D");
// At the very end of clbkPostStep or clbkPreStep
hUcgo.WarnUserUCGONotInstalled("Shuttle-D");
}
// --------------------------------------------------------------
// clbkVisualCreated
// --------------------------------------------------------------
void ShuttleD::clbkVisualCreated (VISHANDLE vis, int refcount)
{
hUcgo.SetUcgoVisual(vis); // must be called in clbkVisualCreated.
}
////////////////////////////////////////////////////////
// SendCargHudMessage
////////////////////////////////////////////////////////
char *ShuttleD::SendCargHudMessage(void)
{
dCargHudMessageDelay=15; // 15 seconds display delay for msg
return cCargoHudDisplay;
}
// --------------------------------------------------------------
// Respond to buffered keyboard events
// --------------------------------------------------------------
int ShuttleD::clbkConsumeBufferedKey (DWORD key, bool down, char *kstate)
{
if (!down) return 0; // only process keydown events
if(key==OAPI_KEY_G)
{ //Gear
RevertGEAR();
return 1;
}
if(key==OAPI_KEY_K)
{// Payload Bay B
RevertPLBAYB();
return 1;
}
if(key==OAPI_KEY_O)
{// hatch
RevertPLBAYA();
return 1;
}
if(key==OAPI_KEY_E&&!KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
// PERFORM THE EVA, first we get is name with "GetCrewNameBySlotNumber" then we perform EVA with "EvaCrewMember"
int Returned=Crew.EvaCrewMember(Crew.GetCrewNameBySlotNumber(SelectedUmmuMember));
// we provide feedback to user (You can display a message on panel or wathewer)
// here below all the return code possible:
switch(Returned)
{
case TRANSFER_TO_DOCKED_SHIP_OK:
sprintf(SendHudMessage(),"Transfer to docked ship Ok - %s transfered",
Crew.GetLastEvaedCrewName());SelectedUmmuMember=0;
break;
case EVA_OK:
sprintf(SendHudMessage(),"EVA OK - %s left the ship",
Crew.GetLastEvaedCrewName());SelectedUmmuMember=0;
break;
case ERROR_NO_ONE_ON_BOARD:
strcpy(SendHudMessage(),"Error, no one on board, unable to EVA");
break;
case ERROR_AIRLOCK_CLOSED:
strcpy(SendHudMessage(),"Error, airlock is closed, unable to EVA");
break;
case ERROR_DOCKED_SHIP_HAVE_AIRLOCK_CLOSED:
strcpy(SendHudMessage(),"Error, docked ship's airlock is closed, unable to transfer");
break;
case ERROR_DOCKED_SHIP_IS_FULL:
strcpy(SendHudMessage(),"Error, docked ship is already full transfer failed");
break;
case ERROR_CREW_MEMBER_NOT_FOUND:
strcpy(SendHudMessage(),"Error, no crew by this name in ship");
break;
case ERROR_DOCKEDSHIP_DONOT_USE_UMMU:
strcpy(SendHudMessage(),"Error, docked ship do not use UMmu 2.0, ask author to add it");
break;
case ERROR_MISC_ERROR_EVAFAILED:
strcpy(SendHudMessage(),"Misc error with UMMU install it again");
break;
}
return TRUE;
}
//---------------------------------------------------------------------------
// Ummu Key "1" Select next member This is just internal to the demo
// you may do your own selection system by panel button, name etc etc
if(key==OAPI_KEY_1&&!KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
// we test there is someone aboard
if(Crew.GetCrewTotalNumber()==0)
{
strcpy(SendHudMessage(),"Sorry no one aboard unable to select");
return 1;
}
// we test that we select existing member
if(SelectedUmmuMember<Crew.GetCrewTotalNumber()-1)
SelectedUmmuMember++;
char * Name=Crew.GetCrewNameBySlotNumber(SelectedUmmuMember);
sprintf(SendHudMessage(),"Slot %i %s \"%s\" aged %i Selected for EVA or Transfer, please press \"E\" to EVA",
SelectedUmmuMember,Crew.GetCrewMiscIdBySlotNumber(SelectedUmmuMember),
Name,Crew.GetCrewAgeBySlotNumber(SelectedUmmuMember));
return 1;
}
//---------------------------------------------------------------------------
// Ummu Key "2" Select previous member This is just internal to the demo
// you may do your own selection system by panel button
if(key==OAPI_KEY_2&&!KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
// we test there is someone aboard
if(Crew.GetCrewTotalNumber()==0)
{
strcpy(SendHudMessage(),"Sorry no one aboard unable to select");
return 1;
}
if(SelectedUmmuMember>0)
SelectedUmmuMember--;
char * Name=Crew.GetCrewNameBySlotNumber(SelectedUmmuMember);
sprintf(SendHudMessage(),"Slot %i %s \"%s\" aged %i Selected for EVA or Transfer"
", please press \"E\" to EVA",SelectedUmmuMember,
Crew.GetCrewMiscIdBySlotNumber(SelectedUmmuMember),Name,
Crew.GetCrewAgeBySlotNumber(SelectedUmmuMember));
return 1;
}
//---------------------------------------------------------------------------
// Ummu Key "A" Switch the virtual UMMU airlock door on/off
if(key==OAPI_KEY_A&&!KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
// switch state
Crew.SetAirlockDoorState(!Crew.GetAirlockDoorState());
// display state
if(Crew.GetAirlockDoorState()==TRUE)
strcpy(SendHudMessage(),"Airlock is now open");
else
strcpy(SendHudMessage(),"Airlock is now closed");
return 1;
}
//---------------------------------------------------------------------------
// Get some infos Name of ship and total soul aboard
if(key==OAPI_KEY_S)
{
sprintf(SendHudMessage(),"%i souls aboard ship %s, %i seats available",
Crew.GetCrewTotalNumber(),GetName(),4-Crew.GetCrewTotalNumber());
return 1;
}
//---------------------------------------------------------------------------
// ADD some Fun, Eject the guy, No check of all return code here to keep listing small and clear.
// Notice eject function doesn't check airlock state at all.
// GOOD IDEA: Get the Object's handle after ejection with function "GetObjHandleOfLastEVACrew"
// and add to it one very small tank, thruster and smoke, then fire thruster (see pilot ejection of DGIV)
// BAD IDEA: Not testing the handle returned by "GetObjHandleOfLastEVACrew" before using may
// cause a CTD if by any bad luck the pointer is invalid (handle==NULL)
if(key==OAPI_KEY_ESCAPE&&!KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
if(Crew.EjectCrewMember(Crew.GetCrewNameBySlotNumber(SelectedUmmuMember))==EVA_OK)
sprintf(SendHudMessage(),"%s EJECTED",Crew.GetLastEvaedCrewName());
SelectedUmmuMember=0;
return 1;
}
//---------------------------------------------------------------------------
// Use a different Mesh (type "C" then EVA someone)
// better idea is to use the new UMMU Id definition
// look readme.txt in folder "config/UMMUIdConfig"
if(key==OAPI_KEY_C)
{
Crew.SetAlternateMeshToUseForEVASpacesuit("mmu"); // the stock mmu of orbiter located in "meshes/mmu.msh"
strcpy(SendHudMessage(),"Mesh changed");
return 1;
}
// THIS IS FOR ADDING CREW SEE PDF doc "Allow user to add crew to your ship
// without scenery editor"
if(key==OAPI_KEY_M&&!KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
AddUMmuToVessel(TRUE);
}
// 9 key "select" one cargo on disk (cycle)
if(key==OAPI_KEY_9&&!KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
sprintf(SendCargHudMessage(),"%s - selected",hUcgo.ScnEditor_SelectNextCargoAvailableOnDisk());
return 1;
}
// SHIFT+9 key "add last cargo selected by key 9"
// If iSelectedCargo=-1 (default) add to the first free slot found
if(key==OAPI_KEY_9&&KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
if(hUcgo.ScnEditor_AddLastSelectedCargoToSlot(iSelectedCargo)==TRUE)
{
strcpy(SendCargHudMessage(),"Cargo added to ship");
}
else
{
if(iSelectedCargo<0)
{
strcpy(SendCargHudMessage(),"Cargo not added (ship full or weight excess ?)");
}
else
{
strcpy(SendCargHudMessage(),"Cargo not added (slot full ship full or weight excess ?)");
}
}
return 1;
}
// "C" grapple cargo. If iSelectedCargo=-1 (default) add to the first free slot found
if(key==OAPI_KEY_C&&!KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
int ReturnedCode=hUcgo.GrappleOneCargo(iSelectedCargo);
// for return code list see function "GrappleOneCargo" in the header
switch(ReturnedCode)
{
case 1:
strcpy(SendCargHudMessage(),"Cargo grappled");
break;
case 0:
strcpy(SendCargHudMessage(),"No cargo in range");
break;
case -1:
strcpy(SendCargHudMessage(),"cargo exceed maximum mass");
break;
case -2:
strcpy(SendCargHudMessage(),"bad config, mesh not found or slot not declared");
break;
case -3:
strcpy(SendCargHudMessage(),"Can't grapple cargo, slot not empty");
break;
case -4:
strcpy(SendCargHudMessage(),"Can't grapple cargo,doors closed ");
break;
case -5:
strcpy(SendCargHudMessage(),"Can't grapple cargo,Ship full");
break;
default:
strcpy(SendCargHudMessage(),"Misc error Unable to grapple cargo");
}
return 1;
}
// SHIFT+C release cargo. If iSelectedCargo=-1 (default) release the first free slot found
if(key==OAPI_KEY_C&&KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
if(hUcgo.ReleaseOneCargo(iSelectedCargo)!=FALSE)
{
strcpy(SendCargHudMessage(),"Cargo released");
}
else
{
strcpy(SendCargHudMessage(),"Cargo not released (empty slot, no cargo aboard?)");
}
return 1;
}
// "8" show some info on cargo
if(key==OAPI_KEY_8&&!KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
sprintf(SendCargHudMessage(),"%i cargos aboard. "
"Total cargos weight: %.0fkg",hUcgo.GetNbrCargoLoaded(),hUcgo.GetCargoTotalMass());
return 1;
}
return 0;
}
//-------------------------------------------------------------------------
// THIS IS FOR ADDING CREW SEE PDF doc "Allow user to add crew to your ship
// without scenery editor"
bool UMmuCrewAddCallback(void *id, char *str, void *data)
{
if(strlen(str)<2||strlen(str)>38)
return false;
char *cPtr=(char*)data; if(*cPtr==2){*cPtr=3;strcpy(cPtr+2,str);}
else if(*cPtr==4){*cPtr=5;strcpy(cPtr+42,str);}
else if(*cPtr==6){*cPtr=7;strcpy(cPtr+82,str);}return true;
}
void ShuttleD::AddUMmuToVessel(BOOL bStartAdding)
{
if(bStartAdding==FALSE&&cAddUMmuToVessel[0]==0)
return;
if(bStartAdding==TRUE){
int salut=sizeof(cAddUMmuToVessel);
memset(cAddUMmuToVessel,0,sizeof(cAddUMmuToVessel));
cAddUMmuToVessel[0]=1;
}
else if(cAddUMmuToVessel[0]==1){
cAddUMmuToVessel[0]=2;
oapiOpenInputBox ("Enter new crew's name (or escape)",UMmuCrewAddCallback,0,30,(void*)cAddUMmuToVessel);
}
else if(cAddUMmuToVessel[0]==3){
cAddUMmuToVessel[0]=4;
oapiOpenInputBox ("Enter crew's age",UMmuCrewAddCallback,0,30,(void*)cAddUMmuToVessel);
}
else if(cAddUMmuToVessel[0]==5){
cAddUMmuToVessel[0]=6;
oapiOpenInputBox ("Enter function (Capt,Sec,Vip,Sci,Doc,Tech,Crew,Pax)",UMmuCrewAddCallback,0,30,(void*)cAddUMmuToVessel);
}
else if(cAddUMmuToVessel[0]==7){
cAddUMmuToVessel[0]=0;
int Age=max(5,min(100,atoi(&cAddUMmuToVessel[42])));
if(Crew.AddCrewMember(&cAddUMmuToVessel[2],Age,70,70,&cAddUMmuToVessel[82])==TRUE){
sprintf(SendHudMessage(),"Crew \"%s\" aged %i added to vessel",&cAddUMmuToVessel[2],Age);
}
else{
strcpy(SendHudMessage(),"ERROR: Crew not added (vessel full?)");
}
}
}
//=========================================================
// Load and Delete Module Stuff
//=========================================================
DLLCLBK void InitModule (HINSTANCE hModule)
{
g_hDLL = hModule;
hFont = CreateFont (-20, 3, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 0, "Arial");
hPen = CreatePen (PS_SOLID, 3, RGB (120,220,120));
hBrush = CreateSolidBrush (RGB(0,128,0));
// perform global module initialisation here
}
DLLCLBK void ExitModule (HINSTANCE hModule)
{
// perform module cleanup here
DeleteObject (hFont);
DeleteObject (hPen);
DeleteObject (hBrush);
}
//=========================================================
// Load and Delete Vessel Stuff
//=========================================================
DLLCLBK VESSEL *ovcInit (OBJHANDLE hvessel, int flightmodel)
{
return new ShuttleD (hvessel, flightmodel);
}
DLLCLBK void ovcExit (VESSEL *vessel)
{
if (vessel)
delete (ShuttleD*)vessel;
}
void ShuttleD::clbkPostCreation (void)
{
////////////////////////////////////////////////////////////////
// 3-ORBITERSOUND EXAMPLE - INIT AND LOADING OF WAV
// THIS MUST BE CALLED ABSOLUTELY IN THE "POSTCREATION CALLBACK"
////////////////////////////////////////////////////////////////
// here we connect to OrbiterSound and store the returned ID in your class
// this is the first thing to do. You must call this in "clbkPostCreation"
// (new version of ovcPostCreation wich is now obsolet)
SHD=ConnectToOrbiterSoundDLL3(GetHandle());
RequestLoadVesselWave3(SHD,GEARUP,"Sound\\ShuttleD\\gearup.wav",INTERNAL_ONLY);
RequestLoadVesselWave3(SHD,GEARDOWN,"Sound\\ShuttleD\\geardown.wav",INTERNAL_ONLY);
RequestLoadVesselWave3(SHD,PLBAYAOPEN,"Sound\\ShuttleD\\plbayaopen.wav",INTERNAL_ONLY);
RequestLoadVesselWave3(SHD,PLBAYACLOSE,"Sound\\ShuttleD\\plbayaclose.wav",INTERNAL_ONLY);
RequestLoadVesselWave3(SHD,PLBAYBOPEN,"Sound\\ShuttleD\\plbaybopen.wav",INTERNAL_ONLY);
RequestLoadVesselWave3(SHD,PLBAYBCLOSE,"Sound\\ShuttleD\\plbaybclose.wav",INTERNAL_ONLY);
// now we are allowed for example to replace variable sound of OrbiterSound.
// it will use them instead of the stock one when our vessel have the focus, see header file for parameter
// (you can replace more than the four below see parameters for "ReplaceStockSound3()")
ReplaceStockSound3(SHD,"Sound\\ShuttleD\\mainext.wav", REPLACE_MAIN_THRUST);
ReplaceStockSound3(SHD,"Sound\\ShuttleD\\attfire.wav", REPLACE_RCS_THRUST_ATTACK);
ReplaceStockSound3(SHD,"Sound\\ShuttleD\\attsustain.wav", REPLACE_RCS_THRUST_SUSTAIN);
ReplaceStockSound3(SHD,"Sound\\ShuttleD\\aircond.wav", REPLACE_AIR_CONDITIONNING);
ReplaceStockSound3(SHD,"Sound\\ShuttleD\\aircond.wav", REPLACE_COCKPIT_AMBIENCE_1);
ReplaceStockSound3(SHD,"Sound\\ShuttleD\\aircond.wav", REPLACE_COCKPIT_AMBIENCE_2);
ReplaceStockSound3(SHD,"Sound\\ShuttleD\\aircond.wav", REPLACE_COCKPIT_AMBIENCE_3);
ReplaceStockSound3(SHD,"Sound\\ShuttleD\\aircond.wav", REPLACE_COCKPIT_AMBIENCE_4);
ReplaceStockSound3(SHD,"Sound\\ShuttleD\\aircond.wav", REPLACE_COCKPIT_AMBIENCE_5);
ReplaceStockSound3(SHD,"Sound\\ShuttleD\\aircond.wav", REPLACE_COCKPIT_AMBIENCE_6);
ReplaceStockSound3(SHD,"Sound\\ShuttleD\\aircond.wav", REPLACE_COCKPIT_AMBIENCE_7);
ReplaceStockSound3(SHD,"Sound\\ShuttleD\\aircond.wav", REPLACE_COCKPIT_AMBIENCE_8);
ReplaceStockSound3(SHD,"Sound\\ShuttleD\\aircond.wav", REPLACE_COCKPIT_AMBIENCE_9);
// Now your ship have custom sound you can end here if you don't want to bother anymore
// with sound, your ship is already customised. Anyway I'll show you more below.
//...
// here we will load a sound that will play when we pass 500 meter altitude
// We will play it later ourself when we reach 500 meter (see opcPreStep below)
RequestLoadVesselWave3(SHD,MY500METERSOUND,"Sound\\OrbiterSound_SDK\\sound\\my500meter.wav",RADIO_SOUND);
// AS we will play it using the "radioexclusive function" and as we don't want to be disturbed
// by OrbiterSound's ATC we set the ATC option of OrbiterSound to false (no more ATC will play)
// it's not an obligation while the "playradio..." function stop any stock ATC sound that is already playing
// but if you want to use radio sound you may not want to be disturbed by "off-topic" atc.
SoundOptionOnOff3(SHD,PLAYRADIOATC,FALSE);
// we disable also the stock countdown when we take-off.. it's annoying :)
SoundOptionOnOff3(SHD,PLAYCOUNTDOWNWHENTAKEOFF,FALSE);
// Here we will load a radar sound that will play in cockpit view only and after take-off below 500 meter
// this sound will be looped and will see it's frequency varying as we approach ground
RequestLoadVesselWave3(SHD,MYRADARSOUND,"Sound\\OrbiterSound_SDK\\sound\\myradar.wav",INTERNAL_ONLY);
// Here is THE example of an external sound that must be also faded by distance and pressure
// as stated in the header of ObiterSoundSDK3.h it's IMPORTANT that you call this sound looped
// and at each frame otherwise it will not be faded properly.
// "EXTERNAL_ONLY_FADED_CLOSE" mean that it will be faded at close distance as the RCS sound in external view.
RequestLoadVesselWave3(SHD,MYEXTERNAL_UFO_FADEDSOUND,"Sound\\OrbiterSound_SDK\\sound\\myUfoSound.wav",EXTERNAL_ONLY_FADED_CLOSE);
}
// --------------------------------------------------------------
// loop called each frame
// --------------------------------------------------------------
void ShuttleD::clbkPreStep (double simt, double simdt, double mjd)
{
double Altitude=0;
static BOOL AltitudeSoundPlayed=FALSE;
static BOOL RadarFlagForSound=FALSE;
///////////////////////////////////////////////////////////////////
// 4-ORBITERSOUND EXAMPLE - PLAYING THE SOUND WE LOADED DYNAMICALLY
///////////////////////////////////////////////////////////////////
// ----------------------------------------------------------
// We play the "500 meter" sound we loaded previously
// we use the function "playradio" wich stop OrbiterSound atc
// sound if one is playing.
// ----------------------------------------------------------
oapiGetFocusAltitude(&Altitude);
if(Altitude>500&&Altitude<550&&AltitudeSoundPlayed==FALSE)
{
PlayVesselRadioExclusiveWave3(SHD,MY500METERSOUND,255); // 255=volume maximum
AltitudeSoundPlayed=TRUE;
}
if(Altitude<500||Altitude>550)
AltitudeSoundPlayed=FALSE;
// ------------------------------------------------------
// here we play our radar sound that slide with altitude
// ------------------------------------------------------
if(Altitude<500&&Altitude>2)
{
PlayVesselWave3(SHD,MYRADARSOUND,LOOP,255,(int)(11025+((500-Altitude)*40))); // play looped and a frequency that increase with altitude
RadarFlagForSound=TRUE;
}
else if(RadarFlagForSound=TRUE)
{
// we stop the sound only once (it would not harm else but it will save a bit of processor time)
StopVesselWave3(SHD,MYRADARSOUND);
}
// ------------------------------------------------------
// here we play our external "ufo" sound
// ------------------------------------------------------
// As stated a sound that play in external view must be called looped heach frame so it
// fade properly with distance and pressure. Also we add a litle effect: if the ship is landed
// the frequency is lower simulating an "iddle" engine.
if(Altitude<2)
PlayVesselWave3(SHD,MYEXTERNAL_UFO_FADEDSOUND,LOOP,255,11025); // original wav is 11025 hz
else
PlayVesselWave3(SHD,MYEXTERNAL_UFO_FADEDSOUND,LOOP,255,9000);
// -------------------------------------------------------------
// another example with a different behaviour of the "Ufo" sound
// -------------------------------------------------------------
// here an example of the ufo sound that will play only beetween 0 and 500 meter high.
// I show it here so you know how to stop/start an external sound.
//if(Altitude<500)
// PlayVesselWave3(MyID,MYEXTERNAL_UFO_FADEDSOUND,LOOP,255); // original wav is 11025 hz
//else
// StopVesselWave3(MyID,MYEXTERNAL_UFO_FADEDSOUND); // you can use a flag to avoid reapeated call (even the impact is very low, the function return immediately if the sound is already stoped)
}
