class SkillTimeRamp(HasTunableSingletonFactory, AutoFactoryInit):
        FACTORY_TUNABLES = {
            'skill':
            Skill.TunableReference(
                description=
                "\n                The skill that should influence the interaction's running time.\n                "
            ),
            'least_skilled_completion_time':
            Tunable(
                description=
                '\n                Number of Sim minutes it should take the least-skilled Sim to\n                reach the goal value in the worst case, that is, if the stat is\n                as far from the goal value as possible.\n                ',
                tunable_type=int,
                default=None),
            'most_skilled_completion_time':
            Tunable(
                description=
                '\n                Number of Sim minutes it should take the most-skilled Sim to\n                reach the goal value in the worst case, that is, if the stat is\n                as far from the goal value as possible.\n                ',
                tunable_type=int,
                default=None)
        }

        @property
        def stat(self):
            return self.skill

        def get_maximum_running_time(self, interaction):
            skill_level = interaction.sim.get_effective_skill_level(self.skill)
            quantized_value = self.skill.convert_from_user_value(skill_level)
            p = (self.skill.max_value - quantized_value) / (
                self.skill.max_value - self.skill.min_value)
            time = sims4.math.interpolate(self.most_skilled_completion_time,
                                          self.least_skilled_completion_time,
                                          p)
            return time
Exemple #2
0
class _SimInfoSkillFixupAction(_SimInfoFixupAction):
    FACTORY_TUNABLES = {'skill': Skill.TunableReference(description='\n            The skill which will be assigned to the sim_info.\n            '), 'initial_level': Tunable(description='\n            The initial level at which to assign the skill.\n            ', tunable_type=int, default=1)}

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def __call__(self, sim_info):
        sim_info.commodity_tracker.set_user_value(self.skill, self.initial_level)
    class SkillTimeCurve(HasTunableSingletonFactory, AutoFactoryInit):
        FACTORY_TUNABLES = {
            'skill':
            Skill.TunableReference(
                description=
                "\n                The skill that should influence the interaction's running time.\n                "
            ),
            'curve':
            TunableCurve(
                description=
                "\n                A curve describing the relationship between a Sim's skill level\n                (x-axis) and the interaction's running time (y-axis).  The time\n                is the number of Sim minutes it should take the specified goal\n                commodity to reach the goal value in the worst case, that is, if\n                the stat is as far from the goal value as possible.\n                "
            )
        }

        @property
        def stat(self):
            return self.skill

        def get_maximum_running_time(self, interaction):
            skill_level = interaction.sim.get_effective_skill_level(self.skill)
            time = self.curve.get(skill_level)
            return time
