| 08-23-2009, 07:50 PM | #2 |
Well... Maybe it is only the BJ CreateNUnitsAtLoc that's buggy ? :S As I don't believe the the native CreateUnit bugs this way, right ? :o |
| 08-24-2009, 05:44 PM | #3 |
@Komaqtion: see EDIT first post BTW: Can't that VERY irritating 600 seconds between posts be removed? |
| 08-24-2009, 05:47 PM | #4 | |
Quote:
|
| 08-25-2009, 10:19 AM | #5 |
Anyway, why to you use "Owner of Triggering Unit" at some lines and "Owner of Casting Unit" at the others? EDIT: and try to put a temporary unit variable in the GUI code to refer to the Casting unit. I have this weird experience when I was a GUI user where the code fail to refer to the "Casting Unit" when I refer to it too many times in a trigger. Try to put the casting unit in a variable first. Maybe that will help. |
| 08-25-2009, 12:46 PM | #6 |
Are you sure the type of the dummy unit you are trying to create exists? And do you have any events running when a unit enters the map? If that's the case, try disabling those, to find the source of the problem. |
| 08-25-2009, 07:39 PM | #8 | |
Muahaha, that will teach you not to mess with GUI-wielding Grandpa here :p Anyway, what's the local unit dummy for here? JASS:
private function Loop takes nothing returns nothing
local Chain chain = GetTimerData(GetExpiredTimer())
local unit dummy = null
if chain.SetNextUnit() != true then
call chain.destroy()
call ReleaseTimer(GetExpiredTimer())
else
call chain.BanishAndLightning()
endif
endfunction
and you don't kill the dummy units after you create them here?? JASS:method BanishAndLightning takes nothing returns nothing local unit dummy = CreateUnit( GetOwningPlayer(.targets[0]), DUMMY, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), bj_UNIT_FACING) debug call BJDebugMsg("BanishAndLightning") call UnitAddAbility(dummy, BANISHID) call IssueTargetOrder(dummy, "banish", .targets[.index]) set dummy = CreateUnit( GetOwningPlayer(.targets[0]), DUMMY, GetUnitX(.targets[.index - 1]), GetUnitY(.targets[.index - 1]), bj_UNIT_FACING) call UnitAddAbility(dummy, LIGHTNINGID) call IssueTargetOrder(dummy, "chainlightning", .targets[.index]) set dummy = null endmethod EDIT: Quote:
Try nulling the .targets array everytime you destroy the struct. Structs that are destroyed doesn't automatically null its values, so the previous units are still referred to by the .targets variable from the struct that was created at the first cast. |
| 08-25-2009, 08:14 PM | #9 |
Don't worry about nulling your TimerUtils timers - they are never destroyed, so the handle index doesn't need to be recycled. You might want to consider making your units group a global (or static) group and modifying your boolexpr such that it never admits units into the group - only parses through them and makes the appropriate adjustments if it meets the conditions. In that way, you could probably also avoid the GetTriggerUnit() call within the boolexpr by using a temp global that you set the casting unit to. It would also cut out the FirstOfGroup loop and speed things up a bit. That might not solve the CreateUnit problem but may help anyway. |
| 08-27-2009, 05:52 AM | #10 |
It's still not working, still same problem. I nulled the array onDestroy. JASS:scope ChainBanish initializer Init globals private constant integer SPELLID = 'A01O' private constant integer BANISHID = 'A00P' private constant integer LIGHTNINGID = 'A01Q' private constant integer TARGETS = 7 private constant integer DUMMY = 'h009' private constant real PERIOD = 0.50 private constant real BOUNCERANGE = 700.00 endglobals //============================================================================= globals private boolexpr be private constant integer TARGETSPLUSONE = TARGETS + 1 endglobals private function isUnitEnemy takes nothing returns boolean return IsUnitEnemy(GetEnumUnit(), GetOwningPlayer(GetTriggerUnit())) endfunction private struct Chain unit array targets[TARGETSPLUSONE] integer index static method create takes unit u1, unit u2 returns Chain local Chain chain = Chain.allocate() set chain.targets[0] = u1 set chain.targets[1] = u2 set chain.index = 1 return chain endmethod method onDestroy takes nothing returns nothing local integer index = 0 loop exitwhen index > TARGETS set .targets[index] = null set index = index + 1 endloop endmethod method BanishAndLightning takes nothing returns nothing local unit dummy = CreateUnit( GetOwningPlayer(.targets[0]), DUMMY, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), bj_UNIT_FACING) debug call BJDebugMsg("BanishAndLightning") call UnitAddAbility(dummy, BANISHID) call IssueTargetOrder(dummy, "banish", .targets[.index]) set dummy = CreateUnit( GetOwningPlayer(.targets[0]), DUMMY, GetUnitX(.targets[.index - 1]), GetUnitY(.targets[.index - 1]), bj_UNIT_FACING) call UnitAddAbility(dummy, LIGHTNINGID) call IssueTargetOrder(dummy, "chainlightning", .targets[.index]) set dummy = null endmethod method SetNextUnit takes nothing returns boolean local group units = NewGroup() local integer i = 0 if .index == (TARGETS) then call ReleaseGroup(units) debug call BJDebugMsg("targets full") return false endif call GroupEnumUnitsInRange(units, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), BOUNCERANGE, be) set .index = .index + 1 loop exitwhen i == .index if .targets[i] == FirstOfGroup(units) then call GroupRemoveUnit( units, FirstOfGroup(units)) set i = -1 endif set i = i + 1 endloop set .targets[.index] = FirstOfGroup(units) call ReleaseGroup(units) if .targets[.index] != null then debug call BJDebugMsg("unit found") return true else debug call BJDebugMsg("unit not found") return false endif endmethod endstruct private function Loop takes nothing returns nothing local Chain chain = GetTimerData(GetExpiredTimer()) if chain.SetNextUnit() != true then call ReleaseTimer(GetExpiredTimer()) call chain.destroy() else call chain.BanishAndLightning() endif endfunction private function Actions takes nothing returns nothing local Chain chain = Chain.create(GetTriggerUnit(), GetSpellTargetUnit()) local timer t = NewTimer() call chain.BanishAndLightning() call SetTimerData( t, chain) call TimerStart( t, PERIOD, true, function Loop) endfunction private function Conditions takes nothing returns boolean return GetSpellAbilityId() == SPELLID endfunction private function Init takes nothing returns nothing local trigger gg_trg_Chain_Banish = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( gg_trg_Chain_Banish, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition( gg_trg_Chain_Banish, Condition( function Conditions ) ) call TriggerAddAction( gg_trg_Chain_Banish, function Actions ) set be = Condition(function isUnitEnemy) endfunction endscope @TheWye: -I forgot to remove the line with the local dummy -My dummies have negative regen @Zerzax: -The CreateUnit problem is solved. -Could you explain a bit more what you mean with a global group? I don't understand it. |
| 08-27-2009, 06:59 AM | #11 |
Hurmm... what did I miss here.. I'm not using TimerUtils or GroupUtils (or whatever it is called) so I'm not sure about this.... Does Code:
call ReleaseGroup(units) EDIT: even if it doesn't it still wouldn't fix your problem would it..?..?? hmmm... EDIT2: so I assume that this JASS:if .targets[.index] != null then debug call BJDebugMsg("unit found") return true else debug call BJDebugMsg("unit not found") return false endif always returns false after the first cast? EDIT3: what if you add a tempUnit variable here: JASS:
call GroupEnumUnitsInRange(units, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), BOUNCERANGE, be)
set .index = .index + 1
loop
exitwhen i == .index
set tempUnit= FirstOfGroup(units)
if .targets[i] == tempUnit then
call GroupRemoveUnit( units, tempUnit )
set i = -1
endif
set i = i + 1
endloop
set .targets[.index] = FirstOfGroup(units)
Do you think it will help? (your code is quite confusing to me :p) Anyway, if I were you, I would do this part this way instead: JASS:
call GroupEnumUnitsInRange(units, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), BOUNCERANGE, be)
set .index = .index + 1
loop
exitwhen i == .index
call GroupRemoveUnit( units, .targets[i])
set i = i + 1
endloop
set .targets[.index] = FirstOfGroup(units)
|
| 08-27-2009, 02:40 PM | #12 |
I didn't look at the code closely enough, so I don't know if this will apply exactly. Ooh, and I guess group recycling is fine as well. But you can try doing this: JASS:struct static group enumGroup // now you have a global group that never gets destroyed. static boolexpr be // or a global, doesnt matter static integer tempCount = 0 // set this to 0 before using GroupEnumUnits() static player tempOwner = null // set this before using GroupEnumUnits() static Chain temp // same as above static method filter takes nothing returns boolean local unit enum = GetFilterUnit() if IsUnitEnemy(enum, .tempOwner) and .tempCount <= TARGETS then set .tempCount = .tempCount + 1 if .tempCount == .temp.index then set enum == .temp.targets[.temp.index] endif endif return false endmethod endstruct I'm pretty unfamiliar with the idea behind this but I hope this helps anyway, no more firstofGroup or trigger natives |
| 08-28-2009, 05:36 PM | #13 |
The GetTriggerUnit in the boolexpr was bugging too. I think GetBlablaUnit only works in the function that is called by the trigger. The only thing i changed was storing the owner of the caster in a variable and using the variable inside the condition func. Final code (ignoring additional optimising): JASS:scope ChainBanish initializer Init globals private constant integer SPELLID = 'A01O' private constant integer BANISHID = 'A00P' private constant integer LIGHTNINGID = 'A01Q' private constant integer TARGETS = 7 private constant integer DUMMY = 'h009' private constant real PERIOD = 0.50 private constant real BOUNCERANGE = 700.00 endglobals //============================================================================= globals private boolexpr be private constant integer TARGETSPLUSONE = TARGETS + 1 private player tempPlayer endglobals private function isUnitEnemy takes nothing returns boolean return IsUnitEnemy(GetFilterUnit(), tempPlayer) endfunction private struct Chain unit array targets[TARGETSPLUSONE] integer index static method create takes unit u1, unit u2 returns Chain local Chain chain = Chain.allocate() set chain.targets[0] = u1 set chain.targets[1] = u2 set chain.index = 1 return chain endmethod method onDestroy takes nothing returns nothing local integer index = 0 loop exitwhen index > TARGETS set .targets[index] = null set index = index + 1 endloop endmethod method BanishAndLightning takes nothing returns nothing local unit dummy = CreateUnit( GetOwningPlayer(.targets[0]), DUMMY, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), bj_UNIT_FACING) debug call BJDebugMsg("BanishAndLightning") call UnitAddAbility(dummy, BANISHID) call IssueTargetOrder(dummy, "banish", .targets[.index]) set dummy = CreateUnit( GetOwningPlayer(.targets[0]), DUMMY, GetUnitX(.targets[.index - 1]), GetUnitY(.targets[.index - 1]), bj_UNIT_FACING) call UnitAddAbility(dummy, LIGHTNINGID) call IssueTargetOrder(dummy, "chainlightning", .targets[.index]) set dummy = null endmethod method SetNextUnit takes nothing returns boolean local group units = NewGroup() local integer i = 0 if .index == (TARGETS) then call ReleaseGroup(units) debug call BJDebugMsg("targets full") return false endif set tempPlayer = GetOwningPlayer(.targets[0]) call GroupEnumUnitsInRange(units, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), BOUNCERANGE, be) set .index = .index + 1 loop exitwhen i == .index call GroupRemoveUnit( units, .targets[i]) set i = i + 1 endloop set .targets[.index] = FirstOfGroup(units) call ReleaseGroup(units) if .targets[.index] != null then debug call BJDebugMsg("unit found") return true else debug call BJDebugMsg("unit not found") return false endif endmethod endstruct private function Loop takes nothing returns nothing local Chain chain = GetTimerData(GetExpiredTimer()) if chain.SetNextUnit() != true then call ReleaseTimer(GetExpiredTimer()) call chain.destroy() else call chain.BanishAndLightning() endif endfunction private function Actions takes nothing returns nothing local Chain chain = Chain.create(GetTriggerUnit(), GetSpellTargetUnit()) local timer t = NewTimer() call chain.BanishAndLightning() call SetTimerData( t, chain) call TimerStart( t, PERIOD, true, function Loop) endfunction private function Conditions takes nothing returns boolean return GetSpellAbilityId() == SPELLID endfunction private function Init takes nothing returns nothing local trigger gg_trg_Chain_Banish = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( gg_trg_Chain_Banish, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition( gg_trg_Chain_Banish, Condition( function Conditions ) ) call TriggerAddAction( gg_trg_Chain_Banish, function Actions ) set be = Condition(function isUnitEnemy) endfunction endscope When i can i will give you both some more rep :), finally solved this one month old problem. |
| 08-29-2009, 12:43 AM | #14 |
I'm glad it works :D |
| 08-29-2009, 08:59 AM | #15 |
Ahhh I see. Good for you then!! And I learn something from this as well :) |
