Raccourcis clavier pour Settings.xml

Collection d'informations non triées publiées par George Moromisato sur le fonctionnement interne de Transcendance

### Dossiers du ministère

George publiera parfois des informations très détaillées sur Ministry . Voir la Ministry\_notes page

### Sur les versions futures

Il existe une chaîne de portes menant de Sol à St. Katharine's, mais elle n'est pas incluse dans la v1 (elle le sera probablement dans la future version). Lien du forum

La porte des étoiles Kuiper mène au système Centauri (qui n'est pas inclus dans la v1). Lien du forum

### À l'échelle du jeu

Les planètes et les étoiles utilisent une échelle exponentielle inverse :

La formule est (en gros)

taille des pixels = ( (taille en km) ^ (0,25) ) \* 22,25

### Arme de destruction massive

Lorsque vous frappez une grande station, seules les armes de destruction massive comptent. Les armes de destruction massive représentent un certain pourcentage des dégâts normaux d'une arme, en utilisant ce tableau :

```
* DDM0 = 0%
 * ADM1 = 4 %
 *ADM2 = 10 %
 *ADM3 = 20%
 *ADM4 = 34%
 *ADM5 = 52%
 *ADM6 = 74 %
 * ADM7 = 100 %

```

Par exemple, si 10 points de dégâts WMD3 touchent une station, alors la station ne subit que 20 % des dégâts, soit 2 points. Indépendamment de ce qui précède, tout coup sur une station provoque au moins 1 point de dégâts, donc même les armes sans ADM causent des dégâts (cela peut ou non changer à l'avenir).

Notez que seules les stations avec multiHull="true" comptent comme de "grandes stations".

Les navires subissent généralement tous les dégâts (indépendamment des armes de destruction massive), mais pour les navires dotés de segments de blindage « non critiques », les armes de destruction massive entrent en jeu. La probabilité qu'un coup sur un segment non critique détruise le navire augmente pour les armes ADM.

Lorsque vous frappez des épaves, etc., seules les armes de destruction massive comptent.

### Le temps en transcendance

Le temps dans la transcendance est quantifié. Le Bullet-time l’est doublement. N'oubliez pas que l'univers se met à jour tous les 1/30ème de seconde (en temps réel), ce qui signifie que le temps ne peut pas être subdivisé en dessous de ce quantum.

Puisque le mouvement est juste (vitesse X temps), le mouvement dans Transcendance est également quantifié, c'est-à-dire que les objets sembleront « sauter » d'un point de l'espace à un autre.

Les balles dans Transcendance obéissent à ces lois quantiques. Parfois, les balles semblent « sauter » à travers une barrière solide. Ce n’est pas une illusion, mais plutôt une propriété des lois quantiques de Transcendance.

Les navires ne semblent jamais traverser les murs car ce sont des objets macroscopiques grands et (relativement) lents ; mais les balles sont petites et rapides et sujettes à ces effets quantiques.

Pourquoi est-ce que je ne corrige pas simplement ce bug (quantique) ?

Ouais, je n'ai pas de bonne réponse à ça :)

#### En savoir plus sur le temps dans la transcendance

Depuis les forums

L'échelle de temps actuelle est de 1 tick = 2 secondes de temps de jeu.

Dans une future version, je conserverai un chronomètre de jeu séparé qui pourra avancer (et reculer ?) indépendamment du nombre de ticks.

Par exemple, lorsque vous franchissez une porte, un temps plus long peut s'écouler que celui indiqué sur le décompte des ticks.

J'ajouterai des fonctions pour convertir les ticks en temps de jeu et vice versa.

Si vous écrivez aujourd'hui des fonctions qui effectuent cette conversion et ne faites pas d'hypothèses sur la relation entre les ticks et le temps de jeu, vous devriez alors pouvoir migrer naturellement une fois que les fonctions intégrées apparaîtront.

Quelques notes sur l'univers canonique :

1. Dans l’Espace Humain, les dates sont encore mesurées selon les normes terrestres : jours, mois, années.

2. Au début du jeu dans la campagne Domina & Oracus, nous sommes en 2419.

3. Les dates galactiques (c'est-à-dire le calendrier utilisé par les Races Anciennes) sont évidemment différentes. Ils mesurent les « dates » en utilisant quatre valeurs :

Un « orbis » correspond à peu près à une révolution galactique, soit environ 211,65 millions d'années. Un « orbis » est divisé en 30 « trisem » Un « trisem » est divisé en 200 « arcs » Un « arc » est divisé en 780 « genres »

Un « genre » correspond à environ 45 ans.

N'importe quelle date de l'histoire galactique peut être exprimée avec ces quatre chiffres (avec une résolution de 45 ans) :

La date galactique actuelle est :

21.2.198.473

Je n'ai pas vraiment calculé d'échelles de temps inférieures à une granularité de 45 ans.

### Rendu des objets spatiaux pour la transcendance

Pour positionner la caméra et les lumières, imaginez que l'objet est à l'origine : La caméra est à 6 unités et à 12 unités au-dessus de l'objet. La source de lumière est à 3 unités vers la gauche (vue de la caméra), 5 unités derrière [Remarque : LA LUMIÈRE VIENT DU HAUT À GAUCHE DE L'IMAGE, « DERRIÈRE » se traduit par « derrière le navire du point de vue de la caméra » et NON « derrière le navire du point de vue du navire »] et 5 unités au-dessus de l'objet (Remarque : traitez la source de lumière comme étant à l'infini).

Parements acceptables pour les navires : 1 2 3 4 5 6 8 9 dix 12 15 18 20 24 30 36 40 45 60 72 90 120 180 360

#### Une autre façon de comprendre la scène 3D

*Cette section ne vient pas directement de George, c'est une tentative de clarifier davantage la configuration de George.*

En supposant un système de coordonnées droitier :

\* Le centre de rotation du navire est à l'origine. Lorsque le vaisseau est orienté droit vers le haut dans Trans, il pointe vers le bas de l'axe +Y, les côtés gauche et droit sont respectivement -X et +X, +Z est le haut du vaisseau (ce que vous voyez principalement dans Trans) .

\* La caméra est située le long de la ligne -1y:2z et pointe vers l'origine.

\* La lumière principale (une lampe infinie/solaire) est située le long de la ligne -1x:2y:4z. (EG -1,2,4; -2,4,8, etc.), et pointe vers l'origine. Je veux probablement faire du shadowcasting sur celui-ci.

Pour un système de coordonnées gaucher, échangez X et Y (+X est « avant », +Y est « droite »)

### Paramètres de débogage vidéo

Lors de l'exécution du jeu avec /debugvideo, les paramètres sont imprimés dans le debug.log

Paint = Le temps (en millisecondes) nécessaire pour peindre tous les objets (navires, stations, effets, etc.) dans un tampon hors écran. Si celui-ci est élevé, cela signifie qu'il y a une tonne d'objets sur l'écran OU que certains effets (explosions, etc.) mettent beaucoup de temps à être peints.

Blt = Le temps (en millisecondes) nécessaire pour supprimer le tampon hors écran de la carte vidéo. Si ce chiffre est élevé, cela signifie que la carte vidéo ne peut pas suivre le rythme. Cela pourrait s'améliorer avec /dx. Ce nombre est constant quel que soit le nombre d'objets à l'écran ou dans le système (mais peut varier si d'autres applications accèdent à la carte vidéo).

Update = Le temps (en millisecondes) nécessaire pour calculer l'état du jeu. Si ce chiffre est élevé, cela signifie qu’il y a beaucoup d’objets qui font beaucoup de choses. Par exemple, ce temps augmente avec beaucoup de nains. Cela augmente également si vous êtes en pilote automatique (puisque nous mettons à jour plusieurs fois par image).

