Shadowburn effect help plz.

Level 3
Joined
Dec 28, 2007
Messages
46
I am trying to make a spell similar to shadowburn talent from WoW. Except not with shadow, with ice (thats the easy part).

the spell des. is:

Untitled-1-2.png


The spell I want to make will do lets say, 150 damage and put a buff on that says they are "chilled to the core" or w/e. Basically just saying they are under the effect of the spell. Then if they die with the buff on them, instead of making a soul shard or w/e like the WoW spell, the caster will get a buff that "empowers" him or something.

The problem I am having is I have no way that works of checking whether the unit has the buff on them when they die. When the unit is dead the buff is removed. :( Can anyone help me find a way to check this?
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
I finaly found a nice MUI solution for this with just a addition of 1 line of code (using a local of course...).

Im really proud of myself since im a really idiot concerning JASS (and maybe other things :p) so you can all screw yourselves and think whatever you want... quietly :p

The basic triggers go like this
  • Untitled Trigger 001
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
    • Actions
      • Unit - Set the custom value of (Target unit of ability being cast) to 1
      • Wait 5.00 seconds
      • Unit - Set the custom value of (Target unit of ability being cast) to 0
  • Untitled Trigger 002
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Custom value of (Triggering unit)) Equal to 1
    • Actions
      • Unit - Create 5 Footman for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees

As you can see, the problem is the "wait 5 seconds".
If another unit casts your spell beetwin those 5 seconds, the first unit's custom value won't change back to 0.

So, I simply changed the trigger to custom script and now it looks like this
Code:
function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
    call SetUnitUserData( GetSpellTargetUnit(), 1 )
    call TriggerSleepAction( 5.00 )
    call SetUnitUserData( GetSpellTargetUnit(), 0 )
endfunction

//===========================================================================
function InitTrig_Untitled_Trigger_001 takes nothing returns nothing
    set gg_trg_Untitled_Trigger_001 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Untitled_Trigger_001, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddAction( gg_trg_Untitled_Trigger_001, function Trig_Untitled_Trigger_001_Actions )
endfunction


If you would really look at what it does you'll pretty much already undertsand what to do, but anyway, here is the solution using a local

Code:
function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
    [COLOR="Red"]local unit u = GetSpellTargetUnit()[/COLOR]
    call SetUnitUserData( [COLOR="red"]u[/COLOR], 1 )
    call TriggerSleepAction( 5.00 )
    call SetUnitUserData( [COLOR="red"]u[/COLOR], 0 )
endfunction

//===========================================================================
function InitTrig_Untitled_Trigger_001 takes nothing returns nothing
    set gg_trg_Untitled_Trigger_001 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Untitled_Trigger_001, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddAction( gg_trg_Untitled_Trigger_001, function Trig_Untitled_Trigger_001_Actions )
endfunction


The red letters are the changes.

I guess this will easly solve all this kind of spells for GUI users easly (since I saw about 5 of them this week) :D
 
Level 3
Joined
Dec 28, 2007
Messages
46
w00t! You are learning JASS? thats awesome dude. Lemme try it out and see what I can get. I was gonna do this spell in JASS anyways but I always try to figure out any possible ways to do it GUI first, then knowing how it works in GUI i write out my JASS script with improvements.

Just to try to think some more, is there any other way to store the boolean/switch of whether to apply the effect? The only reason I ask, is in case something else was to be using the custom value field on that unit. I have no such coincidence, but it would be nice to make this COMPLETELY MUI.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
I didn't know you are using JASS so I made it as much GUI as it can be.
This is the best solution (using custom values) known in GUI.
Besides, I suck at JASS :p

Learning... not really, but seeing that im anyway starting to learn Java from a book, I do pretty much wanna start learning JASS since it seems not too hard and I think it will help me a lot in Java (it makes me understand all the structure of functions and stuff like that).

Anyway about the question, I guess you could use a local boolean ?

Code:
function Trig_Untitled_Trigger_001_Copy_Actions takes nothing returns nothing
    local boolean b = true
    call TriggerSleepAction( 5.00 )
    set boolean = false
endfunction

