Page 1 of 1

Trains Of Europe - Help with coding

Posted: 07 Apr 2011 10:12
by Emperor Jake
Hi
I'm currently working on a massive new set, which builds on my old Generic European Set. I have coded four new railtypes, each representing a different voltage system used in Europe:
1500V DC (DC15)
3000V DC (DC30)
15KV AC (ELAC)
25KV AC (ELRL) - regular electric rail; default electrics run on this

This is working fine so far - until I tried to code a multi-system locomotive.

Code: Select all

		track_type:         bitmask(ELRL, ELAC, DC15, DC30);
doesn't seem to work; the engine stubbornly keeps going on unelectrified tracks.

I then tried several other things, the one that seemed to work best out of them was creating another railtype that was compatible with all four electrified tracktypes. However, it clutters up the railtypes menu, and it doesn't appear to be possible for a locomotive to run on only ELAC and ELRL, but not the DC ones, for example.


Here is the code for the railtypes:

Code: Select all

item(FEAT_RAILTYPES) {
    property {
        label:                      "ELAC";
        name:                       string(STR_AC15);
        menu_text:                  string(STR_AC15);
        build_window_caption:       string(STR_AC15_BUILD);
        autoreplace_text:           string(STR_AC15_AUTOREPLACE);
        new_engine_text:            string(STR_AC15_NEW_ENGINE);
//	introduction_date:  date(1950,1,1);
        compatible_railtype_list:   ["RAIL","ELRL","ELAC","DC15","DC30"];          
	powered_railtype_list:      ["ELAC"];                 
        railtype_flags:             bitmask(RAILTYPE_FLAG_CATENARY);
        curve_speed_multiplier:     1;
//      station_graphics:           RAILTYPE_STATION_RAIL;          
        construction_cost:          2;                               
//        speed_limit:                230 km/h;
        acceleration_model:         ACC_MODEL_RAIL;  
	sort_order: 18;                 
    }
    graphics {             
	CATENARY_PYLONS: elac_pylons_group;             
    }
}

item(FEAT_RAILTYPES) {
    property {
        label:                      "DC15";
        name:                       string(STR_DC15);
        menu_text:                  string(STR_DC15);
        build_window_caption:       string(STR_DC15_BUILD);
        autoreplace_text:           string(STR_DC15_AUTOREPLACE);
        new_engine_text:            string(STR_DC15_NEW_ENGINE);
//	introduction_date:  date(1950,1,1);
        compatible_railtype_list:   ["RAIL","ELRL","ELAC","DC15","DC30"];          
	powered_railtype_list:      ["DC15"];                 
        railtype_flags:             bitmask(RAILTYPE_FLAG_CATENARY);
        curve_speed_multiplier:     1;
//      station_graphics:           RAILTYPE_STATION_RAIL;          
        construction_cost:          2;                               
//       speed_limit:                160 km/h;
        acceleration_model:         ACC_MODEL_RAIL;
	sort_order: 16;                    
    }
    graphics {             
	CATENARY_PYLONS: dc15_pylons_group;   
	CATENARY_WIRE:   dc_wire_group;          
    }
}

item(FEAT_RAILTYPES) {
    property {
        label:                      "DC30";
        name:                       string(STR_DC30);
        menu_text:                  string(STR_DC30);
        build_window_caption:       string(STR_DC30_BUILD);
        autoreplace_text:           string(STR_DC30_AUTOREPLACE);
        new_engine_text:            string(STR_DC30_NEW_ENGINE);
//	introduction_date:  date(1950,1,1);
        compatible_railtype_list:   ["RAIL","ELRL","ELAC","DC15","DC30"];          
	powered_railtype_list:      ["DC30"];                 
        railtype_flags:             bitmask(RAILTYPE_FLAG_CATENARY);
        curve_speed_multiplier:     1;
//      station_graphics:           RAILTYPE_STATION_RAIL;          
        construction_cost:          2;                               
//        speed_limit:                160 km/h;
        acceleration_model:         ACC_MODEL_RAIL;
	sort_order: 17;                    
    }
    graphics {             
	CATENARY_PYLONS: dc30_pylons_group;   
	CATENARY_WIRE:   dc_wire_group;          
    }
}

