Open PS2 Loader,запуск игр через LAN

Написано: четверг, 18 апреля 2013 г. автор st1x51
0

Недавно откопал PS2 и захотел поиграть в пару игр,проблемы запуска игр через USB не было,но это не вариант,так как скорость передачи данных мала,некоторые игры могут глючить или вообще не запуститься.Собственно вспомнил про запуск игр через LAN.В интернете есть много способов запуска ps2 игр через lan,но они не слишком информативные.Предлагаю свой вариант.

1)Для начала конечно же вам нужен сетевой LAN кабель,можете заранее воткнуть его в свой PC и в PS2.
2)Нужно разделить свой жесткий диск и отформатировать нужную вам часть в систему FAT32,ибо если у вас NTFS,OPL даже не найдет игр.
По этому туториалу я разделил свой D диск и создал диск X размером в 50гб,мне этого достаточно было.
Так как жесткий диск в Win7 просто так не отформатировать в FAT32,я откопал утилиту под названием fat32format,которая может это сделать,когда-то она запускалась только через командную строку,но я нашел GUI версию програмы. Как ей пользоваться,писать не буду,все очень просто.

3)Создаем папку PS2SMB на нашем диске с FAT32,жмем второй кнопкой мыши на папке>Свойства>Доступ>Общий доступ,там нужно добавить учетную запись гостя(Гость или Guest) и выдать права на чтение(если учетная запись гостя выключена,включите ее)
В папке PS2SMB создаем папки DVD и CD,в DVD будут лежать образы игр(весом не более 4 гб,так как фат32),а в CD будут лежать CD игры,например Half-life Decay.
Названия игр обязательно должны быть такого типа: код региона.название.iso,например SLUS_211.56.WithoutWaring.iso (код региона можно узнать,если открыть диск с игрой винраром,бывает код выглядит как LOADER.00,это нормально,так как диск с пиратским лоадером)

4)Далее идем в  Панель управления>Администрирование>Локальная политика безопасности >Локальные политики>Назначение Прав пользователя>Доступ к компьютеру из сети и добавляем Гостя

5)Открываем Центр управления сетями и общим доступом>изменение параметров адаптера>там будет "подключение по локальной сети",жмите на нем Свойство
В поле ip напишите 192.168.1.2,маска подсети сама поставится
Откройте  Центр управления сетями и общим доступом>Дополнительные параметры общего доступа>выключите там "общий доступ с парольной защитой"

6)Запускаем на вашей PS2 uLaunchELF,заходим в файловый браузер(кнопка О),потом заходим в MISC,тыкаем на PS2NET.Вверху покажется ip приставки(если ip 192.168.1.x,то все нормально,если 192.168.0.x,то нужно вернуться в пункт 5 и сменить ip на 192.168.0.3 например)

7)Скидываем OPL на флешку(в архиве opl,который использую я,это opl 0.8,знаю что есть 0.9,но 0.8 привычнее)
Вставляем флешку в PS2,запускаем файловый браузер,заходим в папку mass,запускаем OPL.
Далее жмем start,потом заходим в network config,там прописываем ip компа и приставки.
Сохраняем настройки,выбираем меню с играми по сети,жмем Start Device(если у вас есть игры на жестком диске:D),все.

Есть игры,которые весят больше 4гб,для таких игр была сделана утилита USBUtil
Открываем USBUtil,нажимаем File->Create Game From ISO ,выбираем образ игры,ждем пока образ разделится,полученные файлы кидаем в папку PS2SMB.
Среди файлов есть файл ul.cfg,в нем список ваших игр,этот файл нужно обновлять с помощью USBUtil,иначе у вас в списке всегда будет одна игра.Для обновления списка игр нужно в USBUtil нажать Utill>Recover list of games и выбрать папку PS2SMB.

P.S:Если образ вашей игры mdf/mds,просто смените расширение mdf на iso
P.S.2:Если какая-либо игра зависает.то ее нужно пропатчить USBUtil патчем IOPRP,иногда это помогает.


QuakeC:Плавающие объекты в Quake

Написано: воскресенье, 24 марта 2013 г. автор st1x51
0

Сложность: Средняя
Вы хотите, чтобы различные части тела, мертвые тела и рюкзачки в воде плавали? Тогда вы не должны пропустить этот урок, и даже с малыми знаниями QuakeC-программирования, вы сможете заставить другие вещи плавать.
Шаг 1 - Подготовка новой директории для мода.
Для начала, нам нужно скопировать неизмененные файлы QuakeC версии 1.06, а также скопировать файл floater.qc, содержание которого находится в самом конце этого урока, разумеется, вам нужно будет только создать файл с именем floater.qc и вставить в него текст, о котором чуть позже...
Итак, создайте в директории с Quake директорию, которую мы назовем FLOATER, и, чтобы Вы могли нормально делать мод, создайте внутри только что созданной директории еще одну директорию, которую назовем SRC.
Теперь скопируйте QuakeC файлы, а также файл floater.qc, в директорию SRC.
Шаг 2 - Добавление нового файла с исходного кодами
Так, как мы с вами внесли в наш мод новый файл, мы должны добавить его в список файлов для компиляции. Этим списком является файл progs.src, который сообщает компилятору, какие файлы с исходными кодами принадлежат к нашему моды.
Добавьте floater.qc после defs.qc в progs.src так, как показанно ниже:

