Differences

This shows you the differences between the selected revision and the current
version of the page.


fr:wmebook:ch4 2011/10/19 13:41 fr:wmebook:ch4 2011/10/19 17:33 current
Line 3: Line 3:
Juste avant nous avons fait des essais sur une démo pré-compilées, Mais maintenant il est tant de revenir à la racine et de créer un nouveau projet complet comme on a envie. Démarrez le gestionnaire de projet et presser Ctrl+N (sinon cliquez sur l’icône nouveau projet (new project)ou choisissez Nouveau projet (New Project) dans le menu Fichiers (File) ). Nommez votre projet comme vous le souhaitez et laissez WME le créer. Juste avant nous avons fait des essais sur une démo pré-compilées, Mais maintenant il est tant de revenir à la racine et de créer un nouveau projet complet comme on a envie. Démarrez le gestionnaire de projet et presser Ctrl+N (sinon cliquez sur l’icône nouveau projet (new project)ou choisissez Nouveau projet (New Project) dans le menu Fichiers (File) ). Nommez votre projet comme vous le souhaitez et laissez WME le créer.
-Vous pouvez voir que WME a créé un nouveau projet en y mettant quelques éléments prédéfinis ainsi le démarrage de notre nouveau jeu sera plus simple car nous pouvons dès maintenant lancer ce projet minimaliste et ça marche.Ce que nous allons faire bien, c'est de tourner notre attention vers le point le jeu commence réellement. Ce point c'est un simple fichier appelé **game.script** //(Qui se trouve dans data->scripts)//.+Vous pouvez voir que WME a créé un nouveau projet en y mettant quelques éléments prédéfinis ainsi le démarrage de notre nouveau jeu sera plus simple car nous pouvons dès maintenant lancer ce projet minimaliste et ça marche. Ce que nous allons quand même faire, c'est de porter notre attention sur le point avec lequel le jeu commence réellement. Ce point c'est un simple fichier appelé **game.script** //(Qui se trouve dans data->scripts)//.
 +Vous pouvez facilement vérifier dans votre gestionnaire de projet, que le jeu a un script attaché à lui et ça ne sera pas une surprise pour vous, que ce script c'est ... game.script. Tout simplement dit, la toute première chose que fait WME après avoir initialisées toutes les fenêtres du système c'est d’exécuter ce fichier. Je parle de ça assez largement, parce que je veut que vous compreniez bien la souplesse de WME. A ce niveau rien n'est décidé, à quoi va ressembler le jeu, comment le jeu se joue, etc...
-You can easily check in your Project Manager, that the game has one script attached to it and it won’t be surprise for you, that this attached script is ... game.script. So simply said the very first thing WME does after initializing all windows system stuff is to execute this file. I am speaking about it so broadly, because I want you to fully understand how versatile WME is. At this point nothing is decided, how the game will look, how the game will play etc.  +Essayons de découvrir ce que le script du jeu fait par petit blocs:
- +
-Let’s try to uncover what game script does by little blocks:+
<code script> <code script>
Line 15: Line 14:
</code> </code>
-First we include the file base.inc, which contains 3 global variables - actor, Scene and Keyboard. This way we don’t have in every single script declare global Scene; before calling for example Scene.GetNode(); Base.inc in turn includes another file called const.inc which contains constants for actor directions and text alignment. In course of our game creation we will add global variables and constants in these files to keep our game tidy. We can also separate our includes into more files if we’re so inclined. Second file contains definition to keyboard codes so we don’t have to guess numbers and simply type their textual representation like VK_ESCAPE instead of 27 if we want to test for Esc key.+D'abord nous intégrons le fichier base.inc, qui contient 3 variables globales - actor, Scene et Keyboard. Comme ça on a pas besoin, dans chaque script, à déclarer global Scene; avant d'appeler par exemple Scene.GetNode();
 +Base.inc à son tour, introduit un autre fichier appelé const.inc qui contient les constantes les directions de l'acteur et les alignement de texte. Au cours de la création de notre jeu nous ajouterons des variables globales et des constantes dans ces fichiers pour garder notre jeu bien rangé. Nous pouvons également séparer nos Includes dans plus de fichiers si on est obligé. Le deuxième fichier contient la définition des codes claviers, nous n'avons donc pas à deviner des chiffres mais tapez simplement leur représentation textuelle comme VK_ESCAPE au lieu de 27 si on veut tester la touche Esc.
