Thief: the Dark Fate Forum

Гильдия Редакторов => DromEd => Тема начата: Chuzhoi от 26 марта 2017 17:56:19

Название: Скрипты для NewDark
Отправлено: Chuzhoi от 26 марта 2017 17:56:19
Цитата: Zontik от 23 марта 2017 16:11:49
Chuzhoi, я так понял, ты уже почитал немного по сути вопроса. С каким из двух инструментов работать удобнее? Для какого документация написана толковее, точнее и подробнее? Какой лучше изучать с околонулевым уровнем подготовки?
Учитывая наличие третьего вопроса, для меня важнее всего ответ на второй.
Мне трудно что-то посоветовать.  Конечно, для себя я бы выбрал Squirrel, несмотря на то, что с этим языком я раньше дела не имел - там привычный С-образный синтаксис; там имеется классическое ООП, основанное на классах, которого нет в Lua; кроме того, сама репутация языка (несмотря на то, что он довольно молодой) вроде как уже достаточно высока. Кроме того, поддержка новых функций NewDark тоже имеет достаточно важное значение, как ни крути. Но...

Во-первых, важно понимать, что язык - это язык, а API - это API. Документации к языку Lua на сайте LGScript нет - надо искать доки и учебники по Lua на специализированных сайтах; точно также нет документации по языку Squirrel в тех четырех текстовых файликах, которые приложены к Squirrel.osm. И если говорить чисто о языке, то мне кажется, что новичку, который далек от программирования, все-таки будет легче освоить Lua, нежели Squirrel - сам язык, как мне кажется, синтаксически несколько проще (хотя это еще вопрос), и ввиду довольно высокой популярности самого языка документации в интернете по нему навалом (в т. ч. и на русском языке) - чем вряд ли сможет похвастать Squirrel. По крайней мере, я сходу не нашел ни одного толкового руководства по "белке" на русском языке.

А что касается мощи и возможностей языка, то при тех объемах и той сложности скриптинга, с которыми приходится иметь дело при создании ФМ (когда функция - обработчик сообщения занимает в среднем пять строчек), я вообще не вижу большой разницы, какой язык использовать. Даже если кому-нибудь взбрело бы в голову использовать для скриптинга в Thief какой-нибудь диалект SQL, то, полагаю, мы бы все равно примерно с тем же объемом усилий добились аналогичных результатов. ООП, которое я упомянул ранее - это хорошо, но вряд ли в нем есть какой-то реальный профит в нашей ситуации, когда в основном нужно "что-то подправить" - ну разве что если мы будет городить совершенно новую игру с нуля.

Ну а во-вторых, если говорить о самом API, то, опять же, документация к LGScript представлена в более подробном и удобоваримом виде - на сайте есть структурированный онлайн-справочник по API (в котором даны краткие описания всех сообщений движка и функций с их аргументами) и небольшой, но достаточно информативный туториал, построенный по принципу "от простого к сложному". Документация же к Squirrel.osm расчитана на подготовленного человека и в части описания собственно API предельно лаконична - там даны лишь структуры классов и имена функций с перечнем аргументов (без каких-либо комментариев). В самом API используются разные подходы: в LGScript - более простой  функциональный (скрипт представляет собой набор функций, обрабатывающих сообщения), а в Squirrel script - объектно-ориентированный (скрипт представляет собой класс, унаследованный от SqRootScript, методы которого обрабатывают сообщения - уже напугал, да?) Конечно, документацию по API в некоторой степени можно считать универсальной, и ничто не мешает использовать справочник по LGScript для программирования в Squirrel script (ведь сообщения и сервисы движка те же), но то, что полученные сведения придется переводить из одной "системы координат" в другую, для новичка может оказаться непосильной задачей.

