• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!
  • ✅ The POLL for Hive's Texturing Contest #34 is OPEN! Vote for the TOP 3 SKINS! 🔗Click here to cast your vote!
  • ✅ The POLL for Hive's Techtree Contest #20 is OPEN! Vote for the TOP 3 FACTIONS! 🔗Click here to cast your vote!

[JASS] Creating special effect for player

Status
Not open for further replies.
Level 6
Joined
Mar 26, 2008
Messages
239
Explanation: I wanted to create special effect for player (the effect will ve visible only for 1 or group of players), but I didn't know how. Then I read this tutor:
https://www.hiveworkshop.com/forums/jass-ai-scripts-tutorials-280/using-getlocalplayer-59368/
Here is the method I used(For those who don't want to look for it in the tutor:thumbs_up:):
JASS:
function AddSpecialEffectForPlayer takes location where, string modelpath, player whichplayer returns nothing
    local string s = ""
    if GetLocalPlayer() == whichplayer then
       set s = modelpath
endif
       call AddSpecialEffectLoc(modelpath,where)
endfunction
But this method caused desync.
Question:
1)Can it be fixed? And if not then:
2)How can I do that? (I mean any other method)
 
The desync can't be fixed in this case, its inevitable, but you might be able to change it by changing the model of a dummy unit to an SFX then giving it invisibility limited to only the player(s) that you don't want able to see it.
 
You're using the wrong variable in your AddSpecialEffectLoc call. It should be:

JASS:
function AddSpecialEffectLocForPlayer takes player forPlayer, string modelPath, location loc returns effect
    if GetLocalPlayer() != forPlayer then
        set modelPath = ""
    endif
    call AddSpecialEffectLoc( modelPath, loc )
endfunction

I changed it up a little bit but the problem was you using modelpath instead of s. I don't know why this would be causing a desync in any situation though.
 
When you use the code I have posted, does it desync? It shouldn't.

LexX said:
What worng variable?

You use modelpath (as I said above) to create the special effect, so setting s in a local-player if-statement won't change anything. What you were doing is creating a special effect that used the same model-path for every player (not localizing it). This also means that the fact that your map is having desync problems has nothing to do with this code because you weren't even doing anything local before but you still reported a desync.

hvo-busterkomo said:
JASS:
function AddSpecialEffectForPlayer takes location where, string modelpath, player whichplayer returns nothing
    local string s = ""
    if GetLocalPlayer() == whichplayer then
       set s = modelpath
endif
       call AddSpecialEffectLoc(modelpath,where)
endfunction
So as you can see, the model path is only correct for one player, for all other players the effect would be blank, thus creating the special effect for only 1 player.

Yea this is wrong. He's setting s = modelpath for the local player but then he is just using modelpath to create the special effect, making the if-statement useless. What a great tutorial.
 
When you use the code I have posted, does it desync? It shouldn't.

You use modelpath (as I said above) to create the special effect, so setting s in a local-player if-statement won't change anything. What you were doing is creating a special effect that used the same model-path for every player (not localizing it). This also means that the fact that your map is having desync problems has nothing to do with this code because you weren't even doing anything local before but you still reported a desync.

Yea this is wrong. He's setting s = modelpath for the local player but then he is just using modelpath to create the special effect, making the if-statement useless. What a great tutorial.
Well it DOES desync, I used some other things with locals before(like ping minimap, create floating text and some others). Then I made a spell with effects which only owner of caster should see. But everytime I used the spell my friends, with whom I was testing the map, were disconnected.
So...I asked to write the right way to make effect visible for player, and not explain why method in tutor is wrong or not, so PLEASE write it:wink:I need it=)
 
So...I asked to write the right way to make effect visible for player, and not explain why method in tutor is wrong or not, so PLEASE write it:wink:I need it=)

The desync can't be fixed in this case, its inevitable, but you might be able to change it by changing the model of a dummy unit to an SFX then giving it invisibility limited to only the player(s) that you don't want able to see it.

  • SFX for player
    • Events
      • Player - Player 1 (Red) types a chat message containing <Empty String> as A substring
    • Conditions
    • Actions
      • Set p = (Player((Integer((Entered chat string)))))
      • Set loc = (Point(0.00, 0.00))
      • Unit - Create 1 Footman for p at loc facing Default building facing degrees
      • Custom script: if GetLocalPlayer() != udg_p then
      • Unit - Hide (Last created unit)
      • Custom script: endif
      • Special Effect - Create a special effect attached to the overhead of (Last created unit) using Abilities\Spells\Other\TalkToMe\TalkToMe.mdl
      • Custom script: call RemoveLocation(udg_loc)
      • Game - Display to (All players) the text: (Name of p)
