Using wagons only for certain locomotives
Moderator: Graphics Moderators
Using wagons only for certain locomotives
I am currently working on a set of freight locomotives and wagons.
I already have several passenger cars, where I have set which cars can have extra passenger carriages attached. For this I use the following code:
The passenger wagon has the name: "ITEM_PASS"
and an example freight wagon has the name "ITEM_ECCO_WAG"
I would like to know how I would have to change this code so I can separately say which wagons I can attach to which trains.
I tried to look into how the 2CC set handled this, but I didn't understand where their code was going.
- NekoMaster
- Tycoon
- Posts: 4001
- Joined: 16 Aug 2008 22:26
- Skype: neko-master
- Location: Oshawa, Ontario, CANADA
Re: Using wagons only for certain locomotives
Nekomasters Projects! (Downloads available on BaNaNaS!) \(>^w^<)/
# NARS ADD-ON SET 2CC | 2cc Rapid Transit For Me! (2ccRTFM) | 2cc Wagons In NML (2ccWIN)
# NML Category System (Organize your GRFS!) <- TT-Forums Exclusive Download!
Re: Using wagons only for certain locomotives
That's odd.NekoMaster wrote:I would kind of like to know how that works as I've had to disable the "can attach" wagon feature in my 2cc code for NARS ADD-ON Set 2cc
I really just do:
Code: Select all
graphics {
default: SPRITEGROUP_LINIMO; // Use this group
purchase: SPRITESET_PURCH_LINIMO; // Use this set for the menu
can_attach_wagon: switch_CAN_ATTACH;
}
- planetmaker
- OpenTTD Developer
- Posts: 9432
- Joined: 07 Nov 2007 22:44
- Location: Sol d
Re: Using wagons only for certain locomotives
Of course. But the important part happens in switch_CAN_ATTACH which you didn't show And there you can also decide which wagon can be attachedErato wrote:That's odd.NekoMaster wrote:I would kind of like to know how that works as I've had to disable the "can attach" wagon feature in my 2cc code for NARS ADD-ON Set 2cc
I really just do:But with this it's whether I can attach any wagon, or nothing at all.Code: Select all
graphics { default: SPRITEGROUP_LINIMO; // Use this group purchase: SPRITESET_PURCH_LINIMO; // Use this set for the menu can_attach_wagon: switch_CAN_ATTACH; }
Code: Select all
switch (FEAT_TRAINS, SELF, switch_CAN_ATTACH, vehicle_type_id) {
one_allowed_wagon_id: CB_RESULT_ATTACH_ALLOW;
another_allowed_wagon_id: CB_RESULT_ATTACH_ALLOW;
return CB_RESULT_ATTACH_DISALLOW
}
Code: Select all
graphics {
default: SPRITEGROUP_LINIMO; // Use this group
purchase: SPRITESET_PURCH_LINIMO; // Use this set for the menu
can_attach_wagon: CB_RESULT_ATTACH_ALLOW;
additional_text string(STR_ONLY_SUITABLE_FOR_ENGINES_OF_TYPE_XYZ);
}
OpenTTD: manual | online content | translations | Wanted contributions and patches
#openttdcoop: blog | wiki | public server | DevZone | NewGRF web translator
DevZone - home of the free NewGRFs: OpenSFX | OpenMSX | OpenGFX | Swedish Rails | OpenGFX+ Trains|RV|Industries|Airports|Landscape | NML
-
- Tycoon
- Posts: 2781
- Joined: 22 Feb 2011 18:34
Re: Using wagons only for certain locomotives
What did you not understand in that code? It basically uses the ID of the new vehicle to determine which can_attach-switch should be called, and then uses the ID of the vehicle in front to determine if the new vehicle can be attached.Erato wrote:I tried to look into how the 2CC set handled this, but I didn't understand where their code was going.
Re: Using wagons only for certain locomotives
Transportman wrote:What did you not understand in that code? It basically uses the ID of the new vehicle to determine which can_attach-switch should be called, and then uses the ID of the vehicle in front to determine if the new vehicle can be attached.Erato wrote:I tried to look into how the 2CC set handled this, but I didn't understand where their code was going.
Code: Select all
switch(FEAT_TRAINS, PARENT, switch_can_attach_unit_rail, [STORE_TEMP(position_in_consist_from_end, 0x10F), var[0x61, 0, 0x0000FFFF, 0xC6]])
Re: Using wagons only for certain locomotives
It's not documented anywhere, so it's understandable that you don't know it. But if one checks the source for NMLC one can see how it's supposed to work.
Code: Select all
var[num, <shift>, <mask>, <param>]
num - The variable to access. This is feature specific so accessing for example variable 0xB4 on a train would return the current speed.
shift - An optional parameter that performs a bitwise shift on the result. Example: 123 << 4 = 1,968 or in binary: 0111 1011 << 4 = 0111 1011 0000, in other words. It shifts bits left or right. I would assume positive numbers are left shift (<<) and negative numbers are right shift (>>)
mask - An optional parameter that masks the result. For example: 123 & 0xF = 11 or in binary: 0111 1011 & 0000 1111 = 1011. That is, if both bits are 1 in the result and the mask then they are kept.
param - An optional parameter that is sent to the "60+x" variable in question. In this case, since we are working on var 0x61 which is "query variable of n'th vehicle in chain" we are trying to get the value of variable C6 (Vehicle type ID) on the n'th vehicle in the chain.
So, we are trying to base our decision in the switch on the vehicle ID of the wagon that exists before this wagon is attached to the chain.
We only allow adding "unit_rail" wagons to DMU, EMU, unit_rail and SMU's before it.
Now you wonder, how does 0x61 (query var of n'th vehicle in chain) know what the n'th vehicle in the chain is? I mean, there's only a parameter for what variable (0xC6, vehicle id) to get from that n'th vehicle.
Well, when using var 0x61, you have to make use of a temporary variable that refers to the actual offset in the chain. That's what the previous STORE_TEMP(x, 0x10F) does. It stores a value in a SPECIAL register used for this very purpose.
In this case, the value is the "position_in_consist_from_end" variable.
But i fail to see the logic behind this one though... Wouldn't it simply suffice to store 0 (zero) in that temporary register? Or is it actually counting from the engine down because the vehicle being evaluated is a wagon? So many question marks.
Either way, surely there's a reason for that. And if you search for it, you end up on page 43 of the NML language thread: viewtopic.php?t=48891&start=840
And there you have it. Even the comments on the code you pasted tells you the same story. Albeit a bit briefer...
Code: Select all
//Check vehicle ID of the vehicle in front of the unit wagon being attached
//The offset for var 61 is determined by position_in_consist_from_end, which results in the last wagon before the vehicle being attached
Re: Using wagons only for certain locomotives
I see. So I tried using it.Cadde wrote:For you to understand that expression, let's start out with the "var[...]" statement.
It's not documented anywhere, so it's understandable that you don't know it. But if one checks the source for NMLC one can see how it's supposed to work.Or in other words, get variable from n'th vehicle in chain that is "Vehicle type ID" applying no bit shifting and applying logical AND 0x0000FFFF to the result. Or in other words, clamping the result between 0 and 65535.Code: Select all
var[num, <shift>, <mask>, <param>] num - The variable to access. This is feature specific so accessing for example variable 0xB4 on a train would return the current speed. shift - An optional parameter that performs a bitwise shift on the result. Example: 123 << 4 = 1,968 or in binary: 0111 1011 << 4 = 0111 1011 0000, in other words. It shifts bits left or right. I would assume positive numbers are left shift (<<) and negative numbers are right shift (>>) mask - An optional parameter that masks the result. For example: 123 & 0xF = 11 or in binary: 0111 1011 & 0000 1111 = 1011. That is, if both bits are 1 in the result and the mask then they are kept. param - An optional parameter that is sent to the "60+x" variable in question. In this case, since we are working on var 0x61 which is "query variable of n'th vehicle in chain" we are trying to get the value of variable C6 (Vehicle type ID) on the n'th vehicle in the chain.
So, we are trying to base our decision in the switch on the vehicle ID of the wagon that exists before this wagon is attached to the chain.
We only allow adding "unit_rail" wagons to DMU, EMU, unit_rail and SMU's before it.
Now you wonder, how does 0x61 (query var of n'th vehicle in chain) know what the n'th vehicle in the chain is? I mean, there's only a parameter for what variable (0xC6, vehicle id) to get from that n'th vehicle.
Well, when using var 0x61, you have to make use of a temporary variable that refers to the actual offset in the chain. That's what the previous STORE_TEMP(x, 0x10F) does. It stores a value in a SPECIAL register used for this very purpose.
In this case, the value is the "position_in_consist_from_end" variable.
But i fail to see the logic behind this one though... Wouldn't it simply suffice to store 0 (zero) in that temporary register? Or is it actually counting from the engine down because the vehicle being evaluated is a wagon? So many question marks.
Either way, surely there's a reason for that. And if you search for it, you end up on page 43 of the NML language thread: viewtopic.php?t=48891&start=840
And there you have it. Even the comments on the code you pasted tells you the same story. Albeit a bit briefer...If you don't understand some code, but it still works beautifully, then what's the harm in re-using it?Code: Select all
//Check vehicle ID of the vehicle in front of the unit wagon being attached //The offset for var 61 is determined by position_in_consist_from_end, which results in the last wagon before the vehicle being attached
Code: Select all
//ITS
switch(FEAT_TRAINS, PARENT, switch_can_attach_its, [STORE_TEMP(position_in_consist_from_end, 0x10F), var[0x61, 0, 0x0000FFFF, 0xC6]]) {
ITEM_RANGE_ITS: CB_RESULT_ATTACH_ALLOW_IF_RAILTYPES; //Allow
ITEM_RANGE_ITS_WAG: CB_RESULT_ATTACH_DISALLOW; //Allow self
CB_RESULT_ATTACH_DISALLOW;
}
What happened?
Re: Using wagons only for certain locomotives
If you aren't already, use notepad++ and import the NML syntax highlighting from here: http://dev.openttdcoop.org/documents/24
Then check to make sure you have all the required opening and closing brackets "(){}" etc prior in your file.
If you don't believe me, make a dummy GRF with just that switch statement in it besides the required GRF block.
EDIT: Oh and make sure you are on the latest NMLC version.
Code: Select all
C:\Users\Cadde>nmlc --version
0.4.4
Library versions encountered:
PLY: 3.4
PIL: 1.1.7
Re: Using wagons only for certain locomotives
"Unexpected token ','" means the parser expected something else than a comma.The switch being line 12. If I remove the comma. I get an error message for an unknown "var" on line 12.
Removing symbols that look ok on first sight is likely not the solution. (But I don't know that "var" thing, so my "ok" doesn't mean much.)
A common trick here is to split the line into several lines, where each line then contains a single comma.That is change the line to
Code: Select all
switch(FEAT_TRAINS,
PARENT,
switch_can_attach_its,
[STORE_TEMP(position_in_consist_from_end,
0x10F),
var[0x61,
0,
0x0000FFFF,
0xC6]]) {
Before that comma, something is not right, most likely some bracket or a wrong number of arguments, as Cadde already said.
Re: Using wagons only for certain locomotives
All my brackets are properly opened and closed.Cadde wrote:You most likely have a problem on a line further up. The "serializer" can travel quite a bit before it finds an unexpected character and only then will it complain.
If you aren't already, use notepad++ and import the NML syntax highlighting from here: http://dev.openttdcoop.org/documents/24
Then check to make sure you have all the required opening and closing brackets "(){}" etc prior in your file.
If you don't believe me, make a dummy GRF with just that switch statement in it besides the required GRF block.
EDIT: Oh and make sure you are on the latest NMLC version.
Code: Select all
C:\Users\Cadde>nmlc --version 0.4.4 Library versions encountered: PLY: 3.4 PIL: 1.1.7
As for the version:
Code: Select all
nmlc --version
unknown
Library versions encountered:
PLY: 3.10
PIL: 1.1.7
That, interestingly enough, results in an error on the latter of these lines:Alberth wrote:"Unexpected token ','" means the parser expected something else than a comma.The switch being line 12. If I remove the comma. I get an error message for an unknown "var" on line 12.
Removing symbols that look ok on first sight is likely not the solution. (But I don't know that "var" thing, so my "ok" doesn't mean much.)
A common trick here is to split the line into several lines, where each line then contains a single comma.That is change the line toThen run the program again, and the error message will point at a different line (most likely). Since there is only one comma at that line, you get precisely which comma is not recognized.Code: Select all
switch(FEAT_TRAINS, PARENT, switch_can_attach_its, [STORE_TEMP(position_in_consist_from_end, 0x10F), var[0x61, 0, 0x0000FFFF, 0xC6]]) {
Before that comma, something is not right, most likely some bracket or a wrong number of arguments, as Cadde already said.
Code: Select all
0xC6]]) {
ITEM_RANGE_ITS: CB_RESULT_ATTACH_ALLOW_IF_RAILTYPES; //Allow
In a way, this error is still on the same line.
Re: Using wagons only for certain locomotives
Double check that your substitutions are getting expanded properly. I copied your code into a trivial nml and it compiled without error but, of course, I had to replace ITEM_RANGE_ITS* with constants.Erato wrote: That, interestingly enough, results in an error on the latter of these lines:It's the same error, even though there is no comma on that line, before that line and on the next line.Code: Select all
0xC6]]) { ITEM_RANGE_ITS: CB_RESULT_ATTACH_ALLOW_IF_RAILTYPES; //Allow
In a way, this error is still on the same line.
In case it matters, I used the NotRoadTypes branch of nmlc.
Code: Select all
$ nmlc --version
v6347:96b8395ca393 from 2017-05-18
Library versions encountered:
PIL: 1.1.7
PLY: 3.10
Re: Using wagons only for certain locomotives
It makes sense that the code should work. For the range, I did this, which should work:rowdog wrote:Double check that your substitutions are getting expanded properly. I copied your code into a trivial nml and it compiled without error but, of course, I had to replace ITEM_RANGE_ITS* with constants.Erato wrote: That, interestingly enough, results in an error on the latter of these lines:It's the same error, even though there is no comma on that line, before that line and on the next line.Code: Select all
0xC6]]) { ITEM_RANGE_ITS: CB_RESULT_ATTACH_ALLOW_IF_RAILTYPES; //Allow
In a way, this error is still on the same line.
In case it matters, I used the NotRoadTypes branch of nmlc.Code: Select all
$ nmlc --version v6347:96b8395ca393 from 2017-05-18 Library versions encountered: PIL: 1.1.7 PLY: 3.10
Code: Select all
#define ITEM_RANGE_ITS \
ITEM_ITS_PERSONEN, \
ITEM_ITS_MATERIAL, \
ITEM_ITS_MASSENGUT, \
Re: Using wagons only for certain locomotives
Re: Using wagons only for certain locomotives
I'm pretty certain that wouldn't be the case.Cadde wrote:Well, your NMLC version reports as "unknown" and that to me sounds like you have some experimental NMLC to begin with.
I tried it again in cmd and got this instead:
Code: Select all
v6201:45b1e0507a8d from 2016-12-23
Library versions encountered:
PLY: 3.4
PIL: 1.1.7
Re: Using wagons only for certain locomotives
But now that i am a bit more awake, the #defines you have there... I don't normally use #defines, but that surely looks like it's gonna resolve to this:
Code: Select all
//ITS
switch(FEAT_TRAINS, PARENT, switch_can_attach_its, [STORE_TEMP(position_in_consist_from_end, 0x10F), var[0x61, 0, 0x0000FFFF, 0xC6]]) {
ITEM_ITS_PERSONEN,
ITEM_ITS_MATERIAL,
ITEM_ITS_MASSENGUT,: CB_RESULT_ATTACH_ALLOW_IF_RAILTYPES; //Allow
ITEM_RANGE_ITS_WAG: CB_RESULT_ATTACH_DISALLOW; //Allow self
CB_RESULT_ATTACH_DISALLOW;
}
But if it were me, assuming your id's are in sequential order... Let's for instance say that this were true:
Code: Select all
#define ITEM_ITS_PERSONEN 0x01
#define ITEM_ITS_MATERIAL 0x02
#define ITEM_ITS_MASSENGUT 0x03
Code: Select all
#define ITEM_RANGE_ITS 0x01..0x03
#define ITEM_ITS_PERSONEN 0x01
#define ITEM_ITS_MATERIAL 0x02
#define ITEM_ITS_MASSENGUT 0x03
#define ITEM_RANGE_ITS_WAG ...
...
//ITS
switch(FEAT_TRAINS, PARENT, switch_can_attach_its, [STORE_TEMP(position_in_consist_from_end, 0x10F), var[0x61, 0, 0x0000FFFF, 0xC6]]) {
ITEM_RANGE_ITS: CB_RESULT_ATTACH_ALLOW_IF_RAILTYPES; //Allow
ITEM_RANGE_ITS_WAG: CB_RESULT_ATTACH_DISALLOW; //Allow self
CB_RESULT_ATTACH_DISALLOW;
}
Re: Using wagons only for certain locomotives
Indeed, this is wrong. There is no NML version that allows trailing commas.Cadde wrote:Right, still looks experimental to me.
But now that i am a bit more awake, the #defines you have there... I don't normally use #defines, but that surely looks like it's gonna resolve to this:So, as you can see, not correct NML switch syntax unless the revision you are using allows that?/code]Code: Select all
//ITS switch(FEAT_TRAINS, PARENT, switch_can_attach_its, [STORE_TEMP(position_in_consist_from_end, 0x10F), var[0x61, 0, 0x0000FFFF, 0xC6]]) { ITEM_ITS_PERSONEN, ITEM_ITS_MATERIAL, ITEM_ITS_MASSENGUT,: CB_RESULT_ATTACH_ALLOW_IF_RAILTYPES; //Allow ITEM_RANGE_ITS_WAG: CB_RESULT_ATTACH_DISALLOW; //Allow self CB_RESULT_ATTACH_DISALLOW; }
@Erato:To be fully correct, you also have to remove the \ at the end of the last line. (Now it also merges the line below it, that is, your #define is one line longer than you think it is.)
-
- Tycoon
- Posts: 2781
- Joined: 22 Feb 2011 18:34
Re: Using wagons only for certain locomotives
That is the reason I switched vehicle ID's in the 2cc TrainsInNML, to create ranges of vehicle IDs that are of the same type, so I could use those ranges in this type of switches.Cadde wrote:Right, still looks experimental to me.
But now that i am a bit more awake, the #defines you have there... I don't normally use #defines, but that surely looks like it's gonna resolve to this:So, as you can see, not correct NML switch syntax unless the revision you are using allows that? If it does then show me that documentation please.Code: Select all
//ITS switch(FEAT_TRAINS, PARENT, switch_can_attach_its, [STORE_TEMP(position_in_consist_from_end, 0x10F), var[0x61, 0, 0x0000FFFF, 0xC6]]) { ITEM_ITS_PERSONEN, ITEM_ITS_MATERIAL, ITEM_ITS_MASSENGUT,: CB_RESULT_ATTACH_ALLOW_IF_RAILTYPES; //Allow ITEM_RANGE_ITS_WAG: CB_RESULT_ATTACH_DISALLOW; //Allow self CB_RESULT_ATTACH_DISALLOW; }
But if it were me, assuming your id's are in sequential order... Let's for instance say that this were true:Then you could do this:Code: Select all
#define ITEM_ITS_PERSONEN 0x01 #define ITEM_ITS_MATERIAL 0x02 #define ITEM_ITS_MASSENGUT 0x03
Code: Select all
#define ITEM_RANGE_ITS 0x01..0x03 #define ITEM_ITS_PERSONEN 0x01 #define ITEM_ITS_MATERIAL 0x02 #define ITEM_ITS_MASSENGUT 0x03 #define ITEM_RANGE_ITS_WAG ... ... //ITS switch(FEAT_TRAINS, PARENT, switch_can_attach_its, [STORE_TEMP(position_in_consist_from_end, 0x10F), var[0x61, 0, 0x0000FFFF, 0xC6]]) { ITEM_RANGE_ITS: CB_RESULT_ATTACH_ALLOW_IF_RAILTYPES; //Allow ITEM_RANGE_ITS_WAG: CB_RESULT_ATTACH_DISALLOW; //Allow self CB_RESULT_ATTACH_DISALLOW; }
Re: Using wagons only for certain locomotives
Ah. I understand.Cadde wrote:Right, still looks experimental to me.
But now that i am a bit more awake, the #defines you have there... I don't normally use #defines, but that surely looks like it's gonna resolve to this:So, as you can see, not correct NML switch syntax unless the revision you are using allows that? If it does then show me that documentation please.Code: Select all
//ITS switch(FEAT_TRAINS, PARENT, switch_can_attach_its, [STORE_TEMP(position_in_consist_from_end, 0x10F), var[0x61, 0, 0x0000FFFF, 0xC6]]) { ITEM_ITS_PERSONEN, ITEM_ITS_MATERIAL, ITEM_ITS_MASSENGUT,: CB_RESULT_ATTACH_ALLOW_IF_RAILTYPES; //Allow ITEM_RANGE_ITS_WAG: CB_RESULT_ATTACH_DISALLOW; //Allow self CB_RESULT_ATTACH_DISALLOW; }
But if it were me, assuming your id's are in sequential order... Let's for instance say that this were true:Then you could do this:Code: Select all
#define ITEM_ITS_PERSONEN 0x01 #define ITEM_ITS_MATERIAL 0x02 #define ITEM_ITS_MASSENGUT 0x03
Code: Select all
#define ITEM_RANGE_ITS 0x01..0x03 #define ITEM_ITS_PERSONEN 0x01 #define ITEM_ITS_MATERIAL 0x02 #define ITEM_ITS_MASSENGUT 0x03 #define ITEM_RANGE_ITS_WAG ... ... //ITS switch(FEAT_TRAINS, PARENT, switch_can_attach_its, [STORE_TEMP(position_in_consist_from_end, 0x10F), var[0x61, 0, 0x0000FFFF, 0xC6]]) { ITEM_RANGE_ITS: CB_RESULT_ATTACH_ALLOW_IF_RAILTYPES; //Allow ITEM_RANGE_ITS_WAG: CB_RESULT_ATTACH_DISALLOW; //Allow self CB_RESULT_ATTACH_DISALLOW; }
Also. This worked thanks.
Who is online
Users browsing this forum: No registered users and 25 guests