В общем, если Zontik самостоятельно начнет изучать LGScript, то он с большей вероятностью добьется некоторых успехов, нежели если он возьмется за "белку", где его, учитывая околонулевую подготовленность, почти наверняка ждет фиаско. У LGScript, по большому счету, только один серьезный недостаток - он не поддерживает новые функции Dark Engine. А вообще, если бы вместо Squirrel.osm в NewDark включили бы доработанный lgs.osm, то я бы глазом не моргнул и был бы только рад, несмотря на всю мою любовь к си-образным языкам. Так что сам выбирай. Вообще, я думаю, мир не без добрых людей, и на чем бы ты ни остановил свой выбор, без помощи ты не останешься. Но проще будет с LGScript. Но это мое мнение. Кто не согласен, тот может высказаться.
Название: Скрипты для NewDark
Отправлено: nemyax от 26 марта 2017 19:22:33
На ttlg резонно отмечают (http://www.ttlg.com/forums/showthread.php?t=147690&p=2352466&viewfull=1#post2352466), что можно и вовсе обойтись без скриптинга, а написать себе что надо на си. Тоже вариант.
Название: Скрипты для NewDark
Отправлено: Zontik от 27 марта 2017 09:21:58
Я когда-то давно изучал С, но это было еще до появления С++. С последним у меня понимание так и не сложилось, поэтому мысль уловил и в общем-то согласен.
Хотя все равно гложет мысль, что я чего-то в этой жизни не понимаю.
Цитироватьскрипт представляет собой класс, унаследованный от SqRootScript, методы которого обрабатывают сообщения
Вот если можно объяснить это нормальными человеческими словами - было бы здорово. В порядке общего развития. Что такое класс? Что такое метод? Про сообщения объяснять не надо, наверное, если это то же самое, что и в LGS.
Название: Скрипты для NewDark
Отправлено: HellRaiser от 27 марта 2017 09:48:07
Цитата: Zontik от 27 марта 2017 09:21:58
Цитироватьскрипт представляет собой класс, унаследованный от SqRootScript, методы которого обрабатывают сообщения
Вот если можно объяснить это нормальными человеческими словами - было бы здорово. В порядке общего развития. Что такое класс? Что такое метод? Про сообщения объяснять не надо, наверное, если это то же самое, что и в LGS.

Короч, если совсем простыми словами, то слющай дарагой сюды:
Класс - это структура данных (типа struct в Си), только в ООП юзается как элементарная единица данных. Ну вот например, есть у тебя тип данных с плавающей точкой (как float в Сях), по сути его можно описать как класс, который имеет набор определённых свойств, необходимых для работы с вещественными числами. Метод класса - это функция, которая работает с внутренними полями класса - мемберами (или членами, кому как удобно называть). Член класса - это поле внутри класса (аналогично в структурах, за тем исключением, что доступ к ним в отличии от структур, по-дефолту закрыт). Методы в литературе тоже обзывают мембер-функциями, так что не путаться - это одно и то же.

Возвращаемся к нашему флоуту: у тебя есть класс, в котором есть набор функций-методов, описывающих операции с вещественным числом: умножение, деление, приведение типа и проч, есть мембер(ы): описывающие например мантиссу и порядок твоего флоута. Так же есть некий 4-байтовый контейнер, в котором ты хранишь своё число в каком угодно тебе виде, а при обращении к объекту твоего класса специальная функция-мембер (или метод) вернёт вызывающему тот самый флоут, который мы привыкли видеть в архитектуре х86.

Касательно наследования: у тебя есть базовый класс (а лучше - интерфейс), описывающий поведение какого-нить объекта (группы объектов): ну например .... ну например.... ну например.....
ну пусть будет жЫвотное.
Так вот, у базового класса есть например функции "родиться", "умереть", "размножиться" и "пожрать".  Это поведение свойственно всем животным. Но ты решил придумать своё мифическое животное, например единорога, так?
Мы опустим щас всю иерархию (животное->млекопитающее->парнокопытное->лошадеобразное), где каждый унаследованный класс конкретизирует абстракцию понятия животное и сводит его к конкретному описанию конкретного животного и будем счситать, что от обычного животного единорог отличается лишь наличием рога на лбу...
Поэтому мы пишем унаследованный класс единорог, которому добавятся мемберы описывающие длину рога и и его цвет например..

Надеюсь, в общих чертах понятно разложил? Более подробно могу в личке рассказать :)
Название: Скрипты для NewDark
Отправлено: Zontik от 27 марта 2017 09:53:23
Единственное, что я понял хорошо - это степень своего невежества. На этом достаточно, спасибо.
Название: Скрипты для NewDark
Отправлено: nemyax от 27 марта 2017 09:55:27
Пора открывать отдельную тему про программизм в моддинге вора.
Название: Скрипты для NewDark
Отправлено: HellRaiser от 27 марта 2017 10:02:13
[off]Вот чё, на самом деле чтоли из меня НАСТОЛЬКО наиприпоганейший объясняльщег?[/off]
Название: Скрипты для NewDark
Отправлено: nemyax от 27 марта 2017 10:13:56
[off]

HellRaiser
Лично мне ты объяснял вполне успешно. Но мне надо было для дела, а не на форуме потрындеть.[/off]
Название: Скрипты для NewDark
Отправлено: HellRaiser от 27 марта 2017 10:44:47
nemyax, благодарю, отлегло ))
Zontik
ну может так понятнее будет?

*** это чисто для примера, так что господа программировщики, прошу не пинать***

class base_object
{
private: // доступ к этим членам закрыт, их может менять только сам класс (т.е. мемберы класса)
BOOL bIsExistInThisReality; // мембер (член) класса
protected: // это защищённые мемберы, для всех других классов они как закрытые, а для унаследованных от данного класса - доступны. Короч модификатор видимости такой.
void createObject();  // это метод класса
void destroyObject(); // это тоже метод класса (или функция-член, ибо всё, что внутри фигурных скобок - есть члены класса)
public: // доступ к этим мемберам открыт:
BOOL IsObjectCreated(); // это тоже метод класса
  virtual void Show() = 0; // ключевое слово vitrual означает, что функция в производном классе будет переопределена по-другому, для того, об это м поговорим чуть ниже
// более того, "=0" означает, что эта функция не должна быть описана в данном классе, а только в производных. И верно же- как "показать" то, у чего нет формы, а только флаг существования?
};

