Скриптование - Страница 85 - Скрипты / конфиги / движок - AMK Team
Перейти к контенту

Рекомендуемые сообщения

Тема для обсуждения скриптов всего и всех в серии игр STALKER.


Задавая вопрос (!):
1. Внимательно изучите суть вопроса. Вопрос должен соответствовать выбранной Вами темы. Это поможет сохранить порядок и читабельность темы, а также облегчит поиск и понимание сего;
2. Изучите то, что уже есть в теме (пролистайте "руками", воспользуйтесь поиском на форуме);
3. Изучите информацию которая может вам помочь:

 
 

Stalkerin. Там есть много хороших статей касательно данной темы.
Уроки по модостроению. Есть рабочие примеры готовых скриптов различного назначения.

 

Справочное руководство по языку Lua 5.1
https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual/ru
Справочник по функциям и классам. Собрано много информации по функциям и классам, не всем, но по основные сведения предоставлены.

4. Дабы не превращать обсуждение в "кашу" разной информативной направленности, задавайте несколько вопросов по порядку (в разных постах) после того, как получите ответ на предыдущий вопрос;
5. "Спасибо" и тому подобное - будьте так любезны в ПМ. Если не любите писать в ПМ, в конце вопроса напишите фразу: "Заранее спасибо!" - или что-то в этом духе;
6. ПОЖАЛУЙСТА! Указывайте, для какой игры Вам необходима информация (ТЧ, ЧН, ЗП), если стоит мод - укажите название мода;
7. Если Вы что-то сделали и результат не такой, какой Вами задумывался, то, пожалуйста, приводите коды которые Вы изменяли/писали целиком! Это поможет другим правильно ответить на Ваш вопрос, а также оградит Вас от лишней писанины.
8. Оформляйте сообщение. Пользуйтесь тегами для того, чтобы отделить код от текста. Пишите грамотно - ПОЛЬЗУЙТЕСЬ ЗНАКАМИ ПРЕПИНАНИЯ.
9. И помните: «Правильно заданный вопрос – половина ответа».

 

Какие вопросы следует задавать, а какие нет...

 

Задавайте вопросы, которые касаются непосредственно скриптов и их работы, т.е. Вы что-то делаете, а у Вас что-то не получается, при этом у Вас на руках должен быть хотя бы какой-то код, свидетельствующий о Вашей причастности к вопросу.

 

Вопросы которые будут удалятся, следовательно их задавать не нужно:
-- Где находится та или иная функция?
Для ответа используем поиск по словам среди файлов оригинальной игры или мода, если объект поиска относится к нему, при помощью программы, которая Вам наиболее симпатизирует;
-- Как сделать что-то/то-то?
С подобными вопросами, либо в "ковырялки", где Вам вероятнее всего так же не ответят, либо выдвигаем мысли, подкреплённые теорией, практикой (идеальный вариант) и здравым рассудком;
-- Вопросы со смыслом: "сделайте", "совместите" и подобными глаголами повелительного наклонения.
-- К тому же удалению будут подвергаться вопросы, в которых масштабно не используются теги, для отделения кода и цитат от основного текста, а также не вписан в спойлер код размером превышающие семь строк.
Ответ на возможно возникший вопрос: В какую тему можно обратиться по поводу логики и спавна объектов?
В тему "ковырялок" соответствующей версии игры, для которой Вы задаёте вопрос.

И последнее: очень рекомендовано к прочтению Правила форума
 


  • Спасибо 1
  • Полезно 2
Ссылка на комментарий
https://www.amk-team.ru/forum/topic/6185-skriptovanie/

Кстати чтобы узнать секцию костюма надо писать db.actor:item_in_slot(6):section()

И сравнивать outfit == "костюм". У меня луа чекер сломался так что попробуй пройтись им ещё

Изменено пользователем TRAMP14

Вот этот фрагмент суров:

 

    if nano < af_num then
        psy_hit.power = 0.0005
        psy_hit.type = hit.radiation
        db.actor:hit(psy_hit)
    end
    if nano >= af_num then
        psy_hit.power = 0
        psy_hit.type = hit.radiation
        db.actor:hit(psy_hit)
    end

 

 

