Template IsWar3Minimized

Troll-Brain

You can change this now in User CP.
Reaction score
85
It's a script for the lul'z.

By war3 minimized i mean when you reduce it to use an other software, i'm not talking about the window mode.
It won't work on single player mode because war3 is paused when you minimize it, but war3 won't be paused when you play on local area network, battle.net,whatever.

DrawBacks that shouldn't be fixed :

- Each time the "system" will do a check, a "pan" camera will be applied, so if the player pressed an arrow or moved the camera with the mouse, the movement will be stop.
Unfortunately i don't think it could be fix in any way, even for the arrows, since the arrow press event has delay.

- Theoretically it could fail if the user press the space bar.

- You can't use it when a camerasetup or just a camera field which are currently applied during time, last time i checked it fucks up all the move.

- You can't use a target noise

DrawBacks that should be fixed :

- Theoretically it could fuck up the player unit selection. (game cache sync instead ? but i don't know how to do it for each players, someone ?)

- You can't use it with SetCameraTargetController and such things, i think i could play around that using hooks though.

I know :

- It will fail if the camera is on top right, but fortunately this case can be fixed easily
- The code needs to be improved in some ways, like adding more constants, use the booleexpr of TriggerRegisterPlayerEvent, be able to enable/disable the check, handle leavers, and so one.

It's one second (in)accurate and i don't recommend to try a lower value.

Now, i just want to know your feedbacks, and if they are good enough i will work on removing some cons, fixing known lame things.

PS : If you already pan your camera each 0.03 s or so, you would inline this method instead.

JASS:
library IsWc3Minimized initializer onInit needs SyncDatas

globals
    private constant real PERIOD = 1.0 // it's the period which the system check for each player if war3 is minimized, don't use a value lower than 1.0 s
endglobals

globals // you should'nt edit them
    private constant real MARGIN = 0.03
    private constant real EPSILON = 0.1
endglobals

globals
    private integer array TimeElapsed
    private timer Tim
    private real X
    private real Y
    private sound DummySound
    private integer Index
    private boolean CheckNeeded = true
    private real Xmin
    private real Xmax
    private real Ymin
    private real Ymax
    private boolean SecondCheck = false
endglobals

function GetMinimizeTimeForPlayer takes player whichPlayer returns integer
    return TimeElapsed[GetPlayerId(whichPlayer)]
endfunction

function IsMinimizeForPlayer takes player whichPlayer returns boolean
    return TimeElapsed[GetPlayerId(whichPlayer)] != 0
endfunction

private function Update takes integer i returns nothing
    local integer index = GetPlayerId(GetSyncedPlayer())

    if GetBooleanForPlayer(SCOPE_PREFIX,GetSyncedPlayer()) then
        set TimeElapsed[index] = TimeElapsed[index]+1
    else
        set TimeElapsed[index] = 0
    endif
endfunction

private function Actions takes nothing returns nothing

    local real r = TimerGetTimeout(Tim)
    local real x
    local real y
    local boolean b = false
    
    if r == MARGIN then
    
        if SecondCheck then

            if CheckNeeded then
            
                set b = (GetCameraTargetPositionX() == X and GetCameraTargetPositionY() == Y)
                call SetCameraPosition(X,Y)
                 
            endif

            call TimerStart(Tim,PERIOD-2.*MARGIN,false,function Actions)
            call SyncBoolean(b,SCOPE_PREFIX,Update,0)
            
            return

        elseif CheckNeeded and X == GetCameraTargetPositionX() and Y == GetCameraTargetPositionY() then // the camera doesn't move
            
            if X >= Xmax then
                set x = Xmax - EPSILON
            elseif X <= Xmin then
                set x = Xmin + EPSILON
            else
                set x = X + EPSILON
            endif
            
            if Y >= Ymax then
                set y = Ymax - EPSILON
            elseif Y <= Ymin then
                set y = Ymin + EPSILON
            else
                set y = Y + EPSILON
            endif
            
            call SetCameraPosition(x,y)
            
        endif        
        
        set SecondCheck = true
        call TimerStart(Tim,MARGIN,false,function Actions)
        return
        
        
    elseif r == PERIOD-2.*MARGIN then // yeah i could just use an else here, it's just for the code sense

        set SecondCheck = false
        set CheckNeeded = true
        call StartSound(DummySound)
        
        if GetSoundIsPlaying(DummySound) then // war3 can't be minimized
            set CheckNeeded = false
        
        else
            
            set X = GetCameraTargetPositionX()
            set Y = GetCameraTargetPositionY()
        
        endif
        call TimerStart(Tim,MARGIN,false,function Actions)
        
    endif    

endfunction

private function onInit takes nothing returns nothing
    local integer i = 0
    
    set Tim = CreateTimer()

    call TimerStart(Tim,PERIOD-2.*MARGIN,false,function Actions)
    

    set DummySound = CreateSound("Sound\\Music\\mp3Music\\Credits.mp3", false, false, false, 0, 0, "")
    call SetSoundVolume(DummySound,0)
    set Xmax = GetCameraBoundMaxX()
    set Xmin = GetCameraBoundMinX()
    set Ymax = GetCameraBoundMaxY()
    set Ymin = GetCameraBoundMinY()
    
endfunction

endlibrary


JASS:
library SyncDatas initializer onInit

globals
    private gamecache GC = null // leave it to null, or use your own but i don't recommend it
                                // i only let this possibility because of the limit of 256 game caches
endglobals

private function interface FunctionInterface takes integer i returns nothing

globals
    private force Players
    private integer I
    private string TempVariableName
    private FunctionInterface TempFunc
    private integer TempIndex
    private player SyncedPlayer = null
endglobals

private function Crash takes nothing returns nothing // just a test function
    call Crash.execute()
endfunction

function GetSyncedPlayer takes nothing returns player
    return SyncedPlayer
endfunction

//! runtextmacro t_InitSyncDatas("boolean","Boolean","false")
//! runtextmacro t_InitSyncDatas("integer","Integer","0")
//! runtextmacro t_InitSyncDatas("real","Real","0.")
//! runtextmacro t_InitSyncDatas("string","String","null")

//! textmacro t_InitSyncDatas takes TYPE , TYPE_NAME , TYPE_NULL

globals
    private $TYPE$ Temp$TYPE_NAME$ = $TYPE_NULL$
endglobals

private function DoThe$TYPE_NAME$Sync takes nothing returns nothing
    local integer i = GetPlayerId(GetEnumPlayer())
    local string variableName = TempVariableName
    local string s = SCOPE_PREFIX + "$TYPE_NAME$"
    local FunctionInterface f = TempFunc
    local integer data = TempIndex
    
    if GetLocalPlayer() == Player(i) then
        call Store$TYPE_NAME$(GC,s,variableName+I2S(i),Temp$TYPE_NAME$)
    endif
    call TriggerSyncStart()
    
    //if GetLocalPlayer() == Player(1) then // just to test the case when a player left during the sync
      //  call Crash()
    //endif
    
    if GetLocalPlayer() == Player(i) then
        call SyncStored$TYPE_NAME$(GC, s, variableName+I2S(i))
    endif

    call TriggerSyncReady()
    
    set SyncedPlayer = Player(i)
    call f.evaluate(data)
    set SyncedPlayer = null

endfunction

private function Callback$TYPE_NAME$ takes nothing returns nothing
    call DoThe$TYPE_NAME$Sync.execute()
endfunction

function Get$TYPE_NAME$ForPlayer takes string variableName, player whichPlayer returns $TYPE$
    return GetStored$TYPE_NAME$(GC,SCOPE_PREFIX + "$TYPE_NAME$",variableName+I2S(GetPlayerId(whichPlayer)))
endfunction

function Sync$TYPE_NAME$ takes $TYPE$ which$TYPE_NAME$, string variableName, FunctionInterface whichFunction, integer data returns nothing
    set TempVariableName = variableName
    set Temp$TYPE_NAME$ = which$TYPE_NAME$
    set TempFunc = whichFunction
    set TempIndex = data
    call ForForce(Players,function Callback$TYPE_NAME$)
    set TempVariableName = ""
    set Temp$TYPE_NAME$ = $TYPE_NULL$
    set TempFunc = 0
    set TempIndex = 0
endfunction

//! endtextmacro

private function HandleLeavers takes nothing returns boolean
    call ForceRemovePlayer(Players,GetTriggerPlayer())
    return false
endfunction

private function onInit takes nothing returns nothing
    local trigger trig = CreateTrigger()
    local integer i = 0
    
    set Players = CreateForce()
    
    if GC == null then
        set GC = InitGameCache(SCOPE_PREFIX)
    endif
    
    loop
    exitwhen i == 12
    
        if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(i)) == MAP_CONTROL_USER then
            call ForceAddPlayer(Players,Player(i))
            call TriggerRegisterPlayerEvent(trig,Player(i),EVENT_PLAYER_LEAVE)
            call TriggerAddCondition(trig,function HandleLeavers)
        endif
    
    set i = i+1
    endloop
    