void base_object::createObject()
{
  bIsExistInThisReality = TRUE;
}
void base_object::destroyObject()
{
  bIsExistInThisReality = FALSE;
}
base_object::base_object() // конструктор класса
{
  createObject();
}

base_object::base_object() // деструктор класса
{
  destroyObject();
}

////////////////////////////////////////////////////////////////////////////////////
class triangle: public base_object
{
private: // у него есть помимо базового ещё и координаты, которые можно менять извне с помощью функции SetPosition
// также неявно в этом объекте будет присутствовать переменная bIsExistInThisReality, но менять мы её не сможем
int x;
int y;
int z;
public:
virtual void Show();
void SetPosition (int newX, int newY, int newZ);
}

void triangle::SetPosition(int newX, int newY, int newZ)
{
x = newX;
y = newY;
z = newZ;
}
void triangle::Show()
{
// рисуем треугольник на экране
}

class rectangle: public base_object
{
private: // у него есть помимо базового ещё и координаты, которые можно менять извне с помощью функции SetPosition
// также неявно в этом объекте будет присутствовать переменная bIsExistInThisReality, но менять мы её не сможем
int a;
int b;
int c;
int d;
public:
virtual void Show();

}
void rectangle::Show()
{
// рисуем прямоугольник на экране
}

class circle: public base_object
{
private:
int radius;
int x;
int y;
public:
virtual void Show();

}
void circle::Show()
{
// рисуем прямоугольник на экране
}

void main()
{
  base_object* arr[3];
  arr[0] = new circle();
  arr[1] = new rectangle();
  arr[2] = new triangle(); 
  ...
  for (int i = 0 ; i < 3)
  arr[i]->Show(); // для каждого типа объекта будет вызываться своя рисовальная функция
}
Название: Скрипты для NewDark
Отправлено: Zontik от 27 марта 2017 10:44:59
[off]Ты нормально объяснил, а я понял, что не был готов к таким объяснениям. В принципе могу понять, о чем речь, но полок, чтобы разложить эти знания, у меня в голове еще нет. Для правильного вопроса еще надо созреть.[/off]
Название: Скрипты для NewDark
Отправлено: HellRaiser от 27 марта 2017 10:52:11
Zontik теперь точно отлегло  ;D
Название: Скрипты для NewDark
Отправлено: ndk от 27 марта 2017 11:08:29
Цитата: nemyax от 26 марта 2017 19:22:33
На ttlg резонно отмечают (http://www.ttlg.com/forums/showthread.php?t=147690&p=2352466&viewfull=1#post2352466), что можно и вовсе обойтись без скриптинга, а написать себе что надо на си. Тоже вариант.
Совсем нет. Сейчас так уже не делают. (время выставил) :)
https://youtu.be/WC6Xx_jLXmg?t=1m56s
Название: Скрипты для NewDark
Отправлено: nemyax от 27 марта 2017 13:09:35
Цитата: Zontik от 27 марта 2017 10:44:59
[off]я понял, что не был готов к таким объяснениям[/off]
[off]Тыж учил си. Вот это примерно как оборачивать структы другими структами (можно с применением объединений, чёб доступ к членам был прямее). Разве что в сях все члены на виду, а в плюсах можно прикрыться.
А вместо методов можно включать в структы указатели на функции, хотя смысла тут маловато.
[/off]
Название: Скрипты для NewDark
Отправлено: Zontik от 27 марта 2017 14:13:12
[off]То есть глобализация, если по-русски? Если да, то принцип понятен, вопрос - как это использовать на практике. Избавление от рутины?
Пробовал как-то разобраться в тексте простенькой программы на С++. Был поражен, насколько сложно докопаться до ответов на простейшие конкретные вопросы. Такое ощущение, будто все конкретные вещи определяются "где-то там", и как туда забраться и что-то исправить - фиг знает.[/off]
Название: Скрипты для NewDark
Отправлено: nemyax от 27 марта 2017 14:19:40
Цитата: Zontik от 27 марта 2017 14:13:12
[off]То есть глобализация, если по-русски?[/off]
[off]Почему глобализация? Обычное наследование. Такой, но с перламутровыми пуговицами.[/off]
Название: Скрипты для NewDark
Отправлено: HellRaiser от 27 марта 2017 14:33:51
Ну вот "где-то там" как раз и описана вся суть (будь то сторонняя библиотека или конкретные апи), а в простенькой программе нужно конкретизировать определённое поведение через все эти полиморфизмы и наследования. Да и как я уже говорил тут на форуме давно: программизм это умение складывать пазл, запчасти которого и есть сторонние библиотеки и интерфейсы. Нужно только грамотно их сложить так, чтобы это в итоге заработало, а ошибки и исключения выкидывались не в твоей программе, а в тех самых кусках, в которые ты не можешь залезть по копирастным или физическим причинам.