of cause you should use a dummy model with nothing but an attachment point
 

Attachments

  • SFX for player
    • Events
      • Player - Player 1 (Red) types a chat message containing <Empty String> as A substring
    • Conditions
    • Actions
      • Set p = (Player((Integer((Entered chat string)))))
      • Set loc = (Point(0.00, 0.00))
      • Unit - Create 1 Footman for p at loc facing Default building facing degrees
      • Custom script: if GetLocalPlayer() != udg_p then
      • Unit - Hide (Last created unit)
      • Custom script: endif
      • Special Effect - Create a special effect attached to the overhead of (Last created unit) using Abilities\Spells\Other\TalkToMe\TalkToMe.mdl
      • Custom script: call RemoveLocation(udg_loc)
      • Game - Display to (All players) the text: (Name of p)
of cause you should use a dummy model with nothing but an attachment point
No, this is not what I need, because what if I want to make an effect for player, attached to weapon (arms, legs, etc.) of any unit?
I need make the effect visible/unvisible without using dummy unit.
 
JASS:
globals
    private effect effectVar = null
endglobals

function addSpecialEffectForPlayer takes player p, real x, real y, string eff returns effect
    local string s = ""

    if GetLocalPlayer() == p then
        set s = eff
    endif

   set effectVar = AddSpecialEffect(s, x, y)
   set s = null
   return effectVar
endfunction
This too?
 
if it does not work you could do something like

if local player == playerWhichShallSeeTheEffect then
create special effect on a unit
else
create special effect on a unit which is not visible
endif

so you don't mess up the handle counter
I don't know what it is though
worth a try anyway
"create special effect on a unit which is not visible" means dumy unit which is hidden, and I said that I need to make effect invisible itself and not with help of dummies, because, for example, if I want to make effect attached to a hero (weapon, arms, etc.) it won't work at all.
 
JASS:
globals
    private effect effectVar = null
endglobals

function addSpecialEffectForPlayer takes player p, real x, real y, string eff returns effect
    local string s = ""

    if GetLocalPlayer() == p then
        set s = eff
    endif

   set effectVar = AddSpecialEffect(s, x, y)
   set s = null
   return effectVar
endfunction
This too?
It is the same like I did but much more complicated.
Here is the part of code in my spell:
JASS:
private function Effect takes nothing returns nothing
 local string s
    if ( GetUnitState(GetEnumUnit(), UNIT_STATE_LIFE) <= 0 ) then
      if (GetLocalPlayer() == GetOwningPlayer(GetTriggerUnit())) then
        set s = "Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl"
      endif
      call DestroyEffect( AddSpecialEffect( s , GetUnitX(GetEnumUnit()) , GetUnitY(GetEnumUnit()) ))
      call SetUnitState( GetTriggerUnit(), UNIT_STATE_MANA , GetUnitState(GetTriggerUnit() , UNIT_STATE_MANA) + 5.00 + 5.00 * I2R(GetUnitAbilityLevel(GetTriggerUnit() , 'A01R')) )
      call RemoveUnit( GetEnumUnit() )
      set I = I + 5 + 5 * GetUnitAbilityLevel(GetTriggerUnit() , 'A01R')
    endif
 set s = null
endfunction
 
Mine also cleans all leaks that were made by my function. Also please try to use my function.
Well, in my function there are no leaks, and result of both systems is the same, just your is more complicated, you set strings and effects about 2 times (first type string for function and then set s = eff, and set effectVar =... and then return effectVar) and I just set s and create effect. This is the only difference.
But still I'll try, but don't know when I'l be able to check if it works or not, so conversation continues=)

EDIT:
Hey, I forgot!
I told 2 times that:
1)I need system which could make effect visible to player or player group, and your system contains only player. OK, it's fixable, then:
2)I need system that could make ANY created effect visible only for player or player group, not only CreateSpecialEffect(...), for example AddSpecailEffectTarget(...). I don't want to make many systems for 1 purpose. So I need 1 system (well if not system then just way, like in my spell, the system is in the spell, not separate function) for all effects and player and player group.
 
