HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Custom Damaged Bladestorm

01-19-2006, 05:36 AM#1
combatken
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 seconds

Turns 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 )
endfunction


local 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
qwertyui
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
combatken
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
The_AwaKening
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)
You need to change Picked unit belongs to an enemy to Matching unit belongs to an enemy.
01-19-2006, 06:42 AM#5
combatken
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
qwertyui
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:
Collapse 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
combatken
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
The_AwaKening
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
Vexorian
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
Mystic Prophet
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 :)