HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Replay Detection Script

07-03-2008, 09:52 AM#1
PandaMine
This function I discovered myself (and with the help of Captain Griffen). Simply put, if your actually playing a game, it will return true HOWEVER if your viewing the game as a replay it will return false. The function has been tested in MultiPlayer and it now causes no desyncs (by tested I mean vigorously tested by IceFrog for like 3 months). There is only one downside, and that is the function uses up one pause.

There might be a second version of the function that doesn't use up a pause (discovered by Strilanc) however there are a couple of issues with it

How does it work?
Simply put a replay is just a file that contains the inputs from the various players when playing a game. However when Wc3 views a replay, there are differences then if you were physically playing the game. One of the differences is pausing. If you are actually playing and you pause a game, it is paused. However during a replay, if you pause a game the replay simply finishes at the point you paused the game, if the game is resumed some time later then the replay completely skips the pause phase. There are only a few things that work in real time during pauses when your playing the game (anything else you do during the pause just gets 'suspended' until the game is resumed). The 2 things that work in real time are camera angles and trigger sleep action.

The function works by moving the camera during the pause. If the camera is moved during the pause, then you are playing the actual game. If the camera isn't moved then it is the replay (since the pause phase is totally skipped)

- It is HIGHLY recommended that you save the returning value of the function into a boolean variable i.e.
set someboolean = IsInGame()
So you only call the function once (since it takes up a pause)

Collapse JASS:
//<- InGame function created by PandaMine with help from Captain Griffen
function IsInGame takes nothing returns boolean
    local integer counter = 0
    local real camerax
    local real cameray
    local real x
    local real y
    local boolean output
    loop
        exitwhen counter > 11
        if GetLocalPlayer() == Player(counter) then
            set camerax = GetCameraTargetPositionX()
            set cameray = GetCameraTargetPositionY()
        endif
        set counter = counter + 1
    endloop
    set counter = 0
    call PauseGame(true)
    call TriggerSleepAction(0)
    loop
        exitwhen counter > 11
        if GetLocalPlayer() == Player(counter) then
            call SetCameraPosition(camerax + 1,cameray + 1)
        endif
        set counter = counter + 1
    endloop
    call TriggerSleepAction(0)
    call PauseGame(false)
    set counter = 0
    loop
        exitwhen counter > 11
        if GetLocalPlayer() == Player(counter) then
            set x = GetCameraTargetPositionX()
            if x == camerax + 1 then
                set output = true
            else
                set output = false
            endif
            call SetCameraPosition(camerax,cameray)
        endif
        set counter = counter + 1
    endloop
    return output
endfunction

With the new change to the function, it no longer needs to be synchronized however you should still initialize it like this because it has been reported that selecting units + triggersleepaction can cause desyncs

Collapse JASS:
function Initiate takes nothing returns nothing
    call EnableUserControl(false)
    call TriggerSleepAction(.0)
    set udg_InGame = IsInGame()
    call EnableUserControl(true)
endfunction
07-03-2008, 11:11 AM#2
DioD
This is antimaphack components isn it?
07-03-2008, 12:58 PM#3
PandaMine
kind of, sought of, not really (yes it is included in AMHS)

It was made because anti map hack needed it, but it can be used for anything. Hell you can even make a replay viewer engine out of this, all it is is its a simple function that detects if you are playing the game or watching the replay
07-03-2008, 02:18 PM#4
Vexorian
I just tested and you need either an attachment or a [jass] tag to submit. So it is working fine, just need to improve the error message?

Edit: There are bugs in my Jass tag detector, trying to fix them.
07-03-2008, 03:03 PM#5
Captain Griffen
It can be very useful for stuff like extra info being displayed in replays (more economic data, etc.). I'll give this newer function a good testing in the next Warlords version today or tomorrow (I'm still using the old one, probably the first one I got to work properly that needed a sync; works fine but a bit inefficient).
07-03-2008, 03:53 PM#6
Rising_Dusk
It's cute, but you should really fix your indenting.
07-03-2008, 04:49 PM#7
Captain Griffen
All seems to be in fine working order. You might want to change it to this though:

Collapse JASS:
function IsInGame takes nothing returns boolean
    local integer counter = 0
    local real camerax
    local real cameray
    local real x
    local real y
    local boolean output
    loop
        exitwhen counter > 11
        if GetLocalPlayer() == Player(counter) then
            set camerax = GetCameraTargetPositionX()
            set cameray = GetCameraTargetPositionY()
        endif
        set counter = counter + 1
    endloop
    set counter = 0
    call PauseGame(true)
    call TriggerSleepAction(0)
    loop
        exitwhen counter > 11
        if GetLocalPlayer() == Player(counter) then
            call SetCameraPosition(camerax + 1,cameray + 1)
        endif
        set counter = counter + 1
    endloop
    call TriggerSleepAction(0)
    call PauseGame(false)
    set counter = 0
    loop
        exitwhen counter > 11
        if GetLocalPlayer() == Player(counter) then
            set x = GetCameraTargetPositionX()
            if x == camerax + 1 then
                set output = true
            else
                set output = false
            endif
            call SetCameraPosition(camerax,cameray)
        endif
        set counter = counter + 1
    endloop
    return output
endfunction

Which goes 0-11 rather than 1-12, makes more sense reading wise, but other than that it's fine. And yes, you really should indent like the rest of the known universe (but that's a few key stroke for anyone importing it).

Approved
07-04-2008, 01:10 AM#8
PandaMine
Actually the version in AMHS is indented, this is the code I copied from another site

The indentation is fixed and the counter goes properly from 0-11 instead of 1-12 (it was a silly habit I developed when I wen't from GUI to JASS)
07-04-2008, 10:49 AM#9
Captain Griffen
Great. Well, I can confirm that, assuming there isn't some strange and ellusive bug in this particularly function which hasn't appeared yet, that it works great; been using a very similar function in Warlords for ages, and it's pretty nifty.

As much as I hate to say it, credit probably more has to go to toadcop than me, since he noticed that the GetCamera___ functions differed from replay to normal; I just sort of put all the clues from other people together.
07-05-2008, 05:56 PM#10
ThomasEddington
This may seem like a dumb question, but...what kind of situation would require me to know if I am playing a game or watching a replay? Is this something that applies to battle.net users? (I have never used battle.net)
07-05-2008, 09:04 PM#11
Vexorian
Perhaps you want some debug messages to appear during a replay and not otherwise?
07-05-2008, 09:26 PM#12
Captain Griffen
Or greater indepth info on screen for watching replays (obviously you don't want to give all that info to players while in game; that'd be silly).
07-07-2008, 02:25 AM#13
PandaMine
One really handy use could be, as you well know when viewing replays you don't see that green arrow that comes up when a unit is ordered to move to a point

With this system you could add that in replays, to show that green arrow whenever a unit moves to a spot for that player in focus
09-30-2008, 07:38 PM#14
Troll-Brain
Quote:
There might be a second version of the function that doesn't use up a pause (discovered by Strilanc)

Do you have one ?
11-05-2008, 04:09 AM#15
Builder Bob
Great system. It's really useful for preventing certain cinematic fade out/in as well as forced camera changes when watching replays.

Why do you need the loops and the GetLocalPlayer() checks though. They seem kind of redundant since GetCamera/SetCamera functions give local returns and output anyway. Maybe there's something I'm missing.