La Bibliothèque de Neverwinter Nights
Aide et informations diverses sur Neverwinter Nights ainsi que D&D3.
La date/heure actuelle est 20/04/2024 00:11:40


  Page 1 sur 1 ¤

Voir le sujet précédent ¤ Voir le sujet suivant 
Auteur Message
Baldurien
L'homme qui chutait sur le macadam
Inscrit le: 12 Sep 2002
Messages: 14064
Localisation: Quadran Alpha
Répondre en citant
Posté le : 24/08/2003 22:11:38 Sujet du message : [Tutorial] Ma caméra et moi

Grosse nouveautée présentée avec The Which Wake, les fonctions "Camera" permettent de prendre le contrôle de la caméra du joueur et ainsi de faire des scénes d'introduction.

Neverwinter Nights : Shadows of Undrentide va plus loin dans la gestion des caméras car il inclut carrément des fonctions scécifiques, des nouvelles variables et des effets spécialements dédiés à la Caméra.

Ce topic a pour but de faire une sorte d'explication de ces fonctions, et de comment devenir un Réalisateur digne de ce nom à Neverwinter Nights (enfin, on va essayer).

Ce qu'il vous faut :

  • Neverwinter Nights : Shadows of Undrentide v1.31 : c'est ma version de jeu, donc je la conseille...
  • Du papier vierge si possible, où l'on puisse écrire des coordonnées
  • Un stylo


La première chose risque dure à avoir car chez Atari on est des pros pour ce qui est de traduire et de sortir les jeux dans des temps raisonnables par rapport à la version original. Néanmoins, certaines des fonctions présentées existent déjà dans Neverwinter Nights avec le patch 1.29.

Les fonctions :

void DelayCommand( float fSeconds, action aActionToDelay );

C'est la fonction la plus utile car elle nous permet de faire une pile de commandes en attente. Cela correspond à un Timer. Cette fonction va être plus que prédominante dans votre script : oui, si vous vous amusez à foutre toutes les commandes Caméra en même temps, hé bien vous aurez un truc indigeste pour l'utilisateur.

void SetCutsceneMode( object oCreature, int nInCutscene=TRUE )

Deuxième fonction très utile car elle va mettre le jeu en mode "CutScene" pour la créature oCreature (un joueur humain bien sûr) si nInCutscene vaut TRUE.

  1. Dans ce mode, le personnage ne peut plus rien faire.
  2. Il n'y a plus rien. Cela équivaut à appuyer sur H
  3. N'oubliez JAMAIS de désactiver ce mode ! Sinon le joueur sera bloqué... et forcé de faire Alt + F4


Typiquement, vous devez l'appeler avec tout appel de fonction de Caméra, et après tout appel de fonction de Caméra, avec un DelayCommand pour éviter de rompre le mode "CutScene" avant qu'il n'ai commencé.

Ensuite, vous devrez vous assurer de l'invibilité du personnage : faites un tour plus bas, je donne un fragment de mon code concernant les CutScene.

void StoreCameraFacing()
void RestoreCameraFacing()

Le premier stocke les paramètres de la caméra, le second les restaure. Typiquement, vous devez stocker les paramètres quand vous démarrez la scéne d'introduction - par exemple dans une fonction "cut_mode" qui ferait un appel à SetCutsceneMode et à StoreCameraFacing() si on active le mode CutScene ou à RestoreCameraFacing() si on le stoppe.

N'oubliez pas : vous devez stocker avant tout modification de la caméra. Sachez aussi que c'est assez désagréable pour l'utilisateur de devoir manuellement tout reparamétrer.

De plus, vous devez restaurer la caméra après un certain délai, et pas tout de suite - sinon cela sert strictement à rien.

void SetCameraMode(object oPlayer, int nCameraMode)

Change le type de caméra du joueur. Typiquement :

int CAMERA_MODE_CHASE_CAMERA

Caméra qui suit le joueur par derrière, et qui empêche le zoom. Par contre, on peut changer l'angle d'inclinaison de la caméra par rapport à l'axe z.

int CAMERA_MODE_STIFF_CHASE_CAMERA

Je ne sais pas trop à quoi il sert, ...

int CAMERA_MODE_TOP_DOWN

