Voir la version complète : Mise à jours de scripts actifs
peroxyde
09/07/2010, 14h59
Tient une question pour Serial (enfin en tout cas je m'en réfère à mon maître:Respect:)
Pour une mise à jour de script... comment qu'on fait? ^^
Parce que un script qui tourne en boucle à un task id que je n'arrive jamais à savoir à l'avance et je ne sais jamais lequel attribuer (je me souviens plus vraiment des commandes que j'avais regardé)
Pour l'instant le seul moyen que j'ai de savoir si un script tourne ou non c'est d'attribuer une variable globale.
Elle me permet de lancer le script si elle est nulle (et de passer sa valeur à "script actif") et dans certain cas de faire tourner le script tant qu'elle n'est pas nulle. Mais c'est un peu lourd comme procédé je me demandais comment vous faisiez pour cibler un script et le réinitialiser avec la nouvelle version.
Je suis tout ouïe pour un petit cours là dessus maître!
Serial Kicked
11/07/2010, 03h55
Rahhh, la question :)
(le pire c'est que j'ai vraiment cherché longuement)
Bon alors, deux choses:
Avoir un script qui tourne en boucle sur rien, c'est mal, très mal ! Si, si ! Enfin, pas tant que ça en fait, mais ce n'est pas très propre quand on sait qu'Egosoft nous a donné les outils pour celà. Les Plugins AL pour être plus précis, qui ont la particularité que tu puisse définir un script qui est rappelé toutes X secondes/minutes/heures. Comme le script est rappelé au lieu de boucler il reste toujours à jour. Par contre je ne vais pas te faire un long tutorial là dessus, vu qu'il en existe un datant de X2 (http://forum.egosoft.com/viewtopic.php?t=55155) (en anglais) et qui marche toujours de nos jours. Khaak Patrols est un plugin AL relativement simple, tu peux jeter un oeil aux fichiers al.plugin.sk.khaak et anarkis.khaak.al.*
Bon évidemment je ne te vois pas recommencer pour si peu. :grin:
Tu utilises la seule méthode valable pour tuer une task globale (c'est pour ça qu'on évite de s'en servir), Il y a bien un "Get PID" mais pas de "Kill PID" comme commande donc c'est inutile.
Pour ta methode sans plugin AL, je te conseillerai de stocker ton numero de version dans un fichier de langue, de façon à pouvoir le récuperer depuis le setup
<t id=101>100</t> et pas <t id=101>1.00</t>
dans le dit fichier de langue, qu'on puisse le convertir en chiffre.
Comme ça dans ton fichier de setup tu peux faire quelque chose comme ça:
$current.ver = read text: page=$PageID id=101 // j'assume que ton numero de version est stocké ici
$current.ver = string $ver to integer
$running.ver = get global variable: name='peroxyde.annonce.version'
If $running.ver = null
| // Tu lances ton script qui boucle, vu que c'est une nouvelle install. //
else $running.ver < $current.ver
| set global variable: name='peroxyde.annonce.reset' value=[TRUE]
| while get global variable: name='peroxyde.annonce.reset'
| | =wait 100ms (on attend que ton script rende la main)
| end
| // Tu relances ici ton script qui boucle, il sera mis à jour //
end
set global variable: name='peroxyde.annonce.version' value=$current.ver
ton global script qui loop:
while not get global variable: name='peroxyde.annonce.reset'
| ...
| tes instructions habituelles
| ...
end
set global variable: name='peroxyde.annonce.reset' value=nullEdit : pas oublier d'incrémenter le numero dans ton fichier de langue à chaque update, et de *charger* le dit fichier de langue avant le code que j'ai tapé.
Serial Kicked
11/07/2010, 04h15
La methode précédente à l'avantage de gérer un peu mieux ce qui se passe, mais vu la teneur de ton script, je doute qu'il en ai besoin. Donc voici une version vachement simplifiée:
Script d'appel:
While $Script.Actif
| = call script 'main.script'
| = wait 1000 ms
end
Avec "main.script" qui contient tout ce qui devait être dans ta boucle auparavant à part le "wait" final qu'il vaut mieux mettre dans le script d'appel. Ca mettra ton script à jour automatiquement, mais ce n'est pas forcement mieux que l'autre méthode s'il y a beaucoup de choses à reset à chaque mise à jour de ton script.
peroxyde
11/07/2010, 04h30
Mmm. Pas bête. Ça va sûrement me servir pour Annonces. heureusement pour ce script, j'ai qu'un global script Loopant (GSL on va dire)
En fait je posait la question pour l'autre très gros script qui n'est pas prévu pour NH (trop long, je savais dès le début que j'aurais pas le temps) à savoir RéSISTE.
Car si j'applique un script sur un ennemi il perd son ordre en court ce que je ne veux pas.
Du coup dans résiste j'ai autant de script globaux que d'ennemis repérés. Autant dire que si je me ballade en zone ennemie, j'ai une foule de GSL qui tournent.
C'est toujours le même mais une instance par ennemi. Sachant que j'ai la même chose pour chaque propriété du joueur, c'est un b¤rdel (sal¤perie de masque) monstre. Alors pour mettre à jour les instances qui tournent je te laisse imaginer...
Je vais me renseigner du coup voir comment fonctionnent les AL, si ça peux me sauver.
Sinon en utilisant le même principe avant de s'arrêter les vaisseaux s'insèrent dans une liste qui après mise à jour sera lancée le script... moui ça doit être faisable en cas de coup dur.
Serial Kicked
11/07/2010, 04h58
Nope, on ne fait pas comme ça. C'est un coup à tuer le moteur du jeu ça. Un script global par plugin c'est déjà trop.
Fais tourner tes tâches (c'est le nom que ça porte, pas GSL :wink:) sur les objets concernés comme ceci:
$navire -> Start task $id with script "nom de ton script" and prio 0 arg1=...
où:
$navire est le vaisseau sur lequel lancer le script
$id est la un numéro élevé genre au dessus de 500 c'est bien. 0 est utilisé pour le script principal (attack all, dock at, etc.), 1-10 pour les ordres de tourelles. C'est le "slot" on va dire dans lequel va tourner ton script. J'ai réservé officiellement les numéro 890-900. Certains autres scripteurs ont fait de même. Y a aussi une commande pour trouver une tache libre.
la prio, tu vas la laisser à zero et devrait jamais trop à t'en préoccuper. Le jour où tu voudras interrompre un script par un autre puis que le premier reprenne la main pour la task 0 t'en auras besoin. pas avant. Mais faudra te taper le MSCI handbook par coeur avant de commencer à faire ce genre de choses :):grin:
arg1, arg2... sont les arguments pour ton script, si ta tâche est appelée sans argument, tu les laisse à null.
peroxyde
11/07/2010, 07h04
houlà... bon je vais revenir dessus demain parce que là va falloir que j'aille dormir...
Je n'arrive quasiment plus à lire!
Les taches peuvent s'exécuter en parallèle sur un même objet?
Parcequ'avec $ship ->start script, le vaisseau arrête sa commande en cours. C'est là mon soucis. Je veux pas qu'un commerçant arrête de commercer pour jeter un œil sur son radar ni qu'un ennemi arrête son chemin.
J'avais déjà repéré les task mais justement comment savoir quel id attribuer? Si tu dis qu'il y a une commande, taing j'ai jamais vu:shock:
J'ai réservé officiellement les numéro 890-900.
heu... On peux mettre plusieurs task du même numéro? Parceque je suis rapidement monté à 50 ennemis dans la bdd.
Ça peux monter jusqu'à combien?
Ou ça fonctionne comme les commandes additionnelles des vaisseaux et stations (le "slot", sauf que c'est pas visible pour le joueur)?
La prio, tu vas la laisser à zero et devrait jamais trop à t'en préoccuper. Le jour où tu voudras interrompre un script par un autre puis que le premier reprenne la main pour la task 0 t'en auras besoin. pas avant. Mais faudra te taper le MSCI handbook par coeur avant de commencer à faire ce genre de choses
Booh... Je:arrow::parking_boulets: J'en ai eu besoin à une époque ou j'essayais de refaire le calcul du trajet des ts qui s'obstinait à passer à travers les secteurs xenon en les utilisant comme raccourcis. J'essayais avec la priorité des scripts mais si j'avais sû que ça se faisait avec les tasks...
Comme je voyais Global script task et que mes scripts globaux avait un pid que je n'avais jamais fixé moi même je pensais que script et task étaient la même chose.
Nope, on ne fait pas comme ça. C'est un coup à tuer le moteur du jeu ça
La vache, l'est résistant mon pc! Pas un ralentissement quand même!
Ah je sais je vais être chiant mais tant que j'y suis: Je sais qu'un script lancé sur un objet n'apparaît pas dans le menu Global Script task (sûrement dû au "Global" avec ce que j'apprends.) Ce qui est particulièrement chiant car j'adore pouvoir faire un simple [Suppr] pour tuer le script en cours.
J'immagine que la task n'y apparaît pas et queje ne peux pas tuer une tache aussi simplement?
Je te remercie encore, C'est plus simple expliqué ainsi que une simple ligne de description dans un listing des commande sur un post du forum ES.
[edit]Ah mince, je peux pas de nouveau te mettre de point de reput'. Dommage ça m'a éclairci vraiment! Dès que je pourrais!
Serial Kicked
11/07/2010, 09h29
Bon, reprenons.
Tu vas lire tout ça calmement, à tête reposée, quand tu auras bien dormi, et que tu seras motivé. Ce sont des bases plus ou moins indispensables si on veut scripter quoique ce soit en rapport avec les vaisseaux et stations. Y a pas le choix faut le savoir, sinon on fait des bêtises (la preuve). Merci de tout lire en entier avant de poser les questions :wink:
(les autres vous pouvez le remercier, la release sera pour demain j'ai mal au crane maintenant :biggreen:)
D'abord
Ce que tu fais n'est pas plus lent. C'est juste incontrôlable (en plus ça empêche les utilisateurs de tuer des taches globales spécifique manuellement à cause du b0rdel que tu rajoutes dans le menu "global script tasks"). Certes, tu peux faire du code bizarre et spawner des centaines de taches globales. Et ça pourrait même marcher. Mais il n'en reste pas moins que le code est malpropre (et que si un scripteur, voir même un utilisateur qui s'y connait t'attrape avec ça il va t "engueuler", c'est rare mais ça arrive). Pour faire un parallèle, dans beaucoup de langages de programmation il reste encore l'antique commande "GoTo" du vieux BASIC, ce n'est pour ça que que les programmeurs l'utilisent encore :grin:
De plus la méthode que je présente plus bas a plein plein d'avantages.
Avant toute choses, tu vas me faire plaisir. Tu lances X3, mode fenêtré, tu ouvres l'éditeur de script:
Script Debugging: Additional Information" -> ON
Tu fermes l'éditeur. Va te promener prés d'un gros vaisseau M1 ou M2. Sélectionne le, presse pour voir ses information, scroll tout en bas jusqu'à ce que tu tombes sur un onglet appelé Script Task Info. Wahou voici la liste de tout ce qui tourne sur le dit carrier. Ca devrait déjà t'aider à te faire une meilleure idée.
Un vaisseau peut tourner tout un tas de tâches simultanément. Chaque tache est identifiée par un numéro.
Tâche 0 : Commande principale d'un vaisseau (Dock At, Attack All, etc etc)
Tâches 1 à 9 : Ordres des tourelles du vaisseau
Tâches 10 et 11 : Commandes additionnelles (ADS: Automated Carrier)
12 à 100 sont réservés par Egosoft
Tâche = Task = Slot
(à ce sujet, oublie le mot slot. C'est ce que disent les joueurs, pas les scripteurs).
Tout cela tourne en simultané
(enfin pas exactement mais pour toi et les autres ça ne fait pas de différence).
Quand tu fais un $navire -> Call Script et que tu ne lances pas cette commande depuis le vaisseau en question (par exemple dans ton setup) le moteur assume que tu veux remplacer l'ordre courant du vaisseau. En conséquence, il remplace la tâche 0 par ton nouveau script. Et ce n'est pas ce que tu veux ici.
Quand on veut créer une nouvelle tache pour un vaisseau, on utilise la commande que je viens de décrire et que tu as mal lu. C'est à dire:
$navire -> Start [U]task $id with script "nom de ton script" and prio 0 arg1=...
Exemple:
$navire -> Start task 900 with script "anarkis.khaak.task.radar" and prio 0 arg1=null arg2=null arg3=null arg4=null
Le $navire a maintenant une tache numéroté 900 correspondant à mon script anarkis.khaak.radar. Voici un contenu résumé de celui ci en pseudo code et qui va aider à expliquer la suite:
01 while get global variable: name="anarkis.khaak.plugin"
02 | $danger = [THIS] -> call script "recherche de navire adverse dangereux à portée"
03 | if $danger
04 | | [THIS] -> interrupt task 0 with script "saut vers un endroit sûr" and prio 200
05 | end
06 | = wait 1000 ms
07 | if [OWNER] != Kha'aK
08 | | return null
09 | end
10 endAvant d'en venir au contenu à ce qui te fait te gratter la tête sache que comme le script tourne sur le vaisseau, tu peux maintenant te servir des valeurs suivantes:
[THIS] = le vaisseau.
[SECTOR] = le secteur actuel du vaisseau
[OWNER] = la race du vaisseau
[HOMEBASE] = vaisseau mère (null si aucun)
[ENVIRONMENT] = [SECTOR] si undocké sinon c'est la station/carrier auquel il est arrimé.
Alors j'imagine que tu vas me dire que la ligne 02 va interrompre ce qu'était en train de faire le vaisseau dans sa tache 0. En fait ce n'est pas le cas ici. Quand tu fais un "= [THIS] -> call script" depuis une tache, le jeu va faire tourner le script comme une sous routine de la tache en cours.
Passons à la ligne 04 qui va me servir à expliquer brièvement la priorité et deux trois autres détails. Il faut savoir qu'il est fortement déconseillé (lire interdit à votre niveau) de donner des ordres de déplacement / attaque / whatever depuis une autre tache que la task 0. Du coups, les concepteurs ont mis en place un système de priorité. (le prio que j'ai voulu eviter tout à l'heure, mais tu l'as cherché) et la possibilité d'interrompre un script par un autre. C'est ce que fait la commande interrupt task ici.
Dans le cas présent j’interromps la tâche principale (task 0) du vaisseau (patrouille de secteur en secteur) par un script de saut vers un secteur plus sécurisé. Une fois le saut terminé la tâche principale reprendra son travail.
Passons maintenant à la priorité. Tu as demandé, tu vas être servi. :biggreen:
Donc, chaque tache à une priorité, cette valeur sert à déterminer si la fonction "interrupt task" marchera bel et bien ou pas. On ne peut interrompre une task que par une autre ayant une priorité égale ou supérieure. Ce n'est d'habitude pas un problème parce que les tasks ont une priorité de 0 de toute façon. Alors pourquoi j'ai fichu 200 dans mon exemple ?
Parce qu'il y a des cas particuliers.
Quand un vaisseau est attaqué, un script spécial nommé SIGNAL_ATTACKED est appelé et il va interrompre la tâche 0 du vaisseau par un script de combat ayant une priorité de 100.
Comme je veux que mon vaisseau jump à l'abris même quand il est attaqué (surtout quand il est attaqué, même) j'utilise une priorité de 200 comme ça je suis certain d'interrompre le script de combat et de faire mon saut. Si j'avais mis 0 ou 10 il n'aurait pu sauter que lorsqu'il n'est pas en train de se défendre.
Pourquoi je n'ai pas foutu 5000 ou un million comme priorité alors ?
A cause des deux autres cas spéciaux, la capture et la mort. Quand un vaisseau est capturé, la tache 0 est interrompue (puis tuée) par le SIGNAL_CAPTURED, celui ci a une priorité de 300.
Comme je ne veux pas que mon vaisseau maintenant réduit à l'état d'épave saute de secteur en secteur il faut que ma priorité soit en dessous de 300. (c'est aussi la raison pour laquelle je vérifie le [owner] dans les dernières lignes)
Le dernier cas à connaitre est le SIGNAL_KILLED, pareil il interrompt et tue la tache 0 avec un script de priorité 10.000. Pareil, si j'avais mis un priorité de 500.000 ca aurait signifié que le vaisseau était invincible pendant son saut (ce qui aurait donné un vaisseau qui fini son jump avec 0 hull et qui refuse de mourir).
C'est le plus clair que je puisse faire pour les priorités. Et comme je te dis à moins de te mettre à tuner l'IA des vaisseau tu n'en as vraiment pas besoin.
Autre choses à savoir:
Quand le vaisseau meurt, la tache meurt avec lui sans que t'ai besoin de rajouter des lignes inutiles.
N'utilises JAMAIS l'option START call script quand tu donne un ordre à un vaisseau depuis ce même vaisseau. C'est utilisé pour donner des autres à d'autres objets, pas à celui sur lequel tu tournes.
Je sais qu'un script lancé sur un objet n'apparaît pas dans le menu Global Script task (sûrement dû au "Global" avec ce que j'apprends.) Ce qui est particulièrement chiant car j'adore pouvoir faire un simple [Suppr] pour tuer le script en cours. J'immagine que la task n'y apparaît pas et queje ne peux pas tuer une tache aussi simplement?Comme son nom l'indique il liste les tasks globales, pas les locales. C'est peut être chiant, mais je ne pense pas que tu comptes faire faire la même chose à tes utilisateurs quand ton script patine dans la semoule pour une raison X ou Y ?
Les task locales tu peux les tuer de mille et une façon.
Tu peux faire un check pour une variable locale ou globale dans ta boucle.
Tu peux créer un script vide que tu utilisera pour tuer tes taches de cette façon:
$navire -> Start task $id with script "peroxide.cmd.empty" and prio 0 arg1=...
Dernière chose, il est sensé faire quoi ton script ? En particuliers ces centaines de tasks globales que tu lances partout ? Parce qu'il y a probablement bien plus simple. Et j'aurais probablement pu me passer de toutes ces explications, trop tard now :grin:
Maintenant si tu as des questions, ne te gènes pas pour me les poser.
note: T'inquiète pour les points de "réputation", je n'en ai rien à cirer :grin:
peroxyde
11/07/2010, 16h38
Hallelujah! ♫ Hallelujah! ♪
J'ai du mal à trouver les mots justes mais tu peux pas savoir à quel point toutes tes explications sont appréciées et... pfiou! illumine soudain mon ciel de scripteur!
:merci:
J'étais encore loin en disant que t'avais été un modèle pour mon apprentissage!
A l'image de notre chêne et de notre roseau, je suis votre padawan! :Respect:
Tu vas lire tout ça calmement, à tête reposée, quand tu auras bien dormi, et que tu seras motivé. Ce sont des bases plus ou moins indispensables si on veut scripter quoique ce soit en rapport avec les vaisseaux et stations. Y a pas le choix faut le savoir, sinon on fait des bêtises (la preuve). Merci de tout lire en entier avant de poser les questions :wink:
Tout ce que vous voudrez Maître :biggreen:
Pour faire un parallèle, dans beaucoup de langages de programmation il reste encore l'antique commande "GoTo" du vieux BASIC, ce n'est pour ça que que les programmeurs l'utilisent encore :grin:
Ah Merdouille j'aime bien le goto et le gosub....
Avant toute choses, tu vas me faire plaisir Oui maître! :Respect:
Un vaisseau peut tourner tout un tas de tâches simultanément. [...](enfin pas exactement mais pour toi et les autres ça ne fait pas de différence).
Ah c'est donc bien ce que je voulais.
Et oui je sais qu'X3 est monocore (enfin je sais pas si ça a un rapport lol), et qu'il n'exécute un autre script que pendant les waits du script en cours. En fait, je croyais que les prio servait à choisir quels autres scripts faire tourner en attendant. En fait ça à rien à voir.
Tu peux maintenant te servir des valeurs suivantes:
[THIS] = le vaisseau.
[SECTOR] = le secteur actuel du vaisseau
[OWNER] = la race du vaisseau
[HOMEBASE] = vaisseau mère (null si aucun)
[ENVIRONMENT] = [SECTOR] si undocké sinon c'est la station/carrier auquel il est arrimé.
Oui je connais et j'avais déjà utilisé, mais comme il faut que le script tourne sur l'objet, j'en avais laissé tombé l'utilisation (sauf cas rare) par contre [ENVIRONMENT] :shock: ça va être utile! Même pour Annonce! Parce que là (par exemple) pour savoir sur quelle station est arrimé le joueur je fais:
$sector <- [playership] get sector
$StationArray <- get station array from $sector
$SizeArray <- size of array $StationArray
$Inc=0
While $Inc<$SizeArray
| $Stationtest <- $StationArray[$Inc]
| $ShipArray <- get shiparray from station/ship/truc
| $SizeArray2 <-size of array $ShipArray
| Inc2=0
| While Inc2 < $SizeArray2
| $Shiptest <- $ShipArray[$Inc]
| Skip if $Shiptest != $playership
| | GoTo : suite
| inc= $Inc2
| end
inc= $Inc
end
suite:
...
lol2 Tu m'étonnes que j'en suis à près de 1200 lignes de code...
C'est peut être chiant, mais je ne pense pas que tu comptes faire faire la même chose à tes utilisateurs quand ton script patine dans la semoule pour une raison X ou Y?
Non bien sûr, mais quand en cours de développement tu as des versions différentes d'un vaisseau à un autre c'est ultra chiant. Pouvoir tuer le script sans avoir à recharger une partie pour qu'il se mette à jour c'est quand même beaucoup plus rapide (et de loin)
Tu peux créer un script vide que tu utiliseras pour tuer tes taches de cette façon:
$navire -> Start task $id with script "peroxyde.cmd.empty" and prio 0 arg1=...
Ouh ça c'est beau! Je vais faire même mieux, je vais en faire un outil, pour sûr! (Prompt:vaisseau? tache? Kill!:akimbo:)
Dernière chose, il est sensé faire quoi ton script ? En particuliers ces centaines de tasks globales que tu lances partout ? Parce qu'il y a probablement bien plus simple. Et j'aurais probablement pu me passer de toutes ces explications, trop tard now :grin:
Oh non pas trop tard! C'est exactement ce qui m'intéressait. J'aurais un gros remaniement à faire parce que j'ai beaucoup avancé dans ce script (même si je suis loin de la fin je dirais au premier quart) mais ça va m'être très utile.
RéSISTE fonctionne ainsi:
Toute propriété du joueur transmet au joueur (selon ses critères (audio et/ou soustitres et/ou journal ou... rien) toutes les rencontres ennemies existante.
Donc sur chaques propriétés du joueur tourne le script "Surveillance"
Les résultats renvoyés par le script dépendent de la propriété sur laquelle il tourne (sat, station ou vaisseau), ses équipements du vaisseau si c'en est un, et du secteur dans laquelle se trouve la propriété (secteur défini comme Core par le joueur ou secteur standard)
Chaque ennemi repéré (rentrant dans le radar d'une propriété) est tagué, entré dans une base de donnée (bdd) et se voie affublé d'un script "Mise à Jour". (un simple chrono)
Le tag, évite qu'un même ennemi repéré par plusieurs propriétés ne soit rapporté au joueur autant de fois qu'il y a de propriétés impliquées.
Toute les (je sais plus) 30 secondes, si l'ennemi est toujours dans le radar de la propriété, la propriété remet le chrono de l'ennemi à 0.
Une fois hors radar, selon un temps paramétrable par le joueur, l'ennemi reste un temps dans les "archives" de la base de données. C'est le script "MaJ" de l'ennemi qui change le statut de l'entrée dans la Bdd.
Au delà d'un second temps paramétrable, le script "MàJ" supprime l'entrée de la Bdd et s'arrête : l'ennemi a définitivement été perdu de vue et à été oublié
Tient d'ailleurs ça me fait penser que du coup la task ici ne me conviens pas, parce que pour le background, si l'ennemi est détruit hors radar, il faut qu'il puisse rester dans la base de donnée jusqu'au terme du second temps. Si je change pour passer au task il va falloir trouver une astuce, genre l'inscrire dans une bdd secondaire gérée par un script qui tournera où lui? en global? (non non j'ai rien dit j'ai rien dit, me suis trompé maitre, je vais trouver... plus tard) mhmmm le serpent se mord la queue...
Rhâa plus je me relis plus y'a des trucs qui me chiffonnent : la task "maj" n'aura pas le temps de mettre à jour la Bdd même si l'ennemi se fait détruire à vue, puisque justement il se sera fait détruire! A moins de mettre une prio supérieur au kill? (non je déconne pas taper, j'arrête!)
bon faut que je termine Annonces, je réfléchirais à ce script plus tard.
La Bdd n'est consultable qu'une fois une station/vaisseau capital du joueur à été défini comme centre de crise.
4 pages disponibles:
- Ennemis visible en secteur standards
- ennemis récemment vu en secteur standard
- ennemis visible en secteur Core
- ennemis récemment vu en secteur Core
Les ennemis y sont triés par secteurs:
http://img21.imageshack.us/img21/9433/yeahdt.th.jpg (http://img21.imageshack.us/i/yeahdt.jpg/)
Maintenant si tu as des questions, ne te gènes pas pour me les poser.
Si tu m'y invites j'y manquerais pas!
Serial Kicked
12/07/2010, 01h52
Pas de problème :smile:
Ah Merdouille j'aime bien le goto et le gosub....Gosub a son utilité. Goto est en général un problème de mauvais design dans ton code à de rares exceptions, le plus souvent parce que tu (enfin, vous) ne sais pas utiliser break et continue. Je vais reprendre l'exemple du code que t'as posté pour te donner un exemple. Ce qui n'empeche pas qu'utiliser [ENVIRONMENT] ou $ship -> get environment est la solution d'une seule ligne qui marche le mieux, hin.
Voici comment, si environment n'existait pas, tu aurais pu taper la chose:
$sector <- [playership] get sector
$StationArray <- get station array from $sector
$SizeArray <- size of array $StationArray
$PlayerInStation = null
While $SizeArray
| dec($SizeArray)
| $Stationtest <- $StationArray[$Inc]
| $ShipArray <- get shiparray from station/ship/truc
| if find [PLAYERSHIP] in array: $ShipArray
| | $IsPlayerInStation := $StationTest
| | break
| end
end
Une fois la boucle parcourue, PlayerInStation sera null s'il est en vol, et correspondra à la station à laquelle il est arrimé sinon.
3 choses ici.
1) Pour parcourir un array de station, ship ou n'importe quoi, c'est plus rapide de
réduire la valeur utilisée pour récupérer la taille de cet array à chaque itération, ca fait une commande et une variable de moins, et ça t'évite d'oublier d'initialiser ton compteur (ce qui résulterait dans une boucle infinie / plantage).
2) Pour rechercher une valeur précise dans un array, y a depuis TC la merveilleuse fonction "find xxx in array:", ici ça t'évite d'avoir à faire une seconde loop dans dans la première. Le gain de vitesse est énorme (même si pour de si petites boucles ça ne se remarque pas forcément), et les possibilités de se planter réduites.
3) Et last but not least, pour sortir de la boucle une fois qu'on a trouvé ce que l'on veut, il y la commande break, plus propre que du goto. Le break, te fais sortir de la boucle en cours. Note que s'il y avait eu deux boucles imbriquées comme dans ton exemple, break ne t'aurait fait sortir que de la seconde. (ça te "remonte" d'un niveau pourrait on dire). Pour information, Le copinou de break est continue. Celui ci ne te fait pas quitter la boucle, mais fait te fait sauter toutes les instructions qui suivent et te fait passer donc à la prochaine itération, exemple:
$array = all my ships
$cnt = size of $array
while $cnt
| dec $cnt
| $ship = $array[$cnt]
| if $ship est un vilain pas beau que je veux pas traiter
| | continue
| end
| $ship -> changer ce que je veux sur les autres navires
end
Ce sont de bonnes habitudes à prendre, non seulement ton code est beaucoup plus rapide, il est plus vite tapé, et surtout il te laisse beaucoup moins de place pour faire des erreurs d'étourderie (initialiser tes compteurs à zero est l'exemple le plus flagrant ici) toujours chiantes à repérer.
Passons à ton script now. Ne va pas tout te retaper pour ce que je vais raconter, je ne fais que te donner quelques pistes que tu peux suivre ou pas.
Une fois hors radar, selon un temps paramétrable par le joueur, l'ennemi reste un temps dans les "archives" de la base de données. C'est le script "MaJ" de l'ennemi qui change le statut de l'entrée dans la Bdd.Ton script présente une difficulté, c'est que tu veux conserver les informations sur les vaisseaux après leur mort. C'est faisable mais ça demande pas mal de grattage de crâne. Je reviendrai dessus après.
Je vais assumer que ta BDD est un array stocké dans une globale variable dont chaque case porte sur un vaisseau repéré. Si c'est pas ça, bah tant pis :p
Tout d'abord tu n'as pas besoin de taguer les méchants, suffit d'utiliser le find in array de tout à l'heure pour retrouver s'ils sont dans la BDD.
Par exemple dans le radar qui tourne sur tes vaisseau:
$flags = [Find.Enemy] | [Find.Multiple]
maxdist=30000 ...
$BDD = get global variable: name='my.bdd'
While "plugin est actif"
| $array = find ship in sector=[sector], flags=$flags, $refobject=[THIS], max=100, $range=50000 ...
| $cnt = size of $array
| while $cnt
| | dec($cnt)
| | $select = $array[$cnt]
| | if not find $select in array: $BDD
| | | Append $select to $BDD
| | end
| | $select -> Start Task 1000 with script "peroxyde.task.compteur" prio=0 ...
| end
| = wait (1000)
end
Donc il va parcourir tout les vaisseaux méchants à portée de l'object sur lequel ça tourne, s'il ne trouve pas la chose dans la BDD il l'ajoute. Et dans le 2 cas il relance ta tache compteur sur le vaisseau en question, ce qui aura pour effet de le remettre à zéro.
Le compteur tournant sur les méchants, je vais supposer qu'il enlève les vaisseaux de la base de données au bout d'1 heure:
peroxyde.task.compteur
$current.time = playingtime
$end.time = $current.time + ( 60 * 60 )
while $current.time < $end.time
| =wait 5000 ms
| $current.time = playingtime
end
$BDD = get global variable: name="My.BDD"
index = get index of [THIS] in array $BDD offset= -1 + 1
remove element from array $BDD at index $index
Voilà ca c'est qui tient à jour ta base de donnée. Ca ne regle pas le problème des décès par contre. Là je ne peux que te donner une astuce et te laisser jouer un peu avec les commandes.
L'idée est d'avoir non seulement la première BDD qui contient donc le "pointeur" vers chaque vaisseau (ce qui te permet de recupérer les informations dynamiquement pour chaque navire tant qu'il est vivant). Et d'en avoir une seconde qui contient directement du texte. C'est ici qu'une et une seule tache globale peut avoir son utilité.
Je m'explique, cette tache globale, va tenir à jour un autre array BDD.Texte, de la même taille que le premier, en gros de cette façon:
While $cnt
| $select = $BDD[$cnt]
| if $select exists
| | $sector = $select -> get sector
| | $description = String fmt = "Nom: %s - Secteur: %s", $select, $sector,..
| | $BDD.Text[$cnt] = $description
| end
end
Comme ça si le vaisseau est mort, quand c'est le moment d'afficher le menu, pouf, tu peux te rabattre sur BDD.Text et afficher sa dernière mise à jour.
Tu pourrais même te passer de taper ce code dans une task globale et l'inscrire directement dans le compteur du vaisseau en question, ca rendrait le code encore plus court.
Voilou, bon courage :biggreen:
A moins de mettre une prio supérieur au kill? (non je déconne pas taper, j'arrête!)Bien! Tu t'es rendu compte sans que j'insiste dessus lourdement que c'est la dernière chose à faire. :smile:
:)
peroxyde
12/07/2010, 03h14
En fait effectivement la bdd est une variable globale. C'est une Array d'array. Un tableau donc. Du style bdd[ ship1{nom; immatriculation;secteur;cible;temps, autre variable}; ship2...]
L'avantage par rapport à 2 tableau, c'est que c'est plus facile pour mes neurones "visuellement" pour classer les données dans le tableau.
Le nom : ben pour le nom mais après traitement car il faut que ça passe dans les colonnes d'affichage de compte rendu (coupure du mot et rajout de point de suspension)
L'immatriculation pour ceux qui veulent se venger (si on avait pas de moteur de saut et qu'on a pas eu le temps d'arriver sur place alors qu'on avait été prévenu) ^^ et flinguer celui qui nous a fait perdre des profitssss.
Secteur : dernier secteur connu
Cible : si la menace à une cible en cour (affiché uniquement quand la cible est une propriété joueur et si cette propriété à un logiciel qui lui permette de dire qu'elle a été verrouillé ou que l'ennemi a commencé à tirer.)
Time : 0 si visible, 1 minute de battement, pour passer en mode "perdu de vue" et à partir de là depuis combien de temps il n'a pas été vu.
Pour le décès même si je perd des informations lors de la désignation de la propriété gérant la bdd, je peux faire gérer
- le temps hors radar par le central.
- le décès dans le radar en considérant if not object<-exist et que le chrono est à moins de 10 secondes, l'objet à été "vu" détruit.
Jusqu'à présent la bdd était constitué en permanence et consultable dès qu'un central était défini. Mais ça fait plus réaliste qu'elle commence à se constituer au moment de la désignation. Et qu'elle disparaisse avec sa destruction d'ailleurs.
J'étais parti sur une "petite" question et je me retrouve avec plein de choses incroyables. Même le compteur de temps est plus perfectionné que le mien. Je me sens presque misérable.
Bon je dis pas qu'avec acharnement mes script ne fonctionnent pas. mais bon. j'ai l'impression d'être de plus en plus petit!
Bon je fais un marque page la dessus. Je reviendrais voir ça!
Merci pour ce temps de partage!
Serial Kicked
12/07/2010, 03h29
huhu :smile:
T'as choisi des sujets pas forcement faciles pour commencer, et je salue l'effort. C'est trop rare pour ne pas être noté. Le coups de l'array d'array est très bien pensé d'ailleurs. J'avais volontairement zappé cette solution parce qu'elle est n'est pas très intuitive ou facile à expliquer. Bravo donc :wink:
Comme j'ai dit je ne fais que donner quelques conseils histoire que tu ne te retrouves pas bloqué à un point ou un autre de ton code parce que tu te serais mis dans une impasse impossible à corriger. J'ai pas mal d'années de programmation derrière moi dont 5 sur le moteur de X, autant que ça serve à d'autres :smile:.
Powered by vBulletin™ Version 4.0.3 Copyright © 2012 vBulletin Solutions, Inc. Tous droits réservés - Version française vbulletin-fr.org