Скриптинг в GTA IV
#141
Отправлено 26 July 2009 - 09:56
#142
Отправлено 26 July 2009 - 11:18
для открытия исполняемых файлов нужен дизассемблер. Лучше всего использовать IDA 5 Pro. Искать на cracklab.ru
открывать понятно,но как после етого их засунуть в borland? да и редоктировать не очень удобно в этой проге
#143
Отправлено 26 July 2009 - 12:22
открывать понятно,но как после етого их засунуть в borland? да и редоктировать не очень удобно в этой проге
А что, вообще, хочется сделать? (И что именно не удобно редактировать?)
PS. Предлагаю переместиться сюда: http://forums.gtamod...p?showtopic=423
#144
Гость_squilky_*
Отправлено 14 September 2009 - 10:26
#145
Отправлено 14 September 2009 - 12:39
#146
Отправлено 14 September 2009 - 19:53
Я пока не встретил ни одного (!) стабильного модуля из .asi, .net.dll, .lua ... Переюзал около 3-х десятков различных модов, каждый из них "подвешивал" игру в разных ситуациях.В 4-й гта есть новый способ писания скриптов раньше было а main.scm или подобных а сейчас можно как то подключать отдельные скриптовые файлы
.asi, .net.dll, .lua - это тупиковый путь развития скриптинга, т.к.скажите пожалуйста, как можно их создавать и какой там язык может есть уже ечебники?.
1. Слишком сложно в реализации.
2. Невозможность редактирования.
3. Только во внутреннем скрипте (script.img) можно предусмотреть все конфликтные ситуации, при которых работа скрипта может быть аварийно завершена, но никак не во внешних .asi, .net.dll, .lua ...
Сообщение отредактировал Capushon: 15 September 2009 - 09:41
#147
Отправлено 15 September 2009 - 17:56
Будем надеется что listener, Alexander, или Seemann в скором времени создаст что-нибудь в чём можно было бы редактировать script.img, а дальше дело пойдёткак то подключать отдельные скриптовые файлы, скажите пожалуйста, как
ps: Иначе на скриптинге, в том виде, в каком он всем был доступен - можно ставить крест ...
#148
Отправлено 15 September 2009 - 18:00
.asi, .net.dll, .lua - это тупиковый путь развития скриптинга, т.к.
1. Слишком сложно в реализации.
2. Невозможность редактирования.
3. Только во внутреннем скрипте (script.img) можно предусмотреть все конфликтные ситуации, при которых работа скрипта может быть аварийно завершена, но никак не во внешних .asi, .net.dll, .lua ...
1. все зависит от знания того или иного языка и опыта работы с программой для редактирования. Программисту с опытом работы с Дельфи или Visual Studio написать такой модуль проще чем программисту без опыта. (для сравнения: скриптеру с опытом работы в саннике гораздо легче написать скрипт чем новичку).
2. скрипты lua поддаются редактированию (хотя может я отстал от жизни). Опять же в этом есть свои плюсы (защита собственных скриптов и все такое, тебе ли не знать
3. опыт работы с CLEO подсказывает, что самые хорошие скрипты - те, которые не используют ресурсы других скриптов (в т.ч. оригинальных). если это условие выполняется, кол-во конфликтов снижается до минимального кол-ва (и их можно избежать простыми проверками)
#149
Отправлено 19 November 2009 - 08:55
Сможешь сделать динамическую автоподстановку переменных, констант, типов, native и скриптовых функций, полей структур с учётом инклудов в своём редакторе? Этого очень не хватает. После выхода компилятора SCO выйдет тыща облочек для него, и автоподстановка - весомый аргумент будет для популярности твоей оболочки.Но у меня есть опыт (небольшой :-) в синтаксических интерпретаторах.
Путь к Delphi 7 хранится в реестре: раздел HKEY_CURRENT_USER\Software\Borland\Delphi\7.0 ключ RootDir. Путь к SA (в короткой форме) хранится в разделе HKEY_LOCAL_MACHINE\SOFTWARE\Rockstar Games\GTA San Andreas\Installation ключ ExePath. Путь к SB3 в реестре нет. И вообще INI-плагины - тупиковый путь, оттуда сложно что-либо сделать.Если все это запустить на другом компе, то скорее всего все будет недоступным, потому что пути к программам в INI нужно переписать.
Насчёт плагинов (dll) - должна быть возможность добавления пунктов главного и контекстного меню прямо из плагина, а не редактировать текстовую таблицу вручную.
И наверное лучше открыть отдельную темку для обсуждения KEdit, если конечно планируется дальше её развивать.
С классами (В SCO) конечно удобнее, но если вручную их писать одному человеку получится очередной долгострой как классы к SB (которые так и не были доделаны за 5 лет существования). IMHO, безполезно, если определены только часть полей, а не все...У меня такое предложение. Вместо однократного объявления в interface: ... определить классы Player, Ped, Vehicles, и т.д., опубликовать функции:
Сообщение отредактировал VcSaJen: 20 November 2009 - 04:48
#150
Отправлено 09 February 2010 - 06:40
1) Функция SetMissionFlag во-первых, только включает режим миссии, но не выключает, во-вторых в игре всё равно можно сохраниться или запустить другую миссию. Как нормально включить/отключить режим миссии? В OpenIV есть описание глобальной переменной g_OnMision, но она никак не используется в оригинальных миссиях.
2) Как вывести заголовок миссии? Есть функция SetMsgForLoadingScreen, но она только ставит запись посередине экрана маленьким шрифтом и в углу появляется кнопка OK.
3) Как отправить игроку SMS-сообщение? По всему видимому, за это отвечает скриптовая функция:
function sub_36b2(var0)
{
auto var3, var4, var5, var6, var7, var8, var9, var10;
var4 = 0;
strcpy(&var5, 16, "TM_NAME_");
if (G[91].v135)
{
return 0;
}
else if (G[569][G[569] - 1 * 6].v0[0] != -1)
{
if (!sub_36f8())
{
sub_aee(0);
}
}
if (*(var0 + 24) != -1)
{
return 0;
}
else
{
var9 = sub_3777(*(var0 + 0).v0, *(var0 + 0).v1, *(var0 + 0).v2, *(var0 + 0).v3, *(var0 + 0).v4, *(var0 + 0).v5);
if (var9 != -1)
{
sub_aee(var9);
}
var3 = 0;
while (var3 <= (G[569] - 1))
{
if (G[569][var3 * 6].v0[0] == -1)
{
G[569][var3 * 6].v0 = *(var0 + 0).v0;
G[569][var3 * 6].v1 = *(var0 + 0).v1;
G[569][var3 * 6].v2 = *(var0 + 0).v2;
G[569][var3 * 6].v3 = *(var0 + 0).v3;
G[569][var3 * 6].v4 = *(var0 + 0).v4;
G[569][var3 * 6].v5 = *(var0 + 0).v5;
*(var0 + 24) = var3;
var3 = G[569];
var4 = var4 + 1;
if (var4 > 1)
{
SET_PHONE_HUD_ITEM(1, "UNREAD_MESSAGES", var4);
}
else
{
strcati(&var5, 16, sub_9d0(0, *(var0 + 0).v0, *(var0 + 0).v1, *(var0 + 0).v2, *(var0 + 0).v3, *(var0 + 0).v4, *(var0 + 0).v5));
SET_PHONE_HUD_ITEM(1, &var5, var4);
}
G[91].v130 = 1;
PLAY_AUDIO_EVENT("MOBILE_PHONE_SMS_RECIEVE");
if (G[555] == 9)
{
G[91].v101 = 1015;
}
else if (G[91].v0 == 1014)
{
G[91].v23 = 1;
}
INCREMENT_INT_STAT_NO_MESSAGE(300, 1);
G[15654][17] = 1;
}
else if (sub_9d0(4, G[569][var3 * 6].v0, G[569][var3 * 6].v1, G[569][var3 * 6].v2, G[569][var3 * 6].v3, G[569][var3 * 6].v4, G[569][var3 * 6].v5) == 0)
{
var4 = var4 + 1;
}
var3 = var3 + 1;
}
SET_MESSAGES_WAITING(1);
return 1;
}
}
она присутствует во всех скриптах, отправляющих SMS игроку.Но при попытке переписать её для Delphi я попал в сеть перекрёстных вызовов функций.
4) Что означает в декомпиляторе OpenIV код:
Var1 + 8 + 0 = Var1 + 8 + 0 - 24;Возможно, правильнее будет:
*(&Var1 + 8 + 0) := *(&Var1 + 8 + 0) - 24;или
*(Var1 + 8 + 0) := *(Var1 + 8 + 0) - 24;Или что имелось ввиду?
Некоторый код в OpenIV отличается от SparkIV:
Local[701][8(3)] в SparkIV декомпилирует как L[701][8 * 3]
Ещё пара: Var3 + 0[0(1)] в SparkIV превращается в &((*(var2 + 0))[0])
Это недоработки?
5) Как сделать так, чтобы в такси можно было выбрать иконку добавленной миссии?
6) Как скрипту-плагину перехватить управление за миг до начала записи сохранения? (Что-бы до сохранения удалить объекты Ext-скрипта)
7) Кодировка русских букв в версии 1.0.0.4 поменялась или нет?
8) Как загрузить WTD и вывести текстуру на экран? DrawBox и TextDraw прекрасно рисуется, а текстуры нет. Пробовал загружать по-обычному и через StreamedTxd - не рисуется.
P.S. Полезный совет: когда вы пишете миссии в Delphi, надо контролировать, умер ли игрок или арестован и немедленно прекратить миссию при этом. Проще всего это сделать так:
uses
ScriptNatives,
ScriptTypes,
ScriptUseful,
SysUtils;
type
EPlayerDead=class(Exception);
{...}
procedure Mission;
procedure Wait(Time: Cardinal);
var t1,t2: Cardinal; t: integer;
begin
if Time<60 then
begin
ScriptNatives.Wait(Time);
if not IsPlayerPlaying(playerId) then
begin
raise EPlayerDead.Create('Player dead or arrested!');
end;
Exit;
end;
GetGameTimer(@t1);
t:=0;
while Cardinal(Abs(t))<Time do
begin
ScriptNatives.Wait(1);
GetGameTimer(@t2);
t:=t2-t1;
if not IsPlayerPlaying(playerId) then
begin
raise EPlayerDead.Create('Player dead or arrested!');
end;
end;
end;
begin
try
try
{...Здесь пишем код миссии...}
finally
{Очистка}
end;
except
on EPlayerDead do
begin
{Действия при провале}
Exit;
end;
end;
end;
{...}
Ещё совет: что-бы не перезапускать GTA каждый раз при изменении ext-скрипта, создайте файл clear.bat в папке Alice со следующим содержанием:
del MyScript.~ext ren MyScript.ext MyScript.~extвместо MyScript нужно подставить имя скрипта. Перед компиляцией нужно запустить этот bat'ник.
#151
Отправлено 14 February 2010 - 13:35
1) Функция SetMissionFlag во-первых, только включает режим миссии, но не выключает, во-вторых в игре всё равно можно сохраниться или запустить другую миссию. Как нормально включить/отключить режим миссии? В OpenIV есть описание глобальной переменной g_OnMision, но она никак не используется в оригинальных миссиях.
Для каждой миссии, используется отдельный скрипт, запущенный в отдельном потоке.
Флаг того, это mission script - выставляется во внутреннем поле структуры потока.
Еще одна иллуюстрация:3) Как отправить игроку SMS-сообщение? По всему видимому, за это отвечает скриптовая функция:
она присутствует во всех скриптах, отправляющих SMS игроку.
Но при попытке переписать её для Delphi я попал в сеть перекрёстных вызовов функций.
074:00000627: ---- Function (1/10) {
v_4 = 0;
v_5 = "T1_NAME_" /*[16]*/;
if ((g_15._f21C))
return 0;
if ((g_1f2[/*6*/ (g_1f2)-1]._f0[/*1*/ 0])!=-1)
if (!sub_66b ())
sub_798 (0);
if (((v_0)._f18)!=-1)
return 0;
v_9 = sub_86d ({((v_0)._f0/* 6 */)});
if ((v_9)!=-1)
sub_798 ((v_9));
v_3 = 0;
while ((v_3)<=(g_1f2)-1) {
if ((g_1f2[/*6*/ (v_3)]._f0[/*1*/ 0])==-1) {
g_1f2[/*6*/ (v_3)] = {((v_0)._f0/* 6 */)}/* 6 */;
(v_0)._f18 = (v_3);
v_3 = (g_1f2);
v_4 = (v_4)+1;
if ((v_4)>1) {
$SET_PHONE_HUD_ITEM ({1, "UNREAD_MESSAGES", (v_4)});
} else {
v_5 += sub_691 ({0, ((v_0)._f0/* 6 */)})/*S:[16]:I*/;
$SET_PHONE_HUD_ITEM ({1, v_5, (v_4)});
}
g_15._f208 = 1;
$PLAY_AUDIO_EVENT ("MOBILE_PHONE_SMS_RECIEVE");
if ((g_1e5)==9) {
g_15._f194 = 1016;
} else
if ((g_15._f0)==1015)
g_15._f5C = 1;
$INCREMENT_INT_STAT_NO_MESSAGE ({300, 1});
g_3d24[/*1*/ 2] = 1;
} else
if (sub_691 ({4, (g_1f2[/*6*/ (v_3)]/* 6 */)})==0)
v_4 = (v_4)+1;
v_3 = (v_3)+1;
}
$SET_MESSAGES_WAITING (1);
return 1;
}
4) Что означает в декомпиляторе OpenIV код:
Var1 + 8 + 0 = Var1 + 8 + 0 - 24;Возможно, правильнее будет:
*(&Var1 + 8 + 0) := *(&Var1 + 8 + 0) - 24;или
*(Var1 + 8 + 0) := *(Var1 + 8 + 0) - 24;Или что имелось ввиду?
Правильнее будет: var1._f8._f0 -= 24;
А указателей там нет, как явления. Только ссылки.
Некоторый код в OpenIV отличается от SparkIV:
Local[701][8(3)] в SparkIV декомпилирует как L[701][8 * 3]
Ещё пара: Var3 + 0[0(1)] в SparkIV превращается в &((*(var2 + 0))[0])
Это недоработки?
В целом, да. От того, что нормальных описаний типов нет.
Spark пишет для массива смещние в байтах. Open - как и положено, индекс. (и указывает в скобках размер элемента).
Конструкция вида var3+0[0(1)] - предположительно имелась в виду var3.length
Это как-то связано с блипами. Предположительно, нужно добавить блип соответствующего типа.5) Как сделать так, чтобы в такси можно было выбрать иконку добавленной миссии?
А этого делать не надо. Нужно выставлять потоку этого скрипта флаг DONT_SAVE6) Как скрипту-плагину перехватить управление за миг до начала записи сохранения? (Что-бы до сохранения удалить объекты Ext-скрипта)
Я не видел русскую кодировку до этого. В 1.0.0.4 - UTF87) Кодировка русских букв в версии 1.0.0.4 поменялась или нет?
Вот, что вспомнил.
С остальным попробую разобраться, как будет свободная минутка.
#152
Отправлено 17 February 2010 - 01:51
Я скрипчу на Alice *.EXT плагины-скрипты. А там хотя скрипты не сохраняются, но всё, что было создано скриптом, сохраняется при сохранении. Т.е. например скрипт создал три маркера, а затем если сохраниться-загрузиться, то будет уже шесть маркеров (три сохранились, а три создались заново).6) Как скрипту-плагину перехватить управление за миг до начала записи сохранения? (Что-бы до сохранения удалить объекты Ext-скрипта)
А этого делать не надо. Нужно выставлять потоку этого скрипта флаг DONT_SAVE
А для выставления этого флага есть только функция THIS_SCRIPT_SHOULD_BE_SAVED() без параметров (не работающая в Alice).
И ещё насчёт режима миссии: как всё таки он переключается? (когда значки других миссий скрываются и нельзя сохраниться)
#153
Отправлено 18 February 2010 - 16:15
Как бы сделать красиво случайную выборку константы из перечисления?
enum eWeather
{
WEATHER_EXTRA_SUNNY,
WEATHER_SUNNY,
WEATHER_SUNNY_WINDY,
WEATHER_CLOUDY,
WEATHER_RAINING,
WEATHER_DRIZZLE,
WEATHER_FOGGY,
WEATHER_LIGHTNING,
WEATHER_EXTRA_SUNNY_2,
WEATHER_SUNNY_WINDY_2,
};
А то только всякое непотребство в голову лезет типа:
...
int rnd = (double)rand()/(RAND_MAX+1)*9;
switch(rnd)
{
case 0:
weather = WEATHER_EXTRA_SUNNY;
break;
case 1:
weather = WEATHER_SUNNY;
break;
case 2:
weather = WEATHER_SUNNY_WINDY;
break;
case 3:
weather = WEATHER_CLOUDY;
break;
case 4:
weather = WEATHER_RAINING;
break;
case 5:
weather = WEATHER_DRIZZLE;
break;
case 6:
weather = WEATHER_FOGGY;
break;
case 7:
weather = WEATHER_LIGHTNING;
break;
case 8:
weather = WEATHER_EXTRA_SUNNY_2;
break;
case 9:
weather = WEATHER_SUNNY_WINDY_2;
break;
}
ForceWeatherNow(weather);
SetSyncWeatherAndGameTime(1);
...
#154
Отправлено 18 February 2010 - 17:18
#155
Отправлено 24 February 2010 - 00:56
Можно, я уже написал гоночную миссию.полноценные миссии на данный момент писать в гта4 можно?
Если ты умеешь программировать, то есть для Delphi - Alice от Alexander'a, для С++ - С++ Script Hook от Aru, и для C# .NET Script Hook.я не следил за этим. просто скажите да\нет и дайте ссыль на прогу. если вам не сложно
#157
Отправлено 04 March 2010 - 04:16
#158
Отправлено 04 March 2010 - 09:08
Делается, но неспешно и вялотекуще.
Если в жизни не будет никаких резких перемен, где-то через месяц будет закрытая бета.
#160
Отправлено 06 March 2010 - 05:59
Исходники:
RaCon.dpr
library RaCon; {$R *.res} {$E ext}
uses
ScriptNatives,
ScriptTypes,
ScriptUseful,
SysUtils,
ClipBrd,
Windows,
Math,
UnitRacesClass in 'UnitRacesClass.pas';
{$DEFINE DEBUG}
const
Rus ='АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя';
EncodedRus='ЋЏђ‘’“”•–—™љ›њќћџ ЎўЈ¤Ґ¦§Ё©Є«¬®Ї°±Ііґµ¶·ё№є»јЅѕїАБВГДЕЖЗИЙКЛМН';
function EncodeRus(const text: string): string;
var I,p: Integer;
begin
Result:=Text;
for I:=1 to Length(Result) do
begin
if Result[i]='ё' then Result[i]:='е';
if Result[i]='Ё' then Result[i]:='Е';
p:=pos(Result[i], Rus);
if p>0 then Result[i]:=EncodedRus[p];
end;
end;
function DecodeRus(const text: string): string;
var I,p: Integer;
begin
Result:=Text;
for I:=1 to Length(Result) do
begin
p:=pos(Result[i], EncodedRus);
if p>0 then Result[i]:=Rus[p];
end;
end;
procedure ShowText(text: string; time: integer = 5000);
begin
PrintStringWithLiteralStringNow('string', PChar(EncodeRus(text)), time, 1);
end;
function Round(X: Extended): Int64;
begin
Result:=System.Round(X);
end;
type
EPlayerDead=class(Exception);
TVector3=record
X,Y,Z: Single;
end;
TDynIntArray=array of Integer;
//Массивы миссии
var
RaceCars: array of Cardinal;
Drivers: array of Cardinal;
RaceNames: array of string;
RaceFinishTimes: array of Cardinal;
ModelHashs: array of Cardinal;
Checkpoints: array of TVector3;
CarCurCP: array of Integer;
RiderBlips: array of Cardinal;
CarInOutR: array of Boolean;
procedure main(); export;
const
AngleStep=15.0;
var
{
Car, DM: Cardinal;
XForce,YForce: Single;
CurForce: Single;
I: Integer;
D0,D1,D2,D3,D4: Integer;}
X,Y,Z,Angle: Single;
PlayerId : i32;
PlayerChar : Ped;
procedure Mission(Id: Integer);
procedure Wait(Time: Cardinal);
var t1,t2: Cardinal; t: integer;
begin
if Time<60 then
begin
ScriptNatives.Wait(Time);
if not IsPlayerPlaying(playerId) then
begin
raise EPlayerDead.Create('Player dead or arrested!');
end;
Exit;
end;
GetGameTimer(@t1);
t:=0;
while Cardinal(Abs(t))<Time do
begin
ScriptNatives.Wait(1);
GetGameTimer(@t2);
t:=t2-t1;
if not IsPlayerPlaying(playerId) then
begin
raise EPlayerDead.Create('Player dead or arrested!');
end;
end;
end;
{const
ModelsCount=3;
Models: array [0..ModelsCount-1] of string
= ('infernus',
'banshee',
'comet');}
//Массивы миссии см. выше
var
I: Integer;
N: Integer;
CPMarker: Cardinal;
CPBlip, CPNextBlip: Cardinal;
CPType: Integer;
B{, PlInCar}: boolean;
function CompareCars(Index1, Index2: Integer): Integer;
var
dist1, dist2: Single;
X,Y,Z: Single;
begin
Result:=CompareValue(CarCurCP[Index1], CarCurCP[Index2]);
if Result=0 then
begin
if CarCurCP[Index1]>High(Checkpoints) then
begin
Result:=-CompareValue(RaceFinishTimes[Index1],
RaceFinishTimes[Index2]);
end else
begin
GetCarCoordinates(RaceCars[Index1],@X,@Y,@Z);
GetDistanceBetweenCoords3D(Checkpoints[CarCurCP[Index1]].X,
Checkpoints[CarCurCP[Index1]].Y,
Checkpoints[CarCurCP[Index1]].Z,
X, Y, Z, @dist1);
GetCarCoordinates(RaceCars[Index2],@X,@Y,@Z);
GetDistanceBetweenCoords3D(Checkpoints[CarCurCP[Index2]].X,
Checkpoints[CarCurCP[Index2]].Y,
Checkpoints[CarCurCP[Index2]].Z,
X, Y, Z, @dist2);
Result:=-CompareValue(dist1,dist2);
end;
end;
Result:=-Result;
end;
function GetRacersPos: TDynIntArray;
var
Size: Integer;
k: integer; // текущий элемент массива
i: integer; // индекс для ввода и вывода массива
changed: boolean; // TRUE, если в текущем цикле были обмены
buf: integer; // буфер для обмена элементами массива
begin
Size:=Length(RaceCars);
SetLength(Result, Size);
for I:=0 to Size-1 do
begin
Result[I]:=I;
end;
//Сортировка
repeat
Changed:=FALSE; // пусть в текущем цикле нет обменов
for k:=0 to SIZE-2 do
begin
if CompareCars(Result[k], Result[k+1])=1 then
begin // обменяем k-й и k+1-й элементы
buf := Result[k];
Result[k] := Result[k+1];
Result[k+1] := buf;
changed := TRUE;
end;
end;
until not changed; // если не было обменов, значит
// массив отсортирован
end;
function GetMetresToFinish(Index: Integer): Single;
var
I, N0: Integer;
X,Y,Z,D: Single;
begin
Result:=0.0;
N0:=CarCurCP[Index];
if N0>High(Checkpoints) then Exit;
GetCarCoordinates(RaceCars[Index],@X,@Y,@Z);
GetDistanceBetweenCoords3D(X,Y,Z,Checkpoints[N0].X,
Checkpoints[N0].Y,
Checkpoints[N0].Z,
@D);
Result:=D;
for I:=N0 to High(Checkpoints)-1 do
begin
GetDistanceBetweenCoords3D(Checkpoints[I].X,
Checkpoints[I].Y,
Checkpoints[I].Z,
Checkpoints[I+1].X,
Checkpoints[I+1].Y,
Checkpoints[I+1].Z,
@D);
Result:=Result+D;
end;
{Windows.Beep(2000, 50);
ShowText(IntToStr(N0)+', '+IntToStr(Index));
Wait(0);
Sleep(1000);}
end;
function GetBehindInMetres(Index: Integer): string;
var G: Integer;
begin
if Index=0 then
begin
Result:='---';
Exit;
end;
G:=System.Round(GetMetresToFinish(0)-
GetMetresToFinish(Index));
Result:=IntToStr(G);
if G>0 then Result:='+'+Result;
end;
procedure DrawPos;
const
LineH=0.039;
ScaleX=0.18;
StartPos=0.9;
var
Poss: TDynIntArray;
I, Len: Integer;
s: string;
begin
Poss:=GetRacersPos;
Len:=High(RaceCars)+1;
DrawRect(StartPos, 0.2729+(LineH*Len)/2, ScaleX, LineH*Len, 200, 200, 255, 150);
for I:=0 to Len-1 do
begin
SetTextScale(0.40 * 0.75, 0.40);
SetTextColour(240,240,255,255);
SetTextDropshadow(0,0,0,0,0);
SetTextEdge(1,0,0,128,255);
s:='';
if Poss[I]<>0 then
begin
if IsCarDead(RaceCars[Poss[I]]) or IsCharDead(Drivers[Poss[I]]) then
begin
SetTextColour(128,128,128,255);
SetTextEdge(1,64,64,64,255);
//s:=' (Мёртв)';
end;
if CarCurCP[Poss[I]]>High(Checkpoints) then
begin
SetTextColour(198,0,198,255);
//SetTextEdge(1,255,0,128,255);
//s:=' (На финише)';
end;
end;
SetTextDrawBeforeFade(False);
DisplayTextWithLiteralString(StartPos-(ScaleX/2)+0.01, 0.2729+(LineH*I)+(LineH/8),
'string', PChar(EncodeRus(IntToStr(I+1)+'. '+RaceNames[Poss[I]]+s)));
UsePreviousFontSettings;
DisplayTextWithLiteralString(StartPos+(ScaleX/2)-0.05, 0.2729+(LineH*I)+(LineH/8),
'string', PChar(GetBehindInMetres(Poss[I])));
//Windows.Beep(2000, 100);
//Sleep(500);
SetSpritesDrawBeforeFade(False);
if Poss[I]=0 then
DrawRect(StartPos, 0.2729+(LineH*I)+LineH/2, ScaleX, 0.0332, 200, 200, 255, 150);
end;
Poss:=nil;
end;
function GameTimer: Cardinal;
begin
GetGameTimer(@Result);
end;
function IsCarStopped(veh : Vehicle): b8;
begin // Из-за кривого названия в Alice
Result:=IsCarStoppedestrian(veh);
end;
procedure ShowNumber(N: Integer);
function Cube(V: Single): Single;
begin
Result:=V*V*V*V*V;
end;
function S10(V: Single): Single;
begin
Result:=V*V*V*V*V*V*V*V*V*V;
end;
var
LastT: Cardinal;
X,Y,T,Sc,Al: Single;
begin
T:=0;
LastT:=GameTimer;
while T<=1 do
begin
//X:=Cube((T-0.5)*1.53)+0.25+T*0.5;
//Y:=1*Sqr(X-0.5)+0.2;
X:=Cube((T-0.5)*1.8)+0.25+T*0.5;
Y:=1*Sqr(X-0.5)+0.2;
Al:=-S10((X-0.5)*2)+1;
Al:=Al*255;
if Al>255 then Al:=255;
if Al<0 then Al:=0;
Sc:=((1/(T*50+1))-0.1);
if Sc<0 then Sc:=0;
Sc:=Sc+0.1;
SetTextScale(Sc*12.0*0.75, Sc*12.0);
SetTextDropshadow(2, 10,10,10,Round(Al));
SetTextColour(191,234,66,Round(Al));
SetTextCentre(True);
DisplayTextWithNumber(X,Y,'number',N);
T:=T+(GameTimer-LastT)/1500;
LastT:=GameTimer;
Wait(16);
end;
end;
var LastT: Cardinal; T: Single;
procedure TickShowGo(Text: string);
function S10(V: Single): Single;
begin
Result:=V*V*V*V*V*V*V*V*V*V;
end;
var
Sc,Al: Single;
begin
if T<=1 then
begin
//SetTextDropshadow(0, 0,0,0,0);
SetTextCentre(True);
Al:=-S10((T-0.5)*2)+1;
Al:=Al*255;
if Al>255 then Al:=255;
if Al<0 then Al:=0;
Sc:=-5*T+1;
if Sc<0 then Sc:=0;
Sc:=Sc+0.1;
SetTextScale(Sc*12.0*0.75, Sc*12.0);
SetTextColour(191,234,66 ,Round(Al));
SetTextDropshadow(2, 10,10,10,Round(Al));
DisplayTextWithLiteralString(0.5,0.4,'string',PChar(EncodeRus(Text)));
T:=T+(GameTimer-LastT)/1500;
LastT:=GameTimer;
end;
end;
var LastUpsidedown{,Temp}: Integer;
const P1=1;P2=0;P3=3;P4=10;
{1 0 3 10}
begin
with Ra[Id].Environment do
begin
//DONE: Доделать погоду и окружение
if EnableWeather then
ForceWeather(Weather);
if EnableTime then
SetTimeOfDay(Hours, Minutes);
SetCarDensityMultiplier(TrafficDensity);
SetPedDensityMultiplier(PedsDensity);
end;
SetLength(CheckPoints, Ra[Id].CPsCount);
for N:=0 to Ra[Id].CPsCount-1 do
begin
CheckPoints[N].X:=Ra[Id].CPs[N].Pos.X;
CheckPoints[N].Y:=Ra[Id].CPs[N].Pos.Y;
CheckPoints[N].Z:=Ra[Id].CPs[N].Pos.Z;
end;
SetLength(ModelHashs, Ra[Id].UsedModelsCount);
for I:=0 to Ra[Id].UsedModelsCount-1 do
begin
ModelHashs[I]:=Ra[Id].UsedModels[I];
end;
CPMarker:=0;
try
try
SetLength(RaceCars, Ra[Id].RacersCount);
SetLength(Drivers, Ra[Id].RacersCount);
SetLength(CarCurCP, Ra[Id].RacersCount);
SetLength(RiderBlips,Ra[Id].RacersCount);
SetLength(RaceNames, Ra[Id].RacersCount);
SetLength(RaceFinishTimes,Ra[Id].RacersCount);
SetLength(CarInOutR, Ra[Id].RacersCount);
for I:=0 to Ra[Id].RacersCount-1 do
begin
RaceNames[I]:=Ra[Id].Racers[I].RacerName;
end;
for i:=0 to High(ModelHashs) do
RequestModel(ModelHashs[I]);
LoadAllObjectsNow;
for I:=0 to High(RaceCars) do
with Ra[Id].Racers[I] do
begin
CarCurCP[I]:=0;
CarInOutR[I]:=False;
CreateCar(GetHashKey(PChar(CarModel)), StartPos.X, StartPos.Y, StartPos.Z, @RaceCars[I], True);
if ColorEnabled then
begin
ChangeCarColour(RaceCars[I], CarColor1, CarColor2);
end;
SetCarHeading(RaceCars[I], StartAngle);
with CarProofs do
SetCarProofs(RaceCars[I],BP,FP,EP,CP,MP);
//if I<>0 then
// SetVehicleSteerBias(RaceCars[I],SteerBias);
LockCarDoors(RaceCars[I],DoorState);
FreezeCarPosition(RaceCars[I],true);
AddBlipForCar(RaceCars[I], @RiderBlips[I]);
ChangeBlipScale(RiderBlips[I], 0.6);
end;
SetBlipAsFriendly(RiderBlips[0], true);
ChangeBlipScale(RiderBlips[0], 1.0);
ChangeBlipDisplay(RiderBlips[0], 0);
WarpCharIntoCar(PlayerChar, RaceCars[0]);
{$IFDEF DEBUG}
//SetCharAllAnimsSpeed(PlayerChar,2.0);
//SetCharMoveAnimSpeedMultiplier(PlayerChar,0.3);
//SetCharGravity(PlayerChar,5E-15);
{$ENDIF}
for I:=1 to High(RaceCars) do
begin
CreateRandomCharAsDriver(RaceCars[I],@Drivers[I]);
SetCharGetOutUpsideDownCar(Drivers[I],false);
//AddStuckCarCheckWithWarp(RaceCars[I], 1.0, 2000, true, true, true, Boolean(-1));
//AddUpsideDownCarCheck(RaceCars[I]);
SetBlipAsShortRange(RiderBlips[I], True);
end;
CPMarker:=CreateCheckpoint(2,CheckPoints[0].X,
CheckPoints[0].Y,
CheckPoints[0].Z+1.0,
CheckPoints[1].X,
CheckPoints[1].Y,
CheckPoints[1].Z,
1.0);
AddBlipForCoord(CheckPoints[0].X,CheckPoints[0].Y,CheckPoints[0].Z,@CPBlip);
AddBlipForCoord(CheckPoints[1].X,CheckPoints[1].Y,CheckPoints[1].Z,@CPNextBlip);
ChangeBlipScale(CPNextBlip,0.6);
DimBlip(CPNextBlip,True);
SetCamBehindPed(PlayerChar);
DoScreenFadeIn(750);
Wait(750);
{PlayAudioEvent('FRONTEND_OTHER_RACE_321');
PrintWithNumberBig('NUMBER', 3, 1000, true);
Wait(1000);
PlayAudioEvent('FRONTEND_OTHER_RACE_321');
PrintWithNumberBig('NUMBER', 2, 1000, true);
Wait(1000);
PlayAudioEvent('FRONTEND_OTHER_RACE_321');
PrintWithNumberBig('NUMBER', 1, 1000, true);
Wait(1000);}
ShowNumber(3);
ShowNumber(2);
ShowNumber(1);
PlayAudioEvent('FRONTEND_OTHER_RACE_GO');
for I:=1 to High(RaceCars) do
begin
TaskCarDriveToCoord(Drivers[I],RaceCars[I],
CheckPoints[0].X,
CheckPoints[0].Y,
CheckPoints[0].Z,
Ra[Id].CPs[0].Speed, P1, P2, P3, Ra[Id].CPs[0].Radius, P4);
end;
for I:=0 to High(RaceCars) do
begin
FreezeCarPosition(RaceCars[I], False);
end;
LastUpsidedown:=GameTimer;
LastT:=GameTimer;
T:=0;
while true do
begin
TickShowGo('Старт!');
for I:=1 to High(RaceCars) do
begin
with Ra[Id].CPs[CarCurCP[I]] do
if LocateCar3D(RaceCars[I],
CheckPoints[CarCurCP[I]].X,
CheckPoints[CarCurCP[I]].Y,
CheckPoints[CarCurCP[I]].Z,
Radius, Radius, Radius, False) then
begin
Inc(CarCurCP[I]);
CarInOutR[I]:=False;
//ClearCharTasks(Drivers[I]);
if CarCurCP[I]<=High(CheckPoints) then
begin
TaskCarDriveToCoord(Drivers[I],RaceCars[I],
CheckPoints[CarCurCP[I]].X,
CheckPoints[CarCurCP[I]].Y,
CheckPoints[CarCurCP[I]].Z,
Speed, P1, P2, P3, Radius, P4);
SetCarForwardSpeed(RaceCars[I], 20.0);
end
else begin
if RaceFinishTimes[I]=0 then RaceFinishTimes[I]:=GameTimer;
CarCurCP[I]:=High(CheckPoints)+1;
end
end;
{if LocateCar3D(RaceCars[I],
CheckPoints[CarCurCP[I]].X,
CheckPoints[CarCurCP[I]].Y,
CheckPoints[CarCurCP[I]].Z,
50.0, 50.0, 50.0, False) then
begin
end;}
end;
{DONE: При взрыве машины игрока - провал}
{DONE: Если гонщик взорвался, то прибавть к имени (Умер)}
{DONE: Если гонщик финишировал, то прибавть к имени (---)}
{DONE: Сделать счётчик как в NFS:MW}
{DONE: Сделать показ расстояния отставания/опережения}
{DONE: Сделать так, чтобы при финишировании оставался порядок (массив вреиён финиширования)}
if IsCarDead(RaceCars[0]) then
begin
ShowText('~r~Вы остались без машины!');
raise EPlayerDead.Create('CarDead');
end;
if IsCarUpsidedown(RaceCars[0]) and
IsCharInCar(PlayerChar, RaceCars[0]) then
begin
if ((GameTimer-LastUpsidedown) > 5000) then
begin
SetPlayerControl(PlayerId, False);
DoScreenFadeOut(2500);
while IsScreenFading do Wait(50);
GetCarCoordinates(RaceCars[0], @X, @Y, @Z);
GetClosestCarNodeWithHeading(X,Y,Z,@X,@Y,@Z,@Angle);
SetCarCoordinates(RaceCars[0], X, Y, Z);
SetCarHeading(RaceCars[0], Angle);
DoScreenFadeIn(750);
SetPlayerControl(PlayerId, True);
end
end else LastUpsidedown:=GameTimer;
if not IsCharInCar(PlayerChar, RaceCars[0]) then
begin
AddNextMessageToPreviousBriefs(False);
ShowText('Сядьте в ~b~автомобиль',100);
ChangeBlipDisplay(RiderBlips[0],2);
end else
if LocateCar3D(RaceCars[0],
CheckPoints[CarCurCP[0]].X,
CheckPoints[CarCurCP[0]].Y,
CheckPoints[CarCurCP[0]].Z,
10.0, 10.0, 10.0, False) then
begin
ChangeBlipDisplay(RiderBlips[0],0);
Inc(CarCurCP[0]);
DeleteCheckpoint(CPMarker);
PlayAudioEvent('FRONTEND_GAME_PICKUP_CHECKPOINT');
if CarCurCP[0]>High(CheckPoints) then
begin
B:=true;
for I:=1 to High(RaceCars) do
begin
B:=B and (CarCurCP[I]<High(CheckPoints)+1);
end;
if B then
begin
AddScore(playerId, 12000);
TriggerMissionCompleteAudio(1);
ShowText('Вы победили!');
end else ShowText('~r~Вы проиграли.');
Break;
end;
if CarCurCP[0]=High(CheckPoints)
then CPType:=3
else CPType:=2;
CPMarker:=CreateCheckpoint(CPType,
CheckPoints[CarCurCP[0]].X,
CheckPoints[CarCurCP[0]].Y,
CheckPoints[CarCurCP[0]].Z+1.0,
CheckPoints[CarCurCP[0]+1].X,
CheckPoints[CarCurCP[0]+1].Y,
CheckPoints[CarCurCP[0]+1].Z,
1.0);
RemoveBlip(CPBlip);
RemoveBlip(CPNextBlip);
AddBlipForCoord(CheckPoints[CarCurCP[0]].X,
CheckPoints[CarCurCP[0]].Y,
CheckPoints[CarCurCP[0]].Z,
@CPBlip);
if CarCurCP[0]=High(CheckPoints) then
ChangeBlipSprite(CPBlip, 65);
if CarCurCP[0]<High(CheckPoints) then
begin
AddBlipForCoord(CheckPoints[CarCurCP[0]+1].X,
CheckPoints[CarCurCP[0]+1].Y,
CheckPoints[CarCurCP[0]+1].Z,
@CPNextBlip);
if (CarCurCP[0]+1)=High(CheckPoints) then
ChangeBlipSprite(CPNextBlip, 65);
ChangeBlipScale(CPNextBlip,0.6);
DimBlip(CPNextBlip,True);
end;
end;
DrawPos;
Wait(1);
end;
finally
SetCarDensityMultiplier(1.0);
SetPedDensityMultiplier(1.0);
DeleteCheckpoint(CPMarker);
RemoveBlip(CPBlip);
RemoveBlip(CPNextBlip);
for i:=0 to High(ModelHashs) do
MarkModelAsNoLongerNeeded(ModelHashs[I]);
for I:=1 to High(RaceCars) do
begin
//RemoveStuckCarCheck(RaceCars[I]);
//RemoveUpsidedownCarCheck(RaceCars[I]);
MarkCarAsNoLongerNeeded(@RaceCars[I]);
MarkCharAsNoLongerNeeded(@Drivers[I]);
RemoveBlip(RiderBlips[I]);
end;
MarkCarAsNoLongerNeeded(@RaceCars[0]);
RemoveBlip(RiderBlips[0]);
ReleaseWeather;
Finalize(RaceCars );
Finalize(Drivers );
Finalize(RaceNames );
Finalize(RaceFinishTimes);
Finalize(ModelHashs );
Finalize(Checkpoints );
Finalize(CarCurCP );
Finalize(RiderBlips );
Finalize(CarInOutR );
end;
except
on EPlayerDead do
begin
Exit;
end;
end;
end;
var
//Font: Cardinal;
WTD, MyTexture,r: cardinal;
{t1,t2:cardinal;
t: Integer;}
F: TextFile;
//rChar: Cardinal;
//x2,y2,z2,d: Single;
Hash,hash2,Car,ped: Cardinal;
I: Integer;
blips: array of Cardinal;
var
MemInfo: TMemoryBasicInformation;
ModName: array[0..MAX_PATH] of Char;
S: string;
begin
Wait(2000);
try
//TODO: Добавить время отставанья/опереженья
AssignFile(F, 'coords.log');
Rewrite(F);
CloseFile(F);
Ra:=TRaces.Create('Alice\RaCon');
SetLength(blips, ra.Count);
//ShowText('Count='+IntToStr(ra.Count));
//Wait(5000);
for I:=0 to Ra.Count-1 do
begin
//ShowText('(blips)I='+IntToStr(I), 2000);
//Wait(2000);
with Ra[I].General.BlipPos do
AddBlipForContact(X, Y, Z, @(Blips[I]));
ChangeBlipSprite(Blips[I], Ra[I].General.BlipSprite);
ChangeBlipDisplay(Blips[I], 2);
ChangeBlipNameFromAscii(Blips[I], PChar(EncodeRus(Ra[I].General.RaceName)));
end;
//2
//3-только на общей карте
//4
//5-только на радаре
while True do
begin
PlayerId := GetPlayerId();
if PlayerId >= 0 then
if IsPlayerPlaying(PlayerId) then
if PlayerHasChar(PlayerId) then
begin
GetPlayerChar(PlayerId, @PlayerChar);
if PlayerChar > 0 then
begin
{$IFDEF DEBUG}
//SetCarDensityMultiplier(0.0);
//SetPedDensityMultiplier(0.0);
//SetRandomCarDensityMultiplier(0.0);
//SetParkedCarDensityMultiplier(10.0);
SetCharProofs(PlayerChar,true,false,false,false,true);
ClearWantedLevel(playerId);
{$ENDIF}
for I := 0 to Ra.Count-1 do
with Ra[I].General do
begin
//ShowText('(Ra)I='+IntToStr(I),2000);
//Wait(2000);
DrawColouredCylinder(BlipPos.X, BlipPos.Y, BlipPos.Z, 2.5, 2.5, MarkerColor.Red, MarkerColor.Green, MarkerColor.Blue, 255);
if LocateCharAnyMeans3D(PlayerChar, BlipPos.X, BlipPos.Y, BlipPos.Z, 2.5, 2.5, 2.5, False) then
begin
{TODO: Узнать, как делается запись вместо Загрузки}
{TODO: Узнать, как нормально поставить флаг миссии}
{TODO: Поставить PTFX на старте как в Most Wanted}
//SetMsgForLoadingScreen('M_43');
//Hash:=5 div Round(Sin(0));
//Hash:=ScriptNatives.Round(-1.0);
//ShowText(IntToStr(Hash));
//PInteger($DDDDDDDD)^:=-1;
//hash:=GetHashKey('admiral');
//RequestModel(hash);
//LoadAllObjectsNow;
//GetOffsetFromCharInWorldCoords(PlayerChar,0.0,3.0,0.0,@X,@Y,@Z);
//for hash2:=0 to 100 do CreateCar(hash, X, Y, Z+1.0, @Car, False);
DoScreenFadeOut(750);
while IsScreenFading do Wait(50);
SetMissionFlag(True);
PCardinal(GetGlobalsArray+10978*4)^:=1;
Mission(I);
PCardinal(GetGlobalsArray+10978*4)^:=0;
SetMissionFlag(False);
Break;
end;
end;
if KeyPressed(Ord('I')) then
begin
Append(F);
GetCharCoordinates(PlayerChar, @X,@Y,@Z);
DecimalSeparator:='.';
//Format('%.4f, %.4f, %.4f', [X,Y,Z])
Clipboard.AsText:=FloatToStr(X)+', '+FloatToStr(Y)+', '+FloatToStr(Z)+', ';
WriteLn(F,X:1:4,', ',Y:1:4,', ',Z:1:4,', ');
ShowText('Скопировано.',1000);
CloseFile(F);
end;
{$IFDEF DEBUG}
if KeyPressed(Ord('U')) then
begin
GetCharHeading(PlayerChar,@Angle);
//GetCharCoordinates(PlayerChar,@x,@y,@z);
Windows.Beep(200,20);
//if GetClosestChar(X,Y,Z,10.0, 1, 1, @rChar) then
//begin
//GetCharCoordinates(rChar,@x2,@y2,@z2);
//GetDistanceBetweenCoords3D(X,Y,Z,x2,y2,z2,@d);
Angle:=Angle+90.0;
X:=ScriptNatives.Cos(Angle)*5.0;
Y:=ScriptNatives.Sin(Angle)*5.0;
Z:=20.0;
//SetCharVelocity(rChar,X2,Y2,Z2);
//ApplyForceToPed(rChar,1,X,Y,Z,0.0,0.0,0.0,1,1,1,10000);
SwitchPedToRagdollWithFall(PlayerChar, 2000, 3000, 0, X, Y, Z, 50.0, 0.0,0.0,0.0,0.0,0.0,0.0);
// Windows.Beep(5000,50);
Wait(200);
//end;
end;
if KeyPressed(Ord('J')) then
begin
hash:=GetHashKey('admiral');
hash2:=GetHashKey('ig_Gordon');
GetOffsetFromCharInWorldCoords(PlayerChar,0.0,3.0,0.0,@X,@Y,@Z);
RequestModel(hash);
RequestModel(hash2);
LoadAllObjectsNow;
CreateCar(hash,X,Y,Z,@Car,true);
GetOffsetFromCharInWorldCoords(PlayerChar,1.0,0.0,0.0,@X,@Y,@Z);
CreateChar(5,hash2,X,Y,Z, @Ped, True);
TaskEnterCarAsPassenger(Ped,Car,60000,1);
//TaskEnterCarAsDriver(Ped,Car,60000);
LockCarDoors(Car,6);//1. Открыто
//2. Закрыто
//3. Закрыто только для игрока
//4. Заперто (если внутри, то невозможно выйти)
//5. Открыто?
//6. Открыто?
//7. Закрыто, но можно разбить окно
//8. Закрыто (не оглядывается)
MarkModelAsNoLongerNeeded(hash);
MarkModelAsNoLongerNeeded(hash2);
wait(5000);
//WarpCharIntoCar(PlayerChar,Car);
end;
if KeyPressed(Ord('L')) then
begin
GetScriptRendertargetRenderId(@R);
SetTextRenderId(R);
SetTimerA(0);
wtd:=LoadTxd('Qub3d');
//RequestStreamedTxd('zombie.wtd', true);
Windows.Beep(10000,5);
//LoadAllObjectsNow;
//while not HasStreamedTxdLoaded('zombie.wtd') do
//begin
// Wait(50);
//end;
//MyTexture:=GetTextureFromStreamedTxd('zombie.wtd', 'zlogo.dds');
MyTexture:=GetTexture(wtd, 'QUB3D_LOGO_150906');
//Windows.Beep(10000,50);
//while not IsFontLoaded(Font) do Wait (50);
Windows.Beep(5000,100);
while TimerA<5000 do
begin
//SetTextFont(Font);
DrawSprite(MyTexture, 0.5, 0.5, 0.8, 0.8, 0.0, 255,255,255,255);
DrawCurvedWindow(0.4, 0.4, 0.2, 0.2, 240);
//DrawRect(0.0,0.0, 0.1,0.1, 255,0,0,255);
//DisplayText(0.5, 0.5, 'M_43');
Wait(1);
end;
ReleaseTexture(MyTexture);
RemoveTxd(wtd);
//MarkStreamedTxdAsNoLongerNeeded('zombie.wtd');
Windows.Beep(1000,100);
//Inc(Font);
end;
{$ENDIF}
end;
end;
Wait(50);
end;
except
on E: Exception do
begin
Windows.Beep(100, 100);
Windows.Beep(1600, 100);
Windows.Beep(100, 100);
Windows.Beep(1600, 100);
Windows.Beep(100, 100);
Windows.Beep(1600, 100);
ShowText('-------------------------------',0);
ShowText('или в крайнем случае на ящик VcSaJen@ya.ru',0);
ShowText('Пожалуйста сообщите эти данные автору в темке RaCon на http://forums.gtamodding.ru/',0);
ShowText('Адрес: '+IntToHex(Integer(ExceptAddr),8),0);
ShowText('Адрес Main: '+IntToHex(Integer(@main),8),0);
VirtualQuery(ExceptAddr, MemInfo, SizeOf(MemInfo));
if (MemInfo.State = MEM_COMMIT) and
(GetModuleFileName(THandle(MemInfo.AllocationBase), ModName, SizeOf(ModName)) <> 0) then
begin
S:=ModName;
Delete(S, Pos(GetCurrentDir,S), Length(GetCurrentDir)+1);
//ShowText('Локальный адрес Base: '+IntToHex(Integer(ExceptAddr)-Integer(MemInfo.BaseAddress),8),0);
ShowText('Локальный адрес: '+IntToHex(Integer(ExceptAddr)-(Integer(MemInfo.AllocationBase)+$1000),8),0);
//ShowText('Base: '+IntToHex(Integer(MemInfo.BaseAddress),8),0);
ShowText('Allocation base: '+IntToHex(Integer(MemInfo.AllocationBase),8),0);
ShowText('Модуль: '+S,0);
end
else begin
end;
ShowText(E.Message,0);
ShowText('Класс: '+E.ClassName,0);
ShowText('-------------------------------',0);
ShowText(' Информация об ошибке:',0);
ShowText('-------------------------------',0);
AddNextMessageToPreviousBriefs(False);
ShowText('В RaCon возникла ошибка. Перепишите информацию об ошибке и перезагрузите игру.',5000);
Wait(5000);
{'~r~'+E.ClassName+': '+E.Message}
AddNextMessageToPreviousBriefs(False);
ShowText('Информацию об ошибке смотрите в "Истории" (Briefs) в меню (2-й пункт, сразу после "Карты").',60000);
//Clipboard.AsText:=E.Message;
Exit;
end;
end;
end;
procedure aDLLProc(Reason: Integer);
begin
// if game is ended, destroy the player
if Reason = DLL_PROCESS_DETACH then
begin
Finalize(RaceCars );
Finalize(Drivers );
Finalize(RaceNames );
Finalize(RaceFinishTimes);
Finalize(ModelHashs );
Finalize(Checkpoints );
Finalize(CarCurCP );
Finalize(RiderBlips );
Finalize(CarInOutR );
end;
end;
exports main;
begin
DllProc:=@aDLLProc;
end.
UnitRacesClass.pas
unit UnitRacesClass;
interface
uses SysUtils, IniFiles, Classes, ScriptNatives;
type
TVector3=record
X,Y,Z: Single;
end;
TRot3=TVector3;
TProofs=record
BP,FP,EP,CP,MP: Boolean;
end;
//TPedData=record
// RandomPedModel: Boolean;
// PedModel: string;
// Weapon: Integer;
// PedProofs: TProofs;
//end;
TRacerData=record
RacerName: string;
CarModel: string;
ColorEnabled: Boolean;
CarColor1,CarColor2: Integer;
//Driver: TPedData;
//Passengers: array [0..2] of TPedData;
CarProofs: TProofs;
StartPos: TVector3;
StartAngle: Single;
DoorState: Byte;
SteerBias: Single;
end;
TCPData=record
Pos: TVector3;
Radius: Single;
Speed: Single;
end;
TObjData=record
Model: string;
Pos: TVector3;
Rot: TRot3;
Collision: Boolean;
Indestructible: Boolean;
Freeze: Boolean;
Comment: string;
end;
TRGBColor=record
Red,Green,Blue: Byte;
end;
TGeneralData=record
RaceName: string;
RaceType: Integer;
OftenTimes: Boolean;
Award: Integer;
BlipSprite: Integer;
MarkerColor: TRGBColor;
BlipPos: TVector3;
RequiredPassedCount: Integer;
RequiredPassed: array of string;
NoneIsPassed: Boolean;
end;
TViewData=record
ShowRacersList: Boolean;
end;
TEnvironmentData=record
EnableWeather: Boolean;
Weather: Integer;
EnableTime: Boolean;
Hours: Integer;
Minutes: Integer;
TrafficDensity: Single;
PedsDensity: Single;
end;
TRaces=class;
TRace=class(TObject)
private
//FOwnerRaces: TRaces;
FRacersCount: Integer;
FRacers: array of TRacerData;
FCheckpointsCount: Integer;
FCheckpoints: array of TCPData;
FObjectsCount: Integer;
FObjects: array of TObjData;
FGeneral: TGeneralData;
FView: TViewData;
FEnvironment: TEnvironmentData;
FUsedModels: array of Integer;
FUsedModelsCount: Integer;
function GetCPs(Index: Integer): TCPData;
function GetObjs(Index: Integer): TObjData;
function GetRacers(Index: Integer): TRacerData;
function GetModel(Index: Integer): Integer;
protected
procedure UpgUsedModels;
public
property General: TGeneralData read FGeneral;
property RacersCount: Integer read FRacersCount;
property Racers[Index: Integer]: TRacerData read GetRacers;
property CPsCount: Integer read FCheckpointsCount;
property CPs[Index: Integer]: TCPData read GetCPs;
property ObjsCount: Integer read FObjectsCount;
property Objs[Index: Integer]: TObjData read GetObjs;
property View: TViewData read FView;
property Environment: TEnvironmentData read FEnvironment;
property UsedModelsCount: Integer read FUsedModelsCount;
property UsedModels[Index: Integer]: Integer read GetModel;
constructor Create(FileName: string);
destructor Destroy; override;
procedure Open(FileName: string);
end;
TRaces=class(TObject)
private
FRaces: array of TRace;
FCount: Integer;
function GetRace(Index: Integer): TRace;
public
property Races[Index: Integer]: TRace read GetRace; default;
property Count: Integer read FCount;
constructor Create(Dir: string);
destructor Destroy; override;
procedure Open(Dir: string);
end;
var
Ra: TRaces;
implementation
{ TRace }
constructor TRace.Create(FileName: string);
begin
inherited Create;
Open(FileName);
end;
destructor TRace.Destroy;
begin
Finalize(FRacers);
Finalize(FCheckpoints);
Finalize(FObjects);
Finalize(FUsedModels);
inherited;
end;
function TRace.GetCPs(Index: Integer): TCPData;
begin
Result:=FCheckpoints[Index];
end;
function TRace.GetObjs(Index: Integer): TObjData;
begin
Result:=FObjects[Index];
end;
function TRace.GetRacers(Index: Integer): TRacerData;
begin
Result:=FRacers[Index];
end;
function TRace.GetModel(Index: Integer): Integer;
begin
Result:=FUsedModels[Index];
end;
procedure TRace.Open(FileName: string);
var
Ini: TIniFile;
I, Count: Integer;
S: string;
List: TStringList;
begin
DecimalSeparator:='.';
Ini:=TIniFile.Create(FileName);
List:=TStringList.Create;
with ini do
try
//Общее
with FGeneral do
begin
RaceName:=ReadString('general', 'RaceName', '***НЕ УКАЗАНО***');
RaceType:=ReadInteger('general', 'RaceType', 0);
OftenTimes:=ReadBool('general', 'OftenTimes', False);
Award:=ReadInteger('general', 'Award', 0);
BlipSprite:=ReadInteger('general', 'BlipSprite', 0);
MarkerColor.Red:=ReadInteger('general', 'MarkerColor.Red', 0);
MarkerColor.Green:=ReadInteger('general', 'MarkerColor.Green', 0);
MarkerColor.Blue:=ReadInteger('general', 'MarkerColor.Blue', 0);
BlipPos.X:=ReadFloat('general', 'Blip.X', 0.0);
BlipPos.Y:=ReadFloat('general', 'Blip.Y', 0.0);
BlipPos.Z:=ReadFloat('general', 'Blip.Z', 0.0);
List.CommaText:=ReadString('general', 'RequiredPassed', '');
SetLength(RequiredPassed, List.Count);
RequiredPassedCount:=List.Count;
for I:=0 to List.Count-1 do
begin
RequiredPassed[I]:=List[I];
end;
NoneIsPassed:=ReadBool('general', 'NoneIsPassed', True);
end;
// Гонщики
Count:=ReadInteger('racers', 'Count', 0);
SetLength(FRacers, Count);
Self.FRacersCount:=Count;
for I:=0 to Count-1 do
begin
with FRacers[I] do
begin
S:='Racer'+IntToStr(I);
RacerName:=ReadString(S,'RacerName','***Ошибка INI***');
StartPos.X:=ReadFloat(S,'StartPos.X',0);
StartPos.Y:=ReadFloat(S,'StartPos.Y',0);
StartPos.Z:=ReadFloat(S,'StartPos.Z',0);
StartAngle:=ReadFloat(S,'StartAngle',0);
CarModel:=ReadString(S,'CarModel','banshee');
ColorEnabled:=ReadBool(S,'ColorEnabled',False);
CarColor1:=ReadInteger(S,'CarColor1',0);
CarColor2:=ReadInteger(S,'CarColor2',0);
SteerBias:=ReadFloat(S,'SteerBias',5.0);
CarProofs.BP:=ReadBool(S,'CarProofs.BP',true);
CarProofs.FP:=ReadBool(S,'CarProofs.FP',true);
CarProofs.EP:=ReadBool(S,'CarProofs.EP',true);
CarProofs.CP:=ReadBool(S,'CarProofs.CP',true);
CarProofs.MP:=ReadBool(S,'CarProofs.MP',true);
DoorState:=ReadInteger(S,'DoorState',1);
end;
end;
//Контрольные точки
Count:=ReadInteger('CPs', 'Count', 0);
SetLength(FCheckpoints, Count);
FCheckpointsCount:=Count;
for I:=0 to Count-1 do
begin
with FCheckpoints[I] do
begin
S:='CP'+IntToStr(I);
Pos.X:=ReadFloat(S,'Pos.X',0);
Pos.Y:=ReadFloat(S,'Pos.Y',0);
Pos.Z:=ReadFloat(S,'Pos.Z',0);
Radius:=ReadFloat(S,'Radius',7);
Speed:=ReadFloat(S,'Speed',200);
end;
end;
//Вид
FView.ShowRacersList:=ReadBool('view', 'ShowRacersList', true);
//Среда
with FEnvironment do
begin
EnableWeather:=ReadBool('environment', 'EnableWeather', False);
Weather:=ReadInteger('environment', 'Weather', -1);
EnableTime:=ReadBool('environment', 'EnableTime', false);
Hours:=ReadInteger('environment', 'Hours', 12);
Minutes:=ReadInteger('environment', 'Minutes', 0);
TrafficDensity:=ReadFloat('environment', 'TrafficDensity', 1.0);
PedsDensity:=ReadFloat('environment', 'PedsDensity', 1.0);
end;
//Объекты
Count:=ReadInteger('objects', 'Count', 0);
SetLength(FObjects, Count);
FObjectsCount:=Count;
for I:=0 to Count-1 do
begin
with FObjects[I] do
begin
S:='Object'+IntToStr(I);
Model:=ReadString(S,'Model','null');
Pos.X:=ReadFloat(S,'Pos.X',0);
Pos.Y:=ReadFloat(S,'Pos.Y',0);
Pos.Z:=ReadFloat(S,'Pos.Z',0);
Rot.X:=ReadFloat(S,'Rot.X',0);
Rot.Y:=ReadFloat(S,'Rot.Y',0);
Rot.Z:=ReadFloat(S,'Rot.Z',0);
Collision:=ReadBool(S,'Collision',true);
Indestructible:=ReadBool(S,'Indestructible',false);
Freeze:=ReadBool(S,'Freeze',false);
Comment:=ReadString(S,'Comment','***ОШИБКА INI***');
end;
end;
UpgUsedModels;
finally
Ini.Free;
List.Free;
end;
end;
procedure TRace.UpgUsedModels;
var
List: TStringList;
I: Integer;
begin
List:=TStringList.Create;
List.Sorted:=True;
List.Duplicates:=dupIgnore;
List.CaseSensitive:=False;
for I := 0 to FRacersCount-1 do
begin
List.Add(FRacers[I].CarModel);
end;
for I := 0 to FObjectsCount-1 do
begin
List.Add(FObjects[I].Model);
end;
SetLength(FUsedModels, List.Count);
FUsedModelsCount:=List.Count;
for I := 0 to List.Count-1 do
begin
FUsedModels[I]:=GetHashKey(PChar(List[I]));
end;
List.Free;
end;
{ TRaces }
constructor TRaces.Create(Dir: string);
begin
inherited Create;
Open(Dir);
end;
destructor TRaces.Destroy;
var I: Integer;
begin
for I:=0 to FCount-1 do
begin
FRaces[I].Free;
end;
Finalize(FRaces);
inherited;
end;
function TRaces.GetRace(Index: Integer): TRace;
begin
Result:=FRaces[Index];
end;
procedure TRaces.Open(Dir: string);
var
Rec: TSearchRec;
N: Integer;
E: Integer;
begin
N:=0;
E:=FindFirst('.\Alice\RaCon\*.RaCon', $3, Rec);
try
while E=0 do
begin
if FileExists('Alice\RaCon\'+Rec.Name) then
begin
Inc(N);
SetLength(FRaces, N);
FRaces[N-1]:=TRace.Create(GetCurrentDir+'\Alice\RaCon\'+Rec.Name);
E:=FindNext(Rec);
end;
end;
finally
FCount:=High(FRaces)+1;
FindClose(Rec);
end;
end;
initialization
finalization
Ra.Free;
end.
Количество пользователей, читающих эту тему: 2
0 пользователей, 2 гостей, 0 анонимных
