Вот есть у тебя некий интерфейс, ну назовём его "сценой" (я в этих ваших мрак-моторах ещё не ковырялся достаточно подробно ). Вот есть у сцены свойство "дождь". Есть сообщение (метод) по которому генерится начало и конец дождя (а может и не генерится). А ты решил взять и сделать сцену со снегом. И тут у тебя 2 варианта: или переписать огроменнейший класс только ради того, чтобы изменить одно свойство, или унаследоваться от имеющегося и добавить ему параметр, отвечающий за выпадение снега. В итоге это выглядит как глобальный условный оператор, только не на уровне кода, а на уровне компилятора, который без нас знает, когда и чью конкретную функцию вызвать.

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

ну вот как примитивнейший пример (как это б выглядело):
class scene
{
...
virtual void OnWeatherChange()
{
  ...
   StartRain(); //
  ...
}
...
};

class snow_scene : scene
{
void StartSnow()
{
...
}
virtual void OnWeatherChange()
{
  StartSnow();
}
};


И собсна всё. Т.е. ты модифицировал одну функцию, не ломая при этом всю остальную программу.  Главное, чтобы вызывающий код понимал, что твой класс нуна загрузить в определённом месте в определённое время. А уж как он его подтянет - это не наши заботы, ровно как и то, какие жучары сидят внутри кода АПИ-шного класса.



Название: Скрипты для NewDark
Отправлено: Zontik от 27 марта 2017 14:49:22
Собственно, я бы так и поступал со снегом, будь он у меня. И именно так поступаю с дождем. А то, что предлагает Чужой (переписать дождь на Белке) - это и есть "переписать огромнейший класс", когда можно просто взять и поменять параметр в графе "вид осадков". Да?
Правда, переписывать класс в этом случае все равно придется, поскольку галки "стартовать дождь по триггеру" в существующем классе нет, и просто взять и добавить ее нельзя. Только лезть в "туда, где всё".
ЦитироватьТ.е. ты модифицировал одну функцию, не ломая при этом всю остальную программу.
Вот в этом-то и была моя основная проблема: я не мог модифицировать функцию, не зная, где она, какая она, что делает и чего требует. Модифицировать заочно, что ли?
ЦитироватьГлавное, чтобы вызывающий код понимал, что твой класс нуна загрузить в определённом месте в определённое время.
Но сначала ты сам должен разобраться, что это за место и время. И уже потом пытаться вдолбить свое понимание программе через какое-то (на этот раз известное) место.
Название: Скрипты для NewDark
Отправлено: HellRaiser от 27 марта 2017 15:28:28
Цитата: Zontik от 27 марта 2017 14:49:22
А то, что предлагает Чужой (переписать дождь на Белке) - это и есть "переписать огромнейший класс", когда можно просто взять и поменять параметр в графе "вид осадков". Да?
Это уже по-другому называется. Есть ли смысл в данном переезде - я не могу сказать. Будет ли удобнее или легче с точки зрения программирования модифицировать и расширять твой код - тем более не могу.

Цитата: Zontik от 27 марта 2017 14:49:22
Правда, переписывать класс в этом случае все равно придется, поскольку галки "стартовать дождь по триггеру" в существующем классе нет, и просто взять и добавить ее нельзя. Только лезть в "туда, где всё".
А может оно есть в обёрточках этой самой белки? Тогда наверно есть смысл послушать Чужого.

Цитата: Zontik от 27 марта 2017 14:49:22
Вот в этом-то и была моя основная проблема: я не мог модифицировать функцию, не зная, где она, какая она, что делает и чего требует. Модифицировать заочно, что ли?
Ну ты же по коду мог определить, что делает именно эта программа? Или не очень?

