INNE Tworzenie NewGRF w NML #1 - drezyna WM-15A.
#3
Drezyna WM-15A - wersja podstawowa...
Korzystając z przedstawionych wcześniej zasad narysowałem widoki drezyny WM-15A oraz towarzyszącej jej często przyczepy PWM-15. Grafiki zostały przygotowane w oparciu o opracowane wcześniej szablony, wykorzystujące paletę DOS. Pasek pod oknami kabiny został narysowany z użyciem kolorów o indeksach z grupy "Company", w grze będzie więc przybierał kolory gracza:

[Obrazek: 244wm15a.png]

Dla tak przygotowanego rysunku należy następnie zdefiniować w języku NML zestawy sprite-ów, opisujące poszczególne pojazdy. Do tego celu wykorzystamy template-y, zdefiniowane w jednym z wcześniejszych postów:
Kod:
spriteset(spriteset_wm15a_empty, "gfx/wm15a.png") {
    template_sprite_train(4, 20)
}
spriteset(spriteset_wm15a_purchase, "gfx/wm15a.png") {
    template_sprite_purchase(4, 100)
}
spriteset(spriteset_pwm15_empty, "gfx/wm15a.png") {
    template_sprite_train(4, 60)
}
spriteset(spriteset_pwm15_purchase, "gfx/wm15a.png") {
    template_sprite_purchase(4, 120)
}

Spriteset-y to zestawy sprite-ów, wykorzystywanych przez grę do wyświetlenia pojazdu. Typowo jest to 8 sprite-ów, ukazujących pojazd ze wszystkich stron. W przypadku pojazdów symetrycznych, w dodatku rozrysowanych na szablonie 8/8, zestaw sprite-ów może zostać ograniczony do 4 widoków. W naszym przypadku zestaw 8 widoków drezyny jest wczytywany za pomocą jednego wywołania template-u template_sprite_train.
Pojedyncze sprite-y, które mają w nazwie "_purchase" to ikonki, wyświetlane w menu kupowania nowego taboru. Sprite-y te są opcjonalne. Mogą być wykorzystane np. do wyświetlenia dodatkowych informacji o pojeździe.

Kolejnym krokiem jest zdefiniowanie w NML pojazdu oraz zaprogramowanie jego parametrów. Kod NML, definiujący drezynę WM-15A wygląda następująco:
Kod:
item(FEAT_TRAINS, item_wm15a) {
    property {
        /* common properties */
        name:                           string(STR_WM15A_NAME);
        climates_available:             bitmask(CLIMATE_TEMPERATE, CLIMATE_ARCTIC);
        introduction_date:              date(1977, 1, 1);
        model_life:                     VEHICLE_NEVER_EXPIRES;
        vehicle_life:                   20;
        reliability_decay:              20;
        refittable_cargo_classes:       bitmask(CC_PASSENGERS, CC_MAIL, CC_EXPRESS, CC_PIECE_GOODS);
        non_refittable_cargo_classes:   bitmask(CC_REFRIGERATED, CC_LIQUID);
        cargo_allow_refit:              [];
        cargo_disallow_refit:           [];
        loading_speed:                  5;
        cost_factor:                    10;
        running_cost_factor:            18;
        /* train properties */
        sprite_id:                      SPRITE_ID_NEW_TRAIN;
        speed:                          80 km/h;
        misc_flags:                     bitmask();
        refit_cost:                     0;
        track_type:                     RAIL;
        ai_special_flag:                AI_FLAG_CARGO;
        power:                          147 kW;
        running_cost_base:              RUNNING_COST_DIESEL;
        dual_headed:                    0;
        cargo_capacity:                 15;
        weight:                         20 ton;
        ai_engine_rank:                 0; // not intended to be used by the ai
        engine_class:                   ENGINE_CLASS_DIESEL;
        extra_power_per_wagon:          0 kW;
        tractive_effort_coefficient:    0.3;
        air_drag_coefficient:           0.1;
        length:                         8;
        extra_weight_per_wagon:         0;
        visual_effect_and_powered:      visual_effect_and_powered(VISUAL_EFFECT_DIESEL, -2, DISABLE_WAGON_POWER);
        bitmask_vehicle_info:           0;
    }
    graphics {
        default:            spriteset_wm15a_empty;
        purchase:           spriteset_wm15a_purchase;
    }
}

