#1 23-07-2008 19:55

Mad Driver
From: Moscow
Registered: 21-07-2008
Posts: 2
Website

Работа с компонентами машины

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

Last edited by Seemann (24-11-2010 00:45)

Offline

#2 23-07-2008 20:09

3Doomer
From: КаZан
Registered: 14-05-2008
Posts: 659
Website

Re: Работа с компонентами машины

Экспериментальным путём ищешь оффсет выхлопной трубы и цепляешь с спецэффект к машине с таким оффсетом.

Я бы сделал, но у всех машин глушаки в разных местах)))


GIMS developer

Offline

#3 24-07-2008 13:47

listener
From: Vice City
Registered: 09-11-2006
Posts: 615
Website

Re: Работа с компонентами машины

Можно взять за основу создание эффектов нитры.
.text:006A3BD0     CAutomobile__createNitroParticles

Координаты выхлопной трубы (вектор в model space) лежат в первом поле vehicleStruct по индексу 6 (+0x48)
modelPtrs[modelIndex]->vehicleStruct->_f0[6]


C5 - GTA IV/RDR/GTA V script compiler.
~ 60% done.

Offline

#4 25-07-2008 08:56

3Doomer
From: КаZан
Registered: 14-05-2008
Posts: 659
Website

Re: Работа с компонентами машины

listener wrote:

Можно взять за основу создание эффектов нитры.
.text:006A3BD0     CAutomobile__createNitroParticles

Координаты выхлопной трубы (вектор в model space) лежат в первом поле vehicleStruct по индексу 6 (+0x48)
modelPtrs[modelIndex]->vehicleStruct->_f0[6]

А может где-нибудь есть координаты попадания пули при выстреле? Ведь там появляется спецэффект....можно будет сделать следы от пуль=))


GIMS developer

Offline

#5 07-07-2009 16:34

Gyr
From: Серпухов
Registered: 03-02-2009
Posts: 246
Website

Re: Работа с компонентами машины

Можно взять за основу создание эффектов нитры.
.text:006A3BD0     CAutomobile__createNitroParticles

Координаты выхлопной трубы (вектор в model space) лежат в первом поле vehicleStruct по индексу 6 (+0x48)
modelPtrs[modelIndex]->vehicleStruct->_f0[6]

Вектор то один, а координат должно быть три. Как быть?


Специально для тех, кто не умеет читать по английски. Мой ник читается как "ГИР"!!!
Народная мудрость:
Прежде чем задавать вопросы,ПОЧИТАЙ СПРАВКУ!!!!

Offline

#6 07-07-2009 18:25

listener
From: Vice City
Registered: 09-11-2006
Posts: 615
Website

Re: Работа с компонентами машины

Вектор (в данном случае - RwV3D (он же D3DVECTOR или rage::Vector3)) - набор из трех координат.

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


C5 - GTA IV/RDR/GTA V script compiler.
~ 60% done.

Offline

#7 10-07-2009 18:04

Alien
Registered: 12-10-2008
Posts: 564

Re: Работа с компонентами машины

круто:clap:
Только без базы listener'а разобраться невозможно. Там в иерархии объектов все жуть как запутано.:rolleyes: Одна структура ссылается на другую, та на третью и т.д. Я до сих пор в шоке от того, как listener все это реверсил.:wow:
Небольшой примерчик по использованию:

{$CLEO}
0000:
while true
    wait 100
    if
        player.Defined(0)
    then
        if
            actor.Driving($PLAYER_ACTOR)
        then
            if
                0ab0: 1 //LMB
            then
                03C0: 0@ = actor $PLAYER_ACTOR car 
                0AB1: call_scm_func @GetExhaustPipeOffset 1 car 0@ 1@ 2@ 3@
                066C: 0@ = attach_particle "flamethrower" to_car 0@ with_offset 1@ 2@ 3@ rotation 0.0 -90.0 0.0 flag 1
                while 0ab0: 1 //LMB
                    wait 100
                    064C: make_particle 0@ visible 
                end
                0650: destroy_particle 0@
            end
        end
    end
end