Si vous faites le calcul, chaque image doit être traitée en un peu plus de 33 millisecondes pour atteindre 30 images par seconde. Si la somme des valeurs ci-dessus dépasse 33 millisecondes, vous n'obtiendrez pas un jeu fluide.

Sur un Dell M1330, mes temps à Eridani ressemblent à ceci :

22/12/2008 11:31:36 Images : 30 Peinture : 2 Blt : 7 Mise à jour : 0 22/12/2008 11:31:46 Images : 30 Peinture : 3 Blt : 10 Mise à jour : 0 22/12/2008 11:31:56 Images : 30 Peinture : 3 Blt : 9 Mise à jour : 0

Plus profondément dans le jeu, Paint et Update commencent à grimper.

### Schéma de capitalisation DockScreen Actions

1. S'il s'agit d'une commande, utilisez des majuscules :

Acheter des articles Remplacer l'armure Parlez au chef de la station

2. If it's the name of a place, then use title capitalization:

Dock Services Ringer Lab Hall of Mirrors

3. If it's something the player says, put it in quotes and punctuate:

“Who is Domina?” “OK, you have a deal.” “He says you betrayed the Fleet.”

### Code source des calculs internes du missile George (probablement ancien)

Je ne sais pas si cela va aider (ou confondre) mais voici le code que j'utilise pour calculer le temps d'interception pour qu'un missile d'une vitesse donnée frappe une cible se déplaçant à une certaine vitesse (constante).

Une fois que vous avez calculé le temps d'interception, vous pouvez utiliser une simple trigonométrie pour calculer où viser (puisque vous saurez où se trouvera le navire lorsque le missile frappera).

Bonne chance!

```
Métrique CSystem  ::  CalcInterceptTime
   (
   const  Vector  &  vTarget  ,
   const  Vector  &  vTargetVel  ,
    Métrique rMissileSpeed  ​​,
    Métrique  *  retrRange
    )

   // CalcInterceptTime
   //
   // Renvoie le temps qu'il faudrait pour intercepter une cible
   // à vTarget, se déplaçant avec la vitesse vTargetVel, avec
   // un missile de vitesse rMissileSpeed.   Renvoie < 0,0 si le missile ne peut pas
   // intercepter la cible.
    //
   // La formule d'interception est :
   //
   // A +- B sqrt(C)
   // t = --------------
   // D
   //
   // Où :
   / / A = B * rVi
   // B = 2 * rRange
   // C = rMissileSpeed^2 - rVj^2
   // D = 2 * (C - rVi^2)
   //
   // rVi = la vitesse cible le long du vecteur de position
   // rVj = la vitesse cible tangentielle au vecteur position
   // rRange = la distance (initiale) à la cible
   // rMissileSpeed ​​= la vitesse du missile

   {
    Métrique rRange  =  vTarget.   Longueur  (  )  ;
    Vecteur vPosNormal  =  vTarget  /  rRange  ;

    si   (  retrRange  )
    *  retrRange =  rPlage  ;

    // Calcule les orthogonales de la vitesse le long du vecteur position

    Métrique rVi  ,  rVj  ;
    vTargetVel.   Générer des orthogonaux  (  vPosNormal  ,   &  rVi  ,   &  rVj  )  ;

    // Déterminez l'intérieur de la racine carrée.   Si cette valeur est négative
   // ​​alors nous n'avons pas de cours d'interception.

    Métrique C  =  rMissileSpeed  ​​*  rMissileSpeed  ​​-  rVj  *  rVj  ;
    si   (  C  <   0,0  )
    renvoie   -  1,0  ;

    // Calculez le dénominateur.   Si cette valeur est 0 alors nous n'avons
   // pas de cours d'interception.

    Métrique D  =   2   *   (  C  -  rVi  *  rVi  )  ;
    if   (  D  ====   0.0  )
    renvoie   -  1.0  ;

    // Calculer A et B

    Métrique B  =   2   *  rRange  ;
    Métrique A  =  B  *  rVi  ;

    // Calcule les deux racines

    Métrique Z  =  B  *   sqrt  (  C  )  ;
    Métrique R1  =   (  A  +  Z  )   /  D  ;
    Métrique R2  =   (  A  -  Z  )   /  D  ;

    // Si la première racine est positive alors renvoie-la

   si   (  R1  >   0.0  )
    return  R1  ;

    // Sinon, nous renvoyons la deuxième racine, qui peut être
   // ou non positive

   return  R2  ;
    }

```

### Un peu d'histoire sur (objCommunicate)

La vérité est que (objCommunicate) n'est probablement pas la bonne façon d'implémenter les autons.

Un peu d'histoire:

Comme vous le savez, toutes les IA des navires (quel que soit le contrôleur) honorent une liste séquentielle de commandes. Exemple:

Code:

