• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Always see selection circle

Status
Not open for further replies.
Level 9
Joined
Jun 22, 2012
Messages
472
Hey there!

I can't use team color on models in my project and I'm looking for another way to display units owning. I was thinking selection circles with their green/yellow/red system could do the trick. Or simply team-colored circles.

I would like to know if it is possible to always display selection circles even when a unit is not selected/being selected? Assuming that selected units could have a bigger selection circle to be able to differentiate them from the other units.

+rep for helpers!
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
You could use an ability to attach a model to the unit. Similar to adding hero glow to units. You just need a model that looks like a selection circle and is teamcolored.
 
Level 9
Joined
Jun 22, 2012
Messages
472
The problem is that I already use team color to give realism to textures (for example, pink will never be used, contrary to black or brown), and as far as I know the team-color of the attached model is the same than the unit.
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Then you would have to create different models and different abilities to attach them to the units. One model+abilitiy per color.
An alternative would be to use a dummy unit that follows the unit, but that's not a good solution.
 
Level 9
Joined
Jun 22, 2012
Messages
472
Other colors would be ugly in my opinion. My suggestion is to only use green colored circles and only show them locally using GetLocalPlayer(). You can control who can only see "Special Effects". Example, you can make a certain green circle on a certain unit only visible to Player1.

Yeah I agree, green and red circles would perfectely do the job. I looked at the options when creating a SFX in GUI, nothing about local player. Does using "GetLocalPlayer()" require Jass? Or is it possible to use it with a custom script?


Then you would have to create different models and different abilities to attach them to the units. One model+abilitiy per color.

Tell me if I'm wrong, but with this method every player will see the same thing right?
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Yeah, I thought you wanted different colors for different palyers.
Should be doable with custom script. This is how you would use the JASS-if with custom script:
  • LocalPlayer
    • Events
    • Conditions
    • Actions
      • Custom script: if(udg_Player == GetLocalPlayer()) then
      • -------- actions --------
      • Custom script: endif
 
Level 9
Joined
Jun 22, 2012
Messages
472
Using dummy units seem not foreseeable because this would increase a lot the number of units on the map (one circle per unit and per player...). So I decided to give it a try using three passive abilities based on 'Sphere' that attach a green/yellow/red circle.

Is there a way to change the size of a model attached with such an ability through triggers? I would like that attached circles fit the selection circles radius.

I've tryed to create a 'Stand medium' animation for the circle, with a different radius, while using "required animation names - attachments" set to "medium" on the unit. But it doesn't seem to change the size of the circle displayed.
 
Level 22
Joined
Feb 6, 2014
Messages
2,466
Then you would have to create different models and different abilities to attach them to the units. One model+abilitiy per color.
Not true, you just have to set the string parameter of AddSpecialEffect different for each player using GetLocalPlayer().

Does using "GetLocalPlayer()" require Jass?
Yes, JASS or GUI Custom script will do the job.
 
Level 9
Joined
Jun 22, 2012
Messages
472
Mission accomplished! Using GetLocalPlayer(), I give the wanted circle to the wanted units thanks to a passive ability based on 'Sphere' (three in fact, one for each color). And I've found a way to set the radius of the circle, by changing the scaling of origin attachments of models (that's a bit annoying to do, but it works well). The circle system is activable/desactivable with a command in chat.

Here is a preview of the result :
WC3_Scrn_Shot_021617_164219_01.jpg


If anyone is interested in this system, just let me know :)! +rep for everybody

4th point in this
GetLocalPlayer() faq
i've never tried but maker of FAQ says he has and it appears sound.

I don't see anything about giving locally an ability to a unit, do you think it can cause desync?
 
Level 9
Joined
Jun 22, 2012
Messages
472
im 99% sure it is going to even if it's a visual only ability. do it by attaching the special effect.

Aaaarg... If I remember well, special effects are leaking, so it is necessary to remove them when the unit dies. That means I need to have access to all created SFX for when the units will die or when I want to simply remove the circles. And I don't know how to do this...
 