//===========================================================================
function InitTrig_Untitled_Trigger_001_Copy takes nothing returns nothing
    set gg_trg_Untitled_Trigger_001_Copy = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Untitled_Trigger_001_Copy, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddAction( gg_trg_Untitled_Trigger_001_Copy, function Trig_Untitled_Trigger_001_Copy_Actions )
endfunction


[Edit] Hmmm, for some reason this seems like illegal actions to me. Im not sure why, I just don't think this is good lol.

[Edit2] Probably wouldn't be able to use the local boolean in the other trigger ?
 
Level 3
Joined
Dec 28, 2007
Messages
46
yea if you use a local boolean to do it it wont transfer to the other trigger nor even to other functions within the same trigger....

I think i have an idea though. Could you use the custom value as a set of flags? This way you can use the custom value for more than one trigger.

a 1 in a flag is false and a 2 is true (since if its zero there wont be a digit there at all in some cases). e.g. 011111 would just be 11111.

e.g. the custom value is a 6 digit number. 111111. the first (leftmost) digit is one flag, say for our ability. the 2nd another, and so on and so forth.

In order to set the flag for our ability all we would have to do is add 100000 and we have 211111. This has our one flag set and the others not. to remove the flag just subtract 100000 and you have 111111 again.

To test the flag im guessing you could use I2S() function to make into a string and then test the first digit with a substring function....

Im gonna try this when I have time. Would be revolutionary if it worked. :thumbs_up:
 