:GetExhaustPipeOffset
0A97: 0@ = car 0@ struct
0@ += 0x22 
0A8D: 0@ = read_memory 0@ size 2 virtual_protect 0 //model index
0@ *= 4
0@ += 0xA9B0C8
0A8D: 0@ = read_memory 0@ size 4 virtual_protect 0 //CModel
0@ += 0x5C                                        
0A8D: 0@ = read_memory 0@ size 4 virtual_protect 0 //vehicle struct
0@ += 0x48
0A8D: 1@ = read_memory 0@ size 4 virtual_protect 0 //x
0@ += 4
0A8D: 2@ = read_memory 0@ size 4 virtual_protect 0 //y
0@ += 4
0A8D: 3@ = read_memory 0@ size 4 virtual_protect 0 //z
0AB2: ret 3 1@ 2@ 3@

Скрипт добавляет пламя из огнемета к выхлопной трубе машины по нажатию lmb.
Можно еще проверить наличие у машины второй трубы, но второй партикл прицепить не получается=(... Наверно из-за того, что в структуре CPhysical только 1 поле для хранения указателя на attachment.

Last edited by Alien (12-07-2009 10:03)

Offline

#8 10-07-2009 18:57

Gyr
From: Серпухов
Registered: 03-02-2009
Posts: 246
Website

Re: Работа с компонентами машины

Да... Не думал я что всё так запутанно. Да и к тому же я еще не совсем разобрался с некоторыми опкодами. Что даёт опкод 0AB1: call_scm_func , например?


Специально для тех, кто не умеет читать по английски. Мой ник читается как "ГИР"!!!
Народная мудрость:
Прежде чем задавать вопросы,ПОЧИТАЙ СПРАВКУ!!!!

Offline

#9 23-09-2009 21:19

CraZZZy-GameRRR
From: Москва
Registered: 11-08-2009
Posts: 97
Website

Re: Работа с компонентами машины

А как координаты фар вычислить?

Offline

#10 23-09-2009 21:27

3Doomer
From: КаZан
Registered: 14-05-2008
Posts: 659
Website

Re: Работа с компонентами машины

поищи по форуму, кто-то делал


GIMS developer

Offline

#11 25-09-2009 07:44

Sw[ee]t
From: Нижний Новгород
Registered: 16-02-2009
Posts: 686
Website

Re: Работа с компонентами машины

CraZZZy-GameRRR wrote:

А как координаты фар вычислить?

Поиск по всем форумам.
И уточняй запрос в форме поиска, автор: listener  smile

Gyr wrote:

Что даёт опкод 0AB1: call_scm_func , например?

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

Offline

#12 25-09-2009 18:57

kostay scr
From: Беларусь
Registered: 25-05-2007
Posts: 176

Re: Работа с компонентами машины

Call scm func Дает возможность сделать gosub с возвращаемым значением - просто функция:)
Блин чё за тупы ошибки -Лает...

Last edited by kostay scr (26-09-2009 15:33)


GTA VC - ЭТО НАСТОЯЩАЯ ГТА!

Offline

#13 26-09-2009 14:58

listener
From: Vice City
Registered: 09-11-2006
Posts: 615
Website

Re: Работа с компонентами машины

Sw[ee]t wrote:
CraZZZy-GameRRR wrote:

А как координаты фар вычислить?

Поиск по всем форумам.
И уточняй запрос в форме поиска, автор: listener  smile

Не надо делать из меня икону wink Я далеко не всеведущ и не вездесущ.

Фары - нулевой компонент для передних и первый - для задних (смещения в VehicleStruct +0 и +12 соответственно). Как считаются координаты правой/левой фары внутри компонента я, не загладывая в код, не скажу (это должно быть где-то в районе CAutomobile::preRender/CAutomobile::render)/


C5 - GTA IV/RDR/GTA V script compiler.
~ 60% done.

Offline

#14 26-09-2009 16:51

Sw[ee]t
From: Нижний Новгород
Registered: 16-02-2009
Posts: 686
Website

Re: Работа с компонентами машины

Не надо делать из меня икону good Я далеко не всеведущ и не вездесущ.

