See site in english Voir le site en francais
Website skin:
home  download  forum  link  contact

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

Author Topic: [C++]Affichage des ressources des réservoirs dans le HUD  (Read 3610 times)

0 Members and 1 Guest are viewing this topic.

Offline ea76620

  • Sr. Member
  • ****
  • Posts: 393
  • Country: France fr
  • Karma: 15
07 August 2012, 12:05:56
Bonjour,

Pour mon projet de module de station compatible UCGO et UMMU(ainsi que d'autres choses) je dois mettre dans le HUD la quantité restante dans les différents réservoir.

Cepandant ça m'affiche n'importe quoi  comme valeurs (je dois théoriquement obtenir des pourcentages).



dans clbkPostStep :
Code: [Select]
// transformation des valeurs en pourcentage
POxygen=(GetPropellantMass(&oxygentank)*100)/2000;  //2000 représente la masse maximum en ressources du réservoir.
PFood=(GetPropellantMass(&foodtank)*100)/2000;
PFuel=(GetPropellantMass(&maintank)*100)/2000;

sprintf(SendRessourcesHudMessage(),"O2 Level = %i food level = %i fuel level = %i",POxygen,PFood,PFuel);

Note : si je met GetPropellantMass(oxygentank), GetPropellantMass(foodtank) et GetPropellantMass(&maintank) à la place de POxygen, PFood et PFuel j'ai les même valeurs bizarre.


Les différentes réservoir (2000kg chacun) :

Code: [Select]
// propellant resources
maintank = CreatePropellantResource (PB_FUELMASS);
foodtank = CreatePropellantResource (PB_FOODMASS);
oxygentank = CreatePropellantResource (PB_OXYGENMASS);

initialisation des variables dans clbkSetClassCaps :

Code: [Select]
POxygen=0;
PFood=0;
PFuel=0;

et dans le .h

Code: [Select]
double POxygen;
double PFood;
double PFuel;

Je pense que j'ai du me trompé quelque part mais je ne sais pas ou.

Merci d'avance

A+

PS : la consommation des ressources par l'équipage (et la mort de l'équipage quand y a plus rien) fonctionne sans problème. J'ai consulter les valeurs des réservoirs d'oxygène et de nourriture dans l'éditeur de scénarios et elles sont normales.



Message modifié ( 07-08-2012 12:17 )


Offline Jim Lovell

  • Global Moderator
  • Legend
  • *****
  • Posts: 1530
  • Country: Belgium be
  • Karma: 31
    • Mon site
Reply #1 - 07 August 2012, 12:36:07
Je vais peut-être dire une bêtise, mais tu mais des %i dans ton sprintf, or tu initialises des double...
Je n'ai jamais été bon dans toutes ces histoires de casting mais est-ce que ça pourrait être une piste ?


Jim Love:love:LL
C'est en se plantant que l'on construit ses racines....


ConneXion

Offline SolarLiner

  • Global Moderator
  • Legend
  • *****
  • Posts: 2769
  • Country: France fr
  • Karma: 55
  • a été remercié par Le Créateur
Reply #2 - 07 August 2012, 12:54:03
Quote
Jim Lovell a écrit:
Je vais peut-être dire une bêtise, mais tu mais des %i dans ton sprintf, or tu initialises des double...
Je n'ai jamais été bon dans toutes ces histoires de casting mais est-ce que ça pourrait être une piste ?


Oui, tu déclares des doubles mais tu les utilises en tant que integer ...
essayes plutôt ça:
Code: [Select]
sprintf(SendRessourcesHudMessage(),"O2 Level = %d food level = %d fuel level = %d",POxygen,PFood,PFuel);ou ça:
Code: [Select]
sprintf(SendRessourcesHudMessage(),"O2 Level = %f food level = %f fuel level = %f",POxygen,PFood,PFuel);
Pour l'utilisation en float (deuxième option), je n'ai jamais réussi à faire afficher juste quelques chiffres après a virgule.



Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15407
  • Karma: 256
  • Hein, quoi !?
    • FsPassengers
Reply #3 - 07 August 2012, 12:54:45
Je pense que c'est bien ce que dit Jim (EDIT: grillé par solar :) )

%i sert au entier et affiche n'importe quoi avec des valeurs flottantes comme des doubles.

Essaie:

Code: [Select]
sprintf(SendRessourcesHudMessage(),"O2 Level = %.0f food level = %.0f fuel level = %.0f",POxygen,PFood,PFuel);
'%.0f' affiche zéro chiffre après la virgule, '%.2f' affiche deux chiffres etc. etc.

Pour prendre de TRÈS bonnes habitude je te conseille fortement de nommer le type de tes variables correctement selon la notation hongroise:

Exemple:
Code: [Select]
double dPOxygen;    // 'd'= double
float fPOxygen;        // 'f'= float
int iPoxygen;            // 'i'= integer
char cPoxygen[25];   // 'c'= char

Après même 1000 lignes de code tu vas t'arracher les cheveux sans notation correcte:

Code: [Select]
// pas de bol, le premier est bool le deuxième est char et encore celle-là n'est pas vicieuse
// car tu aurais une erreur compilateur. Alors que d'autres...
if(ValeurCheveux==ValeurArrache)  

// tu l'aurais vu tout de suite avec
if(bValeurCheveux==cValeurArrache)  



Message modifié ( 07-08-2012 13:40 )


Offline ea76620

  • Sr. Member
  • ****
  • Posts: 393
  • Country: France fr
  • Karma: 15
Reply #4 - 07 August 2012, 14:36:36
J'ai mis ça :

Code: [Select]
fPOxygen=(GetPropellantMass(&oxygentank)*100)/2000;
fPFood=(GetPropellantMass(&foodtank)*100)/2000;
fPFuel=(GetPropellantMass(&maintank)*100)/2000;
sprintf(SendRessourcesHudMessage(),"O2 Level %.2f food level %.2f fuel level %.2f",fPOxygen,fPFood,fPFuel);

et déclarer mes variables comme ça :

Code: [Select]
float fPOxygen;
float fPFood;
float fPFuel;

Les valeurs de l'O2 et de la nourriture restent à zéro (et le fuel fait n'importe quoi).





Message modifié ( 07-08-2012 14:49 )

« Last Edit: 07 August 2012, 16:21:50 by ea76620 »

Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15407
  • Karma: 256
  • Hein, quoi !?
    • FsPassengers
Reply #5 - 07 August 2012, 14:49:38
Mhhh déjà tu aurais du les laisser en double... GetPropellantMass retourne des doubles et tes autres valeurs sont aussi en double.

Essaie comme cela:

Code: [Select]
dPOxygen=(GetPropellantMass(&oxygentank)*100)/2000;
dPFood=(GetPropellantMass(&foodtank)*100)/2000;
dPFuel=(GetPropellantMass(&maintank)*100)/2000;
sprintf(SendRessourcesHudMessage(),"O2 Level %.2f food level %.2f fuel level %.2f",dPOxygen,dPFood,dPFuel);

Code: [Select]
double dPOxygen;
double dPFood;
double dPFuel;



Message modifié ( 07-08-2012 14:52 )

« Last Edit: 07 August 2012, 16:21:50 by DanSteph »

Offline ea76620

  • Sr. Member
  • ****
  • Posts: 393
  • Country: France fr
  • Karma: 15
Reply #6 - 07 August 2012, 15:05:19
ça n'arrange rien :



voila le log de compilation, si ça peut être utile :

Quote
1>------ Début de la génération : Projet : supplymodule, Configuration : Debug Win32 ------
1>  supplymodule.cpp
1>C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppBuild.targets(990,5): warning MSB8012: TargetPath(H:\programmes\orbiter\Orbitersdk\samples\Supplymodule\Debug\supplymodule.dll) ne correspond pas à la valeur de la propriété OutputFile (H:\programmes\orbiter\Modules\supplymodule.dll) de Linker. Cela peut entraîner une génération incorrecte de votre projet. Pour corriger ce problème, vérifiez que les valeurs des propriétés $(OutDir), $(TargetName) et $(TargetExt) correspondent à la valeur spécifiée dans %(Link.OutputFile).
1>     Création de la bibliothèque Debug\supplymodule.lib et de l'objet Debug\supplymodule.exp
1>LINK : warning LNK4098: conflit entre la bibliothèque par défaut 'LIBCMT' et les autres bibliothèques ; utilisez /NODEFAULTLIB:library
1>  SDbase.vcxproj -> H:\programmes\orbiter\Orbitersdk\samples\Supplymodule\Debug\supplymodule.dll
========== Génération : 1 a réussi, 0 a échoué, 0 mis à jour, 0 a été ignoré ==========



