INNE Tworzenie NewGRF w NML #1 - drezyna WM-15A.
#5
Kontynuując wątek tworzenia drezyny WM-15A, przedstawiam opis kolejnego etapu prac.

Projekt drezyny - wizualizacja towarów
Kolejnym etapem rozwoju projektu drezyny WM-15A jest dodanie wizualizacji przewożonych ładunków. Dotychczas bowiem drezyna była widoczna w grze cały czas jako pusta, nawet wtedy, kiedy była załadowana jakimś towarem.
Wprowadzenie takiej wizualizacji wymaga wcześniejszego opracowania dodatkowych kompletów grafik, przedstawiających pojazd w stanie załadowanym. W przypadku prezentowanej drezyny zestaw takich dodatkowych grafik jest bardzo obszerny, gdyż drezynę można przebudowywać do przewozu przeróżnych towarów:

[Obrazek: 308wm15a.png]

Powyższy zestaw grafik ukazuje drezynę wypełnioną towarami wynikającymi z obsługiwanej kombinacji (CC_PASSANGERS, CC_MAIL, CC_EXPRESS, CC_GOODS). Mamy więc: drewno, stal, żywiec i papier. Pozostałe ładunki wynikające z tej kombinacji (poczta i towary) oraz towary wprowadzone przez inne dodatki (FIRS, ECS, itp.) będą przedstawiane umownie w postaci uniwersalnych skrzyń. Pasażerowie (z oczywistych powodów) nie będą wizualizowani. Wink
Każdy komplet grafik przedstawia dodatkowo wagon załadowany w różnym stopniu: w około 50% oraz w 100%. Grafiki te będą wykorzystane m.in. do animacji procesu ładowania wagonu.

Uaktywnienie powyższych grafik wymaga zdefiniowania w kodzie NML wszystkich nowych spriteset-ów, przedstawiających ładunki, oraz połączenia ich w tzw. grupy sprite-ów (spritegroup), odpowiedzialnych za animacje. Grupa sprite-ów to obiekt, zawierający dwie listy spriteset-ów. Lista loading przedstawia sekwencję stanów pojazdu w trakcie jego załadunku/wyładunku. Natomiast lista loaded przedstawia stany pojazdu już pustego/załadowanego (będącego w trasie). Każda z obu list może zawierać dowolną liczbę spriteset-ów, przy czym pierwszy na liście odpowiada załadunkowi 0%, ostatni: 100%, a pośrednie: kolejnym stanom pośrednim załadunku. Definicja spritegroup-y dla jednego z przykładowych ładunków (towary) będzie wyglądała następująco:
Kod:
/* empty sprites */
spriteset(spriteset_wm15a_empty, "gfx/wm15a.png") {
    template_sprite_train(4, 20)
}
/* sprites with cargos */
spriteset(spriteset_wm15a_goods_half, "gfx/wm15a.png") {
    template_sprite_train(4, 80)
}
spriteset(spriteset_wm15a_goods_full, "gfx/wm15a.png") {
    template_sprite_train(4, 120)
}
spritegroup spritegroup_wm15a_goods {
    loaded:  [spriteset_wm15a_empty, spriteset_wm15a_goods_half, spriteset_wm15a_goods_full];
    loading: [spriteset_wm15a_empty, spriteset_wm15a_goods_half, spriteset_wm15a_goods_full];
}

Tak zdefiniowana przykładowa grupa sprite-ów będzie odpowiedzialna za animację, w której ilość widocznego ładunku będzie zależna od stopnia załadowania wagonu:
0 - 33%: wagon pusty,
33 - 66%: wagon z 1 skrzynią,
66 - 100%: wagon z 2 skrzyniami.
Takie przedziały animacji nie są jednak optymalne. Dla wagonu załadowanego np. w 67% bardziej bowiem pasowałby widok wagonu załadowanego w 50% niż w 100%.
Na szczęście "charakterystykę załadunku" można kształtować w dowolny sposób. I tak na przykład, zapis:
Kod:
spritegroup spritegroup_wm15a_goods {
    loaded:  [spriteset_wm15a_empty, spriteset_wm15a_goods_half, spriteset_wm15a_goods_half, spriteset_wm15a_goods_full];
    loading: [spriteset_wm15a_empty, spriteset_wm15a_goods_half, spriteset_wm15a_goods_half, spriteset_wm15a_goods_full];
}
... spowoduje, że zależność od stopnia załadowania wagonu będzie teraz wyglądała następująco:
0 - 25%: wagon pusty,
25 - 75%: wagon z 1 skrzynią,
75 - 100%: wagon z 2 skrzyniami.

