#1 14-11-2010 05:10

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

Улучшение движения трамваев [REL/CLEO4/GTA SA]

Описание:

Скрипт улучшает движение трамваев в игре, делая его более реалистичным и безопасным:
- Трамвай останавливается, если перед ним имеется препятствие (пешеход, транспортное средство).
- Трамвай останавливается на запрещающий сигнал светофора попутного направления
   (в том числе и на выходе с перекрёстка, что является минусом).
- Трамвай останавливается на остановках, обозначенных специальным знаком.
   Иногда на остановках в трамвай будут заходить пассажиры (или выходить из него).
- В трамваях появляются водители.
- Игрок может войти в трамвай как водитель (кнопка "["  ) или как пассажир (кнопка "]").
   Перед нажатием кнопок надо подойти к трамваю. Стоимость проезда игрока пассажиром - 5$.
- На карте трамвай будет обозначен синим маркером.

Установка:

1.Скачать и установить библиотеку КЛЕО 4 с сайта http://cleo.sannybuilder.com/
2.Поместить файл clever_trams.cs в папку cleo.

Примечания:

1.Во время миссии скрипт работать не будет.
2.Скрипт ищет трамвай по номеру модели (ID 449).

Код (готовый скрипт прикреплён к сообщению):

{$CLEO}                      // Improvement of trams traffic  (by Den_spb)
var
    0@: Integer 
    1@: Integer
                   // 2-14 переменные для одноразовых значений
    15@: Integer
    16@: Integer
    17@: Integer
    18@: Float
    19@: Float
    20@: Integer
    21@: Float
    22@: Integer
    23@: Integer
end
const
    TRAM = 0@
    TRAM_STRUCT = 1@
    FLAGS = 15@
    PASSENGER_0 = 16@
    PASSENGER_1 = 17@
    LAST_0BJECT_X = 18@
    LAST_0BJECT_Y = 19@
    0BJECT = 20@
    Y_DIMENSION = 21@
    MAR_KER = 22@
    STOPS_C0UNT = 23@
                         // BIT FLAGS:
    MANY_CARRIAGES = 0
    AUTODRIVE_OFF = 1
    TRAM_IS_STOPPING = 2
    CJ_IS_PASSENGER = 3