<code script> <code script>
Line 22: Line 22:
</code> </code>
-As you already should know by now, all basic objects are members of the Game object. But there are two reasons why we need variables to hold those nested objects. First WME doesn’t allow nesting so you can’t use for example:+Comme vous devriez déjà le savoir maintenant, tous les objets de base sont membres de l'objet Game. Mais il y a deux raisons pour lesquelles nous avons besoin de variables pour stocker ces objets imbriqués. Premièrement WME ne permet pas les imbrications donc vous ne pouvez pas utiliser par exemple:
<code script> <code script>
Line 28: Line 28:
</code> </code>
-and second it looks much more clean if you write //Scene.GetNode("Door");// anyway.+et deuxièmement ça semble, de toute façon, plus clair si vous écrivez //Scene.GetNode("Door");//.
-So back to those lines – we’ve created a global variable Keyboard which contains a reference to //Game.Keyboard// object and which will be used for querying keyboard entry and global variable which holds reference to Scene object. As a little side note - this object is still the same even if you’re changing scenes so you don’t have to reassign it every time you changed the scene.+Donc, retour à ces lignes - Nous avons créé une variable globale Keyboard qui fait référence à l'objet //Game.Keyboard// et qui sera utilisé pour interrogé les saisies clavier et une variable globale qui fait référence à l'objet Scene.  
 + 
 +Comme petite annotation dans la marge - Cet objet est toujours le même, même si vous décidez de changer des scènes ainsi vous n'avez pas à la réassigner à chaque fois que vous avez changé la scène.
<code script> <code script>
Line 37: Line 39:
</code> </code>
-By default you have the preset behavior that if you right click on a hotspot, little menu appears where you can choose from three actions. **Now do me a favor and delete those two lines.** We’ll try to go barebones.+Par défaut vous avez un truc prédéfini, que si vous faites un clic droit sur ​​un hot-spot, un petit menu apparait dans lequel vous pouvez choisir entre trois actions. **Maintenant, faite moi plaisir et dégommer moi ces 2 lignes.** Nous allons essayer de le dépouiller. 
 + 
 +Vous devez vous demander, qu'est que window (fenêtre)? Window c'est un groupe d'éléments graphique (boutons, images, champs d’édition pour saisir un texte) ce qui est bien pratique pour concevoir un GUI (Interface Graphique pour l'Utilisateur). Le gros avantage c'est que c'est indépendant de la scène, vous pouvez donc l'avoir à l'écran pour toutes les scènes sans avoir à replacé, expressément, les éléments à chaque fois.
