def get_callback_flags_actions(feature, id, flags): """ Get a list of actions to set the callback flags of a certain item @param feature: Feature of the item @type feature: C{int} @param id: ID of the item @type id: L{Expression} @param flags: Value of the 'callback_flags' property @type flags: C{int} @return: A list of actions @rtype: C{list} of L{BaseAction} """ assert isinstance(id, expression.ConstantNumeric) act0, offset = create_action0(feature, id, None, None) act0.num_ids = 1 assert feature in callback_flag_properties prop_info_list = callback_flag_properties[feature] if not isinstance(prop_info_list, list): prop_info_list = [prop_info_list] for prop_info in prop_info_list: act0.prop_list.append( Action0Property( prop_info['num'], parse_property_value(prop_info, expression.ConstantNumeric(flags)), prop_info['size'])) return [act0]
def get_disable_actions(disable): """ Get the action list for a disable_item block @param disable: Disable block @type disable: L{DisableItem} @return: A list of resulting actions @rtype: C{list} of L{BaseAction} """ feature = disable.feature.value if feature not in disable_info: raise generic.ScriptError("disable_item() is not available for feature {:d}.".format(feature), disable.pos) if disable.first_id is None: # No ids set -> disable all assert disable.last_id is None first = 0 num = disable_info[feature]["num"] else: first = disable.first_id.value if disable.last_id is None: num = 1 else: num = disable.last_id.value - first + 1 act0 = Action0(feature, first) act0.num_ids = num for prop in disable_info[feature]["props"]: act0.prop_list.append( Action0Property(prop["num"], num * [expression.ConstantNumeric(prop["value"])], prop["size"]) ) return [act0]
def get_volume_actions(volume_list): """ Get a list of actions to set sound volumes @param volume_list: List of (sound id, volume) tuples, sorted in ascending order @type volume_list: C{list} of (C{int}, C{int})-tuples @return: A list of actions @rtype: C{list} of L{BaseAction} """ action_list = [] first_id = None # First ID in a series of consecutive IDs value_series = [] # Series of values to write in a single action for id, volume in volume_list: if first_id is None: first_id = id continue_series = first_id + len(value_series) == id if continue_series: value_series.append(volume) if not continue_series or id == volume_list[-1][0]: # Write action for this series act0, offset = create_action0(0x0C, expression.ConstantNumeric(first_id), None, None) act0.num_ids = len(value_series) act0.prop_list.append(Action0Property(0x08, [expression.ConstantNumeric(v) for v in value_series], 1)) action_list.append(act0) # start new series, if needed if not continue_series: first_id = id value_series = [volume] return action_list
def get_basecost_action(basecost): action6.free_parameters.save() action_list = [] tmp_param_map = {} # Cache for tmp parameters # We want to avoid writing lots of action0s if possible i = 0 while i < len(basecost.costs): cost = basecost.costs[i] act6 = action6.Action6() act0, offset = create_action0(0x08, cost.name, act6, action_list) first_id = cost.name.value if isinstance( cost.name, expression.ConstantNumeric) else None num_ids = 1 # Number of values that will be written in one go values = [] # try to capture as much values as possible while True: cost = basecost.costs[i] if isinstance(cost.value, expression.ConstantNumeric): values.append(cost.value) else: # Cache lookup, saves some ActionDs if cost.value in tmp_param_map: tmp_param, tmp_param_actions = tmp_param_map[ cost.value], [] else: tmp_param, tmp_param_actions = actionD.get_tmp_parameter( cost.value) tmp_param_map[cost.value] = tmp_param act6.modify_bytes(tmp_param, 1, offset + num_ids) action_list.extend(tmp_param_actions) values.append(expression.ConstantNumeric(0)) # check if we can append the next to this one (it has to be consecutively numbered) if first_id is not None and (i + 1) < len(basecost.costs): nextcost = basecost.costs[i + 1] if isinstance(nextcost.name, expression.ConstantNumeric ) and nextcost.name.value == first_id + num_ids: num_ids += 1 i += 1 # Yes We Can, continue the loop to append this value to the list and try further continue # No match, so stop it and write an action0 break act0.prop_list.append(Action0Property(0x08, values, 1)) act0.num_ids = num_ids if len(act6.modifications) > 0: action_list.append(act6) action_list.append(act0) i += 1 action6.free_parameters.restore() return action_list
def get_language_translation_tables(lang): action0 = Action0(0x08, lang.langid) if lang.genders is not None: action0.prop_list.append(LanguageTranslationTable(0x13, lang.genders, lang.gender_map)) if lang.cases is not None: action0.prop_list.append(LanguageTranslationTable(0x14, lang.cases, lang.case_map)) if lang.plural is not None: action0.prop_list.append(Action0Property(0x15, expression.ConstantNumeric(lang.plural), 1)) if len(action0.prop_list) > 0: return [action0] return []
def parse_sort_block(feature, vehid_list): prop_num = [0x1A, 0x20, 0x1B, 0x1B] action_list = [] if len(vehid_list) >= 2: last = vehid_list[0] idx = len(vehid_list) - 1 while idx >= 0: cur = vehid_list[idx] prop = Action0Property(prop_num[feature], [last], 3) action_list.append(Action0(feature, cur.value)) action_list[-1].prop_list.append(prop) last = cur idx -= 1 return action_list
def parse_property(prop_info, value_list, feature, id): """ Parse a single property @param prop_info: A dictionary with property information @type prop_info: C{dict} @param value_list: List of values for the property, with unit conversion applied @type value_list: C{list} of L{Expression} @param feature: Feature of the associated item @type feature: C{int} @param id: ID of the associated item @type id: L{Expression} @return: A tuple containing the following: - List of properties to add to the action 0 - List of actions to prepend - List of modifications to apply via action 6 - List of actions to append @rtype: C{tuple} of (C{list} of L{Action0Property}, C{list} of L{BaseAction}, C{list} of 3-C{tuple}, C{list} of L{BaseAction}) """ action_list = [] action_list_append = [] mods = [] if 'custom_function' in prop_info: props = prop_info['custom_function'](*value_list) else: # First process each element in the value_list final_values = [] for i, value in enumerate(value_list): if 'string_literal' in prop_info and ( isinstance(value, expression.StringLiteral) or prop_info['string_literal'] != 4): # Parse non-string exprssions just like integers. User will have to take care of proper value. # This can be used to set a label (=string of length 4) to the value of a parameter. if not isinstance(value, expression.StringLiteral): raise generic.ScriptError( "Value for property {:d} must be a string literal". format(prop_info['num']), value.pos) if len(value.value) != prop_info['string_literal']: raise generic.ScriptError( "Value for property {:d} must be of length {:d}". format(prop_info['num'], prop_info['string_literal']), value.pos) elif isinstance(value, expression.ConstantNumeric): pass elif isinstance(value, expression.Parameter) and isinstance( value.num, expression.ConstantNumeric): mods.append((value.num.value, prop_info['size'], i * prop_info['size'] + 1)) value = expression.ConstantNumeric(0) elif isinstance(value, expression.String): if not 'string' in prop_info: raise generic.ScriptError( "String used as value for non-string property: " + str(prop_info['num']), value.pos) string_range = prop_info['string'] stringid, string_actions = action4.get_string_action4s( feature, string_range, value, id) value = expression.ConstantNumeric(stringid) action_list_append.extend(string_actions) else: tmp_param, tmp_param_actions = actionD.get_tmp_parameter(value) mods.append( (tmp_param, prop_info['size'], i * prop_info['size'] + 1)) action_list.extend(tmp_param_actions) value = expression.ConstantNumeric(0) final_values.append(value) # Now, write a single Action0 Property with all of these values if prop_info['num'] != -1: props = [ Action0Property(prop_info['num'], final_values, prop_info['size']) ] else: props = [] return (props, action_list, mods, action_list_append)