end
TRAM = -1
0A8C: write_memory 0x6F7863 size 2 value 0 virtual_protect 1  // при создании трамваев создавать и водителей для них
LAST_0BJECT_X = 50000.0
LAST_0BJECT_Y = 50000.0
while true
    wait 0
    if or
        not player.Defined($PLAYER_CHAR)
        $ONMISSION <> 0                      
    then
        continue
    end
    if
        856E:   not car TRAM defined     
    then
        if
            8154:   not actor $PLAYER_ACTOR in_zone 'SF'  // San Fierro
        then
            continue
        end
        if      
            gosub @SEARCH_TRAM
        then
            marker.CreateAboveCar(MAR_KER TRAM) 
            07E0: set_marker MAR_KER type_to 1  
            018B: set_marker MAR_KER radar_mode 2   
            FLAGS = 0
            0A97: TRAM_STRUCT = car TRAM struct
            TRAM_STRUCT += 0x5D4
            0A8D: TRAM_STRUCT = read_memory TRAM_STRUCT size 4 virtual_protect 0
            07E4: get_model 449 dimensions_cornerA_to 2@ 3@ 4@ dimensions_cornerB_to 5@ Y_DIMENSION 7@
            if
                TRAM_STRUCT > 0
            then
                Y_DIMENSION += 16.0
                08BD: set FLAGS bit MANY_CARRIAGES
            else
                Y_DIMENSION += 12.0 
            end
            0209: 8@ = random_int_in_ranges 0 2
            if
                8@ == 0
            then
                0561: PASSENGER_0 = create_passenger_in_car TRAM seat 0
                actor.RemoveReferences(PASSENGER_0)
            else 
                0561: PASSENGER_1 = create_passenger_in_car TRAM seat 1
                actor.RemoveReferences(PASSENGER_1)
            end   
        end            
    else                                                                                           // tram defined
        0AB5: store_actor $PLAYER_ACTOR closest_vehicle_to 2@ closest_ped_to 3@
        if and                              // посадка игрока в трамвай в качестве водителя или пассажира при нажатии клавиш
            003B:   2@ == TRAM // (int) 
            $ONMISSION == 0
            not actor.Driving($PLAYER_ACTOR) 
        then
            if
                0AB0:  key_pressed 219 //      [
            then
                05CB: AS_actor $PLAYER_ACTOR enter_car TRAM as_driver -1 ms
            else
                if
                    0AB0:  key_pressed 221 //      ]
                then
                    if
                        0431:   car TRAM passenger_seat_free 0 
                    then
                        05CA: AS_actor $PLAYER_ACTOR enter_car TRAM passenger_seat 0 -1 ms 
                    else
                        if
                            0431:   car TRAM passenger_seat_free 1
                        then
                            05CA: AS_actor $PLAYER_ACTOR enter_car TRAM passenger_seat 1 -1 ms
                        end
                    end    
                end
            end
        end      // cj entering tram
        046C: 2@ = car TRAM driver
        if
            856D:  not  actor 2@ defined 
        then
            08BD: set FLAGS bit AUTODRIVE_OFF
            06DD: set_train TRAM speed 0.0
        end        
        if                                    // выполнение действий при произведённой посадке игрока в трамвай
            actor.InCar($PLAYER_ACTOR TRAM)
        then
            if
                003C:   $PLAYER_ACTOR == 2@ // (int) 
            then
                08BD: set FLAGS bit AUTODRIVE_OFF
                06DD: set_train TRAM speed 0.0
            else
                if
                    88B7:   not test FLAGS bit CJ_IS_PASSENGER 
                then
                    08BD: set FLAGS bit CJ_IS_PASSENGER
                    0109: player $PLAYER_CHAR money += -5    
                end 
            end
        else
            08C3: clear FLAGS bit CJ_IS_PASSENGER 
        end        //   cj not in tram
        if
            88B7:   not test FLAGS bit AUTODRIVE_OFF    // автоведение включено
        then
            if
                88B7:   not test FLAGS bit TRAM_IS_STOPPING   // если не включён процесс остановки перед знаком остановки
            then
                if
                    gosub @CHECK_OBSTACLES
                then
                    06DD: set_train TRAM speed 0.0
                  {  Car.StorePos(TRAM 2@ 3@ 10@) ///////////////////////////////////////////////////////////////////////////////////////////
                    10@ += 3.0
                    024F: create_corona_with_radius 1.0 type 2 lensflares 0 with_color 255 255 0 at 2@ 3@ 10@ /////////////////////      }
                else
                    Car.StorePos(TRAM 2@ 3@ 10@)
                    0407: store_coords_to 5@ 6@ 4@ from_car TRAM with_offset 0.0 -1.0 0.0 
                    0407: store_coords_to 7@ 8@ 4@ from_car TRAM with_offset 0.0 1.0 0.0
                    0509: 4@ = distance_between_XY LAST_0BJECT_X LAST_0BJECT_Y and_XY 5@ 6@
                    0509: 9@ = distance_between_XY LAST_0BJECT_X LAST_0BJECT_Y and_XY 7@ 8@
                    if
                        0025:   9@ > 4@ // (float) 
                    then
                        0407: store_coords_to LAST_0BJECT_X LAST_0BJECT_Y 4@ from_car TRAM with_offset 0.0 -50000.0 0.0    
                    end 
                    if
                        gosub @SEARCH_OBJECTS
                    then
                        object.StorePos(0BJECT LAST_0BJECT_X LAST_0BJECT_Y 12@)
                        06DD: set_train TRAM speed 0.0
                      {  12@ += 2.0 ///////////////////////////////////////////////////////////////////////////////////////////////////////////
                        024F: create_corona_with_radius 1.0 type 2 lensflares 0 with_color 0 0 255 at LAST_0BJECT_X LAST_0BJECT_Y 12@ /////// }
                    else    
                        06DD: set_train TRAM speed 11.11
                    end                        
                end
            else
                if
                    01C1:   car TRAM stopped 
                then
                    if
                        32@ < -5000
                    then
                        32@ = -5000                       
                        if and
                            0431: car TRAM passenger_seat_free 0
                            0431: car TRAM passenger_seat_free 1
                        then
                            car.StorePos(TRAM 2@ 3@ 4@)
                            if
                                gosub @SEARCH_PASSENGERS
                            then   
                                0209: 8@ = random_int_in_ranges 0 2 
                                if
                                    8@ == 0
                                then
                                    05CA: AS_actor 5@ enter_car TRAM passenger_seat 0 -1 ms 
                                else
                                    05CA: AS_actor 5@ enter_car TRAM passenger_seat 1 -1 ms
                                end
                            end
                        else
                            if
                                STOPS_C0UNT >= 2
                            then
                                0432: PASSENGER_0 = get_actor_handle_from_car TRAM passenger_seat 0
                                if and
                                    056D:   actor PASSENGER_0 defined 
                                    803C:  not  $PLAYER_ACTOR == PASSENGER_0 // (int) 
                                then
                                    0633: AS_actor PASSENGER_0 exit_car   
                                else
                                    0432: PASSENGER_1 = get_actor_handle_from_car TRAM passenger_seat 1
                                    if and
                                        056D:   actor PASSENGER_1 defined 
                                        803C:  not  $PLAYER_ACTOR == PASSENGER_1 // (int) 
                                    then
                                        0633: AS_actor PASSENGER_1 exit_car
                                    end    
                                end
                                STOPS_C0UNT = 0
                            else
                                STOPS_C0UNT += 1 
                            end     
                        end         
                    else
                        if
                            32@ >= 0
                        then
                            08C3: clear FLAGS bit TRAM_IS_STOPPING
                            06DD: set_train TRAM speed 11.11
                        end
                    end
                end
            end    // tram is stopping
        end  // cj is not driver          
    end   // tram defined
end

:SEARCH_TRAM        // ищем трамвай
if
    0AE2: TRAM = random_vehicle_near_point 0.0 0.0 0.0 in_radius 6000.0 find_next 0 pass_wrecked 1 //IF and SET
then
    repeat
        if
            0137:   car TRAM model == 449
        then
            0A97: TRAM_STRUCT = car TRAM struct
            TRAM_STRUCT += 0x5D0
            0A8D: TRAM_STRUCT = read_memory TRAM_STRUCT size 4 virtual_protect 0
            if
                TRAM_STRUCT == 0   // предыдущий вагон отсутствует (данный вагон является нулевым)
            then   
                0485: return_true
                return
            end
        end
    until 8AE2: not TRAM = random_vehicle_near_point 0.0 0.0 0.0 in_radius 6000.0 find_next 1 pass_wrecked 1 //IF and SET
end
TRAM = -1
8485: return_false
return

:CHECK_OBSTACLES       // ищем препятствия перед трамваем
07E4: get_model 449 dimensions_cornerA_to 2@ 3@ 4@ dimensions_cornerB_to 5@ 8@ 7@
2@ -= 0.1
5@ += 0.1
repeat
    0407: store_coords_to 9@ 10@ 11@ from_car TRAM with_offset 2@ 0.0 4@              //1
    0407: store_coords_to 12@ 13@ 14@ from_car TRAM with_offset 2@ Y_DIMENSION 4@
    if
        86BD:   not no_obstacles_between 9@ 10@ 11@ and 12@ 13@ 14@ solid 0 car 1 actor 1 object 0 particle 0 
    then
        0485: return_true
        return
    end
    0407: store_coords_to 9@ 10@ 11@ from_car TRAM with_offset 2@ Y_DIMENSION 4@     //2
    0407: store_coords_to 12@ 13@ 14@ from_car TRAM with_offset 5@ Y_DIMENSION 4@
    if
        86BD:   not no_obstacles_between 9@ 10@ 11@ and 12@ 13@ 14@ solid 0 car 1 actor 1 object 0 particle 0 
    then
        0485: return_true
        return
    end
    0407: store_coords_to 9@ 10@ 11@ from_car TRAM with_offset 5@ 0.0 4@             //3
    0407: store_coords_to 12@ 13@ 14@ from_car TRAM with_offset 5@ Y_DIMENSION 4@
    if
        86BD:   not no_obstacles_between 9@ 10@ 11@ and 12@ 13@ 14@ solid 0 car 1 actor 1 object 0 particle 0 
    then
        0485: return_true
        return
    end
    0407: store_coords_to 9@ 10@ 11@ from_car TRAM with_offset 2@ 8@ 4@               //6
    0407: store_coords_to 12@ 13@ 14@ from_car TRAM with_offset 5@ 8@ 4@
    if
        86BD:   not no_obstacles_between 9@ 10@ 11@ and 12@ 13@ 14@ solid 0 car 1 actor 1 object 0 particle 0 
    then
        0485: return_true
        return
    end
    0087: 3@ = 2@ // (float)
    repeat
        0407: store_coords_to 9@ 10@ 11@ from_car TRAM with_offset 3@ 8@ 4@             //поперечн.
        0407: store_coords_to 12@ 13@ 14@ from_car TRAM with_offset 3@ Y_DIMENSION 4@
        if
            86BD:   not no_obstacles_between 9@ 10@ 11@ and 12@ 13@ 14@ solid 0 car 1 actor 1 object 0 particle 0 
        then
            0485: return_true
            return
        end               
        3@ += 0.4 // старое значение 0.2
    until 0025:   3@ > 5@ // (float)            
    4@ += 1.0  //  старое значение 0.5
until 0025:   4@ > 7@ // (float)
8485: return_false 
return

:SEARCH_PASSENGERS    // ищем пассажиров, желающих прокатиться на трамвае
if
    0AE1: 5@ = random_actor_near_point 2@ 3@ 4@ in_radius 20.0 find_next 0 pass_deads 1 //IF and SET
then
    repeat
        089F: get_actor 5@ pedtype_to 6@ 
        if or
            6@ == 4
            6@ == 5
        then
            080E: get_actor 5@ ped_event_to 6@
            if and
                6@ == 13
                803B: not 5@ == $PLAYER_ACTOR // (int) 
            then
                0485: return_true
                return
            end
        end
    until 8AE1: not 5@ = random_actor_near_point 2@ 3@ 4@ in_radius 20.0 find_next 1 pass_deads 1 //IF and SET
end
8485: return_false
return

:SEARCH_OBJECTS   // ищем попутный светофор с запрещающим сигналом или знак трамвайной остановки
if
    0AE3: 0BJECT = random_object_near_point 2@ 3@ 10@ in_radius Y_DIMENSION find_next 0
then
    repeat
        if and       // проверяем модель объекта
            89CC: not object 0BJECT model_is 3855  //   GAY_TRAFFIC_LIGHT      +
            89CC: not object 0BJECT model_is 1315  //   TRAFFICLIGHT1          +
            89CC: not object 0BJECT model_is 1352  //   CJ_TRAFFIC_LIGHT3      +
            89CC: not object 0BJECT model_is 1350  //   CJ_TRAFFIC_LIGHT4      +
            89CC: not object 0BJECT model_is 1351  //   CJ_TRAFFIC_LIGHT5      +
            89CC: not object 0BJECT model_is 3516  //      VGSSTRIPTLIGHTS1    +
            89CC: not object 0BJECT model_is 1283  //       MTRAFFIC1          +
        then
            if and
                89CC: not object 0BJECT model_is 1284   //      MTRAFFIC2      +
                89CC: not object 0BJECT model_is 1375   //    TRAMSTOP_SF      +                
            then
                continue
            end
        end                                 
        object.StorePos(0BJECT 4@ 9@ 12@)
        12@ += 1.0
        0509: 14@ = distance_between_XY 2@ 3@ and_XY 4@ 9@ 
        0509: 13@ = distance_between_XY 2@ 3@ and_XY LAST_0BJECT_X LAST_0BJECT_Y        
        if or    // находится ли новый объект ближе к трамваю, чем старый найденный объект и нет ли препятствий между трамваем и объектом
            0025:   14@ > 13@ // (float)
            86BD:   not no_obstacles_between 2@ 3@ 10@ and 4@ 9@ 12@ solid 1 car 0 actor 0 object 0 particle 0  
        then
            continue
        end     
        0509: 12@ = distance_between_XY 4@ 9@ and_XY 5@ 6@ 
        0509: 13@ = distance_between_XY 4@ 9@ and_XY 7@ 8@
        if          // находится ли новый объект перед трамваем
            0035:   13@ >= 12@ // (float) 
        then
            continue
        end
        if         // проверки угла и цвета светофора (если это светофор)
            09CC: object 0BJECT model_is 1375   //    TRAMSTOP_SF      + 
        then
            if and
                8045: not  4@ == LAST_0BJECT_X // (float) 
                8045: not  9@ == LAST_0BJECT_Y // (float) 
            then
                32@ = -900000
                08BD: set FLAGS bit TRAM_IS_STOPPING
                0485: return_true
                return
            end    
        else    // объект является светофором
            0174: 6@ = car TRAM Z_angle  //////////////////////////////////////////////////////////////////////////////////////////////////
            0176: 8@ = object 0BJECT Z_angle 
            0063: 8@ -= 6@ // (float)
            0656: get_angle 8@ absolute_degrees_to 8@
            if
                gosub @CHECK_TRAFFICLIGHT_ANGLE
            then
                0176: 8@ = object 0BJECT Z_angle
                if and
                    8@ >= 60.0
                    8@ <= 150.0
                then
                    0AA7: call_function 0x49D3A0 num_params 0 pop 0 9@ // тип светофора 2   WE
                else
                    if and
                        8@ >= 240.0
                        8@ <= 330.0
                    then
                        0AA7: call_function 0x49D3A0 num_params 0 pop 0 9@ // тип светофора 2   WE
                    else
                        0AA7: call_function 0x49D350 num_params 0 pop 0 9@ // тип светофора 1   NS
                    end
                end
                for 8@ = 8 to 31
                    08C3: clear 9@ bit 8@
                end  // значения функций: 0 - зелёный, 1 - желтый, 2 - красный
                if
                    9@ <> 0
                then
                    0485: return_true
                    return
                end            
            end             
        end        
    until  8AE3: not 0BJECT = random_object_near_point 2@ 3@ 10@ in_radius Y_DIMENSION find_next 1
end
8485: return_false
return

:CHECK_TRAFFICLIGHT_ANGLE  // проверяем, является ли светофор попутным трамваю
if or
    8@ > 315.0
    8@ < 45.0
then
    0485: return_true
    return
end
if or
    09CC: object 0BJECT model_is 1283
    09CC: object 0BJECT model_is 1284
then
    if and
        8@ > 135.0
        8@ < 225.0
    then
        0485: return_true
        return
    end
end    
8485: return_false
return

Last edited by Den_spb (16-11-2010 02:25)

Offline

#2 14-11-2010 10:28

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

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

Жесть!!!

Offline

#3 14-11-2010 18:02

Seemann
Registered: 07-08-2006
Posts: 2,156

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

Да, по описанию крутняк ))