Mode de caméra le plus libre : permet de changer Zoom, Angle (par rapport à l'est) et Inclinaison par rapport à l'axe z. Je pense personnellement que vous devriez toujours prendre ce mode pour vos intros.


void SetCameraFacing( float fDirection, float fDistance = -1.0f, float fPitch = -1.0, int nTransitionType=CAMERA_TRANSITION_TYPE_SNAP )

C'est grosso modo la fonction qui fait tout : c'est elle qui se charge de changer les paramètres de la caméra.

float fDirection

Direction de la caméra par rapport à l'est. Cela veut dire que vous entrez la valeur 0.0 alors cela pointera vers l'est, 90.0 vers le nord, etc. Notez bien : si vous donnez une valeur alors il y aura rotation de la caméra. Pour éviter ça, utilisez la valeur -1.0 qui évitera cette facheuse rotation (par exemple, vous définissez la caméra à 0.0 et en dessous, vous la redéfinissez à 0.0 : cela fera un tour complêt au frais de la maison!)

[voir nTransitionType]

A noter : les valeurs négatives ne risquent pas de fonctionner ... ce qui est assez logique car "-1.0f" correspond à "359.0f" et correspond à "garder la valeur actuelle".

float fDistance

Distance entre le joueur et le caméraman (invisible, ça doit être un dragonfée). peut prendre une valeur entre 5 et 20 sauf dans le mode CAMERA_MODE_CHASE_CAMERA où elle reste bloquée à 6. La valeur -1.0f permet de garder la valeur actuelle.

Selon la vitesse (nTransitionType), le changement de distance - ou zoom si on veut - fera se déplacer la caméra jusqu'à atteindre la distance souhaitée.

float fPitch

Lorsque dans le jeu vous appuyez sur "PgUp" ou "PgDn" soit du pavé numérique (touche 3 et 9) quand il est désactivé, ou sur les touches à côté de "Suppr", "Fin", vous effectuez une rotation par rapport à l'axe z.
Vous changez juste l'inclinaison de la caméra par rapport à cet axe.
fPitch varie entre 1 et 50 sauf en mode CAMERA_MODE_CHASE_CAMERA où ça varie de 1 à 62.
Il est dommage que l'on ne puisse pas aller plus bas, du genre pour avoir une vie telle qu'on voit correctement l'horizon.

Les valeurs minimales (1.0) indiquent qu'on est près de l'axe z et les valeurs maximales qu'on en est loin.

Je ne sais pas si avec le CameraHak ces valeurs peuvent aller plus loin... Qui sait ?

La valeur -1.0 évite - comme pour la distance et la direction - de changer la valeur actuelle

int nTransitionType

Ca, c'est le truc le plus important. Il va vous permettre de décider des rotations à faire et à quelle vitesse.

Ci-dessous la liste des constantes liées, et leur vitesse :

int CAMERA_TRANSITION_TYPE_CRAWL = 2

Mouvement de la caméra TRES TRES lent. Si vous voulez endormir le joueur, n'hésitez plus !

int CAMERA_TRANSITION_TYPE_VERY_SLOW = 5

Un peu moins lente que la vitesse précédente, mais toujours endormante !

int CAMERA_TRANSITION_TYPE_SLOW = 20

Mouvement lent. Il vous conviendra presque toujours, je dis!

int CAMERA_TRANSITION_TYPE_MEDIUM = 40

Mouvement médian. Un parfait équilibre entre le "rapide" et le "lent".

int CAMERA_TRANSITION_TYPE_FAST = 70

Mouvement rapide (pas testé)

int CAMERA_TRANSITION_TYPE_VERY_FAST = 100

Mouvement très rapide (pas testé)

int CAMERA_TRANSITION_TYPE_SNAP = 0

Mouvement ultra rapide ! En fait, c'est tellement rapide qu'il n'y a pas de mouvement. Si vous voulez, en choisissant cette valeur la caméra se placera directement là où vous voulez qu'elle soit. Cette constante est votre amie pour les plans fixes !
_________________
#nwnights-fr @ irc.darkmyst.org TitanQuest-FR
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web du posteur Ignorer l'utilisateur
 
Baldurien
L'homme qui chutait sur le macadam
Inscrit le: 12 Sep 2002
Messages: 14064
Localisation: Quadran Alpha
Répondre en citant
Posté le : 24/08/2003 22:35:43 Sujet du message :

Apprendre à manipuler la caméra

Tout se passe principalement par les waypoints, et les triggers. Vous me direz mais... qu'est-ce que cela vient faire ?

Personnellement, j'utilise les triggers pour vérifier le timing de ma scéne d'introduction : oui, c'est une chose que vous n'aurez pas autrement (malheureusement).

Les Waypoint vont vous permettre de faire des points de passage, et aussi des points de plan, où l'ont placera le joueur.

1. Marquer les waypoints

- Chaque waypoint devra avoir son tag de manière unique. Veillez-y, c'est important.
- Pour vos tests, il est conseillé de nommer les waypoints pour le placement du joueur, donc de la caméra, tel que le mot Camera apparaisse. Par exemple : cuts1_camera1 pour indiquer le premier waypoint de caméra de la scéne d'intro 1

2. Rendre visible l'invisible

Les waypoints sont par nature invisible. En supposant que le tag du waypoint contienne le mot Camera, ce script devrait vous afficher un Placeable Shall of Light bleu pour les points de caméra, et un Placeable Shall of Light Rouge pour les autres Waypoints.

Code :

void main()
{
  object oWaypoint = GetFirstObjectInArea();

  while ( GetIsObjectValid( oWaypoint ) )
  {
    if ( GetObjectType( oWaypoint ) == OBJECT_TYPE_WAYPOINT )
    {
      if ( FindSubString( GetTag( oWaypoint ), "camera" ) > -1 )
        CreateObject( OBJECT_TYPE_PLACEABLE, "plc_magicblue", GetLocation( oWaypoint ) );
      else
        CreateObject( OBJECT_TYPE_PLACEABLE, "plc_magicred", GetLocation( oWaypoint ) );
    }
    oWaypoint = GetNextObjectInArea();
  }
}


Je ne l'ai pas testé, mais y a pas d'erreur... Donc ... ?
Par contre, vous devez l'éxécuter soit dans un trigger, soit dans la zone. Dans ce cas, pensez à ajouter OBJECT_SELF comme paramètre Area de GetNextObjectInArea et GetFirstObjectInArea.

3. Timing

Cela sera assez important : combien de temps va mettre un NPC pour arriver à un point ? Bonne question non? Combien de temps mettra-t'il entre deux points ? Ce script, à placer dans l'événement OnEnter d'un trigger, vous permettra de faire cela.

Code :

/*
Demarre par :
  (Trigger Timing).OnEnter()
But :
  Comme le suggere le nom du script, cela permet
  de calculer une distance entre deux points en
  secondes et en fonction du personnage qui va
  faire la distance entre ces deux points.
*/
#include "bcn_debug"
void main()
{
  object oEntering = GetEnteringObject();
  float fStartTime = GetLocalFloat( oEntering, "t_timing_start" );
  float fMilliTime = IntToFloat( GetTimeSecond() );
  fMilliTime += IntToFloat( GetTimeMillisecond() ) / 1000;
  float fDifference = fMilliTime - fStartTime;

  print( "Milli-second :" + FloatToString( fDifference, 6, 3 ) );

  SetLocalFloat( oEntering, "t_timing_start", fMilliTime );
}


La librairie bcn_debug est décrite plus bas.

Ce script va stocker le temps d'arrivée dans le premier Trigger, et va faire la différence entre le premier et le second trigger. Vous devriez éviter de faire des triggers gigantesques puisque ça risquerait de fausser vos calculs.

Note : un petit bug s'est glissé dedans : plutôt que de chercher le temps en seconde + milliseconde, le script va arrondir à la seconde inférieure. (en gros ? il ne prend que GetTimeSecond() en compte !)
_________________
#nwnights-fr @ irc.darkmyst.org TitanQuest-FR
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web du posteur Ignorer l'utilisateur
 
Baldurien
L'homme qui chutait sur le macadam
Inscrit le: 12 Sep 2002
Messages: 14064
Localisation: Quadran Alpha
Répondre en citant
Posté le : 24/08/2003 22:39:12 Sujet du message :

Librairie

Note : j'appelle librairie ce que beaucoup appelle bibliothéque. Vous faites comme vous voulez, mais moi je préfére librarie DONC je l'utilise.

bcn_debug
Code :

// Envoi message au premier joueur
void print( string message, float fDelay = 0.0 );

/* fonction de debuggage */
/* envoi un message au client (premier joueur) */
void print( string message, float fDelay = 0.0 )
{
  object player = GetFirstPC();
  DelayCommand( fDelay, SendMessageToPC( player, "[debug::print()] " + message ) );
}


Cette fonction vous sera utile un peu partout. Cela affiche un message au premier joueur, et ce dans l'écran de dialogue. On peut aussi y ajouter un délai.

bcn_cutscene (en cours d'évolution)
Code :


#include "bcn_debug"
/* cutscene function */
// @ref SetCutsceneMode
void cut_mode( object oCreature, int bState, float fDelay = 0.0 );
// @ref PlayAnimation
void cut_animation( object oCreature, int iAnimation, float fDuration = 0.0, float fDelay = 0.0 );
// @ref ActionJumpToLocation
void cut_jump_to_location( object oCreature, location lLocation, float fDelay = 0.0 );
// @ref ActionMoveToLocation
void cut_move_to_location( object oCreature, location lLocation, float fDelay = 0.0, int bRun = FALSE );
// @ref SetCameraFacing, SetCameraMode
void cut_set_camera( object oCreature, float fDelay, int iCameraType, float fFacing, float fZoom, float fPitch, int nSpeed );
// Cache le joueur et le rend etheral pour ne pas etre blesse
void cut_player_hide( object oPlayer );
// @ref (none)
void cut_player_show( object oPlayer );
// @ref GetLocation, GetObjectByTag
location cut_get_location( string sTag );
// @ref
void cut_say( object oCreature, string sDialog, float fDelay = 0.0 );

void cut_mode( object oCreature, int bState, float fDelay = 0.0 )
{
  if ( bState == TRUE )
    StoreCameraFacing();

  DelayCommand( fDelay, SetCutsceneMode( oCreature, bState ) );

  if ( bState == FALSE )
    DelayCommand( fDelay + 0.1, RestoreCameraFacing() );
}

void cut_animation( object oCreature, int iAnimation, float fDuration = 0.0, float fDelay = 0.0 )
{
  DelayCommand( fDelay, AssignCommand( oCreature, PlayAnimation( iAnimation, 1.0, fDuration ) ) );
}

void cut_move_to_location( object oCreature, location lLocation, float fDelay = 0.0, int bRun = FALSE )
{
  if ( GetCommandable( oCreature ) == FALSE )
  {
    SetCommandable( TRUE, oCreature );
    DelayCommand( fDelay, AssignCommand( oCreature, ActionMoveToLocation( lLocation, bRun ) ) );
    SetCommandable( FALSE, oCreature );
  }
  else
    DelayCommand( fDelay, AssignCommand( oCreature, ActionMoveToLocation( lLocation, bRun ) ) );
}

void cut_jump_to_location( object oCreature, location lLocation, float fDelay = 0.0 )
{
  if ( GetCommandable( oCreature ) == FALSE )
  {
    SetCommandable( TRUE, oCreature );
    DelayCommand( fDelay, AssignCommand( oCreature, ActionJumpToLocation( lLocation ) ) );
    SetCommandable( FALSE, oCreature );
  }
  else
    DelayCommand( fDelay, AssignCommand( oCreature, ActionJumpToLocation( lLocation ) ) );
}

void _camera_set( object oCreature, int iCameraType, float fFacing, float fZoom, float fPitch, int nSpeed)
{
  print( "Camera Debug Mode :" );
  print( "-------------------------------------------" );
  print( "camera.type := " + IntToString( iCameraType ) );
  print( "camera.facing := " + FloatToString( fFacing ) );
  print( "camera.zoom := " + FloatToString( fZoom ) );
  print( "camera.pitch := " + FloatToString( fPitch ) );
  print( "camera.speed := " + IntToString( nSpeed ) );
  print( "-------------------------------------------" );

  SetCameraMode( oCreature, iCameraType);
  AssignCommand( oCreature, SetCameraFacing( fFacing, fZoom, fPitch, nSpeed ) );
}
void cut_set_camera( object oCreature, float fDelay, int iCameraType, float fFacing, float fZoom, float fPitch, int nSpeed)
{
  DelayCommand( fDelay, _camera_set( oCreature, iCameraType, fFacing, fZoom, fPitch, nSpeed ) );
}

void cut_player_hide( object oPlayer )
{
  effect eHide = ExtraordinaryEffect( EffectVisualEffect( VFX_DUR_CUTSCENE_INVISIBILITY ) );
  //effect eEtheral = ExtraordinaryEffect( EffectEthereal() );

  //ApplyEffectToObject( DURATION_TYPE_PERMANENT, eEtheral, oPlayer );
  ApplyEffectToObject( DURATION_TYPE_PERMANENT, eHide, oPlayer );

}
// @ref (none)
void cut_player_show( object oPlayer )
{
  effect eEffect = GetFirstEffect( oPlayer );
  int iType, iSubType;

  while ( GetIsEffectValid( eEffect ) )
  {
    iType = GetEffectType( eEffect );
    iSubType = GetEffectSubType( eEffect );
/*
           iType == EFFECT_TYPE_ETHEREAL ||
           iType == EFFECT_TYPE_SANCTUARY
*/

    if ( ( iType == EFFECT_TYPE_VISUALEFFECT ||
           iType == EFFECT_TYPE_IMPROVEDINVISIBILITY  ) &&
           iSubType == SUBTYPE_EXTRAORDINARY
       )
    {
      RemoveEffect( oPlayer, eEffect );
    }
    eEffect = GetNextEffect( oPlayer );
  }
}

location cut_get_location( string sTag )
{
  return GetLocation( GetObjectByTag( sTag ) );
}

void cut_say( object oCreature, string sDialog, float fDelay = 0.0 )
{
  DelayCommand( fDelay, AssignCommand( oCreature, SpeakOneLinerConversation( sDialog, oCreature ) ) );
}

_________________
#nwnights-fr @ irc.darkmyst.org TitanQuest-FR
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web du posteur Ignorer l'utilisateur
 
Baldurien
L'homme qui chutait sur le macadam
Inscrit le: 12 Sep 2002
Messages: 14064
Localisation: Quadran Alpha
Répondre en citant
Posté le : 24/08/2003 22:58:19 Sujet du message :

Explication de cette dernière librairie :

1. le mot-clef @ref suivi d'un nom de fonction indique qu'il faut se référer à la fonction dans le NWScript.

2. Je le dis là : il existe bien entendu une librairie proposée par Bioware, et qui se nomme x1_inc_cutscene sauf qu'il s'agit plus de fonction spécifique à la campagne Solo de Shadows of Undrentide. Utilisez-les si vous voulez, mais :
a. elles ne sont pas vraiment documentées
b. elles vous forcent à passer un paramètre nCutScene à chaque fois. C'est chiant !
c. certaines parties sont en effet spécifique à la campagne Solo de SoU.

void cut_mode( object oCreature, int bState, float fDelay = 0.0 );

Si bState == TRUE, alors une scéne d'introduction est démarrée après fDelay secondes. oCreature se voit alors privé de toute possibilité de sortir du jeu. Cette fonction stocke les paramètres de la caméra avec StoreCameraFacing.
Sinon, alors on stoppe la scéne d'intro pour oCreature au bout de fDelay secondes. Cette fonction fait aussi appel à RestoreCameraFacing pour remettre correctement la caméra.


void cut_animation( object oCreature, int iAnimation, float fDuration = 0.0, float fDelay = 0.0 );

Fait jouer à la créature oCreature la scéne d'animation iAnimation pendant fDuration secondes, et au bout de fDelay secondes. Ceci vérifie aussi si la créature peut être commandée (GetCommandable) et la libére le temps de lui faire faire l'animation.

void cut_jump_to_location( object oCreature, location lLocation, float fDelay = 0.0 );

Envoie la créature à la place lLocation au bout de fDelay secondes.

void cut_move_to_location( object oCreature, location lLocation, float fDelay = 0.0, int bRun = FALSE );

Fait bouger la créature vers lLocation au bout de fDelay seconde en courant ou non.

void cut_set_camera( object oCreature, float fDelay, int iCameraType, float fFacing, float fZoom, float fPitch, int nSpeed );

Change les paramètres de la caméra pour la créature oCreature. Ceci ne vérifie pas si le joueur peut être commandé, NOTEZ BIEN QUE SI VOUS UTILISEZ cut_mode il n'y a pas lieu de vous servir de SetCommandable !.

Pour ça, voyez la description de SetCameraFacing, SetCameraMode décrite plus haut.


void cut_player_hide( object oPlayer );

Cache le joueur c'est à dire le rend invisible pour lui (il ne voit plus le corps de son personnage, par contre, l'ordinateur le verra.) Notez qu'il peut attaquer dans ce mode, et il restera invisible.

1. Notez bien que les ennemis pourront l'attaquer ! Voici un script pompé dans la campagne Solo de nwn pour éviter ça :
Code :

    //Make sure hostiles will not attack PC until after cutscene is over.
    SetStandardFactionReputation(STANDARD_FACTION_HOSTILE, 100, oPC);

oPC est le joueur.

2. Il pourra aussi se prendre les dégâts d'une boule de feu lancée. Pensez donc à le rendre Immortel avec SetImmortal. Et n'oubliez pas de le rendre mortel après la CutScene!

void cut_player_show( object oPlayer );

Supprime l'effet produit par cut_player_hide. Typiquement, cela rend le joueur visible.
Notez bien : cela peut aussi supprimer d'autres effets appliqués au joueur. Pour éviter au plus cela, l'effet produit par cut_player_show est de type Extraordinaire, et on vérifie qu'il s'agit d'un effet Extraordinaire dans cette fonction.

Cela marche bien comme ça. Bioware est plus intelligent je dirais, car ils utilisent une créature (par exemple Drogan dans le chapitre 1) qui va vous appliquer l'effet, et ensuite ils vérifient que le créateur de l'effet est Drogan.

location cut_get_location( string sTag );

Cette fonction est très utile. En fait, j'en avais marre de taper
Code :

location lTruc = GetLocation( GetObjectByTag( sTag ) );


Une petite correction serait d'ajouter un paramètre nNth comme le fait la fonction GetObjectByTag... Enfin bref, moi j'utilise que des objets avec des tags uniques sur une même zone...

void cut_say( object oCreature, string sDialog, float fDelay = 0.0 );

Fait parler une créature avec le dialogue sDialog, en utilisant les tokens placés sur celle-ci, et au bout de fDelay secondes.

Cela utilise en fait la fonction SpeakOneLinerConversation.
_________________
#nwnights-fr @ irc.darkmyst.org TitanQuest-FR
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web du posteur Ignorer l'utilisateur
 
Baldurien
L'homme qui chutait sur le macadam
Inscrit le: 12 Sep 2002
Messages: 14064
Localisation: Quadran Alpha
Répondre en citant
Posté le : 24/08/2003 23:05:08 Sujet du message :

Ceci, ce sont les outils de base. Ce n'est pas fini : vous n'allez pas faire des scénes d'intro comme ça au toolset, ça ne donnera jamais rien. Je le sais, j'ai passé presque une nuit dessus, et croyez moi... j'ai plus eu envie de recommencer !

Mais alors comment faire ?

Simple : il y a peu Lendraste nous proposait un script de Channel (ou Canaux Privé... sigh... ) pour Neverwinter Nights; hé bien moi, je m'en suis légérement inspiré pour faire un système de gestion de la caméra "ingame".

En gros ? Vous entrez dans la fenêtre de dialogue des fonctions qui s'éxécuteront dans le jeu et qui vous simplifieront la vie, croyez moi !

Tout d'abord, crez un Wyrmling, ou n'importe quoi qui peut voler, c'est mieux. Le Wyrmling est très bien je trouve. J'ai pris un blanc.

Placez ce premier script dans le OnSpawn du Dragon :
Code :

#include "bcn_debug"
void main()
{
  AssignCommand( OBJECT_SELF, AddHenchman( GetFirstPC() ) );

  SetListening( OBJECT_SELF, TRUE );
  SetListenPattern( OBJECT_SELF, "help", 1000 );
  SetListenPattern( OBJECT_SELF, "join", 1001 );
  SetListenPattern( OBJECT_SELF, "part", 1002 );
  SetListenPattern( OBJECT_SELF, "follow", 1003 );
  SetListenPattern( OBJECT_SELF, "sc (**) (**) (**) (**)", 3004 );
  SetListenPattern( OBJECT_SELF, "sc (**) (**) (**)", 3000 );
  SetListenPattern( OBJECT_SELF, "scf (**)", 3001 );
  SetListenPattern( OBJECT_SELF, "scz (**)", 3002 );
  SetListenPattern( OBJECT_SELF, "scp (**)", 3003 );
  SetListenPattern( OBJECT_SELF, "jump (**)", 4000 );
  SetListenPattern( OBJECT_SELF, "makemove (**) (**) (**)", 4001 );
}


Je l'ai appelé b_hcm_spawn (pour Balbarie, Henchman, Spawn) mais peu importe.
L'appel de la librairie bcn_debug n'est peut être pas intelligent, vous pouvez l'enlever.

Créez ensuite un autre script, que vous placerez dans le OnConversation : c'est lui qui fera ce que vous désirez.

Code :

#include "bcn_debug"
#include "bcn_cutscene"
void main()
{
  int i, iPattern = GetListenPatternNumber();
  object oObject, oPlayer = GetFirstPC();

  float fFace, fZoom, fPitch;
  int iMode = CAMERA_MODE_TOP_DOWN;
  int iSpeed = CAMERA_TRANSITION_TYPE_SNAP;
  int bGood = FALSE;

  location lWhereToGo;

  switch ( iPattern )
  {
    case 1000:
      print( "The Listener, Command List : " );
      print( "sc <face> <zoom> <pitch>[ <speed>]: change camera face, zoom and pitch. For <speed> see below." );
      print( "scf <face> : change camera face" );
      print( "scz <zoom> : change camera zoom" );
      print( "scp <pitch> : change camera pitch" );
      print( "join : hire the listener as henchman" );
      print( "part : remove the listener from your henchman list" );
      print( "follow : the listener will follow you..." );
      print( "jump <tag> : jump to a waypoint with cut_jump_to_location" );
      print( "makemove <object_tag> <wp_tag1> <wp_tag2> : jump <object_tag> to <wp_tag1> and then make him move his ass to <wp_tag2>" );

      print( "Speed Value :" );
      print( "CAMERA_TRANSITION_TYPE_CRAWL := " + IntToString( CAMERA_TRANSITION_TYPE_CRAWL ) );
      print( "CAMERA_TRANSITION_TYPE_FAST := " + IntToString( CAMERA_TRANSITION_TYPE_FAST ) );
      print( "CAMERA_TRANSITION_TYPE_MEDIUM := " + IntToString( CAMERA_TRANSITION_TYPE_MEDIUM ) );
      print( "CAMERA_TRANSITION_TYPE_SLOW := " + IntToString( CAMERA_TRANSITION_TYPE_SLOW ) );
      print( "CAMERA_TRANSITION_TYPE_SNAP := " + IntToString( CAMERA_TRANSITION_TYPE_SNAP ) + " [Default]" );
      print( "CAMERA_TRANSITION_TYPE_VERY_FAST := " + IntToString( CAMERA_TRANSITION_TYPE_VERY_FAST ) );
      print( "CAMERA_TRANSITION_TYPE_VERY_SLOW := " + IntToString( CAMERA_TRANSITION_TYPE_VERY_SLOW ) );
    break;
    case 1001:
      AddHenchman( oPlayer );
      AssignCommand( OBJECT_SELF , ActionForceFollowObject( oPlayer, 1.0 ) );
    break;
    case 1002:
      RemoveHenchman( oPlayer );
    break;
    case 1003:
      AssignCommand( OBJECT_SELF , ActionForceFollowObject( oPlayer, 1.0 ) );
    break;
    case 3001:
      fFace = StringToFloat( GetMatchedSubstring( 1 ) );
      fZoom = -1.0;
      fPitch = -1.0;
      bGood = TRUE;
    case 3002:
      if ( bGood == FALSE )
      {
        fFace = -1.0;
        fZoom = StringToFloat( GetMatchedSubstring( 1 ) );
        fPitch = -1.0;
        bGood = TRUE;
      }
    case 3003:
      if ( bGood == FALSE )
      {
        fFace = -1.0;
        fZoom = -1.0;
        fPitch = StringToFloat( GetMatchedSubstring( 1 ) );
        bGood = TRUE;
      }
    case 3004:
      if ( GetMatchedSubstringsCount() == 8 )
        iSpeed = StringToInt( GetMatchedSubstring( 7 ) );
    case 3000:
      if ( GetMatchedSubstringsCount() > 2 )
      {
        fFace = StringToFloat( GetMatchedSubstring( 1 ) );
        fZoom = StringToFloat( GetMatchedSubstring( 3 ) );
        fPitch = StringToFloat( GetMatchedSubstring( 5 ) );
      }
      cut_set_camera(
        oPlayer, 0.0, iMode,
        fFace, fZoom, fPitch,
        iSpeed
      );
    break;

    case 4000:
      lWhereToGo = cut_get_location( GetMatchedSubstring( 1 ) );

      print( "Jumping to <" + GetMatchedSubstring( 1 ) + ">" );
      cut_jump_to_location( oPlayer, lWhereToGo );

      AssignCommand( OBJECT_SELF, ClearAllActions( TRUE ) );
      cut_jump_to_location( OBJECT_SELF, lWhereToGo );
      AssignCommand( OBJECT_SELF , ActionForceFollowObject( oPlayer, 1.0 ) );
    break;
    case 4001:
      oObject = GetObjectByTag( GetMatchedSubstring( 1 ) );

      print( "<" + GetName( oObject ) + "> is jumping to <" + GetMatchedSubstring( 3 ) + "> and then he will move to <" + GetMatchedSubstring( 5 ) + ">" );

      AssignCommand( oObject, ClearAllActions( TRUE ) );
      cut_jump_to_location(
        oObject,
        cut_get_location( GetMatchedSubstring( 3 ) )
      );
      AssignCommand( oObject, ClearAllActions( TRUE ) );
      cut_move_to_location(
        oObject,
        cut_get_location( GetMatchedSubstring( 5 ) )
      );
    break;
  }
}

Celui-là, je l'ai nommé b_hcm_conv.
_________________
#nwnights-fr @ irc.darkmyst.org TitanQuest-FR
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web du posteur Ignorer l'utilisateur
 
Baldurien
L'homme qui chutait sur le macadam
Inscrit le: 12 Sep 2002
Messages: 14064
Localisation: Quadran Alpha
Répondre en citant
Posté le : 24/08/2003 23:17:25 Sujet du message :

Ceci ajoutera des commandes assez simple :

1. help : déclenche l'aide qui vous récite les commandes, et leur paramètre.

2. sc <direction> <distance> <inclinaison>[ <vitesse>]

Cette fonction est un raccourci pour :

cut_set_camera( oPlayer, 0.0, iMode, <direction>, <distance>, <inclinaison>, <vitesse> );

oPlayer correspondra toujours au premier joueur
0.0 au délai avant activation de la commande
iMode est un raccourci pour CAMERA_MODE_TOP_DOWN. Comme je l'ai dis, c'est ce mode qui reste à mon goût le meilleur.

Si la vitesse n'est pas fournie, alors elle prend la valeur 0 ou CAMERA_TRANSITION_TYPE_SNAP.

Si vous entrez n'importe quoi, cela devrait faire n'importe quoi : par exemple sc a b c d reviendra à sc 0.0 0.0 0.0 0.0. Notez que vous n'avez absolument pas besoin de mettre "0.0" pour "0" et que vous pourrez utiliser - sauf pour la vitesse - des valeurs flottantes, par exemple un angle de 12.5, etc.

3. scf <direction>

Raccourci pour : sc <direction> -1 -1 0

4. scz <distance>

Raccourci pour : sc -1 <distance> -1 0

5. scp <inclinaison> :

Raccourci pour : sc -1 -1 <inclinaison> 0


6. join :

Rajoute le "listener" en tant qu'Henchman. C'est primordiable. Aussi ça le force à vous suivre pour être sûr qu'il soit toujours auprès de vous pour activer les commandes.

7. part :

Enléve le "listener" de votre liste d'henchman/créature.

8. follow :

Force le "listener" à vous suivre. (à faire si vous ne voulez pas de lui en tant qu'henchmen).

9. jump <tag> :

Vous envoie sur un waypoint nommé par <tag>. A noter qu'il s'agit du premier waypoint ayant pour tag <tag>. (cf ce que j'ai dis plus haut).

10. makemove <object_tag> <wp_tag1> <wp_tag2> :

Fonction utile pour suivre à la caméra un personnage. Par exemple :

makemove cuts1_andrew cuts1_andrew1 cuts1_andrew2

Fera bouger la créature avec le tag cuts1_andrew sur le waypoint (ou autre) cuts1_andrew1,
puis lui dira d'avancer (en marchant) vers le waypoint (ou autre) cuts1_andrew2.

Cette dernière fonction est assez pratique , je peux vous l'assurez.
_________________
#nwnights-fr @ irc.darkmyst.org TitanQuest-FR
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web du posteur Ignorer l'utilisateur
 
Baldurien
L'homme qui chutait sur le macadam
Inscrit le: 12 Sep 2002
Messages: 14064
Localisation: Quadran Alpha
Répondre en citant
Posté le : 24/08/2003 23:23:53 Sujet du message :

Comment s'en servir ?

On est d'accord sur une chose : c'est bien gentil ce truc-muche là mais comment je m'en sers ? Ah ! Simple : il va vous permettre de faire des tests de direction, de distance et d'inclinaison de votre caméra, ainsi que de faire les rotations sans avoir à vous faire chier en NWScript (enfin pour le moment!)

Il vous suffit de tester ce qui vous convient, et de noter les paramètres sur un bout de papier. Et c'est fini les scénes d'intro dures à faire ! (enfin... le timing risque de vous turlupiner , mais bref!)

Bien sûr, ce n'est pas optimal, mais pour moi, là, ça reste encore le meilleur outil pour scéne d'introduction !



A venir : je pense que je ferai un module de test, pour vous montrer ce que l'on peut faire.
_________________
#nwnights-fr @ irc.darkmyst.org TitanQuest-FR
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web du posteur Ignorer l'utilisateur
 
DarkWolf(Pg)
Acolyte
Inscrit le: 20 Aoû 2003
Messages: 33
Répondre en citant
Posté le : 25/08/2003 10:57:08 Sujet du message :

C'est super d'avoir posté toute les fonctions "de base" necessaire pour réaliser une scène d'intro. Je n'ai pas eu besoin de ta bibliotheque (qui a l'air trés utile des qu'on veut faire des plans un peu plus subtile) car je ne fait qu'un 360 en m'éloignant progressivement suivi d'un second qui incline l'axe de la camera.

Au fait j'ai installé le camerahacpack et l'angle de la camera maxi est 90 du coup (trés pratique je trouve).

Merci encore d'avoir donné ce tutorial :>>
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
DarkWolf(Pg)
Acolyte
Inscrit le: 20 Aoû 2003
Messages: 33
Répondre en citant
Posté le : 25/08/2003 10:59:16 Sujet du message :

Vi on édite et ? (Si ya un bouton supprimer message je suis désolé je ne le vois pas) et il ne veut pas envoyer de texte vide
C'est pas grave c'était juste pour éviter à un modo de nettoyer (ou de polluer si personne ne passe)
Dernière édition par DarkWolf(Pg) le 25/08/2003 11:52:19; édité 1 fois
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
Baldurien
L'homme qui chutait sur le macadam
Inscrit le: 12 Sep 2002
Messages: 14064
Localisation: Quadran Alpha
Répondre en citant
Posté le : 25/08/2003 11:36:19 Sujet du message :

En général, on fait des edit de ses messages;)
(c'est pas grave sinon)


[edit]
Inutile de préciser que la librarie est en constante évolution. Donc je ferais les ajouts ici.
_________________
#nwnights-fr @ irc.darkmyst.org TitanQuest-FR
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web du posteur Ignorer l'utilisateur
 
Baldurien
L'homme qui chutait sur le macadam
Inscrit le: 12 Sep 2002
Messages: 14064
Localisation: Quadran Alpha
Répondre en citant
Posté le : 25/08/2003 22:57:11 Sujet du message :

Bon j'ai ajouté un tas de truc, je crois que ferais une explication plus claire de tout cela quand j'aurais fini avec...


Edit : problème détecté avec cut_mode : la caméra est mal restaurée, et souvent on voit le corps du joueur...
_________________
#nwnights-fr @ irc.darkmyst.org TitanQuest-FR
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web du posteur Ignorer l'utilisateur
 
lendraste
Grand Maître Chanteur du Conseil
Inscrit le: 20 Fév 2003
Messages: 1403
Localisation: Quelque part ailleurs
Répondre en citant
Posté le : 28/08/2003 07:23:01 Sujet du message :

Bon, voici un add-on qui, je le pense, intéressera les paresseux ou ceux qui ne savent pas trop scripter. En insérant (ou modifiant) les éléments suivants (parmi ceux déjà donné) votre listener sera en mesure d'enregistrer les commandes de mouvements de caméra et de personnages et de créer automatiquement un script qui sera en mesure de les rejouer. C'est un petit truc fait vite fait et sans prétention. L'idée peut être améliorée par bien des idées et Baldurien s'y est déjà intéressé (puisqu'il a eu la primauté de ce script). S'il y a des améliorations, elles viendront donc de lui.

Le code se compose d'une nouvelle bibliothèque bcn_recorder et d'une modification des deux scripts du Listener (OnSpawn et OnConversation). Il ajoute 4 commandes à la liste :
recstart : démarrage de l'enregistrement avec vidage de la "bande"
recstop : arrêt temporaire de l'enregistrement
recrelease : reprise de l'enregistrement là où il a été stoppé
recexport <nom> : export du script sous le <nom> donné dans le Log.

Le script exporté sera situé entre deux balises :
----- cut-scene : <nom> -----
pour le début
et
----- end cut-scene -----
pour la fin.

Tout ce qui est situé entre ces deux balises (non incluse) est un script directement importable dans le module. Le temps s'écoulant entre la reproduction de chaque commande passé est du temps réel. Si vous avez mis une minute entre deux commandes le script rejouera l'animation en laissant une minute, cependant, vous pouvez personnaliser le script pour modifier ces temps.
Les commandes liées au Listener ne sont pas prise en charge, seul les mouvements de caméra et les déplacements induit par commandes (téléportation ou autre) sont pris en compte.

A toute fin utile, je précise que j'ai testé les scripts de Baldurien (et les miens) sur une version NWN 1.30.

La bibliothèque bcn_recorder
Code :

#include "bcn_debug"
#include "bcn_cutscene"

string BCN_STEP="BCN_CURRENTSTEP";
string BCN_ACTIVE="BCN_ACTIVE";
string BCN_STARTTIME="BCN_STARTTIME";
string BCN_RECA="BCN_RECORDACTION";
string BCN_RECD="BCN_RECORDDELAY";
string BCN_RECP="BCN_RECORDPARAM";

string GetDoubleQuote()
{
  string sTmp=GetStringByStrRef(464);
  return GetStringRight(sTmp,1);
}


void BCN_PutRecDelay(int nRec, float fDelay)
{
  SetLocalFloat(GetModule(), BCN_RECD+IntToString(nRec), fDelay);
}

float BCN_GetRecDelay(int nRec)
{
  return GetLocalFloat(GetModule(), BCN_RECD+IntToString(nRec));
}

void BCN_PutRecAction(int nRec, int nAction)
{
  SetLocalInt(GetModule(), BCN_RECA+IntToString(nRec), nAction);
}

int BCN_GetRecAction(int nRec)
{
  return GetLocalInt(GetModule(), BCN_RECA+IntToString(nRec));
}

void BCN_PutRecParam(int nRec, int nParam, string sParamValue)
{
  SetLocalString(GetModule(), BCN_RECP+IntToString(nParam)+"_"+IntToString(nRec), sParamValue);
}

string BCN_GetRecParam(int nRec, int nParam)
{
  return GetLocalString(GetModule(), BCN_RECP+IntToString(nParam)+"_"+IntToString(nRec));
}

string BCN_FormatInt(int nValue, int nFormat)
{
  string sTmp=IntToString(nValue);
  if (GetStringLength(sTmp)<nFormat)
  {
    string sTmp2="";
    int nCnt;
    for (nCnt=1;nCnt<=nFormat;nCnt++)
    {
      sTmp2=sTmp2+"0";
    }
    sTmp=GetStringRight(sTmp2+sTmp, nFormat);
  }
  else
  {
    sTmp=GetStringRight(sTmp, nFormat);
  }
  return sTmp;
}

void BCN_RecorderActivate()
{
  SetLocalInt(GetModule(), BCN_ACTIVE, TRUE);
}

void BCN_RecorderDeactivate()
{
  SetLocalInt(GetModule(), BCN_ACTIVE, FALSE);
}

int BCN_IsRecorderActive()
{
  return GetLocalInt(GetModule(), BCN_ACTIVE);
}

void BCN_RecorderStepInit()
{
  SetLocalInt(GetModule(), BCN_STEP, 0);
}

void BCN_RecorderStepAdvancement()
{
  SetLocalInt(GetModule(), BCN_STEP, GetLocalInt(GetModule(), BCN_STEP)+1);
}

int BCN_LastRecorderStep()
{
  return GetLocalInt(GetModule(), BCN_STEP);
}

float BCN_AbsoluteTime()
{
  float fAbsTime = 0.0;
  fAbsTime = fAbsTime + IntToFloat(GetCalendarMonth()) * HoursToSeconds(24) * 28.0;
  fAbsTime = fAbsTime + IntToFloat(GetCalendarDay()) * HoursToSeconds(24);
  fAbsTime = fAbsTime + IntToFloat(GetTimeHour()) * HoursToSeconds(1);
  fAbsTime = fAbsTime + IntToFloat(GetTimeMinute()) * 60.0;
  fAbsTime = fAbsTime + IntToFloat(GetTimeSecond());
  return fAbsTime;
}

void BCN_StartTime()
{
  SetLocalFloat(GetModule(), BCN_STARTTIME, BCN_AbsoluteTime());
}

float BCN_GetRecordDelay()
{
  float fTmp=BCN_AbsoluteTime();
  float fStart=GetLocalFloat(GetModule(), BCN_STARTTIME);
  return fTmp-fStart;
}

void BCN_RecorderStart()
{
  BCN_RecorderStepInit();
  BCN_RecorderActivate();
  BCN_StartTime();
}

void BCN_RecorderStop()
{
  if (BCN_IsRecorderActive())
  {
    BCN_RecorderDeactivate();
  }
}

void BCN_RecorderRelease()
{
  if (!BCN_IsRecorderActive())
  {
    BCN_RecorderActivate();
  }
}

void BCN_Record(int nPattern)
{
  if (BCN_IsRecorderActive())
  {
    BCN_RecorderStepAdvancement();
    int nStep=BCN_LastRecorderStep();
    float fDelay=BCN_GetRecordDelay();
    BCN_PutRecDelay(nStep, fDelay);
    BCN_PutRecAction(nStep, nPattern);
    switch (nPattern)
    {
      case 3001 :
      case 3002 :
      case 3003 :
      case 4000 :
      {
        BCN_PutRecParam(nStep, 1, GetMatchedSubstring( 1 ) );
      }break;
      case 4001 :
      case 3000 :
      {
        BCN_PutRecParam(nStep, 1, GetMatchedSubstring( 1 ) );
        BCN_PutRecParam(nStep, 2, GetMatchedSubstring( 3 ) );
        BCN_PutRecParam(nStep, 3, GetMatchedSubstring( 5 ) );
      }break;
      case 3004 :
      {
        BCN_PutRecParam(nStep, 1, GetMatchedSubstring( 1 ) );
        BCN_PutRecParam(nStep, 2, GetMatchedSubstring( 3 ) );
        BCN_PutRecParam(nStep, 3, GetMatchedSubstring( 5 ) );
        BCN_PutRecParam(nStep, 4, GetMatchedSubstring( 7 ) );
      }break;
    }
  }
}

void BCN_RecorderExport(string sName)
{
  PrintString("----- cut-scene : " + sName + " -----");
  PrintString("#" + "include " + GetDoubleQuote() + "bcn_cutscene" + GetDoubleQuote());
  PrintString("");
  PrintString("void cut_complex_move(object oObject, location lLoc1, location lLoc2)");
  PrintString("{");
  PrintString("  AssignCommand(oObject, ActionJumpToLocation(lLoc1));");
  PrintString("  AssignCommand(oObject, ActionMoveToLocation(lLoc2));");
  PrintString("}");
  PrintString("");
  PrintString("void main()");
  PrintString("{");
  PrintString("  // -- Variables déclaration --");
  PrintString("  object oPlayer=GetFirstPC();");
  PrintString("  float fFace;");
  PrintString("  float fZoom;");
  PrintString("  float fPitch;");
  PrintString("  int iSpeed = CAMERA_TRANSITION_TYPE_SNAP;");
  PrintString("  int iMode = CAMERA_MODE_TOP_DOWN;");
  PrintString("  location lWhereToJump;");
  PrintString("  location lWhereToGo;");
  PrintString("  object oObject;");
  PrintString("");
  int nMax=BCN_LastRecorderStep();
  int nCnt=1;
  float fDelay;
  int nAction;
  string sTmp;
  while (nCnt<=nMax)
  {
    nAction=BCN_GetRecAction(nCnt);
    PrintString("  // -- Step " + IntToString(nCnt) + " --");
    fDelay=BCN_GetRecDelay(nCnt);
    switch (nAction)
    {
      case 3000 :
      {
        PrintString("  fFace = " + FloatToString(StringToFloat(BCN_GetRecParam(nCnt, 1))) + ";");
        PrintString("  fZoom = " + FloatToString(StringToFloat(BCN_GetRecParam(nCnt, 2))) + ";");
        PrintString("  fPitch = " + FloatToString(StringToFloat(BCN_GetRecParam(nCnt, 3))) + ";");
        PrintString("  iMode = CAMERA_MODE_TOP_DOWN;");
        PrintString("  iSpeed = CAMERA_TRANSITION_TYPE_SNAP;");
        PrintString("  DelayCommand(" + FloatToString(fDelay) + ", cut_set_camera(oPlayer, 0.0, iMode, fFace, fZoom, fPitch, iSpeed));");
      }break;
      case 3001 :
      {
        PrintString("  fFace = " + FloatToString(StringToFloat(BCN_GetRecParam(nCnt, 1))) + ";");
        PrintString("  fZoom = -1.0;");
        PrintString("  fPitch = -1.0;");
        PrintString("  iMode = CAMERA_MODE_TOP_DOWN;");
        PrintString("  iSpeed = CAMERA_TRANSITION_TYPE_SNAP;");
        PrintString("  DelayCommand(" + FloatToString(fDelay) + ", cut_set_camera(oPlayer, 0.0, iMode, fFace, fZoom, fPitch, iSpeed));");
      }break;
      case 3002 :
      {
        PrintString("  fFace = -1.0;");
        PrintString("  fZoom = " + FloatToString(StringToFloat(BCN_GetRecParam(nCnt, 1))) + ";");
        PrintString("  fPitch = -1.0;");
        PrintString("  iMode = CAMERA_MODE_TOP_DOWN;");
        PrintString("  iSpeed = CAMERA_TRANSITION_TYPE_SNAP;");
        PrintString("  DelayCommand(" + FloatToString(fDelay) + ", cut_set_camera(oPlayer, 0.0, iMode, fFace, fZoom, fPitch, iSpeed));");
      }break;
      case 3003 :
      {
        PrintString("  fFace = -1.0;");
        PrintString("  fZoom = -1.0;");
        PrintString("  fPitch = " + FloatToString(StringToFloat(BCN_GetRecParam(nCnt, 1))) + ";");
        PrintString("  iMode = CAMERA_MODE_TOP_DOWN;");
        PrintString("  iSpeed = CAMERA_TRANSITION_TYPE_SNAP;");
        PrintString("  DelayCommand(" + FloatToString(fDelay) + ", cut_set_camera(oPlayer, 0.0, iMode, fFace, fZoom, fPitch, iSpeed));");
      }break;
      case 3004 :
      {
        PrintString("  fFace = " + FloatToString(StringToFloat(BCN_GetRecParam(nCnt, 1))) + ";");
        PrintString("  fZoom = " + FloatToString(StringToFloat(BCN_GetRecParam(nCnt, 2))) + ";");
        PrintString("  fPitch = " + FloatToString(StringToFloat(BCN_GetRecParam(nCnt, 3))) + ";");
        PrintString("  iMode = CAMERA_MODE_TOP_DOWN;");
        PrintString("  iSpeed = " + IntToString(StringToInt(BCN_GetRecParam(nCnt, 4))) + ";");
        PrintString("  DelayCommand(" + FloatToString(fDelay) + ", cut_set_camera(oPlayer, 0.0, iMode, fFace, fZoom, fPitch, iSpeed));");
      }break;
      case 4000 :
      {
        PrintString("  lWhereToGo = cut_get_location(" + GetDoubleQuote() + BCN_GetRecParam(nCnt, 1) + GetDoubleQuote() + ");");
        PrintString("  DelayCommand(" + FloatToString(fDelay) + ", cut_jump_to_location( oPlayer, lWhereToGo ));");
      }break;
      case 4001 :
      {
        PrintString("  oObject = GetObjectByTag(" + GetDoubleQuote() + BCN_GetRecParam(nCnt, 1) + GetDoubleQuote() + ");");
        PrintString("  lWhereToJump = cut_get_location (" + GetDoubleQuote() + BCN_GetRecParam(nCnt, 2) + GetDoubleQuote() + ");");
        PrintString("  lWhereToGo = cut_get_location (" + GetDoubleQuote() + BCN_GetRecParam(nCnt, 3) + GetDoubleQuote() + ");");
        PrintString("  DelayCommand(" + FloatToString(fDelay) + ", cut_complex_move( oPlayer, lWhereToJump, lWhereToGo ));");
      }break;
    }
    nCnt++;
  }
  PrintString("}");
  PrintString("----- end cut-scene -----");
  print("Cutscene " + sName + " exported");
}



Le OnSpawn Du Listener
Code :

#include "bcn_debug"
void main()
{
  AssignCommand( OBJECT_SELF, AddHenchman( GetFirstPC() ) );

  SetListening( OBJECT_SELF, TRUE );
  SetListenPattern( OBJECT_SELF, "help", 1000 );
  SetListenPattern( OBJECT_SELF, "join", 1001 );
  SetListenPattern( OBJECT_SELF, "part", 1002 );
  SetListenPattern( OBJECT_SELF, "follow", 1003 );
  SetListenPattern( OBJECT_SELF, "sc (**) (**) (**) (**)", 3004 );
  SetListenPattern( OBJECT_SELF, "sc (**) (**) (**)", 3000 );
  SetListenPattern( OBJECT_SELF, "scf (**)", 3001 );
  SetListenPattern( OBJECT_SELF, "scz (**)", 3002 );
  SetListenPattern( OBJECT_SELF, "scp (**)", 3003 );
  SetListenPattern( OBJECT_SELF, "jump (**)", 4000 );
  SetListenPattern( OBJECT_SELF, "makemove (**) (**) (**)", 4001 );
  SetListenPattern( OBJECT_SELF, "recstart", 5000);
  SetListenPattern( OBJECT_SELF, "recstop", 5001);
  SetListenPattern( OBJECT_SELF, "recrelease", 5002);
  SetListenPattern( OBJECT_SELF, "recexport **", 5003);
}




Le OnConversation du Listener
Code :

#include "bcn_recorder"
void main()
{
  int i, iPattern = GetListenPatternNumber();
  object oObject, oPlayer = GetFirstPC();

  float fFace, fZoom, fPitch;
  int iMode = CAMERA_MODE_TOP_DOWN;
  int iSpeed = CAMERA_TRANSITION_TYPE_SNAP;
  int bGood = FALSE;

  location lWhereToGo;

  if ((iPattern>=3000) && (iPattern<=4001))
  {
    BCN_Record(iPattern);
  }

  switch ( iPattern )
  {
    case 1000:
      print( "The Listener, Command List : " );
      print( "sc <face> <zoom> <pitch>[ <speed>]: change camera face, zoom and pitch. For <speed> see below." );
      print( "scf <face> : change camera face" );
      print( "scz <zoom> : change camera zoom" );
      print( "scp <pitch> : change camera pitch" );
      print( "join : hire the listener as henchman" );
      print( "part : remove the listener from your henchman list" );
      print( "follow : the listener will follow you..." );
      print( "jump <tag> : jump to a waypoint with cut_jump_to_location" );
      print( "makemove <object_tag> <wp_tag1> <wp_tag2> : jump <object_tag> to <wp_tag1> and then make him move his ass to <wp_tag2>" );
      print( "recstart : to begin the recording of the cutscene" );
      print( "recstop : to stop the recording" );
      print( "recrelease : to continue recording where it has been stopped" );
      print( "recexport <name> : to create the <name> cutscene into the log" );

      print( "Speed Value :" );
      print( "CAMERA_TRANSITION_TYPE_CRAWL := " + IntToString( CAMERA_TRANSITION_TYPE_CRAWL ) );
      print( "CAMERA_TRANSITION_TYPE_FAST := " + IntToString( CAMERA_TRANSITION_TYPE_FAST ) );
      print( "CAMERA_TRANSITION_TYPE_MEDIUM := " + IntToString( CAMERA_TRANSITION_TYPE_MEDIUM ) );
      print( "CAMERA_TRANSITION_TYPE_SLOW := " + IntToString( CAMERA_TRANSITION_TYPE_SLOW ) );
      print( "CAMERA_TRANSITION_TYPE_SNAP := " + IntToString( CAMERA_TRANSITION_TYPE_SNAP ) + " [Default]" );
      print( "CAMERA_TRANSITION_TYPE_VERY_FAST := " + IntToString( CAMERA_TRANSITION_TYPE_VERY_FAST ) );
      print( "CAMERA_TRANSITION_TYPE_VERY_SLOW := " + IntToString( CAMERA_TRANSITION_TYPE_VERY_SLOW ) );
    break;
    case 1001:
      AddHenchman( oPlayer );
      AssignCommand( OBJECT_SELF , ActionForceFollowObject( oPlayer, 1.0 ) );
    break;
    case 1002:
      RemoveHenchman( oPlayer );
    break;
    case 1003:
      AssignCommand( OBJECT_SELF , ActionForceFollowObject( oPlayer, 1.0 ) );
    break;
    case 3001:
      fFace = StringToFloat( GetMatchedSubstring( 1 ) );
      fZoom = -1.0;
      fPitch = -1.0;
      bGood = TRUE;
    case 3002:
      if ( bGood == FALSE )
      {
        fFace = -1.0;
        fZoom = StringToFloat( GetMatchedSubstring( 1 ) );
        fPitch = -1.0;
        bGood = TRUE;
      }
    case 3003:
      if ( bGood == FALSE )
      {
        fFace = -1.0;
        fZoom = -1.0;
        fPitch = StringToFloat( GetMatchedSubstring( 1 ) );
        bGood = TRUE;
      }
    case 3004:
      if ( GetMatchedSubstringsCount() == 8 )
        iSpeed = StringToInt( GetMatchedSubstring( 7 ) );
    case 3000:
      if ( GetMatchedSubstringsCount() > 2 )
      {
        fFace = StringToFloat( GetMatchedSubstring( 1 ) );
        fZoom = StringToFloat( GetMatchedSubstring( 3 ) );
        fPitch = StringToFloat( GetMatchedSubstring( 5 ) );
      }
      cut_set_camera(
        oPlayer, 0.0, iMode,
        fFace, fZoom, fPitch,
        iSpeed
      );
    break;

    case 4000:
      lWhereToGo = cut_get_location( GetMatchedSubstring( 1 ) );

      print( "Jumping to <" + GetMatchedSubstring( 1 ) + ">" );
      cut_jump_to_location( oPlayer, lWhereToGo );

      AssignCommand( OBJECT_SELF, ClearAllActions( TRUE ) );
      cut_jump_to_location( OBJECT_SELF, lWhereToGo );
      AssignCommand( OBJECT_SELF , ActionForceFollowObject( oPlayer, 1.0 ) );
    break;
    case 4001:
      oObject = GetObjectByTag( GetMatchedSubstring( 1 ) );

      print( "<" + GetName( oObject ) + "> is jumping to <" + GetMatchedSubstring( 3 ) + "> and then he will move to <" + GetMatchedSubstring( 5 ) + ">" );

      AssignCommand( oObject, ClearAllActions( TRUE ) );
      cut_jump_to_location(
        oObject,
        cut_get_location( GetMatchedSubstring( 3 ) )
      );
      AssignCommand( oObject, ClearAllActions( TRUE ) );
      cut_move_to_location(
        oObject,
        cut_get_location( GetMatchedSubstring( 5 ) )
      );
    break;
    case 5000 :
    {
      BCN_RecorderStart();
    }break;
    case 5001 :
    {
      BCN_RecorderStop();
    }break;
    case 5002 :
    {
      BCN_RecorderRelease();
    }break;
    case 5003 :
    {
      string sExportName = GetMatchedSubstring( 1 );
      BCN_RecorderExport(sExportName);
    }break;
  }
}
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé MSN Messenger Numéro ICQ Ignorer l'utilisateur
 
DarkWolf(Pg)
Acolyte
Inscrit le: 20 Aoû 2003
Messages: 33
Répondre en citant
Posté le : 28/08/2003 08:28:54 Sujet du message :


Baldurien a écrit :

Edit : problème détecté avec cut_mode : la caméra est mal restaurée, et souvent on voit le corps du joueur...
J'ai eu ce problème, je ne sais pas si c'est tré propre ni c'est du à un coup de chance mais j'ai "résolu" ce problème en assignant les commandes StoreCameraFacing et RestoreCameraFacing au joueur.
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
Baldurien
L'homme qui chutait sur le macadam
Inscrit le: 12 Sep 2002
Messages: 14064
Localisation: Quadran Alpha
Répondre en citant
Posté le : 29/08/2003 16:35:51 Sujet du message :

Normalement, je crois l'avoir fait avec la nouvelle version. Je la fouterai quand j'aurais le temps
_________________
#nwnights-fr @ irc.darkmyst.org TitanQuest-FR
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web du posteur Ignorer l'utilisateur
 
Cassin
Papa-poule(t) & poissard intemporel
Inscrit le: 16 Sep 2002
Messages: 7471
Localisation: 6 bis rue de la Couveuse, Poulailler 39b
Répondre en citant
Posté le : 09/09/2003 07:10:11 Sujet du message :

Bon, j'ai enfin trouvé le temps hier de me pencher là-dessus, et c'est vraiment très pratique en effet comme Bibliothèque Wink


Mais j'ai une petite question : comment donne-t-on le sens de rotation à la caméra ?

Parce que là c'est un peu aléatoire je trouve... Hier en faisant divers test, je fait un mouvement de 180°, du sud vers le nord, vitesse slow, ça tourne en antihoraire. Je décide de poursuivre le mouvement et de revenir au sud (360° quoi) mais de faire la deuxième moitié en vitesse FAST (histoire de pas m'endormir Laughing), et bien au lieu de continuer dans le même sens, la caméra repart en marche arrière (en sens horaire donc) ! Pas top pratique donc...
_________________
Aventure ! Camaraderie ! Et acier sur acier ! Les ingrédients légendaires ! Hein Bouh ?

http://cassin1306.spaces.live.com
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web du posteur Ignorer l'utilisateur
 
lendraste
Grand Maître Chanteur du Conseil
Inscrit le: 20 Fév 2003
Messages: 1403
Localisation: Quelque part ailleurs
Répondre en citant
Posté le : 09/09/2003 09:36:49 Sujet du message :

Je pense qu'une amélioration sympa pourrait être de pouvoir faire des "snaps" de la position de la caméra puis d'indiquer quel type de mouvement on souhaite avoir entre deux "snaps" pour qu'il calcule automatiquement le mouvement.
Désolé, je n'ai que l'idée et pas le temps de la mettre en oeuvre.
_________________
Lendraste de Loreval
Qui cherche la Vérité cherche celui qui la détient, car elle n'existe pas à l'état naturel.
La cité des mensonges - 1
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé MSN Messenger Numéro ICQ Ignorer l'utilisateur
 
Cassin
Papa-poule(t) & poissard intemporel
Inscrit le: 16 Sep 2002
Messages: 7471
Localisation: 6 bis rue de la Couveuse, Poulailler 39b
Répondre en citant
Posté le : 15/09/2003 10:50:18 Sujet du message :

Une petite question au passage : est-il possible de décentrer la caméra du joueur, pour faire par exemple une vue "à la Survival Horror" (comme Resident Evil quoi Niark), comme c'était le cas avec le hak de John Gestalt ?
_________________
Aventure ! Camaraderie ! Et acier sur acier ! Les ingrédients légendaires ! Hein Bouh ?

http://cassin1306.spaces.live.com
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web du posteur Ignorer l'utilisateur
 
Baldurien
L'homme qui chutait sur le macadam
Inscrit le: 12 Sep 2002
Messages: 14064
Localisation: Quadran Alpha
Répondre en citant
Posté le : 15/09/2003 13:03:49 Sujet du message :

ah ? il permettait de faire ça ?

Bah c'est juste un script mon basar, j'ai rien touché d'autre !

Par contre rien ne t'empêche de faire une copie du joueur : cela permet de lui faire voir son lui malgré la caméra

[edit]

Sinon niveau rotation, c'est assez simple !

Déjà la caméra à un angle alpha oki ?

on veut qu'elle aille à beta

Si alpha > beta > 0° alors la caméra ira de beta vers alpha (droite)
Si alpha < beta > 0° alors la caméra ira de alpha vers beta (gauche)

Etc.
_________________
#nwnights-fr @ irc.darkmyst.org TitanQuest-FR
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web du posteur Ignorer l'utilisateur
 
Le grognon
Voyageur
Inscrit le: 16 Sep 2003
Messages: 2
Répondre en citant
Posté le : 16/09/2003 10:56:08 Sujet du message :


lendraste a écrit :
Bon, voici un add-on qui, je le pense, intéressera les paresseux ...
Je t'aime toi Embarassed

Salut aux Bibliothecaires du coin Razz
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
castorus
Acolyte
Inscrit le: 24 Déc 2005
Messages: 23
Répondre en citant
Posté le : 07/02/2006 14:53:23 Sujet du message :

Moi je plaiderais plutôt mes conditions a moi qui sont :

Si Beta < (180.0+Alpha) Alors Mouvement de caméra Antihoraire
Sinon Si Beta > (180.0+Alpha) Alors mouvement de camera Horaire.
Sinon Si Beta == (180.0+Alpha) Alors Mouvement Antihoraire.


Parce que tes conditions foire pour nottament :
Alpha = 270.0
Beta = 0.0

car
270.0 > 0.0 > 0.0 !FAUX
270.0 < 0.0 > 0.0 !FAUX

On ne sait pas dans quel direction va tourner la caméra.

Tandis qu'avec les miennes :
0.0 < (180.0 + 270.0) !JUSTE Donc Mouvement Antihoraire
0.0 > (180.0 + 270.0) !FAUX
0.0 == (180.0 + 270.0) !FAUX


voila dites moi ce que vous en pensez et essayez de trouver les failles ^^ BYBYE.
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
Montrer les messages depuis :
Page 1 sur 1 ¤


Vous ne pouvez pas poster de nouveaux sujets dans ce forum
Vous ne pouvez pas répondre aux sujets dans ce forum
Vous ne pouvez pas éditer vos messages dans ce forum
Vous ne pouvez pas supprimer vos messages dans ce forum
Vous ne pouvez pas voter dans les sondages de ce forum


Sauter vers:
FAQ | Rechercher | Liste des Membres | Groupes d'utilisateurs | S'enregistrer | Profil | Se connecter pour vérifier ses messages privés | Connexion
Powered by phpBB 2.* [m] © 2001, 2002 phpBB Group
Theme rewritten in beautiful XHTML code by Baldurien.
Thème "La Bibliothèque de Neverwinter" crée par Kruger
Traduction par : phpBB-fr.com
Page generated in 57.566ms