Может, лучше так?

 

    if nano < af_num then
        psy_hit.power = 0.0005
    else 
        psy_hit.power = 0
    end
    psy_hit.type = hit.radiation
    db.actor:hit(psy_hit)

 

И, как уже сказали, outfit="novice_outfit" - это присвоение, а не проверка на равенство.

:)

 

Еще совет - вместо громадных if вынеси имена секций бронежилетов в таблицы и просто потом проверяй наличие элемента. И не нужно в каждом ифе писать if outfit and. Сделай проверку выше.

Изменено пользователем KD87

А как проверить что ГГ находится на янтаре? Пробовал несколько функций все вылетали.

И когда же над lua перестанут издеваться... Неужели так сложно запомнить простые правила этого простого языка?(уж поверьте мне - в lua они действительно простые - могу сравнивать так как знаю четыре языка и шапочно знаком с еще 5-6).

И писать код обдумав прежде и алгоритм и инструментарий, а не лишь бы что то написать.

local tOutfits ={
["novice_outfit"]                    =0,
["bandit_outfit"]                    =0,
["killer_blue_exoskeleton"]          =0,
["svoboda_exoskeleton"]              =0,
["monolit_exoskeleton"]              =0,
["broken_exoskeleton"]               =0,
["monolit_scientific_outfit"]        =0,
["bandit_master_outfit"]             =0,
["soldier_outfit"]                   =0,
["bandit_veteran_outfit"]            =0,
["killer_outfit"]                    =1,
["monolit_outfit"]                   =1,
["svoboda_light_outfit"]             =1,
["dolg_outfit"]                      =1,
["dolg_black_exoskeleton"]           =1,
["merc_scientific_outfit"]           =1,
["neytral_exo_antigas_outfit"]       =1,
["military_outfit"]                  =1,
["military_stalker_commander_outfit"]=1,
и т.д.
}
local nano=0
local currentOutfit=nil 
local actor =  db.actor
function update()
    if not actor then
    actor = db.actor
    end 
    
local oOutfit= actor and actor:get_current_outfit()
--// чтобы не проверять на каждом цикле апдейте  - пока костюм не поменялся ничего не делаем
if currentOutfit and oOutfit and currentOutfit==oOutfit then
return end 
--//иначе  узнаем секцию 
local sSection = oOutfit and oOutfit:section()
   if sSection and tOutfits[sSection] then
      nano=tOutfits[sSection]
       currentOutfit=oOutfit
    end 
end

 

 

// Извини, что вмешиваюсь в твое сообщение, но +1. :) Министр.

Изменено пользователем Министр

Привет всем. У меня есть скрипт:

local ne_jrat = {"medkit","medkit_scientic","medkit_army"}

local iTimer

function Startingg()

iTimer = time_global() + 10*1000 -- взводим таймер на 10cek

db.actor:give_info_portion(porsh1) -- выдаём порш

end

 

function Timer_N_minutes() -- вызывается из ':update' сталкер-биндера

if iTimer and iTimer < time_global() then

iTimer = nil

db.actor:disable_info_portion(porsh1) -- по истечению 10 секунд удаляем порш

end

end

function no_eat(obj) -- это в биндер на :use_inventory_item(obj)

local s_obj = alife():object(obj:id())

if db.actor:has_info(porsh1) then -- пока есть поршень

for k, v in pairs(ne_jrat) do

if if(s_obj) and (s_obj:section_name()==v) then -- нельзя ничего жрать

db.actor:drop_item(v)

db.actor:hide_weapon() -- есл попробовал сожрать - пусть выкидывает

end

end

end

end

 

По идее, после использования аптечки, в течении 10 секунд нельзя использовать другую аптечку, и у гг убираются руки.

А еще у меня есть лог вылета:

FATAL ERROR

 

[error]Expression : !m_error_code

[error]Function : raii_guard::~raii_guard

[error]File : D:\prog_repository\sources\trunk\xrServerEntities\script_storage.cpp

[error]Line : 748

[error]Description : ....e.r. - Зов Припяти\gamedata\scripts\xr_logic.script:1275: attempt to index local 'obj' (a nil value)

 

 

stack trace:

 

 