Zdefiniowane spritegroup-y należy teraz powiązać z konkretnymi rodzajami ładunku. W tym celu konieczna jest rozbudowa naszej tabeli towarów o nowe wizualizowane towary:
Kod:
/* cargos */
cargotable {
    PASS, TOUR, MAIL,
    GOOD, WOOD, LVST, STEL, PAPR    // <- dodane
}

Wyświetlanie odpowiednich grafik można zrealizować za pośrednictwem switch-y. Jednak najprostszą metodą jest powiązanie towarów z grafikami bezpośrednio w sekcji graphics pojazdu:
Kod:
graphics {
        PASS:               spriteset_wm15a_empty;
        TOUR:               spriteset_wm15a_empty;
        WOOD:               spritegroup_wm15a_wood;
        LVST:               spritegroup_wm15a_lvstck;
        STEL:               spritegroup_wm15a_steel;
        PAPR:               spritegroup_wm15a_paper;
        default:            spritegroup_wm15a_goods;
        purchase:           spriteset_wm15a_purchase;
        can_attach_wagon:   switch_wm15a_can_attach;
        start_stop:         switch_wm15a_start_stop;
        cargo_capacity:     switch_wm15a_capacity;
    }
W przypadku pasażerów i turystów wyświetlany jest zawsze tylko jeden i ten sam spriteset, ukazujący drezynę z pustą paką. Dla innych wyszczególnionych ładunków wyświetlane są odpowiednie spritegroup-y. Natomiast w przypadku pozostałych ładunków (również tych nie wymienionych w GRF-ie) będzie wyświetlany uniwersalny spritegroup przedstawiający ładunek skrzyń.

Kompletny kod dodatku NewGRF
Poniżej zamieszczam pełną treść pliku nml, zawierającego wyżej opisane zmiany. Pozostałe pliki, prezentowane w poprzednim poście, nie uległy zmianie.

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,         10,        28,          -5,        -14]
    [x+ 16,      y,         26,        28,         -15,        -17]
    [x+ 46,      y,         36,        20,         -18,        -13]
    [x+ 86,      y,         26,        28,          -7,        -17]
    [x+120,      y,         10,        28,          -5,        -14]
    [x+136,      y,         26,        28,         -15,        -17]
    [x+166,      y,         36,        20,         -18,        -13]
    [x+206,      y,         26,        28,          -7,        -17]
}
template template_sprite_purchase(x, y) {
// [left_x,   upper_y,    width,    height,    offset_x,    offset_y]
    [x,          y,         50,        12,         -25,         -6]
}