defs.qc
floater.qc // наш новый файл
subs.qc
fight.qc

Шаг 3 - Изменение существующего исходного кода.
Изменения будут начинатся и заканчиватся коментариями // FLOATER.

Изменение файла client.qc. Сейчас мы с вами сделаем некоторое изменение в функции PlayerPreThink (ориентир на 914-ю строчку). После изменение начало функции должно выглядет так:

local float mspeed, aspeed;
local float r;

// FLOATER
// контроль "плавучести" над плавающими объектами
floaterPreThink();
// FLOATER

if (intermission_running)

Добавив floaterPreThink();, мы предоставляем Quake способность контролировать плавающие объекты (для краткости назовем их плавуны). Этот выполняется всегда на протяжении всей игры с некоторой задержкой (в один кадр), то есть если существуют какие-либо плавуны, то они сразу же становятся зависимыми от их текущих характеристик : они могут быть падающими, плавающими, погружающимися или могут просто лежать на поверхности.

Шаг 5 - Даем объектам способность плавать.
Погружающийся плавун зависит от скорости падения, но потом падает на какую-нибудь поверхность, где плавает, как поплавок, верх-вниз в течение 30 секунд и наконец падает на саму поверхность и теряет скорость.

Иногда вы сможете найти плавун, который удерживает свою скорость или кружится вокруг в течении того времени, пока он плавает, как поплавок. Скажу сразу, я не писал код для чего-нибудь подобного. Еще объекты иногда удерживают скорость по x или y.

Максумум 32 плавуна могут быть активированны в одно и тоже время (смотрите конфигурации в файле floater.qc) - в этом случае, когда какой-нибудь активированный плавун достигает поверхности (дна, пола, земли, и т.д.) нам нужно его деактивировать (т.е. сделать так, чтобы плавун использовал обычную quake-физику, например, как у объектов на поверхности).

Чтобы активировать у объекта способность плавания, мы должны вызвать свойство, которое называется floaterEnabl. Его мы опишем в файле floater.qc.

Сделайте изменения в файле player.qc (начиная, примерно, с 466-ой строчки) так, как показанно ниже:

new.origin = self.origin;
setmodel (new, gibname);

// FLOATER
// зададим объекту размеры по оси Z ... Тогда будет казаться, что он как бы "висит" в воде
setsize( new, '0 0 -4', '0 0 12' );
// FLOATER

new.velocity = VelocityForDamage (dm);
new.movetype = MOVETYPE_BOUNCE;


Причина для изменения размеров останков игрока или монстра (далее джибзы) заключается в том, чтобы создать иллюзию плавания объекта в воде, в то время, когда он уже находится на дне.

Следующие изменения в файле player.qc будут начинаются, с примерно 484-ой строчки.

new.frame = 0;
new.flags = 0;

// FLOATER
// указываем джибзам, чтобы они могли плавать
floaterEnable (new, 2);
// FLOATER

Если сейчас вы откомпилируете и запустите полученное, то вы сможете увидеть джибзы, плавающие в воде. Но можно и дальше пойти.

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

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

Центр объекта мы подсчитаем следующим образом:
Во-первых, как мы видим центр объекта в Quake?

Все модели в Quake окружает так называемая коробка, находящаяся в координатах 'X Y Z' (ниже центра модели, назовем их mins) и 'X Y Z' (выше центра модели, назовем их maxs), что дает частичный размер (maxs - mins) и центр (размер - maxs) коробке. Вы, наверное спросите, зачем нужна эта коробка? Что ж, она нужна для того, чтобы задать так называемый контур объекта, который будет принимать на себя все попадания по объекту, в том числе и попадания других объектов...

Следующая диаграмма покажет размещение головы (в смысле, воображаемой ;), которая имеет коробку с размерами '-16 -16 0', '16 16 56':


====== --- верхушка коробки (56)

------
[голова]
------ --- низ коробки (0), центр (0)
~~~~~~ --- поверхность воды

примечание : наша диаграма не имеет действительных размеров..

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

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

Чтобы взять плавающую как поплавок голову, мы передаем ей второй параметр свойства floaterEnable. Значение 5 (я использую 5, так как внешний размер (модель) головы как правило составляет 20% от всего размера коробки) сделает визуальный центр головы в воде так, как показано ниже:


====== --- верхушка коробки (56)

------
[голова] --- визуальный центр в воде (5)
------ --- низ коробки (0), центр (0)
~~~~~~ --- поверхность воды

Далее немного другой пример. Если тело умирает, то размеры коробки следующие: '-16 -16 -24', '16 16 32'.


====== --- верхушка коробки (56)
--- центр (24)
------
[тело] --- визуальный центр в воде (6)
------

====== --- низ коробки
~~~~~~ --- поверхность воды