W sekcji property znajduje się lista parametrów, definiujących właściwości nowego pojazdu. Przyglądając się kodowi, warto zwrócić uwagę na parę rzeczy. Jedną z nich jest sposób zdefiniowania listy obsługiwanych ładunków. Konfiguracja ładunków jest dokonana wyłącznie przy użyciu tzw. klas towarów, bez wymieniania ich z nazwy. Zgodnie z zapisem, drezyna będzie bardzo uniwersalnym pojazdem. Będzie ona mogła wozić zarówno pasażerów (jakoś się wcisną do małej kabiny Smile), pocztę, jak i różne towary, określane ogólnie "drobnicą", lecz z wykluczeniem towarów wymagających przewożenia w chłodniach oraz ciekłych. Taka ogólna konfiguracja pozwala na obsługę również innych towarów niż występujące domyślnie w OTTD, np. towarów wprowadzonych do gry przez inne dodatki.
Pełną listę oraz opis dostępnych parametrów pojazdów można znaleźć tutaj: http://newgrf-specs.tt-wiki.net/wiki/NML...icle_types .

W sekcji graphics zdefiniowane są natomiast zestawy sprite-ów, wymaganych do wyświetlenia pojazdu na ekranie. W najprostszej wersji wymagany jest tylko jeden zestaw: default.

W podobny sposób została zdefiniowana przyczepka PWM-15:
Kod:
item(FEAT_TRAINS, item_pwm15) {
    property {
        /* common properties */
        name:                           string(STR_PWM15_NAME);
        climates_available:             bitmask(CLIMATE_TEMPERATE, CLIMATE_ARCTIC);
        introduction_date:              date(1977, 1, 1);
        model_life:                     VEHICLE_NEVER_EXPIRES;
        vehicle_life:                   20;
        reliability_decay:              20;
        refittable_cargo_classes:       bitmask(CC_MAIL, CC_EXPRESS, CC_PIECE_GOODS);
        non_refittable_cargo_classes:   bitmask(CC_REFRIGERATED, CC_LIQUID);
        cargo_allow_refit:              [];
        cargo_disallow_refit:           [];
        loading_speed:                  5;
        cost_factor:                    130;
        running_cost_factor:            1;
        /* train properties */
        sprite_id:                      SPRITE_ID_NEW_TRAIN;
        speed:                          80 km/h;
        misc_flags:                     bitmask();
        refit_cost:                     0;
        track_type:                     RAIL;
        ai_special_flag:                AI_FLAG_CARGO;
        power:                          0;
        running_cost_base:              RUNNING_COST_DIESEL;
        cargo_capacity:                 15;
        weight:                         12 ton;
        ai_engine_rank:                 0; // not intended to be used by the ai
        extra_power_per_wagon:          0 kW;
        tractive_effort_coefficient:    0.3;
        air_drag_coefficient:           0.1;
        length:                         6;
        extra_weight_per_wagon:         0;
        visual_effect_and_powered:      visual_effect_and_powered(VISUAL_EFFECT_DISABLE, 0, DISABLE_WAGON_POWER);
        extra_weight_per_wagon:         0 ton;
        bitmask_vehicle_info:           0;
    }
    graphics {
        default:            spriteset_pwm15_empty;
        purchase:           spriteset_pwm15_purchase;
    }
}

Różnica, czy dany pojazd będzie traktowany przez grę jako wagon czy lokomotywa, wynika w zasadzie tylko z jednego parametru. W przypadku wagonu power = 0;
Niektóre parametry są w przypadku wagonu nieistotne lub mają trochę inne znaczenie. Przykładowo, parametr speed, który dla lokomotywy określa jej maksymalną prędkość, dla wagonu określa jego limit prędkości, spowalniający cały pociąg...

