Нужна помощь?
Создайте тему в соответствующем разделе
Не нужно писать всё в чат!Загляните на торговую площадку
Там вы можете купить
всё что касается игровых серверовНе хотите бан?
Пожалуйста, ознакомьтесь с нашими правилами
Не нарушайте порядок!Продаёте или покупаете?
Пользуйтесь услугами гаранта
Мы сделаем вашу сделку безопасной
Таблица лидеров
Популярные публикации
Отображаются публикации с наибольшей репутацией на 03/07/19 в Сообщения
-
2 балла
Выбор точек спавна игроков по UID из файла
PJIIOxa и ещё один отреагировал на BorizzK за сообщение в теме
Перевыкладываю Чуть улучшил 1 вынес переменные с путем и именем файла из функции загрузки в класс, что бы можно было использовать в других функциях этого класса 2 в функции проверки уид на наличие его в массиве и загрузки координат для игрока с этим уид добавил проверку на наличие файла-флага в каталоге если файл есть происходит перезагрузка массива из файла - таким образом можно не перегружая сервер добавлять уид координаты в файл для новых игроков и они будут подгружены при первом их входе //Version 07.03.2019.1634 //Author: Borizz.K aka [G.P.]NOIZZ(MC2) (s-platoon.ru) class Server_SpawnPoints_Class { ref map<string,string> m_playersSpawnPoints = new map<string,string>; string FileName = "playersSpawnPoints.lst"; string m_SettingsPath = "$CurrentDir:\\mpmissions\\dayzOffline.chernarusplus\\_CONF\\"; //Folder with config files - .ini or .lst // Or "$Profiles:\\" string m_autoReloadFlag = "playersSpawnPointsAutoReload"; void Server_SpawnPoints_Class() { Print("::: [Server_SpawnPoints_Class] ::: Init :::"); LoadPlayersSpawnPointsByUid(); } void ~Server_SpawnPoints_Class() { Print("::: [Server_SpawnPoints_Class] ::: UnInit :::"); } void LoadPlayersSpawnPointsByUid() { /* Файл playersSpawnPoints.lst кладем в папку указанную в параметре запуска сервера -profiles= тогда путь будет "$Profiles:\\" или если кладем в файл в mpmissions\dayzOffline.chernarusplus\_CONF путь будет "$CurrentDir:\\mpmissions\\dayzOffline.chernarusplus\\_CONF\\" Путь меняется в переменной m_SettingsPath - "$Profiles:\\" или "$CurrentDir:\\mpmissions\\dayzOffline.chernarusplus\\_CONF\\" Можете указать свой путь, но он должен быть либо в $Profiles: либо в $CurrentDir: Формат файла: Steam UID в привычном виде 17 цифр Координаты Комментарий (через пробелы) Помните любая ошибка может привести к крашу сервера Не желательны пустые строки! Пример: 76562298156537008 1300 0 5600 Дима 76561998116927209 3000 0 3000 Вася из Новороссийска Про массив: ref map<string, string> m_playersSpawnPoints = new map<string, string>; m_playersSpawnPoints тут массив типа map, где каждый элемент массива состоит из 2х ячеек. 1. Индекс - тип string 2. Значение - тип string Пример работы с массивом типа map Запись в массив m_playersSpawnPoints.Insert("76562298156537008", "1300 0 5600"); //записываем первый элемент - индекс dayz, значение 10 m_playersSpawnPoints.Insert("76561998116927209", "3000 0 3000"); //записываем второй элемент - индекс dayzf, значение 17 Чтение из массива: Получаем значение 0го элемента string m = m_playersSpawnPoints.GetElement(0); // = "1300 0 5600" Получаем индекс 0го элемента string name = m_playersSpawnPoints.GetKey(0); / /= "76562298156537008" Получаем значение по индексу (в данном случае нас интерисует именно ЭТО) string n = m_playersSpawnPoints.Get("76561998116927209"); // = "3000 0 3000" //затем n переводим в вектор Usage in CreateCharacter function for change default spawn position: string PlayerUID = identity.GetPlainId(); if (PlayerUID) { if (m_playersSpawnPoints.Contains(PlayerUID) { pos = m_playersSpawnPoints.Get(PlayerUID).ToVector(); } } */ FileHandle file; string file_line; array<string> read_line; int linecount = 0; //Comments check bool skipline = false; bool skipblock = false; //Comments check file = OpenFile(m_SettingsPath + FileName, FileMode.READ); if (file != 0) { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read File: " + m_SettingsPath + FileName + " :::"); while (FGets(file, file_line) >= 0) { linecount++; //Comments check and skip if (file_line.IndexOfFrom(0,"//") == 0 || file_line.IndexOfFrom(0,"#") == 0 || file_line.IndexOfFrom(0," ") == 0 || file_line.Length() <= 0) { skipline = true; } else { skipline = false; } if (file_line.IndexOfFrom(0,"/*") == 0) { skipblock = true; } else if (file_line.IndexOfFrom(0,"*/") == 0) { skipblock = false; skipline = true; } //Comments check if (!skipline && !skipblock) { read_line = new array<string>; file_line.Split(" ",read_line); if (read_line.Count() >= 4) { if (read_line.Get(0).Length() == 17) { if (read_line.Get(1).ToFloat() > 0 && read_line.Get(3).ToFloat() > 0) { if (!m_playersSpawnPoints.Contains(read_line.Get(0))) { m_playersSpawnPoints.Insert(read_line.Get(0), read_line.Get(1) + " " + read_line.Get(2) + " " + read_line.Get(3)); // UID, Position Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " Add UID " + read_line.Get(0) + " spawnpoint: " + read_line.Get(1) + " " + read_line.Get(2) + " " + read_line.Get(3) + " to m_playersSpawnPoints"); } else { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " UID " + read_line.Get(0) + " duplicated, check file!"); } } else { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " Position error: '" + read_line.Get(1) + " " + read_line.Get(2) + " " + read_line.Get(3) + "' :::"); } } else { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " UID error: " + file_line + " :::"); } } else { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " have errors: " + file_line + " :::"); } } } CloseFile(file); if (m_playersSpawnPoints.Count() > 0) { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Players personal spawn points count: " + m_playersSpawnPoints.Count() + " :::"); } else { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Players personal spawn points is not loaded! :::"); } } else { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Error open file: " + m_SettingsPath + FileName + " :::"); } } vector GetPlayerSpawnPoint(PlayerIdentity identity) { vector pos; if ( FileExist(m_SettingsPath + m_autoReloadFlag) ) LoadPlayersSpawnPointsByUid(); if (identity.GetPlainId()) { string p_UID = identity.GetPlainId(); if (m_playersSpawnPoints.Contains(p_UID)) { pos = m_playersSpawnPoints.Get(p_UID).ToVector(); Print ("::: [Server_SpawnPoints_Class] ::: GetPlayerSpawnPoint ::: Selected personal spawn point Pos: " + pos.ToString() + " for player: " + identity.GetName() + " with UID: "+ p_UID); return pos; } } return "0 0 0"; } } -
2 балла
Выбор точек спавна игроков по UID из файла
VIRrusR и ещё один отреагировал на BorizzK за сообщение в теме
Давайте разберем как это все работает по строкам, что бы новичкам было понятно Описал как мог - тк немного не трезв и все такое ))) Многим так станет понятней //Version 06.03.2019.1030 //Author: Borizz.K aka [G.P.]NOIZZ(MC2) (s-platoon.ru) class Server_SpawnPoints_Class //Это класс { //Это открывающая скобка - начало тела класса //Определяем переменную в классе - в данном случае массив типа map каждый элемент которого состоит из двух строк //Первая строка это индекс, вторая значение //Переменная заданная в классе дотсупна всем функциям в классе. //Так же к ней можно обращаться из других классов //Вот так - Server_SpawnPoints_Class.m_playersSpawnPoints ref map<string,string> m_playersSpawnPoints = new map<string,string>; void Server_SpawnPoints_Class() //Это определение функциии-конструктора класса - выполняется всегда при инициализации/определении класса. { Print("::: [Server_SpawnPoints_Class] ::: Init :::"); //Это выполнится при выполнении конструктора //печать в лог LoadPlayersSpawnPointsByUid(); //Это выполнится при выполнении клнструктора } void ~Server_SpawnPoints_Class() //Это определение функциии-деструктора класса - выполняется всегда при деинициализации класса. Например при корректном завершении работы сервера. { Print("::: [Server_SpawnPoints_Class] ::: UnInit :::"); //Это выполнится при выполнении деструктора //печать в лог } void LoadPlayersSpawnPointsByUid() //Это определение функциии { //Это открывающая скобка - начало тела функции //Это определение переменных функции. Получить к ним доступ можно только в пределах функции string FileName = "playersSpawnPoints.lst"; // Переменная типа строка string m_SettingsPath = "$CurrentDir:\\mpmissions\\dayzOffline.chernarusplus\\_CONF\\"; //Folder with config files - .ini or .lst // Or "$Profiles:\\" // Переменная типа строка FileHandle file; // Переменная типа файл, в нее помещается указатель на открытыфй файл string file_line; //Переменная типа строка - в нашем случае сюда будет помещяться строка прочитанная из файла array<string> read_line; //Строковой массив каждый элемент которого - строка - в нашем случае сюда будет помещяться подстроки из прочтенной строки файла int linecount = 0; //Целочисленная переменная типа - может содержать в себе только целые числа. В нашем случае счетчик строк. //Comments check bool skipline = false; //Логическая переменная которая может принимать значение true или false bool skipblock = false; //Логическая переменная которая может принимать значение true или false //Comments check file = OpenFile(m_SettingsPath + FileName, FileMode.READ); //Пытаемся открыть файл с именем из переменной FileName по пути из переменной m_SettingsPath в режиме для чтения if (file != 0) //Условие. Если файл открылся в переменую file попадет числовой указатель на файл, если не открылся то переменная будет содержать 0 { //Это открывающая скобка - начало тела условия - ЕСЛИ файл открыт Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read File: " + m_SettingsPath + FileName + " :::"); //печать в лог //While - это условный цикл. Цикл будет выполняться пока из файла будут читаться строки, как только будет достигнут конец файла значение функции FGets(file, file_line) станет -1 и цикла прервется //Тут условие цикла совмещено с чтением строки из файла - фнкция FGets(file, file_line) читает строку из файла file и помещает ее в переменную file_line если строки кончились возвращает -1 while (FGets(file, file_line) >= 0) { //Это открывающая скобка - начало тела цикла ПОКА linecount++; //Увеличиваем счетчик строк на 1. Можно так же записать как linecount = linecount + 1; но linecount++; короче //Comments check and skip //Тут мы проверям строку на наличие в ней определенных символов или их последовательностей - IndexOfFrom возвращает true или false // file_line.IndexOfFrom(0,"//") == 0 - если file_line содержит в 0 позиции последовательность "//" то IndexOfFrom вернет true // или file_line.IndexOfFrom(0,"#") == 0 если file_line содержит в 0 позиции "#" то IndexOfFrom вернет true // или file_line.IndexOfFrom(0," ") == 0 если file_line содержит в 0 позиции " " // или file_line.Length() <= 0 если длинна строки file_line <= 0 Length() вернет true //Вобщем если хоть одно условие = true (верно) то выполнится код внутри условия if (file_line.IndexOfFrom(0,"//") == 0 || file_line.IndexOfFrom(0,"#") == 0 || file_line.IndexOfFrom(0," ") == 0 || file_line.Length() <= 0) //Если одно из условий верно {//Это открывающая скобка - начало тела условия ЕСЛИ skipline = true; // логическая переменная skipline примет значение true //в последствии если skipline == true то обработка текущей строки выполнена не будет //(в условиях сравнения всегда используется двойной знак =, одинарный используется в присвоении) }//Это закрывающая скобка - начало тела условия ЕСЛИ else //ИЛИ Если одно из условий НЕ верно {//Это открывающая скобка - условие ИЛИ skipline = false; // логическая переменная skipline примет значение false //в последствии если skipline == false то обработка текущей строки будет выполнена }//Это закрывающая скобка - конец тела условия ИЛИ if (file_line.IndexOfFrom(0,"/*") == 0) //file_line.IndexOfFrom(0,"/*") == 0 - если file_line содержит в 0 позиции последовательность "/*" то IndexOfFrom вернет true {//Это открывающая скобка - начало тела условия ЕСЛИ skipblock = true; // логическая переменная skipblock примет значение true //в последствии если skipblock == true то обработка строк не будет выполняться до тех пор пока не встретится */ (см ниже условие else if (file_line.IndexOfFrom(0,"*/") >= 0) }//Это закрывающая скобка - конец тела условия ЕСЛИ else if (file_line.IndexOfFrom(0,"*/") >= 0) //file_line.IndexOfFrom(0,"*/") >= 0 - если file_line содержит в позиции 0 или дальше последовательность "*/" то IndexOfFrom вернет true {//Это открывающая скобка - условие ИЛИ ЕСЛИ skipblock = false; // логическая переменная skipblock примет значение false //в последствии если skipblock == false то обработка строк будет продолжена skipline = true; //логическая переменная skipline примет значение true //в последствии если skipline == true то обработка ntreotq строки не будет выполнена }//Это закрывающая скобка - конец тела условия ИЛИ ЕСЛИ //Comments check if (!skipline && !skipblock) //Если skipline == false и skipblock == false - то обрабатываем строку {//Это открывающая скобка - начало тела условия ЕСЛИ read_line = new array<string>; //(очищаем) массив read_line file_line.Split(" ",read_line); //file_line (в нее была считана строка из файла) делится на подстроки (разделителем является пробел) и каждая подстрока загоняется последовательно в элементы массива read_line //Если скажем file_line содержит в себе "Вася Ваня Петя" то элемент 0 массива read_line будет содержать Вася, элемент 1 Ваня, элемент 2 Петя, а элемент 3 будет пуст. итд итп //Чем больше подстрок через пробел тем больше элементов массива будет заполнено //в нашем случае на интерисуют 4 подстроки и 4 элемента массива //Тк в файле каждая строка состоит из UID и координат вида X Z Y - например - 76561198156937127 2698.36 23.2 5989.59 //То элемент 0 массива read_line будет содержать 76561198156937127, элемент 1 2698.36, элемент 2 23.2, элемент 3 5989.59 //Если в строке будет еще текст через пробелы, то и остальные эелементы будут заполнены, но мы их будем игнорировать //Дальнейшее описание будет отталкиваться именно от этого содержания - 76561198156937127 2698.36 23.2 5989.59 if (read_line.Count() >= 4) //Если кол-во элементов массива read_line больше или равно 4м условие будет выполнено { if (read_line.Get(0).Length() == 17) //если элемент 0 массива read_line имеет длинну 17 символов (Steam UID имеет 17 цифр) то условие будет выполнено - в нашем случае это 76561198156937127 { if (read_line.Get(1).ToFloat() > 0 && read_line.Get(3).ToFloat() > 0) //Если элемент 1 массива read_line (содержит координату X - 2698.36) переведенное в число с плавающей точкой больше 0 И Если элемент 3 массива read_line (содержит координату Y - 5989.59) переведенное в число с плавающей точкой больше 0 (Z мы в условии игнорируем) условие будет выполнено { if (!m_playersSpawnPoints.Contains(read_line.Get(0))) //Если массив m_playersSpawnPoints НЕ содержит UID (те в него еще не записывался элемент 0 массива read_line) //Зачем нам в массиве дублирование UID - условие будет выполнено { m_playersSpawnPoints.Insert(read_line.Get(0), read_line.Get(1) + " " + read_line.Get(2) + " " + read_line.Get(3)); // В элемент массива m_playersSpawnPoints, будет вставлена строка - read_line.Get(0) содержащая UID (перая часть элемента - индекс), следом будет вставлена собранная из трех частей строка содержащая координаты (это значение) Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " Add UID " + read_line.Get(0) + " spawnpoint: " + read_line.Get(1) + " " + read_line.Get(2) + " " + read_line.Get(3) + " to m_playersSpawnPoints"); //вывод в лог } else //Если массив m_playersSpawnPoints одержит UID (те в него УЖЕ записывался элемент 0 массива read_line) //Зачем нам в массиве дублирование UID то просто вывод в лог инфы о дублировании UID в файле { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " UID " + read_line.Get(0) + " duplicated, check file!"); } } else //ИЛИ - ОШИБКА { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " Position error: '" + read_line.Get(1) + " " + read_line.Get(2) + " " + read_line.Get(3) + "' :::"); } } else //ИЛИ read_line.Get(0).Length() != 17 - не равно 17 - А UID всегда = 17 символам - ОШИБКА { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " UID error: " + file_line + " :::"); } } else //read_line.Count() < 4 - ОШИБКА { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " have errors: " + file_line + " :::"); } } }//Это закрывающая скобка - конец тела цикла ПОКА //Строки в файле закончились CloseFile(file); //Закрываем файл if (m_playersSpawnPoints.Count() > 0) //Диагностика - если кол-во элементов массива m_playersSpawnPoints > 0 { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Players personal spawn points count: " + m_playersSpawnPoints.Count() + " :::"); //Выводим в лог инфу о кол-ве } else { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Players personal spawn points is not loaded! :::"); //Выводим в лог инфу что массив не загружен } }//Это открывающая скобка - начало тела условия - ЕСЛИ файл открыт else //Файл не открыт - ошибка (либо файла нет либо еще что-то) { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Error open file: " + m_SettingsPath + FileName + " :::"); } }//Это закрывающая скобка - конец тела функции //Эта функция вызывается нами для получения координат по UID из функции CreateCharacter класса миссии vector GetPlayerSpawnPoint(PlayerIdentity identity) //Функция возвращающая данные типа vector и принимающая в качестве параметров в переменную identity типа PlayerIdentity ссылку на личность подключившегося игрока { vector pos; //определяем переменную типа vector if (identity.GetPlainId()) //Проверка на всякий случай - если ссылка на личность вернет Steam UID то { string p_UID = identity.GetPlainId(); //В строковую переменную p_UID штатная функция GetPlainId() вернет Steam UID if (m_playersSpawnPoints.Contains(p_UID)) //Если в массиве m_playersSpawnPoints есть UID который мы получили выше в переменную p_UID { pos = m_playersSpawnPoints.Get(p_UID).ToVector(); //Получаем из массива m_playersSpawnPoints значение по индексу p_UID и сразу переводим его в vector и загоняем его в переменую pos Print ("::: [Server_SpawnPoints_Class] ::: GetPlayerSpawnPoint ::: Selected personal spawn point Pos: " + pos.ToString() + " for player: " + identity.GetName() + " with UID: "+ p_UID); //пишем в лог результат return pos; //функция возвращает значение содержащееся в переменной pos и завершает работу } } return "0 0 0"; //во всех остальных случаях функция возвращает 0 0 0 по завершению работы } } //Это закрывающая скобка - конец тела класса -
2 балла
Выбор точек спавна игроков по UID из файла
paranoyk и ещё один отреагировал на VIRrusR за сообщение в теме
BorizzK , большое спасибо за проделанную работу, разъяснения и проявленное терпение! Всё работает! Специально для дремучих и безграмотных, типа меня, рассказываю как делать пошагово, ибо в теме много слов, вопросов и т.д.: 1. Вписываем в самое начало файла init.c строки: #include "$CurrentDir:\\mpmissions\\dayzOffline.chernarusplus\\_MOD\\SpawnPoints\\SpawnPointsClass.c" //Server_SpawnPoints_Class ref Server_SpawnPoints_Class Server_SpawnPoints = new Server_SpawnPoints_Class(); Если там у Вас уже есть какие-то подключения через #include, то прямо под ними, следующей строкой. Далее, после строки "override PlayerBase CreateCharacter(PlayerIdentity identity, vector pos, ParamsReadContext ctx, string characterName)" , вместо того, что там есть вписываем вот это: { //Координаты по UID vector p_SpawnPoint = Server_SpawnPoints.GetPlayerSpawnPoint(identity); //See Server_SpawnPoints_Class if (p_SpawnPoint) { pos = p_SpawnPoint; Print ("::: init.c ::: PlayerBase CreateCharacter ::: Selected personal spawn point: Pos: " + pos.ToString() + " for player: " + identity.GetName() + " with UID: " + identity.GetPlainId()); } //Координаты по UID Entity playerEnt; playerEnt = GetGame().CreatePlayer(identity, characterName, pos, 0, "NONE");//Creates random player Class.CastTo(m_player, playerEnt); GetGame().SelectPlayer(identity, m_player); return m_player; } Для "ванильного" init.c должно получится так: #include "$CurrentDir:\\mpmissions\\dayzOffline.chernarusplus\\_MOD\\SpawnPoints\\SpawnPointsClass.c" //Server_SpawnPoints_Class ref Server_SpawnPoints_Class Server_SpawnPoints = new Server_SpawnPoints_Class(); void main() { //INIT WEATHER BEFORE ECONOMY INIT------------------------ Weather weather = g_Game.GetWeather(); weather.MissionWeather(false); // false = use weather controller from Weather.c weather.GetOvercast().Set( Math.RandomFloatInclusive(0.4, 0.6), 1, 0); weather.GetRain().Set( 0, 0, 1); weather.GetFog().Set( Math.RandomFloatInclusive(0.05, 0.1), 1, 0); //INIT ECONOMY-------------------------------------- Hive ce = CreateHive(); if ( ce ) ce.InitOffline(); //DATE RESET AFTER ECONOMY INIT------------------------- int year, month, day, hour, minute; int reset_month = 9, reset_day = 20; GetGame().GetWorld().GetDate(year, month, day, hour, minute); if ((month == reset_month) && (day < reset_day)) { GetGame().GetWorld().SetDate(year, reset_month, reset_day, hour, minute); } else { if ((month == reset_month + 1) && (day > reset_day)) { GetGame().GetWorld().SetDate(year, reset_month, reset_day, hour, minute); } else { if ((month < reset_month) || (month > reset_month + 1)) { GetGame().GetWorld().SetDate(year, reset_month, reset_day, hour, minute); } } } } class CustomMission: MissionServer { void SetRandomHealth(EntityAI itemEnt) { if ( itemEnt ) { int rndHlt = Math.RandomInt(55,100); itemEnt.SetHealth("","",rndHlt); } } override PlayerBase CreateCharacter(PlayerIdentity identity, vector pos, ParamsReadContext ctx, string characterName) { //Координаты по UID vector p_SpawnPoint = Server_SpawnPoints.GetPlayerSpawnPoint(identity); //See Server_SpawnPoints_Class if (p_SpawnPoint) { pos = p_SpawnPoint; Print ("::: init.c ::: PlayerBase CreateCharacter ::: Selected personal spawn point: Pos: " + pos.ToString() + " for player: " + identity.GetName() + " with UID: " + identity.GetPlainId()); } //Координаты по UID Entity playerEnt; playerEnt = GetGame().CreatePlayer(identity, characterName, pos, 0, "NONE");//Creates random player Class.CastTo(m_player, playerEnt); GetGame().SelectPlayer(identity, m_player); return m_player; } override void StartingEquipSetup(PlayerBase player, bool clothesChosen) { EntityAI itemTop; EntityAI itemEnt; ItemBase itemBs; float rand; itemTop = player.FindAttachmentBySlotName("Body"); if ( itemTop ) { itemEnt = itemTop.GetInventory().CreateInInventory("Rag"); if ( Class.CastTo(itemBs, itemEnt ) ) itemBs.SetQuantity(4); SetRandomHealth(itemEnt); itemEnt = itemTop.GetInventory().CreateInInventory("RoadFlare"); SetRandomHealth(itemEnt); rand = Math.RandomFloatInclusive(0.0, 1.0); if ( rand < 0.35 ) itemEnt = player.GetInventory().CreateInInventory("Apple"); else if ( rand > 0.65 ) itemEnt = player.GetInventory().CreateInInventory("Pear"); else itemEnt = player.GetInventory().CreateInInventory("Plum"); SetRandomHealth(itemEnt); } } }; Mission CreateCustomMission(string path) { return new CustomMission(); } 2. Создаём по пути "/serverfiles/mpmissions/dayzOffline.chernarusplus" на Вашем сервере папку \_MOD\ 3. В папке \_MOD\ создаём ещё одну папку \SpawnPoints\ 4. В папку \SpawnPoints\ помещаем файл "SpawnPointsClass.c" следующего содержания: //Version 06.03.2019.2035 //Author: Borizz.K aka [G.P.]NOIZZ(MC2) (s-platoon.ru) class Server_SpawnPoints_Class { ref map<string,string> m_playersSpawnPoints = new map<string,string>; //Конструктор - выполняется всегда при инициализации класса void Server_SpawnPoints_Class() { Print("::: [Server_SpawnPoints_Class] ::: Init :::"); LoadPlayersSpawnPointsByUid(); } //Деструктор - выполняется всегда при деинициализации класса (например при корректной остановке сервера) void ~Server_SpawnPoints_Class() { Print("::: [Server_SpawnPoints_Class] ::: UnInit :::"); } void LoadPlayersSpawnPointsByUid() { /* Файл playersSpawnPoints.lst кладем в папку указанную в параметре запуска сервера -profiles= тогда путь будет "$Profiles:\\" или если кладем в файл в mpmissions\dayzOffline.chernarusplus\_CONF путь будет "$CurrentDir:\\mpmissions\\dayzOffline.chernarusplus\\_CONF\\" Путь меняется в переменной m_SettingsPath - "$Profiles:\\" или "$CurrentDir:\\mpmissions\\dayzOffline.chernarusplus\\_CONF\\" Можете указать свой путь, но он должен быть либо в $Profiles: либо в $CurrentDir: Формат файла: Steam UID в привычном виде 17 цифр Координаты Комментарий (через пробелы) Помните любая ошибка может привести к крашу сервера Не желательны пустые строки! Пример: 76562298156537008 1300 0 5600 Дима 76561998116927209 3000 0 3000 Вася из Новороссийска Про массив: ref map<string, string> m_playersSpawnPoints = new map<string, string>; m_playersSpawnPoints тут массив типа map, где каждый элемент массива состоит из 2х ячеек. 1. Индекс - тип string 2. Значение - тип string Пример работы с массивом типа map Запись в массив m_playersSpawnPoints.Insert("76562298156537008", "1300 0 5600"); //записываем первый элемент - индекс dayz, значение 10 m_playersSpawnPoints.Insert("76561998116927209", "3000 0 3000"); //записываем второй элемент - индекс dayzf, значение 17 Чтение из массива: Получаем значение 0го элемента string m = m_playersSpawnPoints.GetElement(0); // = "1300 0 5600" Получаем индекс 0го элемента string name = m_playersSpawnPoints.GetKey(0); / /= "76562298156537008" Получаем значение по индексу (в данном случае нас интерисует именно ЭТО) string n = m_playersSpawnPoints.Get("76561998116927209"); // = "3000 0 3000" //затем n переводим в вектор Usage in CreateCharacter function for change default spawn position: string PlayerUID = identity.GetPlainId(); if (PlayerUID) { if (m_playersSpawnPoints.Contains(PlayerUID) { pos = m_playersSpawnPoints.Get(PlayerUID).ToVector(); } } */ string FileName = "playersSpawnPoints.lst"; string m_SettingsPath = "$CurrentDir:\\mpmissions\\dayzOffline.chernarusplus\\_CONF\\"; //Folder with config files - .ini or .lst // Or "$Profiles:\\" FileHandle file; string file_line; array<string> read_line; int linecount = 0; //Comments check bool skipline = false; bool skipblock = false; //Comments check file = OpenFile(m_SettingsPath + FileName, FileMode.READ); if (file != 0) { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read File: " + m_SettingsPath + FileName + " :::"); while (FGets(file, file_line) >= 0) { linecount++; //Comments check and skip if (file_line.IndexOfFrom(0,"//") == 0 || file_line.IndexOfFrom(0,"#") == 0 || file_line.IndexOfFrom(0," ") == 0 || file_line.Length() <= 0) { skipline = true; } else { skipline = false; } if (file_line.IndexOfFrom(0,"/*") == 0) { skipblock = true; } else if (file_line.IndexOfFrom(0,"*/") == 0) { skipblock = false; skipline = true; } //Comments check if (!skipline && !skipblock) { read_line = new array<string>; file_line.Split(" ",read_line); if (read_line.Count() >= 4) { if (read_line.Get(0).Length() == 17) { if (read_line.Get(1).ToFloat() > 0 && read_line.Get(3).ToFloat() > 0) { if (!m_playersSpawnPoints.Contains(read_line.Get(0))) { m_playersSpawnPoints.Insert(read_line.Get(0), read_line.Get(1) + " " + read_line.Get(2) + " " + read_line.Get(3)); // UID, Position Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " Add UID " + read_line.Get(0) + " spawnpoint: " + read_line.Get(1) + " " + read_line.Get(2) + " " + read_line.Get(3) + " to m_playersSpawnPoints"); } else { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " UID " + read_line.Get(0) + " duplicated, check file!"); } } else { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " Position error: '" + read_line.Get(1) + " " + read_line.Get(2) + " " + read_line.Get(3) + "' :::"); } } else { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " UID error: " + file_line + " :::"); } } else { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Read Line c" + linecount + " have errors: " + file_line + " :::"); } } } CloseFile(file); if (m_playersSpawnPoints.Count() > 0) { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Players personal spawn points count: " + m_playersSpawnPoints.Count() + " :::"); } else { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Players personal spawn points is not loaded! :::"); } } else { Print("::: [Server_SpawnPoints_Class] ::: LoadPlayersSpawnPoints() ::: Error open file: " + m_SettingsPath + FileName + " :::"); } } vector GetPlayerSpawnPoint(PlayerIdentity identity) { vector pos; if (identity.GetPlainId()) { string p_UID = identity.GetPlainId(); if (m_playersSpawnPoints.Contains(p_UID)) { pos = m_playersSpawnPoints.Get(p_UID).ToVector(); Print ("::: [Server_SpawnPoints_Class] ::: GetPlayerSpawnPoint ::: Selected personal spawn point Pos: " + pos.ToString() + " for player: " + identity.GetName() + " with UID: "+ p_UID); return pos; } } return "0 0 0"; } } 5. Создаём по пути "/serverfiles/mpmissions/dayzOffline.chernarusplus" на Вашем сервере папку \_CONF\ 6. В папку \_CONF\ помещаем файл "playersSpawnPoints.lst" следующего содержания: 6561198156923007 2698.36 0 5989.59 ПЕТЯ //Тут комментарий Где: 6561198156923007 - Steam ID игрока 2698.36 0 5989.59 - координаты точки возрождения в формате X, Z, Y (долгота, высота , широта), если высота равна нулю, то заспавнит на поверхность земли или ближайшую твёрдую поверхность. ПЕТЯ - имя игрока для Вас (ни на что не влияет), после "//" можете вписать любое пояснение (// противный тип из клана чумазеков) Последующего игрока вписываем аналогично, в следующей строке. Запускаем сервер, убиваем персонажа, наслаждаемся респавном по заданным координатам. -
1 баллPJIIOxa Рекомендую в вызовах CallLater вместо CALL_CATEGORY_GAMEPLAY и спользовать CALL_CATEGORY_SYSTEM Ибо если сервер сильно нагружен, контекст GAMEPLAY на стороне сервера имеет приоритет ниже чем SYSTEM (у него вообще нет ограничений) и вызовы могут стоять в очереди и ожидать завершения вызовов с более высоким приоритетом
-
1 баллbergaut Только с модом клиента.Для сервера делатье немного долго и нудно (прописать всего лишь обьекту "ноу диструкт"). Без клиентского на карте в он лайне будет "невидимая" модель.
-
1 баллПеределать мой скрипт координат по UID под характер по UID сами не хотите попробовать? Давайте в той теме я разберу как работает функция (заодно потренькаю свои навыки обьяснения) и тогда быть может Вам станет понятней и Вы сможете что-то сделать сами?
-
1 баллVIRrusRБлин... Ну народ Ну все просто же В фунцию createcharacter в переменную charactername попадает желательный класснейма перса Что мешаетт его менять по uid как и координаты спавна? Кстати, а зачем проверять входил перс на сервер или нет? Createcharacter выполняется первый раз при входе и создании перса и в последствии перс не создается заново, а грузится из базы игроков сервера, вот когда умрете, перс при след входе создастся заново, те аыполнится createcharacter
-
1 баллСкрипт из мода вынуть и вуаля Ну или завтра я покажу как переделать мой скрипт спавна по уид в лут по уид
-
1 баллзначит, немного по другому все, нежели я запомнил. это был порт карты версии 0,61 на арму. ниже, 2 файла, original-config.cpp - он же исходник и edited-config.cpp - он же измененный, в котором есть светлые ночи. смотрите класс DayLightingBrightAlmost и DayLightingRainy, если мне не изменяет память, то именно там я и указывал параметры освещения ночью. эти конфиги располагались в worlds_chernarusplus.pbo, в нынешней версии часть конфига перекочевала в DZ.pbo, но не суть. в нынешней версии можно поколдовать с конфигом именно worlds_chernarusplus.pbo. original-config.cpp edited-config.cpp
-
1 баллПочему я написал, что перемотка времени - дичь, все просто. Момент перемотки времени, приводит к фризам, на некоторых серверах этот момент может длится до 30 секунд + что я замечал, что при перемотке резко изменяются значения погоды, что тоже приводит к фризам, поскольку для каждого времени суток используются разные значения погоды. сейчас поищу файл, о котором говорил + поищу измененный файл от старой версии, со светлыми ночами.
-
1 баллИзменил CALL_CATEGORY_GAMEPLAY на CALL_CATEGORY_SYSTEM Вроде работает, но надо часов 12 подождать
-
1 баллПродолжение Раздел 2. Использование. Поскольку использовать выдачу спавн-точек по UIВ логично при первом подключении игрока к серверу, использовать содержимое массива для выдачи координат спавна по UID мы будеем в штатной функции сервера/миссии CreateCharacter находим эту функцию в теле класса миссии ее определение выглядит вот так override PlayerBase CreateCharacter(PlayerIdentity identity, vector pos, ParamsReadContext ctx, string characterName) { //тут код и добаляем в самом начале код вот так override PlayerBase CreateCharacter(PlayerIdentity identity, vector pos, ParamsReadContext ctx, string characterName) { if (identity.GetPlainId()) { string p_UID = identity.GetPlainId(); if (m_playersSpawnPoints.Contains(p_UID)) { vector p_SpawnPoint = m_playersSpawnPoints.Get(p_UID).ToVector(); Print ("::: init.c ::: PlayerBase CreateCharacter ::: Selected personal spawn point Pos: " + pos.ToString() + " for player: " + identity.GetName() + " with UID: "+ p_UID); } } if (p_SpawnPoint) pos = p_SpawnPoint; //тут остальной нативный (штатный) код } Что имеем if (identity.GetPlainId()) - проверка на наличие "идентичности" или "личности" подключившегося игрока лучше проверить, а то вдруг дисконнект в виде разрыва соединения и тп глюков потом будут ошибки в логе - не красиво string p_UID = identity.GetPlainId(); - получаям Steam UID в привычном виде 17 цифирь if (m_playersSpawnPoints.Contains(p_UID)) - если наш массив m_playersSpawnPoints содержит в индексах UID игрока то { vector pos = m_playersSpawnPoints.Get(p_UID).ToVector(); - перезаписываем содержимое переменной pos (содержащей выданные сервером координаты нового игрока) координатами полученными из массива по UID. } Вот собственно и все Ну а далее в этой штатной функции идет штатное создание персонажа Отступлю с собьяснением Entity playerEnt; // определяем переменную в которую попадет персонаж ( "сущность" ) - на самом деле тип Entity то же самое что и EntityAI playerEnt = GetGame().CreatePlayer(identity, characterName, pos, 0, "NONE"); - создание персонажа - вот тут как раз и указываются координаты создания перса Class.CastTo(m_player, playerEnt); - кастим сущность из класса EntityAI в переменную m_player класса PlayerBase что бы иметь ссылку на обьект соответствующего класса - странно, но определять тип переменной m_player в данном случае не обязательно GetGame().SelectPlayer(identity, m_player); - связываем "идентичность/личность" подключившегося игрока с персонажем из переменной m_player return m_player; - функция возвращает вызвавшему ее ДВИЖКУ ссылку на обьект которым управляет игрок Добавлю можно создавать файлы с любыми конфигами на основе этого кода читать их в массивы достаточно просто немного переделать код Есть вопросы? Задавайте Спасибо за внимание...
-
Рассылка