В случае мертвого тела, нам нужно изменить центр на -18 (6-24), чтобы изменить визуальный центр для плавуна.

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

Шаг 6 - Доделываем наш мод.
1. Изменения в файле client.qc

Первые изменения начинаются примерно с 483-ей строки и заключаются в следующем:

void() PutClientInServer =
{
local entity spot;

// FLOATER
// делаем так, чтобы только мертвые игроки плавали как поплавки
floaterDisable (self);
// FLOATER

spot = SelectSpawnPoint ();

Следующее изменение начинается примерно с 791-ой строки.

if (self.movetype == MOVETYPE_NOCLIP)
return;

// FLOATER
// это будет проверкой для жизней при <0%, чтобы
// мертвый игрок не плавает так, как люди,
// а плавал так, как плавают трупы ;)
if( self.health <=0 ) return;
// FLOATER

if (self.waterlevel !=3)

2. Изменения в файле player.qc

Во-первых, перейдем на, примерно 504-ую строчку и сделаем следующие изменения:

self.flags = self.flags-(self.flags & FL_ONGROUND);
self.avelocity = crandom()* '0 600 0';

// FLOATER
// делаем голову плавающей
floaterEnable (self, 5);
// FLOATER

Далее перейдем на примерно 573-ю строчку:

self.angles_x = 0;
self.angles_z = 0;

// FLOATER
// теперь мы делаем тело плавающим
floaterEnable (self, -18);
// FLOATER

if (self.weapon == IT_AXE)

3. Изменения в файле combat.qc ведутся примерно с 78-ой строчки и заключаются в следующем:

if (self.flags & FL_MONSTER)
{
// FLOATER
// делаем тела мертвых монстров плавающими
floaterEnable (self, -18);
// FLOATER

killed_monsters = killed_monsters+1;
WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
}

4. В файле world.qc изменения начинаются примерно с 390-ой строки:

setorigin (bodyque_head, ent.origin);
setsize (bodyque_head, ent.mins, ent.maxs);

// FLOATER
bodyque_head.sFloating = ent.sFloating;
bodyque_head.state = ent.state;
bodyque_head.speed = ent.speed;

bodyque_head.fOriginOffset = ent.fOriginOffset;

bodyque_head.ltime = ent.ltime;

if( ent.flags & FL_INWATER )
bodyque_head.flags = bodyque_head.flags | FL_INWATER;
// FLOATER

bodyque_head = bodyque_head.owner;

Изменения, которые были чуть выше (4), делают копии мертвых тел игрока, который еще не появился вновь (т.е. до того, как игрок нажмет на гашетку, чтобы респавнится).

5. Изменения в файле items.qc протекают с 1380-ой строки:

item.nextthink = time+120; // убрать объект через 2 минуты
item.think = SUB_Remove;

// FLOATER
// делаем рюкзак, который выкидывается при смерти (назовем его бэкпэком) плавающим.
floaterEnable (item, 6);
// FLOATER

Шаг 7 - Вот и все.
Вот и все, что нам нужно было сделать, теперь компилируйте и запускайте Quake с нашими новыми модификациями.
Надеюсь вы будете в восторге от этого!

--------------------------------------------------------------------------------
P.S.: И еще одна последняя вещь. Вы наверное спросите где же все-таки взять содержимое для файла floater.qc? Отвечаем: оно находится ниже....

/*
==============================================================================
"floater.qc" разработал Alan Kivlin

12 мая 1997 года

Коментарии к модификации
-------------------------------

Данная модификация нужна для того, чтобы делать объекты плавающими в воде и на ее поверхности

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

Иногда вы сможете найти плавун, который удерживает свою скорость или кружится вокруг в течении того времени, пока он плавает, как поплавок. Скажу сразу, я не писал код для чего-нибудь подобного. Еще объекты иногда удерживают скорость по x или y.

Эта модификация зарегестрирована Alan Kivlin'ом в 1997 году.

Другие авторы МОГУТ использовать эту модификацию, как основу для других своих дополнений.
^^^^^^^^
ВНИМАНИЕ: Alan Kivlin (или как его еще называют Virtuoso) не несет ответственности за ущерб, психологические воздействия, потерю сна или усталость после использования данной модификации.
Если вы скопируете это на компакт-диск, то вы будете должны мне одну копию CD. Если вам это не нравится, то не копируйте это на CD!
Если вы возьмете мою работу и ни разу не упомяните обо мне, то ВЫ СГОРИТЕ В АДУ, так, как горят поросята Фроги в духовке.
Использование этой модификации в комерческих целях привет к тому, что к вам ночью завалятся дружки Сатаны и вам будет очень плохо, потому, что надо сначала переговорить со мной (Alan Kivlin), ok?

Спасибо Dave 'Zoid' Kirsch за его копирайт, который я поместил выше.
==============================================================================
*/

// вызов последнего кадра
float fFloaterLastFrame;

// делаем на объекте метку "floating", когда тот плавает
.string sFloating;

// изменения центра плавуна после проверки
.float fOriginOffset;

// флаги состояния плавуна
float FS_FALLING = 1; // падает
float FS_SURFACING = 2; // на поверхности
float FS_FLOATING = 3; // плавает
float FS_SINKING = 4; // опускается

// максимальное число одновременно плавающих объектов
float FLOATER_MAXIMUM = 32;

//----------------------------------------------------------------------------

// возвращаем значение TRUE (правда), если находится в воде, лаве или кислоте
float (entity ent) floaterInWater;

// делаем объект плавающим
void (entity ent, float offset) floaterEnable;

// делаем объект не плавающим
void (entity ent) floaterDisable;

// контролируем плавание всех плавунов
void () floaterPreThink;

//----------------------------------------------------------------------------

/*
==============================================================================
Значение "floaterInWater"
Возвращаем значение TRUE, если находится в воде, лаве или кислоте
==============================================================================
*/

float (entity ent) floaterInWater =
{
local vector where;
local float contents;

where = ent.origin;
where_z = where_z+ent.fOriginOffset;

contents = pointcontents (where);

if (contents >= -5 && contents <= -3) // в воде (-3), кислоте (-4) или лаве (-5) возвращаем TRUE.
return true;
return false;
};

/*
==============================================================================
Функция "floaterenable" вызывает у объекта способность плавать
==============================================================================
*/
void (entity ent, float offset) floaterenable=
{
local float floatercount;
local entity floater, oldest;
oldest = floater = find (world, sfloating, "floating");
while (floater)
{
floatercount = floatercount + 1;
if (floater.ltime <= oldest.ltime) oldest=floater;
floater = find (floater, sfloating, "floating");
}
if (floatercount == floater_maximum)
floaterdisable (oldest);
ent.sfloating = "floating";
ent.state = FS_FALLING;
ent.speed = 0; // сохраним изменения центра, использованного при проверке
ent.foriginoffset = offset; // "стартуем" время опускания плавуна
ent.ltime = time+30+random()*5;
if (floaterinwater(ent))
{
ent.movetype = MOVETYPE_TOSS;
ent.flags = ent.flags | fl_inwater; // ставим флаг "в воде"
}
else
{
ent.movetype = MOVETYPE_BOUNCE;
ent.flags = ent.flags-(ent.flags & fl_inwater); // убираем флаг "в воде"
}
};

/*
==============================================================================
Функция "floaterdisable" отнимает у объекта способность плавать
==============================================================================
*/
void( entity ent ) floaterdisable=
{
// прекращаем плавание
ent.sfloating = string_null;
};

/*
==============================================================================
Функция "floaterprethink" контролирует плавание всех плавунов
==============================================================================
*/
void() floaterprethink=
{
local entity ent;
if (ffloaterlastframe == framecount) return;
ffloaterlastframe = framecount;
ent = find (world, sfloating, "floating");
while (ent)
{
if ((ent.state == FS_FLOATING) && (ent.flags & fl_onground))
{
// если мы на земле, то мы должны уже упасть, это случается
// когда плавун на движущейся платформе, которая покинула воду
ent.state = FS_FALLING;
ent.speed = 0;
}
if (ent.state == FS_FLOATING)
{
if (ent.speed > 0) ent.velocity_z = ent.speed*(1+frametime*8); // плывем вверх
else ent.velocity_z = 0; // плывем вниз
}
else if (ent.state == FS_SURFACING)
// если у объекта стоит флаг "на поверхности", то
{
if (ent.velocity_z > 0) ent.velocity_z = ent.speed; // сохраняем скорость на поверхности
else if (floaterInWater(ent)) ent.state = FS_SINKING; // can't reach the surface so make it sink
}
else if (ent.state == FS_SINKING)
// иначе, если у объекта стоит флаг "погружающийся", то
if (ent.flags & FL_ONGROUND) floaterDisable(ent);
// если он уже на дне, то отбираем у него способность плавать
else ent.velocity_z = 0; // иначе, заставляем его погружаться медленно

if (floaterInWater(ent))
{
if (!(ent.flags & FL_INWATER))
{
ent.movetype = MOVETYPE_TOSS;

// ставим флаг "в воде"
ent.flags = ent.flags | FL_INWATER;

if (ent.state == FS_FLOATING) ent.speed = 72+random()*16;
// начинаем плыть вверх
else if (ent.state == FS_FALLING) sound (ent, CHAN_BODY, "player/h2ojump.wav", 1, ATTN_NORM);
// проигрываем звук вхождения в воду
}

if (ent.state == FS_FALLING)
{
if (!ent.speed)
{
if (ent.velocity_z < 0) // ставим максимальную скорость падения, до того как плавун достигнет поверхности
ent.speed = ent.velocity_z*8;
}
if ((ent.velocity_z <= ent.speed) || (ent.flags & fl_onground))
{
// start surfacing
ent.state = FS_SURFACING;
ent.speed = 128+random()*32;
ent.velocity_z = ent.speed;
ent.velocity_x = 0;
ent.velocity_y = 0;
}
}
}
else
{
if ((ent.flags & fl_inwater))
{
ent.movetype = MOVETYPE_BOUNCE;

//убираем флаг "в воде"
ent.flags = ent.flags-fl_inwater;
if (ent.state == FS_FLOATING) ent.speed = 0; // начинаем плавать вниз
else if (ent.state == FS_SINKING)
{
ent.state = FS_FALLING;
ent.speed = 0;
}
if (ent.state == FS_FALLING) sound (ent, chan_body, "player/h2ojump.wav" , 1, attn_norm); // play leave water sound
}
if (ent.state == FS_SURFACING)
{
// как только объект касается поверхности воды, то выталкиваем его наружу...
ent.velocity_z = ent.speed*1.5;
// ...и заставляем его плыть вниз
ent.state = FS_FLOATING;
ent.speed = 0;
}
}
if (ent.ltime <=time)
{
if (ent.flags & fl_inwater)
{
// если плавун достаточно опустился в воду, то ставим ему флаг "погружающийся"
ent.state = FS_SINKING;
ent.ltime = time+10+random()*5;
}
}
ent.watertype = 0;

// доругие физические движения не работают для плавуна
ent.flags = ent.flags-(ent.flags & fl_onground);
ent = find (ent, sfloating, "floating");
}

QuakeC:Персональный телепорт

Написано: автор st1x51
0

Сложность: Легкая
На это уроке, как вы уже догадались, мы создадим персональый телепортер. Все изменения проходят в файлах weapons.qc и defs.qc.
Шаг 1
Итак, для начала откроем файл weapon.qc и в самом верху, где написанно несколько нижеприведенных строчек, добавим наши четыре помеченные строчки.
/*
*/
void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
void () player_run;
void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
void(vector org, vector vel, float damage) SpawnBlood;
void() SuperDamageSound;
void() DropTeleport; //добавить
void() Teleport_to_drop; //добавить
void (vector org) spawn_tfog; //добавить
void (vector org, entity death_owner) spawn_tdeath; //добавить
Этим самым мы объявили четыре функции, которые мы создадим впоследствии.
Шаг 2
О'кей, теперь мы должны создать функции для телепорта. Итак, найдите функцию ImpulseCommands и перед ней добавте нижеследюющее:
/*
==========
Self Teleporter
==========
*/

void() DropTeleport = //эта функция кладет на месте игрока "точку для телепортации"(ТТ)
{
if(!self.tele_dropped)
{
self.teledrop_dest = spawn(); //создаем временный объект для ТТ
}
self.teledrop_dest.origin = self.origin; //запоминаем координаты ТТ
self.teledrop_dest.mangle = self.angles;
self.tele_dropped = 1;
dprint("Teleport destination dropped.");
};

void() Teleport_to_drop = //эта функция телепортирует игрока туда, где находится ТТ
{
local vector org;
if(!self.tele_dropped)
{
dprint("No destination dropped.");
return;
}
if(self.health <= 0)
{
return;
}
spawn_tfog (self.teledrop_dest.origin);
makevectors (self.teledrop_dest.mangle);
org=self.teledrop_dest.origin;
spawn_tfog (org);
spawn_tdeath (org,self);
setorigin (self,self.teledrop_dest.origin);
self.angles=self.teledrop_dest.mangle;
self.fixangle=1;
self.velocity=v_forward * 100;
self.teleport_time=time + 0.5;
self.flags=self.flags - self.flags & fl_onground;
remove(self.teledrop_dest); //удалите эту строчку, если вы хотите, чтобы ТТ оставался после телепортации.
};
Шаг 3
Теперь в функции Impulse Commands, что находится чуть ниже наших тлько что написанных функций, над строчкой self.impulse = 0; добавьте следующие две строчки:

if (self.impulse == 14) DropTeleport ();
if (self.impulse == 15) Teleport_to_drop ();
Шаг 4
И, наконец, последний шаг в нашем моде. Откройте файл defs.qc, и в самом конце этого файла добавте следующее:
.entity teledrop_dest;
.float tele_dropped;
(ОЧЕНЬ ВАЖНО, что все добавляемые строчки в файле defs.qc должны находится в самом конце этого файла!)
Шаг 5
Вот и все! Теперь откомпилируйте и запустите полученное. Не забудте присвоить клавишам новые impulse-команды (impulse 14 - скинуть ТТ, impulse 15 - телепортироваться)! Приятной вам игры...

QuakeC:Взрывпакет

Написано: автор st1x51
0

Сложность: Средняя
Шаг 1
Ок, в в этом уроке мы научимся создавать Взрывпакет. Звучит внушающе, не так ли? Нельзя не согласиться! Найдите функцию Impulse Commands в файле weapons.qc. Скопируйте код, который написан ниже и добавьте импульс-команду (impulse 20), которая будет активизировать DropDetpack:
/*
============
ImpulseCommands

============
*/
void() ImpulseCommands =
{
if (self.impulse >= 1 && self.impulse <= 8) w_changeweapon ();
if (self.impulse== 9) cheatcommand ();
if (self.impulse== 10) cycleweaponcommand ();
if (self.impulse== 11) serverflagscommand ();
if (self.impulse == 20) DropDetpack (); //активизировать функцию DropDetpack, когда мы введем в консоли "impulse 20".
if (self.impulse == 255) QuadCheat ();

self.impulse = 0;
};
Шаг 2
Так, теперь нам надо добавить функцию, которую мы назовем DropDetpack, в файле weapons.qc (давайте добавим ее чуть выше блока Player Weapon Use). Вот описание этой функции:
void() DropDetpack =
{
if (self.ammo_rockets >= 25)
//Смотрим, есть ли у игрока хотя бы 25 рокет. Если есть, то...
{
self.ammo_rockets = self.ammo_rockets - 25; //забираем у него 25 рокет,

local entity item; //создаем локальный объект (пусть будет "item"),

item = spawn(); //запускаем объект "item" в игру,
item.origin = self.origin - '0 0 24'; //кладем объект "item" ниже центра игрока на 24 еденицы (т.е. под ноги игрока),

item.velocity_z = 300; //подбрасываем объект "item" на 300 едениц вверх,
item.velocity_x = -100 + (random() * 200); //а по горизонтали объект "item" полетит
item.velocity_y = -100 + (random() * 200); //в каком-нибудь случайном направлении

item.flags = FL_ITEM;
item.solid = SOLID_TRIGGER; //SOLID_TRIGGER, означает, что если кто-то коснется объекта "item",
// то активизируется некоторый триггер(его мы пропишем чуть позже).
item.movetype = MOVETYPE_TOSS; //Тип движения... эээ... броском !!
setmodel (item, "progs/backpack.mdl"); //Присваеваем объекту "item" модель "backpack", находящуюся в директории "progs/",
setsize (item, '-16 -16 0', '16 16 56'); //Задаем габариты объекта "item" ('-x -y -z' , '+x +y +z' ),
item.owner = self; //говорим объекту "item", что его выпустили мы.
item.touch = DetpackTouch; //если наш взрывпакет упал на кого-нибудь, когда мы его выкинули,
// то активируем функцию DetpackTouch

item.nextthink = time + 120; //После 2 минут переходим к функции item.think
item.think = DetpackExplode; //которая "запускает" функцию DetpackExplode
}
else //Ну, а если нету 25 рокет, то...
{
sprint (self, "You haven't enough rockets, baby.\n"); //Выводим надпись "You haven't enough rockets, baby."
return; //и возвращаемся в игру
}
};
Шаг 3
О'кей. Теперь сделаем две функции : первая - DetpackTouch, которая прикажет Взрывпакету взорваться, если на нее наступит кто-нибудь (кроме нас самих, конечно) и вторая - DetpackExplode, которая... отлично сработает, если Взрывпакет попадает на кого нибудь во время его выброса. Т.е у нас есть две причины, чтобы взорвать Взрывпакета >:)

Сейчас я опишу как это происходит:
Когда наш Взрывпакет попадает на кого-нибудь, то мы сразу взрываем его функцией DetpackExplode. Если же на Взрывпакет наступит кто-то, то мы сначала функцией DetpackTouch определяем, кто наступил на него, "мы" или "не мы", и если "не мы", то взрываем Взрывпакет функцией DetpackExplode. Т.е. в функции DetpackExplode мы нуждаемся раньше функции DetpackTouch, следовательно функция DetpackTouch должна быть ниже функции DetpackExplode.

Вот код, что мы должны написать:

void () DetpackExplode =
{
T_RadiusDamage (self, self.owner, 1000, world); //Здесь мы задаем радиус поражения, у гранат он
//равен 120, но ведь мы хотим БОЛЬШОГО ВЗРЫВА,
//и поэтому ставим 1000 !!! ;-)

//Далее указываем, что :
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); //а) объект темповый(временный),
WriteByte (MSG_BROADCAST, TE_EXPLOSION); //б) объект взрывчатый(хе-хе, а как же иначе-то?>:о).
WriteCoord (MSG_BROADCAST, self.origin_x); //создает X-координату для Backpack
WriteCoord (MSG_BROADCAST, self.origin_y); //создает Y-координату для Backpack
WriteCoord (MSG_BROADCAST, self.origin_z); //создает Z-координату для Backpack

BecomeExplosion (); //Производим ВЗРЫВ (БОЛЬШОЙ) !!!
};

void() DetpackTouch =
{
if (other == self.owner) //делаем так, чтобы detpack игнорировал нас, если он упадет на нас
{
return; //то есть возвращаемся в игру.
}
if (other.takedamage == DAMAGE_AIM) //Если игрок (кроме нас) или монстр, на которого упал наш detpack может быть поврежден,то
{
DetpackExplode(); //Производим ВЗРЫВ (см.предыдущую функцию) !!!
return; //и возвращаемся в игру.
}
if (self.velocity == '0 0 0') //если detpack уже не падает, то:
{
self.avelocity = '0 0 0'; //препятствуем "угловому движению"
}
};

Отлично... эти функции нужно добавлять ниже нашей функции DropDetpack.
Шаг 4
Последний шаг! Так, как наше дополнение использует новую модель (backpack.mdl), то нам нужно ее "подготовить". Итак, под подготовкой звуков в самом верху файла weapons.qc добавте самую нижнюю строчку примера:

precache_sound ("weapons/grenade.wav"); // звук выстрела из гранатомета
precache_sound ("weapons/bounce.wav"); // звук отскока гранаты от стены
precache_sound ("weapons/shotgn2.wav"); // звук выстрела из двустволки
precache_model ("progs/backpack.mdl"); // модель рюкзачка для DetPack

И кто тут сказал, что это трудно ?! Теперь компилируйте и посмотрите, что получилось. Во время игры наберите в консоли impulse 20 и посмотрите что получилось!!

QuakeC:Больше крови

Написано: автор st1x51
0

Сложность: Легкая
Шаг 1
Это дополнение дает больше крови в сетевой и одиночной играх . Все это делается очень легко в файле weapons.qc. Откройте этот файл для редактирования и опускайтесь вниз до нижеприведенных строчек.
/*
================
SpawnBlood
================
*/

void(vector org, vector vel, float damage) SpawnBlood =
{
particle (org, vel*0.1, 73, damage*2);
};

Шаг 2
Вставте три строчки, которые указаны ниже.
/*
================
SpawnBlood
================
*/

void(vector org, vector vel, float damage) SpawnBlood =
{
particle (org, vel*0.1, 79, damage*1);
particle (org, vel*0.25, 74, damage*5);
particle (org, vel*0.15, 69, damage*2);
};

Шаг 3
Вот и все! Согласитесь, что это было очень легко. Теперь компилируйте и запускайте полученное. Возмите в игре SuperShotgun (он сделает наш мод более эффективным :) и идите охотится на Grunt'ов! (Примечание: использование этого дополнения совместно с дополнением Больше мяса(урок 2) дает потрясающей эффект >:)

QuakeC:Магнум

Написано: автор st1x51
0

Сложность: Легкая
Шаг 1
Все это дополнение делается в файле weapons.qc. Когда мы его сделаем, у вас получится зверский Магнум! На этом уроке вы встретите несколько маленьких установок для оружия (таких, как на сколько градусов вверх идет отдача, конус разлета, и т.д.).. Но они очень легкие. К тому же, я помогу вам :) Теперь, найдите в файле weapons.qc текст, который похож на текст указанный в шаге 2.
Шаг 2
Итак, все, что вы должны сделать, это поменять некоторые числа, например так, как это показанно ниже.
(Внимание: не делайте Магнум слишком мощным, если вы расчитываете играть с ним по сети!)
/*
================
W_FireShotgun
================
*/
void() W_FireShotgun =
{
local vector dir;

sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
// воспроизвести звук выстрела из Shotgun

self.punchangle_x = -2; //угол обзора отклониться вверх на 2 единицы

self.currentammo = self.ammo_shells = self.ammo_shells - 1;
//здесь мы указываем, сколько патрон отнимется за один выстрел

dir = aim (self, 1000); //расстояние 100%-го попадания.

FireBullets (20, dir, '0.04 0.04 0');
//20 осколков в конусе разлета.
//0.04 - это высота и ширина конуса разлета (для Магнума лучше сделать 0.001).
};
Шаг 3
Вот и все! Компилируйте и запускайте полученное. Теперь ваш Shotgun будет сеять смерть вокруг.

QuakeC:Больше мяса

Написано: автор st1x51
0

Автор: Timm 'Mr?' Stokke
eMail: hestokke@online.no
Сложность: Легкая

Наиболее простой путь для увеличения количества мяса в сетевой игре
Шаг 1
Весь этот мод делается в файле player.qc, который нужно открыть для изменения. Когда вы все это сделаете, то у вас должно быть в два раза больше мыса в Сетевой игре. Все, что вам нужно будет делать, это копировать и вставлять некоторые строчки. Итак, переходим к самому основному, к шагу 2.
Шаг 2
Итак, скопируйте какую-либо строчку ThrowGib в функции GibPlayer, и вставте ее чуть ниже на одну строчку! А теперь сделаем мяса в два раза больше( т.е. так, как мы задумали). Посмотрите, как должно выглядеть оригинальное начало функции GibPlayer.
ThrowHead ("progs/h_player.mdl", self.health);
ThrowGib ("progs/gib1.mdl", self.health);
ThrowGib ("progs/gib2.mdl", self.health);
ThrowGib ("progs/gib3.mdl", self.health);
И примерно так оно может выглядеть после изменения.
ThrowHead ("progs/h_player.mdl", self.health);
ThrowGib ("progs/gib1.mdl", self.health);
ThrowGib ("progs/gib1.mdl", self.health);
ThrowGib ("progs/gib2.mdl", self.health);
ThrowGib ("progs/gib2.mdl", self.health);
ThrowGib ("progs/gib3.mdl", self.health);
ThrowGib ("progs/gib3.mdl", self.health);
Шаг 3
И это все! Скомпилируйте полученное, и запустите дополнение. Но не жалуйтесь, если оно не работает в одиночном режиме игры, так как оно работает только в сетевой игре (deathmatch и cooperative). Если вы хотите еще больше мяса, то копируйте и вставляйте строчки с ThrowGib по-больше, но только не перестарайтесь...