item(FEAT_RAILTYPES) {
    property {
        label:                      "RAIL";
        compatible_railtype_list:   ["TRIF","RAIL","ELRL","ELAC","DC15","DC30"];          
	powered_railtype_list:      ["TRIF","ELRL","ELAC","DC15","DC30"];                 
    }
}

item(FEAT_RAILTYPES) {
    property {
        label:                      "ELRL";
        name:                       string(STR_AC25);
        menu_text:                  string(STR_AC25);
        build_window_caption:       string(STR_AC25_BUILD);
        autoreplace_text:           string(STR_AC25_AUTOREPLACE);
        new_engine_text:            string(STR_AC25_NEW_ENGINE);
        compatible_railtype_list:   ["RAIL","ELRL","ELAC","DC15","DC30"];          
	powered_railtype_list:      ["ELRL"];                 
    }
}

/*
item(FEAT_RAILTYPES) {
    property {
        label:                      "MULT";
        name:                       string(N_A);
        menu_text:                  string(N_A);
        build_window_caption:       string(N_A);
        autoreplace_text:           string(N_A);
        new_engine_text:            string(N_A);
        compatible_railtype_list:   ["ELRL","ELAC","DC15","DC30"];          
	powered_railtype_list:      ["ELRL","ELAC","DC15","DC30"];
	introduction_date:  date(9999,1,1); 
	speed_limit: 1;
        construction_cost:          65525;                   
    }
}
*/

And the multi system locomotive:

Code: Select all

switch (FEAT_TRAINS, SELF, ms_train_power_switch, current_railtype) {
	ELRL: return 2000;
	ELAC: return 2000;
	DC30: return 1500;
	DC15: return 1500;
//	RAIL: return 0;  //train just coasts to a halt on unpowered track
    CB_FAILED;
}

switch (FEAT_TRAINS, SELF, ms_train_speed_switch, current_railtype) {
	ELRL: return 230;
	ELAC: return 200;
	DC30: return 160;
	DC15: return 160;
//	RAIL: return 1;  //makes game crash when engine enters RAIL
//	RAIL: return 0;  //game says max speed is 65,535 km/h
    CB_FAILED;
}

switch (FEAT_TRAINS, SELF, ms_railtype_switch, extra_callback_info1) {
	PROP_TRAINS_POWER: ms_train_power_switch;
	PROP_TRAINS_SPEED: ms_train_speed_switch;
    CB_FAILED;
}

switch (FEAT_TRAINS, SELF, ms_train_switch, current_callback) {
	VEH_CB_VEHICLE_PROPERTIES: ms_railtype_switch;
    test_train_group;
}

//Testing Multi-System Train
item(FEAT_TRAINS, ms_train) {
	property {
		sprite_id:          SPRITE_ID_NEW_TRAIN;
		misc_flags:         bitmask(TRAIN_FLAG_2CC);
		name:               string(STR_NAME_TEST_TRAIN_4);
		climates_available: ALL_CLIMATES;
		track_type:         bitmask(ELRL, ELAC, DC15, DC30);
		introduction_date:  date(1950,1,1);
		speed:              230 km/h;
		tractive_effort_coefficient:    0.5;
		power:              2000 hp;
		weight: 100;
		dual_headed:        0;
		engine_class:       ENGINE_CLASS_ELECTRIC;
		}
		graphics {                          
		ms_train_switch;
		}
		
}
Does anyone have any advice on this? I would appreciate some help. If it's not possible at all, then consider it a feature request :wink:

Thanks,
Jake

Re: Trains Of Europe - Help with coding

Posted: 07 Apr 2011 10:58
by PikkaBird
And this is what happens when we write NML without understanding the grf spec. :)

Re: Trains Of Europe - Help with coding