Level 3
Joined
Dec 28, 2007
Messages
46
Well, I worked on this for a while. And bingo. It completely works. Well the check at least. Maybe you can help me with another problem.... :(

Here is the working flag system:

The part that sets the flag when a spell is cast:
JASS:
function Trig_CS_Set_Flag_Conditions takes nothing returns boolean    
    return ( GetSpellAbilityId() == 'A00B' ) //Put whatever spell here in place of "A000"...
endfunction

function CS_Init_Flags takes unit which_unit returns nothing
    local unit CS_Spell_Target = which_unit
    local integer CS_Flags = GetUnitUserData(CS_Spell_Target)
    if ( CS_Flags <= 111111 ) then
        call SetUnitUserData(CS_Spell_Target, 111111)  
    endif
    set CS_Spell_Target = null
endfunction

function CS_Clear_Flag takes unit which_unit returns nothing
    local unit CS_Spell_Target = which_unit
    local integer CS_Temp_Value = GetUnitUserData(CS_Spell_Target)
    call SetUnitUserData(CS_Spell_Target, (CS_Temp_Value-100000))
    set CS_Spell_Target = null
endfunction    

function Trig_CS_Set_Flag_Actions takes nothing returns nothing
    local unit CS_Spell_Target = GetSpellTargetUnit()
    local integer CS_Temp_Value
    
    call CS_Init_Flags(CS_Spell_Target)
    set CS_Temp_Value = GetUnitUserData(CS_Spell_Target)
    call SetUnitUserData(CS_Spell_Target, (CS_Temp_Value + 100000))
    
    //Make sure to set the TriggerSleepAction() duration to the spell-to-be-cast's
    //buff duration.
    call TriggerSleepAction(5)
    
    call CS_Clear_Flag(CS_Spell_Target)
    set CS_Spell_Target = null      
endfunction

//===========================================================================//
function InitTrig_CS_Set_Flag takes nothing returns nothing
    local integer CS_Event_Player_Index    
    set gg_trg_CS_Set_Flag = CreateTrigger()    
    set CS_Event_Player_Index = 0
    
    loop
        exitwhen  (CS_Event_Player_Index == 16)
        call TriggerRegisterPlayerUnitEvent( gg_trg_CS_Set_Flag, Player(CS_Event_Player_Index), EVENT_PLAYER_UNIT_SPELL_CAST, null)
        set CS_Event_Player_Index = ( CS_Event_Player_Index + 1 )
    endloop    
    
    call TriggerAddCondition(gg_trg_CS_Set_Flag, Condition(function Trig_CS_Set_Flag_Conditions))
    call TriggerAddAction(gg_trg_CS_Set_Flag, function Trig_CS_Set_Flag_Actions)
endfunction


And the part that checks whether a flag is set:
JASS:
function Trig_CS_Test_Flag_Conditions takes nothing returns boolean    
    local unit CS_Check_Unit = GetDyingUnit()
    local string CS_Custom_Str = I2S(GetUnitUserData(CS_Check_Unit))
    local string CS_Flag_Subs = SubString(CS_Custom_Str, 0, 0)
    local string CS_Flag = I2S(2)
    set CS_Check_Unit = null    
    return (CS_Flag_Subs == CS_Flag) 
endfunction
   

function Trig_CS_Test_Flag_Actions takes nothing returns nothing
    //Put any actions to perform if flags match in this section.    
endfunction

//===========================================================================//
function InitTrig_CS_Test_Flag takes nothing returns nothing
    local integer CS_Event_Player_Index    
    set gg_trg_CS_Test_Flag = CreateTrigger()    
    set CS_Event_Player_Index = 0
    
    loop
        exitwhen  (CS_Event_Player_Index == 16)
        call TriggerRegisterPlayerUnitEvent( gg_trg_CS_Test_Flag, Player(CS_Event_Player_Index), EVENT_PLAYER_UNIT_DEATH, null)
        set CS_Event_Player_Index = ( CS_Event_Player_Index + 1 )
    endloop    
    
    call TriggerAddCondition(gg_trg_CS_Test_Flag, Condition(function Trig_CS_Test_Flag_Conditions))
    call TriggerAddAction(gg_trg_CS_Test_Flag, function Trig_CS_Test_Flag_Actions)
endfunction

The only problem is, I dont have a way of putting a buff onto the original caster from within the action section of the Flag-Check trigger. Any help in finding out how to do this would be greatly appreciated.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
[Edit] Hmmm, for some reason this seems like illegal actions to me. Im not sure why, I just don't think this is good lol.

[Edit2] Probably wouldn't be able to use the local boolean in the other trigger ?

The problem with your "script" is that you
set boolean = false
You must use the identifier of the boolean instead of the word "boolean"... Like
set b = false
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
True, but it won't work anyway because its a local.

Alpha, what do you mean a buff on the caster ? just use your ability to give him a buff.

Uh, just as a side question, is l2S = L2S or I2S ?

[Edit] oh ok I got it, "Integer to String" and "String to Integer" ^^
 
Level 3
Joined
Dec 28, 2007
Messages
46
Well my original spell was to check if the unit died from the spell and if it did, the caster would become empowered.

I have no way of knowing who the original caster of the spell is from within the Flag-Check Trigger.

normallly i would make a dummy unit for the owning player of the caster and then make it cast a attack speed buff on the casting unit.....ARGGGG i have no way of knowing from the second trigger who the casting unit OR the owning player is.....
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
If I understand correctly, this spell is some sort of shadow strike without the DoT, that gives you some sort of shard when the unit dies within 5 seconds?

I must be missing something... because what else is there to be done than this:

The actions taken when shadowburn is cast
JASS:
function ShadowBurnActions takes nothing returns nothing
    local unit target = GetSpellTargetUnit()
    local integer i = 0
    loop
        exitwhen i > 24
        if ((GetUnitAbilityLevel(target, 'B002') == 0) and (GetUnitState(target, UNIT_STATE_LIFE) <= 0)) then
            // Create a shard.
            set i = 25
        else
            call TriggerSleepAction(0.2)
            set i = i + 1
        endif
    endloop
    set target = null
endfunction
This checks, every 0,2 seconds for 5 seconds long if the unit still has the buff. If it no longer has the buff;
either the shadowburn was dispelled OR the unit is dead.
if it no longer has the buff, it checks if the unit is still alive. If this is false, you create a shard and instantly exit the loop. Else, you just wait for another 0,2 seconds before checking again..
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
I see...

1) What's the problem exactly?
2) It's better to use something like this:
Flag # 1 = 1
Flag # 2 = 2
Flag # 3 = 4
Flag # 4 = 8
If your unit has flags 2 and 4 checked, the user data would be 10 (flag 2 + flag 4). If your unit has all flags checked, it'd be 15. This way you can add many more flags to a unit - in case you need it.

Why this works? It works because that's how binary numbers work. In binary,
0 = 000
1 = 001
2 = 010
3 = 011 (which would be 1 + 2, thus flag 1 and 2 checked)
4 = 100
Thus you could simply take a look at a certain digit in the binary number, and if it's 1 the flag is checked, if it's 0 it's unchecked.
 
Top