Ну я точно помню, что писал именно ты.
Так бы не говорил.

Offline

#15 22-03-2010 09:44

~AquaZ~
Registered: 01-03-2010
Posts: 726

Re: Работа с компонентами машины

Может получить модель тачки, в зависимости от модели выбрать нужный оффсет и записать в 3 переменные store coords to ... with offset и будут координаты фары. Извините, если я на морозе.

Offline

#16 30-06-2010 09:28

kenking
From: Казахстан
Registered: 28-06-2010
Posts: 251

Re: Работа с компонентами машины

Alien wrote:

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

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

{$CLEO}
0000:
while true
    wait 0
    if
      Player.Defined($PLAYER_CHAR)
    then
        if  
          actor.Driving($PLAYER_ACTOR)
        then
            03C0: 0@ = actor $PLAYER_ACTOR car 
            08EC: 4@ = car 0@ type // Только для авто класса worker 
            if 
              04A3:   4@ == 4 // $ == any 
            then
                if 
                  01C1: car 0@ stopped
                then
                    if 
                      00E1: key_pressed 0 16
                    then
                        0AB1: call_scm_func @GetExhaustPipeOffset 1 car 0@ 1@ 2@ 3@
                        066C: 0@ = attach_particle "riot_smoke" to_car 0@ with_offset 1@ 2@ 3@ rotation 0.0 0.0 0.0 flag 1
                        064C: make_particle 0@ visible 
                        32@ = 0
                        while not 32@ > 1000
                        wait 0
                        end
                        0650: destroy_particle 0@
                    end
                end
            end
        end
    end
end

:GetExhaustPipeOffset
0A97: 0@ = car 0@ struct
0@ += 0x22 
0A8D: 0@ = read_memory 0@ size 2 virtual_protect 0 //model index
0@ *= 4
0@ += 0xA9B0C8
0A8D: 0@ = read_memory 0@ size 4 virtual_protect 0 //CModel
0@ += 0x5C                                        
0A8D: 0@ = read_memory 0@ size 4 virtual_protect 0 //vehicle struct
0@ += 0x48
0A8D: 1@ = read_memory 0@ size 4 virtual_protect 0 //x
0@ += 4
0A8D: 2@ = read_memory 0@ size 4 virtual_protect 0 //y
0@ += 4
0A8D: 3@ = read_memory 0@ size 4 virtual_protect 0 //z
0AB2: ret 3 1@ 2@ 3@

Offline

#17 30-06-2010 13:13

Den_spb
From: Ленинград
Registered: 23-11-2008
Posts: 937
Website

Re: Работа с компонентами машины

Всё хорошо, но опкод 04A3:   4@ == 4 // $ == any предназначен для глобальных переменных (судя по комментарию). В данной ситуации лучше использовать опкод для локальных переменных, а можно просто написать 4@ == 4 - тогда компилятор сам подставит нужный опкод.

Фары - нулевой компонент для передних и первый - для задних (смещения в VehicleStruct +0 и +12 соответственно). Как считаются координаты правой/левой фары внутри компонента я, не загладывая в код, не скажу (это должно быть где-то в районе CAutomobile::preRender/CAutomobile::render)/

По этим смещениям располагаются координаты передней правой и задней правой фары. Для получения координат левых фар надо умножить полученный X-оффсет на -1.0

Last edited by Den_spb (30-06-2010 19:09)

Offline

#18 30-06-2010 13:52

kenking
From: Казахстан
Registered: 28-06-2010
Posts: 251

Re: Работа с компонентами машины

Да, точно не тот опкод поставил, надо  04A4: 4@ == 4 // @ == any
Но скрипт работает и тем опкодом.

Offline

#19 12-03-2011 03:21

Den_spb
From: Ленинград
Registered: 23-11-2008
Posts: 937
Website

Re: Работа с компонентами машины

[center]Определение расположения трёхмерных компонентов моделей[/center]
Выше был описан способ для определения расположения некоторых компонентов в моделях транспорта. Общая формула такая:

