1515
1616import itertools
1717
18- from nml import generic , nmlop , global_constants
18+ from nml import generic , grfstrings , nmlop , global_constants
1919from nml .expression import (
2020 AcceptCargo ,
2121 Array ,
@@ -170,7 +170,7 @@ def get_size(self):
170170#
171171# 'required' (value doesn't matter) if the property is required for the item to be valid.
172172
173- properties = 0x15 * [None ]
173+ properties = 0x16 * [None ]
174174
175175#
176176# Some helper functions that are used for multiple features
@@ -335,6 +335,24 @@ def VariableByteListProp(prop_num, data, len_size=1):
335335 return VariableListProp (prop_num , data , 1 , len_size )
336336
337337
338+ class StringProp (BaseAction0Property ):
339+ """
340+ Property value that is zero-terminated string.
341+ """
342+
343+ def __init__ (self , prop_num , string ):
344+ self .prop_num = prop_num
345+ self .string = string
346+
347+ def write (self , file ):
348+ file .print_bytex (self .prop_num )
349+ file .print_string (self .string .value , True , True )
350+ file .newline ()
351+
352+ def get_size (self ):
353+ return grfstrings .get_string_size (self .string .value ) + 1
354+
355+
338356def ctt_list (prop_num , * values ):
339357 # values may have multiple entries, if more than one item ID is set (e.g. multitile houses)
340358 # Each value is an expression.Array of cargo types
@@ -353,6 +371,38 @@ def VariableWordListProp(num_prop, data, len_size=1):
353371 return VariableListProp (num_prop , data , 2 , len_size )
354372
355373
374+ def badge_list (prop_num , * values ):
375+ # values may have multiple entries, if more than one item ID is set
376+ # Each value is an expression.Array of badge labels
377+
378+ table = global_constants .badge_numbers
379+
380+ for value in values :
381+ if not isinstance (value , Array ):
382+ raise generic .ScriptError ("Value of badgelist property must be an array" , value .pos )
383+
384+ for badge in value .values :
385+ if not isinstance (badge , StringLiteral ) or badge .value not in table :
386+ raise generic .ScriptError (
387+ "Parameter for badges must be a string literal that is also in your badge table" , value .pos
388+ )
389+
390+ return [
391+ VariableListProp (
392+ prop_num ,
393+ [[table [badge .value ] for badge in single_item_array .values ] for single_item_array in values ],
394+ 2 ,
395+ 2 ,
396+ )
397+ ]
398+
399+
400+ def string_property (prop_num , value ):
401+ if not isinstance (value , StringLiteral ):
402+ raise generic .ScriptError ("Value of label property must be a StringLiteral" , value .pos )
403+ return [StringProp (prop_num , value )]
404+
405+
356406def accepted_cargos (prop_num , * values ):
357407 # values may have multiple entries, if more than one item ID is set (e.g. multitile houses)
358408 # Each value is an expression.Array of cargo types and amount arrays
@@ -486,6 +536,7 @@ def single_or_list(prop_name, single_num, multiple_num, value):
486536 "curve_speed_mod" : {"size" : 2 , "num" : 0x2E , "unit_conversion" : 256 },
487537 "variant_group" : {"size" : 2 , "num" : 0x2F },
488538 "extra_flags" : {"size" : 4 , "num" : 0x30 },
539+ "badges" : {"custom_function" : lambda value : badge_list (0x33 , value )},
489540}
490541# fmt: on
491542
@@ -564,6 +615,7 @@ def prop15_test(value):
564615 ],
565616 "variant_group" : {"size" : 2 , "num" : 0x26 },
566617 "extra_flags" : {"size" : 4 , "num" : 0x27 },
618+ "badges" : {"custom_function" : lambda value : badge_list (0x2A , value )},
567619}
568620# fmt: on
569621
@@ -654,6 +706,7 @@ def prop23_test(value):
654706 "variant_group" : {"size" : 2 , "num" : 0x20 },
655707 "extra_flags" : {"size" : 4 , "num" : 0x21 },
656708 "acceleration" : {"size" : 1 , "num" : 0x24 },
709+ "badges" : {"custom_function" : lambda value : badge_list (0x26 , value )},
657710}
658711# fmt: on
659712
@@ -715,6 +768,7 @@ def aircraft_is_large(value):
715768 "range" : {"size" : 2 , "num" : 0x1F },
716769 "variant_group" : {"size" : 2 , "num" : 0x20 },
717770 "extra_flags" : {"size" : 4 , "num" : 0x21 },
771+ "badges" : {"custom_function" : lambda value : badge_list (0x24 , value )},
718772}
719773# fmt: on
720774
@@ -857,6 +911,7 @@ def station_tile_list(value, prop_num, description):
857911 "name" : {"size" : 2 , "num" : (256 , - 1 , 0x1C ), "string" : (256 , 0xC5 , 0xDC ), "required" : True },
858912 "classname" : {"size" : 2 , "num" : (256 , - 1 , 0x1D ), "string" : (256 , 0xC4 , 0xDC )},
859913 "tile_flags" : {"custom_function" : station_tile_flags }, # = prop 1E
914+ "badges" : {"custom_function" : lambda value : badge_list (0x1F , value )},
860915 "heights" : {"custom_function" : lambda x : station_tile_list (x , 0x20 , "Station height" )},
861916 "blocked_pillars" : {"custom_function" : lambda x : station_tile_list (x , 0x21 , "Station blocked pillar" )},
862917}
@@ -1067,6 +1122,7 @@ def mt_house_class(value, num_ids, size_bit):
10671122 "multitile_function" : mt_house_same ,
10681123 "custom_function" : lambda * values : accepted_cargos (0x23 , * values ),
10691124 },
1125+ "badges" : {"custom_function" : lambda value : badge_list (0x24 , value )},
10701126}
10711127# fmt: on
10721128
@@ -1088,6 +1144,7 @@ def mt_house_class(value, num_ids, size_bit):
10881144 "animation_triggers" : {"size" : 1 , "num" : 0x11 },
10891145 "special_flags" : {"size" : 1 , "num" : 0x12 },
10901146 "accepted_cargos" : {"custom_function" : lambda value : accepted_cargos (0x13 , value )},
1147+ "badges" : {"custom_function" : lambda value : badge_list (0x14 , value )},
10911148}
10921149# fmt: on
10931150
@@ -1360,6 +1417,7 @@ def check_accept(acp):
13601417 "nearby_station_name" : {"size" : 2 , "num" : 0x24 , "string" : 0xDC },
13611418 # prop 25+26+27+28 combined in one structure
13621419 "cargo_types" : {"custom_function" : industry_cargo_types },
1420+ "badges" : {"custom_function" : lambda value : badge_list (0x29 , value )},
13631421}
13641422# fmt: on
13651423
@@ -1463,6 +1521,7 @@ def airport_layouts(value):
14631521 "noise_level" : {"size" : 1 , "num" : 0x0F },
14641522 "name" : {"size" : 2 , "num" : 0x10 , "string" : 0xDC },
14651523 "maintenance_cost" : {"size" : 2 , "num" : 0x11 },
1524+ "badges" : {"custom_function" : lambda value : badge_list (0x12 , value )},
14661525}
14671526# fmt: on
14681527
@@ -1503,6 +1562,7 @@ def object_size(value):
15031562 "height" : {"size" : 1 , "num" : 0x16 },
15041563 "num_views" : {"size" : 1 , "num" : 0x17 },
15051564 "count_per_map256" : {"size" : 1 , "num" : 0x18 },
1565+ "badges" : {"custom_function" : lambda value : badge_list (0x19 , value )},
15061566}
15071567# fmt: on
15081568
@@ -1549,6 +1609,7 @@ def label_list(value, prop_num, description):
15491609 "sort_order" : {"size" : 1 , "num" : 0x1A },
15501610 "name" : {"size" : 2 , "num" : 0x1B , "string" : 0xDC },
15511611 "maintenance_cost" : {"size" : 2 , "num" : 0x1C },
1612+ "badges" : {"custom_function" : lambda value : badge_list (0x1E , value )},
15521613}
15531614
15541615#
@@ -1587,6 +1648,7 @@ def label_list(value, prop_num, description):
15871648 "animation_info" : {"size" : 2 , "num" : 0x0F , "value_function" : animation_info },
15881649 "animation_speed" : {"size" : 1 , "num" : 0x10 },
15891650 "animation_triggers" : {"size" : 1 , "num" : 0x11 },
1651+ "badges" : {"custom_function" : lambda value : badge_list (0x12 , value )},
15901652}
15911653
15921654#
@@ -1675,4 +1737,15 @@ def byte_sequence_list(value, prop_num, description, expected_count):
16751737 "heights" : {"custom_function" : lambda x : station_tile_list (x , 0x13 , "Station height" )},
16761738 "blocked_pillars" : {"custom_function" : lambda x : station_tile_list (x , 0x14 , "Station blocked pillar" )},
16771739 "cost_multipliers" : {"custom_function" : lambda x : byte_sequence_list (x , 0x15 , "Cost multipliers" , 2 )},
1740+ "badges" : {"custom_function" : lambda value : badge_list (0x16 , value )},
1741+ }
1742+
1743+ #
1744+ # Feature 0x15 (Badges)
1745+ #
1746+
1747+ properties [0x15 ] = {
1748+ 'label' : {'custom_function' : lambda x : string_property (0x08 , x ), "required" : True },
1749+ 'flags' : {'size' : 4 , 'num' : 0x09 },
1750+ 'name' : {'num' : - 1 , 'string' : None },
16781751}
0 commit comments