Написание плагина для FULL клиента TimeZero на Delphi
Создайте новый проект (File -> New -> Application), и измените его главный модуль на код, приведённый ниже.
Чтобы попасть в главный модуль проекта достаточно перейти по пункту меню Project -> View Source.
Главный модуль плагина:
// Указываем компилятору, что это библиотека и её имя NewTZPlugin
library NewTZPlugin;
// Указываем компилятору директиву, указывающую, что расширение библиотеки будет “tzp”
{$E tzp}
// Подключаем модули
uses
// Из этого модуля будет вызвана функция TextToShortCut для процедуры AddMenuItem
Menus;
// Подключаем ресурсы
{$R *.res}
// Процедура инициализации плагина
procedure PluginInitialization(PlugClass:TPlugInInterface);
begin
// Получаем указатель на интерфейс взаимодействия плагина с FULL клиентом
PlugInterface := PlugClass;
// Добавляем в клиент, в пункт меню "Плагины", - новый подпункт с именем плагина
PlugInterface.AddMenuItem(PLUGIN_NAME, Form1.OnLoad, Form1.GetPngIcon, TextToShortCut('Ctrl+P'));
end;
// Функция возвращающая имя плагина
function PluginName : PChar;
begin
Result := PLUGIN_NAME;
end;
// Процедура завершения плагина
procedure PluginFinalization;
begin
// Данная процедура будет вызвана в момент закрытия клиента
end;
// Разрешаем клиенту видеть следующие процедуры
exports
PluginInitialization,
PluginFinalization,
PluginName;
begin
end.
Далее следует подключить к проекту модуль интерфейса взаимодействия плагина с клиентом. Для этого создайте новый модуль, через меню File -> New -> Unit и замените код нового модуля на код, приведённый ниже.
Модуль интерфейса взаимодействия плагина с клиентом:
Следует изменить значение константы PLUGIN_NAME на название вашего плагина.unit PluginInterfaceUnit;
interface
// Подключаем модули
uses Windows, Forms, Classes, Graphics, Controls;
type
TChatPlace = // Тип определяющий область чата
(cpTopFrame,cpDownFrame,cpAllChat);
// Описание областей:
// cpTopFrame - Верхний фрейм чата
// cpDownFrame - Нижний фрейм чата
// cpAllChat - Весь чат
TChatEvents = // Список событий, которые могут возникнуть в чате
(ceStartChat,ceStopChat,ceStartBattle, ceOther,
ceChangeLocation,ceLocationComeIn,ceLocationLeave,
ceChatMessage,cePrivateMessage,ceSystemMessage);
// Описание событий:
// ceStartChat - Старт чата; (Тип: WideString)
// Ник персонажа, которым вошли в игру
// ceStopChat - Остановка чата; (Тип: Integer)
// Причина остановки чата:
// 0 - Выход из игры
// 1 - Остановка чата пользователем
// 2 - Потеря соединения с чатом
// ceChangeLocation - Переход в другую локацию; (Тип: WideString)
// Имя локации, в которую сделали переход + #9 +
// Список персонажей на этой локации (Через запятую)
// В этот список не входит ник играющего персонажа
// ceLocationComeIn - В локацию вошёл персонаж; (Тип: WideString)
// Ник персонажа
// ceLocationLeave - Локацию покинул персонаж; (Тип: WideString)
// Ник персонажа
// ceStartBattle - Персонаж вступил в бой; (Тип: String)
// Номер боя
// ceChatMessage - Пришло сообщение; (Тип: WideString)
// ID номер сообщения + ‘:’ + дата + ‘:’ +
// Текст сообщения + #9 + Номер цвета текста в чате
// Начиная с 0 до 15
// Соответствие цвета и номера
// можно посмотреть в КПК
// в разделе настройки игры
// cePrivateMessage - Пришло приватное сообщение; (Тип: WideString)
// Аналогично ceChatMessage, только приватные сообщения
// ceSystemMessage - Пришло системное сообщение. (Тип: WideString)
// Аналогично ceChatMessage + ники персонажей
// выделяются знаком & для парсинга,
// а значение системного сообщения символом ^
// ceOther - "Свободное" событие (Пока не используется)
TUserInfoEvents = // Список параметров персонажа, за изменениями которых можно следить
(uieLogin, uieClan, uieLevel, uieSex, uieProfession,
uieAvatarNumber, uieLocation, uieVip, uieNowHp, uieMaxHp,
uieNowPsy, uieMaxPsy, uieNowExp, uieExpToLevel,
uieExpNextLevel, uieExpToUp, uieUp, uieStrength, uieDexterity,
uieIntuition, uieStamina, uieAccuracy, uieIntellect, uieVirus,
uieSkillColdSteel, uieSkillLigthWeapons,
uieSkillMediumWeapons, uieSkillHeavyWeapons, uieSkillThrowWeapons,
uieSkillEnergyWeapons, uieSkillMedicine, uieSkillMinesAndTraps,
uieSkillElectronics, uieSkillPsyControl, uieSkillPsyAttack,
uieSkillPsyMedicine, uieSkillPsyCorruption, uieOther);
// Описание параметров:
// uieLogin - Ник персонажа (Тип: WideString)
// uieClan - Клан персонажа (Тип: WideString)
// uieLevel - Уровень персонажа (Тип: Integer)
// uieSex - Пол персонажа (Тип: Integer)
// 0 - Женский
// 1 - Мужской
// uieProfession - Профессия персонажа (Тип: Integer)
// 1 - Корсар
// 2 - Сталкер
// 3 - Старатель
// 4 - Инженер
// 5 - Наемник
// 6 - Торговец
// 7 - Патрульный
// 8 - Штурмовик
// 9 - Специалист
// 10 - Журналист
// 11 - Чиновник
// 12 - Псионик
// 30 - Дилер
// uieAvatarNumber - Номер изображения персонажа (Тип: Integer)
// uieLocation - Текущая локация персонажа (Тип: WideString)
// uieVip - Наличие "кода доступа альфа" у персонажа (Тип: Boolean)
// uieNowHp - Текущий показатель здоровья персонажа (Тип: Integer)
// uieMaxHp - Максимальный показатель здоровья у персонажа (Тип: Integer)
// uieNowPsy - Текущий показатель пси-энергии у персонажа (Тип: Integer)
// uieMaxPsy - Максимальный показатель пси-энергии у персонажа (Тип: Integer)
// uieNowExp - Текущий показатель опыта персонажа (Тип: Integer)
// uieExpToLevel - Показатель кол-ва остатка опыта до уровня (Тип: Integer)
// uieExpNextLevel - Показатель опыта для следующего уровня (Тип: Integer)
// uieExpToUp - Показатель опыта для получения "апа" (Тип: Integer)
// Up - Дополнительное очко параметров персонажа
// uieUp - Следующий "ап" (Тип: Integer)
// uieStrength - Показатель силы персонажа (Тип: Integer)
// uieDexterity - Показатель ловкости персонажа (Тип: Integer)
// uieIntuition - Показатель интуиции персонажа (Тип: Integer)
// uieStamina - Показатель выносливости персонажа (Тип: Integer)
// uieAccuracy - Показатель меткости персонажа (Тип: Integer)
// uieIntellect - Показатель интеллекта персонажа (Тип: Integer)
// uieVirus - Присутствует ли заражение вирусом X (Тип: Integer)
// uieSkillColdSteel - Навык персонажа "Холодное оружие" (Тип: Real)
// uieSkillLigthWeapons - Навык персонажа "Легкое оружие" (Тип: Real)
// uieSkillMediumWeapons - Навык персонажа "Среднее оружие" (Тип: Real)
// uieSkillHeavyWeapons - Навык персонажа "Тяжёлое оружие" (Тип: Real)
// uieSkillThrowWeapon - Навык персонажа "Метательное" (Тип: Real)
// uieSkillEnergyWeapons - Навык персонажа "Энергетическое" (Тип: Real)
// uieSkillMedicine - Навык персонажа "Медицина" (Тип: Real)
// uieSkillMinesAndTraps - Навык персонажа "Кибернетика" (Тип: Real)
// uieSkillElectronics - Навык персонажа "Электроника" (Тип: Real)
// uieSkillPsyControl - Навык персонажа "Пси-Контроль" (Тип: Real)
// uieSkillPsyAttack - Навык персонажа "Пси-Атака" (Тип: Real)
// uieSkillPsyMedicine - Навык персонажа "Пси-Медицина" (Тип: Real)
// uieSkillPsyCorruption - Навык персонажа "Пси-Искажение" (Тип: Real)
// uieOther - "Свободный" параметр (Пока не используется)
// Запись (Событие изменения параметра персонажа/Данные этого изменения)
TUserInfoEventData = record
UserInfoEvent : TUserInfoEvents;
UserInfoData : Variant;
end;
// Тип TGameChatEvent - набор событий, которые могут возникнуть в чате
TGameChatEvent = set of TChatEvents;
// Тип TGameUserInfoEvent - набор параметров персонажа, за изменениями которых можно следить
TGameUserInfoEvent = set of TUserInfoEvents;
// Класс интерфейс плагина
TPlugInInterface = class
public
// Процедура необходима для добавления пункта подменю (submenu), в главном окне клиента, меню "Плагины"
procedure AddMenuItem(MenuItemCapt: String; Proc: TNotifyEvent; PNG: TMemoryStream; Short: TShortCut); virtual; stdcall; abstract;
// Функция возвращает Handle клиентского окна
function GetClientHandle: THandle; virtual; stdcall; abstract;
// Процедура открытия URL страницы во встроенном браузере клиента
procedure TZBrowserNavigate(URL: String); virtual; stdcall; abstract;
// Процедура обновит список событий чата, за которыми плагин под именем PlugName хочет следить
procedure SetChatEvents(PlugName: String; ChatEvents: TGameChatEvent); virtual; stdcall; abstract;
// Процедура обновит список параметров персонажа, за которыми плагин под именем PlugName хочет следить
procedure SetUserInfoEvents(PlugName: String; UserInfoEvents: TGameUserInfoEvent); virtual; stdcall; abstract;
// Функция получения данных из игры
function GetDataFromGame(Request: String): OleVariant; virtual; stdcall; abstract;
// Функция записи данных в игру
function SetDataInGame(Request,Value: OleVariant): Boolean; virtual; stdcall; abstract;
// Функция проверяет находится ли персонаж с ником NickName в игноре
function CheckOnIgnore(NickName: String): Boolean; virtual; stdcall; abstract;
// Процедура отправки текста в чат
procedure SubmitToChat(Request: String); virtual; stdcall; abstract;
// Процедура очистки чата. Place определяет область очистки чата
procedure ClearChat(Place: TChatPlace); virtual; stdcall; abstract;
// "Свободная" функция (Пока не используется)
function OtherData(Request: Variant): Variant; virtual; stdcall; abstract;
end;
const
// Название плагина
PLUGIN_NAME = 'NewTZPlugin';
var
// PlugInterface - указатель на интерфейс взаимодействия плагина с клиентом
PlugInterface : TPlugInInterface;
implementation
end.
Теперь можно сохранить проект. Сделайте это через пункт меню File -> Save All. Путь для сохранения плагина установите в корневую папку FULL клиента, в папку Plug-Ins, чтобы плагин было легко отлаживать в Debug режиме. В качестве имени файла для Unit2 – укажите PluginInterfaceUnit, для модуля Unit1 – название модуля вашей главной формы плагина, к примеру – MainFormUnit. А имя файла для вашего проекта будет определять уникальность названия файла плагина, оно должно соответствовать его значению, к примеру – ChatMessenger.
Плагину надо указать, кто его будет запускать. Сделайте это через пункт меню Run -> Parameters… Укажите в качестве Host Application - FULL клиент Timezero.exe и закройте диалог нажатием кнопки OK.
Перейдите в главный модуль проекта (Project -> View Source) и допишите в разделе uses имя модуля вашей главной формы. (Пример: MainFormUnit in 'MainFormUnit.pas'):
// Подключаем модули
uses
Menus,
MainFormUnit in 'MainFormUnit.pas',
PluginInterfaceUnit in 'PluginInterfaceUnit.pas';
В инициализации плагина, в процедуре PlugClass.AddMenuItem(PLUGIN_NAME, Form1.OnLoad, Form1.GetPngIcon, TextToShortCut('Ctrl+P')); измените Form1 на имя вашей главной формы, к примеру, MainForm, а 'Ctrl+P' измените на то сочетание “горячих клавиш” с помощью которого будет вызываться в клиенте ваш плагин:
// Процедура инициализации плагина
procedure PluginInitialization(PlugClass:TPlugInInterface);
begin
// Получаем указатель на интерфейс взаимодействия плагина с FULL клиентом
PlugInterface := PlugClass;
// Добавляем в клиент, в пункт меню "Плагины", - новый подпункт с именем плагина
PlugInterface.AddMenuItem(PLUGIN_NAME, MainForm.OnLoad, MainForm.GetPngIcon, TextToShortCut('Ctrl+Alt+P'));
end;
Переходим в модуль главной формы плагина, путём выбора его из меню View -> Units… MainFormUnit, и изменяем его код на приведённый ниже:
unit MainFormUnit;
interface
// Подключаем модули
uses
Classes, Forms, Controls, PluginInterfaceUnit;
type
// TMainForm - описание класса для главной формы плагина
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
// Процедура события обращения пользователя к плагину
// Вызывается при клике на ячейку плагина, в меню "Плагины" FULL клиента
procedure OnLoad(Sender: TObject);
// Функция возвращает поток данных содержащий в себе PNG картинку размерами 24 на 24.
function GetPngIcon: TMemoryStream;
protected
// Процедура инициализации создания главной формы плагина
procedure CreateParams(var PlugParams: TCreateParams); override;
end;
var
// MainForm - имя главной формы плагина
Form1 : TForm1;
implementation
{$R *.dfm}
end.
Далее ставим курсор на процедуре procedure OnLoad(Sender: TObject); и жмём сочетание клавиш CTRL+SHIFT+C. Delphi автоматически создаст все описанные методы в разделе implementation:
implementation
{$R *.dfm}
{ TForm1 }
procedure TForm1.CreateParams(var PlugParams: TCreateParams);
begin
inherited;
end;
function TForm1.GetPngIcon: TMemoryStream;
begin
end;
procedure TForm1.OnLoad(Sender: TObject);
begin
end;
end.
Изменяем код на приведённый ниже:
implementation
{$R *.dfm}
{ TForm1 }
// Процедура инициализации создания главной формы плагина
procedure TForm1.CreateParams(var PlugParams: TCreateParams);
begin
inherited;
// Если вы не хотите, чтобы ваш плагин
// создавался как дочернее окно клиента -
// закомментируйте нижеследующий код.
PlugParams.WndParent := PlugInterface.GetClientHandle;
Visible := FALSE;
end;
// Функция возвращает поток данных содержащий в себе PNG картинку размерами 24 на 24.
function TForm1.GetPngIcon: TMemoryStream;
var
// Объявляем поток ресурсов
ResourceStream : TResourceStream;
begin
try
// Создаём поток в который будем перемещать данные PNG картинки
Result := TMemoryStream.Create;
// "Вытаскиваем" PNG картинку из ресурсов плагина
ResourceStream := TResourceStream.Create(HInstance, 'ICO', 'PNG');
// Записываем в поток данные картинки
Result.LoadFromStream(ResourceStream);
// Освобождаем поток ресурсов
ResourceStream.Free;
except
// Ошибка загрузки PNG картинки из ресурса
Result := nil;
end;
end;
// Процедура события обращения пользователя к плагину
procedure TForm1.OnLoad(Sender: TObject);
begin
// Если главной формы плагина нет - создаём её
if not Assigned(MainForm) then MainForm := TMainForm.Create(nil);
// Отображаем главную форму плагина
MainForm.Show;
end;
end.
Переходим в режим редактирования формы (View -> Toggle Form/Unit), делаем активным окно инспектора объектов (View -> Object Inspector) и, найдя параметр формы Name, - изменяем его на имя главной формы плагина - MainForm. Delphi автоматически заменит все прошлые TForm1 на TMainForm.
Можно сохранить проект (File -> Save All) и в первый раз откомпилировать его, проверив код на наличие ошибок, через пункт меню Project -> Compile ChatMessenger (Где ChatMessenger – это имя вашего проекта). Если вы запустите ваш плагин из Delphi (пункт меню Run -> Run) то получите следующее сообщение об ошибке 'Resource ICO not found' класса EResNotFound – это Debug Delphi сообщает, что в функции GetPngIcon он не смог “вытащить” ресурс с PNG картинкой из плагина, т.к. его ещё нет. Если вы не хотите, чтобы ваш плагин имел PNG иконку в пункте меню "Плагины" FULL клиента – можете удалить весь код функции GetPngIcon из раздела implementation и её объявление в разделе public класса формы, в противном случае воспользуйтесь инструкцией по созданию файла ресурса с PNG картинкой для плагина.
Создание файла ресурса с PNG картинкой для плагина:
После того, как вы подберёте соответствующую вашему плагину PNG картику, размерами 24 на 24 – создайте файл с именем “pngicon.rc” и поместите его рядом с картинкой.
Измените текст файла “pngicon.rc” на нижеследующий:
ICO PNG "Имя вашей PNG картинки.png"
Создайте файл с именем “buildres.bat” и также поместите его рядом с картинкой.
Измените текст файла “buildres.bat” на нижеследующий:
Brcc32 pngicon.rc
Запустив файл “buildres.bat” вы получите файл с ресурсом вашей картинки: “pngicon.RES”. Скопируйте его в корневой каталог вашего плагина.
Подключите этот файл к вашему модулю главной формы плагина в разделе implementation:
implementation
{$R *.dfm}
{$R pngicon.RES}
{ TForm1 }
Теперь можно откомпилировать ваш плагин (CTRL + F9) и запустить его (F9), чтобы проверить, что ошибка класса EResNotFound больше не возникает.
Если всё сделано правильно – то в меню "Плагины" FULL клиента TimeZero появится новая ячейка с именем вашего плагина (имя было указано в модуле PluginInterfaceUnit, в константе PLUGIN_NAME) и PNG картинкой, которая была помещена в ресурсы плагина.
Взаимодействие плагина с игровым чатом и Flash
Клиент позволяет плагинам использовать систему событий, для получения той или иной информации из чата и игрового Flash. В любой момент вы можете послать клиенту команду, указав в параметрах за какими событиями чата или изменениями в параметрах персонажа вы хотите следить, и, как только произойдёт это событие в игре или чате, – вы, тут же, получите ожидаемую информацию.
К примеру:
Вам необходимо знать, когда персонаж вошёл в игру и когда он её покинул.
Переходим в модуль главной формы плагина, (View -> Units… MainFormUnit) переводим Delphi в режим редактирования формы (View -> Toggle Form/Unit) и добавляем на форму компонент TListBox со вкладки Standart. Переключаемся на инспектор объектов (View -> Object Inspector) и начинаем изменять параметры этого компонента:
Св-во Align ставим в alClient.
Св-во Style меняем на lbOwnerDrawFixed.
В этом компоненте будут отображаться события входа и выхода персонажа.
Перейдите в главный модуль проекта (Project -> View Source) и подкорректируйте процедуру инициализации плагина в следующий вид:
// Процедура инициализации плагина
procedure PluginInitialization(PlugClass:TPlugInInterface);
begin
// Получаем указатель на интерфейс взаимодействия плагина с FULL клиентом
PlugInterface := PlugClass;
// Сообщаем клиенту, что плагин будет следить за событием входа и выхода из игры
PlugInterface.SetChatEvents(PLUGIN_NAME, [ceStartChat, ceStopChat]);
// Добавляем в клиент, в пункт меню "Плагины", - новый подпункт с именем плагина
PlugInterface.AddMenuItem(PLUGIN_NAME, MainForm.OnLoad, MainForm.GetPngIcon, TextToShortCut('Ctrl+Alt+P'));
end;
При помощи процедуры SetChatEvents мы указали клиенту список событий ([ceStartChat, ceStopChat]) за которыми плагин будет следить. Чтобы обнулить этот список – достаточно указать пустой набор: PlugInterface.SetChatEvents(PLUGIN_NAME, []);
Теперь следует создать обработчик события, чтобы клиент смог через него общаться с плагином. Для этого добавьте новую процедуру сразу после инициализации плагина:
// Обработчик событий чата, для общения клиента с плагином
procedure OnChatEvent(ChatEvent: TChatEvents; EventData: Variant);
var
EventTime : String;
begin
// Записываем время события
EventTime := DateTimeToStr(now);
// Если главная форма плагина не создана - следует её создать
if not Assigned(MainForm) then MainForm := TMainForm.Create(nil);
// Уточняем, какое событие произошло
// Описание событий TChatEvents можно посмотреть в модуле PluginInterfaceUnit
case ChatEvent of
// Персонаж вошёл в игру: Добавляем в TListBox новую строчку
ceStartChat : MainForm.ListBox1.Items.Add('Дата: '+EventTime+': Персонаж '+EventData+' вошёл в игру.');
// Работа чата остановлена - узнаём причину
ceStopChat : case EventData of
// Персонаж вышел из игры: Добавляем в TListBox новую строчку
0: MainForm.ListBox1.Items.Add('Дата: '+EventTime+': Персонаж вышел из игры.');
// Персонаж остановил работу чата (командой //stop): Добавляем в TListBox новую строчку
1: MainForm.ListBox1.Items.Add('Дата: '+EventTime+': Персонаж остановил работу чата.');
// Потеря соединения с чатом: Добавляем в TListBox новую строчку
2: MainForm.ListBox1.Items.Add('Дата: '+EventTime+': Потеря соединения с чатом.');
end;
end;
end;
Т.к. была задействована функция DateTimeToStr из модуля SysUtils – его надо добавить в раздел подключаемых модулей главного модуля проекта:
// Подключаем модули
uses
Menus,
SysUtils,
MainFormUnit in 'MainFormUnit.pas',
PluginInterfaceUnit in 'PluginInterfaceUnit.pas';
Добавленную процедуру OnChatEvent надо прописать в разделе exports, чтобы клиент мог её вызывать:
// Разрешаем клиенту видеть следующие процедуры
exports
PluginInitialization,
PluginFinalization,
OnChatEvent,
PluginName;
begin
end.
Скомпилируйте плагин (CTRL + F9) и запустите его (F9), чтобы наглядно увидеть результат работы обработчика событий OnChatEvent.
К примеру:
Вам необходимо следить за состоянием здоровья и пси-энергии у персонажа.
Отредактируйте процедуру инициализации плагина в следующий вид:
// Процедура инициализации плагина
procedure PluginInitialization(PlugClass:TPlugInInterface);
begin
// Получаем указатель на интерфейс взаимодействия плагина с FULL клиентом
PlugInterface := PlugClass;
// Сообщаем клиенту, что плагин будет следить за событием входа и выхода из игры
PlugInterface.SetChatEvents(PLUGIN_NAME, [ceStartChat, ceStopChat]);
// Сообщаем клиенту, что плагин будет следить за изменениями параметров здоровья и пси-энергии персонажа
PlugInterface.SetUserInfoEvents(PLUGIN_NAME, [uieNowHp, uieMaxHp, uieNowPsy, uieMaxPsy]);
// Добавляем в клиент, в пункт меню "Плагины", - новый подпункт с именем плагина
PlugInterface.AddMenuItem(PLUGIN_NAME, MainForm.OnLoad, MainForm.GetPngIcon, TextToShortCut('Ctrl+Alt+P'));
end;
При помощи процедуры SetUserInfoEvents мы указали клиенту список параметров персонажа ([uieNowHp, uieMaxHp, uieNowPsy, uieMaxPsy]) за изменениями которых плагин будет следить. Чтобы обнулить этот список – достаточно указать пустой набор:
PlugInterface.SetUserInfoEvents (PLUGIN_NAME, []);
Т.к. здоровье и пси-энергия персонажа имеет текущее и максимальное значение – создайте соответствующий этим параметрам новый тип и две переменные в модуле PluginInterfaceUnit:
// Запись двойного значения (Текущее и максимальное)
TDoubleValue = record
NowValue : integer;
MaxValue : integer;
end;
const
// Название плагина
PLUGIN_NAME = 'NewTZPlugin';
var
// PlugInterface - указатель на интерфейс взаимодействия плагина с клиентом
PlugInterface : TPlugInInterface;
// Здоровье персонажа
PlayerHp : TDoubleValue;
// Пси-энергия персонажа
PlayerPsy : TDoubleValue;
implementation
end.
Далее следует создать обработчик событий изменений параметров персонажа, чтобы клиент смог через него общаться с плагином. Для этого добавьте новую процедуру сразу после инициализации плагина:
// Обработчик событий изменений параметров персонажа, для общения клиента с плагином
procedure OnUserInfoEvent(UserInfoDataChange: array of TUserInfoEventData);
var
// Счётчик для массива
i : integer;
begin
// Проходим по массиву и смотрим какие параметры персонажа изменились
for i:=0 to Length(UserInfoDataChange)-1 do
begin
// В зависимости от изменённых параметров - делаем соответствующие записи в переменные
case UserInfoDataChange[i].UserInfoEvent of
uieNowHp : PlayerHp.NowValue := UserInfoDataChange[i].UserInfoData;
uieMaxHp : PlayerHp.MaxValue := UserInfoDataChange[i].UserInfoData;
uieNowPsy : PlayerPsy.NowValue := UserInfoDataChange[i].UserInfoData;
uieMaxPsy : PlayerPsy.MaxValue := UserInfoDataChange[i].UserInfoData;
end;
end;
// Если главная форма плагина не создана - следует её создать
if not Assigned(MainForm) then MainForm := TMainForm.Create(nil);
// Отображаем в TListBox изменённые параметры персонажа
MainForm.ListBox1.Items.Add('Здоровье персонажа: ' +IntToStr(PlayerHp.NowValue)+'/'+IntToStr(PlayerHp.MaxValue));
MainForm.ListBox1.Items.Add('Пси-энергия персонажа: '+IntToStr(PlayerPsy.NowValue)+'/'+IntToStr(PlayerPsy.MaxValue));
end;
Добавленную процедуру OnUserInfoEvent следует прописать в разделе exports, чтобы клиент мог её вызывать:
// Разрешаем клиенту видеть следующие процедуры
exports
PluginInitialization,
PluginFinalization,
OnUserInfoEvent,
OnChatEvent,
PluginName;
begin
end.
Скомпилируйте плагин (CTRL + F9) и запустите его (F9), чтобы наглядно увидеть результат работы обработчика событий OnUserInfoEvent.
Внимание:
Если вы решили использовать в своём плагине систему событий клиента – пожалуйста, не задерживайте основной поток клиента долгой обработкой. В случае если вам требуется сделать какую-то проверку, которая может занять время, – используйте дополнительные потоки для обработки, к примеру, TTimer или TThread.
К примеру:
Вам необходимо узнать какой-то параметр персонажа, который нельзя получить с помощью системы событий клиента.
В таком случае вы можете воспользоваться функцией получения данных из игры GetDataFromGame.
Вы указываете этой функции переменную, отвечающую за тот или иной параметр персонажа, а она возвращает вам его значение.
Параметры вашего персонажа хранятся в специально отведённом в игровой Flash месте:
_root.USER.Parameter
Где Parameter – это любой из идентификаторов отвечающий за параметр персонажа:
login - Имя персонажа
HP - Текущее количество здоровья
maxHP - Максимальное количество здоровья
str - Сила
dex - Ловкость
int - Интуиция
pow - Выносливость
acc - Меткость
intel - Интеллект
exp - Опыт (обратите внимание, что это значение текущего опыта персонажа)
nextlevel - Необходимое количество опыта для достижения следующего уровня
level - Уровень
pro - Профессия. Идентификатор имеет следующие значения:
1 - Корсар
2 - Сталкер
3 - Старатель
4 - Инженер
5 - Наемник
6 - Торговец
7 - Патрульный
8 - Штурмовик
9 - Специалист
10 - Журналист
11 - Чиновник
12 - Псионик
30 - Дилер
propwr - Уровень профессии (значение от 0 до 1)
man - Пол персонажа
virus - Наличие заражения вирусом X
psy - Текущий уровень пси-энергии
maxPsy - Максимальный уровень пси-энергии
Местонахождение:
X - Первая координата местонахождения персонажа
Y - Вторая координата местонахождения персонажа (обратите внимание на
то, что координаты даются в формате 0..360, а не -180..180)
ROOM - Номер комнаты в шахте
Навыки:
sk0 - Холодное оружие
sk1 - Легкое оружие
sk2 - Среднее оружие
sk3 - Тяжелое оружие
sk4 - Метательное
sk5 - Энергетическое
sk6 - Медицина
sk7 - Минирование
sk8 - Электроника
sk9 - Пси-контроль
sk10 - Пси-атака
sk11 - Пси-медицина
sk12 - Пси-искажение
Таким образом, чтобы присвоить, например, заголовку главной формы плагина имя вашего персонажа нужно сделать следующее:
MainForm.Caption := PlugInterface.GetDataFromGame('_root.USER.login');
ВНИМАНИЕ! Вызывать функции Flash-компоненты из плагина невозможно.
Информация о других персонажах.
Непосредственный доступ к информации другого персонажа описан здесь.
Находясь в игре – можно посмотреть информацию о другом персонаже, с помощью функции записи данных в игру (SetDataInGame), указав в параметрах переменную, отвечающую за отображение игрового диалога информации о персонаже, (‘_root.watchUserInfo.login’) и значение имени игрока.
Пример:
PlugInterface.SetDataInGame('_root.watchUserInfo.login','Keeper Ranson');
Также, можно открыть информацию о персонаже во встроенном браузере FULL клиента, воспользовавшись процедурой TZBrowserNavigate, указав в параметрах ссылку на желаемого персонажа.
Пример:
PlugInterface.TZBrowserNavigate('http://www.timezero.ru/info.ru.html?'+'Keeper Ranson');
Дополнительные возможности плагинов
Клиент позволяет использовать плагинам тот же язык, который использует он сам. При старте FULL клиента и при смене языка через окно настроек – возникает событие PluginSetLanguage, в котором передаётся текущее значение установленного в клиенте языка.
Список всех установленных языков находится в секции "Languages" файла "Language.ini", располагающегося в корневой папке с клиентом.
Для того, чтобы использовать это событие добавьте новую процедуру сразу после инициализации плагина:
procedure PluginSetLanguage(const s_Language: String);
begin
// Переменная s_Language содержит текущее значение установленного в клиенте языка
end;
Добавленную процедуру PluginSetLanguage следует прописать в разделе exports, чтобы клиент мог её вызывать:
// Разрешаем клиенту видеть следующие процедуры
exports
PluginInitialization,
PluginFinalization,
PluginSetLanguage,
PluginName;
begin
end.
В любой момент ваш плагин может обратиться к следующим методам клиента:
- Открыть во встроенном браузере FULL клиента URL страницу:
PlugInterface.TZBrowserNavigate('http://www.timezero.ru');
- Проверить находится ли персонаж в игнор листе (ShowMessage – требует подключение модуля Dialogs): if PlugInterface.CheckOnIgnore('Keeper Ranson') then
ShowMessage('Keeper Ranson - в игнор листе')else ShowMessage('Keeper Ranson - не игнорируется'); - Отправить текст в игровой чат (Этим же способом можно использовать чатовые команды игры. Пример: //ping):
PlugInterface.SubmitToChat('Keeper Ranson');
- Очистить чат. Place определяет область очистки чата: PlugInterface.ClearChat(cpAllChat);
Требования к плагинам
I. Плагин нужно отправить на электронный адрес full_bugs@timezero.ru, где указать:
- В теме письма «Плагин» и название плагина (Пример: "Плагин - Мышка").
- Ник и/или реальное имя человека его написавшего.
- Полное описание плагина (Все возможности и особенности - это необходимо для модерации).
- Должен быть ZIP-архив с исходниками плагина с названием: "Название плагина (source).zip"
- Должен быть ZIP-архив с откомпилированным плагином.
- Отдельно
(вне архивов) должен быть прикреплён текстовый файл с кратким описанием
плагина и его возможностей (для публикации на сайте).
- В плагине обязательно должно быть тем или иным образом указано имя (ник) лица, его написавшего.
- Интерфейс
плагина должен быть выполнен так, чтобы с ним было удобно работать,
элементы управления не должны "наползать" друг на друга.
- Если
плагин предназначен для каких-либо расчётов - обязательно обрабатывать
возможные ошибки и информировать об этом (например, с помощью
MessageBox).
- Плагин обязательно должен представлять
из себя один файл, если это необходимо - все изображения/звуки/видео,
требуемые для работы плагина, должны быть в виде ресурсов,
присоединённых к плагину. Ограничения на создание файлов плагином в
процессе работы нет (распаковка ресурсов, сохранение настроек и пр.).
- Плагин не должен изменять каких-либо данных в файлах настроек/локализации клиента. Разрешается только чтение.
- Плагин не должен требовать установку или наличие какого-либо дополнительного софта для своей работоспособности.