Worldedit
  Worldedit
Le site sur l'éditeur de warcraft 3 !
 
  FAQFAQ   RechercherRechercher   Liste des MembresListe des Membres    Groupes d'utilisateursGroupes d'utilisateurs   medals.php?sid=5ff5c146228477b29944c0dce62f2844Médailles   S'enregistrerS'enregistrer 
 ProfilProfil   Se connecter pour vérifier ses messages privésSe connecter pour vérifier ses messages privés   ConnexionConnexion 
  FAQFAQ World Editor   UploadUploader une map ou une image    UploadAjouter sa map à l'annuaire   UploadConsulter l'annuaire

[vJass] Régénération/Dégénération
Aller à la page 1, 2  Suivante
 
Poster un nouveau sujet   Répondre au sujet    Worldedit Index du Forum -> Fonction Jass
Voir le sujet précédent :: Voir le sujet suivant  
Auteur Message
 Sapeur-Goblin
Floodeur prématuré


Inscrit le: 14 Oct 2009
Messages: 719
Sujets: 40
Spécialité en worldedit: Les bugs
Médailles: 1 (En savoir plus...)
Créateur d'unité (Quantité : 1)

MessagePosté le: 06/03/12 11:55    Sujet du message: [vJass] Régénération/Dégénération Citer

Nom de la fonction : Regeneration & Degeneration
Créateur : Sapeur-Goblin
Fonctions requises : Aucune
Code :
Secret:

Jass:
library Regeneration /*
***********************
*
*   Fonctions
*   ---------
*
*       - Regeneration.add takes unit caster, unit target, real amount, real duration, integer id, boolean cumul, boolean on returns Regeneration
*       - Regeneration.remove takes unit target, integer id returns nothing
*       - Regeneration.has takes unit target, integer id returns boolean
*
*       - Degeneration.add takes unit caster, unit target, real amount, real duration, integer id, boolean cumul, boolean on returns Regeneration
*       - Degeneration.remove takes unit target, integer id returns nothing
*       - Degeneration.has takes unit target, integer id returns boolean
*
***********************/


globals
    private real Intervalle = 0.1             // Interval de temps pour les dégénération
    private constant integer DummyNumber = 12 // Nombre max de joueurs pour lesquels un dummy sera créé
                                              // (il faut en rajouter pour neutre hostile etc)
    private constant integer DummyId = 'dumm' // Indentifiant de l'unité dummy qui infligera les dégâts si le lanceur meurt
    private unit array Dummy[DummyNumber]
endglobals

