Stealth Client Forum

Альтернативный клиент Ultima Online
Текущее время: 24.11.2017 2:02

Часовой пояс: UTC + 2 часа




Начать новую тему Ответить на тему  [ Сообщений: 8 ] 
Автор Сообщение
 Заголовок сообщения: Тонкости скриптинга
СообщениеДобавлено: 18.09.2010 10:47 
Не в сети Novice
Novice

Зарегистрирован: 02.01.2010 13:55
Сообщения: 88
Массивы функций
Была ли у кого-то после изучения материала по массивам мысль: "а можно ли создать массив функций?":?:

Даже если и не была, я все равно расскажу как это сделать. :)

Начнем с того, что можно создавать тип-функцию (процедуру):
Код:
type
  MyProc = procedure();

Простая процедура, которая ничего не принимает. Добавим параметр:
Код:
type
  MyProc = procedure(Text: string);

Теперь мы можем объявить массив нашей процедуры:
Код:
var
  ProcArray: array [0..1] of MyProc;

Следом будут идти сами процедуры. Важно чтобы количество параметров не отличалось от параметров нашего типа.
Код:
procedure First(Text: string);
begin
  AddToSystemJournal('Первая процедура: '+Text);
end;

procedure Second(Text: string);
begin
  AddToSystemJournal('Вторая процедура: '+Text);
end;

Готово. Добавляем их в массив:
Код:
ProcArray[0]:= @First;
ProcArray[1]:= @Second;

Теперь, чтобы вызвать процедуру First, достаточно указать ее индекс в массиве. Полный код будет выглядить так:


Код:
type
  MyProc = procedure(Text: string);

var
  ProcArray: array [0..1] of MyProc;

procedure First(Text: string);
begin
  AddToSystemJournal('Первая процедура: '+Text);
end;

procedure Second(Text: string);
begin
  AddToSystemJournal('Вторая процедура: '+Text);
end;

begin
ProcArray[0]:= @First;
ProcArray[1]:= @Second;

ProcArray[0]('1'); // = First('1')
ProcArray[0]('2'); // = First('2')
ProcArray[1]('3'); // = Second('3')
end.


Это было как бы вводным примерном, возможно, кто-то найдет этому применение. Далее Callback.

_________________
///


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: 18.09.2010 11:17 
Не в сети Novice
Novice

Зарегистрирован: 02.01.2010 13:55
Сообщения: 88
Callback
Как вы уже догадались (наверное), если функции можно записать в переменные, то их можно и передать в другие функции. Так вот, вызов переданной функции из другой и называется колбеком.

Рассмотрим мою функцию FindTypeC из темы Includes

Код:
function FindTypeC(ItemTypes: array of word; Container: cardinal; CallBackFunc: function(FindItem: cardinal):boolean):integer;
var
  i: integer;
  FoundItems: array of cardinal;
begin
if not Assigned(CallBackFunc) then exit;
result:= FindTypeB(ItemTypes, Container, FoundItems);
for i:= 0 to result-1 do
  if not CallBackFunc(FoundItems[i]) then break;
end;

Последним параметром функция принимает некий "тип" function(FindItem: cardinal):boolean. Т.е. с легкостью можно написать свою функцию, не ковыряясь в инклудах или делая циклы, и лишь передать указатель на нее (значок @ перед названием функции).
Код:
function KillTarget(FindItem: cardinal):boolean;
begin
UOSay('.kill');
if WaitForTarget(3000) then TargetToObject(FindItem);
result:= true;
end;

begin
FindTypeC([$0190, $0191], Ground, @KillTarget);
end.


Код:
if not Assigned(CallBackFunc) then exit;
или
Код:
if CallBackFunc = nil then exit;
Проверяет был ли передан указатель на функцию.

Далее, получая некий список предметов (в моем случае), запускается цикл передачи ИД в колбек функцию. Для удобности я использовал именно функцию (возвращающую boolean), а не процедуру, чтобы в любой момент можно было остановить цикл.
Код:
if not CallBackFunc(FoundItems[i]) then break;

_________________
///


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: 18.09.2010 11:42 
Не в сети Novice
Novice

Зарегистрирован: 02.01.2010 13:55
Сообщения: 88
Динамические массивы
На ранних стадиях каждый сталкивался с проблемой установки пределов массива. Эта проблема решается динамическими массивами. Начнем с массива ИД предметов:
Код:
var
  MyArray: array of cardinal;

Вроде все просто, но при внесении каких-либо данных в него, нужно устанавливать размер. Размер массива устанавливается процедурой SetLength, которая принимает два параметра: в первом указывается наш массив, второй - новая длина. Спешу заметить, что отсчет в динамических массивах всегда начинается с 0.
Код:
SetLength(MyArray, 3)

