Inscrit le: 12 Nov 2011 Messages: 1062 Sujets: 107 Spécialité en worldedit: Inactif(Enfin presque) Médailles: 1 (En savoir plus...)
Posté le: 17/05/15 17:58 Sujet du message: Problème avec instances de struct
Pour ceux qui veulent la petite histoire:
Secret:
Voilà, y'a un petit moment que je me suis remis au (*à l'apprentissage du*) vJASS, ayant quelques problèmes avec les stacks/queue malgré l'aide que m'a apporté Troll-Brain sur le sujet, j'avais du mal à réaliser des trucs MUI, donc j'ai décidé d'essayer avec un dot tout simple (mais tout de même un peu configurable) et là c'est le drame:
Lorsque la première instance de la struct est créée, ben j'ai droit à au moins 40"Attempt to destroy a null instance of struct : MyStruct "mais l'effet indiquant que l'unité est censée subir est dot est bien présent.
Sauf qu'après, il se passe rien, et l'effet ne disparais jamais, ensuite, lorsque je relance la création d'une instance, j'ai pas de message autre que celui que j'ai mis qui indique les caractéristiques de la création et l'effet apparaît bien. Et il se passe rien quand j'attend. Donc j'ai besoin d'aide pour comprendre où ça bloque.
struct MyStruct
real damage
real interval
real lasting
real cinterval
effect model
unit target
unit caster
integer count
static method create takes unit t, unit c, real l, real i, real d, string m, string a returns MyStruct
set Count = Count + 1
set Instance[Count] = MyStruct.allocate()
set Instance[Count].lasting = l
set Instance[Count].caster = c
set Instance[Count].damage = d
set Instance[Count].interval = i
set Instance[Count].cinterval = i
set Instance[Count].target = t
set Instance[Count].count = Count
set Instance[Count].model = AddSpecialEffectTarget( m, t, a)
if testmode == true then
call BJDebugMsg("An Instance of Struct was created with the following parameters: |c00FF0000Target|r: " + GetUnitName(t) + " |c00FF0000Caster|r: " + GetUnitName(c) + " |c00FF0000Damage|r: " + R2S(d) + " |c00FF0000Duration|r: " + R2S(l) + " |c00FF0000Interval|r: " + R2S(i) )
endif
if Count == 0 then
call TimerStart( Time, 0.03, TRUE, function MyStruct.Loop )
endif
return Instance[Count]
endmethod
private method action takes nothing returns nothing
set this.cinterval = this.cinterval - 0.03
if this.cinterval <= 0.00 then
call UnitDamageTarget( this.caster, this.target, this.damage, FALSE, TRUE, ATTACK_TYPE_HERO, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS )
set this.cinterval = this.interval
endif
set this.lasting = this.lasting - 0.03
if this.lasting <= 0.00 then
call this.destroy()
endif
endmethod
private static method Loop takes nothing returns nothing
local integer i = -1
loop
exitwhen i == Count
call Instance[i].action()
set i = i + 1
endloop
endmethod
private method destroy takes nothing returns nothing
local integer i = 0
local integer j = 0
call DestroyEffect( this.model )
set j = this.count + 1
set this.target = null
set this.caster = null
set this.model = null
call this.deallocate()
if Count > 0 then
set i = Count
loop
exitwhen j == i
set Instance[j] = Instance[j + 1]
if testmode == TRUE then
call BJDebugMsg( "Instance n°|c00FF0000" + I2S(j+1) + " |rstored in Instance n°|c00FF0000" + I2S(j) )
endif
set j = j + 1
endloop
endif
call Instance[Count].deallocate()
set Count = Count - 1
if Count == -1 then
call PauseTimer( Time )
endif
endmethod
Inscrit le: 12 Nov 2011 Messages: 1062 Sujets: 107 Spécialité en worldedit: Inactif(Enfin presque) Médailles: 1 (En savoir plus...)
Posté le: 18/05/15 18:26 Sujet du message:
J'ai fait quelques modifications et ça fonctionne sur une seule cible, sur plusieurs, le plus souvent ça marche, des fois y'en a une ou deux pour qui ça arrête de fonctionner (surement un problème dû à la réattribution des instances pour éviter les vides dans les boucles qui pompent de la mémoire.)
Pour ce qui est du debugging Le message qui dit que l'instance X + 1 est déplacée à l'instance X monte jusqu'à 766 alors que je fais généralement des tests avec 6 lancements simultanés tout au plus. _________________
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: 19/05/15 19:50 Sujet du message:
Et il est où ce sujet déjà ?
Parce que visiblement tu n'as pas compris comment faire un tableau dynamique "simple" (on ne préserve pas l'ordre relatif des instances)
Y'a peut être des tutos sur le net si je n'arrive pas à me faire comprendre. (mais je veux bien réessayer) _________________
Inscrit le: 12 Nov 2011 Messages: 1062 Sujets: 107 Spécialité en worldedit: Inactif(Enfin presque) Médailles: 1 (En savoir plus...)
Posté le: 20/05/15 16:30 Sujet du message:
Secret:
Troll-Brain a écrit:
Le plus simple et efficace je dirais serait d'utiliser une structure de donnée adaptée tel qu'une pile (stack) ou file d'attente (queue).
Structure qui doit être mise à jour au moment de la création/destruction d'une instance.
C'est relativement facile à implanter une fois le principe simple (sisi) compris.
Voici le principe :
Jass:
// variables globales nécessaires :
Spell array Stack
integer N = 0
struct Spell
static method create takes nothing returns nothing
local thistype this = thistype.allocate()
set Stack[N] = this
set N = N+1
endmethod
method loop takes nothing returns nothing
...
local integer i = N
local thistype instance
loop
exitwhen i == 0
set i = i-1
set instance = Stack[i]
// si on doit détruire l'instance, réorganiser la pile :
set N = N-1
set Stack[i] = Stack[N]
set Stack[N] = 0 // pas nécessaire, mais bon c'est pour le principe ...
endloop
endmethod
...
endstruct
Idéalement Stack et N devraient être des membres de la struct Spell, mais je n'ai pas voulu t'embrouiller avec une syntaxe différente (mais résultat en jass similaire).
Si tu veux comprendre comment réaliser une pile avec un tableau dynamique, je t'invite à le faire sur papier (le pseudo code que j'ai écrit).
Personnellement c'est comme cela que j'ai compris et surtout retenu le fonctionnement.
Ça et puis une recherche sur le net à ce sujet bien entendu.
EDIT : Au fait, même si cette structure au départ est une pile, ca ne le reste pas forcément.
Étant donné que l'on ne conserve pas l'ordre des éléments lors de la destruction d'un élément, mais ici on s'en carre l'oignon, de l'ordre relatif des instances.
Si on voudrait conserver l'ordre, une liste chaînée (linked list) serait plus appropriée.
Mais ceci est une autre histoire qui vous sera (peut être) contée une autre fois.
EDIT 2 : Hmm nan on ne peut pas utiliser ce type de structure donnée en exemple de la sorte.
On ne peut pas à la fois boucler et détruire un élément de la sorte.
Il manque quelque chose, j'y réfléchirai tout à l'heure à tête reposée, je vais au dodo.
EDITH PIAF : Ça devrait être bon, j'avais simplement fait une erreur, je décrémentais N trop tard.
C'est vrai qu'il est pas question de conserver l'ordre dans ce que tu dis :/ mais la grosse différence vient du fait que moi je préferais décrémenter dans la méthode destroy plutôt que dans le loop. Après, j'ai pas trouvé de tutos sur les linked lists sur THW ni sur Wc3c, donc faudrait que je voie sur Thehelper. Et sinon, j'imagine que je peux aussi demander ici . _________________
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: 20/05/15 17:33 Sujet du message:
Citation:
C'est vrai qu'il est pas question de conserver l'ordre dans ce que tu dis :/
En quoi est ce un problème ici ?!
Citation:
mais la grosse différence vient du fait que moi je préferais décrémenter dans la méthode destroy plutôt que dans le loop.
T'es sérieux là ?!
Si vraiment tu veux le faire, rien ne t'empêche de créer une method destroy qui fait la décrémentation (faudrait que i soit accessible ou passé en argument de destroy, mais je ne sais plus si une method destroy peut avoir des arguments ou non)
Citation:
Après, j'ai pas trouvé de tutos sur les linked lists sur THW ni sur Wc3c, donc faudrait que je voie sur Thehelper. Et sinon, j'imagine que je peux aussi demander ici Razz .
Inscrit le: 12 Nov 2011 Messages: 1062 Sujets: 107 Spécialité en worldedit: Inactif(Enfin presque) Médailles: 1 (En savoir plus...)
Posté le: 20/05/15 18:55 Sujet du message:
J'ai vérifié et destroy n'a pas le droit de prendre des arguments.
Donc faut que je le fasse dans le loop. Du coup c'est plus tellement une question de choix.
Sauf si n'importe quelle method qui contient un deallocate peut être considérée comme un équivalent à destroy. _________________
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: 20/05/15 19:23 Sujet du message:
Si tu ne déclares pas de method destroy, elle est tout de même créée et appelle la method deallocate.
Donc même si tu ne créés pas de method destroy tu peux appeler cette method.
Mais le réel intérêt est de pouvoir réécrire destroy, sinon deallocate fait le job.
Quand je parlais de rendre i accessible, c'était une histoire de portée, il ne faut pas que ca soit une variable local quoi, tu peux aussi passer par une method/function intermédiaire.
Ou juste gérer la destruction dans la loop _________________
Inscrit le: 14 Avr 2011 Messages: 1846 Sujets: 119 Spécialité en worldedit: fonctions paramétriques, équation de mouvement.
Posté le: 09/07/15 15:44 Sujet du message:
Sinon rien ne t'empeche de creer une methode orderDestroy, lui mettre des attribus et en faire ce que tu veux (et appeler deallocate ou destroy dedans).
Tu peux meme creer une library List et te faire toute une API de gestion de liste comme en C (et la publier tant qu'a faire, mais je suis sur que ca existe deja) _________________
22:27:43<Seiraw> Bah y a deux genre de personnes
22:27:57<Seiraw> les soumis et les soumises
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