Перейти к контенту

Скриптование


Svoboда

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

bandit_Borov

В старой теме меченый(стрелок) отвечал на этот вопрос, воспроизведу его ответ

 

Аномалии просто alife не заспавнишь - рабочую...вот воспользуйся функцией

 

 

function spawn_anom(anom_name,plosh,position,level_vertex_id,game_vertex_id,powers_a,time_danger
os)
local obj = alife():create(anom_name,position,level_vertex_id,game_vertex_id)
local pac = net_packet()
obj:STATE_Write(pac)
local game_vertex_id = pac:r_u16()
local distance = pac:r_float()
local direction = pac:r_u32()
local level_vertex_id = pac:r_u32()
local object_flags = pac:r_s32()
local custom_data = pac:r_stringZ()
local story_id = pac:r_s32()
local spawn_story_id = pac:r_s32()
local shape_count = pac:r_u8()
for i=1,shape_count do
local shape_type = pac:r_u8()
if shape_type == 0 then
local center = pac:r_vec3()
local plosh = pac:r_float()
else
local box = pac:r_matrix()
end
end
local restrikror_type = pac:r_u8()
local powers = pac:r_float()
local owner_id = pac:r_s32()
local on_off_mode_enabled_time = pac:r_u32()
local on_off_mode_disabled_time = pac:r_u32()
local on_off_mode_shift_time = pac:r_u32()
local offline_interactive_radius = pac:r_float()
local artefact_spawn_places_count = pac:r_u16()
local artefact_position_offset = pac:r_s32()
local last_spawn_time_present = pac:r_u8()
if pac:r_elapsed()~= 0 then 
abort("left=%d",pac:r_elapsed())
end
pac:w_begin(game_vertex_id)
pac:w_float(distance)
pac:w_u32(direction)
pac:w_u32(level_vertex_id)
pac:w_u32(object_flags)
pac:w_stringZ(custom_data)
pac:w_s32(story_id)
pac:w_s32(spawn_story_id)
pac:w_u8(1)
pac:w_u8(0)
local sphere_center = vector()
sphere_center:set(0,0,0)
pac:w_vec3(sphere_center)
pac:w_float(plosh)
pac:w_u8(restrikror_type)
if powers_a ~= nil then 
powers = powers_a 
end
pac:w_float(powers)
if time_dangeros == nil then 
owner_id = bit_not(0) 
else 
owner_id = time_dangeros 
end
pac:w_u32(owner_id)
pac:w_u32(on_off_mode_enabled_time)
pac:w_u32(on_off_mode_disabled_time)
pac:w_u32(on_off_mode_shift_time)
pac:w_float(offline_interactive_radius)
pac:w_u16(artefact_spawn_places_count)
pac:w_u32(artefact_position_offset)
pac:w_u8(last_spawn_time_present)
pac:r_seek(0)
obj:STATE_Read(pac,pac:w_tell())
return obj
end

спавнить к примеру так

 

local anom_l = {
"секция",
"секция"
}
local level_coor = {
l01_escape = {lvid=595580, gvid=44},
l02_garbage = {lvid=384039, gvid=265},
l03_agroprom = {lvid=438379, gvid=693},
l04_darkvalley = {lvid=392517, gvid=813},
l06_rostok = {lvid=69283, gvid=1311},
l07_military = {lvid=915663, gvid=1546},
l10_radar = {lvid=796328, gvid=1868},
l11_pripyat = {lvid=295965, gvid=2269}
}
function random_spawn()
local gv = level_coor[level.name()]["gvid"]
for i = 1,20 do
local lv = math.random(level_coor[level.name()]["lvid"])
spawn_anom(anom_l[math.random(21)], math.random(3,15), level.vertex_position(lv),lv,gv,math.random(60,90),bit_not(0))
end
end

Я так спавнил радиацию ...Получается отлично...рандомно спавнится

или скачай это ,можешь пользоваться ....

http://depositfiles.com/files/wf3chx3r5

 

 

срабатывала раз ,то можешь в биндер поместить dynamic_anomalies.level_spawn()

а в сам скрипт вставить это

 

