Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
  • Need help?

    Create a topic in the appropriate section
    Don't write everything in the chat!
  • Take a look at the marketplace

    There you can buy
    everything related to game servers
  • Don't want a ban?

    Please read our rules
    Don't disturb the order!
  • Sell or buy?

    Use services of the guarantor
    We will make your deal safe
123new

[Enscript] Учимся основам скриптинга

Recommended Posts

И снова здравствуйте, товарищи и коллеги!

 

Уже не один день наблюдаю среди многих из читающих такую проблему, как непонимание того, что написано в том или ином гайде, скрипте, теме форума по DayZ Standalone. А понимать бы это все это ой как бы не плохо было бы, да, товарищи? Ну хотя бы так, для себя, для осознания происходящего и упрощения своей жизни. Не все же за вас делать постоянно, как считаете?
Что же, решил я вот для вас завести такую темку, полезную. В ней мы не будем рассматривать установку чего-либо или сборку мода. Мы попробуем разобраться в основах языка игры, а именно - написании своего кода, чтении кода игры, данного разработчиком, или чужим модом в мастерской.
Разумеется, надеюсь я и на вашу бескорыстную помощь и поддержку, а также на помощь знатоков и экспертов скриптинга игры, ведь один я не справлюсь в написании этой безмерно полезной для многих и большой темы. А помощь ой как понадобится, чувствую затылком.

Ну ладно, утомил я вас, начнем, пожалуй, согласны?


Оговорюсь сразу, в данной теме мы затронем лишь скриптовую составляющую игры. Т.е. вопросы изменения модов, игры, создания собственных интерфейсов, игровых вещей и прочего освещаться не будут.

 

Темы к ознакомлению, схожие с данным материалом:

https://s-platoon.ru/topic/8622-enscript-delaem-skript-dlya-moda-i-osnovnye-principy-skriptinga-modov/

https://s-platoon.ru/topic/7838-sozdaem-svoy-servernyy-mod-dayz-14-to-discontined

https://s-platoon.ru/topic/8859-enscript-rodnye-funkcii-v-kode-igry-opisanie-nahozhdenie/