Message modifié ( 07-08-2012 15:06 )

« Last Edit: 07 August 2012, 16:21:50 by ea76620 »

Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15407
  • Karma: 256
  • Hein, quoi !?
    • FsPassengers
Reply #7 - 07 August 2012, 15:09:45
Tu peux poster le supplymodule.cpp complet entre [ code ] ?

Dan

« Last Edit: 07 August 2012, 16:21:50 by DanSteph »

Offline ea76620

  • Sr. Member
  • ****
  • Posts: 393
  • Country: France fr
  • Karma: 15
Reply #8 - 07 August 2012, 15:11:06
Code: [Select]
// ==============================================================
//                    ORBITER MODULE: HST
//                  Part of the ORBITER SDK
//          Copyright (C) 2001-2007 Martin Schweiger
//                   All rights reserved
//
// HST.cpp
// HST basic specs and animations
//
// HST mesh and textures by David Sundstrom
// ==============================================================

#define ORBITER_MODULE

#include "supplymodule.h"
#include <stdio.h>
#include "UmmuSDK.h"

// ==============================================================
// HST class implementation
// ==============================================================

// --------------------------------------------------------------
// Constructor
// --------------------------------------------------------------
supplymodule::supplymodule (OBJHANDLE hObj, int fmodel)
: VESSEL2 (hObj, fmodel)
{
ant_proc = 0.0;
ant_status = DOOR_CLOSED;
hatch_proc = 0.0;
hatch_status = DOOR_CLOSED;
array_proc = 1.0;
array_status = DOOR_OPEN;
arrayrot_proc = 1.0;
arrayrot_status = DOOR_OPEN;
DefineAnimations ();
}

// --------------------------------------------------------------
// Define animation sequences for moving parts
// --------------------------------------------------------------
void supplymodule::DefineAnimations (void)
{
// 1. Hi-gain antenna
//static UINT HiGainAnt1Grp[5] = {48,49,50,51,52};
//static MGROUP_ROTATE HiGainAnt1 (0, HiGainAnt1Grp, 5, _V(-2.75,0,-5), _V(0, 1,0), (float)(-PI*0.5));
//static UINT HiGainAnt2Grp[2] = {0,2};
//static MGROUP_ROTATE HiGainAnt2 (0, HiGainAnt2Grp, 2, _V(0.002740,-2.013091,0.238118), _V(1,0,0), (float)(PI*0.51));
//anim_ant = CreateAnimation (0.0196);
//AddAnimationComponent (anim_ant, 0, 1, &HiGainAnt1);
//AddAnimationComponent (anim_ant, 0, 1,   &HiGainAnt2);

// 2. Main telescope hatch
//static UINT HatchGrp[5] = {48,49,50,51,52};
//static MGROUP_ROTATE Hatch (0, HatchGrp, 5, _V(-2.75,0,-5), _V(0, 1,0), (float)(-PI));
//anim_hatch = CreateAnimation (5);
//AddAnimationComponent (anim_hatch, 0, 1, &Hatch);

// 3. Solar arrays - folding
anim_array = CreateAnimation (4);
static UINT ArrayLFoldGrp[3] = {5,71,72};
static UINT ArrayRFoldGrp[3] = {7,75,76};
static UINT ArrayTFoldGrp[3] = {8,77,78};
static UINT ArrayBFoldGrp[3] = {6,73,74};
static MGROUP_ROTATE ArrayLFold1 (0, ArrayLFoldGrp, 3, _V(-2.915,0, 2.315), _V(0, 1,0), (float)(-PI*0.5));
AddAnimationComponent (anim_array, 0, 1, &ArrayLFold1);
static MGROUP_ROTATE ArrayRFold2 (0, ArrayRFoldGrp, 3, _V( 2.915,0, 2.315), _V(0, 1,0), (float)(PI*0.5));
AddAnimationComponent (anim_array, 0, 1, &ArrayRFold2);
//static MGROUP_SCALE  ArrayTFoldGrp1 (0, ArrayLFoldGrp, 4, _V(0,0.053583,1.429349), _V(1,1,4));
//AddAnimationComponent (anim_array, 0.6, 1,   &ArrayLFold3);
static MGROUP_ROTATE ArrayTFold1 (0, ArrayTFoldGrp, 3, _V(0, 2.915,2.315), _V( 1,0,0), (float)(-PI*0.5));
AddAnimationComponent (anim_array, 0, 1, &ArrayTFold1);
static MGROUP_ROTATE ArrayBFold1 (0, ArrayBFoldGrp, 3, _V(0,-2.915,2.315), _V( 1,0,0), (float)(PI*0.5));
AddAnimationComponent (anim_array, 0, 1, &ArrayBFold1);
//static MGROUP_SCALE  ArrayRFold3 (0, ArrayRFoldGrp, 4, _V(0,0.053583,1.429349), _V(1,1,4));
//AddAnimationComponent (anim_array, 0.6, 1,   &ArrayRFold3);

// 3. Solar arrays rotation - folding
anim_arrayrot = CreateAnimation (5);
static UINT ArrayrotLFoldGrp[5] = {68,73,74,75,76};
static UINT ArrayrotRFoldGrp[5] = {67,69,70,71,72};
static MGROUP_ROTATE ArrayrotLFold1 (0, ArrayrotLFoldGrp, 5, _V(-2.65,0,-2.85), _V(0, 1,0), (float)(PI*0.5));
AddAnimationComponent (anim_arrayrot, 0, 1, &ArrayrotLFold1);
static MGROUP_ROTATE ArrayrotRFold1 (0, ArrayrotRFoldGrp, 5, _V( 2.65,0,-2.85), _V(0, 1,0), (float)(-PI*0.5));
AddAnimationComponent (anim_arrayrot, 0, 1, &ArrayrotRFold1);
//static MGROUP_SCALE  ArrayLFold3 (0, ArrayLFoldGrp, 4, _V(0,0.053583,1.429349), _V(1,1,4));
//AddAnimationComponent (anim_array, 0.6, 1,   &ArrayLFold3);
//static MGROUP_ROTATE ArrayRFold1 (0, ArrayRFoldGrp, 5, _V( 1.9, 0.053583,1.429349), _V(0, 1,0), (float)(PI*0.5));
//AddAnimationComponent (anim_array, 0,   0.4, &ArrayRFold1);
//static MGROUP_ROTATE ArrayRFold2 (0, ArrayRFoldGrp, 5, _V(0,0.053583,1.429349), _V(-1,0,0), (float)(PI*0.5));
//AddAnimationComponent (anim_array, 0.4, 0.6, &ArrayRFold2);
//static MGROUP_SCALE  ArrayRFold3 (0, ArrayRFoldGrp, 4, _V(0,0.053583,1.429349), _V(1,1,4));
//AddAnimationComponent (anim_array, 0.6, 1,   &ArrayRFold3);
}

//void supplymodule::ActivateAntenna (DoorStatus action)
//{
// ant_status = action;
//}

//void SDSFT::RevertAntenna (void)
//{
// ActivateAntenna ((ant_status == DOOR_CLOSED || ant_status == DOOR_CLOSING) ?
// DOOR_OPENING : DOOR_CLOSING);
//}

//void supplymodule::ActivateHatch (DoorStatus action)
//{
// hatch_status = action;
//}

//void supplymodule::RevertHatch (void)
//{
// ActivateHatch ((hatch_status == DOOR_CLOSED || hatch_status == DOOR_CLOSING) ?
// DOOR_OPENING : DOOR_CLOSING);
//}

void supplymodule::ActivateArray (DoorStatus action)
{
array_status = action;
}