struct Regeneration
    private static hashtable table = InitHashtable()
    private static timer Tim = CreateTimer()
    private static integer array enumInst
    private static integer Total = 0
   
    private thistype prev
    private thistype next = 0
    private unit caster
    private unit target
    private integer targetId
    private real r
    private real t = 0
    private real dur
    private integer id
    private boolean cumul
    private boolean on
   
    private static method Timer takes nothing returns nothing
        local thistype this
        local real r = 0
        local integer i = 0
        loop
            exitwhen i >= Total
            set this = enumInst[i]
            loop
                exitwhen this == 0
                set this.t = this.t + Intervalle
       
                if GetUnitTypeId(this.caster) == 0 or IsUnitType(this.caster, UNIT_TYPE_DEAD) then
                    if this.on then
                        set this.caster = Dummy[0]
                    else
                        set this.caster = null
                    endif
                endif
               
                if this.t > this.dur or GetUnitTypeId(this.target) == 0 or IsUnitType(this.target, UNIT_TYPE_DEAD) or this.caster == null then
                    if this.next == 0 then
                        call SaveInteger(table, this.targetId, this.id, this.prev)
                    endif
                    if this.prev == 0 then
                        set enumInst[i] = this.next
                    endif
                    if this.prev == 0 and this.next == 0 then
                        set enumInst[i] = enumInst[Total-1]
                        set Total = Total - 1
                        set i = i - 1
                        call RemoveSavedInteger(table, this.targetId, this.id)
                    endif
                    set this.prev.next = this.next
                    set this.next.prev = this.prev
                    set this.caster = null
                    set this.target = null
                    call this.deallocate()
                else
                    if this.cumul then
                        call SetUnitState(this.target, UNIT_STATE_LIFE, GetUnitState(this.target, UNIT_STATE_LIFE) + this.r)
                    elseif this.r > r then
                        set r = this.r
                    endif                           
                endif
                set this = this.next
            endloop
            set this = enumInst[i]
            call SetUnitState(this.target, UNIT_STATE_LIFE, GetUnitState(this.target, UNIT_STATE_LIFE) + r)
            set r = 0
            set i = i + 1
        endloop
        if Total == 0 then
            call PauseTimer(Tim)
        endif
    endmethod
   
    static method has takes unit target, integer id returns boolean
        return HaveSavedInteger(table, GetHandleId(target), id)
    endmethod
   
    static method remove takes unit target, integer id returns nothing
        local thistype this = LoadInteger(table, GetHandleId(target), id)
        call RemoveSavedInteger(table, GetHandleId(target), id)
        loop
            exitwhen this == 0
            set this.t = this.dur
            set this = this.prev
        endloop
    endmethod
   
    static method add takes unit caster, unit target, real r, real dur, integer id, boolean cumul, boolean on returns thistype
        local thistype this
        local thistype prev
        local integer i = GetHandleId(target)
        local integer j
        if GetUnitTypeId(target) != 0 and r > 0 and dur > 0 then
            if GetUnitTypeId(caster) != 0 or on then
                set this = thistype.allocate()
                set this.caster = caster
                set this.target = target
                set this.targetId = i
                set this.r = r * Intervalle
                set this.dur = dur
                set this.id = id
                set this.cumul = cumul
                set this.on = on
                set prev = LoadInteger(table, i, id)
                if prev == 0 then
                    set enumInst[Total] = this
                    set Total = Total + 1
                else
                    set prev.next = this
                    set this.prev = prev
                endif
                call SaveInteger(table, i, id, this)
                if Total == 1 then
                    call TimerStart(Tim, Intervalle, true, function Regeneration.Timer)
                endif
                return this
            endif
        endif
        return 0
    endmethod
   
    method destroy takes nothing returns nothing
        set this.t = this.dur
    endmethod
endstruct