class GameRules(metaclass=TunedInstanceMetaclass,
                manager=services.get_instance_manager(
                    sims4.resources.Types.GAME_RULESET)):
    __qualname__ = 'GameRules'
    INSTANCE_TUNABLES = {
        'game_name':
        TunableLocalizedStringFactory(
            description='\n            Name of the game.\n            ',
            default=1860708663),
        'teams_per_game':
        TunableInterval(
            description=
            '\n            An interval specifying the number of teams allowed per game.\n            \n            Joining Sims are put on a new team if the maximum number of teams\n            has not yet been met, otherwise they are put into the team with the\n            fewest number of players.\n            ',
            tunable_type=int,
            default_lower=2,
            default_upper=2,
            minimum=1),
        'players_per_game':
        TunableInterval(
            description=
            '\n            An interval specifying the number of players allowed per game.\n            \n            If the maximum number of players has not been met, Sims can\n            continue to join a game.  Joining Sims are put on a new team if the\n            maximum number of teams as specified in the "teams_per_game"\n            tunable has not yet been met, otherwise they are put into the team\n            with the fewest number of players.\n            ',
            tunable_type=int,
            default_lower=2,
            default_upper=2,
            minimum=1),
        'players_per_turn':
        TunableRange(
            description=
            '\n            An integer specifying number of players from the active team who\n            take their turn at one time.\n            ',
            tunable_type=int,
            default=1,
            minimum=1),
        'initial_state':
        ObjectStateValue.TunableReference(
            description=
            "\n            The game's starting object state.\n            "),
        'score_info':
        TunableTuple(
            description=
            "\n            Tunables that affect the game's score.\n            ",
            winning_score=Tunable(
                description=
                '\n                An integer value specifying at what score the game will end.\n                ',
                tunable_type=int,
                default=100),
            score_increase=TunableInterval(
                description=
                '\n                An interval specifying the minimum and maximum score increases\n                possible in one turn. A random value in this interval will be\n                generated each time score loot is given.\n                ',
                tunable_type=int,
                default_lower=35,
                default_upper=50,
                minimum=0),
            skill_level_bonus=Tunable(
                description=
                "\n                A bonus number of points based on the Sim's skill level in the\n                relevant_skill tunable that will be added to score_increase.\n                \n                ex: If this value is 2 and the Sim receiving score has a\n                relevant skill level of 4, they will receive 8 (2 * 4) extra\n                points.\n                ",
                tunable_type=float,
                default=2),
            relevant_skill=Skill.TunableReference(
                description=
                "\n                The skill relevant to this game.  Each Sim's proficiency in\n                this skill will effect the score increase they get.\n                "
            ),
            use_effective_skill_level=Tunable(
                description=
                '\n                If checked, we will use the effective skill level rather than\n                the actual skill level of the relevant_skill tunable.\n                ',
                tunable_type=bool,
                default=True),
            progress_stat=Statistic.TunableReference(
                description=
                '\n                The statistic that advances the progress state of this game.\n                '
            )),
        'clear_score_on_player_join':
        Tunable(
            description=
            '\n            Tunable that, when checked, will clear the game score when a player joins.\n            \n            This essentially resets the game.\n            ',
            tunable_type=bool,
            default=False),
        'alternate_target_object':
        OptionalTunable(
            description=
            '\n            Tunable that, when enabled, means the game should create an alternate object\n            in the specified slot on setup that will be modified as the game goes on\n            and destroyed when the game ends.\n            ',
            tunable=TunableTuple(
                target_game_object=TunableReference(
                    description=
                    '\n                    The definition of the object that will be created/destroyed/altered\n                    by the game.\n                    ',
                    manager=services.definition_manager()),
                parent_slot=TunableVariant(
                    description=
                    '\n                    The slot on the parent object where the target_game_object object should go. This\n                    may be either the exact name of a bone on the parent object or a\n                    slot type, in which case the first empty slot of the specified type\n                    in which the child object fits will be used.\n                    ',
                    by_name=Tunable(
                        description=
                        '\n                        The exact name of a slot on the parent object in which the target\n                        game object should go.  \n                        ',
                        tunable_type=str,
                        default='_ctnm_'),
                    by_reference=TunableReference(
                        description=
                        '\n                        A particular slot type in which the target game object should go.  The\n                        first empty slot of this type found on the parent will be used.\n                        ',
                        manager=services.get_instance_manager(
                            sims4.resources.Types.SLOT_TYPE)))))
    }
class UiRecipePicker(UiDialogObjectPicker):
    __qualname__ = 'UiRecipePicker'

    @staticmethod
    def _verify_tunable_callback(instance_class,
                                 tunable_name,
                                 source,
                                 column_sort_priorities=None,
                                 picker_columns=None,
                                 **kwargs):
        if column_sort_priorities is not None:
            length = len(picker_columns)
            if any(v >= length for v in column_sort_priorities):
                logger.error(
                    'UiRecipePicker dialog in {} has invalid column sort priority. Valid values are 0-{}',
                    instance_class,
                    length - 1,
                    owner='cjiang')

    FACTORY_TUNABLES = {
        'skill':
        OptionalTunable(
            Skill.TunableReference(
                description=
                '\n            The skill associated with the picker dialog.\n            '
            )),
        'picker_columns':
        TunableList(
            description='\n            List of the column info\n            ',
            tunable=PickerColumn.TunableFactory()),
        'column_sort_priorities':
        OptionalTunable(
            description=
            '\n            If enabled, specifies column sorting.\n            ',
            tunable=TunableList(
                description=
                '\n                The priority index for the column (column numbers are 0-based\n                index. So, if you wish to use the first column the id is 0).\n                ',
                tunable=int)),
        'verify_tunable_callback':
        _verify_tunable_callback
    }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.picker_type = ObjectPickerType.RECIPE

    def _customize_add_row(self, row):
        for picker_row in self.picker_rows:
            self._build_row_links(row, picker_row)
            self._build_row_links(picker_row, row)

    def _validate_row(self, row):
        return isinstance(row, RecipePickerRow)

    @staticmethod
    def _build_row_links(row1, row2):
        if row1.linked_recipe is not None and row1.linked_recipe is row2.tag:
            row2.linked_option_ids.append(row1.option_id)

    def _build_customize_picker(self, picker_data):
        for column in self.picker_columns:
            column_data = picker_data.recipe_picker_data.column_list.add()
            column.populate_protocol_buffer(column_data)
        if self.skill is not None:
            picker_data.recipe_picker_data.skill_id = self.skill.guid64
        if self.column_sort_priorities is not None:
            picker_data.recipe_picker_data.column_sort_list.extend(
                self.column_sort_priorities)
        for row in self.picker_rows:
            row_data = picker_data.recipe_picker_data.row_data.add()
            row.populate_protocol_buffer(row_data)