void supplymodule::RevertArray (void)
{
ActivateArray ((array_status == DOOR_CLOSED || array_status == DOOR_CLOSING) ?
DOOR_OPENING : DOOR_CLOSING);
}

void supplymodule::ActivateArrayrot (DoorStatus action)
{
arrayrot_status = action;
}

void supplymodule::RevertArrayrot (void)
{
ActivateArrayrot ((arrayrot_status == DOOR_CLOSED || arrayrot_status == DOOR_CLOSING) ?
DOOR_OPENING : DOOR_CLOSING);
}

// ==============================================================
// Overloaded callback functions
// ==============================================================

// --------------------------------------------------------------
// Set vessel class parameters
// --------------------------------------------------------------
void supplymodule::clbkSetClassCaps (FILEHANDLE cfg)

{
// my variables
TRessources=0;
dPOxygen=0;
dPFood=0;
dPFuel=0;
iUpdatetankstatus=0;

THRUSTER_HANDLE th_main[8], th_rcs[24], th_group[4];
//THRUSTER_HANDLE th_main[2], th_hover, th_rcs[14], th_group[4];

SetSize (PB_SIZE);
SetEmptyMass (PB_EMPTYMASS);
SetPMI (PB_PMI);
SetCrossSections (PB_CS);
SetRotDrag (PB_RD);

// docking port definitions
//SetDockParams (PB_DOCK_POS, PB_DOCK_DIR, PB_DOCK_ROT);
//SetDockParams (PB_DOCK2_POS, PB_DOCK2_DIR, PB_DOCK2_ROT);

Dock0 = CreateDock(_V(0,0,4.7),_V(0,0,1),_V(0,1,0));
Dock1 = CreateDock(_V(0,0,-4.7),_V(0,0,-1),_V(0,1,0));
Dock2 = CreateDock(_V(2.7,0,0),_V(1,0,0),_V(0,1,0));
Dock3 = CreateDock(_V(-2.7,0,0),_V(-1,0,0),_V(0,1,0));

// propellant resources
//PROPELLANT_HANDLE hpr = CreatePropellantResource (PB_FUELMASS);
maintank = CreatePropellantResource (PB_FUELMASS);
foodtank = CreatePropellantResource (PB_FOODMASS);
oxygentank = CreatePropellantResource (PB_OXYGENMASS);



// main engine
th_main[0] = CreateThruster (_V(0, 2.5,-3.4), _V(0,0,1), PB_MAXMAINTH, maintank, PB_ISP);
th_main[1] = CreateThruster (_V(0,-2.5,-3.4), _V(0,0,1), PB_MAXMAINTH, maintank, PB_ISP);
th_main[2] = CreateThruster (_V( 2.5,0,-3.4), _V(0,0,1), PB_MAXMAINTH, maintank, PB_ISP);
th_main[3] = CreateThruster (_V(-2.5,0,-3.4), _V(0,0,1), PB_MAXMAINTH, maintank, PB_ISP);
th_main[4] = CreateThruster (_V( 1.8, 1.8,-3.4), _V(0,0,1), PB_MAXMAINTH, maintank, PB_ISP);
th_main[5] = CreateThruster (_V(-1.8,-1.8,-3.4), _V(0,0,1), PB_MAXMAINTH, maintank, PB_ISP);
th_main[6] = CreateThruster (_V(-1.8, 1.8,-3.4), _V(0,0,1), PB_MAXMAINTH, maintank, PB_ISP);
th_main[7] = CreateThruster (_V( 1.8,-1.8,-3.4), _V(0,0,1), PB_MAXMAINTH, maintank, PB_ISP);

th_group[0] = th_main[0];
CreateThrusterGroup (th_main, 8, THGROUP_MAIN);
AddExhaust (th_main[0], 0.4, 0.2, _V(0, 2.5,-3.45), _V(0,0,-1));
AddExhaust (th_main[1], 0.4, 0.2, _V(0,-2.5,-3.45), _V(0,0,-1));
AddExhaust (th_main[2], 0.4, 0.2, _V( 2.5,0,-3.45), _V(0,0,-1));
AddExhaust (th_main[3], 0.4, 0.2, _V(-2.5,0,-3.45), _V(0,0,-1));
AddExhaust (th_main[0], 0.4, 0.2, _V( 1.8, 1.8,-3.45), _V(0,0,-1));
AddExhaust (th_main[0], 0.4, 0.2, _V(-1.8,-1.8,-3.45), _V(0,0,-1));
AddExhaust (th_main[0], 0.4, 0.2, _V(-1.8, 1.8,-3.45), _V(0,0,-1));
AddExhaust (th_main[0], 0.4, 0.2, _V( 1.8,-1.8,-3.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.8), &exhaust_main);

// hover engine
//th_hover = CreateThruster (_V(0,-1.5,0), _V(0,1,0), PB_MAXHOVERTH, hpr, PB_ISP);
//CreateThrusterGroup (&th_hover, 1, THGROUP_HOVER);
//AddExhaust (th_hover, 8, 1, _V(0,-1.5,1), _V(0,-1,0));
//AddExhaust (th_hover, 8, 1, _V(0,-1.5,-1), _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.5, 0.2,-3.4), _V(0,-1,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[ 1] = CreateThruster (_V(-2.5, 0.2, 3.4), _V(0,-1,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[ 2] = CreateThruster (_V( 2.5, 0.2,-3.4), _V(0,-1,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[ 3] = CreateThruster (_V( 2.5, 0.2, 3.4), _V(0,-1,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[ 4] = CreateThruster (_V(-2.5,-0.2,-3.4), _V(0, 1,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[ 5] = CreateThruster (_V(-2.5,-0.2, 3.4), _V(0, 1,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[ 6] = CreateThruster (_V( 2.5,-0.2,-3.4), _V(0, 1,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[ 7] = CreateThruster (_V( 2.5,-0.2, 3.4), _V(0, 1,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[ 8] = CreateThruster (_V(0, 2.5, 3.4), _V(0,0,-1), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[ 9] = CreateThruster (_V(0,-2.5, 3.4), _V(0,0,-1), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[10] = CreateThruster (_V(-0.2, 2.5, 3.4), _V( 1,0,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[11] = CreateThruster (_V( 0.2, 2.5, 3.4), _V(-1,0,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[12] = CreateThruster (_V(-0.2,-2.5,-3.4), _V( 1,0,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[13] = CreateThruster (_V( 0.2,-2.5,-3.4), _V(-1,0,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[14] = CreateThruster (_V(-2.5,0,-3.4), _V(0,0, 1), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[15] = CreateThruster (_V(-2.5,0, 3.4), _V(0,0,-1), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[16] = CreateThruster (_V( 2.5,0, 3.4), _V(0,0,-1), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[17] = CreateThruster (_V( 2.5,0,-3.4), _V(0,0, 1), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[18] = CreateThruster (_V(0,-2.5,-3.4), _V(0,0, 1), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[19] = CreateThruster (_V(0, 2.5,-3.4), _V(0,0, 1), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[20] = CreateThruster (_V(-0.2, 2.5,-3.4), _V( 1,0,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[21] = CreateThruster (_V(-0.2,-2.5, 3.4), _V( 1,0,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[22] = CreateThruster (_V( 0.2, 2.5,-3.4), _V(-1,0,0), PB_MAXRCSTH, maintank, PB_ISP);
th_rcs[23] = CreateThruster (_V( 0.2,-2.5, 3.4), _V(-1,0,0), PB_MAXRCSTH, maintank, PB_ISP);

AddExhaust (th_rcs[ 0], 0.4, 0.2, _V(-2.5, 0.2,-3.15), _V(0,-1,0));
AddExhaust (th_rcs[ 1], 0.4, 0.2, _V(-2.5, 0.2, 3.15), _V(0,-1,0));
AddExhaust (th_rcs[ 2], 0.4, 0.2, _V( 2.5, 0.2,-3.15), _V(0,-1,0));
AddExhaust (th_rcs[ 3], 0.4, 0.2, _V( 2.5, 0.2, 3.15), _V(0,-1,0));
AddExhaust (th_rcs[ 4], 0.4, 0.2, _V(-2.5,-0.2,-3.15), _V(0, 1,0));
AddExhaust (th_rcs[ 5], 0.4, 0.2, _V(-2.5,-0.2, 3.15), _V(0, 1,0));
AddExhaust (th_rcs[ 6], 0.4, 0.2, _V( 2.5,-0.2,-3.15), _V(0, 1,0));
AddExhaust (th_rcs[ 7], 0.4, 0.2, _V( 2.5,-0.2, 3.15), _V(0, 1,0));
AddExhaust (th_rcs[ 8], 0.4, 0.2, _V(0, 2.5, 3.5), _V(0,0,-1));
AddExhaust (th_rcs[ 9], 0.4, 0.2, _V(0,-2.5, 3.5), _V(0,0,-1));
AddExhaust (th_rcs[10], 0.4, 0.2, _V(-0.2, 2.5, 3.15), _V(-1,0,0));
AddExhaust (th_rcs[11], 0.4, 0.2, _V( 0.2, 2.5, 3.15), _V( 1,0,0));
AddExhaust (th_rcs[12], 0.4, 0.2, _V(-0.2,-2.5,-3.15), _V(-1,0,0));
AddExhaust (th_rcs[13], 0.4, 0.2, _V( 0.2,-2.5,-3.15), _V( 1,0,0));
AddExhaust (th_rcs[14], 0.4, 0.2, _V(-2.5,0,-3.5), _V(0,0, 1));
AddExhaust (th_rcs[15], 0.4, 0.2, _V(-2.5,0, 3.5), _V(0,0,-1));
AddExhaust (th_rcs[16], 0.4, 0.2, _V( 2.5,0, 3.5), _V(0,0,-1));
AddExhaust (th_rcs[17], 0.4, 0.2, _V( 2.5,0,-3.5), _V(0,0, 1));
AddExhaust (th_rcs[18], 0.4, 0.2, _V(0,-2.5,-3.5), _V(0,0, 1));
AddExhaust (th_rcs[19], 0.4, 0.2, _V(0, 2.5,-3.5), _V(0,0, 1));
AddExhaust (th_rcs[20], 0.4, 0.2, _V(-0.2, 2.5,-3.15), _V(-1,0,0));
AddExhaust (th_rcs[21], 0.4, 0.2, _V(-0.2,-2.5, 3.15), _V(-1,0,0));
AddExhaust (th_rcs[22], 0.4, 0.2, _V( 0.2, 2.5,-3.15), _V( 1,0,0));
AddExhaust (th_rcs[23], 0.4, 0.2, _V( 0.2,-2.5, 3.15), _V( 1,0,0));

th_group[0] = th_rcs[0];
th_group[1] = th_rcs[2];
th_group[2] = th_rcs[5];
th_group[3] = th_rcs[7];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_PITCHUP);

