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

[JASS] GetLocalPlayer() bug - Advance JASS problem!

Status
Not open for further replies.
Level 12
Joined
Aug 7, 2004
Messages
875
Hey guys.

I've been trying to make a Hero Pick system similar to that of DotA. Basically the Hero Pick system in dota works like this; when a player picks a hero, it removes all the heroes in all tavern for that specific player only. I've been wondering how to do this since there are no natives to do this specific function. So I created my own function using GetLocalPlayer()

JASS:
function RemoveUnitFromAllStockForPlayer takes integer unitId, player whichPlayer returns nothing
    if (GetLocalPlayer() == whichPlayer) then
        call RemoveUnitFromAllStock(unitId)
    endif
endfunction

function AddUnitToAllStockForPlayer takes integer unitId, player whichPlayer returns nothing
    if (GetLocalPlayer() == whichPlayer) then
        call AddUnitToAllStock(unitId,1,1)
    endif
endfunction

function AddUnitToStockForPlayer takes unit whichUnit, integer unitId, player whichPlayer returns nothing
    if (GetLocalPlayer() == whichPlayer) then
        call AddUnitToStock(whichUnit,unitId,1,1)
    endif
endfunction

It works neatly when I tested it singleplayer. However there is a problem I've discovered when I'm testing the map with my friend online. Basically when I pick a Hero everything is fine, but then when he picks a Hero he got disconnected. This keeps happening everytime, the same thing happens vise versa, which makes me come to a conclusion that the error happens on the second player that picks a hero.

I don't know whats wrong with this, but I'm pretty sure its using that GetLocalPlayer() - Can't imagine another way of achieving this.

However the same effect works fine on multiplayer on these functions

This is an effect that I've discovered when browsing through a list of natives. The same effect works for my function

JASS:
function MultiboardSetDisplayForPlayer takes player whichPlayer, multiboard mb returns nothing

JASS:
function MultiboardSetTitleTextForPlayer takes player whichPlayer, multiboard mb, string text returns nothing

They both use GetLocalPlayer() to match with whichPlayer.

I've spent 3 hours solving this problem, reversing the logic and stuff. So now I think I need your help. If you know anything relating to this please help me and I will give rep if possible.

Thanks :grin:
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
First of all.
I will edit later.
Edit:
You say in Dota heroes are removed from the tavern. Dude you do not know that. All you know is that after picking a hero you are not able to pick another one and other heroes are not visible to you. But you do not know how that is done.
Using GetLocalPlayer is tricky, especially if you do not know what you are doing.
Using natives that take player would be better.
Like constant native SetPlayerTechMaxAllowed takes player whichPlayer, integer techid, integer maximum returns nothing

Here is an example:
call SetPlayerTechMaxAllowed(GetTriggeringPlayer(),SomeHeroID,0)

I would also suggest using an array for easier manipulation.
 
Last edited:
Level 12
Joined
Aug 18, 2006
Messages
1,193
i believe to a full extent that a system like that would be obsolete

becouse if you set the limit of heroes a player can have to 1, once the player picks a hero, he wont be able to pick another one( in other words, all heroes from all the taverns will be removed for that player only :p)
 
Level 12
Joined
Aug 7, 2004
Messages
875
OK. According to the Tutorial

these functions will not cause a DeSync error

JASS:
function CreateQuestForPlayer takes player whichPlayer, integer questType, string title, string description, string iconPath returns nothing
    local boolean b = true
    if(GetLocalPlayer() != whichPlayer) then
        set b=false
    endif
    if(b==true) then
        call FlashQuestDialogButton()
        set Quests[GetPlayerId(whichPlayer)] = CreateQuestBJ(questType,title,description,iconPath)
    endif
endfunction

function FlashQuest takes player whichPlayer returns nothing
    local string s = "Sound\\Interface\\QuestActivateWhat1.wav"
    if(GetLocalPlayer() != whichPlayer) then
        set s = ""
    endif
    call PlaySound(s)