Устанавливает длину массива - 3 ячейки. Т.е. теперь нам доступны ячейки MyArray[0], MyArray[1] и MyArray[2].

Данная операция не обязательна, если в миссив нужно записать уже готовые данные.
Код:
MyArray:= [$99881234, $12332112, $00A98877, Backpack]

Длина массива автоматически станет равной 4-м. А в ячейки 0, 1, 2 и 3 запишутся данные указанные в квадратных скобках.

Получить длину массива можно воспользовавшись функцией Length

Так же есть функции определения пределов массива:
Low - показывает минимальный индекс массива (в нашем случае он всегда будет равен 0)
High - показывает максимальный индекс массива (т.е. Length - 1)

_________________
///


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: 18.09.2010 12:04 
Не в сети Developer
Developer

Зарегистрирован: 24.03.2005 17:05
Сообщения: 3638
мощно, очень мощно.



моя "тонкость" конечно попроще, но тоже порой полезно.


как вы знаете (наверное) - если у вас есть класс, то при написании
with Class do вы можете обращаться к его полям и функциям напрямую, без указания класса.

например, для класса TStringList можно обратиться так
Код:
tempstringlist : tstringlist;

with tempstringlist do
  begin
    if Count = 0 then
      Add('fff');
  end;

таким образом, вам ненадо писать tempstringlist.Count и tempstringlist.Add.


но трюк не совсем в этом.

есть ситуации, когда создавать переменную класса не очень нужно (короткие операции).
тогда можно обойтись таким путем
Код:
with Class_Name.Create do



вот вам полный пример, после разберем подробно

Код:
Program Test;
var
 IP: array [0..3] of Byte;
 I: Byte;
 s : String;
begin
s := '127.0.0.1';
with TStringList.Create do
   try
     Delimiter := '.';
     DelimitedText := s;
     if Count = 4 then
     begin
       for I := 0 to 3 do IP[I] := StrToInt(Strings[I]);
       for I := Low(IP) to High(IP) do AddToSystemJournal(IntToStr(IP[i]));
     end;
   finally
     Free;
   end;
end.

Здесь мы как раз наблюдаем работу с строковым списком, не привязанным к переменной.

итак, конструкция try finally end; используется для того, чтобы освобождение класса выполнялось ВСЕГДА, даже при возникновении ошибок.
В процессе работы входящая строка делится на строки по разделителю (символ-разделитель - точка). В качестве образца полученные куски строк (куски айпи-адреса) заносятся в массив IP, а так же выводятся построчно в SystemJournal.

Кстати, здесь же показана работа с High-Low прменительно к массиву.

_________________
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".


Последний раз редактировалось Vizit0r 28.10.2010 13:17, всего редактировалось 2 раз(а).

Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: 18.09.2010 12:56 
Не в сети Novice
Novice

Зарегистрирован: 02.01.2010 13:55
Сообщения: 88
try
Как указывалось выше, "конструкция try finally end; используется для того, чтобы освобождение класса выполнялось ВСЕГДА, даже при возникновении ошибок". А теперь подробнее:

try
<ЛЮБЫЕ ДЕЙСТВИЯ>
finally
<ЗАВЕРШАЮЩИЕ ДЕЙСТВИЯ>
end

Если при выполнении действий между try и finally произойдет ошибка, то сразу выполнится завершающая часть. Даже если ошибки не будет рано или поздно она все равно выполняется.
Но есть один минус: при ошибке выскакивают окна (Невозможно открыть файл или др.), которые зачастую нам вообще не нужны. Для таких мест я использую

try
<ЛЮБЫЕ ДЕЙСТВИЯ>
except
<ДЕЙСТВИЯ ПРИ ОШИБКЕ>
end

Даже такая связка:
Код:
with TStringList.Create do begin
  try
    LoadFromFile('C:\asdsadsa');
  except
  end;
  try
    tempstr:= Lines[0];
  except
  end;
  Free;
end;

Не будет вас обременять какими-либо ненужными окнами, а просто будет продолжать работу. При желании мы всегда можем вывести ошибку в журнал добавив строку
Код:
except
  AddToSystemJournal('Ай-ай-ай, а кто это сделал?')
end;

_________________
///


Последний раз редактировалось NoSilence 12.06.2011 20:58, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: 09.11.2010 21:10 
Не в сети Novice
Novice

Зарегистрирован: 02.01.2010 13:55
Сообщения: 88
Variant
Мечтали ли вы когда-нибудь забить на все эти типы переменных с их "IntToStr", "StrToInt" и т.д.? Variant дарует вам эту возможность, потому что он всетипны, а точнее имеет неопределенный тип.

Всего лишь одно объявление переменной:
Код:
var
  MyVar: variant;