th_group[0] = th_rcs[1];
th_group[1] = th_rcs[3];
th_group[2] = th_rcs[4];
th_group[3] = th_rcs[6];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_PITCHDOWN);

th_group[0] = th_rcs[0];
th_group[1] = th_rcs[1];
th_group[2] = th_rcs[6];
th_group[3] = th_rcs[7];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_BANKLEFT);

th_group[0] = th_rcs[2];
th_group[1] = th_rcs[3];
th_group[2] = th_rcs[4];
th_group[3] = th_rcs[5];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_BANKRIGHT);

th_group[0] = th_rcs[4];
th_group[1] = th_rcs[5];
th_group[2] = th_rcs[6];
th_group[3] = th_rcs[7];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_UP);

th_group[0] = th_rcs[0];
th_group[1] = th_rcs[1];
th_group[2] = th_rcs[2];
th_group[3] = th_rcs[3];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_DOWN);

th_group[0] = th_rcs[11];
th_group[1] = th_rcs[12];
th_group[2] = th_rcs[23];
th_group[3] = th_rcs[20];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_YAWLEFT);

th_group[0] = th_rcs[10];
th_group[1] = th_rcs[13];
th_group[2] = th_rcs[21];
th_group[3] = th_rcs[22];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_YAWRIGHT);

th_group[0] = th_rcs[11];
th_group[1] = th_rcs[13];
th_group[2] = th_rcs[22];
th_group[3] = th_rcs[23];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_LEFT);

th_group[0] = th_rcs[10];
th_group[1] = th_rcs[12];
th_group[2] = th_rcs[20];
th_group[3] = th_rcs[21];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_RIGHT);

th_group[0] = th_rcs[14];
th_group[1] = th_rcs[17];
th_group[2] = th_rcs[18];
th_group[3] = th_rcs[19];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_FORWARD);

th_group[0] = th_rcs[8];
th_group[1] = th_rcs[9];
th_group[2] = th_rcs[15];
th_group[3] = th_rcs[16];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_BACK);

// camera parameters
//SetCameraOffset (_V(0,2.4,3.9));
SetCameraOffset (_V(0,0,-1.6));

// associate a mesh for the visual
//AddMesh ("SD_SFT");
SetMeshVisibilityMode (AddMesh (exmesh_tpl = oapiLoadMeshGlobal ("SD_Supplymodule")), MESHVIS_EXTERNAL);
SetMeshVisibilityMode (AddMesh (vcmesh_tpl = oapiLoadMeshGlobal ("SD_SFT_VC")), MESHVIS_VC);

//hOrbiterVCMesh      = oapiLoadMeshGlobal ("SD_SFT_VC");

//--------------------------------------------------------------
// InitUmmu
// initialisation of Ummu must be done first ! return of 1 mean OK
// return of -999 mean Ummu addon is not installed in user's Orbiter, return of -1
// mean misc error. If error simply all function will fail silently
// and there will be no MMu. It's a good idea to warn the user.
// (see function "WarnUserUMMUNotInstalled" below)
Crew.InitUmmu(GetHandle());
//--------------------------------------------------------------

//--------------------------------------------------------------
// GetUserUMmuVersion
// this check wich version of UMmu addon the user have in his orbiter directory.
// this may be usefull for future version with more function so you can check
// if user installation support the new functions. Return -1 on error (not installed, version cannot be read)
// or version number in float value (ie: 2.0="2.0" version etc etc)
float UMmuVersion=Crew.GetUserUMmuVersion();

//--------------------------------------------------------------
// DefineAirLockShape
// We set the airlock shape and state, this virtual box will be the one
// into were a Ummu asking to reenter will be taken in account
// first parameter is airlock door state (OPEN=TRUE) and other are X,X1,Y,Y1 and Z,Z1
// min and max coordinate for this virtual box (vessel local coordinate)
// Pay attention to reenter when landed (if suitable) and make the box large enough so
// it's not a pain for the user to find airlock's entry. (See PDF doc)
Crew.DefineAirLockShape(TRUE,-1,1,-1,1,-6,-5); // Airlock open, 2 meter large 2 meter high 0.75 meter long (vessel local coordinate)

//--------------------------------------------------------------
// SetMembersPositionOrientationOnEVA
// We define here were the Ummu will appear when they make an EVA
// first parameter is position second is orientation, take care not to make
// them appear to high on ground (will fall and die) or to low (Orbiter "light speed" bug)
Crew.SetMembersPosRotOnEVA(_V(0,0,-5.5),_V(0,0,0)); // 3 meters in front of ship (z) facing direction of ship (vessel local coordinate)

//---------------------------------------------------------------
// finally set the maximum seat available in this ship, default is
// 8 but it can go from 1 to 100
// BAD IDEA: using this to "close" your ship, use "SetAirlockDoorState" instead.
Crew.SetMaxSeatAvailableInShip(5);

//--------------------------------------------------------------
// AddCrewMember
// We'll add four default members for when the ship is spawned by Orbiter's scenario editor.
// parameters are name, age, cardiac pulse,weight (in kilogramm) and Function (Misc ID)
// max four characters wich define the spacesuit used. (see UmmuMiscID in UMuSDK.h header)
// Return 1 on success -1 on error (probably vessel full, name>25 char
// age, pulse or weight out of realistic range or MiscID>4 char)
//Crew.AddCrewMember("Peter Falcon",41,65,74,"Capt"); //(for name and id a-z A-Z 0-9 characters only)
//Crew.AddCrewMember("Fanny Gorgeous",27,67,55,"Eng"); //(for name and id a-z A-Z 0-9 characters only)
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 3,4=select active dock A=(Q for azerty) Open/Close airlock S=info M (? for azerty)=add crew");