struct Degeneration
    private static hashtable table = InitHashtable()
    private static timer Tim = CreateTimer()
    private static integer array enumInst
    private static integer Total = 0
   
    private thistype prev
    private thistype next = 0
    private unit caster
    private unit target
    private integer targetId
    private real r
    private real t = 0
    private real dur
    private integer id
    private boolean cumul
    private boolean on
    private integer playerId
   
    private static method Timer takes nothing returns nothing
        local thistype this
        local real r = 0
        local integer i = 0
        loop
            exitwhen i >= Total
            set this = enumInst[i]
            loop
                exitwhen this == 0
                set this.t = this.t + Intervalle
       
                if GetUnitTypeId(this.caster) == 0 or IsUnitType(this.caster, UNIT_TYPE_DEAD) then
                    if this.on then
                        set this.caster = Dummy[this.playerId]
                    else
                        set this.caster = null
                    endif
                endif
               
                if this.t > this.dur or GetUnitTypeId(this.target) == 0 or IsUnitType(this.target, UNIT_TYPE_DEAD) or this.caster == null then
                    if this.next == 0 then
                        call SaveInteger(table, this.targetId, this.id, this.prev)
                    endif
                    if this.prev == 0 then
                        set enumInst[i] = this.next
                    endif
                    if this.prev == 0 and this.next == 0 then
                        set enumInst[i] = enumInst[Total-1]
                        set Total = Total - 1
                        set i = i - 1
                        call RemoveSavedInteger(table, this.targetId, this.id)
                    endif
                    set this.prev.next = this.next
                    set this.next.prev = this.prev
                    set this.caster = null
                    set this.target = null
                    call this.deallocate()
                else
                    if this.cumul then
                        call UnitDamageTarget(this.caster, this.target, this.r, FALSE, TRUE, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
                    elseif this.r > r then
                        set r = this.r
                    endif                           
                endif
                set this = this.next
            endloop
            set this = enumInst[i]
            call UnitDamageTarget(this.caster, this.target, r, FALSE, TRUE, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
            set r = 0
            set i = i + 1
        endloop
        if Total == 0 then
            call PauseTimer(Tim)
        endif
    endmethod
   
    static method has takes unit target, integer id returns boolean
        return HaveSavedInteger(table, GetHandleId(target), id)
    endmethod
   
    static method remove takes unit target, integer id returns nothing
        local thistype this = LoadInteger(table, GetHandleId(target), id)
        call RemoveSavedInteger(table, GetHandleId(target), id)
        loop
            exitwhen this == 0
            set this.t = this.dur
            set this = this.prev
        endloop
    endmethod
   
    static method add takes unit caster, unit target, real r, real dur, integer id, boolean cumul, boolean on returns thistype
        local thistype this
        local thistype prev
        local integer i = GetHandleId(target)
        local integer j
        if GetUnitTypeId(target) != 0 and r > 0 and dur > 0 then
            if GetUnitTypeId(caster) != 0 or on then
                set this = thistype.allocate()
                set this.caster = caster
                set this.target = target
                set this.targetId = i
                set this.r = r * Intervalle
                set this.dur = dur
                set this.id = id
                set this.cumul = cumul
                set this.on = on
                if GetUnitTypeId(caster) == 0 then
                    set this.playerId = GetPlayerId(GetOwningPlayer(target))
                else
                    set this.playerId = GetPlayerId(GetOwningPlayer(caster))
                endif
                set prev = LoadInteger(table, i, id)
                if prev == 0 then
                    set enumInst[Total] = this
                    set Total = Total + 1
                else
                    set prev.next = this
                    set this.prev = prev
                endif
                call SaveInteger(table, i, id, this)
                if Total == 1 then
                    call TimerStart(Tim, Intervalle, true, function Degeneration.Timer)
                endif
                return this
            endif
        endif
        return 0
    endmethod
   
    method destroy takes nothing returns nothing
        set this.t = this.dur
    endmethod
endstruct

private function Init takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen i >= DummyNumber
        set Dummy[i] = CreateUnit(Player(i), DummyId, 0, 0, 0)
        set i = i + 1
    endloop
endfunction

endlibrary



Utilisation : Tout d'abord, il faut savoir (vous le savez déjà, je pense), que la plupart des buffs de warcraft ne sont pas cumulables, et quand on veut faire des sorts, ça devient vite une galère. Ces fonctions permettent de gérer ces histoires de cumulable/non cumulable.

Je vais détailler l'utilisation de la dégénération car c'est plus marrant Twisted Evil, mais sachez que pour la régénération, c'est pareil.

Ajouter une dégénération :
Jass:
call Degeneration.add(u, c, 10, 20, 'XXXX', false, false)

u : L'unité qui lance la dégénération
c : La cible
10 : Taux de dégénération par seconde
20 : Durée de la dégénération
'XXXX' : Catégorie de dégénération
false : Si vous mettez false, cette dégénération ne sera pas cumulable avec toutes les autres de la même catégorie, sachant que c'est la plus puissante qui se fait ressentir. Avec true, elle sera cumulable avec les autres de la même catégorie, donc avec toutes les dégénérations existante sur l'unité
false : La dégénération ne continuera pas si le lanceur meurt. Avec true, elle continuera.

Enlever une dégénération :

Jass:
call Degeneration.remove(u, 'XXXX')

Enlève toutes les dégénérations de type 'XXXX'.

HasUnitDegeneration :

Jass:
call Degeneration.has(u, 'XXXX')

Renvoie true si l'unité a la dégénération de type 'XXXX'

Copyright : Libre
Remarques : Si vous avez modifié le type d'attaque Chaos dans les constantes, les dégénérations tiendront compte de l'armure.
J'ai empêché de mettre des dégénérations/régénérations négatives parce que, si vous faîtes une régénération négative par exemple, ce sera la moins puissante qui sera ressentie par l'unité.
N'oubliez pas de bien préciser l'unité dummy, qui inflige les dégâts quand le réel lanceur meurt.

Si vous voulez ajouter un effet pour que la régénération/dégénération ne sorte pas de nulle par, je vous invite à utiliser cette fonction.
_________________


Dernière édition par Sapeur-Goblin le 26/04/12 09:21; édité 14 fois
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Hell-Gate
Membre récent


Inscrit le: 27 Fév 2012
Messages: 55
Sujets: 1
Spécialité en worldedit: Modelling et éditeur d'objet :p. Le Gui/Jass me font chier!


MessagePosté le: 06/03/12 13:15    Sujet du message: Citer

Tu t'es forcé Razz
C'est cool! Very Happy
_________________
Yo les enfants! C'est le Big Troll Jo_XDmoi qui est de retour avec un nouveau compte, question d'avoir une meilleure réputation Razz
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Wareditor
The Master of Nothing


Inscrit le: 22 Déc 2008
Messages: 1638
Sujets: 88
Spécialité en worldedit: Effacer


MessagePosté le: 06/03/12 17:55    Sujet du message: Citer

Une régénération négative est pas semblable a une degeneration ( sauf peut être pour savoir qui a kill l'unit cible ? ). Mais en ajoutant une partie cible dans régénération devrait régler la chose.
Essaie d'ajouter une API, serait plus simple a utiliser.
_________________
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Sapeur-Goblin
Floodeur prématuré


Inscrit le: 14 Oct 2009
Messages: 719
Sujets: 40
Spécialité en worldedit: Les bugs
Médailles: 1 (En savoir plus...)
Créateur d'unité (Quantité : 1)

MessagePosté le: 07/03/12 11:13    Sujet du message: Citer

Citation:
Une régénération négative est pas semblable a une degeneration ( sauf peut être pour savoir qui a kill l'unit cible ? ). Mais en ajoutant une partie cible dans régénération devrait régler la chose.

Pas tout à fait, à moins que je ne fasse la régénération par des dégâts négatifs mais bon...
Sinon, il y a déjà une partie cible dans la régénération Wink, sinon ça servirait à rien. C'est l'argument lanceur qui n'existe pas, bien que je vais bientôt en rajouter un pour pouvoir ajouter une fonctionalité : faut-il continuer la régénération si le lanceur est mort?

C'est quoi une API?
_________________
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Wareditor
The Master of Nothing


Inscrit le: 22 Déc 2008
Messages: 1638
Sujets: 88
Spécialité en worldedit: Effacer


MessagePosté le: 08/03/12 20:51    Sujet du message: Citer

Je n'ai pas trop "lu" ton système mais une regen' négative est semblable a une degenration. Enfin si tu ajoute des points de vie a l'unit. En ajoutant des points de vie négatifs cela aura le même effet ?
J'avais vu que ta regen' avais qu'un argument unit donc j'ai pense que tu avais seulement l'unit lanceur ( donne des noms plus compréhensible ).

API c'st l'acronyme de "Application Programming Interface" ( google is your friend ). Voici un exemple.
_________________
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Troll-Brain
Ri1kamoua


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...)
Rédacteur de tuto #3 (Quantité : 1) Grand mage créateur de sort (Quantité : 1)

MessagePosté le: 09/03/12 21:36    Sujet du message: Citer

Ce qu'il veut dire c'est que tu n'as pas de documentation pour l'API.

Même remarque qu'ailleurs, tes noms de variables ne sont pas explicites.

- On peut très bien se retrouver avec une unité morte ayant plus de 0.405 de vie, il vaut mieux utiliser IsUnitType(u,UNIT_TYPE_DEAD).

- Tu ne fais aucune vérification de "sécurité", à savoir si les paramètres de tes fonctions sont valides.

- Pour HasUnitRegeneration il doit y avoir moyen de rendre la complexité algorithmique O(1) plutôt que O(N).

- Tu ne gères pas les cas où une unité meurt/est supprimée de la partie.
D'ailleurs je suppose qu'il faudrait prévoir l'utilisation d'une unité dummy pour infliger les dégâts, ainsi si "u" est supprimée de la partie, le joueur possesseur de "u" continue à infliger des dégâts et recevoir les récompenses pour sa mort éventuelle.

- l'utilisation de string est à éviter quand ce n'est pas nécessaire, ici il vaudrait mieux utiliser un paramètre entier (vive les constant integer).
D'une part parce qu'une erreur de frappe ne sera pas détectée à la compilation du script, d'autre part pour les custom spell une constant integer utilisant le rawcode 'XXXX' du spell devrait déjà définie.
Enfin, la gestion des string en jass est "horrible" (non je ne développerais pas ce dernier point)
_________________
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Sapeur-Goblin
Floodeur prématuré


Inscrit le: 14 Oct 2009
Messages: 719
Sujets: 40
Spécialité en worldedit: Les bugs
Médailles: 1 (En savoir plus...)
Créateur d'unité (Quantité : 1)

MessagePosté le: 31/03/12 15:33    Sujet du message: Citer

Je suis en train d'essayer de l'améliorer mais j'ai quelques questions à propos de ce que tu disais :
Troll-Brain a écrit:
- Tu ne gères pas les cas où une unité meurt/est supprimée de la partie.
D'ailleurs je suppose qu'il faudrait prévoir l'utilisation d'une unité dummy pour infliger les dégâts, ainsi si "u" est supprimée de la partie, le joueur possesseur de "u" continue à infliger des dégâts et recevoir les récompenses pour sa mort éventuelle.

Je suis d'accord mais il faut que "u" prenne le relais que lorsque le réel lanceur meurt, non? Sinon les gains d'xp (qui dépendent de la distance) ne correspondent pas.

Troll-Brain a écrit:
- l'utilisation de string est à éviter quand ce n'est pas nécessaire, ici il vaudrait mieux utiliser un paramètre entier (vive les constant integer).
D'une part parce qu'une erreur de frappe ne sera pas détectée à la compilation du script, d'autre part pour les custom spell une constant integer utilisant le rawcode 'XXXX' du spell devrait déjà définie.
Enfin, la gestion des string en jass est "horrible" (non je ne développerais pas ce dernier point)

Ca ralentit tellement les calculs? Pour gérer les dégénérations cumulables, faudrait utiliser un booléan alors?

Troll-Brain a écrit:
- Pour HasUnitRegeneration il doit y avoir moyen de rendre la complexité algorithmique O(1) plutôt que O(N).

Faut passer par une "indexiation"?
_________________
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Troll-Brain
Ri1kamoua


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...)
Grand mage créateur de sort (Quantité : 1) Rédacteur de tuto #3 (Quantité : 1)

MessagePosté le: 31/03/12 19:31    Sujet du message: Citer

1) Oui bien entendu (même si je n'avais pas pensé à cela huhu)

2) les strings ca suck c'est tout, au delà d'un souci d'efficacité du code, il y a l'aspect pratique.

3) Pas obligé, mais ca serait le must bien entendu, pour tes autres fonctions y'a aussi surement moyen de diminuer la complexité, mais franchement j'ai plus la motivation pour quoi que ce soit.
_________________
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Tirlititi