Официальная документация, связанная с данным материалом (спасибо BorizzK😞

https://community.bistudio.com/wiki/DayZ:Enforce_Script_Syntax

https://community.bistudio.com/wiki/Category:DayZ:Editing

 

Начнем мы, пожалуй, с общего.

Введение. Скрипты.

Скрипты - важная часть функционирования игры, создания модов и модификации как игры, так и сервера. Они позволяют делать чудные модификации, создавать новые опции,  настраивать или изменять в игре по своей задумке практически любой аспект и функционал, заданный разработчиками, дополнять его и разнообразить.


Алгоритм

Ваша первая задача при написании скриптов - определить, какие шаги надо предпринять, чтобы решить какую-либо проблему. Последовательность таких шагов - это и будет алгоритм.
Например,  намерение - передать другу ваш рюкзак. Значит необходимо выполнить следующие действия:

Цитата

 

Шаг 1 - определить вас и друга, как игрока на сервере
Шаг 2 - проверить, имеется ли искомая вещь у вас и в каком она состоянии
Шаг 3 - Скинуть вашу вещь для передачи другу, либо поместить ее в некоторое хранилище на небольшое время

Шаг 4 - Выдать вашу вещь другу, например, подобрав ее, или переместив ее из хранилища

 

Но тут у нас встает вопрос - игрок же вызывает какое-то меню или опцию, которая будет выполнять данные действия. Как это реализовать? Ведь игра - это лишь набор комманд, которые выполняются по одной за раз, как правильно объединить все и сделать корректно?
Сделать это все можно именно посредством скриптинга в данной игре с использованием скриптов.

Интерпретатор

Когда вы составили алгоритм, вам нужно что-то, что может его исполнить. У нас есть компьютерная игра, которая может это сделать. В игре есть игроки, объекты которые могут выполнять те или иные действия, например, получение данных, создание объектов, открытие дверей и т.п. Все имеет свою комманду и результат выполнения. Иными словами, игра сама интерпретирует ваши скрипты и их код в рабочий вид в игре.

Исходный код (Скрипт)

Исходный код (скрипт) - это алгоритм, написанный на каком-либо языке программирования, который преобразуется в машинный код программы и будет выполнен в том или ином случае. В случае в нашей игрой это код, который игра преобразует в понятные для нее комманды и выполняет их.
Скриптинг
Скриптинг - какие-либо действия по написанию скриптов для своих работ\модов\игры. Скриптинг в DayZ в основном основывается на том, что уже имеется в игре. Т.е. на базовом функционале игры, который задан разработчиком. В DayZ вся скриптовая часть, написанная авторами игры, располагается в файлике "scripts.pbo" в папке "dta", который мы можем распаковать через "PBO Manager", например, и поглядеть.
Любые скрипты могут содержать как набор из функций, так и набор из разных классов с функциями, которые могут вам понадобиться.
Enforce Script

Enforce Script (EnScript по простому)- это язык сценариев (интерпретации скриптинга), разработанный для движка игры DayZ "enforce Engine" компанией Bohemia Interactive Studio .

Все скрипты EnScript, основные игровые логики находятся в "scripts.pbo" в папке "dta" каталога "DayZ" или "DayZ Server".  Именно этот файл и будет нам полезен для выяснения того, как работают некоторые вещи (пока, наконец, не появится достойная ссылка на API от разработчиков игра, будь они прокляты).

Основные принципы скриптинга на EnScript:

  • Любая комманда, строка в функции должна завершаться на ; (точку с запятой)
  • Тело любой функции/класса/структуры должно быть заключено в {} (фигурные скобки)
  • Язык крайне чувствителен к регистру, т.е. MyPeremennaya и Myperemennaya будут 2 разными объектами для игры.
  • Язык, крайне схожий с синтаксисом и коммандами C++, C# и JavaScript, для тех, кто знает эти языки хотя бы на любительском уровне, работать и писать свои скрипты будет проще в разы

Структура скриптовой части игры
Распаковав "scripts.pbo"  (файл есть в клиенте игры и сервере, он одинаковый) мы увидим несколько папок, таких как "1_Core", "2_GameLib", "3_Game", "4_World", "5_Mission", "data", "editor" а также файлики "$PREFIX$", "$PRODUCT$","$VERSION$","config.bin","profile_fixed.cfg", "staticDefinesDoc.c". Из того, что мне известно, и что нам пригодится при написании скриптов, я отмечу лишь файлик "config.bin", который составляет основную конфигурацию pbo-файла и включенных в него файлов скриптов (по нему 'компилируются' при запуске игры в скрипты в определенные разделы кода запуска игры). А также папки "1_Core", "2_GameLib", "3_Game", "4_World", "5_Mission".
Сам "config.bin" разбирать мы не будем, это сделано уже ранее в теме вот этой.
Каждая из указанных ранее папок обозначает раздел инициализации кода игры. Например, в "1_Core", "2_GameLib" подгружается основной синтаксис всех функций и переменных игры (то как они будут объявляться в коде, вызываться, какие значения возвращать и принимать). В "3_Game" основной функционал самой игры, обозначающий используемые классы и базовые функции этих классов. В "4_World" все остальные классы, функции и параметры, которые будут исполняться в игре в зависимости от того, какие объекты окружения будут в ней будут и как будут функционировать. В "5_Mission" будет описываться функционал, относящийся к экранам загрузки, меню, их действиям и вызовам.
На основе этих разделов и строится основной принцип скриптинга любого мода и функционирования игры в целом. Если вы откроете любой из модов, который имеет хотя бы 1 скрипт, увидите часть этой структуры.
Основные разделы скриптов также взаимодействуют друг с другом, но только в порядке, в котором они выполняются и описываются. Например, из "5_Mission" вы можете вызывать классы и функции, описанные в "4_World", а из "4_World" вызвать функции в "5_Mission" не получится, поскольку игра их еще не знает на том этапе запуска и 'компиляции кода скрипта'.
Функции
Функции - это набор команд (действий) и параметров(переменных). Для ее вызова используется стандартный формат вида: {имя функции}({параметры функции});

Тело любой функции/класса/структуры должно быть заключено в "{}" (фигурные скобки)
Функции могут быть как заданные разработчиками игры в каких-либо классах, так и написанные вами вручную собственные.
Иногда для ее вызова хватает лишь одной лишь команды, например "MyFunction();". Но чаще в синтаксисе вызова функции присутствует один и более параметров, например "MyFunction("my text");" .
Параметры функции могут не содержать значений, а могут иметь 1 или несколько значений, разделенных запятой, например:

void MyFunction(int MyChislo, string text1, text2, bool value);

У каждой команды может быть свой список данных, которые она может использовать в своем выполнении(например, как было в последнем примере), а также может быть и список данных, которые она вернет. Будут ли эти данные требоваться от функции зависит от автора, который эту функцию пишет (т.е. от разработчиков игры, если это скрипт родной игры, или от вас, если этот скрипт вы пишете сами) Функции с возвращаемыми данными (имеют тип значения, который они возвращают) могут вызываться как вот так:

int chislo = MyFunction("my text"); 

т.е. переменная chislo пример значение, которое функция возвратила
либо так:

MyFunction("my text"); 

  т.е. функция вернет значение, но оно не будет записано, и не будет использоваться далее.
Функции без возврата значений (имеют тип void) могут вызываться только вот так:

MyFunction("my text");

Функции могут иметь несколько типов. Например,

void MyFunction()
{

}

функция без возврата значения. А функция

int  MyFunction()

возвратит значение типа int (число). Соответственно, функции без возврата значений будут содержать лишь код своих вычислений, а функции с возвратом обязаны иметь комменду return {значение} .
Пример функции без возврата значений и принимаемых переменных:

void MyFunction() 
{
	Print(" ---TEST--- ");
}

Функция запишет в script.log текст: " ---TEST--- "
Пример вызова в коде: MyFunction();
Пример функции с возвратом значений и принимаемыми переменными:

string MyFunction(string MyText) 
{
	Print(" ---TEST--- " + MyText);
	return "[" + MyText + "]";
}

Пример вызова в коде:  string MyTXT1 = MyFunction("TEXT FOR TEST");
Функция запишет в script.log текст: " ---TEST--- TEXT FOR TEST " и запишет в переменную MyTXT1 значение [MyText]
Параметров, которые могут передаваться в функцию, может быть несколько, но не рекоммендую их делать более 10.
Переменные и их типы
Переменные - это типы данных, используемые в коде скриптов игры. Типы переменных обозначаются классами, заданными в игре. Это могут быть как заданные разработчиками поумолчанию типы данных, так и собственные классы, написанные вами. Обозначаются переменные общим видом так: {тип переменной} {название переменной}

Строка с обозначением любой переменной или заданием ее значением должно быть закончено точной с запятой на конце!
Например: int chislo, string text, bool value; или string text = "TEST";
Каждый тип означает, какие типы данных может принимать данная переменная, и какой объем в памяти игры она займет. Базовое количество типов схоже с c++ и c#, но есть и типы, обозначаемые заданными классами в игре.
Стоит понимать, что объявленная 1 раз переменная в функции или классе не может быть объявлена в ней же еще раз, но ей может быть присвоено новое значение, например :

void MyFunction()
{
	string myperemennaya="text1"; 
	// тут какие-то вычисления
	myperemennaya="text2";
}

Список используемых типов переменных в игре можно прочитать тут (на немецком):
https://germandayz.de/forum/thread/19551-guide-dayz-standalone-scripting-enforce-scripting/
 Остальные имеют стандартный тип, используемый в том же с++ и c#

Модификаторы функций и переменных.
Также, переменные могут иметь модификаторы доступности данных в функциях. Например:

public: делает переменную открытой к доступу в других функциях

private: делает переменную  закрытой к доступу в других функциях

protected: ограничивает доступ к переменной только для дружественных и дочерних классов.
static - переменная, которая сохраняется в памяти игры даже после удаления экземпляра функции (класса) или переменной из памяти (как в C++).

native - Функция или переменная, реализованная игровым движком, не может быть перезаписана. В исходном коде движка такие функции отмечены со смещением. Невозможно изменить модами и сприптами, только использовать их сами.

ref - ссылка на свой тип класса или переменной, ref - сокр. referal, т.е. ссылка в переводе
Модификаторы также описаны по ссылке выше, и могут быть использованы не только в переменных, но и в функциях игры!

Классы
Классы - это структуры, которые могут содержать определенные функции и переменные, заданные автором скрипта. У классов может быть много функций, переменных, а каждый класс в свою очередь может быть задан и записан в отдельные переменные по нескольку раз. Т.е. это своего рода свой тип переменной, которая может содержать свои данные внутри себя.
Отдельная переменная своего класса или одного из классов игры (например Playerbase) воспринимается как единичный некий экземпляр-объект данного класса, и чем больше таких переменных, тем больше экземпляров одного и того же класса существует в памяти игры. Например: PlayerBase player = NULL;

Также, в классах можно обращаться к переменным и функциям, находящимся внутри классов через символ точки (это как вызов и получение результата функции или переменной). Т.е. для экземпляра класса:

class MyClass
{
	string MyText = "";
	int Chislo = 0;
	void MyFunction()
	{
		Prnt("TEST");
	}
}
ref MyClass Peremennaya = new ref MyClass();

создается переменная, и ее можно вызывать так: string MyResult = Peremennaya.MyText; и значение My Text будет записано в MyResult.
Также можно и вызвать функцию или результат ее выполнения (если функция возвращает значение): Peremennaya.MyFunction() выполнит запись в script.log текста TEST.
Переменные, объявляемые вне функций в классе одном будут доступны во всех функциях этого класса. Но переменные, заданные в классе, будут индивидуальны для каждого экземпляра этого класса. Т.е. если мы создаем свой класс, например, такого содержания:

class MyClass
{
	string MyText = "";
	int Chislo = 0;
}

затем создаем экземпляры этого класса в памяти игры, коммандами

ref MyClass Peremennaya = new ref MyClass();
ref MyClass Peremennaya2 = new ref MyClass();

то у Peremennaya и у Peremennaya2 будут свои данные в MyText и Choislo, не связанные между собой:

Peremennaya.Text = "MyText1";
Peremennaya.Chislo = 2;
Print("Peremennaya.Text = " + Peremennaya2.Text + " Peremennaya.Chislo = " + Peremennaya.Chislo.ToString());
Print("Peremennaya2.Text = " + Peremennaya2.Text + " Peremennaya2.Chislo = " + Peremennaya2.Chislo.ToString());

То мы получим в scriptlog:

"Peremennaya.Text = Peremennaya.Text = MyText1 Peremennaya.Chislo = 2"
"Peremennaya2.Text = Peremennaya2.Text = Peremennaya2.Chislo = 0"

Т.е. в Peremennaya2.Text  будет пусто.
Обязательно для созданных собственных классов переменных указание ссылочности типов - ref (ref - сокр. referal, т.е. ссылка в переводе) - от этого зависит доступность данных в классах и функциях.

Также, из классов можно вызывать и функции, и обращаться к переменным. Разумеется, если они не защищены функцией или модификатором. Например, создадим класс:

Class ClassTest
{
	string MyText1 = "123";
	private string MyText2 = "456";
	void MyFunction1 (string text)
	{
		string MyText3 = "789";
		Print("!!!Used MyFunction:" + text);
	}
	int MyFunction2 ()
	{
		return 2;
	}
}

и создадим экземпляр данного класса, и попробуем к нему обратиться:

ref ClassTest Peremennaya3 = new ref ClassTest();

Print("Text1 = " + Peremennaya3.Text1); // В script.log будет Text1 = 123
Print("Text2 = " + Peremennaya3.Text2); // не запустится игра, так как модификатор private не позволит обратиться к переменной внутри класса
Print("Text3 = " + Peremennaya3.MyFunction1 ("TEXT")); // В script.log будет Text3 = !!!Used MyFunction:TEXT
Peremennaya3.MyFunction2(); // Выолнит функцию MyFunction2 и возвратит значение 2, но оно не будет записано

А вот MyText3 из MyFunction1 не получить, так как она содержится внутри функции в классе.

Моддинг Классов

Классы, в свою очередь, можно менять модами, если они не являются 'нативными', либо не защищены движком игры разработчиков от изменений. Для этого применяют приписку "Modded" перед именем класса с сохранением его имени, например:

Modded class PlayerBase
{

}

Моддинг Функций в классах

Функции в классах также можно перезаписывать. Для этого используется модификатор "override" перед тем, как задать эту функцию, а в теле самой этой функции можно (и крайне рекоммендуется, но не обязательно) использовать вызов "super." с дальнейшим вызовом этой функции и передачей оригинальных параметров функции. Например:

Modded class PlayerBase
{
	override void OnConnect()
	{
		Print("Test1"); // Эта строка выполнится до вызова оригинальной функции		
		super.OnConnect(); // вызов оригинальной функции с сохранением ее параметров
		Print("Test2"); // Эта строка выполнится после вызова оригинальной функции
	}
	override string GetPlayerClass()
	{ 
		string returned_original = super.GetPlayerClass(); // вызов оригинальной функции с сохранением ее параметров и значения в переменную
		if(returned_original == "Bad Type") // Проверка значения
		{
			returned_original = "Good Type"; // Замена значения на нужное нам
		}
		return returned_original; // Возврат значения функцией
	}
	override void EEKilled( Object killer )
	{
		super.EEKilled( killer ); // вызов оригинальной функции с сохранением ее параметров
		Print("Test3"); // Эта строка выполнится после вызова оригинальной функции
	}
}

Как видим, функции перепишутся с вызовом оригинального значения и допиской нужных или коррекцией.
Можно делать и так, но крайне не рекоммендуется:

Modded class PlayerBase
{
	override void OnConnect()
	{
		Print("Test1"); // Эта строка выполнится до вызова оригинальной функции		
		Print("Test2"); // Эта строка выполнится после вызова оригинальной функции
	}
}

Но в таком случае, если утеряно оригинальное выполнение кода игры и наследование функций, игра/сервер могут сломаться. Да и моды, которые параллельно с вашим, будут использовать эту функцию, могут перестать работать.

Моддинг и скриптинг - Разница?

Собственно, если вы осилили все. что описано выше, вы освоили базовую часть скриптинга в данной игре, а значит вас можно поздравить: Теперь вы готовы к написанию собственных скриптов и модов!
Самой по себе разницы между скриптами и модами нету. Скрипты - это составляющая большинства современных модов в DayZ, т.е. непосредственная часть мода. Те же самые скрипты могут быть и в mpmissions и в моде, но с одной разницей -

то что есть в mpmissions может быть в подключено в моде, а то что подключено в моде не всегда может быть подключено в mpmissions. А смысл как раз в том, что игра загружает скрипты последовательно, т.е. сначала оригинальный код игры с dta, потом моды, и только потом mpmission. Сама же "Mpmission" является частью, заданной в классе "5_Mission" в оригинальных скриптах игры, и делится на 2 файла в зависимости от типа запускаемой игры. Для клиента игры это "missionGameplay.c" а для сервера это "missionServer.c", откуда уже и читаем mpmission сервера. Иными словами, на момент чтения mpmission у нас по сути уже считаны и организованы все структуры разделов кода игры, и доступа к изменениям кодов и классов в "mpmissions" у нас нет.

Т.е. то, что вносится в Mpmissions можно вносить в свой мод, но никак не наоборот. Сами же скрипты по своей стркутуре и особенностям такие же.

 

Примечание:

Что же касается модификаторов, типов переменных, функций, классов, используемых в игре в скриптах и модах, можно пока почитать вот тут на немецком: https://germandayz.de/forum/thread/19551-guide-dayz-standalone-scripting-enforce-scripting/ Позже будем пытаться создавать свою тему с данным описанием
Что касается информации о родных функциях и классах, используемых в игре и на сервере - этой информации найти не смог.  Но ее вы можете найти сами так: распаковываем весь scripts.pbo в папку, запускаем Notepad и используем поиск в папке по тексту (Ctrl+F вкладка №3), ищем по кусочкам нужных фраз на английском и смотрим как называется функция, ее расположение в классе.
Также, предлагаю всем, кто заинтересован в облегчении поиска информации о таких функциях, помочь друг другу и составить этот список самим в вот этой теме на форуме:

Поиск по форуму поможет остальным найти интересующую нас информацию 😉


 

Edited by 123new (see edit history)

Share this post


Link to post
Share on other sites









Posted (edited)

Спасибо за полезную тему)) Честно говоря, мало чего поняла, по причине почти полного отсутствия знаний по теме. Но пост вдохновил меня начать изучать (наконец-то) С++) Давно хотела, руки не доходили. 
Надеюсь, не будет нарушением правил портала, если оставлю ссылки на подборки гайдов по теме изучения С++. Не рекламы ради, а для таких же вдохновившихся, как я) Которые хотят, но не знают с чего начать. 

