def play_region_id(self, value): if value != 0 and self._stable_footing_flag != 0: raise InvalidFieldValueError( f"Cannot set 'play_region_id' to a non-zero value ({value}) while `stable_footing_flag` is non-zero." ) if not isinstance(value, int) or value <= -10: raise InvalidFieldValueError("'play_region_id' must be an integer greater than or equal to -9.") self._play_region_id = value
def stable_footing_flag(self, value): if self._play_region_id != 0: raise InvalidFieldValueError( "Cannot set 'stable_footing_flag' to a non-zero value while 'play_region_id' " "is non-zero.") if not isinstance(value, int) or value < 0: raise InvalidFieldValueError( "'stable_footing_flag' must be an integer greater than or equal to 0." ) self._stable_footing_flag = value
def stable_footing_flag(self, value): if not isinstance(value, int) or value < -1: raise InvalidFieldValueError( f"`stable_footing_flag` must be an integer no less than -1 (Collision '{self.name}')." ) if value != 0 and self._play_region_id != 0: raise InvalidFieldValueError( f"Cannot set `stable_footing_flag` to a non-zero value while 'play_region_id' is not zero, even if it " f"is just -1: {self._play_region_id} (Collision '{self.name}')." ) self._stable_footing_flag = value
def force_area_banner(self, value: bool): if not value and self.area_name_id == -1: raise InvalidFieldValueError( "Banner must appear when area name is set to default (-1). You must specify the area name manually to " "set this to False." ) self._force_area_banner = bool(value)
def _string_to_Map(self, string): try: return self.master.maps.GET_MAP(string) except (KeyError, ValueError): raise InvalidFieldValueError( f"Could not interpret input as a Map specifier for field {self.field_nickname}. Try a string like " f"'m10_02_00_00'.")
def pack_type_data(self): """Pack to bytes, presumably as part of a full `MSB` pack.""" # Validate navmesh groups before doing any real work. navmesh_groups = bit_set_to_int_group(self._navmesh_groups, group_size=4) if self.area_name_id == -1 and not self._force_area_banner: raise InvalidFieldValueError( "`force_area_banner` must be enabled if `area_name_id == -1` (default)." ) signed_area_name_id = self.area_name_id * ( -1 if self.area_name_id >= 0 and self._force_area_banner else 1) if self._stable_footing_flag != 0: play_region_id = -self._stable_footing_flag - 10 else: play_region_id = self._play_region_id return self.PART_TYPE_DATA_STRUCT.pack( hit_filter_id=self.hit_filter_id, sound_space_type=self.sound_space_type, _environment_event_index=self._environment_event_index, reflect_plane_height=self.reflect_plane_height, __navmesh_groups=navmesh_groups, vagrant_entity_ids=self.vagrant_entity_ids, __area_name_id=signed_area_name_id, starts_disabled=self.starts_disabled, unk_x27_x28=self.unk_x27_x28, attached_bonfire=self.attached_bonfire, __play_region_id=play_region_id, camera_1_id=self.camera_1_id, camera_2_id=self.camera_2_id, )
def _string_to_float(self, string): if not string.strip("-"): return None # no change try: return float(string) except ValueError: raise InvalidFieldValueError(f"Value of field {self.field_nickname} must be a float.")
def _string_to_GameObject(self, string): # Assume all non-`MapEntry` fields use integers (e.g. `BaseParam`, `Text`). if issubclass(self.field_type, MapEntry): return string else: try: return int(string) except ValueError: raise InvalidFieldValueError( f"Value of field {self.field_nickname} must be an integer ({self.field_type})." )
def _string_to_list(self, string): """At the moment, all elements of `list`-type fields must be integers.""" try: new_value = literal_eval(string) if isinstance(new_value, tuple): new_value = list(new_value) elif not isinstance(new_value, list): raise SyntaxError if not all(isinstance(i, int) for i in new_value): raise SyntaxError except (SyntaxError, ValueError): raise InvalidFieldValueError( f"Value of field {self.field_nickname} must be a list of integers, e.g. [1, 2, 3, ...]" ) return new_value
def draw_groups(self, value): """Converts value to a `set()` (possibly empty) and validates index range.""" if value is None or isinstance(value, str) and value in {"None", ""}: self._draw_groups = set() return try: draw_groups = set(value) except (TypeError, ValueError): raise TypeError( "Draw groups must be a set, sequence, `None`, `'None'`, or `''`. Or use `set` methods like `.add()`." ) for i in draw_groups: if not isinstance(i, int) and 0 <= i < self.DRAW_GROUP_COUNT: raise InvalidFieldValueError( f"Invalid draw group: {i}. Must be 0 <= i < {self.DRAW_GROUP_COUNT}." ) self._draw_groups = draw_groups
def pack_type_data(self): """Pack to bytes, presumably as part of a full `MSB` pack.""" if self.area_name_id == -1 and not self._force_area_banner: raise InvalidFieldValueError("`force_area_banner` must be enabled if `area_name_id == -1` (default).") signed_area_name_id = self.area_name_id * (-1 if self.area_name_id >= 0 and self._force_area_banner else 1) if self._stable_footing_flag != 0: play_region_id = -self._stable_footing_flag - 10 else: play_region_id = self._play_region_id return self.PART_TYPE_DATA_STRUCT.pack( hit_filter_id=self.hit_filter_id, sound_space_type=self.sound_space_type, _environment_event_index=self._environment_event_index, reflect_plane_height=self.reflect_plane_height, __area_name_id=signed_area_name_id, starts_disabled=self.starts_disabled, unk_x0b_x0c=self.unk_x0b_x0c, attached_bonfire=self.attached_bonfire, __play_region_id=play_region_id, camera_1_id=self.camera_1_id, camera_2_id=self.camera_2_id, )