Inscrit le: 21 Fév 2010
Messages: 1785
Sujets: 22
Spécialité en worldedit: La modestie
Médailles: 1 (En savoir plus...)
Grand mage créateur de sort (Quantité : 1)

MessagePosté le: 31/03/12 20:04    Sujet du message: Citer

Tu peux utiliser "UnitAddAbility" et "GetUnitAbilityLevel() > 0", par exemple, si tu ne veux pas utiliser de système d'indexage (avec des compétences invisibles qui ne servent à rien ^^).

Faut juste pas utiliser les groupes d'unités parce que la complexité de "IsUnitInGroup" est sans doute O(n).
_________________
Warcraft III, c'était mieux avant. Y'avait des purs chefs-d'oeuvres du mapping !
Road Of Glory (par moi)
Casse-briques (par moi)
Temple de Glace (par moi)
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Troll-Brain
Ri1kamoua


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...)
Grand mage créateur de sort (Quantité : 1) Rédacteur de tuto #3 (Quantité : 1)

MessagePosté le: 31/03/12 20:11    Sujet du message: Citer

Tirlititi a écrit:
Tu peux utiliser "UnitAddAbility" et "GetUnitAbilityLevel() > 0", par exemple, si tu ne veux pas utiliser de système d'indexage (avec des compétences invisibles qui ne servent à rien ^^).