// The Add mmu without scenery editor variable see PDF doc
cAddUMmuToVessel[0]=0;

iActiveDockNumber=0;
    SetUMMUAirlockPos();

//UCGO 2.0 Initialisation, cargo slot pos, rot declaration
    hUcgo.Init(GetHandle());
    hUcgo.DeclareCargoSlot(0,_V( 1.8, 1.8, 1.5),_V(0,0,-45)); // slot 0
    hUcgo.DeclareCargoSlot(1,_V( 1.8, 1.8,0),_V(0,0,-45)); // slot 1
hUcgo.DeclareCargoSlot(2,_V( 1.8, 1.8,-1.5),_V(0,0,-45)); // slot 2
hUcgo.DeclareCargoSlot(3,_V(-1.8, 1.8, 1.5),_V(0,0,45)); // slot 3
hUcgo.DeclareCargoSlot(4,_V(-1.8, 1.8,0),_V(0,0,45)); // slot 4
hUcgo.DeclareCargoSlot(5,_V(-1.8, 1.8,-1.5),_V(0,0,45)); // slot 5

// UCGO 2.0 Parameters settings
    hUcgo.SetReleaseSpeedInSpace(0.001);        // release speed of cargo in space in m/s
    hUcgo.SetMaxCargoMassAcceptable(8000.0);   // max cargo mass in kg that your vessel can carry
    hUcgo.SetGrappleDistance(50);       // grapple distance radius in meter from center of ship
    hUcgo.SetGlobalGroundReleasePos(_V(0,0,4));// global release position on ground

// 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 = add cargo from disk, 8=infos on cargos");

strcpy(SendSandersHudMessage(),"Welcome in the Sanders aerospace supply module for space station Y to consume a fuel cargo, U to consume a Oxygen cargo, I to consume a Food cargo");

// ********************* beacon lights **********************

static VECTOR3 beacon1pos = {{2.6,0,3}};
static VECTOR3 beacon1col = {{1,1,0.4}};
{
beacon1.shape = (BEACONSHAPE_STAR);
beacon1.pos = &beacon1pos;
beacon1.col = &beacon1col;
beacon1.size = (0.2);
beacon1.falloff = (1);
beacon1.period = (0);
beacon1.duration = (0.5);
beacon1.tofs = (2);
beacon1.active = false;
AddBeacon (&beacon1);
}

static VECTOR3 beacon2pos = {{-2.6,0,3}};
static VECTOR3 beacon2col = {{1,1,0.4}};
    {
beacon2.shape = (BEACONSHAPE_STAR);
beacon2.pos = &beacon2pos;
beacon2.col = &beacon2col;
beacon2.size = (0.2);
beacon2.falloff = (1);
beacon2.period = (0);
beacon2.duration = (0.5);
beacon2.tofs = (2);
beacon2.active = false;
AddBeacon (&beacon2);
}

static VECTOR3 beacon3pos = {{2.8,0,-3}};
static VECTOR3 beacon3col = {{1,1,0.4}};
    {
beacon3.shape = (BEACONSHAPE_STAR);
beacon3.pos = &beacon3pos;
beacon3.col = &beacon3col;
beacon3.size = (0.2);
beacon3.falloff = (1);
beacon3.period = (0);
beacon3.duration = (0.5);
beacon3.tofs = (2);
beacon3.active = false;
AddBeacon (&beacon3);
}

static VECTOR3 beacon4pos = {{-2.8,0,-3}};
static VECTOR3 beacon4col = {{1,1,0.4}};
    {
beacon4.shape = (BEACONSHAPE_STAR);
beacon4.pos = &beacon4pos;
beacon4.col = &beacon4col;
beacon4.size = (0.2);
beacon4.falloff = (1);
beacon4.period = (0);
beacon4.duration = (0.5);
beacon4.tofs = (2);
beacon4.active = false;
AddBeacon (&beacon4);
}

static VECTOR3 beacon5pos = {{0,-2.6,3}};
static VECTOR3 beacon5col = {{1,1,0.4}};
    {
beacon5.shape = (BEACONSHAPE_STAR);
beacon5.pos = &beacon5pos;
beacon5.col = &beacon5col;
beacon5.size = (0.2);
beacon5.falloff = (1);
beacon5.period = (0);
beacon5.duration = (0.5);
beacon5.tofs = (2);
beacon5.active = false;
AddBeacon (&beacon5);
}

static VECTOR3 beacon6pos = {{0,2.6,3}};
static VECTOR3 beacon6col = {{1,1,0.4}};
    {
beacon6.shape = (BEACONSHAPE_STAR);
beacon6.pos = &beacon6pos;
beacon6.col = &beacon6col;
beacon6.size = (0.2);
beacon6.falloff = (1);
beacon6.period = (0);
beacon6.duration = (0.5);
beacon6.tofs = (2);
beacon6.active = false;
AddBeacon (&beacon6);
}

static VECTOR3 beacon7pos = {{0,2.6,-3}};
static VECTOR3 beacon7col = {{1,1,0.4}};
    {
beacon7.shape = (BEACONSHAPE_STAR);
beacon7.pos = &beacon7pos;
beacon7.col = &beacon7col;
beacon7.size = (0.2);
beacon7.falloff = (1);
beacon7.period = (0);
beacon7.duration = (0.5);
beacon7.tofs = (2);
beacon7.active = false;
AddBeacon (&beacon7);
}

static VECTOR3 beacon8pos = {{0,-2.6,-3}};
static VECTOR3 beacon8col = {{1,1,0.4}};
    {
beacon8.shape = (BEACONSHAPE_STAR);
beacon8.pos = &beacon8pos;
beacon8.col = &beacon8col;
beacon8.size = (0.2);
beacon8.falloff = (1);
beacon8.period = (0);
beacon8.duration = (0.5);
beacon8.tofs = (2);
beacon8.active = false;
AddBeacon (&beacon8);
}

}
// --------------------------------------------------------------
// Read status from scenario file
// --------------------------------------------------------------
void supplymodule::clbkLoadStateEx (FILEHANDLE scn, void *vs)
{
char *line;

while (oapiReadScenario_nextline (scn, line)) {
if(Crew.LoadAllMembersFromOrbiterScenario(line)==TRUE)
continue;
if(hUcgo.LoadCargoFromScenario(line)==TRUE) // UCGO load cargo
            continue;
//if (!_strnicmp (line, "ANT", 3)) {
//sscanf (line+3, "%d%lf", &ant_status, &ant_proc);
if (!_strnicmp (line, "FOLD", 4)) {
sscanf (line+5, "%d%lf", &array_status, &array_proc);
//} else if (!_strnicmp (line, "HATCH", 5)) {
// sscanf (line+5, "%d%lf", &hatch_status, &hatch_proc);
} else if (!_strnicmp (line, "ARROT", 5)) {
sscanf (line+5, "%d%lf", &arrayrot_status, &arrayrot_proc);

} else {
ParseScenarioLineEx (line, vs);
}
}

//SetAnimation (anim_ant, ant_proc);
//SetAnimation (anim_hatch, hatch_proc);
SetAnimation (anim_array, array_proc);
SetAnimation (anim_arrayrot, arrayrot_proc);

}

