Svoboда 3 Опубликовано 23 Апреля 2009 Поделиться Опубликовано 23 Апреля 2009 Тема для обсуждения скриптов всего и всех в серии игр STALKER. Задавая вопрос (!): 1. Внимательно изучите суть вопроса. Вопрос должен соответствовать выбранной Вами темы. Это поможет сохранить порядок и читабельность темы, а также облегчит поиск и понимание сего; 2. Изучите то, что уже есть в теме (пролистайте "руками", воспользуйтесь поиском на форуме); 3. Изучите информацию которая может вам помочь: Stalkerin. Там есть много хороших статей касательно данной темы.Уроки по модостроению. Есть рабочие примеры готовых скриптов различного назначения. Справочное руководство по языку Lua 5.1https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual/ruСправочник по функциям и классам. Собрано много информации по функциям и классам, не всем, но по основные сведения предоставлены. Логика со вступлением и четырьмя частями: ВступлениеЧасть перваяЧасть втораяЧасть третьяЧасть четвертая. Smart_terrain (в простонароде - гулаг)Интересный способ настроики логики для гулаговСкриптовая часть игровой логики 4. Дабы не превращать обсуждение в "кашу" разной информативной направленности, задавайте несколько вопросов по порядку (в разных постах) после того, как получите ответ на предыдущий вопрос; 5. "Спасибо" и тому подобное - будьте так любезны в ПМ. Если не любите писать в ПМ, в конце вопроса напишите фразу: "Заранее спасибо!" - или что-то в этом духе; 6. ПОЖАЛУЙСТА! Указывайте, для какой игры Вам необходима информация (ТЧ, ЧН, ЗП), если стоит мод - укажите название мода; 7. Если Вы что-то сделали и результат не такой, какой Вами задумывался, то, пожалуйста, приводите коды которые Вы изменяли/писали целиком! Это поможет другим правильно ответить на Ваш вопрос, а также оградит Вас от лишней писанины. 8. Оформляйте сообщение. Пользуйтесь тегами для того, чтобы отделить код от текста. Пишите грамотно - ПОЛЬЗУЙТЕСЬ ЗНАКАМИ ПРЕПИНАНИЯ. 9. И помните: «Правильно заданный вопрос – половина ответа». Какие вопросы следует задавать, а какие нет... Задавайте вопросы, которые касаются непосредственно скриптов и их работы, т.е. Вы что-то делаете, а у Вас что-то не получается, при этом у Вас на руках должен быть хотя бы какой-то код, свидетельствующий о Вашей причастности к вопросу. Вопросы которые будут удалятся, следовательно их задавать не нужно:-- Где находится та или иная функция? Для ответа используем поиск по словам среди файлов оригинальной игры или мода, если объект поиска относится к нему, при помощью программы, которая Вам наиболее симпатизирует;-- Как сделать что-то/то-то? С подобными вопросами, либо в "ковырялки", где Вам вероятнее всего так же не ответят, либо выдвигаем мысли, подкреплённые теорией, практикой (идеальный вариант) и здравым рассудком;-- Вопросы со смыслом: "сделайте", "совместите" и подобными глаголами повелительного наклонения.-- К тому же удалению будут подвергаться вопросы, в которых масштабно не используются теги, для отделения кода и цитат от основного текста, а также не вписан в спойлер код размером превышающие семь строк.Ответ на возможно возникший вопрос: В какую тему можно обратиться по поводу логики и спавна объектов? В тему "ковырялок" соответствующей версии игры, для которой Вы задаёте вопрос. И последнее: очень рекомендовано к прочтению Правила форума 1 2 Ссылка на комментарий
abramcumner 1229 Опубликовано 7 Сентября 2011 Поделиться Опубликовано 7 Сентября 2011 (изменено) _Призрак_, у машины небось стоит маленькая масса, а у гранаты большой импульс - обычная физика Скажи спасибо, что машина вообще не взрывается. Изменено 7 Сентября 2011 пользователем abramcumner Ссылка на комментарий
Artos 99 Опубликовано 7 Сентября 2011 Поделиться Опубликовано 7 Сентября 2011 (изменено) _Призрак_ То, что машина спавнится точно по координатам - никогда не скажу. Т.к. если спавнится в all.spawn'е - то да, 'точно', если скриптом - о точности только помечтать можно ... Что на нее не действуют законы физики? Хм, и да и нет, но точно, что именно после первого хита, она начинает подчиняется неким игровым 'законам физики'. Будет ли она скатываться от первого хита? У горе-ковырялкина возможно ... Все зависит от собственно силы и импульса хита. Можно и в небо запулить. ;-) По сути: Если хочешь точно застопорить машину - то посмотри ранее посты, где давал уже варианты ступоров, т.е. или 'collide' или 'fixed_bones'. Если же машина для 'езды' - то придется с нет-пакетами (иль еще как) поупражняться, например, отключая ступор(ы) при посадке и включая их при высадке ГГ. Изменено 7 Сентября 2011 пользователем Artos Ссылка на комментарий
*Shoker* 322 Опубликовано 7 Сентября 2011 Поделиться Опубликовано 7 Сентября 2011 (изменено) _Призрак_ local obj = -- клиентский объект машины xr_logic.mob_capture(obj, true) -- берём машину под логику action(obj, move(move.handbrake, 100), cond(cond.time_end, 5000)) Поставив такое на апдейт, ты заставишь машину встать на тормоз, но это касается заведённой машины, насчёт выключенной хз будет работать или нет. Ты можешь сам попробовать - в lua_help найди C++ class move { и пробуй различные варианты. Методы отлично работают, даже если ГГ в машине. Добавлено через 171 мин.: Есть ли способ переместить объекты из инвентаря ГГ в только что заспавненный серверный объект-ящик? Чтобы обойтись без отлова выхода в онлаин? Изменено 7 Сентября 2011 пользователем *Shoker* Ссылка на комментарий
Artos 99 Опубликовано 8 Сентября 2011 Поделиться Опубликовано 8 Сентября 2011 (изменено) *Shoker* Молодец, что и мне напомнил, а то как-то начал делать и ... не закончил. Однако более правильным будет несколько иначе: 1. Функция/метод остановки и постановки на 'ручник' машины уже полностью реализована в схеме машин ( ph_car.script -> action_car:stop_car() ) и если объект под этой схемой - то и использовать встроенный функционал. Если же не под схемой (чего правда не встречал) - то и работать не будет. 2. В твоей строке задается некий аргумент =100? А это задание условной скорости - т.о. этот аргумент при остановке логично ставить в 0. 3. Дополнительно к 'move.handbrake' есть резон задавать константу остановки 'move.off', т.е. 'move.off + move.handbrake'. Взятие же машины под контроль удобнее делать под апдейтом самой 'машинной схемы' ( action_car:update(delta) ), что-то типа: --/ Управление 'ручником' автотранспорта --/ oCar: game_object машины --/ bAction: true=>'стоп', false=>'разрешено движение' function Car_Handbrake(oCar,bAction) local st = db.storage[oCar:id()] --/ сторадж объекта if st and st.car_mgr then --/ менеджер схемы 'ph_car' st.car_mgr .on_handbrake = bAction --/ ставим флаг: вкл/откл ручника end end function action_car:update(delta) --/ из ph_car.script -- ... --/ внешнее управление 'ручником' (остановкой) if self.on_handbrake and (self.time_handbrake or 0) < time_global() then --/ включить ручник? self.time_handbrake = time_global() + 3000 --/ тайм-аут self:stop_car() self.state_moving = iState_moving_end end end Примечание: Машина должна быть 'забиндена' (иметь сторадж в db.storage). Постановка на ручник работает независимо от (от)включенного двигателя или отсутсвия актора внутри. При движении машины - естественно ручник (on_handbrake) должен быть 'снят'. --------------------------------------- Переместить объекты из инвентаря ГГ в иной серверный объект (хотя бы и ящик) - невозможно. Методы трансфера доступны только для гейм-объектов. Если же под 'перемещением' подразумевается возможность удаление предмета и воссоздание его копии в нужном месте - это иной разговор ... Думаю мороки будет поболе, чем дождаться перехода ящика в онлайн, если озаботиться точными копиями ... Изменено 8 Сентября 2011 пользователем Artos Ссылка на комментарий
Mass 5 Опубликовано 8 Сентября 2011 Поделиться Опубликовано 8 Сентября 2011 (изменено) Всем привет! Хочу поделиться тем что нашел. В конце функции pstor_retrieve в xr_logic есть заремленный 'abort', так вот если его раскоментить и поставить перед return nil, то вылезет очень много проблем с функциями pstor_retrieve. Наподобии этих... ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'timers' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_timer_1' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'xt1' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_gtimer_1' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'gt1' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_timer_2' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'xt2' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_gtimer_2' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'gt2' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_timer_3' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'xt3' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_gtimer_3' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'gt3' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_timer_4' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'xt4' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_gtimer_4' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'gt4' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_timer_5' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'xt5' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_gtimer_5' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'gt5' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_timer_6' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'xt6' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_gtimer_6' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'gt6' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_timer_7' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'xt7' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_gtimer_7' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'gt7' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_timer_8' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'xt8' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_gtimer_8' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'gt8' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_timer_9' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'xt9' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_gtimer_9' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'gt9' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_timer_10' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'xt10' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_gtimer_10' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'gt10' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_timer_11' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'xt11' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_gtimer_11' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'gt11' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'x_timer_12' does not exist * Log file has been saved successfully! ! Cannot find saved game ~~~ xr_logic: pstor_retrieve: variable 'xt12' does not exist * Log file has been saved successfully! и т д И это проблема почти всех модов на базе amk Изменено 8 Сентября 2011 пользователем Mass Ссылка на комментарий
abramcumner 1229 Опубликовано 8 Сентября 2011 Поделиться Опубликовано 8 Сентября 2011 Mass, ) А зачем ты сделал, то что сделал? А если аборт переставить в начало функции, то вылезет очень много проблем и в оригинальной игре. Скажи в чем по-твоему заключаются проблемы? Ссылка на комментарий
*Shoker* 322 Опубликовано 8 Сентября 2011 Поделиться Опубликовано 8 Сентября 2011 (изменено) abramcumner Он видимо имел ввиду, что вылезает очень много не найденных переменных в псторе. Mass Это нормально, т.к когда такая функция вызывается первый раз в игре, обычно вызываемая из пстора переменная ещё не была сохранена, и тогда возвращается не nil, а "значение по умолчанию" if defval ~= nil then return defval end Далее уже если переменная будет сохранена, то уже не будет возвращать значение по умолчанию, а то что ты в неё сохранил (до конца игры, или пока не удалишь её сам). Иногда бывает что значение по умолчанию = nil, именно это происходит в твоём случае. и это тоже нормально. Artos Честно говоря я до конца не разбирался в этих функциях, спасибо что разъяснил. 1) Это верно, просто в ЧН/ЗП где то из них эти скрипты вырезали. Можно их вернуть конечно, а можно более мелким методом обойтись. Тут уже желание автора будет. 2) А где нибудь есть разъяснение, какие аргументы ещё можно передавать в другие move-действия? Ну и в догонку тогда уже интересует cond(cond.time_end, 5000) Я так понял, через 5 секунд машина прекратит выполнять это действие, или как? Просто во время моих тестов, насколько я помню, этот параметр ни на что не влиял. Насчёт перемещения всё ясно, я просто хочу реализовать, чтобы изношенные предметы не попадали в продажу. Сейчас приходится спавнить ящик и кидать все вещи туда, а по окончанию диалога возвращать их. Просто думал, может есть ещё более компактные варианты, кроме как колбека спавна ящика через level.client_spawn_manager() Кстати, в ЧН никто не знает как определить начало\конец торговли? В pda.script из колбеков рабочий тока на открытие окна диалога, а при выходе в окно торговли, диалог считается закрытым, и вещи возвращаются ГГ. Пробовал через инфопоршни, но ui_trade возвращал false. Терь думаю, можно ли присобачить на апдейт level.main_input_receiver(), и отлавливать там появление кнопки "Trade", не будет ли код глючить в игре. Добавлено через 20 мин.: const trade_start = 0; const trade_stop = 1; Нашёл такое, надеюсь сработают. Изменено 8 Сентября 2011 пользователем *Shoker* Ссылка на комментарий
Painter 3574 Опубликовано 8 Сентября 2011 Поделиться Опубликовано 8 Сентября 2011 (изменено) Подскажите, как можно удалить через скрипт всех имеющихся фантомов на локации? Пример функции: if (phantom_manager:phantom_count()>1) then --Удаление фантомов :-) end end P.S. Для ЗП. Изменено 8 Сентября 2011 пользователем Jurok Ссылка на комментарий
Artos 99 Опубликовано 8 Сентября 2011 Поделиться Опубликовано 8 Сентября 2011 (изменено) Jurok А в чем заминка самому написать простенький скрипт удаления? Ведь все просто и очевидно: if phantom_manager:phantom_count() > 1 then --/ Удаление фантомов local sim = alife() for id=1,65534 do local soObj = sim:object(id) if soObj and soObj:clsid() == clsid.phantom then alife():release(soObj, true) --/ удаляем end end end или для текущего уровня: if phantom_manager:phantom_count() > 1 then --/ Удаление фантомов на текущем уровне local sim = alife() for id=1,65534 do local oObj = level.object_by_id(id) --/ на текущем уровне? if oObj and oObj:clsid() == clsid.phantom then local soObj = sim:object(id) if soObj then alife():release(soObj, true) --/ удаляем end end end end Добавлено через 11 мин.: *Shoker*: А где нибудь есть разъяснение, какие аргументы ещё можно передавать в другие move-действия? Ну и в догонку тогда уже интересует 'cond(cond.time_end, 5000)' Кроме информации в 'lua_help.script' и кодах оригинальных игр - не встречал толковалок. Немного сам поразбирался ... Вот что получилось: move.none, --/ 1 move.on + move.fwd, --/ 256 +2 вперед move.on + move.fwd + move.left, --/ 256 +2 +8 вперед-налево move.on + move.fwd + move.right, --/ 256 +2 +16 вперед-направо move.on + move.back, --/ 256 +4 назад move.on + move.back + move.left, --/ 256 +4 +8 назад-налево move.on + move.back + move.right, --/ 256 +4 +16 назад-направо move.off, --/ 512 стоп move.off + move.handbrake --/ 512 +128 стоп+постановка на ручник Да и по 'cond.time_end' также только догадки. Судя по тестам - ты прав в догадке, что это таймер периода окончания действия, которое устанавливается строкою: action( object, move(const, speed), cond(const, time) ), после которого (судя по тестам) вызывается новая (пере)установка 'action'. Изменено 8 Сентября 2011 пользователем Artos Ссылка на комментарий
KASIMKA 0 Опубликовано 8 Сентября 2011 Поделиться Опубликовано 8 Сентября 2011 Доброго времени суток! Переписываю схему heli hunter: в функции evaluator_shoot:evaluate() делаю проверку на огневую мощь НПС, при выполнении условия отправляю их в укрытие. if self.fire_power < 3 then self.object:set_detail_path_type(move.line) self.object:set_path_type(game_object.level_path) local hide,lvid = nearest_hide(self.object) utils.send_to_nearest_accessible_vertex(self.object,lvid) state_mgr.set_state(self.object,"sprint") return false end --[[------------------------------------------------------------------------------------------------------------------ Схема "Охотник за вертолётами" Чугай Александр --------------------------------------------------------------------------------------------------------------------]] local def_attack_dist = 200 -- расстояние, на котором вертолёт может быть атакован local def_actor_dist = 50 -- расстояние, на котором игрок может быть атакован function get_nearest_heli(npc_position, attack_dist_sqr) -- print_table(db.heli) local heli = nil for k,v in pairs(db.heli) do if v:position():distance_to_sqr(npc_position) <= attack_dist_sqr and (heli == nil or v:position():distance_to_sqr(npc_position) < heli:position():distance_to_sqr(npc_position)) then heli = v end end return heli end --------------------------------------------------------------------------------------------------------------------- -- Эвалуатор свойства "можно пострелять по вертолёту" --------------------------------------------------------------------------------------------------------------------- local overrides class "evaluator_shoot" ( property_evaluator ) function evaluator_shoot:__init( name, a ) super( nil, name ) self.a = a end function evaluator_shoot:evaluate() if self.delay and self.delay >= time_global() then return false end self.a.heli = get_nearest_heli(self.object:position(), self.a.attack_dist_sqr) self.fire_power = heli_target.get_target_priority(self.object) if self.a.heli == nil then self.delay = time_global() + 500 return false end --проверка на группировку if db.storage[self.a.heli:id()].community ~= nil and (db.storage[self.a.heli:id()].community == self.object:character_community()) then return false end --Проверка на огневую мощь if self.fire_power < 3 then self.object:set_detail_path_type(move.line) self.object:set_path_type(game_object.level_path) hide,lvid,dist = blowout_scheme.nearest_hide(self.object) utils.send_to_nearest_accessible_vertex(self.object,lvid) state_mgr.set_state(self.object,"sprint") return false end -- Проверка на то, что вертолет еще живой. if not bind_heli.is_heli_alive(self.a.heli) then self.a.heli = nil return false end -- проверка не потерялся ли вертолет. -- if db.heli[self.a.heli:id()] ~= nil and -- printf( "dist=%d", self.a.heli:position():distance_to_sqr(self.object:position()) ) if self.a.heli:position():distance_to_sqr(self.object:position()) > self.a.attack_dist_sqr then self.a.heli = nil return false end -- Проверка на то, что враг-игрок не подошел слишком близко local best_enemy = self.object:best_enemy() if best_enemy and best_enemy:id() == db.actor:id() then if db.actor:position():distance_to_sqr(self.object:position()) < self.a.attack_actor_sqr then return false end end -- Проверка на то, что денжер-игрок не подошел слишком близко local best_danger = self.object:best_danger() if best_danger then local bd_object = best_danger:object() if bd_object ~= nil and bd_object:id() == db.actor:id() then if best_danger:position():distance_to_sqr(self.object:position()) < self.a.attack_actor_sqr then return false end end end return true end ---------------------------------------------------------------------------------------------------------------------- -- Действие "стрелять по вертолёту" ---------------------------------------------------------------------------------------------------------------------- class "action_shoot" ( action_base ) function action_shoot:__init( name, a ) super ( nil, name ) self.a = a end function action_shoot:initialize() action_base.initialize( self ) end function action_shoot:execute() action_base.execute( self ) state_mgr.set_state( self.object, "threat_fire", nil, nil, {look_object = self.a.heli}, nil, nil, {yaw_delta=10} ) end function action_shoot:finalize() action_base.finalize( self ) --self.fire_power = nil self.camp = nil self.need_cover = nil self.object:movement_enabled(true) end ---------------------------------------------------------------------------------------------------------------------- function add_to_binder( npc, ini, scheme, section, storage ) printf( "DEBUG: add_to_binder: scheme='%s'", scheme ) local manager = npc:motivation_action_manager() manager:add_evaluator( xr_evaluators_id.chugai_heli_hunter_base, evaluator_shoot( "heli_hunter", storage ) ) local action = this.action_shoot( "action_shoot", storage ) action:add_precondition( world_property(stalker_ids.property_alive, true ) ) action:add_precondition( world_property(xr_evaluators_id.chugai_heli_hunter_base, true ) ) action:add_effect ( world_property(xr_evaluators_id.chugai_heli_hunter_base, false ) ) manager:add_action( xr_actions_id.chugai_heli_hunter_base, action ) action = manager:action( xr_actions_id.alife ) action:add_precondition( world_property( xr_evaluators_id.chugai_heli_hunter_base, false ) ) action = manager:action( stalker_ids.action_combat_planner ) action:add_precondition( world_property( xr_evaluators_id.chugai_heli_hunter_base, false ) ) action = manager:action( stalker_ids.action_danger_planner ) action:add_precondition( world_property( xr_evaluators_id.chugai_heli_hunter_base, false ) ) end function set_scheme( npc, ini, scheme, section ) printf( "DEBUG: set_scheme: scheme='%s' section='%s'", scheme, utils.to_str(section) ) local a = xr_logic.assign_storage_and_bind( npc, ini, scheme, section ) a.attack_dist_sqr = math.pow( utils.cfg_get_number( ini, section, "dist", npc, false, def_attack_dist ), 2 ) a.attack_actor_sqr = math.pow( utils.cfg_get_number( ini, section, "actor_dist", npc, false, def_actor_dist ), 2 ) a.heli = nil a.enabled = true end function disable_scheme(npc, scheme) local st = db.storage[npc:id()][scheme] if st then st.enabled = false end end НПС бегут в укрытие, но когда вертолет улетает\взрывается НПС так и остаются там стоять пока с ними не поговоришь. Как вернуть НПС под свою изначальную логику (или что я делаю неправильно)? Ссылка на комментарий
Artos 99 Опубликовано 8 Сентября 2011 Поделиться Опубликовано 8 Сентября 2011 (изменено) KASIMKA Твоя ошибка: в непонимании структуры и функционирования 'схемы'. Условно: схемы состоят из трех частей: - функции 'set/disable' (пресетов) - установка, сброс, биндер (активация), ... - методы 'evaluators' - проверки условий схемы - методы 'actions' - выполнение действий схемы Если схема активна для объекта - то эвалуаторы схемы вызываются постоянно(!) и в зависимост от проверок различных условий - на выход передают булево значение (истина/лож) о результате проверки. По этим результатам от эвалуаторов - могут запускаться/останавливаться экшены (выполнение действий схемы) и запускаться/блокироваться другие схемы. Ты вставил свой кусок кодов 'Проверка на огневую мощь' в эвалуатор схемы. По сути ты вставил кусок экшена (действия), которые должен выполнять объект при определенном тобою условии. При выпонении условия: 'self.fire_power < 3', которое постоянно(!) проверяется в активном эвалуаторе - ты вынуждаешь объект обязательно выполнять действие (бежать в укрытие). Что же удивляться, что твой НПС подчиняется твоим же указаниям? В эвалуаторе требуется только проверять условие! И уже по результату этой проверки - вызывать выполнение нужного действия. При чем(!) выполнение действия должно иметь окончание! Т.е. по достижении цели действия (в твоем случае - добежал до укрытия) - его выполнение должно быть прекращено. Примечание: По отсутстующему в оригинальной игре (heli_target) невозможно сказать сбрасывается ли у тебя 'self.fire_power', иль вообще принимает какие-то значения для отмены условия. Резюме: Перед правкой/созданием схем - требуется знать и понимать общую структуру схем и их взаимодействий и написать алгоритм работы схемы, который и воплощать в кодах (а не наоборот). Изменено 8 Сентября 2011 пользователем Artos Ссылка на комментарий
Gektor 0 Опубликовано 9 Сентября 2011 Поделиться Опубликовано 9 Сентября 2011 (изменено) Добрый день. Такой вопрос, как регулировать положение точек из которых выходит запотевание в моде динамических худов противогаза от Bak'а (ссылка)? Помогите пожалуйста разобратся . Заранее спасибо. Запотевание (да и др. эффекты) достигается 'показом' соответствующих текстур. Нет 'точек из которых выходит запотевание'. Есть только координаты (экрана) по которым выводятся чередующиеся тектуры, которые прописаны в конфиг-файлах (см. xml-ки). --/ Artos Изменено 9 Сентября 2011 пользователем Artos Ссылка на комментарий
Artos 99 Опубликовано 9 Сентября 2011 Поделиться Опубликовано 9 Сентября 2011 (изменено) Убедительная просьба к спрашивающим: Не пытаться продолжать обсуждение заданного в топике вопроса в ЛС без вестких на то причин. Топик на то и создан, чтобы задавать вопросы и разбираться с ними. Избегайте адресовать (без причины) вопросы(ы) конкретно кому-то. Вам могут дать на тот же вопрос и другие форумчане, а не только выбранный Вами адресат. Не адресуйте вопрос к 'толпе', типа: "Народ! ..." или "Люди! ...". Мы не в пустыне, вы не на трибуне и Нелюди вам все одно не ответят. А вот те, кто себя не ассоциирует с 'толпой' - могут промолчать ... Так же, задавая вопрос, не нужно (тем более кажды раз) 'здороваться'. Это все же форум, а не очная встреча. Ваше "Доброе утро", странно кому-то читать позней ночью, через пару дней, и может оно и не очень у кого-то 'доброе' ... Избегайне неинформативной 'дипломатии' и излишних 'расшаркиваний' ... Изменено 9 Сентября 2011 пользователем Artos Ссылка на комментарий
Gektor 0 Опубликовано 9 Сентября 2011 Поделиться Опубликовано 9 Сентября 2011 (изменено) В том то и дело что координаты точек запотевания ни где в конфигах этого мода я не нашел. 0. Ты и НЕ искал. 1. Уже было сказано, что НЕТ точек запотевания ... 2. Не стОит путать вопросы по теме с просьбами научить азам скриптования (LUA) или вообще с функционированием игры и обучению азам создания модификаций. В данном моде всего лишь 1 (один!) конфиг-файл 'ui_custom_msgs.xml' и не увидеть в нем отделенные комментарием '<!-- Dinamic HUD -->' записи именно мода - может только слепой или с лентяй. В папке текстур не так уж и много текстур и несложно просмотреть и увидеть, что к запотеванию относятчя 'breathN.dds' - тестуры (5 шт). К сведению само название говорит за себя: 'breath' -> 'дыхание' Т.о. найти и определить координаты, куда выводятся тесктуры - минутное дело и не требует сколь-нибудь заумных познаний. Если же тебе захотелось самому 'подвигать' скриптами эти тектуры - то врядли кто (думаю и сам автор мода) будет расписывать весь алгоритм вывода запотевания на экран ... Совет: 1. Выбирать похотелки себе 'по плечу', а не замахиваться на то, что не по силам и не по познаниям. 2. Изучай основы/азы, ФАКи, статьи. На форуме нет нянек и учителей, которые все в сотый раз кому-то персонально разжуют иль растолкуют. --/ Artos Изменено 9 Сентября 2011 пользователем Artos Ссылка на комментарий
KASIMKA 0 Опубликовано 9 Сентября 2011 Поделиться Опубликовано 9 Сентября 2011 (изменено) Пытаюсь подредактировать схему heli hunter. В своем предыдущем посте я пытался вызвать реакцию НПС на вертолет прямо из эвалуатора. Т.к. это неправильно - перенес действия в action: если раньше они хотя бы убегали, то теперь стеляют по вертолету вообще игнорируя условия: --[[------------------------------------------------------------------------------------------------------------------ Схема "Охотник за вертолётами" Чугай Александр --------------------------------------------------------------------------------------------------------------------]] local def_attack_dist = 200 -- расстояние, на котором вертолёт может быть атакован local def_actor_dist = 50 -- расстояние, на котором игрок может быть атакован function get_nearest_heli(npc_position, attack_dist_sqr) -- print_table(db.heli) local heli = nil for k,v in pairs(db.heli) do if v:position():distance_to_sqr(npc_position) <= attack_dist_sqr and (heli == nil or v:position():distance_to_sqr(npc_position) < heli:position():distance_to_sqr(npc_position)) then heli = v end end return heli end --------------------------------------------------------------------------------------------------------------------- -- Эвалуатор свойства "можно пострелять по вертолёту" --------------------------------------------------------------------------------------------------------------------- local overrides class "evaluator_shoot" ( property_evaluator ) function evaluator_shoot:__init( name, a ) super( nil, name ) self.a = a end function evaluator_shoot:evaluate() if self.delay and self.delay >= time_global() then return false end self.a.heli = get_nearest_heli(self.object:position(), self.a.attack_dist_sqr) --провека на существование вертолета if self.a.heli == nil then self.delay = time_global() + 500 self.hide = nil return false end --проверка на группировку if db.storage[self.a.heli:id()].community ~= nil and (db.storage[self.a.heli:id()].community == self.object:character_community()) then return false end -- проверка на то, что вертолет еще живой. if not bind_heli.is_heli_alive(self.a.heli) then self.a.heli = nil return false end self.fire_power = heli_target.get_target_priority(self.object) --Проверка на огневую мощь if self.fire_power < 3 then self.hide = true --return false end -- проверка не потерялся ли вертолет. -- if db.heli[self.a.heli:id()] ~= nil and -- printf( "dist=%d", self.a.heli:position():distance_to_sqr(self.object:position()) ) if self.a.heli:position():distance_to_sqr(self.object:position()) > self.a.attack_dist_sqr then self.a.heli = nil return false end -- Проверка на то, что враг-игрок не подошел слишком близко local best_enemy = self.object:best_enemy() if best_enemy and best_enemy:id() == db.actor:id() then if db.actor:position():distance_to_sqr(self.object:position()) < self.a.attack_actor_sqr then return false end end -- Проверка на то, что денжер-игрок не подошел слишком близко local best_danger = self.object:best_danger() if best_danger then local bd_object = best_danger:object() if bd_object ~= nil and bd_object:id() == db.actor:id() then if best_danger:position():distance_to_sqr(self.object:position()) < self.a.attack_actor_sqr then return false end end end return true end ---------------------------------------------------------------------------------------------------------------------- -- Действие "стрелять по вертолёту" ---------------------------------------------------------------------------------------------------------------------- class "action_shoot" ( action_base ) function action_shoot:__init( name, a ) super ( nil, name ) self.a = a end function action_shoot:initialize() action_base.initialize( self ) end function action_shoot:execute() action_base.execute( self ) if self.hide == true then self.object:set_detail_path_type(move.line) self.object:set_path_type(game_object.level_path) hide,lvid,dist = blowout_scheme.nearest_hide(self.object) utils.send_to_nearest_accessible_vertex(self.object,lvid) state_mgr.set_state(self.object,"sprint") else state_mgr.set_state( self.object, "threat_fire", nil, nil, {look_object = self.a.heli}, nil, nil, {yaw_delta=10} ) end end function action_shoot:finalize() action_base.finalize( self ) self.fire_power = nil self.camp = nil self.hide = nil self.object:movement_enabled(true) end ---------------------------------------------------------------------------------------------------------------------- function add_to_binder( npc, ini, scheme, section, storage ) printf( "DEBUG: add_to_binder: scheme='%s'", scheme ) local manager = npc:motivation_action_manager() manager:add_evaluator( xr_evaluators_id.chugai_heli_hunter_base, evaluator_shoot( "heli_hunter", storage ) ) local action = this.action_shoot( "action_shoot", storage ) action:add_precondition( world_property(stalker_ids.property_alive, true ) ) action:add_precondition( world_property(xr_evaluators_id.chugai_heli_hunter_base, true ) ) action:add_effect ( world_property(xr_evaluators_id.chugai_heli_hunter_base, false ) ) manager:add_action( xr_actions_id.chugai_heli_hunter_base, action ) action = manager:action( xr_actions_id.alife ) action:add_precondition( world_property( xr_evaluators_id.chugai_heli_hunter_base, false ) ) action = manager:action( stalker_ids.action_combat_planner ) action:add_precondition( world_property( xr_evaluators_id.chugai_heli_hunter_base, false ) ) action = manager:action( stalker_ids.action_danger_planner ) action:add_precondition( world_property( xr_evaluators_id.chugai_heli_hunter_base, false ) ) end function set_scheme( npc, ini, scheme, section ) printf( "DEBUG: set_scheme: scheme='%s' section='%s'", scheme, utils.to_str(section) ) local a = xr_logic.assign_storage_and_bind( npc, ini, scheme, section ) a.attack_dist_sqr = math.pow( utils.cfg_get_number( ini, section, "dist", npc, false, def_attack_dist ), 2 ) a.attack_actor_sqr = math.pow( utils.cfg_get_number( ini, section, "actor_dist", npc, false, def_actor_dist ), 2 ) a.heli = nil a.enabled = true end function disable_scheme(npc, scheme) local st = db.storage[npc:id()][scheme] if st then st.enabled = false end end function get_target_priority(obj) if not obj then return 0 end --qqq(obj:section()) local prior = 1 if IsMonster(obj) then -- qqq("monster") prior = 1 elseif IsStalker(obj) then -- максимум - 5 local wpn = obj:item_in_slot(obj:active_slot()) if wpn then local ammo, fm if system_ini():line_exist(wpn:section(), "ammo_class") then ammo = system_ini():r_string(wpn:section(), "ammo_class") if (string.find(ammo, "9x18") -- пистолетные патроны or string.find(ammo, "9x19") or string.find(ammo, "7.62x25") or string.find(ammo, "11.43x23") or string.find(ammo, "357") or string.find(ammo, "samopal") -- + патроны к самопалу or string.find(ammo, "bolt") -- + арбалетные болты or string.find(ammo, "12x7")) -- + патроны для дробовиков then prior = prior + 1 elseif (string.find(ammo, "5.45x39") -- промежуточные патроны or string.find(ammo, "5.56x45") or string.find(ammo, "7.62x39") or string.find(ammo, "9x39")) then prior = prior + 2 elseif (string.find(ammo, "7.62x51") -- винтовочные патроны or string.find(ammo, "7.62x54") or string.find(ammo, "7.92x75")) then prior = prior + 3 else prior = prior + 4 end end if system_ini():line_exist(wpn:section(), "fire_modes") then fm = system_ini():r_string(wpn:section(), "fire_modes") if string.sub(fm,-2,-1) == "-1" then prior = prior + 1 -- автоматическое оружие - приоритет цели выше на 1 end end --qqq(wpn:section()) end elseif string.find(obj:name(),"btr") then prior = 6 elseif (string.find(obj:section(),"helicopter") or string.find(obj:section(),"mi2")) then prior = 7 end --qqq(prior) return prior end Или, если я неправильно выбрал путь решения проблемы - подскажите, как переключить НПС на схему выброса (без выброса) при виде вертолета, если у них нечем в него стрелять, т.е. чтобы НПС вели себя точно также как при выбросе, завидев вертолет? Заранее спасибо! Используйте тэги для вывода участков с кодами, дабы сохранялось форматирование (отступы) и не искажались иные символы --/ Artos Изменено 9 Сентября 2011 пользователем Artos Ссылка на комментарий
Artos 99 Опубликовано 9 Сентября 2011 Поделиться Опубликовано 9 Сентября 2011 (изменено) KASIMKA 1. Применяя конструкции типа: 'self.var_name = ...' следует учитывать, к чему относится 'self'. Устанавливая в эвалуаторе 'self.hide = true' - бессмыслено проверять значение этой переменной в экшене, т.е. она всегда будет равна 'nil'. В данном случае 'self.hide' - это переменная, область которой ограничена классом эвалуактора 'evaluator_shoot' и вне его она недоступна. Для того, чтобы использовать нужную переменную и в экшене ('action_shoot') можно или вынести эту переменную на уровень локальной/глобальной переменной корня скрипт-файла или же использовать типовой прием: 'self.a.hide = true', помещая ее в единый сторадж ('self.a') данной схемы и читать из экшена этой же схемы аналогично: 'if self.a.hide == true then' 2. Из контекста вопроса(ов), можно сделать вывод, что тебе хочется, чтобы при отсутствии необходимого оружия для стрельбы по вертолетем - НПС убегал в укрытие, если же 'имеет' - неясно ... (вероятно не должен убегать, а стрелять по вертушке/сражаться). Данная схема имеет только один эвалуатор и один экшен: - проверка - "можно пострелять по вертолёту" - действие - "стрелять по вертолёту" Т.о. полностью отсутствует проверка - "нужно ли прятаться" и действие - "бежать и прятаться", без реализации которых невозможно осуществить тобою задуманное. Если, как в 1-ый раз, вставлять проверку и действие в общий эвалуатор - ресурсоемкая проверка будет съедать немало ресурсов и будет приводить к тому, что НПС при отсутствии подходящего оружия и при наличии 'живого' вертолета на локации - всегда будут бежать прятаться. Иными словами: требуется второй дополнительый эвалуатор, который по флагу от 1-го (есть вертушка) давал бы команду второму экшену - 'бежать прятаться', запрещая первый экшн (стрелять). Тогда НПС будут вести себя аналогично схеме 'выброса': нет опасности - схема не активна, опасно и есть оружие - стрелять, опасно и безоружен - прятаться. 3. Функция 'get_target_priority(obj)' очень неоптимальна. Использовать постоянные прямые перечтения файлов конфигурации - значительная нагрузка на русурсы. Тем более для эвалуаторов (по сути как апдейт НПС) эта функция мягко говоря 'тяжела'. а) Можно заранее один раз прочитать все конфиги оружия и патронов к нему и занести в таблицу, из которой и пользоваься; б) Постепенное чтение (по мере смены активного оружия) с запоминанием в таблицу нужных значений; в) Можно один раз проверить и запомнить активное оружие и, если оно не менялось - не перепроверять его каждым вызовом функции; г) Комбинация а), б), в). P.S. В дополнение к п.2 Можно попробовать обойтись и имеющейся парой в схеме. В проверке (эвалуаторе) определять необходимость действия (стрелять или прятаться => true). А в действии (экшене) перепроверять условие 'стрелять иль прятаться' (т.е. наличие нужного оружия) и выбирать соответствующую ветвь действия, что конечно потребует экшен разделить на две ветки (вторую ветку 'прятаться' самому написать на базе уже написанных кодов). Изменено 9 Сентября 2011 пользователем Artos Ссылка на комментарий
лнкс 0 Опубликовано 11 Сентября 2011 Поделиться Опубликовано 11 Сентября 2011 (изменено) Всем доброго времени суток. Возник такой вопрос: какой файл(скрипт, конфиг) запрещает на какой-либо локации спавнить нпс определённого ранга? Хочу при респавне на кордоне заспавнить бандюков в ранге "мастер", но простым редактированием spawn_sections.ltx это у меня не получается. Подскажите решение, пожалуйста. Задавайте вопросы более внятно. 1. 'Запрет' и 'не разрешение' - различные понятия. Нет нкаких запретов на (ре)спавн по рангам и по локациям. Имеются нте или иные конфиги/параметры. И если чего-то нет или параметр 'мал' - то не нужно путуть с запретом. 2. 'Респавном' - не спавнят, это 'автоматическое' событие, и тем более, при чем тут редактирование 'spawn_sections.ltx'? Разберись сам что же ты хочешь. Заспавнить кого-то - куда-то, иль настроить респавн. Во втором случае как минимум требуется информация где же тебе потребно чтобы респавнились. --/ Artos Добавлено через 84 мин.: Именно настроить респавн на кордоне, на АТП. В 'spawn_sections.ltx' прописывается ранг нпс при респавне и простое изменение новичков на мастеров не срабатывает. Почему? Потому что метод тыка в подобных вещах порочен и практически на 100% бесполезен. В 'spawn_sections.ltx' прописаны СЕКЦИИ объектос (НПС), в которых в отличии от исходной родительской секции, дополнительно прописываются треьуемые параметры, в том числе и ранг. Эти секции предназначены для любого спавна (само название файла говорит за себя!) и 'респавн' - это только частный случай. Респавны в игре НЕ читают рангов, а оперирует названиями секций и группировками. --/ Artos Изменено 11 Сентября 2011 пользователем Artos Ссылка на комментарий
=VENOM= 51 Опубликовано 12 Сентября 2011 Поделиться Опубликовано 12 Сентября 2011 лнкс, надо было выложить свою изменённую секцию, чтобы оценить, что к чему. В общем случае, если тебе нужно, чтобы на Кордоне спонились мастера-бандосы, сделай так: [esc_bandit_respawn_2]:stalker $spawn = "respawn\esc_bandit_respawn_2" character_profile = sim_bandit_master spec_rank = master community = bandit И респонер при срабатывании выдаст тебе бандюгу-мастера. Но учти, что бандюги-мастера на Кордоне "жить" не смогут (в оргинале смарт "esc_fabrika_bandit"), т.к. в настройках сталкеры такого ранга не берутся в смарты Кордона (файл smart_terrain_presets.ltx). Поэтому, такой NPC заспонится только в случае, если где-то в каком-то "бандитском" смарте на бескрайних просторах Зоны имеется свободное место, подходящее по параметрам (группировка - бандит, ранг - мастер), и тогда, после своего "рождения", свеженький NPC тут же отправится в путешествие на ту локацию, где расположен пресловутый смарт. А если тебе нужно, чтобы мастера-бандюги "жили" на Кордоне, в файле smart_terrain_presets.ltx измени (добавь) в секцию [l01_escape] бандитов-мастеров: [l01_escape] ... bandit = novice, experienced, master ... Другое дело, как это скажется на общей картине (мастера на Кордоне крутовато-с ), но тебе виднее, конечно... С другой стороны, можно, наверное, "поселить" одного бандюгу-мастера на Кордоне (ну, типа, это, "пахана" ). Как это сделать? Сделать это можно, добавив условие на какую-нибудь одну работу в гулаге смарта бандюков на АТП (файл gulag_escape.script), допускающее, что на эту самую работу может быть назначен либо сталкер (бандит) с рангом "мастер", либо, например, только NPC с именем "sim_bandit_master". Ссылка на комментарий
Artos 99 Опубликовано 12 Сентября 2011 Поделиться Опубликовано 12 Сентября 2011 (изменено) =VENOM= Возражу и поправлю. Файл 'smart_terrain_presets.ltx' является конфигом, который предназначен только для универсальных гулагов типа 'general_lager'. Гулаг, о котором и в вопросе и ты говоришь - 'esc_fabrika_bandit' - именнОй. 1. Именно для этого гулага в all.spawn'е организован респавнер 'esc2_respawn_bandits_fabrika', в котором и прописаны секции, которые будут спавниться (esc_bandit_respawn_1, esc_bandit_respawn_2). Т.е. если в респавнер добавить секции бандитов с рангом мастеров - то они и заспавнятся (если не будет иных ограничений). Изменять в исходных секциях я очень бы не рекомендовал, т.к. изменять секции, предназначенные для всей Зоны, ради одного гулага - ну очень недальновидно. Ни что не мешает просто добавить секции 'esc_bandit_respawn_3' и 'esc_bandit_respawn_4' с рангами ветерана и мастера, если не устраивают готовые (cit_bandit_respawn_1, cit_bandit_respawn_2 - ветеран и мастер). 2. Условия приема для этого гулага прописаны в 'gulag_escape.script' и ограничение имеется только одно - по группировке. Т.е. любой бандит будет взят в гулаг при условии наличия свободной работы. Т.о. для 'заматерелости' АТП достаточно только правильно настроить респавнер этого гулага, внеся желаемые секции спавна (при недостатке - досоздать). Изменено 12 Сентября 2011 пользователем Artos Ссылка на комментарий
лнкс 0 Опубликовано 12 Сентября 2011 Поделиться Опубликовано 12 Сентября 2011 (изменено) Artos, а какие могут быть иные ограничения? Дописать секции в спавнере не проблема. Ну во первых не в 'спавнер', а в конфиг секций для спавна. 'Спавнером' все же называют иль скрипт иль схему (se_respawn). Во-вторых, имел ввиду в основном уже имеющиеся секции, которые могут иметь и кастомдату, иль в кодах игры именно этим секциям добавлена логика/ограничения. Дописанные новые - врядли будут иметь ограничения. Хотя дописывать? ... Упомянутые 'cit'- бандиты все одно являются рудиментами от вырезенной локации и ограничений для подобного спавна также не имеют. --/ Artos Добавлено через 37 мин.: Понял, теперь следующее, если удалить с локации смарты, то нпс, заспавненные на ней будут просто бродить везде, где позволяет сетка и реагировать на противника согласно своей стандартной логике? Если удалить смарты с локации, то как минимум потребуется скорректировать немало логики и скриптов ... Но НПС, заспавненные на локации, если им не прописано '[smart_terrains] none = true' - не будут бродить, а проследуют на те локации, где им найдется работенка. Конечно строго по сетке и отвлекаясь на опасности иль подобное. Добавлено через 21 мин.: Хорошо, тогда как сделать привязку нпс к определённой локации? Хм, ... привязать его к какому-либо смарту/гулагу на какой-либо локации. :-) И навязать ему работу из этого смарта/гулага (хоть на другой локации). Работа должна быть по координатам для нужной локации (не обязательно одной с гулагом ее дающим). --/ Artos Изменено 12 Сентября 2011 пользователем Artos Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти