| 01-19-2006, 05:36 AM | #1 |
Edit: Fixed a lot of dumb mistakes (just had to step back from it for a bit) I'm trying to customize the Bladestorm ability so it deals damage to enemies around the target every second equal to an integer variable I have stored. To do this so multiple units can do it at once, I tried converting this into custom text so I could use Local Variables, but I don't know how to pass local variables without getting the game to crash. Code:
Whirlwind
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Whirlwind
Actions
For each (Integer A) from 1 to 5, do (Actions)
Loop - Actions
Unit Group - Pick every unit in (Units in (Region centered at (Position of (Casting unit)) with size (300.00, 300.00))) and do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Picked unit) belongs to an enemy of (Owner of (Casting unit))) Equal to True
Then - Actions
Game - Display to (All players) the text: P!
Unit - Cause (Casting unit) to damage (Picked unit), dealing (4.00 x (Real(pStrength[(Player number of (Owner of (Casting unit)))]))) damage of attack type Normal and damage type Normal
Else - Actions
Wait 1.00 game-time secondsTurns into.. Code:
function Trig_Whirlwind_Local_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'A01F' ) ) then
return false
endif
return true
endfunction
function Trig_Whirlwind_Local_Func001Func001Func001C takes nothing returns boolean
if ( not ( IsUnitEnemy(GetEnumUnit(), GetOwningPlayer(GetSpellAbilityUnit())) == true ) ) then
return false
endif
return true
endfunction
function Trig_Whirlwind_Local_Func001Func001A takes nothing returns nothing
if ( Trig_Whirlwind_Local_Func001Func001Func001C() ) then
call DisplayTextToForce( GetPlayersAll(), "TRIGSTR_805" )
call UnitDamageTargetBJ( GetSpellAbilityUnit(), GetEnumUnit(), ( 4.00 * I2R(udg_pStrength[GetConvertedPlayerId(GetOwningPlayer(GetSpellAbilityUnit()))]) ), ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL )
else
endif
endfunction
function Trig_Whirlwind_Local_Actions takes nothing returns nothing
local unit whirly = GetSpellAbilityUnit()
set bj_forLoopAIndex = 1
set bj_forLoopAIndexEnd = 5
loop
exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
call ForGroupBJ( GetUnitsInRectAll(RectFromCenterSizeBJ(GetUnitLoc(whirly), 300.00, 300.00)), function Trig_Whirlwind_Local_Func001Func001A )
call PolledWait( 1.00 )
set bj_forLoopAIndex = bj_forLoopAIndex + 1
endloop
endfunction
//===========================================================================
function InitTrig_Whirlwind_Local takes nothing returns nothing
set gg_trg_Whirlwind_Local = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Whirlwind_Local, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Whirlwind_Local, Condition( function Trig_Whirlwind_Local_Conditions ) )
call TriggerAddAction( gg_trg_Whirlwind_Local, function Trig_Whirlwind_Local_Actions )
endfunctionlocal unit whirly is set in Trig_Whirlwind_Local_Actions, which calls 2 other functions and changing the 'takes nothing' to 'takes unit whirly' doesn't work. Any ideas? |
| 01-19-2006, 05:53 AM | #2 |
I didn't quite understand what you need a local here for. Your trigger does not work properly? Or is it multiinstanceability problem? Anyway, here is one of the generic solutions to i-cant-pass-anything-to-ForGroup-problem If the custom value of your casting unit is not used, you can store the needed integer in there, and the retrieve that custom value when you need an integer. |
| 01-19-2006, 06:10 AM | #3 |
Unfortunately, the custom value is used for something important. I want to use Local Variables so that 2 units can do this at the same time, but can't because I don't know how to pass the unit's Local Variable in the above code. |
| 01-19-2006, 06:28 AM | #4 |
Part of your problem lies in this call: Code:
Unit Group - Pick every unit in (Units in (Region centered at (Position of (Casting unit)) with size (300.00, 300.00)) matching (((Picked unit) belongs to an enemy of (Player((Player number of (Owner of (Casting unit)))))) Equal to True)) and do (Actions) |
| 01-19-2006, 06:42 AM | #5 |
Yeah, fixed that, it was generally sloppy on my part. The local variable thing is keeping me up though :(, though I'm sure if it works it'll give me a larger variety of spells I can come up with. |
| 01-19-2006, 09:09 AM | #6 |
Okaaay First of all, no way you can implement it in GUI. So we will be working with jass here So i took the GUI-generated code provided as base, and here is what i did with it. a) integrated all action functions in one function. you do not really need more here b) Got rid of ForLoopIntegerA() (which is global) and replaced it with local variable i c)Got rid of ForGroup, by using FirstOfGroup instead. The algorithm is: 1) start loop. repeat 5 times 2) You store the group of targets in a local 3) Start sub-loop, repeat until targets group is empty 4) you store the first unit in group in a local 5) you process this unit for damage receving/non receiving 6) you remove that unit from group of targets 7) you repeat the sub-loop until targets group is empty 8) wait 1 second 9) you repeat the main loop 5 times 10) you clean up so there are no memory leaks What we did here is basically took apart ForGroup function and reimplemented it, using more basic functions, allowing transfer of locals. the code looks like this: JASS:function Trig_Whirlwind_Local_Conditions takes nothing returns boolean return GetSpellAbilityId() == 'A01F' endfunction function Trig_Whirlwind_Local_Actions takes nothing returns nothing local integer i = 0 local unit whirly = GetSpellAbilityUnit() local group targets local unit target local real damage = ( 4.00 * I2R(udg_pStrength[GetConvertedPlayerId(GetOwningPlayer(whirly))]) loop exitwhen i == 5 set targets = GetUnitsInRectAll(RectFromCenterSizeBJ(GetUnitLoc(whirly), 300.00, 300.00)) loop exitwhen CountUnitsInGroup(targets)==0 set target = FirstOfGroup(targets) if (IsUnitEnemy(target,GetOwningPlayer(whirly)) == true) then call DisplayTextToForce( GetPlayersAll(), "TRIGSTR_805" ) call UnitDamageTargetBJ( whirly, target, damage ), ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL ) endif call GroupRemoveUnit(targets, target) endloop call PolledWait( 1.00 ) set i = i + 1 endloop call DestroyGroup(targets) endfunction //=========================================================================== function InitTrig_Whirlwind_Local takes nothing returns nothing set gg_trg_Whirlwind_Local = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( gg_trg_Whirlwind_Local, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition( gg_trg_Whirlwind_Local, Condition( function Trig_Whirlwind_Local_Conditions ) ) call TriggerAddAction( gg_trg_Whirlwind_Local, function Trig_Whirlwind_Local_Actions ) endfunction Now i am not a really gosu coder and usually after i write the code for the first time, it has a lot of mistakes, so i'll give you the final version when i get back home and run it through Jass Shop Pro. Also i tend to forget memory-leaking stuff a lot, so if i missed something, let the true gosu coders here correct me :) Feel free to ask any questions about how this works. Also don't hesistate to ask if you feel you see any mistakes. |
| 01-19-2006, 02:09 PM | #7 |
Lookin' good, just a couple paren problems and it seems to work alright. Thanks for all the help :) |
| 01-19-2006, 02:17 PM | #8 |
Set all your handles to null at the end of the function set whirly=null set targets=null set target=null Then this isn't a problem, but I like to just make it look cleaner if (IsUnitEnemy(target,GetOwningPlayer(whirly)) == true) then could simply be if IsUnitEnemy(target,GetOwningPlayer(whirly)) then However, I think that I would add that condition into the initial group selection rather than individual units. This way it is only checking the condition in the outer loop. |
| 01-19-2006, 02:50 PM | #9 |
and changing it to takes unit won't work because functions to be used as code type arguments (for conditions / actions) can't have arguments. You can always use a bridge global you set the value of the global variable to the one of the local, then in the for group function you use the global. Also note that you could use GetTriggerUnit() which does survive to waits. And you'd need to use local integer variables instead of the default for loop stuff which are globals too. Because you are using waits inside that loop |
| 01-19-2006, 10:55 PM | #10 |
Well Actually, You could get it to work in gui. However it would require setting the damage of the spell to 0.01 or something similar and then detecting when an unit takes that damage. Unfortunately if you try using any unit takes damage on the advanced triggers it won't work, because the damage source wont be detected. So what you have to do, and this is kind of sloppy, is remove all the preplaced units on the map (if they are all put by triggers in the first place its even better) and replace them using a trigger. you then add to the bladestorm event (entering unit takes damage) and create a condition requiring the damage to be 0.01. Sloppy, but I'm fairly certain its the only way to do it in GUI. And if anyone knows how to make it so damage source will work when using the advanced trigger: (any unit takes damage), let me know :) |