Помогите, пожалуйста...

Прошу помощи в поиске ошибки:

Вновь созданные НПС по выдаче инфопоршня спавнятся в разных районах локации, 1-я группа которая возле ГГ передают сообщение по рации 2-й группе (суть ситуации напоминает ту когда при входе ГГ на Дикую Территорию снайперы вызывают Волкодава):

дополнительная строчька в script_sound:

[pri_killer_taras_hello_rnd]

stalker = 0,scenario\pri\naymit_taras_racia

сами звуки:

sounds\characters_voice\scenario\pri\naymit_taras_racia.ogg

sounds\ambient\random\naymit_taras_racia.ogg

 

1. [logic]

active = walker@zasada_pripyat

active = remark

 

[walker@zasada_pripyat]

path_walk = wave1_bomber_walk2

path_look = wave1_bomber_look2

;-- soundgroup = pri_killer_taras_hello (пробовал подключать эту строку толку нет, был вылет без лога)

def_state_moving1 = assault

def_state_moving2 = assault

meet = no_meet

danger = danger_ignore

combat_ignore_cond = {!check_fighting(808) !fighting_actor} ;always

 

[remark]

no_move = true

target = actor

snd = pri_killer_taras_hello

anim = claim

on_signal = sound_end | walker1@zasada_pripyat %play_snd(characters_voice\scenario\pri\naymit_taras_racia)%

meet = no_meet

 

[walker1@zasada_pripyat]

path_walk = wave1_bomber_walk2

path_look = wave1_bomber_look2

def_state_moving1 = assault

def_state_moving2 = assault

meet = no_meet

danger = danger_ignore

combat_ignore_cond = {!check_fighting(808) !fighting_actor} ;always

 

[danger_ignore]

ignore_distance = 5

 

[smart_terrains]

none = true

 

2. [logic]

active = walker@zasada_pripyat

active = sr_sound_act

 

[walker@zasada_pripyat]

path_walk = wave1_bomber_walk2

path_look = wave1_bomber_look2

def_state_moving1 = assault

def_state_moving2 = assault

meet = no_meet

danger = danger_ignore

combat_ignore_cond = {!check_fighting(808) !fighting_actor} ;always

show_spot = true

 

[sr_sound_act]

snd = pri_killer_taras_hello

delay = 2

delay_max = 4

on_signal = sound_end | walker1@zasada_pripyat

 

[walker1@zasada_pripyat]

path_walk = wave1_bomber_walk2

path_look = wave1_bomber_look2

def_state_moving1 = assault

def_state_moving2 = assault

meet = no_meet

danger = danger_ignore

combat_ignore_cond = {!check_fighting(808) !fighting_actor} ;always

show_spot = true

 

[danger_ignore]

ignore_distance = 5

 

[smart_terrains]

none = true

 

3. [logic]

active = walker@zasada_pripyat

active = sr_sound_act

 

[walker@zasada_pripyat]

path_walk = wave1_bomber_walk2

path_look = wave1_bomber_look2

def_state_moving1 = assault

def_state_moving2 = assault

meet = no_meet

danger = danger_ignore

combat_ignore_cond = {!check_fighting(808) !fighting_actor} ;always

show_spot = true

 

[sr_sound_act]

snd = characters_voice\scenario\pri\naymit_taras_racia

delay = 2

delay_max = 4

on_signal = sound_end | walker1@zasada_pripyat

 

[walker1@zasada_pripyat]

path_walk = wave1_bomber_walk2

path_look = wave1_bomber_look2

def_state_moving1 = assault

def_state_moving2 = assault

meet = no_meet

danger = danger_ignore

combat_ignore_cond = {!check_fighting(808) !fighting_actor} ;always

show_spot = true

 

[danger_ignore]

ignore_distance = 5

 

[smart_terrains]

none = true

 

4. [logic]

active = walker@zasada_pripyat

active = sr_sound_act

 

[walker@zasada_pripyat]

path_walk = wave1_bomber_walk2

path_look = wave1_bomber_look2

def_state_moving1 = assault

def_state_moving2 = assault

meet = no_meet

danger = danger_ignore

combat_ignore_cond = {!check_fighting(808) !fighting_actor} ;always