Цитата: Zontik от 27 марта 2017 14:49:22
Но сначала ты сам должен разобраться, что это за место и время.
Не совсем верное утверждение. Ты же знаешь, что за программу ты делаешь - утилиту или плагин, или что-то ещё, поэтому время и место и примерное поведение (примерное, в смысле - приблизительное) тебе должны быть известны какбе. Далее в ход идут те инструменты, которые тебе предоставлены СДКой или документацией. Ну и движемся далее, непосредственно к решению прикладных конкретных задач.
Название: Скрипты для NewDark
Отправлено: Zontik от 27 марта 2017 16:02:01
Вообще я этот дождь привел просто как пример, мне вовсе не нужно включать его по триггеру. И никто код дождя не переписывал (кроме kdau).
ЦитироватьНу ты же по коду мог определить, что делает именно эта программа? Или не очень?
Что делает - я знал и без кода. А вот код заставил меня в этом сомневаться. Нигде не было явных указаний на то, что именно она делает.
Скажу больше: после С у меня вообще было ощущение, будто это не код, а что-то совсем другое. Какая-то декларация о намерениях, а не список конкретных действий.
Смешно звучит, да?
Я лучше оставлю ООП в покое. Подход в решении прикладных задач в редакторе в принципе сходен: ты знаешь время и место, может, приблизительные, а может даже, точнее некуда. Осталось только перевести то, что ты знаешь, в язык понятных редактору действий. Вот тут большинство начинающих авторов и ломается, потому что, во-первых, фиг поймешь, какие действия он умеет выполнять, а во-вторых, образ, которым он действует - это тоже своего рода иностранный язык.
Например, мне нужно, чтобы действие С выполнялось при условии, что выполнены действия А и В, причем не просто выполнены, а не были отменены после выполнения (уже нюанс, который с легкостью игнорируется начинающими). Я знаю, как перевести это условие на язык редактора, мне известны средства, которыми можно этого достичь. Я более-менее представляю, как сделать это на языке высокого уровня, проблема может быть разве что в синтаксисе. Как сделать то же самое на языке ООП - не имею ни малейшего представления, и если даже на самом деле это проще, то для меня - сложнее.
Название: Скрипты для NewDark
Отправлено: nemyax от 27 марта 2017 16:21:47
Цитата: Zontik от 27 марта 2017 16:02:01Как сделать то же самое на языке ООП - не имею ни малейшего представления
Хранишь в своём экземпляре объекта некое состояние. А для удобства перещёлкивания состояния предусматриваешь объекту соответствующие методы. Не?
Название: Скрипты для NewDark
Отправлено: HellRaiser от 27 марта 2017 16:22:36
Цитата: Zontik от 27 марта 2017 14:13:12
Пробовал как-то разобраться в тексте простенькой программы на С++.
Дай поглядеть. Малобукафф вовсе не говорит о простоте (ровно как и наоброт).

ЦитироватьСмешно звучит, да?
Вовсе нет. Это могла быть совсем и не ООП-программа (в том смысле в котором мы сейчас обсуждаем), а просто с событийно-ориентированной архитектурой (типа QT или MFC). Я тоже считаю, что ООП не нужно для решения простых задач. Более того, в скриптах вообще (кроме расширения функционала) не вижу в этом смысла. Да и в больших самостоятельных программах оно не всегда нужно в общем-то. Но ведь могут нарисоваться такие задачи, где без него ну совсем никак не обойтись. Поэтому, лучше наверное с ним, чем без него.
Название: Скрипты для NewDark
Отправлено: Zontik от 27 марта 2017 16:49:01
ЦитироватьХранишь в своём экземпляре объекта некое состояние. А для удобства перещёлкивания состояния предусматриваешь объекту соответствующие методы. Не?
Верю, что именно так это выглядит, когда разбираешься в вопросе. Но не очень-то похоже на набор четких инструкций, правда?
HellRaiser
Тот поезд давно ушел, я даже не помню с какого вокзала. Помню только свое разочарование при виде последнего вагона.
Программа была тестовой из пакета С++ for Windows. И она не была бы простой, если бы ее писали просто на С, уж настолько-то я теперь просветился.
Название: Скрипты для NewDark
Отправлено: HellRaiser от 27 марта 2017 17:10:05
Цитата: Zontik от 27 марта 2017 16:49:01
ЦитироватьХранишь в своём экземпляре объекта некое состояние. А для удобства перещёлкивания состояния предусматриваешь объекту соответствующие методы. Не?
Но не очень-то похоже на набор четких инструкций, правда?
Очень даже похоже. Представь себе конечный автомат с состояниями, может такая аналогия покажет тебе эту медаль с немного другой стороны?

Цитата: Zontik от 27 марта 2017 16:49:01
И она не была бы простой, если бы ее писали просто на С, уж настолько-то я теперь просветился.
Первое правило во всех книжках по программизму: не усложнять без определённой надобности. Если бы она была просто на С, то вполне вероятно, что объём кода был бы чуть больше, а быстродействие чуть выше. Но вовсе не обязательно, что она стала бы сложнее. Всё-таки очень хотелось бы узнать, о чём собсна речь.

Если конкретно про винду, то там есть 2 подхода (и в обоих можно комбинировать и С и С++ в любых пропорциях).
1) Приложение строится по-старинке: есть точка входа WinMain и куча оконных клоассов со своими обработчиками а-ля wndProc, в каждом таком обработчике необходимо на каждый чих писать много кода (рисовалку, реакцию на пункт меню, мыши, клавы, юзер, системные сообщения и т.д.) Особенно канонiчно в таком коде использовать нативное виндовое АПИ, где не всегда понятные названия функций сочетаются с просто ниэпически большим количеством параметров, каждый второй из которых - некая структура, которая ещё и инициализируется другой вспомогательной функцией, принимающей в качестве параметров прочую неведомую херню.

2) событийно-ориентированный код (как я говорил выше - QT или MFC), где весь вышеописанный ужос спрятан в красивые классы (много классов, ОЧЕНЬ МНОГО КЛАССОВ) с удобными обработчиками и позволяющий довольно быстро и относительно удобно разрабатывать оконные приложения. Имеются обёрточки для контейнеров данных, файлов, тредов и прочие полезности. Но точку входа найти намного труднее, т.к. весь код представляет собой некий набор непонятных классов (самый простой пример - от 2 до 6), написанных заранее умными дядями,  производных от базовых классов, отвечающих за вид, диалог, документ...  У MFC и QT тоже есть свои подводные ками, и не мало, но я думаю, что об этом никто не захочет тут поговорить :)