Posted: 07 Apr 2011 11:05
by Yexo
Or without understanding the nml documentation.
http://hg.openttdcoop.org/nml/raw-file/tip/docs/vehicles.html#trains-property wrote: track_type
item from railtypetable
Default railtype table: RAIL, MONO, MGLV. If you install a railtypetable yourself you'll always get the railtype you specified. If you want a vehicle to run on electric rail and you don't have a railtypetable, set track_type to RAIL and make sure that you set engine_class to ENGINE_CLASS_ELECTRIC.
You can't suddenly use a bitmask of multiple values when the documentation says you need "(one) item from railtypetable". If you were able to use a bitmask there the documentation would have said so.

One engine can only ever support one track type. If you want an engine to run on multiple track types you have to make those track types compatible. Just like the default "Rail" and "Electric rail" are compatible. It looks like you've already set the compatible_railtype_list property correctly. However the way you coded it now (with powered_railtype_list only containing the railtype itself) your trains can run on the other track types but won't be able to function as engine there.

Re: Trains Of Europe - Help with coding

Posted: 07 Apr 2011 11:12
by Emperor Jake
Yexo wrote: One engine can only ever support one track type. If you want an engine to run on multiple track types you have to make those track types compatible. Just like the default "Rail" and "Electric rail" are compatible. It looks like you've already set the compatible_railtype_list property correctly. However the way you coded it now (with powered_railtype_list only containing the railtype itself) your trains can run on the other track types but won't be able to function as engine there.
So is what I'm trying to do even possible?

If I make the different railtypes compatible, then they would become pointless because then a 1500V DC only locomotive would simply be able to go on all electric tracks. :?
Yexo wrote: You can't suddenly use a bitmask of multiple values when the documentation says you need "(one) item from railtypetable". If you were able to use a bitmask there the documentation would have said so.
Then maybe nmlc should complain when trying to compile it?

Re: Trains Of Europe - Help with coding

Posted: 07 Apr 2011 11:27
by planetmaker
Emperor Jake wrote:

Code: Select all

		track_type:         bitmask(ELRL, ELAC, DC15, DC30);
An engine can only have one track type associated. It's not a bitmask, I'm afraid.

The compatibility is defined by the track properties of the railtypes.
VEH_CB_VEHICLE_PROPERTIES wrote: Most properties will only change when the vehicle is bought, serviced (enters a depot), visits a station or on loading of a saved game. Other ones such as TE are called every time a TE calculation is run.
On of those properties which can change is power, when the railtype changes.

Thus you could give it a try to adjust power via this callback accordingly - and IIRC you'd have to declare the track types as (unpowered? powered?) compatible.

I might be wrong though ;-)

Re: Trains Of Europe - Help with coding

Posted: 07 Apr 2011 11:47
by Emperor Jake
planetmaker wrote:On of those properties which can change is power, when the railtype changes.

Thus you could give it a try to adjust power via this callback accordingly - and IIRC you'd have to declare the track types as (unpowered? powered?) compatible.

I might be wrong though ;-)
I've already tried this - if I make the tracktypes like this:

Code: Select all

item(FEAT_RAILTYPES) {
    property {
        label:                      "DC30";
        name:                       string(STR_DC30);
        menu_text:                  string(STR_DC30);
        build_window_caption:       string(STR_DC30_BUILD);
        autoreplace_text:           string(STR_DC30_AUTOREPLACE);
        new_engine_text:            string(STR_DC30_NEW_ENGINE);
//	introduction_date:  date(1950,1,1);
        compatible_railtype_list:   ["RAIL","ELRL","ELAC","DC15","DC30"];          
	powered_railtype_list:      ["ELRL","ELAC","DC15","DC30"];                 
        railtype_flags:             bitmask(RAILTYPE_FLAG_CATENARY);
        curve_speed_multiplier:     1;
//      station_graphics:           RAILTYPE_STATION_RAIL;          
        construction_cost:          2;                               
//        speed_limit:                160 km/h;
        acceleration_model:         ACC_MODEL_RAIL;
	sort_order: 17;                    
    }
    graphics {             
	CATENARY_PYLONS: dc30_pylons_group;   
	CATENARY_WIRE:   dc_wire_group;          
    }
}
then EVERY electric locomotive runs on that track regardless of railtype. I want some trains to be only powered under a single railtype.
If I use the callback to set the power to zero, then the train simply coasts to a halt and becomes stuck because it's on a compatible, but unpowered, railtype.

