Recycler les triggers, ça veut dire garder une trace, et le lien vers celui-ci, puis trouver la référence du trigger que l'on veut.
Rentre donc en compte l'efficacité des algo de recherche car on peut avoir un grand nombre de triggers associés, et les ralentissement et autres problèmes.
Désolé mais je ne vois pas l'utilité d'un tel tracking dans ce cas, pour un leak aussi infime.
-> en admettant que le leak ne soit qu'un pointeur (donc environ 4 octets) et qu'on affiche 50 dialogues par minute, on aurait donc 60*4*50 = 11.71ko de leak par heure... pas bien de quoi s'affoler.
Je regarderai néanmoins pour utiliser une condition à la place de l'action, mais il y a aussi quelques problèmes avec les conditions comme l'impossibilité d'utiliser des waits, il faudra donc voir si mon .evaluate() est compatible et si il ne faut pas que je rajoute également un .execute() pour executer les fonctions de dialogues dans un thread différent... si c'est vraiment utile...
C'est peut etre surement le cas, étant donné que le evaluate execute en fait un trigger, mais bon... il faut que je vérifie tout cela, à tête reposée, après les fêtes donc^^
Comme tu peux le voir le problème n'est pas si simple que ça quand on se penche sur les détails _________________
Bêta Systems:70% Bêta Spells:13% Bêta Arts & graphics:70%
Inscrit le: 23 Aoû 2007 Messages: 7143 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
Posté le: 26/12/08 19:53 Sujet du message:
La flemme là mais je suis sur à 99% que j'ai raison et que tu ne comprends pas ce que je veux dire, j'essaierais de faire la modif demain.
Et c'est pas tant le leak qui me gêne (on créé pas des dialogs tous les centièmes de seconde) mais la destruction de trigger réputé pour être unsafe (oui je suis parano), mais y'en a qui ont essayé et ils y sont pas arrivés :p _________________
Inscrit le: 13 Oct 2007 Messages: 994 Sujets: 25 Spécialité en worldedit: Codeur
Posté le: 27/12/08 17:27 Sujet du message:
Je suis un peu d'accord avec Profet, ça fait un gros travail pour sauver pas grand chose au final. Les dialogues sont rarement des choses qu'on utilise tout le temps dans une carte, c'est pas mis dans un déclencheur périodique ces choses la. Et même si c'était le cas le leak reste petit.
Par contre pour le recyclage, j'avais vu un système de recyclage de timer qui utilisais juste un offset a partir d'un premier timer créé, et les timers suivant prenaient juste les références suivantes. C'est peut être la même chose pour les triggers, ce qui fait un tracking très simple en fin de compte. _________________
- La théorie c'est quand rien ne fonctionne mais tout le monde sait pourquoi.
- La pratique c'est quand tout fonctionne mais personne ne sait pourquoi.
- Chez moi la théorie et la pratique sont réunies, rien ne fonctionne et personne ne sait pourquoi.
Inscrit le: 23 Aoû 2007 Messages: 7143 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
Posté le: 27/12/08 19:02 Sujet du message:
Bandes d'impurs :p
C'est pas tant le leak qui me dérange mais le jour où tu verras une fonction de blizzou détruire un trigger, tu me feras signe.
Certes ce n'est pas suffisant en soi pour être parano, mais j'ai déjà lu plusieurs posts à ce sujet, et ce par des "gosus", alors certes tout le monde n'est pas du même avis, mais pour moi dans le doute détruire un trigger saylemal quand je peux l'éviter facilement, ce qui est le cas ici.
Bon va falloir que je modifie le code, la solution est très simple croyez moi.
Secret:
Jass:
//***************************************************************************************************
// FW Simple Dialogs :
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Version : 1.00
// Author(s) : profet
//
// DESCRIPTION:
// Use the Warcraft3's dialog system becomes a painful task when we attempt to
// create a lot of dialogs in our maps, because it requires to create "dialog
// is clicked" triggers and compare the clicked button with buttons stored in
// variables to get desired actions.
//
// Simple Dialogs takes care of triggers creation and buttons comparisons, and
// automatically execute Actions functions defined for each buttons you created.
//
//
// HOW TO USE?
// As DialogCreate() should only be used to create one dialog per player, the
// system handles it automatically and you'll never have to use this function.
//
// When you want to create a new dialog for a player, you need to call the
// function FWSD_NewDialog(*).
//
// Note: If you previously created a dialog, this will clear the dialog
// window and you'll also never have to use DialogClear().
//
// Adding a button to the last created dialog can be done by using a second
// function FWSD_AddDialogButton(*).
// You can specify an ASCII number hotkey as argument.
//
//
// ATTACHING ACTIONS TO BUTTONS:
// The real advantage of this system is the way it links button's clicks and
// actions.
//
// The second argument of FWSD_AddDialogButton(*) takes a pointer
// to the function to execute, called when the button is clicked.
//
// You can also attach data to the dialog, like units or integer by using
// appropriated functions.
//
//
//***************************************************************************************************
library FWSD
globals
public constant integer MAX_BUTTONS = 7
public constant integer CANCEL_HOTKEY = 512
public constant string CANCEL_DEFAULTSTRING = "< Cancel >"
endglobals
globals
private s_dialog array DIALOG
endglobals
//===========================================================================
//This function is executed when a dialog button is clicked.
//It executes the .clicked() method of the dialog's structure.
private function dialogClicked takes nothing returns boolean
call DIALOG[GetPlayerId(GetTriggerPlayer())].Clicked(GetClickedButton())
return false
endfunction
//===========================================================================
//
struct s_dialog
private dialog h
private integer p
private trigger t = null
private integer btnCount = 0
private integer array btn_int[MAX_BUTTONS]
private button array btn_list[MAX_BUTTONS]
private dialogAction array btn_func[MAX_BUTTONS]
unit dialog_u1 = null
unit dialog_u2 = null
integer dialog_int = 0
method SetTitle takes string title returns nothing
call DialogSetMessage( .h, title )
endmethod
method AddButton takes string text, dialogAction func, integer key, integer attachedInt returns boolean
if( .btnCount<MAX_BUTTONS-1 or (key==CANCEL_HOTKEY and .btnCount<MAX_BUTTONS) )then
set .btn_list[.btnCount] = DialogAddButton( .h, text, key )
set .btn_func[.btnCount] = func
set .btn_int[.btnCount] = attachedInt
set .btnCount = .btnCount + 1
return true
endif
return false
endmethod
static method create takes integer p returns s_dialog
local s_dialog this = s_dialog.allocate()
set this.p = p
if this.h == null then // il n'y a pas encore de dialog créé pour cet index de struct
set this.h = DialogCreate()
set this.t = CreateTrigger()
call TriggerAddCondition( this.t, Condition(function dialogClicked ))
call TriggerRegisterDialogEvent( this.t, this.h )
endif
return this
endmethod
endstruct
//===========================================================================
//This function init a new dialog for specified player.
//When 'keepvars' parameter is set to TRUE, the new dialog keeps data attached to
//the previous dialog (usefull to display many dialogs in the raw).
public function NewDialog takes integer playerid, boolean keepvars returns nothing
if( DIALOG[playerid]==0 )then
set DIALOG[playerid] = s_dialog.create(playerid)
endif
if( not keepvars )then
set DIALOG[playerid].dialog_int = 0
set DIALOG[playerid].dialog_u1 = null
set DIALOG[playerid].dialog_u2 = null
endif
call DIALOG[playerid].Clear()
endfunction
//Defines the title of the last intialized dialog for specified player.
public function SetDialogTitle takes integer playerid, string title returns nothing
if( DIALOG[playerid]!=0 )then
call DIALOG[playerid].SetTitle(title)
endif
endfunction
//Defines the attached units of the last intialized dialog.
public function SetDialogUnits takes integer playerid, unit unit1, unit unit2 returns nothing
if( DIALOG[playerid]!=0 )then
set DIALOG[playerid].dialog_u1 = unit1
set DIALOG[playerid].dialog_u2 = unit2
endif
endfunction
//Defines the attached integer of the last intialized dialog.
public function SetDialogInteger takes integer playerid, integer attachedInt returns nothing
if( DIALOG[playerid]!=0 )then
set DIALOG[playerid].dialog_int = attachedInt
endif
endfunction
//Adds a button to the last initialized dialog.
//The 'key' parameter defines the button's hotkey (ASCII numbers).
public function AddDialogButton takes integer playerid, string text, dialogAction func, integer key, integer data returns boolean
if( DIALOG[playerid]!=0 )then
return DIALOG[playerid].AddButton(text,func,key,data)
endif
return false
endfunction
//Displays the last initialized dialog for specified player.
public function StartDialog takes integer playerid returns nothing
if( DIALOG[playerid]!=0 )then
call DIALOG[playerid].Start()
endif
endfunction
//***************************************************************************************************
function interface dialogAction takes integer playerId, integer buttonId, unit dialogUnit1, unit dialogUnit2, integer dialogInteger returns nothing
//***************************************************************************************************
endlibrary
D'ailleurs j'ai pas vu où tu détruisais ta struct o_O.
Et les methods devraient être private nan ?
Bien que personnellement je préfère créer et détruire la struct moi même mais utiliser des methods à la place de fonctions.
C'est plus zoli.
Voici un lien d'un bug avec une destruction de trigger :
public function H2I takes handle h returns integer
return h
return 0
endfunction
private function Actions takes nothing returns nothing
local integer i=0
call DestroyTrigger(GetTriggeringTrigger()) //Without this call, the bug won't happen
call TriggerSleepAction(0.00) //This wait action is needed for the bug to happen
call TriggerSleepAction(0.00)
set i=0
set Loc1=null
loop
exitwhen i > 10
if (Loc1==null) then
call BJDebugMsg("#Loc1 null")
else
call BJDebugMsg("#Loc1 y "+R2S(GetLocationY(Loc1)))
endif
set Loc2[i]=Location(0.,i)
if Loc2[i]==Loc1 then
call BJDebugMsg("FATALatindex:"+I2S(i)+";"+I2S(H2I(Loc2[i]))+" : "+R2S(GetLocationY(Loc2[i])) )
else
call BJDebugMsg("Index:"+I2S(i)+";"+I2S(H2I(Loc2[i]))+" : "+R2S(GetLocationY(Loc2[i])) )
endif
set Loc1=Loc2[i]
set i=i+1
endloop
call BJDebugMsg("Ended")
endfunction
//===========================================================================
public function init takes nothing returns nothing
local trigger trig = CreateTrigger( )
call TriggerRegisterPlayerChatEvent( trig, Player(0), "test", true )
call TriggerAddAction( trig, function Actions )
endfunction
endscope
Donc à priori ca bug si le trigger est en cours d'exécution mais comme je suis paranoïaque je l'étend à la destruction du trigger tout court, car de toute façon il n'est pas toujours évident de savoir quand toutes les "instances" (je ne comprend pas très bien les thread,alors j'utilise ce mot en approximation) du trigger seront achevées.
@Master : Tu parles surement de TimerUtils. _________________
Inscrit le: 13 Oct 2007 Messages: 994 Sujets: 25 Spécialité en worldedit: Codeur
Posté le: 28/12/08 17:27 Sujet du message:
Si j'ai bien compris, le bug dont tu parles c'est lorsque tu détruis un déclencheur qui est en cours d'exécution et qui va effectuer un SleepAction. J'ai envie de dire que quand on fait des trucs pas très propre faut pas s'étonner d'avoir des bugs :/ _________________
- La théorie c'est quand rien ne fonctionne mais tout le monde sait pourquoi.
- La pratique c'est quand tout fonctionne mais personne ne sait pourquoi.
- Chez moi la théorie et la pratique sont réunies, rien ne fonctionne et personne ne sait pourquoi.
Inscrit le: 23 Aoû 2007 Messages: 7143 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
Posté le: 28/12/08 18:05 Sujet du message:
[Master] a écrit:
Si j'ai bien compris, le bug dont tu parles c'est lorsque tu détruis un déclencheur qui est en cours d'exécution et qui va effectuer un SleepAction. J'ai envie de dire que quand on fait des trucs pas très propre faut pas s'étonner d'avoir des bugs :/
Dans certain cas désactiver le trigger peut ne pas être suffisant.
Et là c'est certes flagrant mais la destruction du trigger peut se faire indirectement.
De toute façon cet ex ne me concerne pas, j'utilise des conditions dés que je le peux et je n'utilise pas TriggerSleepAction.
Sinon j'avoue pas avoir regarder plus que cela le code, juste testé.
Je me suis dit que vu que c'était posté par Vexorian, c'était propre :p _________________
Inscrit le: 13 Oct 2007 Messages: 994 Sujets: 25 Spécialité en worldedit: Codeur
Posté le: 29/12/08 14:07 Sujet du message:
Troll-Brain a écrit:
[Master] a écrit:
Si j'ai bien compris, le bug dont tu parles c'est lorsque tu détruis un déclencheur qui est en cours d'exécution et qui va effectuer un SleepAction. J'ai envie de dire que quand on fait des trucs pas très propre faut pas s'étonner d'avoir des bugs :/
Dans certain cas désactiver le trigger peut ne pas être suffisant.
Et là c'est certes flagrant mais la destruction du trigger peut se faire indirectement.
De toute façon cet ex ne me concerne pas, j'utilise des conditions dés que je le peux et je n'utilise pas TriggerSleepAction.
Sinon j'avoue pas avoir regarder plus que cela le code, juste testé.
Je me suis dit que vu que c'était posté par Vexorian, c'était propre :p
Bah justement non pas trop. Il montre que ça fait un bug quand tu fais quelque chose de pas beau justement
Mais par curiosité, c'est quoi l'histoire des conditions ? J'ai pas tout saisi :/ _________________
- La théorie c'est quand rien ne fonctionne mais tout le monde sait pourquoi.
- La pratique c'est quand tout fonctionne mais personne ne sait pourquoi.
- Chez moi la théorie et la pratique sont réunies, rien ne fonctionne et personne ne sait pourquoi.
Tu peux executer des actions dans des fonctions de conditions (qui renvoient un booleen), mais une des limitations est que tu ne peux pas utiliser de wait à l'intérieur.
Mais le principal avantage est qu'il n'y a pas de thread créé donc plus rapide, un autre avantage est qu'il n'y a pas de "leak" sur le trigger avec des conditions.
Le probleme que TB a soulevé, est que lorsque l'on ajoute une action a un trigger que l'on supprime par la suite, l'action n'est pas supprimée de la mémoire en meme temps que le trigger, ce qui créé un leak, il faudrait le faire manuellement, hors blizzard ne nous a pas donné la native pour le faire.
Mais ici ce n'est pas d'actualité car je ne supprime pas le trigger avant la fin de la partie. _________________
Bêta Systems:70% Bêta Spells:13% Bêta Arts & graphics:70%
Inscrit le: 13 Oct 2007 Messages: 994 Sujets: 25 Spécialité en worldedit: Codeur
Posté le: 29/12/08 15:29 Sujet du message:
Ok merci pour les précisions. C'est toujours bon à savoir. _________________
- La théorie c'est quand rien ne fonctionne mais tout le monde sait pourquoi.
- La pratique c'est quand tout fonctionne mais personne ne sait pourquoi.
- Chez moi la théorie et la pratique sont réunies, rien ne fonctionne et personne ne sait pourquoi.
Inscrit le: 23 Aoû 2007 Messages: 7143 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
Posté le: 29/12/08 17:30 Sujet du message:
profet a écrit:
l'action n'est pas supprimée de la mémoire en meme temps que le trigger, ce qui créé un leak, il faudrait le faire manuellement, hors blizzard ne nous a pas donné la native pour le faire.
La seule chose que l'on ne peut détruire dans un trigger c'est les event, mais si il n'y a qu'un seul event, détruire le trigger supprime aussi l'event, sans leak.
Aprés y'a surement des cas particuliers où l'on peut rajouter plusieurs event puis détruire le trigger, sans leak.
La fonction TriggerClearConditions est trés utile étant donné la gestion des conditions, TriggerClearActions l'est beaucoup moins ... _________________
Les entiers sont plus utiles (et tu peux facilement les convertir en joueurs avec Player(id) tandis qu'un GetPlayerId() est bien plus long) car ils servent également d'index pour les variables array. _________________
Bêta Systems:70% Bêta Spells:13% Bêta Arts & graphics:70%
Toutes les heures sont au format GMT + 1 Heure Aller à la page Précédente1, 2, 3, 4Suivante
Page 2 sur 4
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