1)I need system which could make effect visible to player or player group, and your system contains only player. OK, it's fixable, then:
Yeah, pretty easily to manipulate.

2)I need system that could make ANY created effect visible only for player or player group, not only CreateSpecialEffect(...), for example AddSpecailEffectTarget(...). I don't want to make many systems for 1 purpose. So I need 1 system (well if not system then just way, like in my spell, the system is in the spell, not separate function) for all effects and player and player group.
You need to rewrite every function on your own. Thats how wc3 works.

lol, what about initializing s = "" ? ^^
If it isn't set, its crashes wc3 for everyone else.
 
Like you see in my piece of spell, I didn't use other function to create effect and make it visible (like the one you wrote), I used it inside of spell, but this way to make it caused desync, so I asked if there is other way which I could use inside of spell too, but fully working.
 
Just use my function... It should work, I am 100% sure.
And initialize your damn string s variable ...
If I use your function, I'll have to write about 4 functions (player-point, player-unit, player group-point, player group-unit) if not more than 4. It's bad, u know))
And even if I do it, still your function works EXACTLY like piece of code in my spell, can you understand it or not??? They are the SAME, just mine is more simple.
But ANYWAY I'll try it just to calm you down:grin:
 
They are more general, and can be used in any situation. While your code only creates local effects in the spell, my can be used anywhere from any system. This makes mine far more useable as your.
Agree, but your function can only make player-point effect.
If you add player group, unit attachable effect and also timed effect (if I need it to have effect which disappears in some time) and if ALL THIS will be in 1 system and it will work then it'll be cool=)
 
JASS:
/*
    LocalEffects
    
    Small library by Anachron to create
    effects which are displayed locally
    for players and/or forces only.
*/
library LocalEffects

    globals
        private string  eff = null
        private force   for = null
    endglobals

    function addEffectToUnitForPlayer takes player p, unit u, string a, string e returns effect
        set eff = null
        
        if GetLocalPlayer() == p then
             set eff = e
        endif
        
        return AddSpecialEffectTarget(eff, u, a)    
    endfunction
    
    function addEffectOnPositionForPlayer takes player p, real x, real y, string e returns effect
        set eff = null
        
        if GetLocalPlayer() == p then
             set eff = e
        endif
        
        return AddSpecialEffect(eff, x, y)    
    endfunction
    
    function addEffectToUnitForForce takes force f, unit u, string a, string e returns nothing
        local integer i = 0
        
        loop
            exitwhen i >= 15
            
            if IsPlayerInForce(Player(i), f) then
                call addEffectToUnitForPlayer(Player(i), u, a, e)
            endif
            
            set i = i +1
        endloop 
    endfunction
    
    function addEffectOnPositionForForce takes force f, real x, real y, string e returns nothing
        local integer i = 0
        
        loop
            exitwhen i >= 15
            
            if IsPlayerInForce(Player(i), f) then
                call addEffectOnPositionForPlayer(Player(i), x, y, e)
            endif
            
            set i = i +1
        endloop 
    endfunction

endlibrary

Written out of the head, you have to fix the errors.

Example usage in your code:
JASS:
private function Effect takes nothing returns nothing
    if ( GetUnitState(GetEnumUnit(), UNIT_STATE_LIFE) <= 0 ) then
      call DestroyEffect( addEffectOnPositionForPlayer(GetOwningPlayer(GetEnumUnit()) , GetUnitX(GetEnumUnit()) , GetUnitY(GetEnumUnit()), "Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl"))
      call SetUnitState( GetTriggerUnit(), UNIT_STATE_MANA , GetUnitState(GetTriggerUnit() , UNIT_STATE_MANA) + 5.00 + 5.00 * I2R(GetUnitAbilityLevel(GetTriggerUnit() , 'A01R')) )
      call RemoveUnit( GetEnumUnit() )
      set I = I + 5 + 5 * GetUnitAbilityLevel(GetTriggerUnit() , 'A01R')
    endif
 set s = null
endfunction
 