Niezależnie od powyższych różnic, przyczepa PWM15 ma ustawioną inną długość (6 jednostek), gdyż została zaprojektowana na szablonie 6/8. Została też pozbawiona (z oczywistych powodów) możliwości przewożenia pasażerów.

Na koniec jeszcze jedna praktyczna porada. Tworząc nowy dodatek GRF warto umieścić też w jego kodzie, w miejscu poprzedzającym wszelkie definicje spite'ów i pojazdów, niewielki fragment kodu, odpowiedzialny za prawidłowe wyświetlanie sprite'ów w menu zakupu pojazdów oraz w zajezdni:
Kod:
train_width_32_px = 1;
traininfo_y_offset = 2;

Kompletny kod dodatku
Poniżej zamieszczam pełną treść plików, niezbędnych do skompilowania dodatku:
custom_tags.txt
Kod:
VERSION     :0.1.0
TITLE       :WM-15A

lang/english.lng
Kod:
##grflangid 0x01
# This is the English language file

# GRF name and description
STR_GRF_NAME        :{TITLE} {VERSION}
STR_GRF_DESCRIPTION :{TITLE} - the most known polish trolley.{}{COPYRIGHT}2011 Tadeusz Domagalski{}License: GPL v2

STR_WM15A_NAME      :Trolley WM-15A (Diesel)
STR_PWM15_NAME      :Trailer PWM-15

lang/polish.lng
Kod:
##grflangid 0x30
# Polska wersja językowa

# Nazwa GRF oraz opis
STR_GRF_NAME        :{TITLE} {VERSION}
STR_GRF_DESCRIPTION :{TITLE} - popularna polska drezyna.{}{COPYRIGHT}2011 Tadeusz Domagalski{}License: GPL v2

STR_WM15A_NAME      :Drezyna WM-15A (Diesel)
STR_PWM15_NAME      :Przyczepa PWM-15

wm15a.nml
Kod:
grf {
    grfid: "TD\01\01";
    name: string(STR_GRF_NAME);
    desc: string(STR_GRF_DESCRIPTION);
    version: 0;
    min_compatible_version: 0;
}

/* graphics definition */
template template_sprite_train(x, y) {
// [left_x,   upper_y,    width,    height,    offset_x,    offset_y]
    [x,          y,         12,        28,          -5,        -16]
    [x+ 16,      y,         26,        28,         -17,        -18]
    [x+ 46,      y,         36,        20,         -17,        -14]
    [x+ 86,      y,         26,        28,          -7,        -18]
    [x+120,      y,         12,        28,          -5,        -16]
    [x+136,      y,         26,        28,         -17,        -18]
    [x+166,      y,         36,        20,         -17,        -14]
    [x+206,      y,         26,        28,          -7,        -18]
}
template template_sprite_purchase(x, y) {
// [left_x,   upper_y,    width,    height,    offset_x,    offset_y]
    [x,          y,         50,        12,         -25,         -8]
}

train_width_32_px = 1;
traininfo_y_offset = 2;

/* empty sprites */
spriteset(spriteset_wm15a_empty, "gfx/wm15a.png") {
    template_sprite_train(4, 20)
}
spriteset(spriteset_wm15a_purchase, "gfx/wm15a.png") {
    template_sprite_purchase(4, 100)
}
spriteset(spriteset_pwm15_empty, "gfx/wm15a.png") {
    template_sprite_train(4, 60)
}
spriteset(spriteset_pwm15_purchase, "gfx/wm15a.png") {
    template_sprite_purchase(4, 120)
}