function level_spawn()
local level_gg = level.name()
if level_gg == "l01_escape" then
if db.actor:dont_has_info("my1") then
random_spawn()
db.actor:give_info_portion("my1")
end
end
if level_gg == "l02_garbage" then
if db.actor:dont_has_info("my2") then
random_spawn()
db.actor:give_info_portion("my2")
end
end
if level_gg == "l03_agroprom" then
if db.actor:dont_has_info("my3") then
random_spawn()
db.actor:give_info_portion("my3")
end
end
if level_gg == "l04_darkvalley" then
if db.actor:dont_has_info("my4") then
random_spawn()
db.actor:give_info_portion("my4")
end
end
if level_gg == "l06_rostok" then
if db.actor:dont_has_info("my5") then
random_spawn()
db.actor:give_info_portion("my5")
end
end
if level_gg == "l07_military" then
if db.actor:dont_has_info("my6") then
random_spawn()
db.actor:give_info_portion("my6")
end
end
if level_gg == "l10_radar" then
if db.actor:dont_has_info("my7") then
random_spawn()
db.actor:give_info_portion("my7")
end
end
if level_gg == "l11_pripyat" then
if db.actor:dont_has_info("my8") then
random_spawn()
db.actor:give_info_portion("my8")
end
end
end

 

ну и добавить инфопоршни...удачи ..думаю рассказал больше чем надо

 

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

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

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

Спавнить командой spawn_anom(<секция нужной аномалии>,<радиус аномалии>,position,lvid,gvid,<сила аномалии>,-1)

position,lvid,gvid - как в обычном спавне.

У меня работало как надо не со всеми аномалиями, но работало. А чтобы сделать динамические аномалии, одного спавна мало, там нужно еще много чего продумать. Одно убирание аномалий чего стоит. Так и не решил я толком эту задачу. Точнее сделать - сделал, но ТАКИЕ глюки получил, что просто ужас, пришлось отказаться от этой затеи.

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение
Kirag, а сила аномалии разве не в zone_.ltx прописывается?и (параметр max_power_start)

 

Там прописано непонятно что, во всяком случае у меня аномалии на изменение этого параметра не реагируют. Увеличиваю на порядок-другой, а как било еле-еле, так и дальше бьет. Другое дело выставить силу скриптом при спавне, или set_anomaly_power. Эффект зависит от типа аномалии, но в любом случае он ярко выраженный.

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

Не функция, а секция, это совершенно разные вещи. Проверь конфиги, где-то в них ошибка, что-то прописать забыл.

  • Не нравится 1

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

skylancer-3441

С диалогом должно быть примерно так:

 

<dialog id="test_dialog">
    <phrase_list>

        <phrase id="0">
            <text>test_dialog_0</text>
            <next>1</next>
        </phrase>

        <phrase id="1">
            <text>test_dialog_1</text>
            <next>2</next>
        </phrase>

        <phrase id="2">
            <text>test_dialog_2</text>
            <next>3</next>
        </phrase>

        <phrase id="3">
            <text>test_dialog_3</text>
            <next>4</next>
        </phrase>

        <phrase id="4">
            <text>test_dialog_4</text>
            <next>5</next>
        </phrase>

        <phrase id="5">
            <text>test_dialog_5</text>
            <action>test.spawn_item_stalker</action>
        </phrase>

    </phrase_list>
</dialog>

 

Обрати внимание, как расставлены теги next и на положение тега action. Сам спавн не проверял.

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

Struck, то, что можно - это 100%, именно так оно и сделано в оригинале. Выполнение квестов отслеживается по инфопоршенам, а выдаются они тремя способами: либо в диалоге, либо в логике объектов, либо скриптами.

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

 

db.actor:give_info_portion("название_инфопоршена") - выдать

db.actor:disable_info_portion("название_инфопоршена") - убрать

if db.actor:has_info("название_инфопоршена") then ... - проверка на наличие

if not db.actor:has_info("название_инфопоршена") then ... - проверка на отсутствие

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

utak3r

Маленькое дополнение: для корректного спавна ГГ надо еще менять upd:position. Иначе на нужном уровне заспавнит, но не там, где надо, а черт знает где. На армейских складах вообще за карту выбрасывало :)

 

Galil

Ты где-то накосячил в smart_monster_parts.script, судя по логу. Проверь закрытие всех скобок, наличие всех end-ов, не перепутал ли где == (сравнение) и = (приравнивание) и тому подобные ошибки. Что-то не так с синтаксисом, почти наверняка, программа вообще не воспринимает этот файл и не понимает, чего от нее хотят.

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

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение
Подскажите, пожалуйста, как можно сделать так ,что при каждом заходе на локацию, на ней автоматически спавнилось человек 15 бандюков.

 

Понадобится bind_stalker.script

 

