• 🏆 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!

[Snippet] LocalHelper

Level 17
Joined
Apr 27, 2008
Messages
2,455
Honestly, i'm not sure it's worth a submission, comparing to just use a force and the associated natives function.
It could also simply be inlined.
But i've realized that most of people are not aware that we can use a simple global boolean variable for local stuff.

JASS:
library LocalHelper
//http://www.hiveworkshop.com/forums/submissions-414/snippet-localhelper-215108/#post2152752

    globals
        private boolean array Is_for_player
    endglobals
    
    function IsForPlayer takes player which_player returns boolean
        return Is_for_player[GetPlayerId(which_player)]
    endfunction
    
    function IsForPlayerId takes integer which_player_id returns boolean
        return Is_for_player[which_player_id]
    endfunction
    
    struct Local
    
        readonly static player p // = GetLocalPlayer()
        readonly static integer id // = GetPlayerId(thistype.p)
        readonly static string s // = I2S(thistype.id)
        boolean bool // no need to set it to false, since it's an array in the background (vjass -> jass)

        static method create takes nothing returns thistype
            return thistype.allocate()
        endmethod

        method destroy takes nothing returns nothing
            set this.bool = false
            call this.deallocate()
        endmethod
        
        method addPlayer takes player which_player returns nothing
            if which_player == thistype.p then
                set this.bool = true
            endif
        endmethod
        
        method addPlayerId takes integer which_player_id returns nothing
            if which_player_id == thistype.id then
                set this.bool = true
            endif
        endmethod
        
        method removePlayer takes player which_player returns nothing
            if which_player == thistype.p then
                set this.bool = false
            endif
        endmethod
        
        method removePlayerId takes integer which_player_id returns nothing
            if which_player_id == thistype.id then
                set this.bool = false
            endif
        endmethod
        
        method addAllPlayers takes nothing returns nothing
            set this.bool = true
        endmethod
        
        method removeAllPlayers takes nothing returns nothing
            set this.bool = false
        endmethod
        
        static method onInit takes nothing returns nothing
            // you can't use GetLocalPlayer() in a global variable initial value, or wc3 will crash
            set thistype.p = GetLocalPlayer()
            set thistype.id = GetPlayerId(thistype.p)
            set thistype.s = I2S(thistype.id)
            set Is_for_player[thistype.id] = true
        endmethod
        
    endstruct
    
endlibrary

JASS:
scope Sample initializer init // use LocalHelper

    globals
        Local My_force
    endglobals

    private function init takes nothing returns nothing
        set My_force = Local.create()
        call My_force.addPlayer(Player(0))
        call My_force.addPlayer(Player(1))
        // or just : set My_force.bool = (Local.id < 2) , but be aware that it will work only for "static initial add", if you want add/remove players later, use the methods instead
        if My_force.bool then
            // local block only for the red and blue player
            call DisplayTextToPlayer(Local.p,0,0,"hello red and blue")
        endif
        if IsForPlayer(Player(0)) then
            // local block only for Player(0)
            call DisplayTimedTextFromPlayer(Local.p,0,0,42,"this is only for you %s")
        endif
    endfunction
    
endscope
 
Last edited by a moderator:
JASS:
        method addPlayer takes player which_player returns nothing
            set this.bool = (which_player == thistype.p)
        endmethod
        
        method addPlayerId takes integer which_player_id returns nothing
            set this.bool = (which_player_id == thistype.id)
        endmethod
        
        method removePlayer takes player which_player returns nothing
            set this.bool = (which_player != thistype.p)
        endmethod
        
        method removePlayerId takes integer which_player_id returns nothing
            set this.bool = (which_player_id != thistype.id)
        endmethod

edit
Oh, nevermind.
I realized that this wouldn't have the correct behavior :l
I guess it should stay as is.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
No, think more about it.

Let's take my example: i've already the player(0) alone in this custom "force", and then i want to add the player(1).

If you do that the custom "force" will have only one player, the last one added.
"Same" for remove.

EDIT : 2 functions added, and updated the sample as well.
 
Last edited:
Level 17
Joined
Apr 27, 2008
Messages
2,455
No comment, while it's clearly the resource of the year ?!

I would expected at least some comments about my ugly (or not) choice of api names.
I know that wc3 is dying, but maybe it's just because it's me (i'm not crying, just trying to give a little attention to this).
 
Warcraft III isn't dying :p
People only think it's dying because it's a 10-year old game ^.^

On the contrary, there are over 70000000 people registered to Garena O_O
That equates to about a few million or so players :O (Active Players are always much less than the registered users)
And last week, I saw 650000 people online :D

Warcraft III Modding is only dying because we're killing it. We think it's dying, but it's really not, so we leave it assuming it's dying, then it actually /does/ start dying.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
%s is the only string i know, afaik it only works with DisplayTimedTextFromPlayer.
Btw this function display the text for all players, the player argument only needs to be a valid one, if you don't use this (or maybe these) special string(s) you can use any player you want.

Maybe there are some other strings, but i've never experienced it, you can try with %a to %Z
 
Level 16
Joined
Aug 7, 2009
Messages
1,403
But I'm not sure why they would need a double to store the level.
Pfff, typical Blizzard.

Because if it was stored in an int variable as, let's say, "2", all the spels would be dealing 999999 chaos damage, rather than.

Seriously; it's Blizzard, it wouldn't be a Blizzard game if something about it made some sense.

on-topic:
It is actually a quite cool snippet IMO, but is it worth changing my few codes that use forces to this? I mean I'd like to know what's the speed difference between them - until it's not proven that the difference ain't neglible I will consider it neglible.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
That would be unoticeable, just like many speedfreak resources here, but this is not one (you can inline it and use a not array boolean for moar speedfreak power).
The main point is that cut of the verbosity comparing to the usual alternative.
On a bonus side it also doesn't use handles, again still negligible.

I like it but you don't have to use it, as said in the first post, maybe the requirement by itself is annoying, while you can just go for the force alternative.
I've written it in the first place because i've realized that many people are not aware about this, they only think about force and the associated native functions.

So yeah maybe this snippet is cool but not useful.
I just wanted some opinions about it.
 
Last edited:
Level 17
Joined
Apr 27, 2008
Messages
2,455
Forgot to set the boolean to false when you destroy a Local struct instance, fixed. (only does matter if you used Local struct instances dynamically : create/destroy/create...)
Added the method create, just for completness reason, but because it's not a struct extends array, the resulted jass code is still the same with or without this implicit create method.

Note that i could add a boolean argument for the method create, but i'm not sure it's worth it, i think it would just make the code weirder.

I still don't care that much if it's graveyarded for an eventual lack of usefulness, but meh i had to fix it anyway.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
You know what, i think it's worth a bump, just because even if you could inline it, it could be error prone, like when i forgot to flush the boolean on destroy.
Instead of reinventing the wheel you could as well just use it.

Now ideally that shouldn't be a requirement in a public resource, only optional.
But well, even if it's not optional that's not that bad either.

EDIT : Combo triple post.
 
Top