endfunction

However, it does... I don't know why... can someone help me?
 
Level 3
Joined
Dec 18, 2007
Messages
43
As i know first function will desync (cause you create\delete handle for local player)
Try to create for all players and disable it, then enable it only to local player
Try this:
JASS:
function CreateQuestForPlayer takes player whichPlayer, integer questType, string title, string description, string iconPath returns quest
    local quest MyQuest = CreateQuest() 
    local boolean required = (questType == bj_QUESTTYPE_REQ_DISCOVERED) or (questType == bj_QUESTTYPE_REQ_UNDISCOVERED)
    call QuestSetTitle(MyQuest, title)
    call QuestSetDescription(MyQuest, description)
    call QuestSetIconPath(MyQuest, iconPath)
    call QuestSetDiscovered(MyQuest, false)
    call QuestSetCompleted(MyQuest, false)
    call QuestSetRequired(MyQuest, required)
    if(GetLocalPlayer() == whichPlayer) then
        call FlashQuestDialogButton()
        call QuestSetDiscovered(MyQuest, true)
    endif
    return MyQuest
endfunction

function FlashQuest takes player whichPlayer returns nothing
    if(GetLocalPlayer() == whichPlayer) then
        PlaySound("Sound\\Interface\\QuestActivateWhat1.wav")
    endif
endfunction
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
And certain handle values will always be more than 100000 (units, effects etc).
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
Good to know about Gamecaching a lightning = bugs galore :)
But H2I does not use gamecache.
 
Level 12
Joined
Mar 23, 2008
Messages
942
I use that system on my map, I just added all the heroes to a array called AllHeroes and did a loop to disable them to players:

  • For each (Integer A) from 0 to 5, do (Actions)
    • Loop - Actions
      • Player - Make AllHeroes[(Integer A)] Unavailable for training/construction by (Owner of (Entering unit))
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
That should be it.
As for example handle variables would store the integer with ease.

But I must say, that I used Handle variables with lightnings(to destroy them after a period of time) with no problems and certainly no game crashes.
 
Level 6
Joined
Sep 5, 2007
Messages
264
More efficient use of H2I/H2S

I'm in the process of making a DotA'ish map of my own (from scratch). It uses a fair amount of triggered abilities and for speed's sake I use these functions:
JASS:
//**************************************
//        Local Handle Variables
//**************************************
function H2I takes handle h returns integer
    return h
    return 0
endfunction
function H2S takes handle h returns string
    return I2S(H2I(h))
endfunction

function InitLocalVars takes nothing returns nothing
    if (udg_Cache_LocalVars == null) then
        set udg_Cache_LocalVars = InitGameCache("local_vars.w3v")
    endif
endfunction

// **  Integer  **
function SetHandleVarInt takes string subject, string name, integer value returns nothing
    call StoreInteger(udg_Cache_LocalVars, subject, name, value)
endfunction
function GetHandleVarInt takes string subject, string name returns integer
    return GetStoredInteger(udg_Cache_LocalVars, subject, name)
endfunction
// **   Float   **
function SetHandleVarReal takes string subject, string name, real value returns nothing
    call StoreReal(udg_Cache_LocalVars, subject, name, value)
endfunction
function GetHandleVarReal takes string subject, string name returns real
    return GetStoredReal(udg_Cache_LocalVars, subject, name)
endfunction
// **  String   **
function SetHandleVarString takes string subject, string name, string value returns nothing
    call StoreString(udg_Cache_LocalVars, subject, name, value)
endfunction
function GetHandleVarString takes string subject, string name returns string
    return GetStoredString(udg_Cache_LocalVars, subject, name)
endfunction
// **  Boolean  **
function SetHandleVarBoolean takes string subject, string name, boolean value returns nothing
    call StoreBoolean(udg_Cache_LocalVars, subject, name, value)
endfunction
function GetHandleVarBoolean takes string subject, string name returns boolean
    return GetStoredBoolean(udg_Cache_LocalVars, subject, name)