// --------------------------------------------------------------
// Save status to scenario file
// --------------------------------------------------------------
void supplymodule::clbkSaveState (FILEHANDLE scn)
{
char cbuf[256];
SaveDefaultState (scn);
sprintf (cbuf, "%d %0.4f", ant_status, ant_proc);
oapiWriteScenario_string (scn, "ANT", cbuf);
sprintf (cbuf, "%d %0.4f", hatch_status, hatch_proc);
oapiWriteScenario_string (scn, "HATCH", cbuf);
sprintf (cbuf, "%d %0.4f", array_status, array_proc);
oapiWriteScenario_string (scn, "FOLD", cbuf);
sprintf (cbuf, "%d %0.4f", arrayrot_status, arrayrot_proc);
oapiWriteScenario_string (scn, "ARROT", cbuf);

// ORBITER, default vessel parameters
SaveDefaultState (scn);

// UMmu, this will save all our members of crew in scenario
// as airlock state depend of your ship (you may have a real animated airlock)
// it's your responsabilites to save and reload UMmu's airlock state.
Crew.SaveAllMembersInOrbiterScenarios(scn);

// Save UCGO 2.0 cargo in scenario
    hUcgo.SaveCargoToScenario(scn);

//if (beacon1.active) {
// sprintf (cbuf, "%d %d %d", beacon1.active);
// oapiWriteScenario_string (scn, "LIGHTS", cbuf);
// }

}

// --------------------------------------------------------------
// Frame update
// --------------------------------------------------------------
void supplymodule::clbkPostStep (double simt, double simdt, double mjd)
{
// Animate hi-gain antenna
//if (ant_status >= DOOR_CLOSING) {
// double da = simdt * ANTENNA_OPERATING_SPEED;
// if (ant_status == DOOR_CLOSING) {
// if (ant_proc > 0.0) ant_proc = max (0.0, ant_proc-da);
// else                ant_status = DOOR_CLOSED;
// } else {
// if (ant_proc < 1.0) ant_proc = min (1.0, ant_proc+da);
// else                ant_status = DOOR_OPEN;
// }
// SetAnimation (anim_ant, ant_proc);
//}

// Animate main telescope hatch
//if (hatch_status >= DOOR_CLOSING) {
// double da = simdt * HATCH_OPERATING_SPEED;
// if (hatch_status == DOOR_CLOSING) {
// if (hatch_proc > 0.0) hatch_proc = max (0.0, hatch_proc-da);
// else                  hatch_status = DOOR_CLOSED;
// } else {
// if (hatch_proc < 1.0) hatch_proc = min (1.0, hatch_proc+da);
// else                  hatch_status = DOOR_OPEN;
// }
// SetAnimation (anim_hatch, hatch_proc);
//}

// Animate solar arrays
if (array_status >= DOOR_CLOSING) {
double da = simdt * ARRAY_OPERATING_SPEED;
if (array_status == DOOR_CLOSING) {
if (array_proc > 0.0) array_proc = max (0.0, array_proc-da);
else                  array_status = DOOR_CLOSED;
} else {
if (array_proc < 1.0) array_proc = min (1.0, array_proc+da);
else                  array_status = DOOR_OPEN;
}
SetAnimation (anim_array, array_proc);
}

//Animate solar arrays rotation
if (arrayrot_status >= DOOR_CLOSING) {
double da = simdt * ARRAYROT_OPERATING_SPEED;
if (arrayrot_status == DOOR_CLOSING) {
if (arrayrot_proc > 0.0) arrayrot_proc = max (0.0, arrayrot_proc-da);
else                  arrayrot_status = DOOR_CLOSED;
} else {
if (arrayrot_proc < 1.0) arrayrot_proc = min (1.0, arrayrot_proc+da);
else                  arrayrot_status = DOOR_OPEN;
}
SetAnimation (anim_arrayrot, arrayrot_proc);
}

//---------------------------------------------------------------------------
// ProcessUniversalMMu
// Here the routine that detect if someone entered the ship (eva or transfer)
// No need to manage anything here all is automatic, crew is added to your ship, ship's weight is updated,
// and UMmu vessel is automatically deleted from Orbiter. You may just look the return
// code to see if someone entered and display wathewer message on panel or other.
// notice it's FPS friendly, function process only 4 time per second not each frame
// and return immediately if airlock closed or no Ummu is detected in vincinity.
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;
}

//----------------------------------------------------------------------------
// SetCrewMemberPulseBySlotNumber
// Now we will kill all our crew aboard if we crash on ground. First we test
// if we have ground contact, then we check vertical speed and if it's more than
// -3 m/s we kill all people aboard. Of course in your code you'll do that only
// one time using a bool flag if(!bCrewAlreadyKilled) for example. Here we do it each
// time step for code ease of read.
//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");
//}

// TIPS: the vertical speed is often reset to zero when there is ground contact
// this may bug somewhat the death of your crew.
// to have an accurate VertSpeed at touchdown I recommand to record it at very END
// of timestep and use this "old" value. The next frame you'll have the vertspeed value
// of *last frame* just before the crash (GroundContact). This ensure an accurate
// verticalspeed value. (keep this value in your vessel class and don't forget to
// initialize it at zero in setclasscap)
//}

//---------------------------------------------------------------------------
// WarnUserUMMUNotInstalled - IMPORTANT helper
// Put here this function and users will be automatically warned if they don't have
// UMMU installed or if it's outdated. Warning text duration is 20 seconds and text is:
// [AddonName] require "Universal MMU" ver 2.0 or higher. Download at www.orbiter.dansteph.com (message countdown in seconds)
// an additonal "your version of UMMU is outdated" is displayed the last 5 seconds if they have version lower than 2.0
Crew.WarnUserUMMUNotInstalled("supplymodule");
// At the very end of clbkPostStep or clbkPreStep
    hUcgo.WarnUserUCGONotInstalled("supplymodule");


// THIS IS FOR ADDING CREW SEE PDF doc "Allow user to add crew to your ship
// without scenery editor"
AddUMmuToVessel();

//double CrewN = Crew.GetCrewTotalNumber();
    //double O2consumption = CrewN;
    //double O2lvl = GetPropellantMass(oxygentank);
//double foodlvl = GetPropellantMass(foodtank);

// Crew O2 consumption
//if (GetPropellantMass(oxygentank) > 0) {

    //O2lvl = O2lvl-(O2consumption*(simdt*0.001));
    //}

//// Crew food consumption
//if (GetPropellantMass(foodtank) > 0) {

    //foodlvl = foodlvl-(O2consumption*(simdt*0.001));
    //}

Data.dDynPressure =GetDynPressure(); // Pression dynamique

if(iDetecteChangementSeconde!=(int)simt)
{
// le principe: simt donnée par la fonction contient le temp actuel de simulation en seconde
// je le stock dans dDetecteChangementSeconde et je la compare a chaque image avec le temp
// actuel, si pas egal une seconde c'est ecoulée j'incrémente de 1 dTempDeSimulationTotal.
// comme dTempDeSimulationTotal est sauvée/rechargée du scenario elle affichera le temps
// total de vol *avec ce scenario* (on pourrait faire un temp total de vol avec votre addon
// en sauvant dans un fichier externe mais on va pas exagerer dans ce template.)
TRessources++;
iDetecteChangementSeconde=(int)simt;


}

double CrewN = Crew.GetCrewTotalNumber();
double O2consumption = CrewN;
double O2lvl = GetPropellantMass(oxygentank);
double O2lv2;
double foodlvl = GetPropellantMass(foodtank);
double foodlv2;
int TRessources=(0);

if (GetPropellantMass(oxygentank) > 0) {
        O2lv2 = O2lvl-(O2consumption*0.000008);
SetPropellantMass (oxygentank,O2lv2);
TRessources=0;
}

if (GetPropellantMass(foodtank) > 0) {
        foodlv2 = foodlvl-(O2consumption*0.00001);
SetPropellantMass (foodtank,foodlv2);
TRessources=0;
}

if (GetPropellantMass(oxygentank) < 0.000008)  // can be o2 or temperature problem etc etc
    {
        int C=0;
        //  sorry dude, time to kill you all :(
        for(C=0;C<Crew.GetCrewTotalNumber();C++)
        {
        Crew.SetCrewMemberPulseBySlotNumber(C,0); // set cardiac pulse to zero
sprintf(SendHudMessage(),"Oxygen tank are empty, GAME OVER");
        }
    }

if (GetPropellantMass(foodtank) < 0.00001)  // can be o2 or temperature problem etc etc
    {
        int C=0;
        //  sorry dude, time to kill you all :(
        for(C=0;C<Crew.GetCrewTotalNumber();C++)
        {
        Crew.SetCrewMemberPulseBySlotNumber(C,0); // set cardiac pulse to zero
sprintf(SendHudMessage(),"Food reserve are empty, GAME OVER");
        }
    }

