Inscrit le: 21 Avr 2008 Messages: 1607 Sujets: 81 Spécialité en worldedit: Utiliser le travail des autres Médailles: 3 (En savoir plus...)
Posté le: 08/06/12 20:19 Sujet du message: [vJass] 2 sorts qui bugs si utilisés en même temps
Bonjour, Je me suis aperçu d'un bug. Lorsque j'utilise 2 des sorts d'un héros, les sorts bugs complètement, avec des effets spéciaux qui partent dans tous les sens (les fonctions de déplacement dans le code).
Je n'arrive pas à voir si des fonctions peuvent être appelées par les 2 sorts. Je crois que j'ai dû mal encapsuler quelque chose.
Les 2 sorts marchent parfaitement si on utilise qu'eux même avec plusieurs casters.
Merci d'avance
Voilà le premeir sort
Secret:
Jass:
library SolarCrown requires xefx, TimerUtils, GroupUtils, xedamage
//===============================================================================================
//===============================================================================================
//===============================================================================================
globals
private constant integer SPELL_ID = 'A01B'
private constant integer N_BOLT = 3 //Nombre d'effets qui forment le cercle
private constant real FX_SCALE_BOLT_INIT = 1.5
private constant real FX_SCALE_RAY = 0.5
private constant real T_SPIRAL = 1.
private constant real MIN_DIST = 10.
private constant real SPELL_DUR = 5.3
private constant integer RED = 255 //vertex coloring in RGB
private constant integer GREEN = 255
private constant integer BLUE = 200
private constant integer ALPHA = 150
private constant string FX_BOLT = "Abilities\\Weapons\\LordofFlameMissile\\LordofFlameMissile.mdl"
private constant string FX_RAY = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl"
private constant string ORDER_ID = "healingspray"
endglobals
private constant function GetSpeed takes integer lvl returns real
return 1.
endfunction
private constant function GetAoE takes integer lvl returns real
return 200. + 25. * lvl
endfunction
private constant function SPIRAL takes integer lvl returns real
return ((GetAoE(lvl) - MIN_DIST)/(T_SPIRAL)) * XE_ANIMATION_PERIOD
endfunction
private function DamageOptions takes xedamage spellDamage returns nothing
set spellDamage.dtype = DAMAGE_TYPE_MAGIC
set spellDamage.atype = ATTACK_TYPE_NORMAL
set spellDamage.exception = UNIT_TYPE_STRUCTURE
set spellDamage.visibleOnly = true
set spellDamage.damageSelf = true
set spellDamage.damageAllies = false
set spellDamage.allyfactor = -0.0
endfunction
private function IsValidTarget takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD) and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(u, UNIT_TYPE_FLYING) and not IsUnitType(u, UNIT_TYPE_MECHANICAL)and not IsUnitType(u, UNIT_TYPE_STRUCTURE) and IsUnitEnemy(u,GetOwningPlayer(GetTriggerUnit()))==true
endfunction
//===============================================================================================
//===============================================================================================
//===============================================================================================
globals
private xedamage xed
endglobals
private struct Data
timer t
unit c
real sx
real sy
xefx array fx_bolt[N_BOLT]
xefx array fx_ray[N_BOLT]
xefx array fx_ray_2[N_BOLT]
xefx array fx_bolt_2[N_BOLT]
real ex
real ey
integer lvl
real duration = 0.00
real spiral
private static thistype temp
//Creation du cercle
private static method Create takes unit caster, real x, real y returns thistype
local thistype this = thistype.allocate()
local integer i = 0
local real a = (GetUnitFacing(caster) + 360 / N_BOLT + 90) * bj_DEGTORAD
set .c = caster
set .sx = x
set .sy = y
set .t = NewTimer()
set .lvl = GetUnitAbilityLevel(.c, SPELL_ID)
set .spiral = 0
loop
set .ex = .sx + GetAoE(.lvl) * Cos(a)
set .ey = .sy + GetAoE(.lvl) * Sin(a)
set .fx_bolt[i] = xefx.create(.ex, .ey, a + bj_PI / 2 )
set .fx_bolt[i].fxpath = FX_BOLT
set .fx_bolt[i].scale = FX_SCALE_BOLT_INIT
set .fx_bolt[i].z = 60.
call .fx_bolt[i].recolor(RED, GREEN, BLUE, ALPHA)
set .fx_bolt_2[i] = xefx.create(.ex, .ey, a + bj_PI / 2 )
set .fx_bolt_2[i].fxpath = FX_BOLT
set .fx_bolt_2[i].scale = FX_SCALE_BOLT_INIT
set .fx_bolt_2[i].z = 60.
call .fx_bolt_2[i].recolor(RED, GREEN, BLUE, ALPHA)
set .fx_ray[i] = xefx.create(.ex, .ey, a + bj_PI / 2 )
set .fx_ray[i].fxpath = FX_RAY
set .fx_ray[i].scale = FX_SCALE_RAY
set .fx_ray[i].z = 60.
call .fx_ray[i].recolor(RED, GREEN, BLUE, ALPHA)
set .fx_ray_2[i] = xefx.create(.ex, .ey, a + bj_PI / 2 )
set .fx_ray_2[i].fxpath = FX_RAY
set .fx_ray_2[i].scale = FX_SCALE_RAY
set .fx_ray_2[i].z = 60.
call .fx_ray_2[i].recolor(RED, GREEN, BLUE, ALPHA)
set a = a + (2 * bj_PI / N_BOLT)
set i = i + 1
exitwhen i >= N_BOLT
endloop
call SetTimerData(.t, this)
call TimerStart(.t, XE_ANIMATION_PERIOD, true, function thistype.onMove)
return this
endmethod
//Rotation des FX
private static method onMove takes nothing returns nothing
local thistype this = thistype(GetTimerData(GetExpiredTimer()))
local integer i = 0
local real j = -1
local unit u = null
local real x
local real y
local real distance
set temp = this
set x = .sx - .fx_bolt_2[i].x
set y = .sy - .fx_bolt_2[i].y
set distance = SquareRoot(x*x + y*y)
if distance < MIN_DIST then
loop
call .fx_bolt_2[i].destroy()
call .fx_ray_2[i].destroy()
set .fx_bolt_2[i] = xefx.create(.fx_bolt[i].x, .fx_bolt[i].y, (GetUnitFacing(.c) + 360 / N_BOLT + 90) * bj_DEGTORAD + bj_PI / 2 )
set .fx_bolt_2[i].fxpath = FX_BOLT
set .fx_bolt_2[i].scale = FX_SCALE_BOLT_INIT
set .fx_bolt_2[i].z = 60.
call .fx_bolt_2[i].recolor(RED, GREEN, BLUE, ALPHA)
set .fx_ray_2[i] = xefx.create(.fx_bolt[i].x, .fx_bolt[i].y, (GetUnitFacing(.c) + 360 / N_BOLT + 90) * bj_DEGTORAD + bj_PI / 2 )
set .fx_ray_2[i].fxpath = FX_RAY
set .fx_ray_2[i].scale = FX_SCALE_RAY
set .fx_ray_2[i].z = 60.
call .fx_ray_2[i].recolor(RED, GREEN, BLUE, ALPHA)
set i = i + 1
exitwhen i >= N_BOLT
endloop
call GroupEnumUnitsInRange(ENUM_GROUP, .sx, .sy, GetAoE(.lvl), null)
loop
set u = FirstOfGroup(ENUM_GROUP)
if IsValidTarget(u) then
call xed.damageTarget(.c, u, GetDamages(.lvl))
endif
call GroupRemoveUnit(ENUM_GROUP, u)
exitwhen u == null
endloop
set .spiral = SPIRAL(.lvl)
endif
if distance >= GetAoE(.lvl) then
set j = -1.
endif
set .spiral = .spiral + j * SPIRAL(.lvl)
set i = 0
loop
set .fx_bolt[i].xyangle = .fx_bolt[i].xyangle + GetSpeed(.lvl)
set .fx_bolt[i].x = .sx + GetAoE(.lvl) * Cos(.fx_bolt[i].xyangle - bj_PI / 2)
set .fx_bolt[i].y = .sy + GetAoE(.lvl) * Sin(.fx_bolt[i].xyangle - bj_PI / 2)
set .fx_ray[i].xyangle = .fx_ray[i].xyangle + GetSpeed(.lvl)
set .fx_ray[i].x = .sx + GetAoE(.lvl) * Cos(.fx_ray[i].xyangle - bj_PI / 2)
set .fx_ray[i].y = .sy + GetAoE(.lvl) * Sin(.fx_ray[i].xyangle - bj_PI / 2)
set .fx_bolt_2[i].xyangle = .fx_bolt[i].xyangle + GetSpeed(.lvl)
set .fx_bolt_2[i].x = .sx + (GetAoE(.lvl) + .spiral) * Cos(.fx_bolt[i].xyangle - bj_PI / 2)
set .fx_bolt_2[i].y = .sy + (GetAoE(.lvl) + .spiral) * Sin(.fx_bolt[i].xyangle - bj_PI / 2)
set .fx_ray_2[i].xyangle = .fx_ray[i].xyangle + GetSpeed(.lvl)
set .fx_ray_2[i].x = .sx + (GetAoE(.lvl) + .spiral) * Cos(.fx_ray[i].xyangle - bj_PI / 2)
set .fx_ray_2[i].y = .sy + (GetAoE(.lvl) + .spiral) * Sin(.fx_ray[i].xyangle - bj_PI / 2)
set i = i + 1
exitwhen i >= N_BOLT
endloop
set .duration = .duration + XE_ANIMATION_PERIOD
if .duration >= SPELL_DUR or (GetUnitCurrentOrder(.c) != String2OrderIdBJ(ORDER_ID)) or GetWidgetLife(.c) <= 0.405 then
call .destroy()
call ReleaseTimer(GetExpiredTimer())
endif
endmethod
private method onDestroy takes nothing returns nothing
local integer i = 0
loop
call .fx_bolt[i].destroy()
call .fx_bolt_2[i].destroy()
call .fx_ray[i].destroy()
call .fx_ray_2[i].destroy()
set i = i + 1
exitwhen i >= N_BOLT
endloop
endmethod
private static method Conditions takes nothing returns boolean
local thistype this
if GetSpellAbilityId40;) == SPELL_ID then
set this = thistype.Create40;GetTriggerUnit40;), GetSpellTargetX40;), GetSpellTargetY40;))
endif
return false
endmethod
private function DamageOptions takes xedamage spellDamage returns nothing
set spellDamage.dtype = DAMAGE_TYPE_UNIVERSAL
set spellDamage.atype = ATTACK_TYPE_NORMAL
set spellDamage.exception = UNIT_TYPE_STRUCTURE
set spellDamage.visibleOnly = true
set spellDamage.damageSelf = true
set spellDamage.damageAllies = true
set spellDamage.allyfactor = -1.0
endfunction
private function IsValidTarget takes unit u, data s returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD) and IsUnitType(u,UNIT_TYPE_STRUCTURE)==false and IsUnitAlly(u,GetOwningPlayer(s.caster))==true and IsUnitVisible(u,GetOwningPlayer(s.caster))==true and GetUnitLifePercent(u) != 100.00
endfunction
//===============================================================================================
//===============================================================================================
//===============================================================================================
globals
private xedamage xed
endglobals
//struct for the missile
private struct heal
timer t
unit caster
unit target
xefx fx
real x
real y
integer lvl
boolean bonus=false
static method create takes unit c, unit tr, real x, real y, integer lvl returns thistype
local thistype this = heal.allocate()
local real a = Atan2(y-GetUnitY(tr),x-GetUnitX(tr))
set .x = x
set .y = y
set .caster = c
set .target = tr
set .lvl = lvl
set .t = NewTimer()
set .fx = xefx.create(x,y,a)
set .fx.fxpath = FX_MISSILE
set .fx.z = INIT_H
set .fx.scale = SCALE
call .fx.recolor(RED, GREEN, BLUE, ALPHA)
call SetTimerData(.t, this)
call TimerStart(.t, XE_ANIMATION_PERIOD, true, function heal.onMove)
return this
endmethod
private static method onMove takes nothing returns nothing
local thistype this = thistype(GetTimerData(GetExpiredTimer()))
local real x = GetUnitX(.target) - .fx.x
local real y = GetUnitY(.target) - .fx.y
local real z = (GetUnitFlyHeight(.target)-.fx.z) + GetSpeed(.lvl)
local real distance = SquareRoot(x*x + y*y + z*z)
local real angle1 = Atan2(y, x)
local real angle2 = Acos(z / distance)
local real angle3 = Atan2(z, SquareRoot(x * x + y * y))
if not IsUnitType(.target, UNIT_TYPE_DEAD) then
if (distance > MIN_DIST) then
set .fx.xyangle = angle1
set .fx.x = .fx.x + GetSpeed(.lvl) * Cos(angle1) * Sin(angle2)
set .fx.y = .fx.y + GetSpeed(.lvl) * Sin(angle1) * Sin(angle2)
set .fx.z = .fx.z + GetSpeed(.lvl) * Cos(angle2)
set .fx.zangle = angle3
else
call xed.damageTarget(.caster, .target, GetHeal(.lvl))
call DestroyEffect(AddSpecialEffectTarget(FX_HEAL, .target, HEAL_ATTCH))
call .fx.destroy()
endif
else
call .fx.destroy()
call .destroy()
endif
endmethod
private method onDestroy takes nothing returns nothing
call ReleaseTimer(.t)
endmethod
endstruct
//struct for the caster
private struct data
unit caster
timer t
xefx fx
real x
real y
integer lvl
integer nw
integer nt
private static thistype temp
static method create takes nothing returns thistype
local thistype this = data.allocate()
set .caster = GetTriggerUnit()
set .lvl = GetUnitAbilityLevel(.caster,SPELL_ID)
set .nw = Waves(.lvl)
set .nt = MaxTarget(.lvl)
set .t = NewTimer()
call SetTimerData(.t, this)
call TimerStart(.t, CASTING_TIME, true, function thistype.onFinish)
return this
endmethod
private static method onFinish takes nothing returns nothing
local thistype this = thistype40;GetTimerData40;GetExpiredTimer40;)))
local real a
local unit u
local heal h
local integer i = .nt
local unit r
if .nw > 0 then
set .x = GetUnitX40;.caster)
set .y = GetUnitY40;.caster)
set a = Atan240;.y - GetUnitY40;.caster), .x - GetUnitX40;.caster))
set .fx = xefx.create40;x,y,a)
set .fx.fxpath = FX_CASTER
set .fx.z = INIT_H
set .fx.scale = SCALE_2
set .nw = .nw - 1
set temp = this
call GroupEnumUnitsInRange40;ENUM_GROUP, .x, .y, GetAoE40;.lvl), null)
loop
exitwhen i == 0
set r = GroupPickRandomUnit40;ENUM_GROUP)
if IsValidTarget40;r, temp) then
set h = heal.create40;temp.caster, r, temp.x, temp.y, temp.lvl)
call GroupRemoveUnit40;ENUM_GROUP, r)
set i = i - 1
else
call GroupRemoveUnit40;ENUM_GROUP, r)
endif
endloop
loop
set u = FirstOfGroup40;ENUM_GROUP)
call GroupRemoveUnit40;ENUM_GROUP, u)
exitwhen u == null
endloop
set u = null
set r = null
else
call .destroy40;)
endif
endmethod
Inscrit le: 21 Avr 2008 Messages: 1607 Sujets: 81 Spécialité en worldedit: Utiliser le travail des autres Médailles: 3 (En savoir plus...)
Posté le: 09/06/12 11:16 Sujet du message:
Mes autres sorts aussi utilisent ENUM_GROUP... C'est la library Group_Utils, est-ce que ça peut venir de la non destruction des groupes et de leur recyclage par cette library?
J'ai refait des tests avec les corrections de Tirlititi, je ne retrouve pas le bug. On verra bien, mais ça à l'air corrigé.
Merci beaucoup. _________________
Inscrit le: 23 Aoû 2007 Messages: 7146 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
Posté le: 09/06/12 12:06 Sujet du message:
J'ai juste jeté un coup d'oeil au deuxième script, y'a un truc qui m'a sauté aux yeux c'est cela :
Jass:
loop
set u = FirstOfGroup(ENUM_GROUP)
call GroupRemoveUnit(ENUM_GROUP, u)
exitwhen u == null
endloop
C'est complètement inutile, car à chaque appel GroupEnum, ENUM_GROUP est clear.
Sinon recycler des group devrait être complètement inutile car tout simplement moins efficace que Create/DestroyGroup.
Cela dit je ne l'ai pas testé mais c'est vrai pour les timer.
Mais oui ça pourrait être source d'un bug si tu utilises par ex un group qui est censé avoir été recyclé mais pas réutilisé, ou si utilises le même group. _________________
Inscrit le: 21 Avr 2008 Messages: 1607 Sujets: 81 Spécialité en worldedit: Utiliser le travail des autres Médailles: 3 (En savoir plus...)
Posté le: 09/06/12 12:33 Sujet du message:
Il faut le voir avec la boucle précédente.
En fait, je sélectionne des unités au hasard dans le groupe. Les unités peuvent être soignées ou pas, mais si je soigne le nombre max d'unité avant d'enlever toutes les unités du groupes, il en restera dans le groupe. Je pensais faire ça pour nettoyer le groupe et prévenir le fait d'avoir des unités en trop dedans. Quand je n'avais pas ajoutée cette boucle, il y avait des bugs.
loop
exitwhen i == 0
set r = GroupPickRandomUnit(ENUM_GROUP)
if IsValidTarget(r, temp) then
set h = heal.create(temp.caster, r, temp.x, temp.y, temp.lvl)
call GroupRemoveUnit(ENUM_GROUP, r)
set i = i - 1
else
call GroupRemoveUnit(ENUM_GROUP, r)
endif
endloop
loop
set u = FirstOfGroup(ENUM_GROUP)
call GroupRemoveUnit(ENUM_GROUP, u)
exitwhen u == null
endloop
Inscrit le: 23 Aoû 2007 Messages: 7146 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
Posté le: 09/06/12 12:43 Sujet du message:
Ouai mais nan.
Ça équivaut à un GroupClear non "safe", tu vois bien que tu te contentes d'enlever toutes les unités une à une dans cette loop, sans rien faire d'autre.
D'ailleurs ce clear faillira si ton groupe contient des "ghost" unit (unités retirées du jeu mais pas du group). _________________
Inscrit le: 21 Avr 2008 Messages: 1607 Sujets: 81 Spécialité en worldedit: Utiliser le travail des autres Médailles: 3 (En savoir plus...)
Posté le: 09/06/12 13:06 Sujet du message:
Troll-Brain a écrit:
Ouai mais nan.
haha, je vais la garder celle là
Donc tu me conseilles d'arrêter d'utiliser GroupUtils pour préférer des destructions de groupes?
Et d'utiliser GroupClear pour nettoyer les groupes? _________________
Inscrit le: 23 Aoû 2007 Messages: 7146 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
Posté le: 09/06/12 13:24 Sujet du message:
Oui, mais avoir un groupe que l'on ne détruit jamais tel que GROUP_ENUM est utile pour les énumérations instantanées tel qu'ici.
Tu n'as pas besoin de clear le group étant donné que chaque appel de GroupEnum... vide le groupe avant d'éventuellement en ajouter.
La loop que tu utilises pour clear le group est seulement utile si tu codes à l'intérieur.
En fait le but d'une telle loop n'est pas de clear le group, mais de parcourir toutes les unités d'un groupe sans devoir utiliser un ForGroup et donc diviser le code, en bonus c'est aussi plus efficace qu'un ForGroup.
Mais oui forcément ca vide le groupe.
Mais pour les groupes que tu as besoin de garder dans le temps, go UnitLL :p _________________
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