/* Define the actual train */
item(FEAT_TRAINS, item_wm15a) {
    property {
        /* common properties */
        name:                           string(STR_WM15A_NAME);
        climates_available:             bitmask(CLIMATE_TEMPERATE, CLIMATE_ARCTIC);
        introduction_date:              date(1977, 1, 1);
        model_life:                     VEHICLE_NEVER_EXPIRES;
        vehicle_life:                   20;
        reliability_decay:              20;
        refittable_cargo_classes:       bitmask(CC_PASSENGERS, CC_MAIL, CC_EXPRESS, CC_PIECE_GOODS);
        non_refittable_cargo_classes:   bitmask(CC_REFRIGERATED, CC_LIQUID);
        cargo_allow_refit:              [];
        cargo_disallow_refit:           [];
        loading_speed:                  5;
        cost_factor:                    10;
        running_cost_factor:            18;
        /* train properties */
        sprite_id:                      SPRITE_ID_NEW_TRAIN;
        speed:                          80 km/h;
        misc_flags:                     bitmask();
        refit_cost:                     0;
        track_type:                     RAIL;
        ai_special_flag:                AI_FLAG_CARGO;
        power:                          147 kW;
        running_cost_base:              RUNNING_COST_DIESEL;
        dual_headed:                    0;
        cargo_capacity:                 15;
        weight:                         20 ton;
        ai_engine_rank:                 0; // not intended to be used by the ai
        engine_class:                   ENGINE_CLASS_DIESEL;
        extra_power_per_wagon:          0 kW;
        tractive_effort_coefficient:    0.3;
        air_drag_coefficient:           0.1;
        length:                         8;
        extra_weight_per_wagon:         0;
        visual_effect_and_powered:      visual_effect_and_powered(VISUAL_EFFECT_DIESEL, -2, DISABLE_WAGON_POWER);
        bitmask_vehicle_info:           0;
    }
    graphics {
        default:            spriteset_wm15a_empty;
        purchase:           spriteset_wm15a_purchase;
    }
}

item(FEAT_TRAINS, item_pwm15) {
    property {
        /* common properties */
        name:                           string(STR_PWM15_NAME);
        climates_available:             bitmask(CLIMATE_TEMPERATE, CLIMATE_ARCTIC);
        introduction_date:              date(1977, 1, 1);
        model_life:                     VEHICLE_NEVER_EXPIRES;
        vehicle_life:                   20;
        reliability_decay:              20;
        refittable_cargo_classes:       bitmask(CC_MAIL, CC_EXPRESS, CC_PIECE_GOODS);
        non_refittable_cargo_classes:   bitmask(CC_REFRIGERATED, CC_LIQUID);
        cargo_allow_refit:              [];
        cargo_disallow_refit:           [];
        loading_speed:                  5;
        cost_factor:                    130;
        running_cost_factor:            1;
        /* train properties */
        sprite_id:                      SPRITE_ID_NEW_TRAIN;
        speed:                          80 km/h;
        misc_flags:                     bitmask();
        refit_cost:                     0;
        track_type:                     RAIL;
        ai_special_flag:                AI_FLAG_CARGO;
        power:                          0;
        running_cost_base:              RUNNING_COST_DIESEL;
        cargo_capacity:                 15;
        weight:                         12 ton;
        ai_engine_rank:                 0; // not intended to be used by the ai
        extra_power_per_wagon:          0 kW;
        tractive_effort_coefficient:    0.3;
        air_drag_coefficient:           0.1;
        length:                         6;
        extra_weight_per_wagon:         0;
        visual_effect_and_powered:      visual_effect_and_powered(VISUAL_EFFECT_DISABLE, 0, DISABLE_WAGON_POWER);
        extra_weight_per_wagon:         0 ton;
        bitmask_vehicle_info:           0;
    }
    graphics {
        default:            spriteset_pwm15_empty;
        purchase:           spriteset_pwm15_purchase;
    }
}

Po skompilowaniu dodatku do formatu GRF i przekopiowaniu go do katalogu ...\content_download\newgrf, można się już cieszyć nowymi pojazdami, które są dostępne z menu zajezdni jako nowa lokomotywa i nowy wagon.Tongue

c.d.n.


Wiadomości w tym wątku

Skocz do:

[-]
Zamknięcie forum OpenTTD Polska
Forum OpenTTD Polska zostało wyłączone. Obecnie znajduje się tu archiwum dyskusji o dodatkach tworzonych przez naszą społeczność.
Po aktualne treści i dyskusje zapraszamy na nasz discord! :)

[-]
Discord