0A97: 0@ = car 0@ struct
0@ += 0x22 
0A8D: 0@ = read_memory 0@ size 2 virtual_protect 0 //model index
0@ *= 4
0@ += 0xA9B0C8
0A8D: 0@ = read_memory 0@ size 4 virtual_protect 0 //CModel
0@ += 0x5C                                        
0A8D: 0@ = read_memory 0@ size 4 virtual_protect 0 //vehicle struct
0@ += OFFSET                 
0A8D: 1@ = read_memory 0@ size 4 virtual_protect 0 //x offset
0@ += 4
0A8D: 2@ = read_memory 0@ size 4 virtual_protect 0 //y offset
0@ += 4
0A8D: 3@ = read_memory 0@ size 4 virtual_protect 0 //z offset

Смещение OFFSET (кратно 12) будет зависеть от того, координаты какого компонента нужно определить:

+0 - правая передняя фара
+12 - правая задняя фара
+24 - правая передняя фара 2
+36 - правая задняя фара 2
+48 - правое переднее сиденье ??
+72 - источник выхлопных газов
+84 - источник дыма при снижении здоровья
+96 - бензобак

Примечание: если нужно определить координаты левой фары, то после получения оффсетов для правой фары, x-offset правой фары надо умножить на -1.0.

Нередко задают вопросы об определении расположения колёс, дверей и других "трёхмерных" компонентов моделей. Для таких компонентов порядок расчёта координат будет другой.
Здесь Alien публиковал код, позволяющий вычислить расположение пушки танка. Заменив смещение для пушки на смещение для другого компонента (см. таблицу ниже), можно определить его координаты. Общая формула:

         0A97: 1@ = car 0@ struct 
         1@ += OFFSET                            
         0A8D: 9@ = read_memory 1@ size 4 virtual_protect 0 
         if 
             9@ <> 0 
         then
             0AA7: call_function 0x7F0990 num_params 1 pop 1 9@ 10@
         end

В результате 10@ будет записан указатель на матрицу позиции компонента, через которую можно определить его координаты и углы поворота. Некоторые смещения:

0x650 - правое переднее колесо авто
0x658 - правое заднее колесо авто
0x65C - левое переднее колесо авто
0x664 - левое заднее колесо авто
0x668 - правая передняя дверь авто
0x66C - правая задняя дверь авто
0x670 - левая передняя дверь авто
0x674 - левая задняя дверь авто
0x678 - bump_front_dummy
0x67C - bump_rear_dummy
0x688 - bonnet_dummy (капот)
0x68C - boot_dummy (багажник)
0x690 - windscreen_dummy (ветровое стекло)
0x694 - не знаю что, точка между задними колёсами

0x69C - башня танка ?
0x6A0 - пушка танка

Пример: определим месторасположение багажника автомобиля и создадим в этой точке корону.

         0A97: 1@ = car 0@ struct 
         1@ += 0x68C                            
         0A8D: 9@ = read_memory 1@ size 4 virtual_protect 0 
         if 
             9@ <> 0 
         then
             0AA7: call_function 0x7F0990 num_params 1 pop 1 9@ 10@
             0A8E: 11@ = 10@ + 48 // int x
             0A8E: 12@ = 10@ + 52 // int y
             0A8E: 13@ = 10@ + 56 // int z
             0A8D: 11@ = read_memory 11@ size 4 virtual_protect 0
             0A8D: 12@ = read_memory 12@ size 4 virtual_protect 0
             0A8D: 13@ = read_memory 13@ size 4 virtual_protect 0
             04D5: create_corona_at 11@ 12@ 13@ radius 1.0 type 2 flare 2 RGB 0 255 0 
         end

Last edited by Den_spb (12-03-2011 03:24)

Offline

#20 14-03-2011 17:45

Den_spb
From: Ленинград
Registered: 23-11-2008
Posts: 937
Website

Re: Работа с компонентами машины

[center]Перемещение и вращение трёхмерных компонентов моделей[/center]
Существует возможность не только определения текущей позиции трёхмерного компонента, но и его перемещения/вращения в пространстве.
В структуре компонента по смещению 0x10 располагается матрица позиции компонента в системе координат родителя компонента (например, для пушки танка родителем будет являться башня, а для башни родителем будет являться сам танк). Меняя значения элементов данной матрицы, можно добиться перемещения или поворота компонента.
Пример 1. Создадим автомобиль с ID 506. Установим значение X-оффсета правого переднего колеса, равное 5.0