Offline

#4 14-11-2010 21:21

Sergey81
Registered: 19-12-2008
Posts: 654

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

Ещё бы версию под cleo 3, если возможно ))

Offline

#5 14-11-2010 21:55

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

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

Переделывать под КЛЕО3 не буду, т.к. это довольно трудоёмко (например, в КЛЕО4 интерцептор состоит из одного опкода, а в КЛЕО3 для его использования надо писать большой кусок кода). Лучше установи КЛЕО4.

Offline

#6 14-11-2010 23:18

Sergey81
Registered: 19-12-2008
Posts: 654

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

Den_spb wrote:

Переделывать под КЛЕО3 не буду, т.к. это довольно трудоёмко (например, в КЛЕО4 интерцептор состоит из одного опкода, а в КЛЕО3 для его использования надо писать большой кусок кода). Лучше установи КЛЕО4.

Тогда мне как минимум надо будет проверить 60 скриптов на совместимость с клео4, половину(а то и больше) из которых придётся переписывать. И не факт, что переписать удастся, например тот же мод с картой по нажатию клавиши.

Offline

#7 14-11-2010 23:30

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

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

Покажи хоть один клео3-скрипт, который не работает с клео4.

Offline

#8 15-11-2010 00:36

Sergey81
Registered: 19-12-2008
Posts: 654

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

