- Joined
- Oct 10, 2011
- Messages
- 518
I got problems with my spell. Here it is an aura that increases the MaxHp of nearby allies. There is 2 structs Data and Buff.
Data checks the unit that are around the owner of the buff
Buff is a struct for each allies that got the bonus of life
To write the code clearly I made an attribute d on the Buff structure that contains the Data structure of the Aura.
I got the following error :
I think the problem is that the struct Data is below the struct Buff so when there is a call from one to te other one there is the bug.
I changed the order of the 2 structs and I had the same bug but for the calls from Data to Buff.
I hope someone can help me
Data checks the unit that are around the owner of the buff
Buff is a struct for each allies that got the bonus of life
To write the code clearly I made an attribute d on the Buff structure that contains the Data structure of the Aura.
I got the following error :
I think the problem is that the struct Data is below the struct Buff so when there is a call from one to te other one there is the bug.
I changed the order of the 2 structs and I had the same bug but for the calls from Data to Buff.
vJASS:
scope TaurenForce initializer Init_TaurenForce
globals
private constant integer BUFF_ID = 'AAAA'
private constant real AREA = 900
private constant real INTERVAL = 0.5
private constant real INTERVAL_BUFF = 1
endglobals
private function getBonusLife takes real lvl returns real
return 100 * lvl
endfunction
private struct Buff
static Buff array B
static integer BT = 0
static timer T = null
unit target
Data d
real currentLvl
boolean state
private method onDestroy takes nothing returns nothing
local real bonusLife = getBonusLife(.currentLvl)
call GroupRemoveUnit(.d.G1, .target) // <== THE BUG IS ON THAT LINE
call UnitRemoveAbility(.target, BUFF_ID)
call SetUnitMaxHP(.target, (GetUnitMaxHP(.target) - bonusLife))
if GetUnitState(.target, UNIT_STATE_LIFE) > bonusLife then
call regenLife(.target, -bonusLife)
else
call SetUnitState(.target, UNIT_STATE_LIFE, 1)
endif
set .target = null
endmethod
private method checksAura takes nothing returns nothing
local real X = GetUnitX(.d.caster)
local real Y = GetUnitY(.d.caster)
local real X1 = GetUnitX(.target)
local real Y1 = GetUnitY(.target)
local real finalBonus = getBonusLife(.d.lvl)
local real currentBonus = getBonusLife(.currentLvl)
if distancePoints(X, Y, X1, Y1) > AREA then
set .state = false
else
if currentBonus != finalBonus then
set .currentLvl = .d.lvl
call SetUnitMaxHP(.target, (GetUnitMaxHP(.target) + finalBonus - currentBonus))
call regenLife(.target, (finalBonus - currentBonus))
endif
endif
endmethod
static method update takes nothing returns nothing
local Buff b
local integer I = 0
loop
set I = I + 1
set b = .B[I]
if isAlive(b.target) then
if isAlive(b.d.caster) then
call b.checksAura()
else
set b.state = false
endif
else
if not(IsUnitType(b.target, UNIT_TYPE_HERO)) then
set b.state = false
endif
endif
if not(b.state) then
call b.destroy()
set .B[I] = .B[.BT]
set .BT = .BT - 1
set I = I - 1
endif
exitwhen I >= .BT
endloop
if .BT <= 0 then
call PauseTimer(.T)
set .BT = 0
endif
endmethod
static method addBuff takes unit U1, real lvl, Data d returns nothing
local Buff b = Buff.create()
set b.target = U1
set b.currentLvl = lvl
set b.d = d
set b.state = true
set .BT = .BT + 1
set .B[.BT] = b
if .BT == 1 then
call TimerStart(.T, INTERVAL_BUFF, true, function Buff.update)
endif
endmethod
endstruct
private struct Data
static Data array D
static integer DT = 0
static timer T = null
static group G = null
unit caster
group G1
real lvl
private method onDestroy takes nothing returns nothing
call DestroyGroup(.G1)
set .caster = null
set .G1 = null
endmethod
private method applyBuff takes nothing returns nothing
local player P = GetOwningPlayer(.caster)
local unit U2
local real bonusLife = getBonusLife(.lvl)
call GroupEnumUnitsInRange(.G, GetUnitX(.caster), GetUnitY(.caster), AREA, null)
loop
set U2 = FirstOfGroup(.G)
exitwhen U2 == null
call GroupRemoveUnit(.G, U2)
if isAlive(U2) and IsUnitAlly(U2, P) and not(isBuilding(U2)) and IsUnitInGroup(U2, .G1) then
call GroupAddUnit(.G1, U2)
call Buff.addBuff(U2, lvl, this)
call SetUnitMaxHP(U2, GetUnitMaxHP(U2) + bonusLife)
call regenLife(U2, bonusLife)
endif
set U2 = null
endloop
set P = null
endmethod
static method update takes nothing returns nothing
local Data d
local integer I = 0
local integer currentLvl
loop
set I = I + 1
set d = .D[I]
if isAlive(d.caster) then
set currentLvl = GetUnitAbilityLvl(d.caster, BUFF_ID)
if d.lvl != currentLvl then
set d.lvl = currentLvl
endif
call d.applyBuff()
endif
exitwhen I >= .DT
endloop
endmethod
endstruct
function Trig_TaurenForce_Conditions takes nothing returns boolean
return GetLearnedSkill() == 'A020' and GetUnitAbilityLevel(GetTriggerUnit(), 'A020' ) == 1
endfunction
function Trig_TaurenForce_Actions takes nothing returns nothing
local unit U = GetLearningHero()
local real lvl = I2R(GetUnitAbilityLevel(U, GetLearningHeroSkill()))
local Data d
set d = Data.create()
set d.caster = U
set d.G1 = CreateGroup()
set d.lvl = 1
set Data.DT = Data.DT + 1
set Data.D[Data.DT] = d
if Data.DT == 1 then
call TimerStart(Data.T, INTERVAL, true, function Data.update)
endif
set U = null
endfunction
//===========================================================================
function Init_TaurenForce takes nothing returns nothing
local trigger T = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( T, EVENT_PLAYER_HERO_SKILL )
call TriggerAddCondition( T, Condition( function Trig_TaurenForce_Conditions ) )
call TriggerAddAction( T, function Trig_TaurenForce_Actions )
set Data.T = CreateTimer()
set Data.G = CreateGroup()
set Buff.T = CreateTimer()
set T = null
endfunction
endscope
I hope someone can help me
Last edited: