Уважаемые гости и новички, приветствуем Вас на нашем форуме
Здесь вы можете найти ответы практически на все свои вопросы о серии игр «Готика» (в том числе различных модах на нее), «Ведьмак», «Ризен», «Древние свитки», «Эра дракона» и о многих других играх. Можете также узнать свежие новости о разработке новых проектов, восхититься творчеством наших форумчан, либо самим показать, что вы умеете. Ну и наконец, можете обсудить общие увлечения или просто весело пообщаться с посетителями «Таверны».
Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно. Вам необходимо обновить браузер или попробовать использовать другой.
Я еще до конца не закончил перепроверку и чистку заклинания, но (благодаря помощи Saturas-a) удалось довести до ума основную механику. Выкладываю небольшой ролик в надежде услышать, что надо подправить. С эффектами я не заморачивался вообще. Надеюсь на днях закончить и написать развернутую инструкцию.
Вполне себе ничего) Но есть один баг(правда заметить сложно, но есть)
Когда предмет к себе подвигаешь, и вовремя не прекратить каст, то предмет может оказатся в "Центре" гг, что чревато тем что гг просто не сможет сдвинутся с места без марвина.
Bump: А по сути, респект) на днях свой закончу на г2ексте)
Выкладываю обещанную инструкцию по созданию скриптового заклинания телекинеза для Готики2 с возможностью компиляции готиксорсером. Как я уже писал, с эффектами мне было лень возиться, поэтому здесь используется покореженное заклинание ледяного копья. Учитывая существующие мануалы, не думаю, что для кого-то будет проблемой создать отдельное заклинание.
Выкладываемую версию я протестил и постарался предусмотреть защиту на возможные баги, но учитывая, что скриптингом под вторую Готику я никогда не занимался (я и под первую то по сути не занимался ), да и саму ее последний раз проходил несколько лет назад, мог что-то пропустить, поэтому буду благодарен за выловленные ошибки и постараюсь их исправить. Да, чуть не забыл: это все для версии Готики2НВ 2.6, на голде без фикса приводит к вылету.
Для работы нам понадобится старая версия скриптового пакета Икарус (новая слишком специфически использует работу движка и сорсер с ней помирить крайне проблематично) – ее можно найти в тексте обсуждения на немецком воге, классы двигателя и константы желательно брать из последний версий пакета: http://forum.worldofplayers.de/forum/showthread.php?t=969446 , а также пакет функций для работы с переменными типа float в представлении 32 bit IEEE 754: http://forum.worldofplayers.de/forum/showthread.php?t=500080
На всякий случай, выкладываю используемую мной подборку (классы oCNpc, oCItem, oCGame, oWorld, константы, Икарус и Floats32) – их желательно вставить поближе к началу *.src файла: Посмотреть вложение Ikarus_partial.rar. Икарус урезан – есть только необходимые функции, в которые при потребности были внесены правки для перевариваемости сорсером.
Приступим.
Для начала нам надо предоставить возможность заклинаниям ловить предмет в фокус. Для этого меняем в instance Focus_Magic(C_Focus) значение item_prio с -1 на 0.
Можно переходить к созданию инстанции самого заклинания. Сразу остановлюсь на двух моментах. Первое: как только спелы начинают брать в фокус предметы, двиг подкидываем в нагрузку известный по первой Готике баг: если при зажатой ЛК спрятать руну/свиток, то быстрым кликом все той же ЛК можно подобрать предмет на любом расстоянии. Как это убрать, я подробно описывал в теме по лечению багов в Г1, так что детально останавливаться не буду. Второе: для плавного движения предмета нам понадобится цикл с таймером. В случае создания заклинания наилучший подобный цикл сама функция Spell_Logic_нашезаклинание, возвращающая SPL_NEXTLEVEL: период отработки будет задаваться соотношение двух величин - time_per_mana и маны, необходимой для перехода на следующий уровень. Итак, имеем:
Код:
[COLOR=Blue]//стоимость перехода на следующий уровень[/COLOR]
const int STEP_Icelance=1;
[COLOR=Blue]//счетчик цикла[/COLOR]
var int stage;
[COLOR=Blue]//сбивание фокуса при убирании свитка[/COLOR]
func int Spell_Icelance_focus_remover()
{
var oCNpc Npc; Npc = Hlp_GetNpc( hero );
Npc.focus_vob=0;
[COLOR=Blue]//подстраховочное обнуление счетчика[/COLOR]
stage=0;
return false;
};
instance Spell_Icelance(C_Spell_Proto)
{
time_per_mana = 30;
spelltype = SPELL_NEUTRAL;
targetCollectRange = 5000;
targetCollectAlgo = TARGET_COLLECT_FOCUS;
[COLOR=Blue]//чтобы ловило предметы[/COLOR]
targetCollectType = TARGET_TYPE_ITEMS;
[COLOR=Blue]//сбивание фокуса при убирании свитка[/COLOR]
canTurnDuringInvest = Spell_Icelance_focus_remover();
canChangeTargetDuringInvest = false;
};
Пришла очередь тела заклинания. Ассоциируем instance oCItem_Telekinesis (oCItem) с нашим предметом (ссылка на него хранится в Npc.focus_vob) с помощью функции MEM_AssignInst(temp, Npc.focus_vob). Для компиляции в сорсере используем промежуточную переменную с переопределенным типом, которую для компиляции нужно дописать в файл GothicSourcer/ System/RedefinedLocalVariable.dsc следующим образом: int# Spell_Logic_Icelance.temp; (сразу советую дописать туда же int# MEM_InitGlobalInst.game; - она используется в исправленном Икарусе):
Код:
var int temp;
temp = oCItem_Telekinesis;
MEM_AssignInst (temp, Npc.focus_vob);
Для расчета шага движения используем следующие функции из Floats32 (без них никак – Даэдалус с флотами не дружит): аddf – сумма двух float; subf - разница двух float; divf – отношение двух float; mkf – делает из простого int равное ему, но записанное в формате 32 bit IEEE 754.
Координаты кастера и предмета содержатся в _zCVob_trafoObjToWorld соответствующих классов. Данная переменная – массив из 16 элементов сделанный из матрицы 4х4. Последняя строчка пустая, а первые три по столбцам содержат 3 вектора ориентации и координату VOB-а, т.е. нас интересуют элементы [3],[7] и [11]. Не забывайте о путанице с Y и Z – вертикаль в [7]. Еще один важный момент – при движении надо менять координаты как предмета в _zCVob_trafoObjToWorld, так и координаты bbox3D в _zCVob_bbox3D_mins и _zCVob_bbox3D_maxs, т.к. они задаются не в относительной, а в абсолютной системе координат. Теперь все это собираем вместе. Дополнительно вводим счетчик шагов – с его помощью можно регулировать потребление маны, а заодно и задавать алгоритм движения на разных стадиях заклинания (не забываем его обнулить, заодно желательно добавить для надежности запасное обнуление в функцию сбивания фокуса – неизвестно как поведет себя двиг игры при избиении кастера в неподходящий момент). Сейчас в коде подстраховочная начальная стадия движения, чтобы предметы не проваливались под поверхность мира – грубый вариант, подымает на высоту bbox3D. Можно добавить просто постепенное поднятие первые n шагов движения. Советую подганять под потребности мода – если предметы прятать под потолком пещеры, поднятие нежелательно.
Код:
instance oCItem_Telekinesis (oCItem);
var int step_x;
var int step_y;
var int step_z;
var int numb_of_steps;
[COLOR=Blue]//функция движения предмета[/COLOR]
func void new_Telekinesis ()
{
oCItem_Telekinesis._zCVob_trafoObjToWorld[3]=addf(oCItem_Telekinesis._zCVob_trafoObjToWorld[3],step_x);
oCItem_Telekinesis._zCVob_trafoObjToWorld[7]=addf(oCItem_Telekinesis._zCVob_trafoObjToWorld[7],step_z);
oCItem_Telekinesis._zCVob_trafoObjToWorld[11]=addf(oCItem_Telekinesis._zCVob_trafoObjToWorld[11],step_y);
oCItem_Telekinesis._zCVob_bbox3D_mins[0]=addf(oCItem_Telekinesis._zCVob_bbox3D_mins[0],step_x);
oCItem_Telekinesis._zCVob_bbox3D_mins[1]=addf(oCItem_Telekinesis._zCVob_bbox3D_mins[1],step_z);
oCItem_Telekinesis._zCVob_bbox3D_mins[2]=addf(oCItem_Telekinesis._zCVob_bbox3D_mins[2],step_y);
oCItem_Telekinesis._zCVob_bbox3D_maxs[0]=addf(oCItem_Telekinesis._zCVob_bbox3D_maxs[0],step_x);
oCItem_Telekinesis._zCVob_bbox3D_maxs[1]=addf(oCItem_Telekinesis._zCVob_bbox3D_maxs[1],step_z);
oCItem_Telekinesis._zCVob_bbox3D_maxs[2]=addf(oCItem_Telekinesis._zCVob_bbox3D_maxs[2],step_y);
[COLOR=Blue]//наложение эффекта[/COLOR]
Wld_PlayEffect("spellFX_ItemAusbuddeln",oCItem_Telekinesis,oCItem_Telekinesis,0,0,0,FALSE);
};
func int Spell_Logic_Icelance(var int manaInvested)
{
var oCNpc Npc; Npc = Hlp_GetNpc( self );
if (stage==0)
{
[COLOR=Blue]//привязка предмета в фокусе к инстанции oCItem_Telekinesis [/COLOR]
var int temp;
temp = oCItem_Telekinesis;
MEM_AssignInst (temp, Npc.focus_vob);
[COLOR=Blue]//расчет размера сдвига по осям исходя из шага в 10 единиц[/COLOR]
numb_of_steps=Npc_GetDistToItem(self, oCItem_Telekinesis)/10;
step_x=divf(subf(Npc._zCVob_trafoObjToWorld[3],oCItem_Telekinesis._zCVob_trafoObjToWorld[3]),mkf(numb_of_steps));
step_z=divf(subf(Npc._zCVob_trafoObjToWorld[7],oCItem_Telekinesis._zCVob_trafoObjToWorld[7]),mkf(numb_of_steps));
step_y=divf(subf(Npc._zCVob_trafoObjToWorld[11],oCItem_Telekinesis._zCVob_trafoObjToWorld[11]),mkf(numb_of_steps));
};[COLOR=Blue]
//подстраховочная проверка на расстояние, чтобы не произошло наложение анимации перехода в состояние кастования и убирания свитка в конце[/COLOR]
if(self.attribute[ATR_MANA] < STEP_Icelance)||((stage==0)&(Npc_GetDistToItem(self, oCItem_Telekinesis)<180))
{
return SPL_DONTINVEST;
};
if(manaInvested <= STEP_Icelance)
{
return SPL_STATUS_CANINVEST_NO_MANADEC;
}
else if (manaInvested > STEP_Icelance)
{[COLOR=Blue]
//регулировка потребления маны – при таких значениях 1 мана на 10 циклов -100 единиц расстояния [/COLOR]
if ((stage-1)%10==0)
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - STEP_Icelance;
};
if(self.attribute[ATR_MANA] < 0)
{
self.attribute[ATR_MANA] = 0;
};
[COLOR=Blue]//автоматическая остановка при приближении предмета[/COLOR]
if (Npc_GetDistToItem(self, oCItem_Telekinesis)<150)
{
[COLOR=Blue]//при остановке каста закинет в Spell_ProcessMana_Release [/COLOR]
return SPL_STATUS_CANINVEST_NO_MANADEC;
};
[COLOR=Blue]//подстраховочная стадия движения[/COLOR]
if (stage==0)
{
var int start_z;
start_z=subf(oCItem_Telekinesis._zCVob_bbox3D_maxs[1],oCItem_Telekinesis._zCVob_bbox3D_mins[1]);
oCItem_Telekinesis._zCVob_trafoObjToWorld[7]=addf(oCItem_Telekinesis._zCVob_trafoObjToWorld[7],start_z);
oCItem_Telekinesis._zCVob_bbox3D_mins[1]=addf(oCItem_Telekinesis._zCVob_bbox3D_mins[1],start_z);
oCItem_Telekinesis._zCVob_bbox3D_maxs[1]=addf(oCItem_Telekinesis._zCVob_bbox3D_maxs[1],start_z);
Wld_PlayEffect("spellFX_ItemAusbuddeln",oCItem_Telekinesis,oCItem_Telekinesis,0,0,0,FALSE);
};
[COLOR=Blue]//вызов функции сдвига[/COLOR]
new_Telekinesis();
stage+=1;
return SPL_NEXTLEVEL;
};
};
Теперь осталось только «уронить» подтянутый предмет на землю. Для этого нам понадобится класс двига oWorld – функция его привязке к инстанции MEM_World (немного подправленная) MEM_InitGlobalInst() содержится в пакете Икарус – ее желательно запихнуть в функцию инициализации мира при загрузке сейва, если пакет скриптов планируется использовать не только для этого заклинания. Далее делаем следующее: включаем «физику» нашему предмету, отключаем режим «sleep» и заносим в activeVobList (содержит ссылки на все VOB-ы, физика/AI которых отслеживается двигом). Еще надо не забыть убрать из инвентаря использованный свиток – т.к. заклинание вроде как не кастуется, двиг за нас этого не сделает. Полученный код добавляем в Spell_ProcessMana_Release – именно к ней обратится наше заклинание при остановке вкачивания маны:
Код:
func int Spell_ProcessMana_Release(var int manaInvested)
{
...
if(activeSpell == SPL_IceLance)
{
if (stage>0)
{
var oCNpc Npc; Npc = Hlp_GetNpc( self );
MEM_InitGlobalInst();
[COLOR=Blue]//включаем физику[/COLOR]
oCItem_Telekinesis._zCVob_bitfield [0] = oCItem_Telekinesis._zCVob_bitfield [0] | zCVob_bitfield0_physicsEnabled;
[COLOR=Blue]//отключаем режим «sleep»[/COLOR]
oCItem_Telekinesis._zCVob_bitfield[2]=oCItem_Telekinesis._zCVob_bitfield[2] | zCVob_bitfield2_sleepingMode;
[COLOR=Blue]//записываем в activeVobList
[/COLOR] MEM_WriteInt(MEM_World.activeVobList_array+4*(MEM_World.activeVobList_numInArray), Npc.focus_vob);
[COLOR=Blue]//сообщаем, что activeVobList стал на 1 элемент длиннее[/COLOR]
MEM_World.activeVobList_numInArray+=1;
[COLOR=Blue]//проверка на свиток/руну[/COLOR]
if(Npc_GetActiveSpellIsScroll(self))
{
[COLOR=Blue]//убираем свиток в инвентарь на случай если последний[/COLOR]
AI_UnreadySpell(self);
[COLOR=Blue]//забираем свиток из инвентаря[/COLOR]
Npc_RemoveInvItems(self,ItSc_Icelance,1);
}
else
{
[COLOR=Blue]//просто чтобы заклинание при использовании свитка и руны выглядело одинаково[/COLOR]
AI_UnreadySpell(self);
};
stage=0;
};
return SPL_SENDSTOP;
};
...
};
Вроде ничего не забыл
P.S. Просьба к администрации - исправьте, плиз, опечатку в названии темы.
Не совсем понял формулировку... Это просто определяется размер шага по каждой из осей так чтобы вектор направления сохранялся, а расстояние между ГГ и итемом сокращалось на заданную величину (в данном случае порядка 10 единиц).
Saturas, может сдвиг типа x = (pos.f[0] - pitem.f[0]) / 500; лучше делить не на 500, а на расстояние между ГГ и вобом, чтобы была одинаковая скорость движения, а не время доставки итема к цели?
Товарищи, кто занимается плагинами, есть вопрос.
Есть ли нормальный способ реализовать перемещение вобов с помощью телекинеза?
Я пока сделал навскидку один способ- связка (итем + мобси-сундук), но он извратный и имеет ряд ограничений:
1) итем можно поднять, причём напару с сундуком
2) при закле перемещается итем, а сундук уже телепортируется за ним в конце.
Что же, товарищи, перемещение сундуков-то я сделал, но работает тоже корявенько, само перемещение то срабатывает, то срабатывает после сохранения игры
Сам механизм как из заклинания телепорта, но, чтобы цель ловилась в фокус, изменил вот что:
instance Focus_Magic(C_Focus)
{
...
mob_prio = 0;
};
И при вынимании заклинания, ловли в фокус, можно нажимать быструю клавишу, к которой привязана функция.
Если кто поможет, буду рад, ибо не имел ещё тесных контактов с пакетом Икаруса.
George_M,
В телекинезе redleha обнаружил фатальный баг приводящий к вылету игры, если используется последний свиток. Общими усилиями баг удалось побороть.
К телу закла был добавлен Spell_Cast_xxx и в него перенесено все (за исключением принудительного удаления свитка) что было в Spell_ProcessMana_Release. В самом же Spell_ProcessMana_Release теперь выглядит так
при передаче в Spell_Cast_xxx последний свиток удаляется движком игры без вылета.
Также убран AI_UnreadySpell(self); - движек в Spell_Cast_xxx также сам нормально убирает заклинание.
Переработанный телекинез с основными правками Редакция от 22.05.2012
Код:
const int SPL_Cost_Telekinesis = 1;
const int STEP_Telekinesis = 1;
var int stage;
//счетчик цикла
//var int stage;
//сбивание фокуса при убирании свитка
func int Spell_Telekinesis_focus_remover()
{
var oCNpc Npc; Npc = Hlp_GetNpc( hero );
Npc.focus_vob=0;
//подстраховочное обнуление счетчика
stage=0;
return false;
};
instance oCItem_Telekinesis(oCItem);
var int step_x;
var int step_y;
var int step_z;
var int numb_of_steps;
//функция движения предмета
func void new_Telekinesis ()
{
oCItem_Telekinesis._zCVob_trafoObjToWorld[3]=addf(oCItem_Telekinesis._zCVob_trafoObjToWorld[3],step_x);
oCItem_Telekinesis._zCVob_trafoObjToWorld[7]=addf(oCItem_Telekinesis._zCVob_trafoObjToWorld[7],step_z);
oCItem_Telekinesis._zCVob_trafoObjToWorld[11]=addf(oCItem_Telekinesis._zCVob_trafoObjToWorld[11],step_y);
oCItem_Telekinesis._zCVob_bbox3D_mins[0]=addf(oCItem_Telekinesis._zCVob_bbox3D_mins[0],step_x);
oCItem_Telekinesis._zCVob_bbox3D_mins[1]=addf(oCItem_Telekinesis._zCVob_bbox3D_mins[1],step_z);
oCItem_Telekinesis._zCVob_bbox3D_mins[2]=addf(oCItem_Telekinesis._zCVob_bbox3D_mins[2],step_y);
oCItem_Telekinesis._zCVob_bbox3D_maxs[0]=addf(oCItem_Telekinesis._zCVob_bbox3D_maxs[0],step_x);
oCItem_Telekinesis._zCVob_bbox3D_maxs[1]=addf(oCItem_Telekinesis._zCVob_bbox3D_maxs[1],step_z);
oCItem_Telekinesis._zCVob_bbox3D_maxs[2]=addf(oCItem_Telekinesis._zCVob_bbox3D_maxs[2],step_y);
//наложение эффекта
/*
Wld_PlayEffect("spellFX_ItemAusbuddeln",oCItem_Telekinesis,oCItem_Telekinesis,0,0,0,FALSE);
*/
};
instance Spell_Telekinesis(C_Spell_Proto)
{
time_per_mana = 30;
spelltype = SPELL_NEUTRAL;
targetCollectRange = 10000;
targetCollectAlgo = TARGET_COLLECT_FOCUS;
targetCollectType = TARGET_TYPE_ITEMS;
canTurnDuringInvest = Spell_Telekinesis_focus_remover();
canChangeTargetDuringInvest = false;
};
func int Spell_Logic_Telekinesis(var int manaInvested)
{
var oCNpc Npc; Npc = Hlp_GetNpc(self);
if(stage == 0)
{
//привязка предмета в фокусе к инстанции oCItem_Telekinesis
var int temp;
temp = oCItem_Telekinesis;
MEM_AssignInst(temp, Npc.focus_vob);
//расчет размера сдвига по осям исходя из шага в 10 единиц
numb_of_steps = Npc_GetDistToItem(self, oCItem_Telekinesis)/10;
step_x = divf(subf(Npc._zCVob_trafoObjToWorld[3],oCItem_Telekinesis._zCVob_trafoObjToWorld[3]),mkf(numb_of_steps));
step_z = divf(subf(Npc._zCVob_trafoObjToWorld[7],oCItem_Telekinesis._zCVob_trafoObjToWorld[7]),mkf(numb_of_steps));
step_y = divf(subf(Npc._zCVob_trafoObjToWorld[11],oCItem_Telekinesis._zCVob_trafoObjToWorld[11]),mkf(numb_of_steps));
};
//подстраховочная проверка на расстояние, чтобы не произошло наложение анимации перехода в состояние кастования и убирания свитка в конце
if((self.attribute[ATR_MANA] < STEP_Telekinesis) || ((stage==0) && (Npc_GetDistToItem(self, oCItem_Telekinesis) < 180)))
{
return SPL_DONTINVEST;
};
if(manaInvested <= STEP_Telekinesis)
{
return SPL_STATUS_CANINVEST_NO_MANADEC;
}
else if(manaInvested > STEP_Telekinesis)
{
//регулировка потребления маны – при таких значениях 1 мана на 10 циклов -100 единиц расстояния
if((stage - 1) % 10 == 0)
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - STEP_Telekinesis;
};
if(self.attribute[ATR_MANA] < 0)
{
self.attribute[ATR_MANA] = 0;
};
//автоматическая остановка при приближении предмета
if(Npc_GetDistToItem(self, oCItem_Telekinesis) < 150)
{
//при остановке каста закинет в Spell_ProcessMana_Release
return SPL_SENDCAST;//SPL_STATUS_CANINVEST_NO_MANADEC;
};
//подстраховочная стадия движения
if(stage==0)
{
var int start_z;
start_z = subf(oCItem_Telekinesis._zCVob_bbox3D_maxs[1],oCItem_Telekinesis._zCVob_bbox3D_mins[1]);
oCItem_Telekinesis._zCVob_trafoObjToWorld[7] = addf(oCItem_Telekinesis._zCVob_trafoObjToWorld[7],start_z);
oCItem_Telekinesis._zCVob_bbox3D_mins[1] = addf(oCItem_Telekinesis._zCVob_bbox3D_mins[1],start_z);
oCItem_Telekinesis._zCVob_bbox3D_maxs[1] = addf(oCItem_Telekinesis._zCVob_bbox3D_maxs[1],start_z);
Wld_PlayEffect("spellFX_ItemAusbuddeln",oCItem_Telekinesis,oCItem_Telekinesis,0,0,0,FALSE);
};
//вызов функции сдвига
new_Telekinesis();
stage += 1;
return SPL_NEXTLEVEL;
}
else if(Npc_GetDistToItem(self, oCItem_Telekinesis) < 150)
{
return SPL_SENDCAST;
};
return SPL_STATUS_CANINVEST_NO_MANADEC;
};
[COLOR="DarkRed"]func void Spell_Cast_Telekinesis()
{
var oCNpc Npc; Npc = Hlp_GetNpc(self);
MEM_InitGlobalInst();
//включаем физику
oCItem_Telekinesis._zCVob_bitfield[0] = oCItem_Telekinesis._zCVob_bitfield[0] | zCVob_bitfield0_physicsEnabled;
//отключаем режим «sleep»
oCItem_Telekinesis._zCVob_bitfield[2] = oCItem_Telekinesis._zCVob_bitfield[2] | zCVob_bitfield2_sleepingMode;
//записываем в activeVobList
MEM_WriteInt(MEM_World.activeVobList_array + 4*(MEM_World.activeVobList_numInArray),Npc.focus_vob);
//сообщаем, что activeVobList стал на 1 элемент длиннее
MEM_World.activeVobList_numInArray += 1;
stage = 0;
self.aivar[AIV_SelectSpell] += 1;
};[/COLOR]
Что же, товарищи, перемещение сундуков-то я сделал, но работает тоже корявенько, само перемещение то срабатывает, то срабатывает после сохранения игры
Сам механизм как из заклинания телепорта, но, чтобы цель ловилась в фокус, изменил вот что:
instance Focus_Magic(C_Focus)
{
...
mob_prio = 0;
};
И при вынимании заклинания, ловли в фокус, можно нажимать быструю клавишу, к которой привязана функция.
Если кто поможет, буду рад, ибо не имел ещё тесных контактов с пакетом Икаруса.
На данном сайте используются файлы cookie, чтобы персонализировать контент и сохранить Ваш вход в систему, если Вы зарегистрируетесь.
Продолжая использовать этот сайт, Вы соглашаетесь на использование наших файлов cookie.