{$CLEO}
model.Load(506)
repeat
    wait 0
until model.Available(506)
car.Create(0@ 506 -2026.9618, 173.2921, 27.8359)
model.Destroy(506)     
while 056E: 0@ 
    wait 0 
    0A97: 1@ = car 0@ struct 
    1@ += 0x650 // правое переднее колесо
    0A8D: 1@ = read_memory 1@ size 4 virtual_protect 0
    if
        1@ <> 0
    then
        1@ += 0x10 // указатель на матрицу
        1@ += 48 // X-position. Суммирование в 2 этапа применено для наглядности.
        0A8C: write_memory 1@ size 4 value 5.0 virtual_protect 0  // записываем значение в элемент матрицы       
    end
end
0A93:

Результат:
71c163f0ddc3t.jpg
Пример 2. Создадим автомобиль с ID 544. Установим значение X-оффсета правой передней двери, равное 3.0. Также повернём дверь вокруг оси X на Pi/2 радианов (90.0 градусов)

{$CLEO}
model.Load(544)
repeat
    wait 0
until model.Available(544)
car.Create(0@ 544 -2026.9618, 173.2921, 27.8359)
model.Destroy(544)     
while 056E: 0@ 
    wait 0 
    0A97: 1@ = car 0@ struct 
    1@ += 0x668 // int
    0A8D: 1@ = read_memory 1@ size 4 virtual_protect 0
    if
        1@ <> 0
    then
        1@ += 0x10 
        1@ += 48
        0A8D: 2@ = read_memory 1@ size 4 virtual_protect 0 // сохраняем значения эл-тов +48, +52, +56 в памяти т.к. метод поворота матрицы их обнуляет
        1@ += 4
        0A8D: 3@ = read_memory 1@ size 4 virtual_protect 0
        1@ += 4
        0A8D: 4@ = read_memory 1@ size 4 virtual_protect 0
        1@ -= 56
        0AA6: call_method 0x59B120 struct 1@ num_params 3 pop 0 0.0 0.0 1.57  // rot Z rot Y rot X (radians) - метод поворота матрицы
        1@ += 48
        0A8C: write_memory 1@ size 4 value 3.0 virtual_protect 0 // устанавливаем новое значение X-position
        1@ += 4
        0A8C: write_memory 1@ size 4 value 3@ virtual_protect 0 // восстанавливаем старое значение Y-position      
        1@ += 4                                                       
        0A8C: write_memory 1@ size 4 value 4@ virtual_protect 0 // восстанавливаем старое значение Z-position         
    end
end
0A93:

Результат:
ef700af0603et.jpg
Ограничений по перемещению компонентов я не нашёл. А вот вращение приведённым способом похоже работает не для всех компонентов (например, для колёс).

Смещения трёхмерных компонентов, часть 2:

Спецкомпоненты автомобилей и самолётов:
0x698 - подъёмная платформа у #PACKER 443, скребок у #DOZER 486, подъёмник у #FORKLIFT 530,
бетономешалка #CEMENT 524, основание лестницы у #FIRELA 544, стрела у #TOWTRUCK 525
0x69C - лестница у #FIRELA 544  
0x6A0 - кузов у #DUMPER 406 
0x6A8 - люк у #ANDROM 592 
Средние колёса трёхосных автомобилей:
0x654 - правое среднее колесо
0x660 - левое среднее колесо 
Поезда:
0x66C - левая дверь
0x670 - правая дверь
0x674 - правое колесо 1
0x678 - правое колесо 2
0x67C - правое колесо 3
0x680 - правое колесо 4
0x684 - правое колесо 5
0x688 - правое колесо 6
0x68C - левое колесо 1
0x690 - левое колесо 2
0x694 - левое колесо 3
0x698 - левое колесо 4
0x69С - левое колесо 5
0x6A0 - левое колесо 6
0x6A4 - первая тележка (оси 1-3)
0x6A8 - вторая тележка (оси 4-6)