/* empty sprites */
spriteset(spriteset_wm15a_purchase, "gfx/wm15a.png") {
    template_sprite_purchase(4, 60)
}
spriteset(spriteset_wm15a_empty, "gfx/wm15a.png") {
    template_sprite_train(4, 20)
}
spriteset(spriteset_pwm15_purchase, "gfx/wm15a.png") {
    template_sprite_purchase(244, 60)
}
spriteset(spriteset_pwm15_empty, "gfx/wm15a.png") {
    template_sprite_train(244, 20)
}
/* sprites with cargos */
spriteset(spriteset_wm15a_goods_half, "gfx/wm15a.png") {
    template_sprite_train(4, 80)
}
spriteset(spriteset_wm15a_goods_full, "gfx/wm15a.png") {
    template_sprite_train(4, 120)
}
spriteset(spriteset_pwm15_goods_half, "gfx/wm15a.png") {
    template_sprite_train(244, 80)
}
spriteset(spriteset_pwm15_goods_full, "gfx/wm15a.png") {
    template_sprite_train(244, 120)
}
spritegroup spritegroup_wm15a_goods {
    loaded:  [spriteset_wm15a_empty, spriteset_wm15a_goods_half, spriteset_wm15a_goods_half, spriteset_wm15a_goods_full];
    loading: [spriteset_wm15a_empty, spriteset_wm15a_goods_half, spriteset_wm15a_goods_half, spriteset_wm15a_goods_full];
}
spritegroup spritegroup_pwm15_goods {
    loaded:  [spriteset_pwm15_empty, spriteset_pwm15_goods_half, spriteset_pwm15_goods_half, spriteset_pwm15_goods_full];
    loading: [spriteset_pwm15_empty, spriteset_pwm15_goods_half, spriteset_pwm15_goods_half, spriteset_pwm15_goods_full];
}
spriteset(spriteset_wm15a_wood_half, "gfx/wm15a.png") {
    template_sprite_train(4, 160)
}
spriteset(spriteset_wm15a_wood_full, "gfx/wm15a.png") {
    template_sprite_train(4, 200)
}
spriteset(spriteset_pwm15_wood_half, "gfx/wm15a.png") {
    template_sprite_train(244, 160)
}
spriteset(spriteset_pwm15_wood_full, "gfx/wm15a.png") {
    template_sprite_train(244, 200)
}
spritegroup spritegroup_wm15a_wood {
    loaded:  [spriteset_wm15a_empty, spriteset_wm15a_wood_half, spriteset_wm15a_wood_half, spriteset_wm15a_wood_full];
    loading: [spriteset_wm15a_empty, spriteset_wm15a_wood_half, spriteset_wm15a_wood_half, spriteset_wm15a_wood_full];
}
spritegroup spritegroup_pwm15_wood {
    loaded:  [spriteset_pwm15_empty, spriteset_pwm15_wood_half, spriteset_pwm15_wood_half, spriteset_pwm15_wood_full];
    loading: [spriteset_pwm15_empty, spriteset_pwm15_wood_half, spriteset_pwm15_wood_half, spriteset_pwm15_wood_full];
}
spriteset(spriteset_wm15a_steel_half, "gfx/wm15a.png") {
    template_sprite_train(4, 240)
}
spriteset(spriteset_wm15a_steel_full, "gfx/wm15a.png") {
    template_sprite_train(4, 280)
}
spriteset(spriteset_pwm15_steel_half, "gfx/wm15a.png") {
    template_sprite_train(244, 240)
}
spriteset(spriteset_pwm15_steel_full, "gfx/wm15a.png") {
    template_sprite_train(244, 280)
}
spritegroup spritegroup_wm15a_steel {
    loaded:  [spriteset_wm15a_empty, spriteset_wm15a_steel_half, spriteset_wm15a_steel_half, spriteset_wm15a_steel_full];
    loading: [spriteset_wm15a_empty, spriteset_wm15a_steel_half, spriteset_wm15a_steel_half, spriteset_wm15a_steel_full];
}
spritegroup spritegroup_pwm15_steel {
    loaded:  [spriteset_pwm15_empty, spriteset_pwm15_steel_half, spriteset_pwm15_steel_half, spriteset_pwm15_steel_full];
    loading: [spriteset_pwm15_empty, spriteset_pwm15_steel_half, spriteset_pwm15_steel_half, spriteset_pwm15_steel_full];
}
spriteset(spriteset_wm15a_lvstck_half, "gfx/wm15a.png") {
    template_sprite_train(4, 320)
}
spriteset(spriteset_wm15a_lvstck_full, "gfx/wm15a.png") {
    template_sprite_train(4, 360)
}
spriteset(spriteset_pwm15_lvstck_half, "gfx/wm15a.png") {
    template_sprite_train(244, 320)
}
spriteset(spriteset_pwm15_lvstck_full, "gfx/wm15a.png") {
    template_sprite_train(244, 360)
}
spritegroup spritegroup_wm15a_lvstck {
    loaded:  [spriteset_wm15a_empty, spriteset_wm15a_lvstck_half, spriteset_wm15a_lvstck_half, spriteset_wm15a_lvstck_full];
    loading: [spriteset_wm15a_empty, spriteset_wm15a_lvstck_half, spriteset_wm15a_lvstck_half, spriteset_wm15a_lvstck_full];
}
spritegroup spritegroup_pwm15_lvstck {
    loaded:  [spriteset_pwm15_empty, spriteset_pwm15_lvstck_half, spriteset_pwm15_lvstck_half, spriteset_pwm15_lvstck_full];
    loading: [spriteset_pwm15_empty, spriteset_pwm15_lvstck_half, spriteset_pwm15_lvstck_half, spriteset_pwm15_lvstck_full];
}
spriteset(spriteset_wm15a_paper_half, "gfx/wm15a.png") {
    template_sprite_train(4, 400)
}
spriteset(spriteset_wm15a_paper_full, "gfx/wm15a.png") {
    template_sprite_train(4, 440)
}
spriteset(spriteset_pwm15_paper_half, "gfx/wm15a.png") {
    template_sprite_train(244, 400)
}
spriteset(spriteset_pwm15_paper_full, "gfx/wm15a.png") {
    template_sprite_train(244, 440)
}
spritegroup spritegroup_wm15a_paper {
    loaded:  [spriteset_wm15a_empty, spriteset_wm15a_paper_half, spriteset_wm15a_paper_half, spriteset_wm15a_paper_full];
    loading: [spriteset_wm15a_empty, spriteset_wm15a_paper_half, spriteset_wm15a_paper_half, spriteset_wm15a_paper_full];
}
spritegroup spritegroup_pwm15_paper {
    loaded:  [spriteset_pwm15_empty, spriteset_pwm15_paper_half, spriteset_pwm15_paper_half, spriteset_pwm15_paper_full];
    loading: [spriteset_pwm15_empty, spriteset_pwm15_paper_half, spriteset_pwm15_paper_half, spriteset_pwm15_paper_full];
}