Exemple #6
0
class GameRules(HasTunableReference,
                metaclass=TunedInstanceMetaclass,
                manager=services.get_instance_manager(
                    sims4.resources.Types.GAME_RULESET)):
    ENDING_CONDITION_SCORE = 0
    ENDING_CONDITION_ROUND = 1
    INSTANCE_TUNABLES = {
        'game_name':
        TunableLocalizedStringFactory(
            description='\n            Name of the game.\n            ',
            default=1860708663),
        'team_strategy':
        TunableVariant(
            description=
            '\n            Define how Sims are distributed across teams.\n            ',
            auto_balanced=GameTeamAutoBalanced.TunableFactory(),
            part_driven=GameTeamPartDriven.TunableFactory(),
            default='auto_balanced'),
        'teams_per_game':
        TunableInterval(
            description=
            '\n            An interval specifying the number of teams allowed per game.\n            \n            Joining Sims are put on a new team if the maximum number of teams\n            has not yet been met, otherwise they are put into the team with the\n            fewest number of players.\n            ',
            tunable_type=int,
            default_lower=2,
            default_upper=2,
            minimum=1),
        'players_per_game':
        TunableInterval(
            description=
            '\n            An interval specifying the number of players allowed per game.\n            \n            If the maximum number of players has not been met, Sims can\n            continue to join a game.  Joining Sims are put on a new team if the\n            maximum number of teams as specified in the "teams_per_game"\n            tunable has not yet been met, otherwise they are put into the team\n            with the fewest number of players.\n            ',
            tunable_type=int,
            default_lower=2,
            default_upper=2,
            minimum=1),
        'players_per_turn':
        TunableRange(
            description=
            '\n            An integer specifying number of players from the active team who\n            take their turn at one time.\n            ',
            tunable_type=int,
            default=1,
            minimum=1),
        'initial_state':
        ObjectStateValue.TunableReference(
            description=
            "\n            The game's starting object state.\n            ",
            allow_none=True),
        'score_info':
        TunableTuple(
            description=
            "\n            Tunables that affect the game's score.\n            ",
            ending_condition=TunableVariant(
                description=
                '\n                The condition under which the game ends.\n                ',
                score_based=TunableTuple(
                    description=
                    '\n                    A game that ends when one of the teams wins by reaching a \n                    certain score first\n                    ',
                    locked_args={'end_condition': ENDING_CONDITION_SCORE},
                    winning_score=Tunable(
                        description=
                        '\n                        Score required to win.\n                        ',
                        tunable_type=int,
                        default=100)),
                round_based=TunableTuple(
                    description=
                    '\n                    A game that ends after a certain number of rounds.  The Team\n                    with the highest score at that point wins.\n                    ',
                    locked_args={'end_condition': ENDING_CONDITION_ROUND},
                    rounds=Tunable(
                        description=
                        '\n                        Length of game (in rounds).\n                        ',
                        tunable_type=int,
                        default=3)),
                default='score_based'),
            score_increase=TunableInterval(
                description=
                '\n                An interval specifying the minimum and maximum score increases\n                possible in one turn. A random value in this interval will be\n                generated each time score loot is given.\n                ',
                tunable_type=int,
                default_lower=35,
                default_upper=50,
                minimum=0),
            allow_scoring_for_non_active_teams=Tunable(
                description=
                '\n                If checked, any Sim may score, even if their team is not\n                considered active.\n                ',
                tunable_type=bool,
                default=False),
            skill_level_bonus=Tunable(
                description=
                "\n                A bonus number of points based on the Sim's skill level in the\n                relevant_skill tunable that will be added to score_increase.\n                \n                ex: If this value is 2 and the Sim receiving score has a\n                relevant skill level of 4, they will receive 8 (2 * 4) extra\n                points.\n                ",
                tunable_type=float,
                default=2),
            relevant_skill=Skill.TunableReference(
                description=
                "\n                The skill relevant to this game.  Each Sim's proficiency in\n                this skill will effect the score increase they get.\n                ",
                allow_none=True),
            use_effective_skill_level=Tunable(
                description=
                '\n                If checked, we will use the effective skill level rather than\n                the actual skill level of the relevant_skill tunable.\n                ',
                tunable_type=bool,
                default=True),
            progress_stat=Statistic.TunableReference(
                description=
                '\n                The statistic that advances the progress state of this game.\n                ',
                allow_none=True),
            persist_high_score=Tunable(
                description=
                '\n                If checked, the high score and the team Sim ids will be\n                saved onto the game component.\n                ',
                tunable_type=bool,
                default=False)),
        'clear_score_on_player_join':
        Tunable(
            description=
            '\n            Tunable that, when checked, will clear the game score when a player joins.\n            \n            This essentially resets the game.\n            ',
            tunable_type=bool,
            default=False),
        'alternate_target_object':
        OptionalTunable(
            description=
            '\n            Tunable that, when enabled, means the game should create an alternate object\n            in the specified slot on setup that will be modified as the game goes on\n            and destroyed when the game ends.\n            ',
            tunable=TunableTuple(
                target_game_object=TunableReference(
                    description=
                    '\n                    The definition of the object that will be created/destroyed/altered\n                    by the game.\n                    ',
                    manager=services.definition_manager()),
                parent_slot=TunableVariant(
                    description=
                    '\n                    The slot on the parent object where the target_game_object object should go. This\n                    may be either the exact name of a bone on the parent object or a\n                    slot type, in which case the first empty slot of the specified type\n                    in which the child object fits will be used.\n                    ',
                    by_name=Tunable(
                        description=
                        '\n                        The exact name of a slot on the parent object in which the target\n                        game object should go.  \n                        ',
                        tunable_type=str,
                        default='_ctnm_'),
                    by_reference=TunableReference(
                        description=
                        '\n                        A particular slot type in which the target game object should go.  The\n                        first empty slot of this type found on the parent will be used.\n                        ',
                        manager=services.get_instance_manager(
                            sims4.resources.Types.SLOT_TYPE))),
                destroy_at_end=Tunable(
                    description=
                    '\n                    If True, the alternate target object will get destroyed at the end of the game.\n                    ',
                    tunable_type=bool,
                    default=True))),
        'game_over_notification':
        OptionalTunable(
            description=
            "\n            If enabled, when any Sim involved in the game is a player-controlled\n            Sim, display a notification when the game is over.\n            \n            NOTE: As of now, this only triggers when there are *exactly* two\n            teams. To support more teams, we'll need to extend the possible\n            string permutation.\n            ",
            tunable=TunableTuple(
                one_v_one=TunableUiDialogNotificationSnippet(
                    description=
                    "\n                    The notification to show when the game is 1v1.\n                    \n                     * Token 0 is the object the game is being played on\n                     * Token 1 is the winner\n                     * Token 2 is the loser\n                     * Token 3 is the winner's score\n                     * Token 4 is the loser's score\n                    "
                ),
                one_v_many_winner
                =TunableUiDialogNotificationSnippet(
                    description=
                    "\n                    The notification to show when the game is 1 v many, and the\n                    single Sim is the winner.\n                    \n                    * Token 0 is the object the game is being played on\n                    * Token 1 is the winner\n                    * Token 2 is a list of losers (Alice, Bob, and Carol)\n                    * Token 3 is the winner's score\n                    * Token 4 is the loser's score\n                    "
                ),
                one_v_many_loser=TunableUiDialogNotificationSnippet(
                    description=
                    "\n                    The notification to show when the game is 1 v many, and the\n                    single Sim is the loser.\n                    \n                    * Token 0 is the object the game is being played on\n                    * Token 1 is a list of winners (Alice, Bob, and Carol)\n                    * Token 2 is the loser\n                    * Token 3 is the winner's score\n                    * Token 4 is the loser's score\n                    "
                ),
                many_v_many=TunableUiDialogNotificationSnippet(
                    description=
                    "\n                    The notification to show when the game is many v many.\n                    \n                    * Token 0 is the object the game is being played on\n                    * Token 1 is a list of winners (Alice and Bob)\n                    * Token 2 is a list of losers (Carol, Dan, and Erin)\n                    * Token 3 is the winner's score\n                    * Token 4 is the loser's score\n                    "
                ))),
        'game_over_winner_only_notification':
        OptionalTunable(
            description=
            '\n            If enabled, when any Sim involved in the game is a player-controlled\n            Sim, display a notification when the game is over.\n            \n            NOTE: This will show only the winners of the game with the highest \n            score. The winners can be more than one team if they have same \n            score.\n            ',
            tunable=TunableTuple(
                play_alone=TunableUiDialogNotificationSnippet(
                    description=
                    "\n                    The notification to show when Sim play alone.\n                    \n                    * Token 0 is the object the game is being played on\n                    * Token 1 is the Sim's name\n                    * Token 2 is the Sim's score\n                    "
                ),
                winner=TunableUiDialogNotificationSnippet(
                    description=
                    "\n                    The notification to show when the game has 1 team winner.\n                    \n                    * Token 0 is the object the game is being played on\n                    * Token 1 is the winner\n                    * Token 2 is the winner's score\n                    "
                ))),
        'additional_game_behavior':
        OptionalTunable(
            description=
            '\n            If enabled additional behavior will be run for this type of game\n            on multiple phases like creating destroying additional objects on \n            setup of end phases.\n            ',
            tunable=TunableVariant(
                description=
                "\n                Variant of type of games that will add very specific behavior\n                to the game component.\n                e.g. Card battle behavior will create cards and destroy them\n                depending on each actor's inventory.\n                ",
                card_battle=CardBattleBehavior.TunableFactory(),
                create_object=CreateObjectBehavior.TunableFactory(),
                default='card_battle'))
    }

    def __init__(self, game_component, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._game_component = game_component
        self.additional_game_behavior = self.additional_game_behavior(
        ) if self.additional_game_behavior is not None else None

    def add_player(self, sim):
        self.team_strategy.add_player(self._game_component, sim)

    @classmethod
    def can_be_on_same_team(cls, target_a, target_b):
        return cls.team_strategy.can_be_on_same_team(target_a, target_b)

    @classmethod
    def team_determines_part(cls):
        return cls.team_strategy.team_determines_part()

    @classmethod
    def can_be_on_opposing_team(cls, target_a, target_b):
        return cls.team_strategy.can_be_on_opposing_team(target_a, target_b)

    def remove_player(self, sim):
        self.team_strategy.remove_player(self._game_component, sim)
class EffectiveSkillModifier(HasTunableSingletonFactory, BaseGameEffectModifier):
    __qualname__ = 'EffectiveSkillModifier'
    FACTORY_TUNABLES = {'description': '\n        The modifier to change the effective skill or skill_tag tuned in the\n        modifier key The value of the modifier can be negative..\n        ', 'modifier_key': TunableVariant(description='\n            ', skill_type=Skill.TunableReference(description='\n                            What skill to apply the modifier on.'), skill_tag=TunableEnumEntry(description='\n                            What skill tag to apply the modifier on.', tunable_type=tag.Tag, default=tag.Tag.INVALID)), 'modifier_value': Tunable(description='\n            The value to change the effective skill. Can be negative.', tunable_type=int, default=0)}

    def __init__(self, modifier_key, modifier_value, **kwargs):
        BaseGameEffectModifier.__init__(self, GameEffectType.EFFECTIVE_SKILL_MODIFIER)
        self.modifier_key = modifier_key
        self.modifier_value = modifier_value

    def can_modify(self, skill):
        if self.modifier_key is skill.skill_type:
            return True
        return self.modifier_key in skill.tags

    def get_modifier_value(self, skill):
        if self.can_modify(skill):
            return self.modifier_value
        return 0