if (Data.dDynPressure > 7000)  // can be o2 or temperature problem etc etc
    {
        int C=0;
        //  sorry dude, time to kill you all :(
        for(C=0;C<Crew.GetCrewTotalNumber();C++)
        {
        Crew.SetCrewMemberPulseBySlotNumber(C,0); // set cardiac pulse to zero
sprintf(SendHudMessage(),"you tried a reentry with a space station and this is a failure : we can deduce that all crew are death");
        }
    }

dPOxygen=(GetPropellantMass(&oxygentank)*100)/2000;
    dPFood=(GetPropellantMass(&foodtank)*100)/2000;
    dPFuel=(GetPropellantMass(&maintank)*100)/2000;
sprintf(SendRessourcesHudMessage(),"O2 Level = %.2f food level = %.2f fuel level = %.2f",dPOxygen,dPFood,dPFuel);
}

// --------------------------------------------------------------
// Keyboard interface handler (buffered key events)
// --------------------------------------------------------------
int supplymodule::clbkConsumeBufferedKey (DWORD key, bool down, char *kstate)
{

if (!down) return 0; // only process keydown events

//if (KEYMOD_CONTROL (kstate)) {
else
    {
switch (key) {
//case OAPI_KEY_G: // deploy/retract antenna
// RevertAntenna();
// return 1;
//case OAPI_KEY_O: // open/close hatch
// RevertHatch();
// return 1;
//case OAPI_KEY_K: // open/fold solar arrays
// RevertArray();
// return 1;
case OAPI_KEY_O: // open/fold solar arrays rotation
RevertArrayrot();
return 1;
}
//}
//return 0;



//---------------------------------------------------------------------------
// Ummu Key "E" perform the EVA of the selected member
//
// ADD REALISM: It's your responsabilities also to set ship's control accordingly to crew aboard.
// If you want to disable control if no one is aboard have a look at "SetADCtrlMode()"
// and "SetAttitudeMode()" functions of Orbiter. To disable thrusters set their fuel
// ressource to NULL.
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))
//{
if(key==OAPI_KEY_1)
    {
// 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))
//{
if(key==OAPI_KEY_2)
    {
// 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))
//{
if(key==OAPI_KEY_A)
    {
//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_Z)
{
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))
//{
if(key==OAPI_KEY_M)
    {
AddUMmuToVessel(TRUE);
}

// change active dock
if(key==OAPI_KEY_3)
{
if(iActiveDockNumber>0)
iActiveDockNumber--;
sprintf(SendHudMessage(),"Active dock number changed to: %i",iActiveDockNumber);
SetUMMUAirlockPos();
return 1;
}
//---------------------------------------------------------------------------
// change active dock
if(key==OAPI_KEY_4)
{
if(iActiveDockNumber<4)
iActiveDockNumber++;
sprintf(SendHudMessage(),"Active dock number changed to: %i",iActiveDockNumber);
SetUMMUAirlockPos();
return 1;
}

// 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;
}

//if(key==OAPI_KEY_7&&KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
//
//{
//SetFuelMass (4000);
//return 1;
//}


switch (key)

case OAPI_KEY_0:

{
if (beacon1.active == true)
{
beacon1.active = false;
beacon2.active = false;
beacon3.active = false;
beacon4.active = false;
beacon5.active = false;
beacon6.active = false;
beacon7.active = false;
beacon8.active = false;
}
else
{
beacon1.active = true;//beacon[i].active = true;
beacon2.active = true;
beacon3.active = true;
beacon4.active = true;
beacon5.active = true;
beacon6.active = true;
beacon7.active = true;
beacon8.active = true;
}
return true;
}

if(key==OAPI_KEY_Y) //refill fuel tank
{
double dNeededFuel=PB_FUELMASS-GetPropellantMass (maintank);
    if(dNeededFuel<20)
    {
    strcpy(SendCargHudMessage(),"Fuel tanks almost full");
    return 1;
    }
    double dEatenFuel=hUcgo.EatCloserFuelCargo(dNeededFuel);
    if(dEatenFuel<0)
    {
    strcpy(SendCargHudMessage(),"no fuel cargo found aboard or in vincinity");
    return 1;
    }
    // refill
    SetPropellantMass (maintank,GetPropellantMass (maintank)+dEatenFuel);
    sprintf(SendCargHudMessage(),"%.2fkg of fuel added to tank",dEatenFuel);
return 1;
}

if(key==OAPI_KEY_U) //refill O2 tank
{
double dNeededoxygen=PB_OXYGENMASS-GetPropellantMass (oxygentank);
    if(dNeededoxygen<20)
    {
    strcpy(SendCargHudMessage(),"Oxygen tanks almost full");
    return 1;
    }
    double dEatenOxygen=hUcgo.EatCloserOxygenCargo(dNeededoxygen);
    if(dEatenOxygen<0)
    {
    strcpy(SendCargHudMessage(),"no oxygen cargo found aboard or in vincinity");
    return 1;
    }
    // refill
    SetPropellantMass (oxygentank,GetPropellantMass (oxygentank)+dNeededoxygen);
    sprintf(SendCargHudMessage(),"%.2fkg of oxygen added to tank",dNeededoxygen);
return 1;
}

if(key==OAPI_KEY_I) //refill food tank
{
double dNeededfood=PB_FOODMASS-GetPropellantMass (foodtank);
    if(dNeededfood<20)
    {
    strcpy(SendCargHudMessage(),"Oxygen tanks almost full");
    return 1;
    }
    double dEatenfood=hUcgo.EatCloserCargoByType("food",dNeededfood);
    if(dEatenfood<0)
    {
    strcpy(SendCargHudMessage(),"no food cargo found aboard or in vincinity");
    return 1;
    }
    // refill
    SetPropellantMass (foodtank,GetPropellantMass (foodtank)+dNeededfood);
    sprintf(SendCargHudMessage(),"%.2fkg of food added to tank",dNeededfood);
return 1;
}

return 0;

    }


}

bool supplymodule::clbkLoadVC (int id)
{
     id = 0;
SetCameraDefaultDirection (_V(0,0,1));
oapiVCSetNeighbours (-1, 1, -1, 2);
//InitPanel(-1);// VC is -1
     return true;
}

// --------------------------------------------------------------
// Respond to generic messages
// --------------------------------------------------------------
int supplymodule::clbkGeneric (int msgid, int prm, void *context)
{
switch (msgid) {
case VMSG_LUAINTERPRETER:
return Lua_InitInterpreter (context);
case VMSG_LUAINSTANCE:
return Lua_InitInstance (context);
}
return 0;
}

// --------------------------------------------------------------
// Orbiter's HUD callback
// used to display UMMU's message see PDF doc:
// "Example of feedback method by HUD Display"
// --------------------------------------------------------------
void supplymodule::clbkDrawHUD (int mode, const HUDPAINTSPEC *hps, HDC hDC)
{
// draw the default HUD
VESSEL2::clbkDrawHUD (mode, hps, hDC);

// UMmu display messages
if(dHudMessageDelay>0)
{
TextOut (hDC,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*13,cCargoHudDisplay,strlen(cCargoHudDisplay));
        dCargHudMessageDelay-=oapiGetSimStep();
        if(dCargHudMessageDelay<0)
        dCargHudMessageDelay=0;
    }

// Sanders display messages
    if(dSandersHudMessageDelay>0)
    {
        TextOut (hDC,5,hps->H/60*11,cSandersHudDisplay,strlen(cSandersHudDisplay));
        dSandersHudMessageDelay-=oapiGetSimStep();
        if(dSandersHudMessageDelay<0)
        dSandersHudMessageDelay=0;
    }

// Ressources display messages
    if(dRessourcesHudMessageDelay>0)
    {
        TextOut (hDC,5,hps->H/60*17,cRessourcesHudDisplay,strlen(cRessourcesHudDisplay));
        dRessourcesHudMessageDelay-=oapiGetSimStep();
        if(dRessourcesHudMessageDelay<0)
        dRessourcesHudMessageDelay=0;
    }
}