endfunction

endlibrary


And a short lame example :

JASS:
scope TestIsWc3Minimized initializer init

private function Handler takes nothing returns nothing
    call BJDebugMsg(GetPlayerName(Player(0)) + " : " +I2S(GetMinimizeTimeForPlayer(Player(0))))
    call BJDebugMsg(GetPlayerName(Player(1)) + " : " +I2S(GetMinimizeTimeForPlayer(Player(1))))
    call BJDebugMsg(" ")
endfunction

private function init takes nothing returns nothing
    local timer tim = CreateTimer()
    call TimerStart(tim,1.,true,function Handler)
endfunction

endscope
 

quraji

zap
Reaction score
144
JASS:
function IsPlayerAfk takes player whichPlayer returns boolean // same here
    return TimeElapsed[GetPlayerId(whichPlayer)] == 0
endfunction


I really just skimmed this, but shouldn't the return line be:
[ljass]return TimeElapsed[GetPlayerId(whichPlayer)] != 0[/ljass]
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
But technically a player with his war3 minimized would be all but not away from keyboard.
I mean he could be afk but it's less likely, but yeah he is away from war3, so afw instead ? :D
 

Romek

Super Moderator
Reaction score
963
Just as 99% of people don't laugh out loud when they say 'lol', I'm sure many people aren't actually away from the keyboard when they say 'afk'.
Just think of 'afk' as 'Away', without the other two words. :p