Level 23
Joined
Oct 18, 2008
Messages
937
-> hashtable - save effect handle

middle left part - choose "Get string ID" and write whatever you wanna call the value
middle right part - choose "Get Handle ID" and find the thing that refers to your unit. you can also make a handle type variable if you need to set it in some more complicated way.

  • Hashtable - Save Handle Of(Last created special effect) as (Key thisisastring) of (Key (Picked unit)) in thisisahashtable
in your other trigger reference to it looks like this

  • Special Effect - Destroy (Load (Key thisisastring) of (Key (Dying unit)) in thisisahashtable)
you need to create as hashtable before you can store any values in it. it is done like this:

  • Hashtable - Create a hashtable
  • Set thisisahashtable = (Last created hashtable)
and so on the rightmost part you select the hashtable variable you had set in this one.
 
Level 9
Joined
Jun 22, 2012
Messages
472
Do I need to create a hashtable for each player or can I handle all the players with one hashtable? Because a unit will potentially have one circle per player.

middle left part - choose "Get string ID" and write whatever you wanna call the value
middle right part - choose "Get Handle ID" and find the thing that refers to your unit. you can also make a handle type variable if you need to set it in some more complicated way.

If we see the hashtable as an array (I've never used hashtables myself, so I try to uderstand how it works), the first parameter will be the name of the row that contains all attached SFX? For now, I just wrote "Key SFX".

And the second parameter the corresponding unit? I have troubles with this part, I can't put (picked unit). Nor (dying unit) when removing the SFX.
 
Last edited:

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Both values are integers. The first value is usually used as an index for different data to store. For example on 0 you store the Special Effect and 1 you store something else. The second value is used to store the key of the unit you want to attach the data to.
  • Special Effect - Destroy (Load 0 of (Key (Dying unit)) in (Last created hashtable))
This order is used because clear child hashtable will clear all data attached to the unit.
  • Hashtable - Clear all child hashtables of child (Key (Dying unit)) in (Last created hashtable)
Combining these two actions special effect and hashtable data will be removed for this unit.

Replace Last created hashtable with your hashtable variable.
 
Level 9
Joined
Jun 22, 2012
Messages
472
The first value is usually used as an index for different data to store. For example on 0 you store the Special Effect and 1 you store something else.

This means that if a go to up to 11 I can store all circles for all players of a given unit?

The second value is used to store the key of the unit you want to attach the data to.

This means I have to choose an integer for each unit that I want the SFX being stored?
And is it possible to have access to this integer just with the dying/picked unit?
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
First value:

I do not have much experience with GetLocalPlayer so I do not know this would be done the best way. But in general if you go up to 11 you can store 12 variables for a unit.

Second value:

This means I have to choose an integer for each unit that I want the SFX being stored?
And is it possible to have access to this integer just with the dying/picked unit?

Sorry if I wasn't clear enough. For the second value you use the function Hashtable - Get Handle Id.
You should see Key Handle. For the Handle you select dying unit.

This function automatically gives each "handle" a unique ID allowing you to save/data to this handle.
A unit is an example for a handle.

However I would recommend instead of using key(dying unit) to use a custom script:
set udg_INTEGER= GetHandleId(udg_UNIT)
Then you use 0 of INTEGER in the Hashtable action.

The Hashtable - Get Handle Id function in GUI is the same as GetHandleId, but it cannot get the key from a unit variable. You can replace udg_UNIT by whatever you want
( GetTriggerUnit(), GetDyingUnit(), GetEnumUnit(),... )

  • Example
    • Events
    • Conditions
    • Actions
      • Custom script: set udg_INTEGER = GetHandleId(udg_UNIT)
      • Special Effect - Destroy (Load 0 of INTEGER in (Last created hashtable))
      • Hashtable - Clear all child hashtables of child INTEGER in (Last created hashtable)
 
Level 22
Joined
Feb 6, 2014
Messages
2,466
Think of it this way, hashtables are like 2D arrays that can use an index as high as (2^31 -1). The
  • Key(Dying Unit)
is the GUI equivalent of GetHandleId which gives you a unique integer based on the input handle (unit, destructable, etc).
(But unlike arrays, they need to be cleaned or "nulled" when you no longer need the value)

That means if you're creating a new hashtable just for this system, you can use the same value for the parent key of the hashtable like in the example above, he used 0.

Here's a couple of guides about hashtable
Hashtables and MUI
A Complete Beginners Guide to Hashtables

I really recommend you learn hashtable. It is a crucial skill in WC3 Map making.
 
Level 9
Joined
Jun 22, 2012
Messages
472
Alriiiiiiiight! Now that's clear to me, thanks ^^! I'm now able to remove the SFX thanks to the hashtable, but the circles take around 3 or 4 sec to remove when I enter the command (without lag). Is that normal? Maybe is it because of GetLocalPlayer()?

Here are the parts of the triggers that use the hashtable :




  • Hashtable - Create a hashtable
  • Set Circle_hashtable = (Last created hashtable)



  • [...]
  • Set Circle_unit = (Picked unit)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Owner of Circle_unit) Equal to Circle_player
    • Then - Actions
      • Custom script: set udg_Circle_handle = GetHandleId(udg_Circle_unit)
      • Custom script: if (GetLocalPlayer() == udg_Circle_player) then
      • Special effect - Create a special effect attached to the origin of (Picked unit) using CircleGreen.mdx
      • Custom script: endif
      • Table de hachage - Save Handle Of(Last created special effect) as ((Player number of Circle_player) - 1) of Circle_handle in Circle_hashtable
    • Else - Actions
      • [...]



  • [...]
  • Set Circle_unit = (Picked unit)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Owner of Circle_unit) Equal to Circle_player
    • Then - Actions
      • Custom script: set udg_Circle_handle = GetHandleId(udg_Circle_unit)
      • Special effect - Destroy (Load ((Player number of Circle_player) - 1) of Circle_handle in Circle_hashtable)
    • Else - Actions
  • [...]



  • Custom script: set udg_Circle_handle = GetHandleId(GetDyingUnit())
  • Special effect - Destroy (Load 0 of Circle_handle in Circle_hashtable)
  • Hashtable - Clear all child hashtables of child Circle_handle in Circle_hashtable


 