ЗЫ: QT - кроссплатформенный фреймворк, поэтому под линукс и программу портировать не придётся (почти).
ЗЗЫ: есть и другие фреймворки, можно их комбинировать, отчего на плечи ложится более тяжкий груз ответственности, больше прыжков с бубном, чтобы подружить ужа с ежом, но как итог - меньший объём (дааааалеко не всегда) конкретно твоего проекта.
Название: Скрипты для NewDark
Отправлено: nemyax от 27 марта 2017 17:48:40
Цитата: Zontik от 27 марта 2017 16:49:01
не очень-то похоже на набор четких инструкций, правда?
Ну вот псевдоговнокод, если хочешь:

class MyStateTracker
{
  bool stage_a_complete = false;
  bool stage_b_complete = false;
public:
  bool to_thy_work()
  {
    if (stage_a_complete && stage_b_complete)
    {
      // do something clever
      return true;
    }
    return false;
  }
  void check_a(MyState st_a)
  {
    int some_a_metric;
    // analyse state and assign to some_a_metric
    if (some_a_metric >= NICE_A) { stage_a_complete = true; }
  }
  void check_b(MyState st_b)
  {
    int some_b_metric;
    // analyse state and assign to some_b_metric
    if (some_b_metric >= NICE_B) { stage_b_complete = true; }
  }
};

Почти не отличается от подобного же на си, если присмотреться. Тут как раз настоящее ООП и не требуется, как подметил HellRaiser.
Название: Скрипты для NewDark
Отправлено: Chuzhoi от 27 марта 2017 17:57:57
Цитата: Zontik от 27 марта 2017 09:21:58
Я когда-то давно изучал С, но это было еще до появления С++.
Ну вот, ты, оказывается, уже почти все знаешь! А я-то думал, что ты вообще ни бум-бум... А еще говорил про околонулевой уровень.  А больше ты ничего не изучал? Может, Паскаль или Бейсик? Или вот Фортран в свое время в технических вузах преподавали...

В общем, мое мнение поменялось на 180 градусов: теперь я настоятельно рекомендую хотя бы в общих чертах понять, что такое класс и заняться Squirrel. Видишь, HellRaiser тебе уже все объяснил.

(А если серьезно, то я не совсем понимаю, зачем все так усложнять, давать примеры на C++, что-то писать про Qt и проч., и проч. Мы же не собираемся из Зонтика сделать заправского программиста, а просто пытаемся объяснить ему, что такое Squirrel, который на порядок проще, чем C++ - например, там даже приватности членов нет).

А класс - это всего лишь описание объекта. И все. Это примерно как архетип в Thief - вот есть архетип (который еще не объект, а просто его схема), а есть объект, который на основе этого архетипа создан. Или несколько однотипных объектов.

Подобно архетипам в Thief, класс может иметь свойства (это переменные, которые привязаны к классу). Таким образом, всякий раз, когда на основе класса создается объект, создается набор таких переменных (свойств). Можно сказать, что физически объект представляет собой набор таких свойств-переменных. И еще класс может иметь методы (т. е. функции, привязанные к этому классу). Когда у нас создан объект, то мы можем вызывать у него эти функции, благодаря чему объект является не просто хранилищем данных, а "оживает", т. е. выполняет некие задачи, свойственные этому объекту (точнее, свойственные именно этому классу, на основе которого объект был создан).

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

Еще немного терминологии:
- объект, созданный на основе класса, называется экземпляром класса;
- свойства и методы класса называются членами класса.

Собственно, я думаю, это вся теория, которую тебе нужно для начала знать.

Для сравнения приведу скрипт на Lua и аналогичный скрипт на Squirrel. Это скрипт, который выводит id объекта и заодно считает, сколько раз его фробнули (можно для пробы повесить его, например, на кнопку):


-- Это скрипт на Lua

local frobCount = 0

function FrobWorldBegin(msg)
frobCount = frobCount + 1
lgs.DarkUISrv.TextMessage("Object id=" .. msg.to .. " frobbed " .. frobCount .. " times")
return true
end



// Это скрипт на Squirrel

class FrobCount extends SqRootScript
{
frobCount = 0;

function OnFrobWorldBegin()
{
frobCount++;
DarkUI.TextMessage("Object id=" + message().to + " frobbed " + frobCount + " times");
return true;
}
}


Как видишь, не все так страшно. Добавлена строчка спереди и фигурные скобки. Все остальное аналогично.
Название: Скрипты для NewDark
Отправлено: HellRaiser от 27 марта 2017 17:58:54
Обожаю nemyax'а: всё по делу, разжёвано до текста, понятного даже школьнику, без лишних простыней, коротко и сжато (снимаю шляпу пойду спилю рога).

