Суть:

После загрузки игры система ищет на компьютере каждого игрока txt файл, в котором записано некое число, если файла нет, то число=0, потом найденной число синхронизируется через игровой кеш и заполняется массив, после этого мы уже может просуммировать все полученные данные и установить уровень сложности.
Функция Load
globals
integer gk=0
endglobals


function Trig_Evenload_Actions takes nothing returns nothing
local string s=""
local string data=""

call Preloader("save\\PreExp.txt")//меняет всем имя игрока 16 на индивидульное значение или не?  что будет если с фаила игрока 1
////// выгружается 1, а из игрока 2 - 50? а у игрока у кого нет фаилла вызвается "игрок 16"


if GetLocalPlayer()==Player(gk)  then
set s=GetPlayerName(Player(15)) // S примет индвидуальные значения от каждого игрока
endif

if GetPlayerController(Player(gk)) == MAP_CONTROL_USER then
call BJDebugMsg("Загрузка результатов для " +GetPlayerName(Player(gk)))
set data = SyncString(Player(gk), s)//пауза 2 сек
set cgame[gk]=S2I(data)

if cgame[gk]==0 then
call BJDebugMsg(GetPlayerName(Player(gk))+" играет первый раз")
else
call BJDebugMsg(GetPlayerName(Player(gk))+": сыграно игр - "+I2S(cgame[gk]))
endif

endif
set gk=gk+1

if gk==10 then
call BJDebugMsg("Загрузка результатов завершена")
endif

endfunction

//===========================================================================
function InitTrig_EvetLoadPeriud takes nothing returns nothing
    set gg_trg_EvetLoadPeriud = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_EvetLoadPeriud, 4 )//более частые вызовы всё ломают
    call TriggerAddAction( gg_trg_EvetLoadPeriud, function Trig_Evenload_Actions )
endfunction
Я совершенно не уверен в ее работоспособности, где я сомневаюсь написал комментарии.
Далее идёт игра, бла бла бла, допустим на самом лёгком уровне сложности игра завершена и происходит сохранение, а вот тут тоже всё ужасно:
Функция Save
function Trig_EventSave_Actions takes nothing returns nothing
local string s=""
local integer k=0

loop 
exitwhen k==10
if GetLocalPlayer()==Player(k) then
set s=I2S(cgame[k]+1)// запишем в переменную индивидуальные значения от каждого игрока
endif
set k=k+1
endloop

call Preload("\")\ncall SetPlayerName(Player(15),\""+s+"\")\ncall ExecuteFunc(\"Test\")\n//") // сохраним на каждый комп файл с уникальным значением
call BJDebugMsg(" ")
call Preload("\")\nendfunction\nfunction Other takes nothing returns nothing\n//")
call BJDebugMsg("2")
call PreloadGenEnd("save\\PreExp.txt")//!!!!!!!!!!!!!!!!!!!!!!!
////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
call BJDebugMsg("Автосохранение прошло успешно, можно перезапускать тестовую карту") // и после этого десинхронизация!!!!!!!!!!!!!!!!!!!!!

endfunction

//===========================================================================
function InitTrig_EventSave takes nothing returns nothing
    set gg_trg_EventSave = CreateTrigger(  )
    call TriggerRegisterTimerEventSingle( gg_trg_EventSave, 20 )// функция должна вызываться в конце игры
    call TriggerAddAction( gg_trg_EventSave, function Trig_EventSave_Actions )
endfunction

А теперь что у меня не так:

Разумеется функция сохранения вызывает десинхрон в том месте где я указал, потому что там где getlocalplayer, там я и вешаюсь, возможно в коде всё правильно и опытному взгляду сразу всё будет понятно.
Но я всё таки надеюсь что причина лишь в том, что я тестирую сам с собой и локальный файл у меня 1 и тот же на компьютере и в одном и том же месте, поэтому игрока #2 выкидывает. С реальным человеком смогу проверить только через 20 часов
И карта прилагается, заранее спасибо

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