Level 10
Joined
Sep 16, 2016
Messages
269
This
  • if.gif
    [...]
  • set.gif
    Set Circle_unit = (Picked unit)
  • if.gif
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • joinminus.gif
      cond.gif
      If - Conditions
      • line.gif
        joinbottom.gif
        if.gif
        (Owner of Circle_unit) Equal to Circle_player
    • joinminus.gif
      actions.gif
      Then - Actions
      • line.gif
        join.gif
        page.gif
        Custom script: set udg_Circle_handle = GetHandleId(udg_Circle_unit)
      • line.gif
        join.gif
        page.gif
        Custom script: if (GetLocalPlayer() == udg_Circle_player) then
      • line.gif
        join.gif
        if.gif
        Special effect - Create a special effect attached to the origin of (Picked unit) using CircleGreen.mdx
      • line.gif
        join.gif
        page.gif
        Custom script: endif
      • line.gif
        joinbottom.gif
        if.gif
        Table de hachage - Save Handle Of(Last created special effect) as ((Player number of Circle_player) - 1) of Circle_handle in Circle_hashtable
    • joinbottomminus.gif
      actions.gif
      Else - Actions
      • empty.gif
        joinbottom.gif
        if.gif
        [...]

will definitely cause desync


  • Customscript: set udg_Circle_handle = GetHandleId( udg_Circle_unit )
  • Set TempString = <Empty String>
  • Customscript: if GetLocalPlayer() == udg_Circle_player then
  • Set TempString = CircleGreen.mdx
  • Customscript: endif
  • Special effect - Create a special effect attached to the origin of (Picked unit) using TempString
 
Status
Not open for further replies.
Top