Цитата: Chuzhoi от 27 марта 2017 17:57:57
А если серьезно, то я не совсем понимаю, зачем все так усложнять, давать примеры на C++, что-то писать про Qt и проч., и проч.
Да, чёт поток сознания понёс во все тяжкие :embarassed:
Много лишнего текста у меня там, но зато Зонтику нечего бояться, ведь мы почти все скримеры ему уже показали  ;D

Цитата: Chuzhoi от 27 марта 2017 17:57:57
Мы же не собираемся из Зонтика сделать заправского программиста, а просто пытаемся объяснить ему, что такое Squirrel
.... А вдруг ВНЕЗАПНО <...> ?  :eek: 
Название: Скрипты для NewDark
Отправлено: nemyax от 27 марта 2017 23:38:04
Zontik
А вот ровно те же яйца вообще без плюсов:

#include <stdio.h>
#include <stdbool.h>
#define Call(s_ptr, method, ...) s_ptr->method(s_ptr, ##__VA_ARGS__)
#define Nice_a 42
#define Nice_b 0

struct state
{
  int a;
  int b;
};

struct state_tracker
{
  struct state *my_state;
  _Bool stage_a_complete;
  _Bool stage_b_complete;
  void (*check_a)(struct state_tracker *st);
  void (*check_b)(struct state_tracker *st);
  _Bool (*go)(struct state_tracker *st);
};

struct state g_state = {.a=10, .b=20};

void a(struct state_tracker *st)
{
  if(st->my_state->a >= Nice_a) {st->stage_a_complete = true;}
}

void b(struct state_tracker *st)
{
  if(st->my_state->b <= Nice_b) {st->stage_b_complete = true;}
}

_Bool go(struct state_tracker *st)
{
  if(st->stage_a_complete && st->stage_b_complete)
  {
    printf("zngrmmm!\n");
    return 1;
  }
  printf("scht...\n");
  return 0;
}

int main()
{
  struct state_tracker st =
    {.my_state=&g_state
    ,.stage_a_complete=0
    ,.stage_b_complete=0
    ,.check_a=a
    ,.check_b=b
    ,.go=go};
  struct state_tracker *pst = &st;
  printf("a is %i, b is %i\n", g_state.a, g_state.b);
  Call(pst, check_a);
  Call(pst, check_b);
  Call(pst, go);
  g_state.a = 50;
  g_state.b = 0;
  printf("a is %i, b is %i\n", g_state.a, g_state.b);
  Call(pst, check_a);
  Call(pst, check_b);
  Call(pst, go);
  return 0;
}



Тоже коробочка с состоянием, которое можно читать и менять по необходимости, и с методами (функциями-членами).
Единственная странный закидон здесь — способ вызова методов. В сях всё равно не получится как в плюсах (obj.method() или obj_ptr->method()), поэтому нечего и пытаться имитировать плюсовый синтаксис. По-любому придётся указывать коробочку в аргументах функции.
Но можно чуть-чуть автоматизировать через самодельный синтаксис, если:
Убедиться, что оно работает, можно тут: http://www.tutorialspoint.com/compile_c_online.php
Название: Скрипты для NewDark
Отправлено: HellRaiser от 28 марта 2017 09:36:30
Цитата: nemyax от 27 марта 2017 23:38:04
В сях всё равно не получится как в плюсах (obj.method() или obj_ptr->method()), поэтому нечего и пытаться имитировать плюсовый синтаксис. По-любому придётся указывать коробочку в аргументах функции.
Ну это уже крайности, я бы сказал. За последние лет 20, любой разработанный сишный компилер в той или иной степени - немного плюсовый, даже для каких-нить экзотических железок. Поэтому методы вызывать можно. А чисто сишный режим нынче нафих никому не спёрся (кроме случаев, когда нужна поддержка слишком древнего кода на не менее древнем железе). И зачем оно надо так надо над собой издеваться, ведь тот же былинный BC31 уже умел всё красиво? Чистый си был давно и стал легендой, а задачи в те времена были намного проще и не требовали (не так часто как сейчас) таких хитро###сложенных конструкций :)
Название: Скрипты для NewDark
Отправлено: Zontik от 28 марта 2017 09:56:50
nemyax, действительно, почти все понятно.
Chuzhoi, "изучал" на значит "изучил". А первым действительно был Фортран. Бейсик... это так, факультативно, для себя и совсем чуть-чуть.
Поэтому, раз уж мы докатились до примеров, задам глупые вопросы.
1. Что означает return true? Что все прошло успешно? А если нет (как такое вообще возможно?), тогда return что?
2. В результате получаем ту же переменную, но с измененным значением (FrobCount), которая выводится на экран. Это понятно. А вот сама переменная определяется где? Она уже существует в движке, даже если не писать никакой скрипт, и ее название определено "где-то там"? То есть нужен справочник подобных названий?
3. message().to - вот это вообще непонятно. По идее, эта функция, которая должна хранить внутри номер объекта. Но в Lua она называется msg.to. То есть, получается, у самого движка такой функции нет? Дальше: вот эти скобки в первом варианте - они-то что означают?
4. FrobWorldBegin - хоть что-то знакомое. Это передающийся сигнал. Но в двух версиях он почему-то называется по-разному. С какой стати?
Ну и в заключение. Коней на переправе не меняют, так что до завершения кампании я объявляю мораторий на белку. После с удовольствием возьмусь за освоение (по мере необходимости), но сейчас это будет равнозначно попытке усидеть на двух стульях. Поэтому отложим более детальный разговор (как в примере nemyax) до лучших времен.
Название: Скрипты для NewDark
Отправлено: nemyax от 28 марта 2017 11:12:56
Цитата: Zontik от 28 марта 2017 09:56:50message().to - вот это вообще непонятно. По идее, эта функция, которая должна хранить внутри номер объекта.
Здесь вызов функции и доступ к свойству возвращённого значения.
Функция сама по себе ничего не "хранит". Ну то есть отдельные вызовы функции, конечно, хранятся на стеке до ретурна, каждый вызов со своими независимыми данными. Но на стек обычно лазиет только дебаггер. В программе/скрипте ты туда не заглядываешь.
Название: Скрипты для NewDark
Отправлено: Chuzhoi от 28 марта 2017 18:12:29
Цитата: Zontik от 28 марта 2017 09:56:50
1. Что означает return true? Что все прошло успешно? А если нет (как такое вообще возможно?), тогда return что?
Если не написать return true, то, очевидно, функция вернет некое пустое значение, эквивалентное false. Во всех примерах, данных для lgscript, в обработчиках сообщений есть это return true, но никаких комментариев по этому поводу я не нашел. Возможно, это означает, вызвать ли последующие обработчики для данного сообщения, если они имеются (в других скриптах), или завязать с этим делом. Поскольку я не знаю толком, то обычно просто пишу return true (но надо бы все-таки поразбираться с этим делом).