Для себя я выбрала следующие ресурсы для обучения:
Основы программирования на C++ и  Основы С++ для начинающих (плейлист на youtube)
Если кто-то может посоветовать другие полезные материалы по теме, буду благодарна))

Edited by Zabava (see edit history)

Share this post


Link to post
Share on other sites
1 час назад, Zabava сказал:

Спасибо за полезную тему)) Честно говоря, мало чего поняла, по причине почти полного отсутствия знаний по теме. Но пост вдохновил меня начать изучать (наконец-то) С++) Давно хотела, руки не доходили. 
Надеюсь, не будет нарушением правил портала, если оставлю ссылки на подборки гайдов по теме изучения С++. Не рекламы ради, а для таких же вдохновившихся, как я) Которые хотят, но не знают с чего начать. 

Для себя я выбрала следующие ресурсы для обучения:
Основы программирования на C++ и  Основы С++ для начинающих (плейлист на youtube)
Если кто-то может посоветовать другие полезные материалы по теме, буду благодарна))

забава, это не плюсы

Share this post


Link to post
Share on other sites
1 минуту назад, Malinin сказал:

забава, это не плюсы

господин малина, не вынуждайте меня ЧСить вас и здесь)

Share this post


Link to post
Share on other sites
Только что, Zabava сказал:

господин малина, не вынуждайте меня ЧСить вас и здесь)

Я тебе рекомендую смотреть в C#, синтаксис энфорса - вылитый шарп, с плюсами меньше схожеств, цени своё время, Оль)

Share this post


Link to post
Share on other sites
4 минуты назад, Malinin сказал:

Я тебе рекомендую смотреть в C#, синтаксис энфорса - вылитый шарп, с плюсами меньше схожеств, цени своё время, Оль)

вы умеете нормально общаться, меня это радует) спасибо за совет, обязательно учту 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site, you automaticly agree to our Guidelines and Privacy Policy.
We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.