… (shpOrder theShip 'attaquer la cible) (shpCommandez la porte du navire) …

L'extrait de code ci-dessus ordonne à un vaisseau d'attaquer d'abord la cible et, une fois la cible détruite, de sortir. Idéalement, ce que j'aurais dû faire, c'est utiliser ce mécanisme pour les autos. Par exemple, dans le code <Communications>, lorsque vous ordonnez à un auto d'attaquer, le code doit simplement appeler quelque chose comme :

Code:

(shpOrder theAuton 'attaquer theTarget)

Malheureusement, l’un des ordres auxquels obéit un navire est l’ordre d’escorte :

Code:

(shpCommandez le gPlayerShip d'escorte automatique)

Ainsi, lorsqu'un auto vous suit partout, il est au milieu de l'ordre d'escorte. Si vous lui donnez un autre ordre, il n'obéira pas à l'ordre jusqu'à ce que l'ordre d'escorte soit terminé (ce qu'il ne fera jamais).

Une solution possible consiste à annuler l’ordre d’escorte avant de donner l’ordre d’attaque. Malheureusement, le problème est que l'ordre d'escorte est le seul moyen de savoir que l'auto suit le joueur. Si nous annulons l'ordre d'escorte, nous ne saurons pas si l'auto doit suivre le joueur (par exemple, si le joueur entre dans une porte des étoiles).

Quoi qu'il en soit, pour surmonter ces problèmes, j'ai créé un contrôleur spécial pour implémenter l'auto. L'auto est toujours en train d'exécuter l'ordre d'escorte. Mais il peut modifier son comportement en fonction des messages du joueur. J'ai donc ajouté (objCommunicate) pour dire à l'auto qu'il devait attaquer.

Je pense que c'était une erreur. Au lieu de cela, j'aurais dû ajouter une variable distincte sur un navire qui indique qu'il escorte un autre navire. Ensuite, nous pourrions utiliser la machinerie d'ordre standard pour commander les autons et les ailiers.

### Voyage FTL en transcendance

Dans cette période (2400), les humains n'ont PAS la technologie pour quoi que ce soit FTL. Les portes des étoiles (et le moteur de saut extraterrestre) sont tout ce qu'ils ont (et ils ne savent pas comment cela fonctionne). Toutes les communications interstellaires se font via des vaisseaux messagers passant par les portes des étoiles.

Les races extraterrestres de la galaxie (par exemple, Iocrym) disposent de la technologie FTL, mais même cela n'est pas instantané (par exemple, il faut un temps non nul pour traverser une porte des étoiles – temps proportionnel à la distance). Les communications fonctionnent de la même manière : FLT mais pas instantanées.

Domina et Oracus ont une communication instantanée, mais seulement lorsqu'ils communiquent avec un être sensible.

### Calcul du score en jeu

```
int  CShipClass  ::  ComputeScore   (  const  CDeviceDescList  &  Devices  ,
                        int  iArmorLevel  ,
                        int  iPrimaryWeapon  ,
                        int  iSpeed  ​​,
                        int  iThrust  ,
                        int  iManeuver  ,
                         bool bPrimaryIsLauncher  )

 // ComputeScore
 //
 // Calcule le score de la classe en fonction de l'équipement

    {
    int  i  ;
     int  iSpécial  =   0  ;
     int  iExceptionnel  =   0  ;
     int  iDrawback  =   0  ;
     int  iStdLevel  =  iArmorLevel  ;
     int  iWeaponLevel  =   (  iPrimaryWeapon  ====   -  1   ?   0   :  ComputeDeviceLevel  (  Devices.  GetDeviceDesc  (  iPrimaryWeapon  )  )  )  ;

     // Si notre arme est meilleure que notre armure alors ajustez le niveau
    // en fonction de la différence.

     if   (  iWeaponLevel  >  iArmorLevel  )
       {
       switch   (  iWeaponLevel  -  iArmorLevel  )
          {
          cas   1  :
              iStdLevel  =  iWeaponLevel  ;
              iContrainte  ++ ;
              pause  ;

           cas   3  :
              iStdLevel  =  iWeaponLevel  -   2  ;
              iSpécial  +=   2  ;
              pause  ;

           par défaut  :
              iStdLevel  =   (  iWeaponLevel  +  iArmorLevel  )   /   2  ;
           }
       }

    // Si notre meilleure arme est 2 niveaux ou plus en dessous de notre
    niveau // standard, alors prenez les inconvénients de manière exponentielle.

     si   (  iStdLevel  >  iWeaponLevel  +   1  )
        iRetour  +=  min (  16  ,   (  1   <<   (  iStdLevel  -   (  iWeaponLevel  +   2  )  )  )  )  ;
     sinon   si   (  iStdLevel  >  iWeaponLevel  )
        iContrainte  ++ ;

     // Si toutes les statistiques de mouvement sont élevées, cela compte comme
    // une capacité exceptionnelle

    if   (  iSpeed  ​​====  enumHigh  &&  iThrust  ====  enumHigh  &&  iManeuver  ====  enumHigh  )
        iExceptionnel  ++ ;

     // Sinon, traitez-les comme des capacités spéciales ou des inconvénients

    else
       {
       if   (  iSpeed  ​​====  enumLow  )
           iContrainte  ++ ;
        sinon   si   (  iSpeed  ​​====  enumHigh  )
           iSpécial  ++ ;

        si   (  iThrust  ====  enumLow  )
           iContrainte  ++ ;
        sinon   si   (  iThrust  ====  enumHigh  )
           iSpécial  ++ ;

        if   (  iManeuver  ====  enumLow  )
           iContrainte  ++ ;
        sinon   si   (  iManeuver  ====  enumHigh  )
           iSpécial  ++ ;
        }

    // 1 segment d'armure est un inconvénient

    int  iArmorSections  =  GetHullSectionCount  (  )  ;
     si   (  iArmorSections  <=   1  )
        iContrainte  ++ ;

     // 2-3 segments d'armure sont normaux

    sinon   if   (  iArmorSections  <   4  )
       ;

     // 4 segments d'armure ou plus sont spéciaux

    sinon   si   (  iArmorSections  <   8   )
        iSpécial  ++ ;
     sinon   si   (  iArmorSections  <   16  )
        iSpécial  +=   2  ;
     sinon   si   (  iArmorSections  <   32  )
        iSpécial  +=   3  ;
     autre  si   (  iArmorSections  <   64  )
        iSpécial  +=   4  ;
     autre
        iSpécial  +=   5  ;

     // Récupère tous les appareils

     bool bDirectionalBonus  =   faux  ;
     bool bGoodSecondary  =   faux  ;
     int  iDirectionalBonus  =   0  ;
     pour   (  i  =   0  ;  i  <  Devices.  GetCount  (  )  ;  i  ++  )
       {
       const  SDeviceDesc  &  Dev  =  Devices.   GetDeviceDesc  (  je  )  ;
        CDeviceClass  *  pDevice  =  Dev.   Article  .   GetType  (  )  ->  GetDeviceClass  (  )  ;
        int  iDeviceLevel  =  ComputeDeviceLevel  (  Dev  )  ;

       de périphériques spécifiques

        // Changement   (  pDevice  ->  GetCategory  (  )  )
          {
             {
             int  iWeaponAdj  =   (  iDeviceLevel  -  iStdLevel  )  ;

              // S'il s'agit d'une arme secondaire, ajoutez-la au score

             if   (  i  !=  iPrimaryWeapon  )
                {
                // Calculez tout bonus potentiel en fonction du niveau de l'arme
                // par rapport au niveau de base

                 iSpecial  +=  max  (  iWeaponAdj  +   3  ,   0  )  ;
                 }

             // Calculer l'arc de feu

             int  iFireArc  =   (  Dev.  bOmnidirectionnel   ?   360   :  AngleRange  (  Dev.  iMinFireArc  ,  Dev.  iMaxFireArc  )  )  ;

              // Ajustement pour le montage sur tourelle

              iDirectionalBonus  +=   (  max  (  iWeaponAdj  +   3  ,   0  )   *  iFireArc  )  ;
              pause  ;
              }

          case  itemcatReactor  :
             // Les réacteurs ne comptent pas comme des améliorations
            pause  ;

           default  :
             {
             // Les autres appareils ont des capacités spéciales en fonction du niveau

             if   (  iDeviceLevel  >  iStdLevel  +  1  )
                 iExceptionnel  ++ ;
              sinon   si   (  iDeviceLevel  >  iStdLevel  )
                 iSpécial  +=   4  ;
              sinon   si   (  iDeviceLevel  >=  iStdLevel  -  1  )
                 iSpécial  +=   2  ;
              autre
                 iSpécial  ++ ;
              }
          }
       }

    // Si nous n'avons pas d'armes alors nous avons quelques inconvénients

    if   (  iPrimaryWeapon  ====   -  1  )
        iDésavantage  +=   3  ;

     // Ajout d'un bonus si l'arme est omnidirectionnelle

     iSpecial  +=   (  int  )  (  (  iDirectionalBonus  /   270.0  )   +   0.5  )  ;

     // Récupération des paramètres AI

    const  SAISettings  &  AI  =  GetAISettings  (  )  ;
     int  iFireAccuracyScore  ,  iFireRateScore  ;

     si   (  AI.  iFireAccuracy   >   97  )
        iFireAccuracyScore  =   5  ;
     sinon   si   (  AI.  iFireAccuracy   >=   93  )
        iFireAccuracyScore  =   4  ;
     sinon   si   (  AI.  iFireAccuracy   >=   90  )
        iFireAccuracyScore  =   3  ;
     sinon   si   (  AI.  iFireAccuracy   <   75  )
        iFireAccuracyScore  =   1  ;
     autre
        iFireAccuracyScore  =   2  ;

     si   (  AI.  iFireRateAdj   <=   10  )
        iFireRateScore  =   5  ;
     sinon   si   (  AI.  iFireRateAdj   <=   20  )
        iFireRateScore  =   4  ;
     sinon   si   (  AI.  iFireRateAdj   <=   30  )
        iFireRateScore =   3  ;
     sinon   si   (  AI.  iFireRateAdj   >=   60  )
        iFireRateScore  =   1  ;
     autre
        iFireRateScore  =   2  ;

     int  iFireControlScore  =  iFireRateScore  *  iFireAccuracyScore  ;
     si   (  iFireControlScore  >=   20  )
        iExceptionnel  ++ ;
     sinon   si   (  iFireControlScore  >   6  )
        iSpecial  +=   (  (  iFireControlScore  -   5  )   /   2  )  ;
     sinon   si   (  iFireControlScore  <   2  )
        iDésavantage  +=   4  ;
     sinon   si   (  iFireControlScore  <   4  )
        iDésavantage  +=   2  ;

     // Calculer le score final

     ScoreDesc  *  pBase  =   &  g_XP  [  iStdLevel  -  1  ]  ;
     int  iScore  =  pBase  ->  iBaseXP
           +  iSpecial  *  pBase  ->  iSpecialXP
           +  iExceptionnel  *  pBase  ->  iExceptionalXP
           +  iDrawback  *  pBase  ->  iDrawbackXP  ;

     retourner  iScore  ;
     }

```

### Tableau de scores

```
statique ScoreDesc g_XP[] =

    {
       // Score de base
       // Capacité spéciale
       // Capacité exceptionnelle
       // Inconvénient
       // Score de niveau

       { 20, 5, 20, 0, 50 }, // Je
       { 50, 10, 50, -5, 100 }, // II
       { 115, 15, 100, -10, 200 }, // III
       { 200, 20, 170, -20, 350 }, //IV
       { 340, 30, 260, -35, 600 }, //V
       { 500, 45, 370, -50, 900 }, //VI
       { 750, 60, 500, -65, 1400 }, // VII
       { 1050, 80, 650, -85, 1900 }, // VIII
       { 1450, 100, 820, -105, 2600 }, // IX
       { 1900, 125, 1010, -130, 3250 }, // X
       { 2400, 150, 1220, -155, 4200 }, // XI
       { 3000, 180, 1450, -185, 5500 }, // XII
       { 3600, 210, 1700, -215, 6750 }, // XIII
       { 4250, 245, 1970, -250, 8250 }, // XIV
       { 5 000, 280, 2 260, -285, 10 000 }, // XV
       { 6000, 320, 2570, -325, 11500 }, // XVI
       { 7000, 360, 2900, -365, 13250 }, // XVII
       { 8000, 405, 3250, -410, 15000 }, // XVIII
       {9000, 450, 3620, -455, 16750}, // XIX
       { 10 000, 500, 4 010, -505, 18 500 }, // XX
       { 11000, 550, 4420, -555, 20500 }, // XXI
       { 12000, 605, 4850, -610, 22500 }, // XXII
       { 13000, 660, 5300, -665, 25000 }, // XXIII
       { 14000, 720, 5770, -725, 26500 }, // XXIV
       { 15 000, 780, 6 260, -785, 30 000 }, // XXV
    } ;

```

### Raccourcis clavier pour Settings.xml

Si vous regardez Settings.xml, vous pouvez voir qu'il existe une table de mappage entre les clés et les commandes.

Vous pouvez mapper n’importe quelle touche à n’importe quelle commande (vous pouvez mapper plusieurs touches à la même commande, mais pas une seule touche à plusieurs commandes).

Actuellement, la liste complète des commandes prises en charge se trouve dans le fichier Settings.xml.

Pour spécifier une clé, vous pouvez toujours utiliser la représentation hexadécimale du code de clé virtuelle transmis dans wParam de WM\_KEYDOWN ( http://msdn.microsoft.com/en-us/library/ms646280 (VS.85).aspx)

Ou vous pouvez utiliser l'un des noms de clé suivants :

```
"Retour arrière"
 "Languette"
 "Clair"
 "Retour"
 "Changement"
 "Contrôle"
 "Menu"
 "Pause"
 "Capital"
 "Kana"
 "Junja"
 "Final"
 "Kanji"
 "S'échapper"
 "Convertir"
 "Non converti"
 "Accepter"
 "Changement de mode"
 "Espace"
 "Page précédente"
 "Bas de page"
 "Fin"
 "Maison"
 "Gauche"
 "En haut"
 "Droite"
 "Vers le bas"
 "Sélectionner"
 "Imprimer"
 "Exécuter"
 "Instantané"
 "Insérer"
 "Supprimer"
 "Aide"
 "0"
 "1"
 "2"
 "3"
 "4"
 "5"
 "6"
 "7"
 "8"
 "9"
 "UN"
 "B"
 "C"
 "D"
 "E"
 "F"
 "G"
 "H"
 "JE"
 "J"
 "K"
 "L"
 "M"
 "N"
 "Ô"
 "P"
 "Q"
 "R"
 "S"
 "T"
 "U"
 "V"
 "W"
 "X"
 "Y"
 "Z"
 "LWindows"
 "Windows"
 "Applications"
 "Dormir"
 "Pavé numérique0"
 "Pavé numérique 1"
 "Pavé numérique2"
 "Pavé numérique3"
 "Pavé numérique4"
 "Pavé numérique5"
 "Pavé numérique6"
 "Pavé numérique7"
 "Pavé numérique8"
 "Pavé numérique9"
 "Étoile du pavé numérique"
 "Pavé numériquePlus"
 "Séparateur du pavé numérique"
 "Pavé numériqueMoins"
 "Période du pavé numérique"
 "Pavé numériqueSlash"
 "F1"
 "F2"
 "F3"
 "F4"
 "F5"
 "F6"
 "F7"
 "F8"
 "F9"
 "F10"
 "F11"
 "F12"
 "F13"
 "F14"
 "F15"
 "F 16"
 "F17"
 "F18"
 "F19"
 "F20"
 "F21"
 "F22"
 "F23"
 "F24"
 "Verrouillage numérique"
 "Verrouillage du défilement"
 "FJ_Jisho"
 "FJ_Masshou"
 "FJ_Touroku"
 "FJ_Loya"
 "FJ_Roya"
 "Navigateur Retour"
 "Navigateur avant"
 "Actualisation du navigateur"
 "Arrêt du navigateur"
 "Recherche par navigateur"
 "Favoris du navigateur"
 "Accueil du navigateur"
 "VolumeMuet"
 "Baisser le volume"
 "Monter le son"
 "MédiaSuivant"
 "MédiasPrév"
 "MédiaStop"
 "MédiaPlay"
 "LancementMail"
 "LancerMediaSelect"
 "LancementApp1"
 "LancementApp2"
 "Point-virgule"
 "Égal"
 "Virgule"
 "Moins"
 "Période"
 "Sabrer"

```

Remarque : La plupart des noms de touches ci-dessus font référence à des claviers non anglais, ils peuvent donc ne pas fonctionner pour vous. Vous devrez faire quelques expériences.

### Topologie

Voici une mise à jour rapide de mon travail sur les topologies système :

Comme vous le savez, j'ai travaillé sur la partie II, qui nécessitera une manière plus sophistiquée de générer une topologie système. Je veux créer quelque chose de plus aléatoire, au lieu de la topologie linéaire de la première partie.

Mais pour comprendre les changements à venir, il sera utile de savoir exactement comment fonctionnent les topologies des systèmes aujourd’hui. Voici une introduction :

Au début du jeu, nous générons la topologie complète du système comme suit :

1. Rassemblez tous les éléments <SystemTopology>. Transcendence.xml en a une (la topologie principale). Huari.xml en a un autre (pour Huaramarca). Et n’importe quelle extension peut ajouter la sienne. [Il n'existe actuellement aucun moyen de remplacer un élément <SystemTopology> d'une extension.]

2. Chaque élément <SystemTopology> possède un ou plusieurs « nœuds racine » (un nœud marqué avec l'attribut rootNode="true".

3. Nous commençons par le premier nœud racine que nous trouvons et créons. [Remarque : à ce stade du jeu, tout ce que nous faisons est de créer des nœuds topologiques. Nous ne créons pas le système stellaire réel tant que le joueur n'entre pas réellement dans le système.]

4. Ensuite, nous examinons la liste des portes des étoiles menant hors du nœud. [La liste des portes des étoiles peut être une table aléatoire, auquel cas nous choisissons des portes des étoiles aléatoires.]

5. Pour chaque porte des étoiles, nous regardons à quel nœud elle mène. Si cela mène à un nœud que nous avons déjà créé, alors nous connectons la porte et continuons. Mais si cela mène à un nouveau nœud, alors nous récurons : nous créons le nouveau nœud puis regardons sa table stargate (et ainsi de suite).

6. Notez que l'élément stargate pointe parfois vers un nœud appelé « [Prev] ». Cela signifie simplement que la porte des étoiles se reconnecte au nœud que nous traitons pour atteindre ce nœud. [Cela est nécessaire pour que les portes des étoiles soient bidirectionnelles – et en fait, dans les versions futures, cela ne sera pas nécessaire : les portes des étoiles seront bidirectionnelles par défaut.]

7. Une fois tous les nœuds racines traités, nous appelons <OnGlobalTopologyCreated> pour tous les types. À ce stade (et seulement à ce stade), le code peut manipuler la topologie (généralement en ajoutant de nouvelles portes des étoiles, comme dans le cas de Huaramarca).

À partir de l’algorithme ci-dessus, vous pouvez voir quelques implications :

je. Seuls les nœuds racine sont garantis d'être créés. Si un nœud ne se connecte pas (finalement) à un nœud racine, il ne sera pas créé. [Par exemple, vous remarquez qu'aucun nœud ne mène à Huaramarca – nous nous connectons de manière aléatoire à Huaramarca plus tard dans le code (en utilisant sysAddStargateTopology). Mais si Huaramarca n’était pas un nœud racine, il n’aurait jamais été créé et sysAddStargateTopology échouerait.]

ii. Ce qui précède signifie également que les nœuds ignorés de manière aléatoire ne sont jamais créés. Vous ne pouvez pas les atteindre dans le jeu, même via du code. Par exemple, le nœud C4A est parfois (50 %) ignoré.

iii. La topologie est plus ou moins définie après <OnGlobalTopologyCreated>. Il n’y a aucun moyen de changer la topologie après cela (et je n’envisage aucun moyen – nous pouvons toujours activer/désactiver les portes des étoiles plus tard).

Compte tenu de tout cela, il est désormais un peu plus facile de parler des changements et améliorations à venir :

Carte Galactique Bien qu'aucune interface utilisateur ne soit encore implémentée, je prépare une carte galactique qui montre la position de chaque système stellaire sur une carte. Ainsi, chaque nœud aura désormais une coordonnée X,Y. Lorsque vous concevez vos topologies, assurez-vous d'en tenir compte.

Fragments réutilisables Supposons que vous souhaitiez que votre topologie ressemble à ceci :

```
A1--B1--B2
 A2--B5--B6
     B7--B8

```

Notez que le cluster B1-B4 est identique au cluster B5-B8. Ce serait dommage de devoir spécifier deux fois la même topologie.

L'élément <Fragment> vous permet de définir une sous-topologie nommée réutilisable. Lorsqu'une porte des étoiles mène à un fragment, nous générons tous les nœuds du fragment (même si le fragment a déjà été utilisé).

Normalement, les nœuds spécifient une position x,y absolue pour l'endroit où ils apparaissent sur la carte. Mais pour les fragments, la position x,y est relative au nœud qui y mène.

Avec des fragments, vous pouvez créer une topologie modulaire. Par exemple, supposons que vous ayez deux fragments d’apparence différente :

```
--B1--B2
   B3--B4

 et

 --C1--C2--C3--C4

```

Vous pouvez désormais faire en sorte que les nœuds A1 et A2 mènent aléatoirement soit au fragment B1, soit au fragment C1. Bien sûr, à mesure que vous augmentez le nombre de types de fragments (ou que les fragments mènent à des fragments), vous pouvez augmenter le caractère aléatoire du réseau.

Affectation du système à deux passes Aujourd'hui, chacun des nœuds précise le type de système dont il disposera. Chaque nœud peut avoir une table aléatoire de types de systèmes, c'est ainsi que parfois un système est un système de nébuleuse tandis que d'autres fois il s'agit d'un système d'astéroïdes.

Mais la sélection du système a lieu au moment de la création du nœud (avant la création de la topologie entière). Cela rend difficile le placement d’un système spécial dans une partie spécifique de la topologie.

Les versions futures ajouteront une deuxième passe qui vous permettra de modifier les types de système dans des nœuds spécifiques.

Une topologie peut avoir un ou plusieurs éléments <TopologyProcessor>, qui vous permettront de sélectionner un ensemble de nœuds (selon certains types de critères) et de leur attribuer des types de systèmes.

Par exemple, vous pouvez utiliser un <TopologyProcessor> pour choisir un nœud aléatoire doté d'au moins trois portes des étoiles et en faire un type de système spécial. Ou vous pouvez choisir 20 nœuds aléatoires dans la topologie et en faire des systèmes de nébuleuses (ou des systèmes binaires, ou autre).

Vous pouvez également utiliser les éléments <TopologyProcessor> pour appliquer des attributs à des nœuds spécifiques (attributs que vous pourrez interroger ultérieurement lorsque le joueur entre dans un système).

Partie II Galaxie Mes plans pour la deuxième partie sont d'utiliser les fonctionnalités ci-dessus pour créer une topologie semi-aléatoire qui s'étend à toute la galaxie. [Dont la topologie actuelle de Human Space ne sera qu'une petite partie.]

En utilisant les deux phases ci-dessus, la création de la galaxie impliquera :

1. Générer une topologie stargate. La topologie suivra généralement deux bras spiraux majeurs, mais chaque bras aura divers fragments aléatoires qui ressortiront. [Tout cela est à déterminer – jusqu'à ce que je le teste, je ne saurai pas à quel point cela fonctionnera bien.]

2. Attribuer des types de système de manière aléatoire à chaque nœud. Avec les éléments <TopologyProcessor>, je peux découper la galaxie en régions aléatoires. Chaque région aura un environnement particulier (nébuleuse, riche en métaux, pauvre en eau, etc.). Différents environnements auront différents types de systèmes, et les rencontres, souverains, etc. pourront ensuite être ajustés en fonction de l'environnement particulier.

J'espère que cette introduction nous aidera à voir où nous allons, à la fois en termes de partie II et de fonctionnalités de modding à venir.

Les fragments réutilisables et l'affectation du système en deux passes devraient être effectués à temps pour la version 1.04.

### Génération de système

Extrait de ce message du forum : http://neurohack.com/transcendence/forums/viewtopic.php?p=36513#p36513

Il existe deux types de balises (éléments XML) dans une définition de système. Il existe des balises « création » et des balises « localisation ». Une balise de création est quelque chose qui crée un objet dans le système. Par exemple:

```
   <   Type  de poste =  "..."  />

```

Cela crée une station du type donné. Mais où le crée-t-il ? Il le crée partout où la balise parent « location » le dit. Une balise d'emplacement est un élément qui spécifie un emplacement particulier dans le système.

La balise la plus externe est une balise de localisation :

```
<SystemGroup  >

    <Station   type  =  "..."  />
 </SystemGroup  >

```

Dans le code ci-dessus, puisque la balise Station se trouve à l'intérieur de la balise SystemGroup, la station est créée à l'emplacement de SystemGroup, qui est 0,0.

En général, le but d'une balise d'emplacement est de se déplacer de l'emplacement de son parent vers un nouvel emplacement.

La balise Orbitales est une balise de localisation qui se décale d'un centre vers un point sur une orbite :

```
<Groupe Système  >
    orbitales   < Distance  =  "10"   angle  =  "90"  >
       <   Type  de station =  "..."  />
    </Orbitales  >
 </SystemGroup  >

```

L'attribut « distance » est le rayon de l'orbite (sauf indication contraire, toutes les distances sont exprimées en secondes-lumière). L '«angle» est (sans surprise) l'angle autour de l'orbite (comme dans le trig standard, l'angle = 0 est le long de l'axe X positif). Dans cet exemple, un angle de 90 est droit.

N'oubliez pas que la balise Orbitals est relative à son parent. Il se trouve que son parent est le SystemGroup, donc l'emplacement parent est 0,0. Mais si les orbitales se trouvaient à un endroit différent, ce serait relatif à cela.

Par exemple:

```
<Groupe Système  >
    orbitales   < Distance  =  "10"   angle  =  "90"  >
       orbitales   < Distance  =  "5"   angle  =  "0"  >
          <   Type  de station =  "..."  />
       </Orbitales  >
    </Orbitales  >
 </ Groupe système  >

```

Notez qu'il existe deux définitions orbitales. Le plus extérieur se décale de son parent (0,0) jusqu'à un point de 10 secondes-lumière dans la direction de 90 degrés (droit vers le haut). Ensuite, les orbitales internes se décalent de leur parent de 5 secondes-lumière dans la direction de 0 degré (vers la droite). La station sera donc placée 10 secondes-lumière en haut et 5 secondes-lumière à droite de 0,0.

Orbitals possède de nombreux attributs supplémentaires pour définir son comportement, mais en fin de compte, il s'agit avant tout de positionner les objets sur une orbite.

L'attribut « count » crée un multiple de tout élément orbital que contient. Si vous avez spécifié un emplacement absolu (comme ci-dessus), cela créera simplement plusieurs stations au même endroit. Mais vous pouvez spécifier un emplacement aléatoire. En ajoutant le mot-clé « aléatoire » comme angle, vous créez une station avec un angle aléatoire sur l'orbite. Lorsque plusieurs stations sont créées (avec l'attribut count), chaque station sera placée sous un angle différent (aléatoire).

Il existe d'autres types de balises qui compensent l'emplacement :

Frères et sœurs : cette balise se déplace le long de l'orbite de son parent. Vous pouvez utiliser les attributs arcInc et radiusInc pour vous déplacer le long de l'orbite du parent. Ou vous pouvez choisir un angle aléatoire sur l'orbite du parent.

Cheval de Troie et AntiTrojan et juste des cas particuliers de la balise Siblings. Ils se déplacent toujours de 60 degrés vers l'avant ou de 60 degrés vers l'arrière sur l'orbite de leurs parents. En pratique, ils sont identiques aux frères et sœurs avec angleInc="60" et angleInc="-60" [ BTW  : arcInc se déplace le long de l'orbite en secondes-lumière. angleInc se déplace en degrés.]

Décalage : cette balise se décale en coordonnées cartésiennes (x, y) au lieu de coordonnées orbitales.

Il existe deux autres balises spéciales qui nécessitent une explication. Le premier est la recherche.

La balise Lookup est simplement un moyen de partager des parties de la définition du système. C'est comme une macro.

```
<SystemPartTable   unid  =  "..."  >
    <MyCoolStuff  >
       <   Distance  orbitales =  "10"   angle  =  "90"  >
          <   Type  de station =  "..."  />
       </Orbitales  >
    </MyCoolStuff  >
 </SystemPartTable  >

 < SystemType   unid  =  "..."  >
    <SystemGroup  >
       <Lookup   table  =  "MyCoolStuff"  />
    </SystemGroup  >
 </SystemType  >

```

Lorsque ce qui précède est traité, l'élément <Lookup…> sera remplacé par le contenu défini dans SystemPartTable ; le résultat est:

```
<SystemType   unid  =  "..."  >
    <SystemGroup  >
       <   Distance  orbitales =  "10"   angle  =  "90"  >
          <   Type  de station =  "..."  />
       </Orbitales  >
    </SystemGroup  >
 </SystemType  >

```

L’autre balise intéressante est Label. Une étiquette est comme un emplacement réservé qui est ensuite rempli avec quelque chose.

Lorsque le système place des planètes, il positionne également des étiquettes autour des planètes. Par exemple:

```
<Groupe  >
    <   Type  de station =  "&stIcePlanet;"    showOrbit  =  "true"  />

    <   Distance  des orbitales =  "2d6+10"   angle  =  "aléatoire"  >
       <   Attributs  de l'étiquette =  "planète, planétaire, gel"  />
    </Orbitales  >
 </Groupe  >

```

Ce qui précède crée une planète de glace avec une étiquette en orbite autour d'elle à 2d6+10 secondes-lumière. Qu'y a-t-il sur l'étiquette ? Rien pour le moment. Plus tard, il existe d'autres balises qui « remplissent » les étiquettes avec des stations :

```
<RandomLocation   locationCriteria  =  "+planète"  >
    <   Type  de station =  "..."  />
 </RandomLocation  >

```

La balise RandomLocation parcourt toutes les étiquettes libres et en choisit une au hasard. L'attribut locationCriteria est un moyen de préférer des étiquettes particulières (+ planète signifie préférer les étiquettes avec l'attribut « planète »).

Une fois que nous avons choisi une étiquette, nous l'utilisons comme emplacement pour tout ce qui se trouve à l'intérieur de la balise RandomLocation. Dans ce cas, nous créons une station à cet endroit.

Mais que se passe-t-il si vous souhaitez créer une station aléatoire ? Ensuite, vous pouvez utiliser :

```
<RandomLocation   locationCriteria  =  "+planète"  >
    <RandomStation   stationCriteria  =  "*friendly"  />
 </RandomLocation  >

```

La balise RandomStation choisit une station aléatoire qui correspond aux stationCriteria et aux attributs de l'emplacement.

L'image complète ressemble à ceci :

1. Lorsque les planètes sont générées, un ensemble d'étiquettes sont créées. Chaque étiquette possède un ensemble d'attributs décrivant quelque chose sur l'emplacement de l'étiquette (par exemple, une étiquette aura l'attribut « planète » si elle se trouve autour d'une planète.)

2. La balise RandomLocation sélectionne une étiquette aléatoire. Il utilise le locationCriteria spécifié dans la balise RandomLocation pour choisir une étiquette. Dans l’exemple ci-dessus, nous préférons les étiquettes qui ont l’attribut « planète ».

3. Disons que nous choisissons une étiquette aléatoire avec les attributs suivants : « planète, planétaire, gel ». Ces attributs sont désormais associés (temporairement) à l'emplacement de l'étiquette.

4. Maintenant que nous avons choisi une étiquette et un emplacement, nous traitons la balise RandomStation. Nous parcourons chaque StationType et attribuons à chaque station une probabilité de se trouver à cet emplacement. Nous calculons la probabilité comme suit :

un. Nous comparons les stationCriteria aux attributs de la station. Si la station ne correspond pas, nous l'excluons. Sinon, nous ajustons la probabilité en conséquence. Dans l’exemple ci-dessus, nous nous assurons que la station possède l’attribut « convivial ».

b. Ensuite, nous vérifions l'attribut levelFrequency sur StationType et comparons avec le niveau du système. (Toute station qui n'a pas de niveau de fréquence est considérée comme non aléatoire et est exclue).

c. Enfin, nous vérifions l'attribut locationCriteria sur StationType et le comparons aux attributs à l'emplacement de l'étiquette (la plupart des attributs proviennent de l'étiquette elle-même, mais nous prenons également en compte tous les attributs du système).

5. Une fois que nous avons calculé la probabilité de toutes les stations, nous tirons un nombre aléatoire et choisissons une station.

Il existe d'autres balises qui fonctionnent selon des principes similaires. La balise FillLocations est une version itérée de ce qui précède. Il parcourt toutes les étiquettes vides et sélectionne des stations aléatoires pour les remplir.

### Sur les chaînes de version

Ceci est une note rapide pour clarifier la façon dont je gère les numéros de version pour les extensions.

Il n'y a en réalité que deux numéros de version d'extension valides :

« 1.0 » : Ce numéro de version indique que votre extension fonctionne avec 1.0 ou 1.01.

« 1.1 » : ce numéro de version indique que votre extension nécessite une fonctionnalité qui sera publiée pour la première fois après la 1.01 et jusqu'à la 1.1.

Ma philosophie de base est que toutes les versions qui ne figurent pas sur le site principal sont des versions bêta, ce qui signifie que je ne peux pas garantir que les API resteront stables pour la version finale.

La prochaine version qui apparaîtra sur le site principal est la 1.1. D'ici là, toutes les nouvelles fonctionnalités apparues dans la version 1.02-1.05+ seront officielles et je prendrai en charge la rétrocompatibilité sur celles des versions futures (1.2 et au-delà).

### Codes de commande

Une liste de codes de commande pour ces vagues instructions de débogage embêtantes.

1 = « garde »

2 = « quai »

3 = « attaque »

4 = "attendre"

5 = « porte »

6 = « porte sur menace »

7 = « gateOnStationDestroyed »

8 = « patrouille »

9 = « escorte »

10 = « récupérer »

11 = « suivrePlayerThroughGate »

12 = « attaqueNearestEnemy »

13 = « TradeRoute »

14 = « errer »

15 = « butin »

16 = « tenir »

17 = « à moi »

18 = « attendre le joueur »

19 = « attaqueJoueurOnRetour »

20 = « suivre »

21 = « chemin de navigation »

22 = "aller à"

23 = « attendre la cible »

24 = "attendre l'ennemi"

25 = « bombarder »

26 = « approche »

27 = "viser"

28 = « orbite »

29 = « maintenir le cours »

30 = « tourner vers »

31 = « attaqueHold »

### Sur les réacteurs

Cette information est tirée de ce post .

1. Chaque élément combustible comporte un certain nombre d’« unités combustibles ». Par exemple, un crayon combustible à l’hélium contient 2 500 unités combustibles. [Regardez l'attribut data= sur un type d'élément pour déterminer le nombre d'unités de carburant.]

2. Un réacteur avec une efficacité de 100 % consomme 1 unité de combustible pour générer 1,5 MW de puissance pendant 1 tick. Exemple : Une arme tire et consomme 15 MW. À chaque tick, il consommera 10 unités de carburant (15 / 1,5 = 10). Les réacteurs améliorés ont un rendement supérieur à 100 % et peuvent générer plus d'énergie avec une unité de combustible. Les réacteurs endommagés sont le contraire.

3. Une arme d’une puissance nominale de 10 MW consomme 10 MW uniquement lors du tir. Si l'arme ne tire pas, elle tire 1/10 de ce montant (sauf indication contraire dans ralentiPowerUse).

J'espère que cela pourra aider!

En passant, toute cette conception m’a aidé à en apprendre un peu plus sur la puissance. Maintenant, je connais la différence entre un radiateur qui consomme 1 kilowatt et une facture envoyée par la poste indiquant que j'ai utilisé 10 kilowattheures. Un kilowatt est une mesure de la vitesse à laquelle l’énergie circule ; un kilowattheure est une mesure de la quantité d’énergie que j’ai consommée.

De la même manière, la consommation électrique des appareils est mesurée en watts (mégawatts), tandis que la consommation, exprimée en unités de combustible, peut être convertie en mégawattheures avec une formule simple :

mégawattheures = (1,5 \* unités de combustible) / (ticks par heure)

Puisqu’il y a 1 800 ticks par heure (en temps de jeu) et qu’un seul crayon de combustible à l’hélium contient 2 500 unités de combustible, nous pouvons convertir comme suit :

mégawattheures = 1,5 \* 2 500 / 1 800 = ~ 2,08

Autrement dit, un crayon combustible à l’hélium a une puissance de 2,08 mégawattheures.

Et au risque de s’égarer encore plus, notons que ces chiffres sous-estiment largement la puissance de l’énergie nucléaire. Par exemple, un baril de pétrole pèse 139 kg et a une puissance d’environ 1,6 mégawattheure, soit à peu près la même densité énergétique qu’un barreau de combustible à l’hélium. En revanche, 100 kg d’uranium utilisés dans un réacteur à fission produisent environ 2,2 millions de mégawattheures d’énergie.

Je suppose que j'aurais dû faire ces calculs lorsque j'ai trouvé les valeurs pour la première fois.

Pour être honnête, un crayon combustible à l’hélium contient tout le blindage et la structure conçus pour contenir le carburant – le carburant lui-même pèse probablement bien moins de 100 kg. Pour atteindre la même densité énergétique que l’uranium, le combustible réel contenu dans un barreau de combustible à l’hélium ne devrait pas peser plus de 0,1 gramme.

ps : Faites-moi savoir si j'ai raté le calcul.

### Couleur laser

Cette information est tirée de ce post .

Oui, c'est intentionnel, mais avec certaines limites.

En général, je voulais que chaque type de dégâts ait un aspect unique :

Lasers : rouge, vert ou violet (par ordre croissant de puissance)

Cinétique : gris

Particule : verte, avec une texture particulaire

Explosion : flamme

Ion : cyan

Thermo : flamme/orange

Positron : jaune, à texture particulaire

Plasma : jaune

Antimatière : jaune

Nano : divers (gris/vert/etc) mais avec une texture complexe

Graviton : violet/violet

Singularité : noir/blanc/violet

Acide foncé : sarcelle

Dark Steel : gris-vert

Éclair sombre : bleu

Feu sombre : rouge

Pour les lasers, il faudrait probablement éviter le jaune et le bleu (pour éviter toute confusion avec positon/antimatière et ion). Si vous souhaitez créer de nouveaux styles laser, je vous recommande de mélanger plus de blanc (pour rendre le faisceau plus blanc). Par exemple, j'imagine qu'un laser à rayons gamma pourrait être blanc avec des franges violet/violet.

### Planètes pour l'API version 14

Tiré d' ici

La génération utilise des macros et des étiquettes système. Par exemple, si vous regardez StarSystems.xml, vous verrez une définition pour <AsteroidBeltSystem>. Il s'agit d'une macro utilisée pour créer un système de ceinture d'astéroïdes. La macro définit (au hasard) la position de plusieurs planètes. Sous <Orbitals…> vous pouvez voir une référence à une macro « DesertPrimary ».

Si vous regardez la définition de la macro DesertPrimary (dans Worlds.xml), vous verrez qu'elle place deux choses : une planète (stDesertTerrestrialSizeH) et une étiquette.

Une étiquette est un point dans l'espace pouvant accueillir une station (amie ou ennemie). Cette étiquette particulière possède certains attributs, notamment l'attribut « planète », ce qui signifie que l'étiquette se trouve autour d'une planète. Lorsque le système est créé, nous pouvons placer ici une station au hasard, en préférant les stations qui souhaitent se trouver autour d'une planète.

Dans les versions précédentes, l'objet planète lui-même (stDesertTerrestrial…) aurait AUSSI un attribut « planète ». Cela s'est avéré utile au cas où vous souhaiteriez ultérieurement énumérer toutes les planètes d'un système. Mais il s’est avéré que certains objets étaient utilisés à la fois comme planètes et comme lunes, je n’ai donc pas pu attribuer l’attribut à l’objet lui-même.

Au lieu de cela, j'utilise un attribut spécial +isPlanet:true; qui ne correspond que si l'objet est une vraie planète (en orbite autour d'une étoile).

Si vous souhaitez énumérer les objets dans le système, voici quelques conseils :

1. Vous pouvez utiliser l’attribut spécial +scale:world; pour énumérer toutes les planètes, astéroïdes et lunes du système stellaire. +échelle:étoile; correspond à toutes les étoiles.

2. Tous les mondes (définis dans le noyau) ont une taille explicite (en kilomètres). Ils sont répartis en classes de taille :

```
Astéroïde < 1 000 km
                   tailleA Tiny ~ 10 km
                   tailleB Petit ~ 50 km
                   tailleC Moyen ~ 100 km
                   tailleD Large ~ 500 km

                         Planétoïde ~ 2 500 km
                   tailleE Petit ~ 1 000 km
                   tailleF Medium ~ 2 000 km
                   tailleG Large ~ 4 000 km

                         Terrestre ~ 10 000 km
                   tailleH Petit ~ 5 000 km
                   tailleI Moyenne ~ 10 000 km
                   tailleJ Large ~ 20 000 km

                         Géante gazeuse ~ 100 000 km
                   tailleK Petit ~ 50 000 km
                   tailleL Medium ~ 100 000 km
                   tailleM Large ~ 200 000 km

```

3. Vous pouvez faire correspondre une classe de taille spécifique avec +sizeClass:H; (par exemple) pour correspondre à tous les mondes sizeH.

4. Vous pouvez utiliser des attributs normaux pour faire correspondre des ensembles de classes :

+astéroïde ; Correspond à tous les mondes de taille A, B, C, D +planétoïde; Convient à tous les mondes de taille E, F, G +terrestre ; Convient à tous les mondes de taille H, I, J +gasGiant; Convient à tous les mondes de taille K, L, M.

J'espère que cela pourra aider!

### Sur les articles

Tiré d' ici

La chose la plus importante à retenir à propos des objets (armures, appareils, etc.) est que vous ne pouvez les manipuler que par valeur et non par référence. Qu'est-ce que cela signifie? Voici un tutoriel rapide :

Lorsque vous appelez une fonction comme :

(objAddItem gPlayerShip (itmcreate 0xD518FF28 4) 4)

vous ajoutez un seul enregistrement d'élément au vaisseau du joueur. L'inventaire du vaisseau du joueur ressemblera à ceci :

Inventaire des vaisseaux des joueurs : [UNID : 0xD518FF28 nombre : 4 indicateurs : aucun]

Tout d'abord, notez que même si vous avez créé 4 segments d'armure, il n'y a qu'un seul enregistrement. Le disque lui-même compte 4, c'est ainsi que nous effectuons le suivi. Ceci est fait pour plus d’efficacité. Sinon, si vous récupérez 1 000 cartouches, nous aurions 1 000 disques, ce qui coûte trop cher.

Ensuite, remarquez qu’il n’y a pas de champ ID ! Le fait qu'il n'y ait pas de champ ID signifie que vous ne pouvez pas faire référence à l'enregistrement par ID. Alors, comment faites-vous référence aux segments d’armure ? Comment les installer par exemple ?

Vous devez les installer en décrivant exactement les éléments que vous souhaitez installer. Il faut s'y référer par valeur. Effectivement, vous devez faire quelque chose comme ceci :

(shpInstallArmor gPlayerShip « l'armure qui ressemble à : [UNID : 0xD518FF28 count:4 flags:none] »)

Bien sûr, ce qui précède ne fonctionnera pas, mais la fonction itmCreate est essentiellement un moyen de créer des enregistrements de cette forme. Donc les travaux suivants :

(shpInstallArmor gPlayerShip (itmCreate 0xD518FF28 1) 0)

En effet, la sortie de itmCreate est une structure d'enregistrement. Sous les couvertures :

(itmCreate 0xD518FF28 1) → [UNID : 0xD518FF28 nombre : 1 indicateurs : aucun]

Après cela, vous vous retrouverez avec un inventaire qui ressemble à ceci :

Inventaire des vaisseaux des joueurs : [UNID : 0xD518FF28 nombre : 3 indicateurs : aucun] [UNID : 0xD518FF28 nombre : 1 indicateurs : installé installé à : 0]

Notez que le fait d’installer une armure change la donne ! Étant donné que le dossier a changé, vous ne pouvez pas y faire référence par son nom d'origine. Par exemple, supposons que je veuille améliorer l'armure que je viens d'installer. Je pourrais naïvement essayer ceci :

(shpEnhanceItem gPlayerShip (itmCreate 0xD518FF28 1))

Quel segment d'armure serait amélioré ? Parce que l'armure installée a changé (car elle est installée), je ne peux plus utiliser le même code pour y faire référence. Je dois faire quelque chose comme :

(shpEnhanceItem gPlayerShip "l'armure qui ressemble à : [UNID : 0xD518FF28 count:1 flags:installed InstallAt:0]")

Malheureusement, itmCreate ne peut pas générer ce type d'enregistrement (il ne sait pas comment définir l'indicateur installé), vous ne pouvez donc pas l'utiliser. Au lieu de cela, vous devez trouver l’objet sur le vaisseau du joueur et l’utiliser. objGetItems renvoie une liste d'enregistrements d'éléments qui correspondent à un critère spécifique.

(objGetItems gPlayerShip « unid:0xD518FF28 ; ») → [UNID : 0xD518FF28 nombre : 3 indicateurs : aucun] [UNID : 0xD518FF28 nombre : 1 indicateurs : installé installé à : 0]

Étant donné que les deux enregistrements correspondent à l'UNID, objGetItems renvoie à la fois les enregistrements installés et désinstallés. Si je veux uniquement l'élément installé, j'ai besoin du drapeau « I » :

(objGetItems gPlayerShip "unid:0xD518FF28; I") → [UNID : 0xD518FF28 nombre : 1 indicateurs : installé installé à : 0]

Bien sûr, le résultat est toujours une liste, il me faudrait donc utiliser la syntaxe '@' pour obtenir le premier élément de la liste :

(shpEnhanceItem gPlayerShip (@ (objGetItems gPlayerShip "unid:0xD518FF28; I") 0))

objGetItems est un moyen de trouver l'enregistrement d'élément auquel vous souhaitez faire référence. Donc, avec ce (long) tutoriel terminé, nous pouvons parler de votre code.

Dans votre premier exemple, il y a un petit bug dans les critères de objGetItems. Votre code devrait ressembler à ceci :

```
(objadditem gplayership (itmcreate 0xD518FF28 4) 4)
 (shpinstallarmor gplayership (@ (objgetitems gplayership "unid:0xD518FF28; U") 0) 0)
 (shpinstallarmor gplayership (@ (objgetitems gplayership "unid:0xD518FF28; U") 0) 1)
 (shpinstallarmor gplayership (@ (objgetitems gplayership "unid:0xD518FF28; U") 0) 2)
 (shpinstallarmor gplayership (@ (objgetitems gplayership "unid:0xD518FF28; U") 0) 3)

```

Notez que le terme « unid :… » se termine par un point-virgule. Et le terme « U » n'a pas besoin d'un « ^ ».

Mais votre deuxième exemple fonctionne tout aussi bien car vous avez parfaitement décrit l’élément. La deuxième méthode poserait des problèmes si l'élément était amélioré, endommagé, installé ou si des données lui étaient associées. Dans ces cas, vous devez utiliser la syntaxe objGetItems.

De plus, de nombreuses fonctions renvoient l'enregistrement de l'élément après modification. Par exemple, objSetItemData renvoie l'enregistrement d'élément nouvellement modifié et vous pouvez utiliser le résultat pour faire référence à l'élément lors des appels ultérieurs.

### Courbes de réglage du bouclier et du niveau

Courbes de réglage du bouclier et du niveau