/* cargos */
cargotable {
    PASS, TOUR, MAIL,
    GOOD, WOOD, LVST, STEL, PAPR
}

/* switches */
switch(FEAT_TRAINS, SELF, switch_wm15a_can_attach, vehicle_type_id) {
    item_pwm15:  return CB_RESULT_ATTACH_ALLOW;
    return string(STR_WM15A_ATTACH_DISALLOW);
}
switch (FEAT_TRAINS, SELF, switch_wm15a_start_stop, num_vehs_in_consist) {
    1..2: return 0xFF;
    return string(STR_WM15A_CANNOT_START);
}
switch (FEAT_TRAINS, SELF, switch_wm15a_capacity, cargo_type_in_veh) {
    PASS..TOUR: return 7;
    MAIL: return 30;
    return 15;
}
switch (FEAT_TRAINS, SELF, switch_pwm15_capacity, cargo_type_in_veh) {
    MAIL: return 30;
    return 15;
}

/* 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(1900, 1, 1);            // !!!
        model_life:                     VEHICLE_NEVER_EXPIRES;
        vehicle_life:                   30;
        reliability_decay:              20;
        refittable_cargo_classes:       bitmask(CC_PASSENGERS, CC_MAIL, CC_EXPRESS, CC_PIECE_GOODS);
        non_refittable_cargo_classes:   bitmask(CC_REFRIGERATED);
        refittable_cargo_types:         bitmask();
        loading_speed:                  5;
        cost_factor:                    18;     // 7%
        running_cost_factor:            25;     // 10%
        /* 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;
        shorten_vehicle:                SHORTEN_TO_8_8;
        extra_weight_per_wagon:         0;
        visual_effect_and_powered:      visual_effect_and_powered(VISUAL_EFFECT_DIESEL, -2, DISABLE_WAGON_POWER);
        extra_weight_per_wagon:         0 ton;
        bitmask_vehicle_info:           0;
    }

    graphics {
        PASS:               spriteset_wm15a_empty;
        TOUR:               spriteset_wm15a_empty;
        WOOD:               spritegroup_wm15a_wood;
        LVST:               spritegroup_wm15a_lvstck;
        STEL:               spritegroup_wm15a_steel;
        PAPR:               spritegroup_wm15a_paper;
        default:            spritegroup_wm15a_goods;
        purchase:           spriteset_wm15a_purchase;
        can_attach_wagon:   switch_wm15a_can_attach;
        start_stop:         switch_wm15a_start_stop;
        cargo_capacity:     switch_wm15a_capacity;
    }
}

item(FEAT_TRAINS, item_pwm15) {
    property {
        /* common properties */
        name:                           string(STR_PWM15_NAME);
        climates_available:             bitmask(CLIMATE_TEMPERATE, CLIMATE_ARCTIC);
        introduction_date:              date(1900, 1, 1);            // !!!
        model_life:                     VEHICLE_NEVER_EXPIRES;
        vehicle_life:                   30;
        reliability_decay:              20;
        refittable_cargo_classes:       bitmask(CC_MAIL, CC_EXPRESS, CC_PIECE_GOODS);
        non_refittable_cargo_classes:   bitmask(CC_REFRIGERATED);
        refittable_cargo_types:         bitmask();
        loading_speed:                  5;
        cost_factor:                    25;     // 10%
        running_cost_factor:            0;
        /* 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_NONE;
        dual_headed:                    0;
        cargo_capacity:                 15;
        weight:                         12 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;
        shorten_vehicle:                SHORTEN_TO_6_8;
        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 {
        WOOD:               spritegroup_pwm15_wood;
        LVST:               spritegroup_pwm15_lvstck;
        STEL:               spritegroup_pwm15_steel;
        PAPR:               spritegroup_pwm15_paper;
        default:            spritegroup_pwm15_goods;
        purchase:           spriteset_pwm15_purchase;
        cargo_capacity:     switch_pwm15_capacity;
    }
}


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