1) В функции actor_binder:save(packet) допиши в самое начало примерно следующее:

 

function actor_binder:save(packet)
    if utils.level_changing() then
        xr_logic.pstor_store(db.actor, "changing_level", 1)
    end
... и т.д.

 

Это нужно для того, чтобы сохранить информацию о том, какой это сейв - автосейв при смене локации или любой другой.

 

2) В функции actor_binder:net_spawn(data) допиши в конец перед return true вот такое:

 

    if xr_logic.pstor_retrieve(db.actor, "changing_level", 0) == 1 then
        -- Здесь производим нужные действия
        xr_logic.pstor_store(db.actor, "changing_level", 0)
    end

 

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

 

Ну, как заспавнить нужное количество нужных персонажей, ты, я думаю, знаешь :)

 

P.S. Писалось для ТЧ и проверялось на ТЧ, в других версиях не знаю, но что-то наподобие.

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

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение
Kirag, Я делал по-другому.Я в net_spawn() сохранял имя текущего левела.До того сравнивая с предыдущим сохраненным и по необходимости вызывая новопрописанный коллбэк level_change(old,new).

 

Кстати, да, этот метод даже толковее. Он и проще, и позволяет выполнять действия с учетом того, откуда перешли. Век живи, век учись :)

 

а я делал вообще вот так...

 

if level:name() == "l05_bar" then

-- спавнил

end

 

по памяти так, может метод как ни так написал, но смысл такой :)

 

Если это (и только это) в net_spawn актора, то у метода есть большой недостаток - он будет срабатывать не только при переходе на бар, но и при каждом Сейв/Лоаде, причем эффект будет накапливаться каждый С/Л. Вся возня с сохранением имени левелов или факта перехода как раз и нужна, чтобы от этого момента избавиться.

Хотя, смотря когда и что нужно.

 

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

TREWKO, по методу engaged() - используется ли машина кем-либо (true/false). Проверял исключительно на акторе, как сажать в машину непись - я не знаю. Как выгнать - соответственно тоже.

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

По примеру со здоровьем машины - используется чуть сложнее. Все приведенные тобой методы - методы класса CCar. Ты же в качестве переменной car получаешь game_object. Чтобы получить из него CCar, у game_object усть метод get_car(). Т.е. в результате получим:

local car = level_object_by_sid(21005)
car:get_car():SetfHealth(1)

С блокиратором... Сложно. Проще всего такую штуку делать в логике, НО почему-то у меня проблемы вплоть до вылета при попытке второй раз включить какую-либо секцию (любую и после любой, все секции, с которыми проверял, заведомо рабочие). Может, это только у меня? Можно попробовать в строке usable поставить не true, а условие, может помочь. Хотя не знаю, что будет, если условие перестанет выполняться в то время, когда актор в машине. От вылета актора из машины до вылета игры на рабочий стол. На самый крайний случай - залезть в схему и предусмотреть блокировку там, но решение этой задачи пока что совсем не представляю.

 

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

 

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение
DeVaSTaTOR from R.Z.T., посмотри в вертолетном моде spawn.script, функцию heli - это и есть функция спавна. Будет работать даже без мода, она сделана на "базовых" компонентах. Комменты, какой параметр зачем, тоже имеются.

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

TREWKO

А что такое "level_prefix_lights_hanging_lamp", что ты передаешь в функцию в качестве id? Насколько я понимаю, в level.object_by_id(id) агрументом должно быть число, а не строка... Посмотри, как можно из этой строки выжать

нужный(нужные) id.

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

TREWKO

А нафиг здесь таймер? В данном случае куда проще к часам привязаться. Схема простая:

if level.get_time_hours() == hh then
    <установить погоду>
    hh = hh +1 (либо level.get_time_factor(), а то и просто значение тайм фактора, если нужно в реальных часах вместо игровых, тайм фактор обычно целое число, проблем быть не должно)
    if hh > 23 then
        hh = hh - 24 -- в полночь получим 0
    end
end

 

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

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

andrewrap

Чтобы совсем не двигался... По-хорошему, надо бы новую комбат-схему написать, она давным-давно востребована. Логика на словах простая - "стой, придурок, где поставили, и стреляй во все, что заметишь". В принципе, в комбат-схеме зомбей есть что-то похожее - в тот момент, когда зомб знает, где цель, и эта цель близко, он именно так себя и ведет. Жаль, у меня руки коротки в АИ копаться...

 

Спецы по АИ возьмите на заметку, плиз

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