endfunction

//-------------------
//    CONVERSIONS
//-------------------
function GetHandleVarUnit takes string subject, string name returns unit
    return GetStoredInteger(udg_Cache_LocalVars, subject, name)
    return null
endfunction
function GetHandleVarEffect takes string subject, string name returns effect
    return GetStoredInteger(udg_Cache_LocalVars, subject, name)
    return null
endfunction
function GetHandleVarTrigger takes string subject, string name returns trigger
    return GetStoredInteger(udg_Cache_LocalVars, subject, name)
    return null
endfunction
function GetHandleVarRect takes string subject, string name returns rect
    return GetStoredInteger(udg_Cache_LocalVars, subject, name)
    return null
endfunction
function GetHandleVarRegion takes string subject, string name returns region
    return GetStoredInteger(udg_Cache_LocalVars, subject, name)
    return null
endfunction
function GetHandleVarWeatherFX takes string subject, string name returns weathereffect
    return GetStoredInteger(udg_Cache_LocalVars, subject, name)
    return null
endfunction
function GetHandleVarTimer takes string subject, string name returns timer
    return GetStoredInteger(udg_Cache_LocalVars, subject, name)
    return null
endfunction
function GetHandleVarTimerDialog takes string subject, string name returns timerdialog
    return GetStoredInteger(udg_Cache_LocalVars, subject, name)
    return null
endfunction
function GetHandleVarGroup takes string subject, string name returns group
    return GetStoredInteger(udg_Cache_LocalVars, subject, name)
    return null
endfunction

function I2UNIT takes integer i returns unit
    return i
    return null
endfunction
function I2TIMER takes integer i returns timer
    return i
    return null
endfunction
function I2TIMER_DIALOG takes integer i returns timerdialog
    return i
    return null
endfunction
function I2EFFECT takes integer i returns effect
    return i
    return null
endfunction
function I2TRIGGER takes integer i returns trigger
    return i
    return null
endfunction
function I2RECT takes integer i returns rect
    return i
    return null
endfunction
function I2REGION takes integer i returns region
    return i
    return null
endfunction
function I2WEATHER_FX takes integer i returns weathereffect
    return i
    return null
endfunction
function I2GROUP takes integer i returns group
    return i
    return null
endfunction

function FlushHandleVars takes string subject returns nothing
    call FlushStoredMission(udg_Cache_LocalVars, subject)
endfunction

function FlushHandleVarReal takes string subject, string name returns nothing
    call FlushStoredReal(udg_Cache_LocalVars, subject, name)
endfunction
function FlushHandleVarInt takes string subject, string name returns nothing
    call FlushStoredInteger(udg_Cache_LocalVars, subject, name)
endfunction
function FlushHandleVarString takes string subject, string name returns nothing
    call FlushStoredString(udg_Cache_LocalVars, subject, name)
endfunction
function FlushHandleVarBoolean takes string subject, string name returns nothing
    call FlushStoredBoolean(udg_Cache_LocalVars, subject, name)
endfunction

To attach or read an attached var I use:
JASS:
    local string hand = H2S([I]unit[/I])
    local integer var1 = GetHandleVarInt(hand, "name1")
    local integer var2 = GetHandleVarInt(hand, "name2")
    local integer var3 = GetHandleVarInt(hand, "name3")
    local integer var4 = GetHandleVarInt(hand, "name4")

    <Insert other code here>

    call SetHandleVarInt(hand, "name1", var1)
    call SetHandleVarInt(hand, "name2", var2)
    call SetHandleVarInt(hand, "name3", var3)
    call SetHandleVarInt(hand, "name4", var4)

    set hand = null

Doing the H2I only once per handle is alot faster than doing it per variable.

I just thought that I'd let the peoples chatting about H2I know that I had discovered a faster more efficient way of using it.

NOTE: Sorry the post is SOOOO long, I thought the having my whole list of handle var functions would help poeple more.
 
Status
Not open for further replies.
Top