//------------------------------------------------------------------------------------------------------------------
// UTILITY FONCTION  -  UTILITY FONCTION  - UTILITY FONCTION  - UTILITY FONCTION  - UTILITY FONCTION
//
// This below is not mandatory for UMmu to run, anyway such functions can help you to implement UMmu
// in your addon. A recommended read at least.
//
//------------------------------------------------------------------------------------------------------------------

///////////////////////////////////////////////////////////////////////////////////////////
// USING HUD INTERFACE FOR FEEDBACK DISPLAY
//
// This method is explained in the PDF tutorial, now if you want to use another method
// comment the "UMMU" display lines in clbkHudDraw above and use the char variable
// "cUmmuHudDisplay" wich will contain all the messages of UMMU to display it on VC or panel.
// No other change required in code.
///////////////////////////////////////////////////////////////////////////////////////////
char *supplymodule::SendHudMessage()
{
dHudMessageDelay=15;
return cUmmuHudDisplay;
}

////////////////////////////////////////////////////////
// SendCargHudMessage
////////////////////////////////////////////////////////
char *supplymodule::SendCargHudMessage(void)
{
    dCargHudMessageDelay=15; // 15 seconds display delay for msg
    return cCargoHudDisplay;
}

char *supplymodule::SendSandersHudMessage(void)
{
    dSandersHudMessageDelay=15; // 15 seconds display delay for msg
    return cSandersHudDisplay;
}

char *supplymodule::SendRessourcesHudMessage(void)
{
    dRessourcesHudMessageDelay=1; // 15 seconds display delay for msg
    return cRessourcesHudDisplay;
}

//-------------------------------------------------------------------------
// 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 supplymodule::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?)");
}
}
}

// --------------------------------------------------------------
// clbkVisualCreated
// --------------------------------------------------------------
void supplymodule::clbkVisualCreated (VISHANDLE vis, int refcount)
{
hUcgo.SetUcgoVisual(vis); // must be called in clbkVisualCreated.
}

//double supplymodule::foodOxygenConsuption()
//{
// int TRessources=(0);
// double CrewN = Crew.GetCrewTotalNumber();
//
// if (GetPropellantMass(oxygentank) > 0) {
// if (TRessources=1) {
//       oxygentank = oxygentank-(0.008*CrewN);
// }
// }
//}

// END of  "Allow user to add crew to your ship without scenery editor"
//--

///////////////////////////////////////////////////////////////////////////////////////////
// SetUMMUAirlockPos - example with two dock
///////////////////////////////////////////////////////////////////////////////////////////
void supplymodule::SetUMMUAirlockPos(void)
{

int AirlockStatus=Crew.GetAirlockDoorState();
Crew.SetActiveDockForTransfer(iActiveDockNumber);

switch(iActiveDockNumber)
{
case 0:

Crew.DefineAirLockShape(AirlockStatus,-1,1,-1,1,-6,-5);
Crew.SetMembersPosRotOnEVA(_V(0,0,-5.5),_V(0,0,0));
//definissez ici la position de la camera pour ce dock
break;
case 1:
Crew.DefineAirLockShape(AirlockStatus,-1,1,-1,1,-6,-5);
Crew.SetMembersPosRotOnEVA(_V(0,0,-5.5),_V(0,0,0));
//definissez ici la position de la camera pour ce dock
break;
case 2:
Crew.DefineAirLockShape(AirlockStatus,-1,1,-1,1,-6,-5);
Crew.SetMembersPosRotOnEVA(_V(0,0,-5.5),_V(0,0,0));
//definissez ici la position de la camera pour ce dock
break;
case 3:
Crew.DefineAirLockShape(AirlockStatus,-1,1,-1,1,-6,-5);
Crew.SetMembersPosRotOnEVA(_V(0,0,-5.5),_V(0,0,0));
//definissez ici la position de la camera pour ce dock
break;
}
}

// ==============================================================
// API callback interface
// ==============================================================

// --------------------------------------------------------------
// Vessel initialisation
// --------------------------------------------------------------
DLLCLBK VESSEL *ovcInit (OBJHANDLE hvessel, int flightmodel)
{
return new supplymodule (hvessel, flightmodel);
}

// --------------------------------------------------------------
// Vessel cleanup
// --------------------------------------------------------------
DLLCLBK void ovcExit (VESSEL *vessel)
{
if (vessel) delete (supplymodule*)vessel;
}

« Last Edit: 07 August 2012, 16:21:50 by ea76620 »

Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15407
  • Karma: 256
  • Hein, quoi !?
    • FsPassengers
Reply #9 - 07 August 2012, 15:20:29
Essaie comme cela mais gaffe toi un truc: Il y a de grandes chance que tes réservoirs soient vide au lancement du scénario.

Code: [Select]
sprintf(SendRessourcesHudMessage(),"O2 Level = %.2f food level = %.2f fuel level = %.2f",(float)dPOxygen,(float)dPFood,(float)dPFuel);

« Last Edit: 07 August 2012, 16:21:50 by DanSteph »

Offline ea76620

  • Sr. Member
  • ****
  • Posts: 393
  • Country: France fr
  • Karma: 15
Reply #10 - 07 August 2012, 15:26:55
Non, ça ne change rien, ça affiche toujours 0.00 (et des truc bizarre pour le fuel) quelque soit le remplissage des réservoirs.



Message modifié ( 07-08-2012 15:31 )

« Last Edit: 07 August 2012, 16:21:50 by ea76620 »

Offline Bibi Uncle

  • Legend
  • ******
  • Posts: 2264
  • Country: Canada ca
  • Karma: 17
Reply #11 - 07 August 2012, 15:40:29
L'erreur vient de ceci : GetPropellantMass(&oxygentank). La fonction GetPropellantMass est défini comme ceci : double VESSEL::GetPropellantMass (PROPELLANT_HANDLE  ph)  const et ne demande pas un pointeur (bien que PROPELLANT_HANDLE est un typedef d'un pointeur void), mais un PROPELLANT_HANDLE.

Essaie ceci :

Code: [Select]
dPOxygen=(GetPropellantMass(oxygentank)*100)/2000;
dPFood=(GetPropellantMass(foodtank)*100)/2000;
dPFuel=(GetPropellantMass(maintank)*100)/2000;
sprintf(SendRessourcesHudMessage(),"O2 Level %.2f food level %.2f fuel level %.2f",dPOxygen,dPFood,dPFuel);

Et si je peux ajouter un petit commentaire, fait bien attention au casting (et non, nous ne sommes pas dans un film !). Par exemple, GetPropellantMass retourne un double, que tu multiplies par un int puis divise par un int. Essaie de toujours garder le même type entre tes opérations, sauf si tu as réellement besoin de changer de type. Dans ce cas-ci, tu aurais pu simplement ajouter un .0 après tes nombres pour les caster en double. Comme ceci :

Code: [Select]
dPOxygen=(GetPropellantMass(oxygentank)*100.0)/2000.0;
dPFood=(GetPropellantMass(foodtank)*100.0)/2000.0;
dPFuel=(GetPropellantMass(maintank)*100.0)/2000.0;
sprintf(SendRessourcesHudMessage(),"O2 Level %.2f food level %.2f fuel level %.2f",dPOxygen,dPFood,dPFuel);


« Last Edit: 07 August 2012, 16:21:50 by Bibi Uncle »
Émile

Pluton, Saturne et Jupiter
Entendez-vous monter vers vous le chant de la Terre?

- Luc Plamondon

Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15407
  • Karma: 256
  • Hein, quoi !?
    • FsPassengers
Reply #12 - 07 August 2012, 15:59:20
Bien vu !

Dan

« Last Edit: 07 August 2012, 16:21:50 by DanSteph »

Offline ea76620

  • Sr. Member
  • ****
  • Posts: 393
  • Country: France fr
  • Karma: 15
Reply #13 - 07 August 2012, 16:21:50
:merci: , à vous deux, ça marche!



Je vais essayer de mettre le temps restant avant épuisement des réserves.



Message modifié ( 07-08-2012 16:28 )

« Last Edit: 07 August 2012, 16:21:50 by ea76620 »