TREWKO

 

Не уверен, что при попытке прочитать три числа через запятую как float прочитает то, что надо, или хотя бы не вылетит...

 

Попробуй читать это, как строку, и перевести строку в таблицу. Например так:

 

local pr = system_ini():r_string("ini_section","ff_bul")

local pr_table = parse_data(pr)

local mins = tonumber(pr_table[1])

local maxs = tonumber(pr_table[2])

local tiss = tonumber(pr_table[3])

get_console():execute("Значение №1: "..mins.." Значение №2: "..maxs.." Значение №3: "..tiss)

 

Функция parse data у меня прописана в _g.script-е для удобства вызова, разбивает строку в таблицу по запятым, если запятая внутри скобок, она игнорируется, т.е например конструкция area(-117,170,100,alive) будет воспринята как одно целое.

 

function parse_data(str)
    local string_parts = {}
    if str == nil then
        string_parts[1] = nil
        return string_parts
    end
    local str_beg,str_end
    str_end = str
    local split_pos = find_split_pos(str_end)
    while split_pos ~= nil do
        str_beg, str_end = split_string(str_end,split_pos)
        table.insert(string_parts,str_beg)
        split_pos = find_split_pos(str_end)
    end
    table.insert(string_parts,str_end)
    return string_parts
end

function find_split_pos(str)
    local split_pos = string.find(str,",")
    if split_pos == nil then
        return nil
    end
    local br1_pos = string.find(str,"(",1,true)
    local br2_pos = string.find(str,")",1,true)
    if br1_pos ~= nil and br2_pos ~= nil and br1_pos < br2_pos and split_pos > br1_pos then
        local str_end1 = string.sub(str,(br2_pos +1),string.len(str))
        if string.find(str_end1,",") ~= nil then
            split_pos = br2_pos + string.find(str_end1,",")
        else
            split_pos = nil
        end
    end
    return split_pos
end

function split_string(str,split_pos)
    local str_beg = (string.sub(str,1,split_pos-1))
    local str_end = string.sub(str,(split_pos+1),string.len(str))
    return str_beg,str_end
end

 

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

Горчаков Антон

 

Что касается вылета на Затоне - проверь погоду, возмущается по поводу неверного погодного эффекта. Очень не уверен, что аномалии к этому вообще причастны.

 

По поводу отсутствия аномалий на Припяти, и почти на 100% уверен, на Затоне та же картина - тут дело, похоже, в вызове функций спавна. Ты же на ЧАЭС первый раз вызвал, я не ошибаюсь?

Проблема в том, что для определения позиций спавна ты используешь level.vertex_position(n). Метод нужный, но есть одно НО: он работает только для вертексов, расположенных на данной локации. На этой локации все и будет в порядке - аномалии будут в случайных местах, но привязаны к АИ-сетке, читай - к террейну.

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

Так что перед спавном надо делать проверку, какой именно текущий уровень, и спавнить аномалии только для него.

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

Горчаков Антон

 

Например вот так:

 

local lvl = level.name()
if lvl == "l01_escape" then
    -- действия для Кордона
elseif lvl == "l02_garbage" then
    -- действия для Свалки
elseif lvl == "l03_agroprom" then
    -- и т.д. по всем уровням
end

 

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

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

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

кровоSTALKER

А зачем это вообще в апдейте? Тебе ж нужно одноразовое действие при подборе предмета, насколько я понимаю. Перемести в функцию on_item_take(obj) и слегка подредактируй:

 

if obj:section() == "digger_pda" and not has_alife_info("find_instr") then
     db.actor:give_info_portion("find_instr")
     news_manager.send_tip(db.actor, "digger_tip", 10, "stalker", 10000)
     local snd_obj = xr_sound.get_safe_sound_object([[characters_voice\scenario\military\digger_msg]])
     snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0)
end

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

F.O.B.O

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

 

Посмотри в моей подписи мод "Ночные прицелы", там в конце шапки есть ссылка на смену оружия в ножевом слоте для ТЧ.

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение

Shadows,

 

if wpn and (wpn:section() == "wpn_crossbow" or wpn:section() == "wpn_arm_binoc") then

Мои работы:

Ночные прицелы + смена ножевого слота

AI вертолетов + ПЗРК

Soul Cube

 

Работаю только с ТЧ. С ковырянием ЧН/ЗП не связываюсь ни в какой форме. Совсем.

Поделиться этим сообщением


Ссылка на сообщение
×
×
  • Создать...