QuakeC:Сообщения о смерти

Написано: автор st1x51
0

Автор: Timm 'Mr?' Stokke
eMail: hestokke@online.no
Сложность: Легкая

Это очень легкий урок для тех, кому надоели старые сообщения о смерти в Quake. После прочтения этого урока, вы сможете изменять сообщения в сетевой (DM) и одиночной (single) играх. Только для начинающих!
Шаг 1
Все эти изменения производятся в файле под именем client.qc, который нужно открыть для редактирования. Что мы будем делать, чтобы поменять сообщения о смерти, которые возникают все время после того, как вас убивает какой-нибудь монстр? Опуститесь в самый низ открытого файла, где описаны все сообщения о смерти от монстров, от самоубийства и от других игроков при сетевой игре. Мы будем изменять сообщения, появляющиеся при смерти от монстра. Итак, найдите текст, похожий на текст, приведенный в шаге 2.
Шаг 2
А сейчас перейдем непосредственно к редактированию собщений о смерти. Я думаю вы сделаете их немного по своему, потому я не буду приводить детали
if (attacker.flags & FL_MONSTER)
{
if (attacker.classname == "monster_army")
bprint (" was shot by a Grunt\n"); //вывести в верхнем левом углу " was shot by a Grunt".
if (attacker.classname == "monster_demon1")
bprint (" was eviscerated by a Fiend\n");
if (attacker.classname == "monster_dog")
bprint (" was mauled by a Rottweiler\n");
if (attacker.classname == "monster_dragon")
bprint (" was fried by a Dragon\n");
if (attacker.classname == "monster_enforcer")
bprint (" was blasted by an Enforcer\n");
if (attacker.classname == "monster_fish")
bprint (" was fed to the Rotfish\n");
if (attacker.classname == "monster_hell_knight")
bprint (" was slain by a Death Knight\n");
if (attacker.classname == "monster_knight")
bprint (" was slashed by a Knight\n");
if (attacker.classname == "monster_ogre")
bprint (" was destroyed by an Ogre\n");
if (attacker.classname == "monster_oldone")
bprint (" became one with Shub-Niggurath\n");
if (attacker.classname == "monster_shalrath")
bprint (" was exploded by a Vore\n");
if (attacker.classname == "monster_shambler")
bprint (" was smashed by a Shambler\n");
if (attacker.classname == "monster_tarbaby")
bprint (" was slimed by a Spawn\n");
if (attacker.classname == "monster_vomit")
bprint (" was vomited on by a Vomitus\n");
if (attacker.classname == "monster_wizard")
bprint (" was scragged by a Scrag\n");
if (attacker.classname == "monster_zombie")
bprint (" joins the Zombies\n");
return;
Шаг 3
И это все! Откомпилируйте это, и запустите полученное. Теперь идите и... хммм.. и дайте себя убить!

Darkplaces Cell shading

Написано: суббота, 2 февраля 2013 г. автор st1x51
0

Включается такими командами:
r_celshading 1
r_celoutlines 1
r_shadow_deferred 1



 

 

QuakeC: Звук

Написано: среда, 23 января 2013 г. автор st1x51
0

Функция: void sound (entity source, float channel, string sample, float volume, float attenuation)
  source = объект,излучающий звук (например: self)
  channel = канал,используемый для звука(например: CHAN_AUTO) 
 sample = имя wav файла (пример: "ogre/ogdrag.wav") 
 volume = 0.0 для низкой громкости, 1.0 для максимальной
 attenuation = звукоизоляция (например:ATTN_NONE)
 
Функция: void ambientsound(vector position, string sample, float volume, float attenuation)
position = положение в 3D пространстве внутри уровня 
sample = имя wav файла (пример: "ogre/ogdrag.wav") 
volume = 0.0 для низкой громкости, 1.0 для максимальной 
attenuation = звукоизоляция (например:ATTN_NONE)

QuakeC: Математические операции с векторами

Написано: автор st1x51
0

Функция: vector normalize(vector v)
 Возвращает вектор длины 1.Предоставляет вектор коллинеарный к V,но с длинной 1.Это может быть полезно для расчета расстояния вдоль оси.
Функция: float vlen(vector v)
Возвращает длину вектора V (не <0).
Функция: float vectoyaw(vector v)
Возвращает  угол в градусах из вектора.Вычисляет угол отклонения угла,соответствующий данному 3D направлению v.
Функция: vector vectoangles(vector v)
 Возвращает угол наклона (прицеливания(горизонтальной наводки?))  и угол отклонения(азимут) соответствующий данному 3D направлению v.

Функция: string vtos(vector v)
Печатает вектор в виде строки.

Функция: void makevectors(vector angles) 
                          angle = 'pitch yaw 0'
Вычисляет векторы, направленые вперед, вправо и вверх, в соответствии с предоставленным углом.
Возвращает результат в глобальные переменные:
vector  v_forward;  // указывает вперед
vector  v_up;       // указывает вверх
vector  v_right;    // указывает вправо