April fool ?

Citation:
Faut juste pas utiliser les groupes d'unités parce que la complexité de "IsUnitInGroup" est sans doute O(n).


Même si c'est le cas, ce qui n'est clairement pas certain, (c'est peut être un tas binaire ou quelque chose du style).
Ça doit rester suffisamment efficace, car il ne faut pas oublier que le jass est un langage interprété, qui est interprété d'une façon très lente, dans ce genre de fonction le temps d'éxécution du code est probablement insignifiant par rapport au temps de "parsage" du code.
_________________
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Sapeur-Goblin
Floodeur prématuré


Inscrit le: 14 Oct 2009
Messages: 719
Sujets: 40
Spécialité en worldedit: Les bugs
Médailles: 1 (En savoir plus...)
Créateur d'unité (Quantité : 1)

MessagePosté le: 01/04/12 15:12    Sujet du message: Citer

Je ne crois pas que ce soit possible avec des compétences cachées : il en faudrait une pour chaque catégorie. Pareil avec un système d'indexiation, à moins qu'il soit possible d'attacher plusieurs entiers à une même unité, je m'y connais pas trop.
Pour l'instant, pour alléger un peu la fonction, j'ai mis set i = Total quand elle trouve l'unité avec la régénération, ça permet de directement sortir de la boucle.

Edit: Euh une unité qui est remove de la map n'est pas sensée être considérée comme nulle? Parce que après quelques tests, je me suis rendu compte que non. Donc si on utilise RemoveUnit(u), je ne pourrais pas savoir qu'elle a été retirée, donc la régénération pourra pas être retirée/ajoutée.

Edit #2: Une unité qui est retirée de la map est en fait cachée, donc pour détecter ça, c'est un peu la galère puisque si j'utilise IsUnitHidden(u) et que quelque part dans la map on se sert de ShowUnit(u , false), la régénération sera stoppée (ou continuera, mais ce ne sera plus u qui la lancera). Ca peut poser quelques problèmes. Troll-Brain, j'espère que t'as une solution de roxxor Wink.

Edit #3: Enfait non, IsUnitHidden(u) ne marche qu'une fois sur deux... Je vois pas trop où est le problème.

Je poste le code au cas où, mais il me semble que l'erreur vient juste de la manière utilisée pour détecter si une unité est retirée de la map (quand elle meurt, ça marche très bien).

Secret:

Jass:
library AddUnitRegeneration initializer Init

globals
    private constant real Interval = 0.1 //Interval de temps pour les dégénération
    private constant integer ID = 'dumm' //Indentifiant de l'unité dummy qui infligera les dégâts si le lanceur meurt
    private constant integer I = 12
endglobals

private struct degeneration
    unit u
    unit c
    real d
    real t = 0
    real tm
    integer id
    boolean cumul
    boolean on
    integer p
endstruct

private struct regeneration
    unit u
    unit c
    real d
    real t = 0
    real tm
    integer id
    boolean cumul
    boolean on
    integer p
endstruct

globals
    private timer              TimDegeneration = CreateTimer()
    private integer            DTotal           = 0
    private degeneration array DAr
    private unit array Dummy[I]
   
    private timer              TimRegeneration = CreateTimer()
    private integer            RTotal           = 0
    private regeneration array RAr
endglobals

function RemoveDegeneration takes unit u, integer id returns nothing
    local degeneration rg
    local integer i = 0
   
    loop
        exitwhen i >= DTotal
        set rg = DAr[i]
       
        if u == rg.c and id == rg.id then
            set rg.u = null
            set DAr[i] = DAr[DTotal - 1]
            set DTotal = DTotal - 1
            call rg.destroy()
            set i = i - 1
        endif
       
        set i = i + 1
    endloop
endfunction

function RemoveRegeneration takes unit u, integer id returns nothing
    local regeneration rg
    local integer i = 0
   
    loop
        exitwhen i >= RTotal
        set rg = RAr[i]
       
        if u == rg.c and id == rg.id then
            set rg.u = null
            set RAr[i] = RAr[RTotal - 1]
            set RTotal = RTotal - 1
            call rg.destroy()
            set i = i - 1
        endif
       
        set i = i + 1
    endloop
endfunction


function HasUnitDegeneration takes unit u, integer id returns boolean
    local degeneration rg
    local boolean b = false
    local integer i = 0
   
    loop
        exitwhen i >= DTotal
        set rg = DAr[i]
        if u == rg.c and rg.id == id then
            set b = true
            set i = DTotal
        endif
       
        set i = i + 1
    endloop
   
    return b
endfunction

function HasUnitRegeneration takes unit u, integer id returns boolean
    local regeneration rg
    local boolean b = false
    local integer i = 0
   
    loop
        exitwhen i >= RTotal
        set rg = RAr[i]
        if u == rg.c and rg.id == id then
            set b = true
            set i = RTotal
        endif
       
        set i = i + 1
    endloop
   
    return b
endfunction

private function DegenerationTimer takes nothing returns nothing
    local degeneration rg
    local degeneration rt
    local real d    = 0
    local integer i = 0
    local integer c = 0
    local boolean b = true
   
    loop
        exitwhen i >= DTotal
        set rg = DAr[i]
       
        set rg.t = rg.t + Interval
       
        if rg.u == null or IsUnitHidden(rg.u) or IsUnitType(rg.u, UNIT_TYPE_DEAD) then
            if rg.on then
                set rg.u = Dummy[rg.p]
            else
                set rg.u = null
            endif
        endif
       
        if rg.t <= rg.tm and rg.c != null and not IsUnitHidden(rg.c) and not IsUnitType(rg.c, UNIT_TYPE_DEAD) and rg.u != null then
            set d  = rg.d
           
            if not rg.cumul then
                loop
                    exitwhen c >= DTotal
                    set rt = DAr[c]
                   
                    if rg.c == rt.c and rg.id == rt.id and not rt.cumul then
                        if rg.d > rt.d then
                            set d = rg.d
                        elseif rg.d < rt.d then
                            set d = rt.d
                            set b = false
                        elseif rg.d == rt.d then
                            if i > c then
                                set b = false
                            endif
                        endif
                    endif
                   
                    set c = c + 1
                endloop
            endif
           
            if b then
                call UnitDamageTarget(rg.u, rg.c, d, false, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
            endif
        else
            set rg.u = null
            set rg.c = null
            set DAr[i] = DAr[DTotal - 1]
            set DTotal = DTotal - 1
            call rg.destroy()
            set i = i - 1
        endif
       
        set b = true
        set c = 0
        set i = i + 1
    endloop
   
    if DTotal == 0 then
        call PauseTimer(TimDegeneration)
    endif
endfunction

private function RegenerationTimer takes nothing returns nothing
    local regeneration rg
    local regeneration rt
    local real d    = 0
    local integer i = 0
    local integer c = 0
    local boolean b = true
   
    loop
        exitwhen i >= RTotal
        set rg = RAr[i]
       
        set rg.t = rg.t + Interval
       
        if rg.u == null or IsUnitHidden(rg.u) or IsUnitType(rg.u, UNIT_TYPE_DEAD) then
            if rg.on then
                set rg.u = Dummy[rg.p]
            else
                set rg.u = null
            endif
        endif
       
        if rg.t <= rg.tm and rg.c != null and not IsUnitHidden(rg.c) and not IsUnitType(rg.c, UNIT_TYPE_DEAD) and rg.u != null then
            set d  = rg.d
           
            if not rg.cumul then
                loop
                    exitwhen c >= RTotal
                    set rt = RAr[c]
                   
                    if rg.c == rt.c and rg.id == rt.id and not rt.cumul then
                        if rg.d > rt.d then
                            set d = rg.d
                        elseif rg.d < rt.d then
                            set d = rt.d
                            set b = false
                        elseif rg.d == rt.d then
                            if i > c then
                                set b = false
                            endif
                        endif
                    endif
                   
                    set c = c + 1
                endloop
            endif
           
            if b then
                call SetUnitState(rg.c, UNIT_STATE_LIFE, GetUnitState(rg.c, UNIT_STATE_LIFE) + d)
            endif
        else
            set rg.u = null
            set rg.c = null
            set RAr[i] = RAr[RTotal - 1]
            set RTotal = RTotal - 1
            call rg.destroy()
            set i = i - 1
        endif
       
        set b = true
        set c = 0
        set i = i + 1
    endloop
   
    if RTotal == 0 then
        call PauseTimer(TimRegeneration)
    endif
endfunction

function AddUnitDegeneration takes unit u, unit c, real d, real t, integer id, boolean cumul, boolean on returns nothing
    local degeneration rg
    local boolean b       = true
    local integer i       = 0
   
    if c != null and d > 0 and t > 0 then
        if u != null or on then
            set rg = degeneration.create()
            set rg.u  = u
            set rg.c  = c
            set rg.d  = d*Interval
            set rg.tm = t
            set rg.id = id
            set rg.cumul = cumul
            set rg.on = on
            set rg.p = GetPlayerId(GetOwningPlayer(u))
           
            if DTotal == 0 then
                call TimerStart(TimDegeneration, Interval, true, function DegenerationTimer)
            endif
           
            set DAr[DTotal] = rg
            set DTotal = DTotal + 1
        endif
    endif
endfunction

function AddUnitRegeneration takes unit u, unit c, real d, real t, integer id, boolean cumul, boolean on returns nothing
    local regeneration rg = regeneration.create()
    local boolean b       = true
    local integer i       = 0
   
    if c != null and d > 0 and t > 0 then
        if u != null or on then
            set rg.u = u
            set rg.c = c
            set rg.d  = d*Interval
            set rg.tm = t
            set rg.id = id
            set rg.cumul = cumul
            set rg.on = on
            set rg.p = GetPlayerId(GetOwningPlayer(u))
           
            if RTotal == 0 then
                call TimerStart(TimRegeneration, Interval, true, function RegenerationTimer)
            endif
           
            set RAr[RTotal] = rg
            set RTotal = RTotal + 1
        endif
    endif
endfunction

private function Init takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen i >= I
        set Dummy[i] = CreateUnit(Player(i), ID, 0, 0, 0)
        set i = i + 1
    endloop
endfunction

endlibrary


_________________
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Troll-Brain
Ri1kamoua


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...)
Rédacteur de tuto #3 (Quantité : 1) Grand mage créateur de sort (Quantité : 1)

MessagePosté le: 01/04/12 18:03    Sujet du message: Citer

Tirlititi faisait référence aux indexeurs d'unités "modernes" tel que UnitIndexer et AutoIndex qui utilisent la compétence "défendre" des footman, pour détecter quand une unité est remove du jeu (bug exploit), est créée, ainsi que divers event non natifs.

Pour détecter une ghost unit (roxxor ™) :

http://worldedit.free.fr/forum/viewtopic.php?p=100293#100293

On ne peut en effet pas directement lier plusieurs entiers à une unité mais utiliser un unit indexer suffit, en effet chaque unité se voit attribuer un entier unique (via la "custom value"), et avec celle ci on peut utiliser pléthore de structures de données, comme une hashtable, une struct ou même une simple array, ou d'autres abominations mélangeant tout cela.

Mais bon là comme je l'ai dit j'ai la flemme d'aller plus loin, surtout que je devrais probablement réécrire ton code de A à Z.
_________________
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Sapeur-Goblin
Floodeur prématuré


Inscrit le: 14 Oct 2009
Messages: 719
Sujets: 40
Spécialité en worldedit: Les bugs
Médailles: 1 (En savoir plus...)
Créateur d'unité (Quantité : 1)

MessagePosté le: 02/04/12 17:08    Sujet du message: Citer

Voilà, j'ai mis à jour, ça marche. Peut-être qu'un jour, si l'envie me prend, je ferais en sorte qu'on puisse choisir l'intervalle de régénération.
_________________
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Troll-Brain
Ri1kamoua


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...)
Grand mage créateur de sort (Quantité : 1) Rédacteur de tuto #3 (Quantité : 1)