Цитата: Zontik от 28 марта 2017 09:56:50
2. А вот сама переменная определяется где?
Переменную придумал я. Определена она в скрипте (local frobCount = 0 в Lua и frobCount = 0; в белке). Назвать ее можно было как угодно.

Цитата: Zontik от 28 марта 2017 09:56:50
message().to
message() - это функция, возвращающая сообщение, которое в данный момент послано нашему игровому объекту и которое мы обрабатываем. Само сообщение представляет собой объект с несколькими свойствами, которые могут различаться в зависимости от типа сообщения, при этом есть несколько стандартных свойств: from - ID игрового объекта (я специально буду говорить "игровой объект", чтобы отличить его от объектов, с которыми мы имеем дело в скриптах), который послал сообщение; to - ID игрового объекта, который получил сообщение (т. е. именно того объекта, к которому мы прицепили скрипт), message - имя сообщения и т. д. (остальное можно найти в API-reference_messages.txt, где описан базовый класс sScrMsg и его производные классы).

В Lua немножко другая схема - сообщение передается в виде Lua-таблицы через аргумент msg, но все остальное аналогично. ("Таблица" в Lua - это понятие, в общих чертах аналогичное объектам в Squirrel, хотя это не совсем одно и то же).

Цитата: Zontik от 28 марта 2017 09:56:50
FrobWorldBegin - хоть что-то знакомое. Это передающийся сигнал. Но в двух версиях он почему-то называется по-разному. С какой стати?
Так решили авторы данных инструментов. В LGScript функции, обрабатывающие сообщения, называются точно так же, как и сами сообщения, а в белкоскрипте к этим именам еще нужно добавлять On. Мне больше нравится второй вариант, т. к. сразу понятно, что мы имеем дело с обработчиком сообщений, а не с какой-то обычной функцией (Или мы будем говорить "сигнал"? Я не против, нужно только определиться).

Цитата: Zontik от 28 марта 2017 09:56:50
Ну и в заключение. Коней на переправе не меняют, так что до завершения кампании я объявляю мораторий на белку.
Совершенно правильное решение. Даже я, если ты попросишь написать еще какой-нибудь скрипт, напишу его на Lua. Незачем плодить инструменты и подпапки. Если, конечно, тебе в будущем не вздумается управлять погодой...
Название: Скрипты для NewDark
Отправлено: HellRaiser от 08 июня 2017 23:19:47
Короч, нарыл на просторах ютуба:
Базовый курс лекций по сям/крестам. Будет интересно как студентам (или начинающим программерам), так и опытным гуру: чувак в процессе объяснения простых истин параллельно вещает очень много полезных нюансов, которые профессионалам хотя бы неплохо освежить в памяти (а тех, кто про эти нюансы не в курсах - запишем в первую категорию).

Короч, у кого достаточно времени -  наслаждайтеся  ;) Курс состоит из 21 лекции, в среднем по 1.5 часа каждая.
Сцылочка на плейлист. (https://www.youtube.com/playlist?list=PL5hxfU7iakhuz6N1fSHdh7J8iwLOk9ssv)