Как оказалось, используемые значения в структуре CTrain не ограничивается смещением 0x5A0.

Last edited by Den_spb (14-03-2011 18:03)

Offline

#21 14-03-2011 18:03

Alien
Registered: 12-10-2008
Posts: 564

Re: Работа с компонентами машины

например, для пушки танка родителем будет являться башня, а для башни родителем будет являться сам танк

Переписывание моего жаргонно написанного и вообще говоря ошибочного суждения.
@DenSpb - если уж хочешь читать лекции по таким темам, лучше наверное начать с объяснения структуры RwMatrix и векторно-матричных преобразований в целом. listener пытался тут объяснить некоторые аспекты "на пальцах". Но там не хватает картинок, объяснения без них воспринимаются тяжело. Лучше взять какую-нибудь литературу по этой тематике.

Last edited by Alien (14-03-2011 18:16)

Offline

#22 14-03-2011 18:58

Den_spb
From: Ленинград
Registered: 23-11-2008
Posts: 937
Website

Re: Работа с компонентами машины

Переписывание моего жаргонно написанного и вообще говоря ошибочного суждения.

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

если уж хочешь читать лекции по таким темам

Лекции я читать не собирался, здесь не "Справочный раздел" - просто меня пару раз спрашивали о вычислении координат колёс авто,

Last edited by Den_spb (14-03-2011 19:03)

Offline

#23 15-03-2011 06:32

kenking
From: Казахстан
Registered: 28-06-2010
Posts: 251

Re: Работа с компонентами машины

Alien wrote:

Можно еще проверить наличие у машины второй трубы

Если не затруднит, то напиши пожалуйста код такой проверки и определение координат для второй трубы.
Ещё меня интересует как определить из Handling какой тип двигателя установлен на транспорте (дизель, бензин и т.д)?
Заранее спасибо.

Den_spb wrote:

Перемещение и вращение трёхмерных компонентов моделей

Денис, спасибо за доходчивое объяснение полезной информации. 

Den_spb wrote:

А вот вращение приведённым способом похоже работает не для всех компонентов (например, для колёс).

Жалко, что для колёс не работает.

Den_spb wrote:

Некоторые смещения:

Если знаешь, то напиши пожалуйста ещё смещение wing (крылья модели авто).

Ещё сразу вопрос:  координаты компонентов авто определяются в глобальной системе координат. Как пересчитать эти координаты из глобальной системы координат в локальную (связанную с машиной)? Например, для того, чтобы прицепить к авто объект по этим координатам (с этим оффсетом). Я читал твой пост о пересчёте компонентов вектора скорости в теме 'Один вопрос' здесь. Как применить это для координат компонентов авто?
Заранее спасибо.

Offline

#24 15-03-2011 12:57

3Doomer
From: КаZан
Registered: 14-05-2008
Posts: 659
Website

Re: Работа с компонентами машины

вторая труба располагается зеркально первой по оси Y
x2 = -x1
y2 = y1
z2 = z1

Last edited by 3Doomer (15-03-2011 13:00)


GIMS developer

Offline

#25 15-03-2011 18:39

Alien
Registered: 12-10-2008
Posts: 564

Re: Работа с компонентами машины

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

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

Если не затруднит, то напиши пожалуйста код такой проверки и определение координат для второй трубы.
Ещё меня интересует как определить из Handling какой тип двигателя установлен на транспорте (дизель, бензин и т.д)?
Заранее спасибо.

Наличие второй трубы - один из флагов в handling.cfg. Смотри код для создания эффектов нитры, адрес написан выше. Тип двигателя тоже прописан в handling.cfg.

Как пересчитать эти координаты из глобальной системы координат в локальную (связанную с машиной)?

Не надо ничего пересчитывать - они уже посчитатаны. Локальные координаты первичны по отношению к глобальным. Глобальные координаты хранятся в Local Transform Matrix (RwFrame + 50h), локальные - в modelling-матрице (RwFrame + 10h).

Last edited by Alien (15-03-2011 18:40)

Offline

Board footer

Powered by FluxBB