MessagePosté le: 02/04/12 17:29    Sujet du message: Citer

Je vois que tu as gardé ces affreux noms de variables, crois moi ce genre de pratique ne te rendra pas service.

Il est primordial d'avoir un code compréhensible pour éviter des erreurs de logique et en règle générale pouvoir lire/comprendre le code facilement.
Comme il est aussi intéressant d'ajouter des commentaires, notamment si l'on reprend le code des mois ou des années plus tard.

Tu n'as pas besoin de vérifier qu'une unité est == null, étant donné que GetUnitTypeId(null) == 0
_________________


Dernière édition par Troll-Brain le 28/07/12 18:39; édité 1 fois
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
 Sapeur-Goblin
Floodeur prématuré


Inscrit le: 14 Oct 2009
Messages: 719
Sujets: 40
Spécialité en worldedit: Les bugs
Médailles: 1 (En savoir plus...)
Créateur d'unité (Quantité : 1)

MessagePosté le: 03/04/12 15:56    Sujet du message: Citer

Ok, j'ai corrigé et enlevé quelques calculs qui servaient à rien.
J'ai aussi fait en sorte que ça fonctionne si un met un lanceur null dès le début en mettant que le joueur qui inflige la dégénération est le joueur qui la subit, comme ça pas de problème d'xp.
_________________
Revenir en haut
Voir le profil de l'utilisateur Envoyer un message privé
Montrer les messages depuis:   
Poster un nouveau sujet   Répondre au sujet    Worldedit Index du Forum -> Fonction Jass Toutes les heures sont au format GMT + 1 Heure
Aller à la page 1, 2  Suivante
Page 1 sur 2

 
Sauter vers:  
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


Powered by phpBB © 2001, 2005 phpBB Group
Traduction par : phpBB-fr.com