-You may ask, what is a window? Window is a collection of graphical items (buttons, images, edit fields for textual input) which is very practical for forming GUI (graphical user interface). The big advantage is that it’s Scene independent so you can have it on screen for every scene without explicitly forming the elements every time. We’ll look on the windows building later, so let’s focus for now what those two lines mean. First line loads a window file (which contains a definition of the graphical window) and second sets it invisible. The window is attached to the Game object so scene changing can’t affect it. Note that windows are an exception. Entities use //Active//, Windows use //Visible//.+Nous verrons la fabrication des fenêtres plus tard, focalisons nous pour le moment sur ce que veulent dire ses deux lignes. La première ligne charge un fichier .window (qui contient une définition de la fenêtre graphique) et la seconde la rend invisible. Cette fenêtre est attachée à l'objet Game donc le changement de scène ne l'affecte pas. Notez que les fenêtres sont des exceptions. Les entités utilise //Active//, les fenêtres utilise //Visible//.
<code script> <code script>
Line 46: Line 50:
</code> </code>
-And another load of window! This one is meant for captions whenever you hover your mouse over the hotspot. Also we introduce a brand new method for getting a reference to specific part of the window. This one is the actual field which holds the text. Now do me a favor – GetWidget is ancient way how to get the control. Now we use much more intuitive GetControl so rewrite the second line to:+Et encore un chargement de fenêtre! Celle-ci est destinée au légendes (infos-bulles) chaque fois que vous passez votre souris sur le hot-spot. De plus, nous introduisons une toute nouvelle méthode pour faire référence à une partie spécifique de la fenêtre. Celui-ci est le champ réel qui contient le texte. Maintenant pour me faire plaisir - GetWidget est l'ancienne manière d'obtenir le contrôle. Maintenant nous utilisons plus facilement GetControl , donc réécrivez moi la seconde ligne en :
<code script> <code script>
-global WinCaption = win.GetControl("caption"); //You can also remember the parallel Scene.GetNode(name); Window.GetControl(name);+global WinCaption = win.GetControl("caption"); //Vous pouvez également constater la similitude Scene.GetNode(name); Window.GetControl(name);
</code> </code>
-next comes:+vient ensuite:
<code script> <code script>
global MenuObject = null; global MenuObject = null;
</code> </code>
-We store a **null** to MenuObject which will be used later to see what we clicked. Null is a special value, which indicates that there really is nothing. And you can delete this line as well.+Nous stockons un **null** dans MenuObject qui sera utilisé plus tard pour voir ce qui est cliqué. Null est une valeur speciale, qui indique qui n'y a absolument rien. Et vous pouvez, aussi bien, effacer cette ligne.
<code script> <code script>
Line 64: Line 68:
</code> </code>
-Now those are important lines. Variable “actor” is a global variable defined in base.inc which will now be filled with the definition of our .actor file. Again later on we’ll look how the actor files are constructed. For now let’s live with the fact that we have molly and she can do whatever we want.+Maintenant ces lignes sont importantes. La variable "actor" est une variable globale dans base.inc qui sera remplis, maintenant, avec la définition de notre fichier .actor. Encore plus tard nous verrons comment les fichiers d'acteur sont construit. Pour le moment vivons avec le fait que nous avons Molly et qu'elle peut faire tout ce qu'on veut.
-Also as a side note, we can use second function **Scene.LoadActor(actor);** which loads the actor but attaches it to the current scene and cthe actor is destroyed when you leave the scene.+Aussi en note dans la marge, nous pouvons une deuxième fonction **Scene.LoadActor(actor);** qui charge l'acteur mais l'attache à la scène courante et l'acteur est détruit quand vous quittez la scène.
-Last we set up the attribute **MainObject** to our freshly loaded actor, which does the only thing – when actor moves and the scene is supposed to scroll, the scrolling is oriented to this actor. In case there were more switchable actors (like for example in Day of the Tentacle) this attribute will provide correct scrolling for selected character. You can set also null to this attribute.+La dernière ligne, nous plaçons notre acteur fraichement chargé dans l'attribut **MainObject**, ce qui fait la seul chose - lorsque l'acteur se déplace et que la scène est censée défiler, le défilement s'oriente vers l'acteur. Au cas ou il y aurait plusieurs acteurs échangeables (Comme par exemple dans Day of the Tentacle) Cet attribut permettra d'avoir un défilement correct quelque soit le personnage sélectionné. Vous pouvez régler Null dans cet attribut.
<code script> <code script>
-Game.AttachScript("scripts\game_loop.script"); //formerly known as a game_daemon.script+Game.AttachScript("scripts\game_loop.script"); //anciennement connu comme game_daemon.script
</code> </code>
-We’ll attach the core processes, which take care of caption displaying and inventory appearing when you scroll your mouse up. This will be our second file we’ll examine in a minute. Again you can see, that this file is globally attached for the whole game.+Nous allons fixer le processus clés, qui s'occupe de l'affichage des légendes et de l'apparition de l'inventaire quand vous glissé votre souris en haut. Ce sera notre second fichier que nous allons examiner dans une minute. Là encore vous pouvez voir, que ce fichier est globalement attaché au jeu entier.
-And now for something formerly extremely important - now settable from the project manager:+Et voici quelque chose autrefois extrêmement important - désormais paramétrable à partir du gestionnaire de projet:
<code script> <code script>
Line 82: Line 86:
</code> </code>
-This is the point where you define in what scene starts your game. Usually it will be some sort of Menu screen unless you start with some FMV intros or such. Now comes the main cleansing part. As we’re stripping our game down, we’ll now remove all inventory interactions only to add them later when we’ll be more skilled.+C'est le point où vous définissez à quel scène commence votre jeu. Habituellement ça sera un genre d’écran menu sauf si vous démarrez par une intro. ou du genre. Maintenant vient la partie principale de nettoyage. Comme nous sommes en plein épuration de notre jeu, nous allons maintenant virer toutes les interactions avec l'inventaire seulement pour les ajouter plus tard lorsque nous serons plus qualifiés.
-So simply modify on “LeftClick” event to read:+Donc modifiez simplement les événements dans “LeftClick” pour avoir:
<code script> <code script>
Line 101: Line 105:
</code> </code>
-When we left click in the scene, we first look if the click was in the hotspot. WME knows if there is a hotspot under our mouse cursor and fills attribute **ActiveObject** accordingly.  +Quand nous cliquons avec le bouton droit dans la scène, on regarde en premier si le clique était sur un Hot-spot. WME sait s'il y a un hot-spot sous le pointeur de la souris et remplit l'attribut **ActiveObject**en conséquence
-Now we simplified our logic to two states. If we clicked on an object, we’ll call his “LeftClick” event. This brings us back to our experiments in the last chapter where we assigned the “LeftClick” event to door. This is the reason why that event got called in the first place. **ApplyEvent** is a method which is used for running events manually.+Nous avons, maintenant, réduit notre logique à deux états. Si nous avons cliqué sur un objet, nous allons appelé sont événement “LeftClick”. Ça nous ramène à nos essais dans le dernier chapitre, où nous avons attribué l'événement “LeftClick” de la porte. C'est la raison pour laquelle cet événement s'est appelé en premier. **ApplyEvent** c'est une méthode qui est utilisée pour lancer des événements manuellement.
-If we clicked elsewhere (no hotspot under cursor), scene “LeftClick” event is fired. I almost hear you scream now: “Wait a minute. What is a scene “LeftClick” event?!".+Si on clique n’importe où (Pas de hot-spot sous le pointeur), l'événement de la scène "LeftClick" est déclenché. Là, j'ai cru vous entendre crier : " Attends un peu, c'est quoi l’événement de la scène “LeftClick”?!".
-This is another trick by WME which comes out of Scene template. If you create a new scene, or open your room scene in scene edit and switch to the //Properties tab// and click on the **"Scripts..."** button, you’ll see that there are two scripts attached. Your favorite scene_init.script and scripts/scene.script. And since this is the template every single scene uses, let’s uncover what dark mysteries this file holds?+C'est une autre astuce de WME qui sort du modèle de scène (Scene template). Si vous créez une nouvelle scène, ou vous ouvrez votre salle de la scène dans l’éditeur de scène et que vous allez dans //l'onglet Properties// et que vous cliquez sur le bouton **"Scripts..."**, vous allez voir qu'il y a deux scripts attachés. Votre scene_init.script préféré et scripts/scene.script. et comme c'est le modèle que chaque scène utilise, découvrons ce sombre mystère que contient ce fichier?    
<code script> <code script>
Line 117: Line 121:
</code> </code>
-HA! That’s it. if this event is fired, our actor goes to the current mouse position in the scene. So it boils down to the simple thing: If we click on a hotspot it’s left click is fired else our actor walks to the current mouse position. And that’s about the LeftClicks for now.+HA! C'est ça. Si cet évenement est déclenché, notre acteur va à la position actuelle de la souris dans la scene. Donc pour resumer avec des choses simples: Si on clique sur un hot-spot c'est le "left click" qui est declenché alors notre acteur marche vers la position courante de la souris. Et c'est juste le clique gauche pour le moment.
-Let’s move on to the next event “RightClick” and erase the whole block. We don’t need it now and it would only make our head spin.+Déplaçons nous vers l’événement suivant “RightClick” et effacez le bloc entier. Nous n'en avons pas besoin tout suite et ne ferais que vous faire tourner la tête.
-Last two events (“Keypress” and “QuitGame”) deals with menu displaying and handling the alt+f4 combo. We don’t have to bother ourselves with it for now, but rest assured, that we’ll look into them soon too.+Les deux derniers événement (“Keypress” et “QuitGame”) fonctionnent avec les menus d'affichage et la manipulation des combinaison de touches Alt + F4. Nous n'avons pas à nous embêter avec elle pour l'instant, mais rassurez-vous, nous allons les voir rapidement aussi.
-Let’s recap new methods and attributes we learned so far in this chapter:+Récapitulons les nouvelles méthodes et les attributs que nous avons appris jusqu'à présent dans ce chapitre:
-**var window = Game.LoadWindow(window filename);**  - Loads a window definition, attaches it to the Game object and optionally returns a reference to it (in this case to window variable+**var window = Game.LoadWindow(window filename);**  - Charge une définition de fenêtre, qu'il attache à l'objet Game et lui retourne éventuellement un référence (dans ce cas à la variable window) 
-**window.Visible = true / false;** - Makes the loaded window visible/invisible on the screen +**window.Visible = true / false;** - Fait que la fenêtre chargée est visible/invisible à l'écran. 
-**window.GetContro(controlname);** - Returns a reference to a control stored in the window +**window.GetContro(controlname);** - Retourne une référence à un contrôle se trouvant dans la fenêtre. 
-**Game.LoadActor(actor filename);** - Loads an actor from file and attaches it to a game object+**Game.LoadActor(actor filename);** - Charge un acteur d'un fichier et l'attache à l'objet Game
-**Scene.LoadActor(actor filename);** - Loads an actor from file and attaches it to a scene object destroying it after the scene is left+**Scene.LoadActor(actor filename);** - Charge un acteur d'un fichier et l'attache à un objet scène se détruisant après avoir quitter la scène
-**Game.MainObject = actor;** Sets the actor to whom the scene scrolling is synchronized+**Game.MainObject = actor;** Défini vers quel acteur le défilement de la scène est synchronisé
-**Game.ActiveObject;** - stores the reference to an object your mouse cursor is currently over+**Game.ActiveObject;** - Stocke la reference de l'objet au dessus duquel votre souris se trouve
-**Game.ApplyEvent(eventName);** - is a method which fires the event associated to the Game object +**Game.ApplyEvent(eventName);** - c'est une méthode qui déclenche les événements associés à l'objet Game. 
-**Scene.ApplyEvent(eventName);** - is a method which fires the event associated to the Scene object +**Scene.ApplyEvent(eventName);** - C'est une méthode qui déclenche les événements associés à un objet scène. 
-**Node.ApplyEvent(eventName);** - is a method which fires the event associated to the node stored in the object in question.+**Node.ApplyEvent(eventName);** - C'est une méthode qui déclenche les événements associés au nœud (entité) stocké dans l'objet en question.
-For better understanding the last command, we could easily run in our last chapter the “LeftClick” event of the door elsewhere like this:+Pour mieux comprendre la dernière commande, nous pourrions facilement nous précipiter dans notre dernier chapitre à l’événement “LeftClick” de notre porte qui était comme ceci:
<code script> <code script>
Line 143: Line 147:
</code> </code>
-I hope you got my point now... Let’s also look if you have the same *game.script* file as I do before we proceed:+J'espère que vous voyez ce que je veux dire maintenant ... Examinons maintenant si vous avez le même fichier **game.script** que j'ai fait avant que nous commencions:
<code script> <code script>
Line 215: Line 219:
</code> </code>
-Now test the game and you’ll see that it’s still running although we made quite some changes to it. And as we want to continue boiling our example game down to the necessary minimum, we need to look at the **game_loop.script** (formerly named game_daemon.script) as well.+Maintenant testons le jeu et regardons s'il fonctionne encore vu que nous avons fait quelques changement. Et comme nous voulons continuer à epuré notre jeu au strict minimum, nous devons voir dans **game_loop.script** (Ancienement nommé game_daemon.script)
<code script> <code script>
Line 224: Line 228:
</code> </code>
-We can easily delete the line **global WinMenu;** because we’ve already dropped the idea of right click menu.+Nous pouvons tranquillement effacer la ligne **global WinMenu;** parce que nous avons déjà abandonné l'idée de menu clic droit.
<code script> <code script>
Line 230: Line 234:
</code> </code>
-This will be always true. This way we are looking at the infinite loop. To end this loop, one would have to call //Game.DetachScript("scripts\game_loop.script");//+Ça sera toujours vrai. avec ça nous envisageons une boucle sans fin. Pour clore cette boucle, on aurait pu faire appel //Game.DetachScript("scripts\game_loop.script");//
<code script> <code script>
var ActObj = Game.ActiveObject; var ActObj = Game.ActiveObject;
</code> </code>
-We’ve seen exactly the same line before in the game script.+Nous avons vu exactement la même ligne dans le game script
<code script> <code script>
Line 242: Line 246:
</code> </code>
-So first we test if the game is interactive and our mouse cursor is over some active object. But we’ll make this condition a bit simpler so we’ll put away all inventory items logic and it’ll look like this:+D'abord on test si le jeu est interactif et que notre souris est au dessus d'un objet actif. Mais nous allons rendre cette condition un peu plus simple, donc nous allons mettre de côté toute logique d'inventaire d'éléments et ça va ressembler à ceci:
<code script> <code script>
Line 262: Line 266:
</code> </code>
-So what happens if we have our mouse over the object?+Du coup que ce passe t'il si on a notre souris au dessus l'objet?
<code script> <code script>
Line 269: Line 273:
</code> </code>
-WinCaption contains the reference to the text field inside of the caption window loaded in the game script. We set its position to the same coordinates as our mouse X-position and Mouse Y-position + 20 so it’ll be 20 pixels below.+WinCaption contient les références au champs de texte à l'intérieur de la fenêtre des légendes chargés dans le script du jeu. Nous avons fixé sa position aux mêmes coordonnées que la position en X de la souris et la position en Y de la souris + 20 donc la légende sera 20 pixels en-dessous.
<code script> <code script>
Line 276: Line 280:
</code> </code>
-Then we set text aligning to left and set the text of the caption to the node caption as defined in the scene editor.+Ensuite, nous avons défini l'alignement du texte à gauche et mis le texte de la légende dans le nœud légende (node caption) comme défini dans l'éditeur de scène.
<code script> <code script>
Line 282: Line 286:
</code> </code>
-We resize the caption so its size is the same as the size of the displayed text.+Nous redimensionnons la légende pour que sa taille soit la même que la taille du texte affiché.
<code script> <code script>
Line 288: Line 292:
</code> </code>
-If the caption width however extends out of the screen, we set our caption X-position to end exactly with the screen border (based on the resolution).+Si la largeur de légendes s'étend toutefois hors de l'écran, nous avons réglé notre position X de la légende pour finir exactement à la frontière de l'écran (basé sur la résolution).
<code script> <code script>
Line 294: Line 298:
</code> </code>
-We do the same with the height and the bottom border.+Nous faisons pareil  avec la hauteur et la bas de l’écran.
<code script> <code script>
Line 301: Line 305:
</code> </code>
-We display our caption by making it visible and give it focus, which is in this case not necessary, because we don’t interact with it. So we can simply delete this line too.+Nous affichons notre légende en la rendant visible et la mettre en évidence, ce qui est dans ce cas pas nécessaire, parce que nous n’interagissons pas avec elle. Donc on peut simplement effacé cette ligne aussi.
<code script> <code script>
Line 308: Line 312:
</code> </code>
-The rest means that either the game went into non interactive mode or we moved our mouse out of any active hotspots. In both cases we simply hide the caption.+Le reste signifie soit que le jeu est passé en mode non-interactif ou soit nous avons déplacé notre souris hors de tout hot-spots actifs. Dans les deux cas nous avons tout simplement cacher la légende.
<code script> <code script>
Line 315: Line 319:
</code> </code>
-Those two lines deal with inventory showing / disappearing and so we simply delete them.+Ces deux ligne concerne l'apparition/disparition de l'inventaire et on peut donc les effacer.
<code script> <code script>
Line 321: Line 325:
</code> </code>
-Remember what I’ve told you about infinite loops and hanging computers? Enough said+Souvenez vous ce que j'ai dis au sujet des boucles sans fin et les blocages d'ordinateur? j'en ai assez dit
-So let’s look at our revised **game_daemon.script**+Alors regardons notre **game_daemon.script** révisé.
<code script> <code script>
Line 349: Line 353:
</code> </code>
-As you can see, those are the barebones of our starting project. No inventory, no menus, simple point and click game. Moreover you understand now, what’s the brain behind the game and as we build upon it, you’ll feel more comfortable knowing that you have the rock solid background. Next step: **the actor!**+Comme vous pouvez le voir, c'est l’épure de notre projet de départ. Pas d'inventaire, pas de menus, un simple jeu Point and Click. En outre, vous comprenez maintenant, qu'est qui supervise derrière le jeu et comme nous bâtirons sur elle, vous vous sentirez plus à l'aise en sachant que vous avez une base solide comme la roche. Prochaine étape: **les acteurs!**
 
fr/wmebook/ch4.1319024499.txt.gz · Last modified: 2011/10/19 13:41 by Anto0085
Recent changes RSS feed Creative Commons License Driven by DokuWiki