Commits

Anonymous committed c0c1ca4

Feature: 2962: Warn if substitute (and such) properties are not set first.

  • Participants
  • Parent commits c738e4c

Comments (0)

Files changed (2)

File nml/actions/action0.py

 
     return (props, action_list, mods, action_list_append)
 
+def validate_prop_info_list(prop_info_list, pos_list, feature):
+    """
+    Perform various checks on a list of properties in a property-block
+        - make sure that properties that should appear first (substitute type) appear first
+
+    @param prop_info_list: List of dictionaries with property information
+    @type prop_info_list: C{list} of C{dict}
+
+    @param pos_list: List containing position information (order matches prop_info_list)
+    @type pos_list: C{list} of L{Position}
+
+    @param feature: Feature of the associated item
+    @type feature: C{int}
+    """
+    global properties
+    first_warnings = [(info, pos_list[i]) for i, info in enumerate(prop_info_list) if 'first' in info and i != 0]
+    for info, pos in first_warnings:
+        generic.print_warning("Property '%s' should be set before all other properties and graphics." % generic.reverse_lookup(properties[feature], info), pos)
+
+
 def parse_property_block(prop_list, feature, id):
     """
     Parse a property block to an action0 (with possibly various other actions)
 
     prop_info_list = map(lambda prop: get_property_info(feature, prop.name), prop_list)
     value_list = map(lambda prop_info, prop: parse_property_value(prop_info, prop.value, prop.unit), prop_info_list, prop_list)
+    pos_list = map(lambda prop: prop.name.pos, prop_list)
+    validate_prop_info_list(prop_info_list, pos_list, feature)
 
     for prop_info, value in zip(prop_info_list, value_list):
         properties, extra_actions, mods, extra_append_actions = parse_property(prop_info, value, feature, id)

File nml/actions/action0properties.py

 #
 # 'warning' is a string (optional) containing a warning message that will be
 # shown if a property is used. Use for deprecating properties.
+#
+# 'first' (value doesn't matter) if the property should be set first (generally a substitute type)
 
 properties = 0x12 * [None]
 
     return [Action0Property(0x13, ConstantNumeric(town_zones | (climates & 0x800) | ((climates & 0x0F) << 12)), 2)]
 
 properties[0x07] = {
-    'substitute'              : {'size': 1, 'num': 0x08},
+    'substitute'              : {'size': 1, 'num': 0x08 , 'first': None},
     'building_flags'          : {'custom_function': lambda x: two_byte_property(x, 0x09, 0x19)},
     'years_available'         : {'custom_function': house_available_years},  # = prop 0A, 21 and 22
     'population'              : {'size': 1, 'num': 0x0B},
     return props
 
 properties[0x09] = {
-    'substitute'         : {'size': 1, 'num': 0x08},
+    'substitute'         : {'size': 1, 'num': 0x08, 'first': None},
     'override'           : {'size': 1, 'num': 0x09},
     'accepted_cargos'    : {'custom_function': industrytile_cargos}, # = prop 0A - 0C
     'land_shape_flags'   : {'size': 1, 'num': 0x0D},
     return [Action0Property(prop_num, ConstantNumeric(mul1 | (mul2 << 16)), 4)]
 
 properties[0x0A] = {
-    'substitute'             : {'size': 1, 'num': 0x08},
+    'substitute'             : {'size': 1, 'num': 0x08, 'first': None},
     'override'               : {'size': 1, 'num': 0x09},
     'layouts'                : {'custom_function': industry_layouts}, # = prop 0A
     'life_type'              : {'size': 1, 'num': 0x0B},
     return [AirportLayoutProp(layouts)]
 
 properties[0x0D] = {
-    'override'         : {'size': 1, 'num': 0x08},
+    'override'         : {'size': 1, 'num': 0x08, 'first':None},
     # 09 does not exist
     'layouts'          : {'custom_function': airport_layouts}, # = prop 0A
     # 0B does not exist
     return [Action0Property(0x0C, ConstantNumeric(sizey.value << 4 | sizex.value), 1)]
 
 properties[0x0F] = {
-    'class'                  : {'size': 4, 'num': 0x08, 'string_literal': 4},
+    'class'                  : {'size': 4, 'num': 0x08, 'first': None, 'string_literal': 4},
     # strings might be according to specs be either 0xD0 or 0xD4
     'classname'              : {'size': 2, 'num': 0x09, 'string': 0xD0},
     'name'                   : {'size': 2, 'num': 0x0A, 'string': 0xD0},
     return [RailtypeListProp(prop_num, value.values)]
 
 properties[0x10] = {
-    'label'                    : {'size': 4, 'num': 0x08, 'string_literal': 4},
+    'label'                    : {'size': 4, 'num': 0x08, 'string_literal': 4}, # is allocated during reservation stage, setting label first is thus not needed
     'toolbar_caption'          : {'size': 2, 'num': 0x09, 'string': 0xDC},
     'menu_text'                : {'size': 2, 'num': 0x0A, 'string': 0xDC},
     'build_window_caption'     : {'size': 2, 'num': 0x0B, 'string': 0xDC},
 #
 
 properties[0x11] = {
-    'substitute'         : {'size': 1, 'num': 0x08},
+    'substitute'         : {'size': 1, 'num': 0x08, 'first': None},
     'override'           : {'size': 1, 'num': 0x09},
     # 0A - 0D don't exist (yet?)
     # 0E (callback flags) is not set by user