Besides, if you went away from keyboard to get food or something; why would you minimize Warcraft? :p
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
Just as 99% of people don't laugh out loud when they say 'lol', I'm sure many people aren't actually away from the keyboard when they say 'afk'.
But i really do :confused:
Seriously, i think the opposite, when i say i will be afk, it's most likely i go for some food or so :D
But you're probably right, i'm not like the majority of people for the worst and the best ...

Just think of 'afk' as 'Away', without the other two words. :p
Hmm, it's probably the best choice, i still love "away from war3" though.

Besides, if you went away from keyboard to get food or something; why would you minimize Warcraft? :p
That's exactly why i say "afk" is lame here, when i minimize war3 i'm still on pc to look about some porn or whatever :D
And when i'm really afk i don't reduce war3 most of the times.
 

Romek

Super Moderator
Reaction score
963
How about a simple "Is Player Away"?
[ljass]IsPlayerAway[/ljass] and [ljass]GetPlayerAwayTime[/ljass] don't sound too bad either.
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
Indeed.
I will rename that after removing some cons, and fix the possible bug when camera is already on max right.
 

quraji

zap
Reaction score
144
You should test this line:
[ljass] set Dummy = CreateUnit(DUMMY_PLAYER,DUMMY_UNITID,1000000.,1000000.,0.)[/ljass]

Create it for yourself instead to test..because when I tried to create a unit outside the map recently it just was stuck in the corner instead. I had to create it, then SetUnitX it off the map.
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
You should test this line:
[ljass] set Dummy = CreateUnit(DUMMY_PLAYER,DUMMY_UNITID,1000000.,1000000.,0.)[/ljass]

Create it for yourself instead to test..because when I tried to create a unit outside the map recently it just was stuck in the corner instead. I had to create it, then SetUnitX it off the map.

Yes it's created in the corner but it's not the playable map area, it's the entire map, which is enough.
According to Vexorian it seems to crash (sometimes ?) and not instantly when you put an unit outside the whole map.
 

quraji

zap
Reaction score
144
>Yes it's created in the corner but it's not the playable map area, it's the entire map, which is enough.

Are you sure? I think I remember it still being in the walkable area.

>According to Vexorian it seems to crash (sometimes ?) and not instantly when you put an unit outside the whole map.

I thought it just crashed for Macs, but only on a negative x and y? Or something funky like that..
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
Are you sure? I think I remember it still being in the walkable area.
Yes i'm sure, i always test before submit something.

I thought it just crashed for Macs, but only on a negative x and y? Or something funky like that..
I've windows xp sp2, last time checked it crashed when you use an Y outside the whole map (at least a positive one), but not instantly, and it crashed with an X outside the whole map (still a positive one) but not directly, in my case war3 crashed after few seconds on a camera movement which had nothing with the unit position.
 

quraji

zap
Reaction score
144
Okay. I'll take your word for it :)

I just tried this by myself on a test map, on B.Net and for some reason (not sure if it's your system or what), if I panned my camera with the arrow keys they would stop working randomly.

Like, if I held the right arrow it would pan right for a varying number of seconds then just stop (I was not at map bounds). Same thing with the other keys as well. I have to unpress then press it again, until it locks again.

I tried this on another map and it worked fine.
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
It's known if you read the first post.
Unfortunately each time you pan the camera, the arrow key movement is stopped, and i need to pan the camera, it's how it works.
The camera isn't moved on computers with war3 minimized.

All you can do is increase the time between 2 check but then ofc it will be less accurate.
I will explain clearly when the documentation will be made and the code finished.
Anyway it's more a neat toy than something really usable :D

For the right thing it's also known, since when i released the code, and this case can be fixed so easily.
I just wanted some feedbacks before putting more work on this.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top