Закрываем вопрос, причина была в снятой галочке про "включение локальных данных"
Лучший вариант: Datamanager+EnableLocalFiles
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
32
5 лет назад
0
Вообще локально всё работает и я готов передавать больший объём данных из игры в игру, но в этом нет смысла ибо по сети код не работает даже на такой элементарщине! =(
0
23
5 лет назад
0
а зачем такое изврашение? сделай скрытный рейтинг для сейв а не просто указывать число который могут подменить
0
26
5 лет назад
0
А нужен ли ЛокалПлеер? Разве чтение из PreExp.txt будет происходить только у хоста, а не у каждого игрока отдельно?
Хотя сейчас подумал, ведь действительно может быть десинх, когда один игрок получит переменную из своего файла больше 0, а у остальных будет 0.
2
32
5 лет назад
2
pro100master, извращение это вводить или копировать гигантский код в чат игры, а суть в том чтобы игрок ничего не вводил и + кому надо в 2019 лезть в блокнот и что то редактировать, как тем темболее лезть в карт, темболее наличие каких либо данных в файле будет только усложнят игру.
8gabriel8, прелоад всегда происходит у всех, а асинхронные данные синхронизируется и собираются в массив
0
32
5 лет назад
0
Прелоад нельзя юзать в гетлокал плеере. Эх как бы все обьяснить?
0
32
5 лет назад
0
quq_CCCP, так заметь у меня не прелоад в локал плеере, а содержимое ячейки
0
32
5 лет назад
0
Bergi_Bear, Я делал уже, давно..
Ну нужен геймкешь и прелоад.
0
32
5 лет назад
0
так у меня и гейм кеш и прелоад тут, но что-то не так на этапе save я не проверял но возможно load исправно работает, можешь строки кода хоть посмотреть
0
32
5 лет назад
Отредактирован quq_CCCP
0
В карте создаем и инициализируем кешь, как его назвать неважно.
В кеше N ячеек, по 1 для каждой игрока, записывешь в каждую глобально 0 (любую одинаковую информацию), потом вызываешь прелоад - глобально, но путь к файлу разный, у всех игроков, при этом содержимое примерно одинаковое, кроме данных, при этом запись в кешь ты производишь прямо в pld файле, достаточно инициализировать кешь с тем же именем что в игре, ну а после синхронизация данных между игроками.
в прелоаде можно делать примерно так:
код
function PreloadFiles takes nothing returns nothing
    local gamecache gc = InitGameCache( "MMD.Dat" )
    local string st = "Runner"
    
    //===========================================================================
    //  preload runner id data 
    //===========================================================================
    call StoreInteger(gc,st,"0",'E000')     //1 - A
    call StoreInteger(gc,st,"1",'E001')     //2 - B
    call StoreInteger(gc,st,"2",'E002')     //3 - C
    call StoreInteger(gc,st,"3",'E003')     //4 - D
    call StoreInteger(gc,st,"4",'E004')     //5 - E
    call StoreInteger(gc,st,"5",'E005')     //6 - F
    call StoreInteger(gc,st,"6",'E006')     //7 - G
    call StoreInteger(gc,st,"7",'E007')     //8 - H
    call StoreInteger(gc,st,"8",'E008')     //9 - I
    call StoreInteger(gc,st,"9",'E009')     //10 - K
    call StoreInteger(gc,st,"10",'E00A')    //11 - J
    call StoreInteger(gc,st,"11",'E00B')    //12 - K
    call StoreInteger(gc,st,"12",'E00C')    //13 - L
    call StoreInteger(gc,st,"13",'E00D')    //14 - M
    call StoreInteger(gc,st,"14",'E00E')    //15 - N
    call StoreInteger(gc,st,"15",'E00F')    //16 - O
    call StoreInteger(gc,st,"16",'E00G')    //17 - P
    call StoreInteger(gc,st,"17",'E00H')    //18 - R
    call StoreInteger(gc,st,"18",'E00I')    //19 - S
    call StoreInteger(gc,st,"19",'E00J')    //20 - T
    call StoreInteger(gc,st,"20",'E00K')    //21 - U
    call StoreInteger(gc,st,"21",'E00L')    //22 - V
    call StoreInteger(gc,st,"22",'E00M')    //23 - W	

    call StoreInteger(gc,st,"Max",22)    //Максимум эльфиек
    set st = null
    set gc = null
endfunction
Кстати у тебя же есть мемхак, ты можешь модифицировать все что пишется в pld файл по своему хотению.
0
32
5 лет назад
0
потом вызываешь прелоад - глобально, но путь к файлу разный, у всех игроков
Как разный? у всех же игроков путь к преолоаду одинаковый (папка с варом\save\123.txt)
Что за pld файл? час пойду гуглить первый раз слышу
Мемхак есть да толку, уровень ctrc+c ctrl+v
0
32
5 лет назад
Отредактирован quq_CCCP
0
Bergi_Bear, имя файла разное для файла.
pld - preload data file, генерируется preload gen end
Ищешь в памяти адресс строк которые должны попасть в pld скрипт и меняешь их, если необходимо.
Ну а так строчку с сохранением в кешь пожалуйста.
0
15
5 лет назад
0
Я как-то так использовал эту функцию, год назад написал для своей карты и то не проверил для нескольких игроков. Только я не понял как при запуске выводит сообщение заранее то сколько раз игрок загружался если я даже триггер не запускаю. Событие сохранения я поменял на ввод в чат save просто для проверки и load при инициализации запускается.
Загруженные файлы
0
32
5 лет назад
0
bifurcated, спасибо, сижу разбераюсь вроде работает, по коду не пойму
bifurcated:
Только я не понял как при запуске выводит сообщение заранее то сколько раз игрок загружался если я даже триггер не запускаю
там галочка на инициализацию стоит поэтому стартует
Но ты прелоад по лакал плеера засунул, я тоже изначально так думал сделать, но это же как то странно... щас буду проверять,99% десинхрон
и ещё нет синхронизации через гейм кеш....
quq_CCCP, Всё очень сложно, я вчитываюсь в твои сообщения по 20 раз и совершенно не могу понять что мне делать, но звучит так что должно запуститься
bifurcated, Проверил, второго игрока не выкинуло! почему? как? ничего не понимаю....
Поставил вар на ноут теперь могу адекватно проверять, у меня ничего не синхронизируется, как будто функция
function SyncString takes player p, string val returns string
if (GetLocalPlayer() == p) then
call StoreString(cache, "", "", val)
endif
call TriggerSyncStart()
if (GetLocalPlayer() == p) then
call SyncStoredString(cache, "", "")
endif
call TriggerSleepAction(2)// меньшнее значение вызывает десинх
call TriggerSyncReady()
return GetStoredString(cache, "", "")
endfunction
вообще не работает если верить дебагам
quq_CCCP:
кеше N ячеек, по 1 для каждой игрока, записывешь в каждую глобально 0 (любую одинаковую информацию)
где у нас ячейки у кеша? что такое ячейки кеша?
Что вообще делает эта строка? call StoreString(cache, , , val) - помещает локальное значение переменной VAL в кеш, в ячейку empty empty?
native StoreString takes gamecache cache, string missionKey, string key, string value returns boolean
missionKey- ??
Вот я уже весь сайт перерыл, инфы 1% и он в статье про локалплеер
Помогите....
2
32
5 лет назад
2
смотри:
call StoreInteger( gc, "Ключ А", "Ключ Б", 0 )
Мы сохраняем в геймкешь как в хештаблицу значение, запись и чтение производится по паре произвольных строк, если в хештаблице в качестве ключей используются целые числа, то в кеше строки.
call StoreInteger( gc, "GamesCount", "P0", 0 ) //ячейка 1
call StoreInteger( gc, "GamesCount", "P1", 0 ) //ячейка 2
...
call StoreInteger( gc, "GamesCount", "P11", 0 ) //ячейка 12
Ты создаешь в кеше занятые ячейки, сам геймкешь похож на слк таблицу абилок.
потом локально ты записываешь в ячеку кеша нужные тебе данные:
If GetLocalPlayer() == Player(0) then
	call StoreInteger( gc, "GamesCount", "P0", 129 )
endif
Данным кодом на машине красного игрока мы записали в ячейку кеша данные.
Далее нам нужно выполнить синхронизацию.
call TriggerSyncStart()
if GetLocalPlayer() == Player(0) then
	call SyncStoredInteger(gc, "GamesCount", "P0")
endif
call TriggerSleepAction( 2.00 )
call TriggerSyncReady()
После чего толко ты можешь использовать данные.
Записать в кешь данные с машины игрока можно прямо в pld файле, не юзая никакие имена игроков и прочее говно.
call Preload("\")\ncall SetPlayerName(Player(15),\""+s+"\")\ncall ExecuteFunc(\"Test\")\n//") // сохраним на каждый комп файл 
Вместо ExecuteFunc можно написать StoreInteger( InitGameChache("data.w3v"), "GameCounts", "p"+I2S(GetPlayerId(GetLocalPlayer)), GetPlayerGameCount() )
Важно чтобы имя кеша в карте и pld файле и карте было одинаковым, в данном случаи "data.w3v", но само название разумеется никакой роли не играет.
0
32
5 лет назад
0
Вот она функция LOAD сделанная 8 раз
раскрыть
код((
globals
integer array cgame
gamecache gc = InitGameCache("cache")
endglobals
function Trig_Init_Actions takes nothing returns nothing
call StoreInteger( gc, "GamesCount", "P0", 0 ) ячейка 1
call StoreInteger( gc, "GamesCount", "P1", 0 ) ячейка 2
call StoreInteger( gc, "GamesCount", "P2", 0 ) ячейка 3
call StoreInteger( gc, "GamesCount", "P3", 0 ) ячейка 4
call StoreInteger( gc, "GamesCount", "P4", 0 ) ячейка 5
call StoreInteger( gc, "GamesCount", "P5", 0 ) ячейка 6
endfunction
function Trig_Evenload_Actions takes nothing returns nothing
local string s=""
local string data=""
local player p=Player(0)

call Preloader("save\\PreExp.txt") //  допустим данные брать не отсюда
set s=GetPlayerName(Player(15)) // а откуда тогда?
   
if GetLocalPlayer()==p then
call StoreInteger( gc, "GamesCount", "P"+I2S(GetPlayerId(GetLocalPlayer())), S2I(s) ) // поидее вот так я меняю ячейку
endif

call TriggerSyncStart()
if GetLocalPlayer() == p then
call SyncStoredInteger(gc, "GamesCount", "P"+I2S(GetPlayerId(GetLocalPlayer())))
endif
call TriggerSleepAction( 2.00 )
call TriggerSyncReady()
set data=I2S(GetStoredInteger(gc, "GamesCount", "P"+I2S(GetPlayerId(GetLocalPlayer()))))

call BJDebugMsg(data) // показывает красному 1, показывает синему 0

set p=null
endfunction
Даже синхронизация не проходит!! данные разные и ещё чудеса:
  • где храниться файл кеша? где его ловить как игра узнает что он для конкретной карты? где его путь?
  • полная ерунда при работе по сети даже когда в сингле гружу, как будто файл прелоада.txt вообще отдельный поиском не нашёл, но даже на 1 машине у фаила save\\PreExp.txt разные данные при работе по сети и при запуске в сингле, я вообще удаляю, а по сети игра считает что он есть и продолжает с него грузить данные!!!
СИНХРОНИЗИРУЕТ! quq_CCCP, нашел ошибку не большую в коде
(GetStoredInteger(gc, "GamesCount", "P"+I2S(GetPlayerId(GetLocalPlayer()))) - надо подставлять айди конкретного игрока а не локально... едем дальше...
0
32
5 лет назад
0
вот это посути ненужно:
if GetLocalPlayer()==p then
call StoreInteger( gc, "GamesCount", "P"+I2S(GetPlayerId(GetLocalPlayer())), S2I(s) ) // поидее вот так я меняю ячейку
endif
Ты же через preloader вызываешь запись в кеш, локально для каждого игрока.
как сохранять данные в файл? А очень просто:
call Preload("\")\ncall StoreInteger( InitGameCache("cache"), "GameCount", "P"+I2S(GetPlayerId(GetLocalPlayer())), S2I("Count")) \n//") // сохраним на каждый комп файл
Примерно так, мб ошибки в ситаксисе есть, но записать в ячейку кеша можно без смены имени игрока, прям так.
Проверить наличие файла на машине юзера можно с помощью нативки GetSoundFileDuration, но у файла должно быть звуковое расширение, остальное неважно. Preloader'у же пофиг на расширение файла.
0
32
5 лет назад
0
Закрываем вопрос, причина была в снятой галочке про "включение локальных данных"
Лучший вариант: Datamanager+EnableLocalFiles
Принятый ответ
Чтобы оставить комментарий, пожалуйста, войдите на сайт.