JASS:
/*
    LocalEffects
    
    Small library by Anachron to create
    effects which are displayed locally
    for players and/or forces only.
*/
library LocalEffects

    globals
        private string  eff = null
        private force   for = null
    endglobals

    function addEffectToUnitForPlayer takes player p, unit u, string a, string e returns effect
        set eff = null
        
        if GetLocalPlayer() == p then
             set eff = e
        endif
        
        return AddSpecialEffectTarget(eff, u, a)    
    endfunction
    
    function addEffectOnPositionForPlayer takes player p, real x, real y, string e returns effect
        set eff = null
        
        if GetLocalPlayer() == p then
             set eff = e
        endif
        
        return AddSpecialEffect(eff, x, y)    
    endfunction
    
    function addEffectToUnitForForce takes force f, unit u, string a, string e returns nothing
        local integer i = 0
        
        loop
            exitwhen i >= 15
            
            if IsPlayerInForce(Player(i), f) then
                call addEffectToUnitForPlayer(Player(i), u, a, e)
            endif
            
            set i = i +1
        endloop 
    endfunction
    
    function addEffectOnPositionForForce takes force f, real x, real y, string e returns nothing
        local integer i = 0
        
        loop
            exitwhen i >= 15
            
            if IsPlayerInForce(Player(i), f) then
                call addEffectOnPositionForPlayer(Player(i), x, y, e)
            endif
            
            set i = i +1
        endloop 
    endfunction

endlibrary
Written out of the head, you have to fix the errors.
1.Well again you set effect = string o_O Almost whole system is wrong o_O
2.I don't understand why you use globals..
3.But I understood how can I make such system, but STILL it uses the SAME way as in tutor and that is why it WILL still cause desync.

EDIT:
Oh sorry about "1." I wrote, I read wrong=)But "2." and especially "3." stay
 
To prevent leaks.


Wehrm I never had a desync problem with that usage.
What leaks???
you could just make functions return nothing and instead of:
return AddSpecialEffectTarget(eff, u, a)
type:
call DestroyEffect (AddSpecialEffectTarget(eff, u, a))
and instead of global string use local and then set it = null, because if these effects are created veeeeery fast and by not 1 player, then it'll be better to make it with local.
"Wehrm I never had a desync problem with that usage." You just typed it and you say that you used it before? How?=)
And I already told that this way (the way in tutor = the way you wrote) caused desync, I tested it many times, so I cannot understand why you insist that this way works:eekani:
 
What leaks???
Atleast one handle if you want to return that effect.

and instead of global string use local and then set it = null, because if these effects are created veeeeery fast and by not 1 player, then it'll be better to make it with local.
Globals are faster then locals.

"Wehrm I never had a desync problem with that usage." You just typed it and you say that you used it before? How?=)
And I already told that this way (the way in tutor = the way you wrote) caused desync, I tested it many times, so I cannot understand why you insist that this way works
I rewrote, I lost all of my stuff when my HDD crashed.
 
I wanted to ask why you use:
JASS:
function addEffectToUnitForForce takes force f, unit u, string a, string e returns nothing
 local integer i = 0
    loop
    exitwhen i >= 15
      if IsPlayerInForce(Player(i), f) then
        call addEffectToUnitForPlayer(Player(i), u, a, e)
      endif
    set i = i +1
    endloop
endfunction
instead of:
JASS:
function addEffectToUnitForForce takes force f, unit u, string a, string e returns nothing
    if IsPlayerInForce(GetLocalPlayer(), f) then
      call addEffectToUnitForPlayer(GetLocalPlayer(), u, a, e)
    endif
endfunction
It is more simple, isn't it? (don't know if it's right or not so just asking)
And it is even more simple to write separate functions, because for example in addEffectToUnitForForce you use 2 functions when you can use 1.
 
It is more simple, isn't it? (don't know if it's right or not so just asking)
You don't understand. If you use GetLocalPlayer() in this case, the effect handle is only created for one player. Thus disconnecting everyone.

And it is even more simple to write separate functions, because for example in addEffectToUnitForForce you use 2 functions when you can use 1.
Its not possible to put these functions together with no split.
 
Because the second version would run the function localy.
JASS:
function addEffectToUnitForPlayer takes player p, unit u, string a, string e returns effect
        set eff = null

        if GetLocalPlayer() == p then
             set eff = e
        endif

        return AddSpecialEffectTarget(eff, u, a)
endfunction
Running this code localy is the same then just normaly
creating an effect localy and this desyncs.
The funtions all work, I used them often enough.

And in addition:
locals aren't more save then globals.
If no waits/timers are used,
it's impossible for globals to fail.

