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

Принятый ответ

Вот рабочая система с хайва. Различает реплей, одиночную и сетевую игру.
Инициализируется на стадии загрузки карты, поэтому не придется ждать 2.9 сек.
Нет ложного срабатывания на свернутую игру.
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
32
7 лет назад
0
Ну либо игрок обсерв как в доте, еще как то с синиматиком (слышал краем уха) и мемхаком, о последнем вскользь упоминал лич.
Надо будет посмотреть древний -ah мод в некоторых картах, там это как то делали...
В старых амх как то отличали игру от реплея, чтобы не делать юнитов прозрачными когда кто то смотрит реплей www.wc3c.net/showthread.php?t=97922
Там есть костыль определения реплея.
0
21
7 лет назад
0
Есть ещё такие ссылки по теме
Но я так понимаю инфа опубликованная по ним уже не актуальна.
В продолжение вопроса есть ещё одна мысль, как работает GetLocalPlayer() при проигрывании реплея?
Например если изначально сделать отображение всей "доп инфы" на старте игры для всех, а затем сразу же локально скрыть её.
0
32
7 лет назад
0
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
Проверял эту штуку?
0
21
7 лет назад
Отредактирован awesomesk1ll
0
quq_CCCP:
Ну либо игрок обсерв как в доте
Этот вариант не подходит, т.к у нас все 12 слотов доступны для игры).
quq_CCCP:
Проверял эту штуку?
Пока не успел, не дома. Прикидываю варианты "что потестить" )
0
14
7 лет назад
0
quq_CCCP, IsInGame возвращает false, в случае когда идет просмотр реплея или если игра свернута.
0
32
7 лет назад
Отредактирован quq_CCCP
0
IceFog, Ну уже хорошо, что работает.
Еще есть возможность проверки на ретурн баге, но я не знаю в каком направлении копать, мб кто колупал игру знает где посмотреть что игра реплей.
0
21
7 лет назад
0
quq_CCCP:
IceFog, Ну уже хорошо, что работает.
Игра может быть свёрнута и не в реплее, в этом беда..
Если я буду выводить реплейную инфу во время игры будет не очень хорошо).
0
23
7 лет назад
0
свернутый паузит игру проверять паузу и чек игры, вроде как бы! Так как так!
0
32
7 лет назад
0
Так постойте, что мешает вначале чекнуть когда все загрузились - реплей или нет, а потом уже хоть за сворачивайтесь.
На афкашеров пофигу, что им лишнее что то показалось, чаще всего такие вовсе не приходят или ливают.
0
21
7 лет назад
0
quq_CCCP:
На афкашеров пофигу, что им лишнее что то показалось, чаще всего такие вовсе не приходят или ливают.
Да не, часто бывает что пока загрузка идёт кто-то может табнуться мессенжеры/вконтачи посмотреть, или музон переключить.. Нельзя так игроков хоронить корявыми решениями)
0
32
7 лет назад
0
awesomesk1ll, ты можешь синкнуть между всеми значение InGame, кстати там вроде все игроки проверяются, в мультиплеере кто-нить тестил?
0
21
7 лет назад
0
quq_CCCP:
awesomesk1ll, ты можешь синкнуть между всеми значение InGame, кстати там вроде все игроки проверяются, в мультиплеере кто-нить тестил?
та на это не смотри особо) эта либа корявая же..
GetCameraTargetPositionX() возвращает локальное X же?) нафига там цикл вообще.
0
32
7 лет назад
0
Там локал плауер для всех 12 игроков
Смотри код внимательнее
0
21
7 лет назад
0
ловким движением руки из кода выкидываются циклы, а смысл не меняется.
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 
Смотри код внимательнее
0
29
7 лет назад
0
awesomesk1ll,
ты на дисинхрон тестил? Я когда юзал этот код у меня дисинхронизация в самой игре была.
0
21
7 лет назад
0
ну просто GetCameraTargetPositionX() SetCameraPosition() это локальные функции, их можно одновременно для всех игроков запустить спокойно, поправьте если не так)).
0
32
7 лет назад
0
16GB, тестанул код, но делал разделения только на визуальные действия, т.е камеру не перемещал при телепортах и перерождениях героев в реплее, всё норм. Но вот без цилков, рили может десинхать, ты же не для каждого игрока записываешь проверку, а для всех.
Нужно тестить в муи, судя по тому что похожий антихак засунули в доту ниче не дисинхало и ниче не делало вред, правда читеры очень быстро научились обходить прозрачность юнитов и всякие туманы, затеняющие карту...
В доте вроде юзается какая то фишка с кинематиком, хз в чем различие киниматике в игре и в реплее?
Код лень колупать...
0
21
7 лет назад
Отредактирован awesomesk1ll
0
ты на дисинхрон тестил?
Дак нет, я имею ввиду, что дальше то, только то использовать с такой булей, что может локально без десинков работать, это основное правило работы с асинк данными.
В общем это бОльше от нужд зависит, ну вверху я писал, что мне только с отображением поиграться, так что достаточно).
Основные приёмы как не ловить десинк в примерах по getlocalplayer() описаны
В общем пока такие результаты:
Реплей проигрывается с 5-6 игровой секунды, соответственно если двигать и проверять камеру до 5 секунды, в реплее движения камеры не будет.
Но если игрок долго "залипает" в альтабе, то движения камеры так же может и не быть. Вопрос в том каким образом отловить alt+tab или паузу (isPausedGame).
0
32
7 лет назад
0
awesomesk1ll, а что если в кешь записать могут ли двигать камеру все игроки, если все нет - то реплей, если большинство да, то синхронизируем с ними данные и записываем в переменную.
0
14
7 лет назад
0
Попробуй мемхак (код подходит только для патча 1.26a)
Адреса и смещения не делены на 4!
int ptr1 = Read(GameDll + $AB4F80)
int ptr2 = Read(ptr1 + $3C8)
int ptr3 = Read(ptr2 + $15C)
bool IsReplay = (ptr3 != 0)
0
32
7 лет назад
0
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
0
14
7 лет назад
Отредактирован IceFog
0
Нашел смещение для новой версии:
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)
На афкашеров пофигу, что им лишнее что то показалось, чаще всего такие вовсе не приходят или ливают.
Я часто сворачиваю игру, мало ли сколько народ набираться будет.
А после загрузки игры я получаю уведомление от программы.
0
32
7 лет назад
0
IceFog, Прочие фишки реплеев не найдено?
0
14
7 лет назад
Отредактирован IceFog
0
quq_CCCP, ты имеешь ввиду смещения для прочих версий?
у меня есть game.dll только для 1.26a, 1.27a, 1.27b (тут мемхак уже не пашет?)
0
21
7 лет назад
Отредактирован awesomesk1ll
0
Вроде более менее разобрались.
В начале игры происходит лаг, который не дает двигать камеру. Его продолжительность меняется от случая к случаю.
Так же если происходят лаги вызванные происходящим в самой игре (зависит от конкретных решений внутри карты) могут так же появляться
лаги, препятствующие передвижению камеры.
В самом лучшем случае, при просмотре реплея, игра начинается примерно с 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
Загруженные файлы
Чтобы оставить комментарий, пожалуйста, войдите на сайт.