show_spot = true

 

[sr_sound_act]

snd = ambient\random\naymit_taras_racia - как в примере 3.9.3. Секция [sr_sound]

delay = 2

delay_max = 4

on_signal = sound_end | walker1@zasada_pripyat

 

[walker1@zasada_pripyat]

path_walk = wave1_bomber_walk2

path_look = wave1_bomber_look2

def_state_moving1 = assault

def_state_moving2 = assault

meet = no_meet

danger = danger_ignore

combat_ignore_cond = {!check_fighting(808) !fighting_actor} ;always

show_spot = true

 

[danger_ignore]

ignore_distance = 5

 

[smart_terrains]

none = true

 

В результате всех экспериментов при приближении к этой группе логика не отрабатывается должным образом, и звук не произносится.

Возможно, им надо прописать в профиль диалог <start_dialog>hello_dialog</start_dialog> (ели это как то влияет)?

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

Изменено пользователем SEA_CAT

SEA_CAT,

1. [logic]

active = walker@zasada_pripyat

active = remark

 

Простите, но это несколько неправильно B)

 

Актив есть актив, два актива не бывает, второй - вы приобретёте, только запихав товариСЧа в гулаг.

Во вторых - если вы мало понимаете в ремарках - советую Вам о них забыть на время роста... Многие их пишут. но. мало что понимают - вернее, чем это оборачивается.... В чистом ТЧ - вам простится... Но - не более того.

 

Почитал ниже...

active = sr_sound_act

 

изучите мальца возможные варианты логики. Для старта рекомендую типичные валкер, кемпер и камп. :rolleyes:

Изменено пользователем Arhara

Garry_Galler,

А по-сути, зачем тут вообще луа? :) Если данная проверка требуется постоянно, что скажется не + для памяти - сделать на нужных локах - по рестриктору нужного радиуса с проверкой данного итема. При получении актором такового - единственным тупым усилием удалить все рестрикторы, либо оставить нужные и не проверять более то, что имеем.

Доброго времени суток всем.Народ помогите пожалуйста такая проблема все наверно слышали про Interactive Music Mod дак вот я хочу сделать так что бы его можно было отключить в опциях меню игры в графе звуки такой же кнопкой как eax вот здесь

XR_3DA_2011_04_02_04_17_03_00.jpg

файл xml отвечающий за кнопку и скрипт где прописана функция кнопки я нашёл но не могу понять какую функцию и где нужно прописать чтобы моя кнопка отключения звука Interactive Music Modа работала помогите пожалуйста как мне это осуществить а то всю голову уже сломал

Изменено пользователем serega-gamer

Garry_Galler

Все же стОит сравнивать НЕ сами объекты (их юзердаты), а например их игровые идентификаторы (Id), т.е. типа:

 

local currentOutfit = nil

заменить на:

local idOutfit = nil

 

if currentOutfit and oOutfit and currentOutfit==oOutfit then

заменить на:

if idOutfit and oOutfit and idOutfit == oOutfit:id() then

...

currentOutfit=oOutfit

заменить на

idOutfit = oOutfit:id()

 

Также стОит добавить ветку/условие обнуления 'запомненного броника' (currentOutfit/idOutfit), т.к. актор может и снять его ...

 

 

Если еще принять во внимание, что броник ГГ может снять/одеть/поменять только в двух ситуациях:

а) если 'голенький' - подобрал/купил/заспавнился в инвентори броник - это коллбэк на получение предмета (on_item_take);

б) при 'ручном' переодевании, т.е. игроком в окне инвентори - коллбэк на закрытие окна инвентори.

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

Изменено пользователем Artos

Arhara

Спасибо за поправку - с особым уважением отношусь к Вашим работам, кое что с годами успел и для себя перенять.

В данной [logic] хотел вместо второго active поставить danger = danger_condition, но как то не придал этому особо значения - приоритет задачи был иной), ведь на ожидаемый результат это не повлияло, в своих рабочих [logic] для других засад под walker и снайперов под camper второго active пока не ставил (пока на время роста) :)

1. Но, для этого товарища логика бралась из (невымышленного) гулага BOMBER: WAVE на локации Припять (gamedata\config\misc\gulag_pripyat, строка 402 с небольшой корректировкой).