Re: Trains Of Europe - Help with coding

Posted: 07 Apr 2011 12:05
by Yexo
Emperor Jake wrote:
Yexo wrote: You can't suddenly use a bitmask of multiple values when the documentation says you need "(one) item from railtypetable". If you were able to use a bitmask there the documentation would have said so.
Then maybe nmlc should complain when trying to compile it?
Yes, that would be good if that was possible. However it's not so easy, since nmlc first simplifies whatever you write in a single number, and after all a bitmask is just another number.

What you want (only some locomotives are able to run on multiple track types) is indeed impossible. That's not a limitation of NML but a limitation of the current nfo spec.

Re: Trains Of Europe - Help with coding

Posted: 07 Apr 2011 13:15
by Emperor Jake
Yexo wrote:
What you want (only some locomotives are able to run on multiple track types) is indeed impossible. That's not a limitation of NML but a limitation of the current nfo spec.
Dang. That's what I was dreading :(

If it were implemented, what would be the best way? I would think that making "track_type" a bitmask would make the most sense. This would be potentially useful for dual gauge tracks and other fancy new railtype things, such as weight limits (eg "Big Powerful Locomotive" is not compatible with "Cheap Railway Track" because it is too heavy)
I would like to request this feature (or something that will allow doing the same thing if there is a better idea) I have no idea how hard it would be to code though.

Thanks,
Jake

Re: Trains Of Europe - Help with coding

Posted: 07 Apr 2011 20:46
by DJ Nekkid
VarAction2 variable 4A ? (but yes, a bitmask would be nice, but it would need a new property in the train action0)

Re: Trains Of Europe - Help with coding

Posted: 08 Apr 2011 06:56
by Emperor Jake
Adding a callback would work - one that simply decides whether a tracktype is compatible or not.

For example:

Code: Select all


switch (FEAT_TRAINS, SELF, ms_train_power_switch, current_railtype) {
	ELRL: return 2000;
	ELAC: return 2000;
	DC30: return 1500;
	DC15: return 1500;
    CB_FAILED;
}

switch (FEAT_TRAINS, SELF, ms_train_speed_switch, current_railtype) {
	ELRL: return 230;
	ELAC: return 200;
	DC30: return 160;
	DC15: return 160;
    CB_FAILED;
}

switch (FEAT_TRAINS, SELF, ms_properties_switch, extra_callback_info1) {
	PROP_TRAINS_POWER: ms_train_power_switch;
	PROP_TRAINS_SPEED: ms_train_speed_switch;
    CB_FAILED;
}


//decides which railtypes are compatible - all of these are defined as being compatible to RAIL normally
switch (FEAT_TRAINS, SELF, ms_railtype_switch, current_railtype) {  
	ELRL: return 1;
	ELAC: return 1;
	DC30: return 1;
	DC15: return 1;
        TRIF: return 0;
        RAIL: return 0;
    CB_FAILED;
}

switch (FEAT_TRAINS, SELF, ms_train_switch, current_callback) {
	VEH_CB_VEHICLE_PROPERTIES: ms_properties_switch;
	VEH_CB_COMPATIBLE_RAILTYPES: ms_railtype_switch;  //new callback
    test_train_group;
}