Ну например вот - http://gtag.gtagaming.com/forums/index. … wtopic=358
там же есть и решение как пофиксить.

Offline

#9 16-11-2010 02:35

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

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

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

0432: PASSENGER_0 = get_actor_handle_from_car TRAM passenger_seat 0
if and
    056D:   actor PASSENGER_0 defined 
    803C:  not  $PLAYER_ACTOR == PASSENGER_0 // (int) 
then
    0633: AS_actor PASSENGER_0 exit_car

Если PASSENGER_0 не существует, то 0432 возвращает отрицательный хэндл, а проверка на существование почему-то его пропускает. Я заменил проверку на существование проверкой хэндла на неотрицательность

if and
    PASSENGER_0 > 0 
    803C:  not  $PLAYER_ACTOR == PASSENGER_0 // (int) 
then
    0633: AS_actor PASSENGER_0 exit_car

Архив в первом сообщении обновлён.

Offline

#10 16-11-2010 05:47

mfisto
From: Russia Perm
Registered: 01-02-2008
Posts: 558
Website

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

0432: PASSENGER_0 = get_actor_handle_from_car TRAM passenger_seat 0
Вот этот опкод не стоит использовать, т.к он ставит Reference флаг на актера, поэтому лучше пройтись по стркутуре авто и вычислить пассажира.


