From 9a287ae83b3fbd9f20662a93cce362fa70ecb092 Mon Sep 17 00:00:00 2001 From: Andy Date: Sat, 10 Dec 2022 12:55:11 +0000 Subject: [PATCH] Codechange: stub in a structure to support Variants --- src/docs_templates/trains.pt | 2 +- src/gestalt_graphics/pipelines.py | 6 ++--- src/render_docs.py | 6 ++++- src/roster.py | 10 ++++---- src/templates/articulated_parts.pynml | 2 +- src/templates/properties_vehicle.pynml | 2 +- src/train.py | 33 ++++++++++++++++++-------- 7 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/docs_templates/trains.pt b/src/docs_templates/trains.pt index 3c18eb6b2..4ed5af436 100644 --- a/src/docs_templates/trains.pt +++ b/src/docs_templates/trains.pt @@ -135,7 +135,7 @@ ${doc_helper.unpack_name_string(consist)} ${consist.intro_year} - ${sum([unit.default_cargo_capacity for unit in consist.units])} t + ${doc_helper.capacity_formatted_for_docs(consist)} ${consist.speed} mph ${consist.track_type} diff --git a/src/gestalt_graphics/pipelines.py b/src/gestalt_graphics/pipelines.py index 33eeec974..a88b249d0 100644 --- a/src/gestalt_graphics/pipelines.py +++ b/src/gestalt_graphics/pipelines.py @@ -64,7 +64,7 @@ def process_buy_menu_sprite(self, spritesheet): # hard-coded positions for buy menu sprite (if used - it's optional) x_offset = 0 - for unit_counter, unit in enumerate(self.consist.units): + for unit_counter, unit in enumerate(self.consist.default_variant.units): # !! currently no cap on purchase menu sprite width # !! consist has a buy_menu_width prop which caps to 64 which could be used (+1px overlap) unit_length_in_pixels = 4 * unit.vehicle_length @@ -512,12 +512,12 @@ def process_buy_menu_sprite_from_randomisation_candidates(self, spritesheet): # take the first and last candidates; # note that we have to call set here, due to the way random candidates are padded out to make power of 2 list lengths for random bits # we have to use frozen_roster_items as the roster object won't pickle for multiprocessing use (never figured out why) - if len(self.consist.units) > 1: + if len(self.consist.default_variant.units) > 1: raise BaseException( "GenerateBuyMenuSpriteFromRandomisationCandidatesPipeline won't work with articulated consists - called by " + self.consist.id ) - unit_length_in_pixels = 4 * self.consist.units[0].vehicle_length + unit_length_in_pixels = 4 * self.consist.default_variant.units[0].vehicle_length unit_slice_length_in_pixels = ( int(unit_length_in_pixels / 2) + graphics_constants.randomised_wagon_extra_unit_width diff --git a/src/render_docs.py b/src/render_docs.py index 72960c7fd..71c16a5a8 100644 --- a/src/render_docs.py +++ b/src/render_docs.py @@ -379,6 +379,10 @@ def get_replaced_by_name(self, replacement_consist_id, consists): if consist.id == replacement_consist_id: return self.unpack_name_string(consist) + def capacity_formatted_for_docs(self, consist): + result = sum([unit.default_cargo_capacity for unit in consist.default_variant.units]) + return str(result) + " t" + def power_formatted_for_docs(self, consist): if consist.wagons_add_power: return [str(consist.cab_power) + " hp"] @@ -422,7 +426,7 @@ def get_props_to_print_in_code_reference(self, subclass): result = self.fetch_prop(result, "Buy Cost", vehicle.buy_cost) result = self.fetch_prop(result, "Running Cost", vehicle.running_cost) result = self.fetch_prop( - result, "Loading Speed", [unit.loading_speed for unit in vehicle.units] + result, "Loading Speed", [unit.loading_speed for unit in vehicle.default_variant.units] ) props_to_print[vehicle] = result["vehicle"] diff --git a/src/roster.py b/src/roster.py index 40b111b48..22a481291 100755 --- a/src/roster.py +++ b/src/roster.py @@ -224,9 +224,9 @@ def validate_vehicles(self, numeric_id_defender): + consist.id + "' is defined more than once - to fix, search src for the duplicate" ) - if len(consist.units) == 0: + if len(consist.default_variant.units) == 0: raise BaseException("Error: " + consist.id + " has no units defined") - elif len(consist.units) == 1: + elif len(consist.default_variant.units) == 1: if consist.base_numeric_id <= global_constants.max_articulated_id: raise BaseException( "Error: " @@ -237,8 +237,8 @@ def validate_vehicles(self, numeric_id_defender): ) # utils.echo_message(consist.id + " with base_numeric_id " + str(consist.base_numeric_id) + " needs a base_numeric_id larger than 8200 as the range below 8200 is reserved for articulated vehicles") # utils.echo_message(str(consist.base_numeric_id)) - elif len(consist.units) > 1: - for unit in consist.units: + elif len(consist.default_variant.units) > 1: + for unit in consist.default_variant.units: if unit.numeric_id > global_constants.max_articulated_id: raise BaseException( "Error: " @@ -249,7 +249,7 @@ def validate_vehicles(self, numeric_id_defender): + str(global_constants.max_articulated_id) + " (use a lower consist base_numeric_id)" ) - for unit in set(consist.units): + for unit in set(consist.default_variant.units): if unit.numeric_id in numeric_id_defender: raise BaseException( "Error: unit " diff --git a/src/templates/articulated_parts.pynml b/src/templates/articulated_parts.pynml index 7b30f58a6..aa76ac35f 100644 --- a/src/templates/articulated_parts.pynml +++ b/src/templates/articulated_parts.pynml @@ -1,6 +1,6 @@ // add the units to articulated consist switch (FEAT_TRAINS, SELF, ${consist.id}_articulated_cb_switch, extra_callback_info1) { - + ${repeat.unit.index}: return ${unit.id}; return CB_RESULT_NO_MORE_ARTICULATED_PARTS; diff --git a/src/templates/properties_vehicle.pynml b/src/templates/properties_vehicle.pynml index 15505bfad..2efc5830c 100644 --- a/src/templates/properties_vehicle.pynml +++ b/src/templates/properties_vehicle.pynml @@ -143,7 +143,7 @@ item(FEAT_TRAINS, ${vehicle.id}, ${vehicle.numeric_id}) { speed: ${vehicle.id}_switch_speed; purchase_speed: ${int(1.60934 * consist.speed)}; - + articulated_part: ${consist.id}_articulated_cb_switch; diff --git a/src/train.py b/src/train.py index a6621cbf4..8eba271b2 100755 --- a/src/train.py +++ b/src/train.py @@ -120,8 +120,7 @@ def __init__(self, **kwargs): self.floating_run_cost_multiplier = 1 # fixed (baseline) run costs on this subtype, 100 points self.fixed_run_cost_points = 30 # default, over-ride in subclass as needed - # create structure to hold the units - self.units = [] + self.variants = [Variant()] # one default cargo for the whole consist, no mixed cargo shenanigans, it fails with auto-replace self.default_cargos = [] self.class_refit_groups = [] @@ -152,6 +151,11 @@ def __init__(self, **kwargs): # aids 'project management' self.sprites_complete = kwargs.get("sprites_complete", False) + @property + def default_variant(self): + # convenience method for docs etc + return self.variants[0] + def add_unit(self, type, repeat=1, **kwargs): unit = type(consist=self, **kwargs) count = len(self.unique_units) @@ -162,14 +166,14 @@ def add_unit(self, type, repeat=1, **kwargs): unit.id = self.id + "_" + str(count) unit.numeric_id = self.base_numeric_id + count for repeat_num in range(repeat): - self.units.append(unit) + self.default_variant.units.append(unit) @property def unique_units(self): # units may be repeated in the consist, sometimes we need an ordered list of unique units # set() doesn't preserve list order, which matters, so do it the hard way unique_units = [] - for unit in self.units: + for unit in self.default_variant.units: if unit not in unique_units: unique_units.append(unit) return unique_units @@ -178,7 +182,7 @@ def unique_units(self): def unique_spriterow_nums(self): # find the unique spriterow numbers, used in graphics generation result = [] - for unit in set([unit.spriterow_num for unit in self.units]): + for unit in set([unit.spriterow_num for unit in self.default_variant.units]): result.append(unit) # extend with alternative cc livery if present, spritesheet format assumes unit_1_default, unit_1_alternative_cc_livery, unit_2_default, unit_2_alternative_cc_livery if present if self.gestalt_graphics.alternative_cc_livery is not None: @@ -628,12 +632,12 @@ def power_speed_ratio(self): @property def weight(self): - return sum([getattr(unit, "weight", 0) for unit in self.units]) + return sum([getattr(unit, "weight", 0) for unit in self.default_variant.units]) @property def length(self): # total length of the consist - return sum([unit.vehicle_length for unit in self.units]) + return sum([unit.vehicle_length for unit in self.default_variant.units]) @property def loading_speed_multiplier(self): @@ -728,7 +732,7 @@ def nml_expression_for_vehicle_is_electrically_powered_by_tile(self): def buy_menu_x_loc(self): # automatic buy menu sprite if single-unit consist # extend this to check an auto_buy_menu_sprite property if manual over-rides are needed in future - if len(self.units) > 1: + if len(self.default_variant.units) > 1: # custom buy menu sprite for articulated vehicles return 360 elif self.is_randomised_wagon or self.is_caboose: @@ -928,7 +932,7 @@ def cite(self): return cite_name + ", " + random.choice(cite_titles) def render_articulated_switch(self, templates): - if len(self.units) > 1: + if len(self.default_variant.units) > 1: template = templates["articulated_parts.pynml"] nml_result = template(consist=self, global_constants=global_constants) return nml_result @@ -989,7 +993,7 @@ def render(self, templates, graphics_path): self.assert_power() # templating nml_result = "" - if len(self.units) > 1: + if len(self.default_variant.units) > 1: nml_result = nml_result + self.render_articulated_switch(templates) for unit in self.unique_units: nml_result = nml_result + unit.render(templates, graphics_path) @@ -4448,6 +4452,15 @@ def __init__(self, **kwargs): self.gestalt_graphics = GestaltGraphicsCustom("vehicle_torpedo_car.pynml") +class Variant(object): + """ + Base class for buyable variants of a consist, which align with Variants in the grf spec + """ + + def __init__(self, **kwargs): + self.units = [] + + class Train(object): """ Base class for all types of trains