EDIT: hmrf :( :O
 
You don't understand. If you use GetLocalPlayer() in this case, the effect handle is only created for one player. Thus disconnecting everyone.
That's why I asked=)
And in addition:
locals aren't more save then globals.
If no waits/timers are used,
it's impossible for globals to fail.
I know, but if add to this system smth. like timed effect, then it'll better to use locals.
Ok, I'll check this system and see if it works.
 
I tried this
JASS:
function AddSpecialEffectForPlayer takes player p, real x, real y, string eff returns effect
    local string s = ""

    if GetLocalPlayer() == p then
        set s = eff
    endif

   set udg_effect = AddSpecialEffect(s, x, y)
   set s = null
   set eff = null
   set p = null
   return udg_effect
endfunction
  • Test
    • Events
      • Player - Player 1 (Red) types a chat message containing <Empty String> as A substring
    • Conditions
    • Actions
      • Set p = (Player((Integer((Entered chat string)))))
      • Set s = Abilities\Spells\Human\ThunderClap\ThunderClapCaster.mdl
      • Custom script: call DestroyEffect(AddSpecialEffectForPlayer(udg_p, 0, 0, udg_s))
and it instantly disconnects (online only though - did not test solo but with 2 players)

what's wrong?
 
You don't need to null parameter values.

good to know thanks :grin:
(why is it like that? is it the same with all other parameter variables like locations or only with these?)

Also the escape character sequence is invalid. It has to be \\ in vJass.

might be but it's not JASS it's GUI
it triggers as it is supposed to be (tested in the dummy example map uploaded before)

Just use my functions, what so bad about them?

it's yours except I tried to remove the non-existent leak and renamed the global variable
 
good to know thanks
(why is it like that? is it the same with all other parameter variables like locations or only with these?)
It doesn't leak for any variable. Its because blizzard stores the parameters (I think so) in another variables which will be cleaned after execution.

might be but it's not JASS it's GUI
it triggers as it is supposed to be (tested in the dummy example map uploaded before)
But you pass that value into vJass. Test it with \\ please.

it's yours except I tried to remove the non-existent leak and renamed the global variable
Non-existing leak? You added a global GUI variable, thats the same what I did with the global. Thats really awkward.
 
I think it causes desync because we set string of effect using GetLocalPlayer(), and the effect will not be blank for other players like it's said in tutor but it'll cause desync...It'll mean that this method is wrong at all, and there should be other way to make effect for player, not by setting string like that.
I didn't test the system now, but I still think it will cause desync=)
 
It doesn't leak for any variable. Its because blizzard stores the parameters (I think so) in another variables which will be cleaned after execution.

I just tried the same with locations and they leak (probably they won't leak with RemoveLocation and without set loc = null but I did not test it)

But you pass that value into vJass. Test it with \\ please.

things with \ are automatically converted to things with \\ as soon as you convert it to custom script


Non-existing leak? You added a global GUI variable, thats the same what I did with the global. Thats really awkward.

renaming globals is not awkward at all if you don't use JNGP and I was talking about
JASS:
set p = null
set eff = null
 
How about:

JASS:
function SetStringForPlayer takes string s, player p returns string
    if GetLocalPlayer() != p then
        set s = null
    endif
    return s
endfunction

function Something takes nothing returns nothing
    call AddSpecialEffect(SetStringForPlayer("Shiny.mdx", Player(0)), 0, 0)
endfunction

Doesn't seem like it would desync to me. Unless you started setting things globally.

Edit: Tested with a friend, no desyncs. I would recommend using this method.

Edit 2: Attached testmap. Also, dont save it. I forgot that not everyone has cJass. Just push test map or play with it in wc3.
 

Attachments

Last edited:
How about:

JASS:
function SetStringForPlayer takes string s, player p returns string
    if GetLocalPlayer() != p then
        set s = null
    endif
    return s
endfunction

function Something takes nothing returns nothing
    call AddSpecialEffect(SetStringForPlayer("Shiny.mdx", Player(0)), 0, 0)
endfunction
Doesn't seem like it would desync to me. Unless you started setting things globally.

Edit: Tested with a friend, no desyncs. I would recommend using this method.

Edit 2: Attached testmap. Also, dont save it. I forgot that not everyone has cJass. Just push test map or play with it in wc3.
I understood how you made this and will try it as soon as I can. If it really works for me then it's exactly what I need=)
 
o.O

Could you post the code?

Also:

JASS:
function SetStringForForce takes string s, force f returns string
    if IsPlayerInForce(GetLocalPlayer(), f) then
        set s = null
    endif
    return s
endfunction
 
Last edited:
Status
Not open for further replies.
Back
Top