и мы получаем integer, boolean, string и т.п. в одном флаконе! Вот полный список подтипов этого типа:
Код:
  vtInteger    = 0;
  vtBoolean    = 1;
  vtChar       = 2;
  vtExtended   = 3;
  vtString     = 4;
  vtPointer    = 5;
  vtPChar      = 6;
  vtObject     = 7;
  vtClass      = 8;
  vtWideChar   = 9;
  vtPWideChar  = 10;
  vtAnsiString = 11;
  vtCurrency   = 12;
  vtVariant    = 13;
  vtInterface  = 14;
  vtWideString = 15;
  vtInt64      = 16;


Это не нужно объяснять, это нужно показывать!

Код:
MyVar:= true;
if MyVar then
  AddToSystemJournal(MyVar);
Покажет вам "true";

Код:
var
  MyVar: variant;
  i: integer;

begin
i:= 4;
MyVar:= true;
if MyVar then
  AddToSystemJournal(IntToStr(i+MyVar));
end.
True считается как -1, поэтому данный код выведет в журнал "3".

Код:
MyVar:= 7.7;
AddToSystemJournal(IntToStr(MyVar));
При данной оперции дробная часть не откидывается, а округляется. В журнале: "8".

_________________
///


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: 11.11.2010 1:12 
Не в сети Novice
Novice

Зарегистрирован: 28.10.2008 20:44
Сообщения: 95
Мне тоже понравилось! Спасиб за дельные советы! прям как на лекции)


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Тонкости скриптинга
СообщениеДобавлено: 27.07.2016 10:29 
Не в сети Developer
Developer

Зарегистрирован: 24.03.2005 17:05
Сообщения: 3638
пришел тут вопрос на днях:

Цитата:
XXX (17:15:22 23/07/2016)
if (EasyUoGlobalWeapon = 'EventWeapon') or (EasyUoGlobalRing = 'EventRing') or (EasyUoGlobalBracelet = 'EventBracelet') or (EasyUoGlobalStam = 'EventStam') or (EasyUoGlobalHits = 'EventHits') then
XXX (17:15:32 23/07/2016)
this sentence is too long. How to seperate one sentence to two sentence for reading well?


Допилил и прикрутил кой-чего к PAX'у, так что теперь есть 2 варианта:

1) когда надо проверить вхождение строки в массив строк
Код:
if IndexStr (EasyUoGlobalWeapon,['EventWeapon', 'EventWeapon','EventWeapon','EventWeapon']) <> -1 then
  true
else
  false



2) когда на каждый вариант надо свое действие - case для строк.
Код:
 program new;
var x : String;

type
  TEventEUO = (eEUO_eventweapon,
               eEUO_eventring,
               eEUO_eventbracelet,
               eEUO_eventstam,
               eEUO_eventhits);

Begin
  x := 'EventRing';
  case TEventEUO(GetEnumValue(TypeInfo(TEventEUO), 'eEUO_'
                                    +LowerCase(x))) of
    eEUO_eventweapon   : AddToSystemJournal('EventWeapon detected');
    eEUO_eventring   : AddToSystemJournal('EventRing detected');
    eEUO_eventbracelet     : AddToSystemJournal('EventBracelet detected');     
    eEUO_eventstam     : AddToSystemJournal('EventStam detected');     
    eEUO_eventhits     : AddToSystemJournal('EventHits detected');     
  end;     
  x := 'EventHits';
  case TEventEUO(GetEnumValue(TypeInfo(TEventEUO), 'eEUO_'
                                    +LowerCase(x))) of
    eEUO_eventweapon   : AddToSystemJournal('EventWeapon detected');
    eEUO_eventring   : AddToSystemJournal('EventRing detected');
    eEUO_eventbracelet     : AddToSystemJournal('EventBracelet detected');     
    eEUO_eventstam     : AddToSystemJournal('EventStam detected');     
    eEUO_eventhits     : AddToSystemJournal('EventHits detected');     
  end;     
end.

На выходе будет

Цитата:
08:57:23:176 [xxx]: Compiling
08:57:23:213 [xxx]: Compiled succesfully
08:57:23:214 [xxx]: EventRing detected
08:57:23:214 [xxx]: EventHits detected
08:57:23:214 [xxx]: Succesfully executed
08:57:23:215 [xxx]: Script test.sc stopped successfuly

_________________
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".


Вернуться к началу
 Профиль  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 8 ] 

Часовой пояс: UTC + 2 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron


Тюнинг и аксессуары. Тюнинг внедорожников: магазин 4х4 в Одессе. Интернет магазин "AMAX".
Также, на правах рекламы: школьный сайт: school-work.net и еще один: https://www.youtube.com/channel/UCFSPHKHjP22tEl8Rjcst9Fw.


Рейтинг@Mail.ru
Powered by phpBB® Forum Software © phpBB Group