Главная суть этих экспериментов была не создать логику поведения для нового НПС, а именно отыграть звуковой эффект при входе ГГ в рестиктр, то и по совету других при тестировании их на локации Кардон посадил его на [remark] no_move = true - дабы не убежал пока я до него иду ;)

2. Для данного "старта" вроде и выбрал walker с подключением

"]3.9.9. Sr_sound_act

 

Итого, схема, которая играет саунд в голове актера. Всякие там переговоры по ПДА и прочие фейки

[sr_sound_act]

snd = ambient\random\new_drone1 --имя звукового файла

 

* delay = 2000 --задержка перед проигрыванием

* delay_max = 4000 -- между проигрыванием звука будет взят случайный промежуток между delay и delay_max.

* on_signal = sound_end | nil --по сигналу можно перейти в другую секцию.

 

theme = <имя темы из ph_sound_themes>

http://stalkerin.gameru.net/wiki/index.php...1%D1%82%D1%8C_3

хотя подозреваю если попробую какого нибудь из новых или существующих в оригинале снайперов пол camper то результат будет тот же - подозреваю тут причина в другом <_<

Имеется таблица "belt = {}", которая с ходом игры наполняется и постоянно изменяется. Помогите составить скрипт, который проверяет, есть ли в таблице секция "XXX" и, если это так, выполняет действие.

if belt and next(belt) and belt[твой итем в кавычках] then
действие
end

Если я правильно понял вопрос

Более менее разобрался выдачей звуковых схем из логики НПС

http://www.amk-team.ru/forum/index.php?showtopic=6458&view=findpost&p=260737

хотя вот с секцией http://stalkerin.gameru.net/wiki/index.php/%D0%A7%D0%B0%D1%81%D1%82%D1%8C_3

- так до конца и не ясно, запустить её не получилось, а ссылку на её применение видел лишь http://www.amk-team.ru/forum/index.php?showtopic=6458&view=findpost&p=481827

как видно при записи её в alife (через all.spawn)?

Заспавнил несколько зомбей на кордоне скриптом. Поймал вылет:

Попробуйте выключить amk_offline_alife. С этими смартами вообще бардак какой-то творится - мало того, что прописывается в них чёрте знает что (предметы, к примеру), так ещё и убрать зависимость онлайн-статуса непися от статуса смарта - куча проблем.

Вобщем, ситуация такая.

У физических объектов (имеются в виду разбиваемые ящики и т.п. объекты) хит-колбэк биндится не в реините, а в апдейте, по довольно занятным условиям:

function generic_physics_binder:update(delta)
    object_binder.update(self, delta)

    if not self.initialized and db.actor then
        self.initialized = true
        xr_logic.initialize_obj(self.object, self.st, self.loaded, db.actor, modules.stype_item)        

        --' Запускаем ассоциированный с объектом партикл.
        local particle = utils.cfg_get_string(self.st.ini, self.st.section_logic, "particle", self.object, false, "", nil)
        if particle ~= nil then
            self.particle = particles_object(particle)
            self.particle:play_at_pos(self.object:position())
        end

        --' Дизаблим ассоциированный с объектом граф
        local graph_point_marker = utils.cfg_get_string(self.st.ini, self.st.section_logic, "graph_point_marker", self.object, false, "", nil)
        if graph_point_marker ~= nil then
            self.disable_graph_point = patrol(graph_point_marker):game_vertex_id(0)
            game_graph():accessible(self.disable_graph_point, false)
            printf("GRAPH POINT DISABLED")
        end
        
      
         
    end

    if self.st.active_section ~= nil or (self.object:spawn_ini() ~= nil and self.object:spawn_ini():section_exist("drop_box") == true) then
        xr_logic.issue_event(self.object, self.st[self.st.active_scheme], "update", delta)
--    if not self.callbackset then
          self.object:set_callback(callback.hit, generic_physics_binder.hit_callback, self)
          self.object:set_callback(callback.death, generic_physics_binder.death_callback, self)
          self.object:set_callback(callback.use_object, generic_physics_binder.use_callback, self)