I know everything and nothing...

Offline

#11 16-11-2010 14:35

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

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

дереференсить никак? что за тяга в память сразу лезть...


GIMS developer

Offline

#12 16-11-2010 14:44

mfisto
From: Russia Perm
Registered: 01-02-2008
Posts: 558
Website

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

Ты че серьезно что ли? а то что после этого пассажир выходит это как бы ничего, да?


I know everything and nothing...

Offline

#13 17-11-2010 03:42

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

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

mfisto wrote:

0432: PASSENGER_0 = get_actor_handle_from_car TRAM passenger_seat 0
Вот этот опкод не стоит использовать, т.к он ставит Reference флаг на актера, поэтому лучше пройтись по стркутуре авто и вычислить пассажира.

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

Offline

#14 17-11-2010 03:44

mfisto
From: Russia Perm
Registered: 01-02-2008
Posts: 558
Website

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

Хм, у себя я такого не замечал, ну да ладно, коли справедливо заметил.


I know everything and nothing...

Offline

#15 17-11-2010 04:10

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

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

А ты пассажиров сам создавал? Если да, и пользовался этим опкодом:

0561: 0@ = create_passenger_in_car 1@ seat 0

то он references включает.

Offline

#16 17-11-2010 15:52

mfisto
From: Russia Perm
Registered: 01-02-2008
Posts: 558
Website

Re: Улучшение движения трамваев [REL/CLEO4/GTA SA]

Да нет говорю же

0432: PASSENGER_0 = get_actor_handle_from_car TRAM passenger_seat 0

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


I know everything and nothing...

Offline

Board footer

Powered by FluxBB