//Testing Multi-System Train
item(FEAT_TRAINS, ms_train) {
	property {
		sprite_id:          SPRITE_ID_NEW_TRAIN;
		misc_flags:         bitmask(TRAIN_FLAG_2CC);
		name:               string(STR_NAME_TEST_TRAIN);
		climates_available: ALL_CLIMATES;
		track_type:         RAIL;
		introduction_date:  date(1950,1,1);
		speed:              200 km/h;
		tractive_effort_coefficient:    0.5;
		power:              2000 hp;
		weight:              100;
		dual_headed:        0;
		engine_class:       ENGINE_CLASS_ELECTRIC;
		}
		graphics {                          
		ms_train_switch;
		}
		
}

Re: Trains Of Europe - Help with coding

Posted: 08 Apr 2011 10:00
by Yexo
That would make all caching the pathfinder does impossible.

Re: Trains Of Europe - Help with coding

Posted: 08 Apr 2011 10:16
by Emperor Jake
Would it be possible to implement it in any way then? :?

How about a different approach:
Is it possible to keep a railtype from ever appearing to the player, even though it has a vehicle? Because the multi voltage locomotive works best if there is an extra railtype that is compatible with the others.

Re: Trains Of Europe - Help with coding

Posted: 08 Apr 2011 11:11
by Yexo
I don't see the point of such a railtype. What use would it have?

Re: Trains Of Europe - Help with coding

Posted: 08 Apr 2011 11:26
by DJ Nekkid
I do see his point, but imho would a bitmask in the train action0 be better, as an engine can be 'dual voltage' or 'dual type' somehow. (example: 1500VDC, 25kVAC and 750v 3ra rail).
A 1500VDC train would not be powered on 25kVAC and 750v 3rd rails, and thus would the railtype not have thoose as a 'powered' type.
I have not tested the earlier mentioned var2, but that should probably do what im thinking of (4A), in NFO i suspect it would be something like:

Code: Select all

Translation table with:
RAIL // 0
ELRL // 1
15DC // 2
25AC // 3

-1 * 0  02 00 xx 85 4A 00 FF
     01 80 \wx0101 // Allow on 'standard' elrails
     01 80 \wx0102 // Allow on 1500VDC
     01 80 \wx 0103 // Allow on 25k VAC
     00 80 // Dissallow on everything else
Or is the usage for Var2 4A something completely different? As long as 15DC and 25AC is compatible railtypes it should work i think?

Re: Trains Of Europe - Help with coding

Posted: 08 Apr 2011 11:31
by Emperor Jake
Yexo wrote:I don't see the point of such a railtype. What use would it have?
It allows the multivoltage locomotive to travel on all four electric tracktypes, exactly the way I intended, but it also clutters up the railtype list. The other main problem is that a locomotive which isn't compatible with a electrification type will still go on that track, but will become stuck because it has no power.

Here is a test GRF to give you a better idea :)

Re: Trains Of Europe - Help with coding

Posted: 08 Apr 2011 12:53
by Eddi
how about making an articulated engine.

e.g., for a dual-AC engine, first half is powered with 25kV AC, and second half is powered with 15kV AC. with some trickery with shortened and invisible vehicles, you can make it look like a normal single engine.

Re: Trains Of Europe - Help with coding

Posted: 08 Apr 2011 13:26
by Emperor Jake
I've tried that - it didn't work. The engine will only go on whatever tracktype the first part is compatible with, and it ignores the power of the articulated sections as well.

Re: Trains Of Europe - Help with coding

Posted: 08 Apr 2011 14:07
by DJ Nekkid
What eddi talks about should work, did you set the tracktypes to be compatible with eachother?
Im not at home atm, but ill make a test in nfo when i get there...

Re: Trains Of Europe - Help with coding

Posted: 08 Apr 2011 15:03
by as
It won't work, most action0 properties are not available to articulated parts and are ignored.
see http://wiki.ttdpatch.net/tiki-index.php ... ion0Trains (possibly this info is also somewhere in NML docs?)

Re: Trains Of Europe - Help with coding

Posted: 08 Apr 2011 17:43
by Yexo
as wrote:see http://wiki.ttdpatch.net/tiki-index.php ... ion0Trains (possibly this info is also somewhere in NML docs?)
Not yet.