--      self.callbackset=true
--    end
    -- для бтра hit_callback не вызывается. заткнём эту дырку.
    if self.health and (not self.nofixonhit) then
      local health=self.object:get_car() and self.object:get_car():GetfHealth()
      if health then
        if self.health-health>0.00001 then
          -- amk.mylog("health decrease for "..self.object:name())
          self.health=health
          self:hit_callback(self.object, self.health-health, vector():set(1,0,0), db.actor, 0)
          self.nofixonhit=nil
        end
      end
    end
  else
--    self.callbackset=false
    end
end

 

это из амк. Как я выяснил на практике - забинденный таким образом хит-колбэк вызывается, кроме бтров, для тех разбиваемых ящиков в которых что-то есть. Если же разбиваемый ящик пустой - для него хит-колбэк не вызывается.

Ну вот вопрос, как бы поудобнее этот колбэк и к пустым ящикам тоже прицепить, но при этом не привязать его ко всем физ. объектам вообще.

 

Если биндить через реинит, то он тогда сразу на все такие объекты повесится...

Zander_driver

Во-первых,

не старайся выражаться 'мудрено', употребляя незнакомые слова в неподходящих сочетаниях. Новички-модмейкеры может и с 'уважением' почитают и даже попугайничать начнут, но кроме улыбки ... подобное не помогает понятию сути ...

Биндить коллбэк - тупое сочетание несочитаемого. Коллбэк можно 'ставить', и не только в биндерах, а и во многих других местах.

 

Во-вторых, если коллбэк, как выше сказано не обязательно устанавливать в биндере объекта, то что мешает тебе ставить его в любом удобном и подходящем тебе месте? Берешь объект и ставишь ему коллбэк, типа:

oDropBox:set_callback(callback.hit, my_script.hit_callback, nil) - и ловишь его в своем скрипте.

 

К сути:

Ключ к ответу уже имеется в оригинальных кодах биндера физ.объектов: "Биндить предмет нет смысла, если у него нет секции logic" (это из комментов разрабов). Также там имеется фраза: "Прожектор нужно биндить даже без logic"

Иными словами, физ.объекты не имеющие логики (или параметра "drop_box") и не прожекторы не добавляются и не обрабатываются биндером (не биндятся).

 

Также, как ты правильно, хотя и косноязычно, заметил, установка на физ.объекты коллбэка нестандартна.

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

Коллбэк не вызывается НЕ для пустых ящиков, а для ящиков не имеющих логики (точнее условия "drop_box"). Поэтому то они и пустые, что ничего в них не спавнится из-за отсутствия обработки события "death".

 

Честно говоря, неясно для чего тебе коллбэк на хит (hit_callback), а не на разрушение (death_callback), но в любом случае - придется или логику ("drop_box") добавлять или делать нечто аналогичное прожекторам, исключая конечно в 'xr_box.script' обработку твоих пустых добавок ...

Изменено пользователем Artos

Прошу прощения :) увлекся. Просто, я обычно именно на таком языке и изъясняюсь - привык.

А по самой ситуации - мне просто нужно отследить хит всех тех предметов, которые можно сломать с помощью какого либо оружия. И ловить их непосредственно в игровом процессе, как мне представляется, неудобно. О том чтобы решать "нужен ли этому объекту колбэк" уже в момент когда в него стреляют - я и вовсе молчу, т.к. не представляю как это сделать.

 

death мне не подходит, т.к. какой-нибудь ящик может и несколько выстрелов выдержать, и надо обрабатывать каждый.

А поступить как с прожектором... блин, тоже не очень удобно. прожектор это один clsid.projector, а те объекты что нужны мне - это и деревянные ящики, и железные - те что поменьше, и (если я правильно понимаю) доски в заколоченных окнах и дверях некоторых домов. Я почему то думаю что это clsid."разные объекты"

Я даже не знаю как их по clsid узнать, как они называются?

А логика drop_box... разве не подразумевает что из сломанного объекта должно что то выпасть? В случае с ломающейся доской будет нелогично.

Я честно говоря эту сторону мало изучал.

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   0 пользователей

    • Ни один зарегистрированный пользователь не просматривает эту страницу.
×
×
  • Создать...