Задача следующая, в реплее нужно отобразить ряд дополнительной инфы, которая в самой игре может, как отображаться, так и нет. (от предпочтений игрока)
Остались ли какие-то рабочие варианты детекта на то, что просматривается реплэй?

Вот рабочая система с хайва. Различает реплей, одиночную и сетевую игру.
Инициализируется на стадии загрузки карты, поэтому не придется ждать 2.9 сек.
Нет ложного срабатывания на свернутую игру.
`
ОЖИДАНИЕ РЕКЛАМЫ...
32
Ну либо игрок обсерв как в доте, еще как то с синиматиком (слышал краем уха) и мемхаком, о последнем вскользь упоминал лич.
Надо будет посмотреть древний -ah мод в некоторых картах, там это как то делали...
В старых амх как то отличали игру от реплея, чтобы не делать юнитов прозрачными когда кто то смотрит реплей www.wc3c.net/showthread.php?t=97922
Там есть костыль определения реплея.
21
Есть ещё такие ссылки по теме
Но я так понимаю инфа опубликованная по ним уже не актуальна.
В продолжение вопроса есть ещё одна мысль, как работает GetLocalPlayer() при проигрывании реплея?
Например если изначально сделать отображение всей "доп инфы" на старте игры для всех, а затем сразу же локально скрыть её.
32
awesomesk1ll, всегда всегда первый игрок вроде.
//**************************************************************************************
//*                                                                                    *
//*                         REPLAY DETECT ENGINE V1.30                                 *
//*                     CONFIGURATION SETTINGS START HERE                              *
//*                                                                                    *
//**************************************************************************************
library ReplayDetectEngine
globals
boolean InGame = true
boolean array AMHS_FogDisable
boolean array AMHS_InvisDisable
unit array AMHS_FogDummy
unit array AMHS_InvisDummy
endglobals

//-> IsInGame created by PandaMine with help from Captain Griffen
//This function is what makes it possible for the system not to break replays,
//simply put if your actually playing the game, this function will return false.
//It will return true if the game is being viewed in a replay

private function IsInGame takes nothing returns boolean
local integer counter = 1
local real camerax
local real cameray
local real x
local real y
local boolean output
loop
    exitwhen counter > 12
    if GetLocalPlayer() == Player(counter-1) then
        set camerax = GetCameraTargetPositionX()
        set cameray = GetCameraTargetPositionY()
    endif
    set counter = counter + 1
endloop
set counter = 1
call PauseGame(true)
call TriggerSleepAction(0)
loop
    exitwhen counter > 12
    if GetLocalPlayer() == Player(counter-1) then
        call SetCameraPosition(camerax + 1,cameray + 1)
    endif
    set counter = counter + 1
endloop
call TriggerSleepAction(0)
call PauseGame(false)
set counter = 1
loop
    exitwhen counter > 12
    if GetLocalPlayer() == Player(counter-1) 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 

function AMHS_ReplayEngine takes nothing returns nothing
call EnableUserControl(false)
call TriggerSleepAction(.0)
set InGame = IsInGame()
call EnableUserControl(true)
endfunction
Проверял эту штуку?
21
quq_CCCP:
Ну либо игрок обсерв как в доте
Этот вариант не подходит, т.к у нас все 12 слотов доступны для игры).
quq_CCCP:
Проверял эту штуку?
Пока не успел, не дома. Прикидываю варианты "что потестить" )
19
quq_CCCP, IsInGame возвращает false, в случае когда идет просмотр реплея или если игра свернута.
32
IceFog, Ну уже хорошо, что работает.
Еще есть возможность проверки на ретурн баге, но я не знаю в каком направлении копать, мб кто колупал игру знает где посмотреть что игра реплей.
21
quq_CCCP:
IceFog, Ну уже хорошо, что работает.
Игра может быть свёрнута и не в реплее, в этом беда..
Если я буду выводить реплейную инфу во время игры будет не очень хорошо).
22
свернутый паузит игру проверять паузу и чек игры, вроде как бы! Так как так!
32
Так постойте, что мешает вначале чекнуть когда все загрузились - реплей или нет, а потом уже хоть за сворачивайтесь.
На афкашеров пофигу, что им лишнее что то показалось, чаще всего такие вовсе не приходят или ливают.
21
quq_CCCP:
На афкашеров пофигу, что им лишнее что то показалось, чаще всего такие вовсе не приходят или ливают.
Да не, часто бывает что пока загрузка идёт кто-то может табнуться мессенжеры/вконтачи посмотреть, или музон переключить.. Нельзя так игроков хоронить корявыми решениями)
32
awesomesk1ll, ты можешь синкнуть между всеми значение InGame, кстати там вроде все игроки проверяются, в мультиплеере кто-нить тестил?
21
quq_CCCP:
awesomesk1ll, ты можешь синкнуть между всеми значение InGame, кстати там вроде все игроки проверяются, в мультиплеере кто-нить тестил?
та на это не смотри особо) эта либа корявая же..
GetCameraTargetPositionX() возвращает локальное X же?) нафига там цикл вообще.
32
Там локал плауер для всех 12 игроков
Смотри код внимательнее
21
ловким движением руки из кода выкидываются циклы, а смысл не меняется.
private function IsInGame takes nothing returns boolean
local integer counter = 1
local real camerax
local real cameray
local real x
local real y
local boolean output
loop
    exitwhen counter > 12
    if GetLocalPlayer() == Player(counter-1) then
        set camerax = GetCameraTargetPositionX()
        set cameray = GetCameraTargetPositionY()
    endif
    set counter = counter + 1
endloop
set counter = 1
call PauseGame(true)
call TriggerSleepAction(0)
loop
    exitwhen counter > 12
    if GetLocalPlayer() == Player(counter-1) then
        call SetCameraPosition(camerax + 1,cameray + 1)
    endif
    set counter = counter + 1
endloop
call TriggerSleepAction(0)
call PauseGame(false)
set counter = 1
loop
    exitwhen counter > 12
    if GetLocalPlayer() == Player(counter-1) 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 
private function IsInGame takes nothing returns boolean
local integer counter = 1
local real camerax
local real cameray
local real x
local real y
local boolean output
        set camerax = GetCameraTargetPositionX()
        set cameray = GetCameraTargetPositionY()

call PauseGame(true)
call TriggerSleepAction(0)

        call SetCameraPosition(camerax + 1,cameray + 1) 

call TriggerSleepAction(0)
call PauseGame(false)

        set x = GetCameraTargetPositionX()
            set output = (x == camerax)
        call SetCameraPosition(camerax,cameray)

return output
endfunction 
Смотри код внимательнее
28
awesomesk1ll,
ты на дисинхрон тестил? Я когда юзал этот код у меня дисинхронизация в самой игре была.
21
ну просто GetCameraTargetPositionX() SetCameraPosition() это локальные функции, их можно одновременно для всех игроков запустить спокойно, поправьте если не так)).
32
16GB, тестанул код, но делал разделения только на визуальные действия, т.е камеру не перемещал при телепортах и перерождениях героев в реплее, всё норм. Но вот без цилков, рили может десинхать, ты же не для каждого игрока записываешь проверку, а для всех.
Нужно тестить в муи, судя по тому что похожий антихак засунули в доту ниче не дисинхало и ниче не делало вред, правда читеры очень быстро научились обходить прозрачность юнитов и всякие туманы, затеняющие карту...
В доте вроде юзается какая то фишка с кинематиком, хз в чем различие киниматике в игре и в реплее?
Код лень колупать...
21
ты на дисинхрон тестил?
Дак нет, я имею ввиду, что дальше то, только то использовать с такой булей, что может локально без десинков работать, это основное правило работы с асинк данными.
В общем это бОльше от нужд зависит, ну вверху я писал, что мне только с отображением поиграться, так что достаточно).
Основные приёмы как не ловить десинк в примерах по getlocalplayer() описаны
В общем пока такие результаты:
Реплей проигрывается с 5-6 игровой секунды, соответственно если двигать и проверять камеру до 5 секунды, в реплее движения камеры не будет.
Но если игрок долго "залипает" в альтабе, то движения камеры так же может и не быть. Вопрос в том каким образом отловить alt+tab или паузу (isPausedGame).
32
awesomesk1ll, а что если в кешь записать могут ли двигать камеру все игроки, если все нет - то реплей, если большинство да, то синхронизируем с ними данные и записываем в переменную.
19
Попробуй мемхак (код подходит только для патча 1.26a)
Адреса и смещения не делены на 4!
int ptr1 = Read(GameDll + $AB4F80)
int ptr2 = Read(ptr1 + $3C8)
int ptr3 = Read(ptr2 + $15C)
bool IsReplay = (ptr3 != 0)
32
IceFog, проверил в сингле - отличает репу от игры
    private function IsRaplay takes nothing returns boolean
        local integer ptr1 = RMem(GameDLL + $AB4F80)
        local integer ptr2 = RMem(ptr1 + $3C8)
        local integer ptr3 = RMem(ptr2 + $15C)
        return (ptr3 != 0)
    endfunction
19
Нашел смещение для новой версии:
code
int offset

// Не знаю как вы там версии сравниваете
if (VERSION == 1.26a) then
	offset = $AB4F80
elseif (VERSION == 1.27a)
	offset = $BE6350
endif

int ptr1 = Read(GameDll + offset)
int ptr2 = Read(ptr1 + $3C8)
int ptr3 = Read(ptr2 + $15C)
bool IsReplay = (ptr3 != 0)
На афкашеров пофигу, что им лишнее что то показалось, чаще всего такие вовсе не приходят или ливают.
Я часто сворачиваю игру, мало ли сколько народ набираться будет.
А после загрузки игры я получаю уведомление от программы.
19
quq_CCCP, ты имеешь ввиду смещения для прочих версий?
у меня есть game.dll только для 1.26a, 1.27a, 1.27b (тут мемхак уже не пашет?)
21
Вроде более менее разобрались.
В начале игры происходит лаг, который не дает двигать камеру. Его продолжительность меняется от случая к случаю.
Так же если происходят лаги вызванные происходящим в самой игре (зависит от конкретных решений внутри карты) могут так же появляться
лаги, препятствующие передвижению камеры.
В самом лучшем случае, при просмотре реплея, игра начинается примерно с 2.9 сек (проверялось на пустой melee карте)
Таким образом между концом вступительного игрового лага и началом игры в реплее, есть окно, внутри которого можно расположить проверку. (как уже писал выше, передвижение камеры в реплее не работает, если оно вызывалось до старта реплея, 2.9~)
На 0.101 можно не смотреть (т.к выполняется при инициализации карты, в реплее в том числе)
Немного про SetCameraBounds, проверяет текущее положение камеры и двигает её в установленные границы, но не делает этого, если игра свёрнута, в реплее работает так же, как и в обычной игре.
код на котором остановились
library ReplayLib

struct ReplayLib extends array
    readonly static boolean wasPaused = false
    readonly static boolean wasReplay = false
    readonly static boolean wasMeasured = false
    
    private static real x = 0
    private static real y = 0
    
    private static real tx1 = 0
    private static real tx2 = 0
    
    private static real newx1 = 0
    private static real newx2 = 0
    
    private static real minX = 0
    private static real minY = 0
    private static real maxX = 0
    private static real maxY = 0
    
    private static method onReplayTest2 takes nothing returns nothing
        call DestroyTimer(GetExpiredTimer())
        
        set newx2 = GetCameraTargetPositionX()
        
        set wasReplay = (((tx1 != newx1) and (tx2 != newx2)) and (not wasPaused))
        set wasMeasured = true
        
        call SetCameraBounds(minX, minY, minX, maxY, maxX, maxY, maxX, minY)
        call SetCameraPosition(x, y)
        
        call EnableUserControl(true)
    endmethod
    
    // Tests if we are running in a replay
    private static method onReplayTest1 takes nothing returns nothing
        set newx1 = GetCameraTargetPositionX()
        
        call SetCameraPosition(tx2, y) // Pan camera (doesn't occur near start of replays)
        
        call TimerStart(GetExpiredTimer(), 0.2, false, function thistype.onReplayTest2)
    endmethod
    
    private static method onPausedTest takes nothing returns nothing
        set wasPaused = (x == GetCameraTargetPositionX())
        
        call SetCameraPosition(tx1, y) // Pan camera (doesn't occur near start of replays)
        
        call TimerStart(GetExpiredTimer(), 0.5, false, function thistype.onReplayTest1)
    endmethod
    
    // Schedules the replay test as soon as possible
    private static method onInit takes nothing returns nothing
        call EnableUserControl(false) // Block users from manually moving the screen
        
        set x = GetCameraTargetPositionX()
        set y = GetCameraTargetPositionY()
        
        set tx1 = x + 2
        set tx2 = x + 3
        
        set minX = GetCameraBoundMinX()
        set minY = GetCameraBoundMinY()
        set maxX = GetCameraBoundMaxX()
        set maxY = GetCameraBoundMaxY()
        
        call SetCameraBounds(x + 1, y, x + 1, y, tx2, y, tx2, y)
        
        call TimerStart(CreateTimer(), 1.1, false, function thistype.onPausedTest)
    endmethod
endstruct

// Returns the outcome of the replay test
function IsReplay takes nothing returns boolean
    if (not ReplayLib.wasMeasured) then
        call BJDebugMsg("[ReplayLib] Error: used IsReplay() before value was ready.")
    endif
    return ReplayLib.wasReplay
endfunction

endlibrary
Загруженные файлы
Чтобы оставить комментарий, пожалуйста, войдите на сайт.