Пример #1
0
def register_dwarf_npc():
    size = (
        30, 30
    )  # Must not align perfectly with grid cell size (pathfinding issues)
    sprite = Sprite.NEUTRAL_NPC_DWARF
    npc_type = NpcType.NEUTRAL_DWARF
    movement_speed = 0.03
    register_npc_data(npc_type, NpcData.neutral(sprite, size, movement_speed))
    register_npc_behavior(npc_type, NpcMind)
    introduction = "Hello there. I'm always looking for treasure. If you find any, we might be able to strike a deal!"
    dialog_options = [
        sell_item_option(
            plain_item_id(ItemType.GOLD_NUGGET), 20,
            "I'll give you good money for a nugget of pure gold!"),
        sell_item_option(plain_item_id(ItemType.SAPHIRE), 30,
                         "If you find a saphire I can make you real rich!"),
        DialogOptionData("\"Good bye\"", "cancel", None)
    ]
    dialog_data = DialogData("Gimli", PortraitIconSprite.VIKING, introduction,
                             dialog_options)
    register_npc_dialog_data(npc_type, dialog_data)
    sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet.png")
    original_sprite_size = (32, 32)
    scaled_sprite_size = (48, 48)
    indices_by_dir = {
        Direction.DOWN: [(0, 4), (1, 4), (2, 4)],
        Direction.LEFT: [(0, 5), (1, 5), (2, 5)],
        Direction.RIGHT: [(0, 6), (1, 6), (2, 6)],
        Direction.UP: [(0, 7), (1, 7), (2, 7)]
    }
    register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size,
                               scaled_sprite_size, indices_by_dir, (-8, -16))
    register_portrait_icon_sprite_path(
        PortraitIconSprite.VIKING, 'resources/graphics/viking_portrait.png')
Пример #2
0
def register_dwarf_npc():
    size = (
        30, 30
    )  # Must not align perfectly with grid cell size (pathfinding issues)
    sprite = Sprite.NEUTRAL_NPC_DWARF
    npc_type = NpcType.NEUTRAL_DWARF
    movement_speed = 0.03
    register_npc_data(npc_type, NpcData.neutral(sprite, size, movement_speed))
    register_npc_behavior(npc_type, NpcMind)
    sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet.png")
    original_sprite_size = (32, 32)
    scaled_sprite_size = (48, 48)
    indices_by_dir = {
        Direction.DOWN: [(0, 4), (1, 4), (2, 4)],
        Direction.LEFT: [(0, 5), (1, 5), (2, 5)],
        Direction.RIGHT: [(0, 6), (1, 6), (2, 6)],
        Direction.UP: [(0, 7), (1, 7), (2, 7)]
    }
    register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size,
                               scaled_sprite_size, indices_by_dir, (-8, -16))

    register_quest_giver_dialog(
        npc_name="Gimli",
        npc_type=npc_type,
        icon_sprite=UI_ICON_SPRITE,
        icon_sprite_file_path='resources/graphics/viking_portrait.png',
        quest=Quest(QUEST_ID, "Corrupted orb",
                    "Defeat the skeleton king and retrieve the magic orb."),
        quest_min_level=QUEST_MIN_LEVEL,
        quest_intro=
        "I've heard tales of a powerful skeleton mage that possesses a very rare magic orb. I think it's "
        "time that it finds itself a new owner!",
        boss_npc_type=NpcType.SKELETON_BOSS,
        quest_item_type=QUEST_ITEM_TYPE,
        custom_options=[
            sell_item_option(
                plain_item_id(ItemType.GOLD_NUGGET), 20,
                "I'll give you good money for a nugget of pure gold!"),
            sell_item_option(
                plain_item_id(ItemType.SAPPHIRE), 30,
                "If you find a sapphire I can make you real rich!")
        ],
        dialog_before_quest=
        "Hello there. I'm always looking for treasure. If you find any, we might be able to strike a "
        "deal!",
        dialog_give_quest=
        "Hello there. I'm always looking for treasure. If you find any, we might be able to strike a "
        "deal!",
        dialog_during_quest="Hey! Any luck with the orb?",
        dialog_after_completed="Hi old friend! Got any more good stuff?",
        reward_item_id=lambda _: random_item_two_affixes(5))
Пример #3
0
 def on_select(self, game_engine: GameEngine) -> Optional[str]:
     game_state = game_engine.game_state
     player_has_it = game_state.player_state.item_inventory.has_item_in_inventory(
         plain_item_id(self.quest_item_type))
     if player_has_it:
         game_state.player_state.item_inventory.lose_item_from_inventory(plain_item_id(self.quest_item_type))
         play_sound(SoundId.EVENT_COMPLETED_QUEST)
         game_state.player_state.complete_quest(self.quest)
         reward_item_id = self.reward_item_id(game_state)
         if reward_item_id:
             did_add_item = game_engine.try_add_item_to_inventory(reward_item_id)
             if not did_add_item:
                 game_state.game_world.items_on_ground.append(
                     create_item_on_ground(reward_item_id, game_state.game_world.player_entity.get_position()))
             return "Quest completed! Reward gained: " + reward_item_id.name
         return "Quest completed!"
     else:
         play_sound(SoundId.WARNING)
         return "You don't have that!"
Пример #4
0
def register_nomad_npc():
    sprite = Sprite.NEUTRAL_NPC_NOMAD
    npc_type = NpcType.NEUTRAL_NOMAD
    register_npc_data(
        npc_type, NpcData.neutral(sprite=sprite, size=(30, 30), speed=0.03))
    register_npc_behavior(npc_type, NpcMind)
    register_entity_sprite_map(
        sprite=sprite,
        sprite_sheet=SpriteSheet(
            "resources/graphics/enemy_sprite_sheet_3.png"),
        original_sprite_size=(32, 32),
        scaled_sprite_size=(48, 48),
        indices_by_dir={
            Direction.DOWN: [(3, 0), (4, 0), (5, 0)],
            Direction.LEFT: [(3, 1), (4, 1), (5, 1)],
            Direction.RIGHT: [(3, 2), (4, 2), (5, 2)],
            Direction.UP: [(3, 3), (4, 3), (5, 3)]
        },
        position_relative_to_entity=(-8, -16))

    register_quest_giver_dialog(
        npc_name="Nomad",
        npc_type=NpcType.NEUTRAL_NOMAD,
        icon_sprite=PortraitIconSprite.NOMAD,
        icon_sprite_file_path='resources/graphics/nomad_portrait.png',
        quest=QUEST,
        quest_min_level=QUEST_MIN_LEVEL,
        quest_intro=
        "The red baron has caused us great trouble. Get rid of him and I'll be forever "
        "grateful! Oh, and please bring back anything interesting that he's carrying.",
        boss_npc_type=NpcType.WARRIOR_KING,
        quest_item_type=QUEST_ITEM_TYPE,
        custom_options=[
            DialogOptionData("Receive blessing", "gain full health",
                             HealAction()),
            DialogOptionData("Ask for advice", "see random hint", HintAction())
        ],
        dialog_before_quest=
        "Greetings. I am here only to serve. Seek me out when you are wounded or need guidance!",
        dialog_give_quest=
        "Greetings. I am here only to serve. Seek me out when you are wounded or need guidance!",
        dialog_during_quest=
        "Greetings. I am here only to serve. Seek me out when you are wounded or need guidance!",
        dialog_after_completed=
        "Greetings. I am here only to serve. Seek me out when you are wounded or need guidance!",
        reward_item_id=lambda _: plain_item_id(ItemType.PORTAL_KEY))
Пример #5
0
 def __init__(self, global_path_finder: GlobalPathFinder):
     super().__init__(global_path_finder, QUEST_ID,
                      plain_item_id(QUEST_ITEM_TYPE), QUEST_MIN_LEVEL)
Пример #6
0
 def on_hover(self, game_state: GameState, ui_view: GameUiView):
     _quest_on_hover(game_state, ui_view, self.boss_npc_type, plain_item_id(self.quest_item_type))
Пример #7
0
    def handle_user_input(self,
                          events: List[Any]) -> Optional[SceneTransition]:

        transition_to_pause = False

        events_triggered_from_ui: List[EventTriggeredFromUi] = []

        # TODO handle dialog/no dialog more explicitly as states, and delegate more things to them (?)

        if self.ui_view.has_open_dialog():
            self.game_state.game_world.player_entity.set_not_moving()
            user_actions = get_dialog_actions(events)
            for action in user_actions:
                if isinstance(action, ActionChangeDialogOption):
                    npc_type, previous_index, new_index = self.ui_view.change_dialog_option(
                        action.index_delta)
                    self._handle_dialog_change_option(npc_type, previous_index,
                                                      new_index)
                if isinstance(action, ActionPressSpaceKey):
                    result = self.ui_view.handle_space_click()
                    if result:
                        npc_in_dialog, option_index = result
                        npc_type = npc_in_dialog.npc_type
                        blur_npc_action(npc_type, option_index,
                                        self.game_state, self.ui_view)
                        message = select_npc_action(npc_type, option_index,
                                                    self.game_engine)
                        if message:
                            self.ui_view.info_message.set_message(message)
                        npc_in_dialog.stun_status.remove_one()

                        # User may have been holding down a key when starting dialog, and then releasing it while in
                        # dialog. It's safer then to treat all keys as released when we exit the dialog.
                        self.user_input_handler.forget_held_down_keys()
                if isinstance(action, ActionMouseMovement):
                    self.ui_view.handle_mouse_movement_in_dialog(
                        action.mouse_screen_position)
                    # we handle "normal UI" mouse movement here primarily so that you can hover your equipment
                    # while in a dialog. (especially important when buying from an NPC)
                    self.ui_view.handle_mouse_movement(
                        action.mouse_screen_position)
                if isinstance(action, ActionMouseClicked):
                    result = self.ui_view.handle_mouse_click_in_dialog()
                    if result:
                        npc_type, previous_index, new_index = result
                        self._handle_dialog_change_option(
                            npc_type, previous_index, new_index)

        else:
            user_actions = self.user_input_handler.get_actions(events)
            for action in user_actions:
                if isinstance(action, ActionToggleRenderDebugging):
                    self.render_hit_and_collision_boxes = not self.render_hit_and_collision_boxes
                    # TODO: Handle this better than accessing a global variable from here
                    pythongame.core.pathfinding.npc_pathfinding.DEBUG_RENDER_PATHFINDING = \
                        not pythongame.core.pathfinding.npc_pathfinding.DEBUG_RENDER_PATHFINDING
                elif isinstance(action, ActionTryUseAbility):
                    self.game_engine.try_use_ability(action.ability_type)
                elif isinstance(action, ActionTryUsePotion):
                    self.game_engine.try_use_consumable(action.slot_number)
                elif isinstance(action, ActionMoveInDirection):
                    self.game_engine.move_in_direction(action.direction)
                elif isinstance(action, ActionStopMoving):
                    self.game_engine.stop_moving()
                elif isinstance(action, ActionPauseGame):
                    transition_to_pause = True
                elif isinstance(action, ActionMouseMovement):
                    self.ui_view.handle_mouse_movement(
                        action.mouse_screen_position)
                elif isinstance(action, ActionMouseClicked):
                    events_triggered_from_ui += self.ui_view.handle_mouse_click(
                    )
                elif isinstance(action, ActionMouseReleased):
                    events_triggered_from_ui += self.ui_view.handle_mouse_release(
                    )
                elif isinstance(action, ActionRightMouseClicked):
                    events_triggered_from_ui += self.ui_view.handle_mouse_right_click(
                    )
                elif isinstance(action, ActionPressSpaceKey):
                    ready_entity = self.player_interactions_state.get_entity_to_interact_with(
                    )
                    if ready_entity is not None:
                        if isinstance(ready_entity, NonPlayerCharacter):
                            ready_entity.world_entity.direction = get_directions_to_position(
                                ready_entity.world_entity,
                                self.game_state.game_world.player_entity.
                                get_center_position())[0]
                            ready_entity.world_entity.set_not_moving()
                            ready_entity.stun_status.add_one()
                            npc_type = ready_entity.npc_type
                            dialog_data = get_dialog_data(
                                npc_type, self.game_state)
                            option_index = self.ui_view.start_dialog_with_npc(
                                ready_entity, dialog_data)
                            play_sound(SoundId.DIALOG)
                            hover_npc_action(npc_type, option_index,
                                             self.game_state, self.ui_view)
                        elif isinstance(ready_entity, LootableOnGround):
                            self.game_engine.try_pick_up_loot_from_ground(
                                ready_entity)
                        elif isinstance(ready_entity, Portal):
                            self.game_engine.interact_with_portal(ready_entity)
                        elif isinstance(ready_entity, WarpPoint):
                            self.game_engine.use_warp_point(ready_entity)
                        elif isinstance(ready_entity, Chest):
                            self.game_engine.open_chest(ready_entity)
                        elif isinstance(ready_entity, Shrine):
                            self.game_engine.interact_with_shrine(ready_entity)
                        elif isinstance(ready_entity, DungeonEntrance):
                            has_key = self.game_state.player_state.item_inventory.has_item_in_inventory(
                                plain_item_id(ItemType.PORTAL_KEY))
                            if has_key:
                                entering_dungeon_scene = self.scene_factory.switching_game_world(
                                    self.game_engine, self.character_file,
                                    self.total_time_played_on_character,
                                    self._create_dungeon_engine_and_behavior)
                                return SceneTransition(entering_dungeon_scene)
                            else:
                                self.ui_view.info_message.set_message(
                                    "There is a keyhole on the side!")
                        else:
                            raise Exception("Unhandled entity: " +
                                            str(ready_entity))
                elif isinstance(action, ActionPressKey):
                    events_triggered_from_ui += self.ui_view.handle_key_press(
                        action.key)

        # TODO Much noise below around playing sounds. Perhaps game_engine should play the sounds in these cases?
        for event in events_triggered_from_ui:
            if isinstance(event, StartDraggingItemOrConsumable):
                play_sound(SoundId.UI_START_DRAGGING_ITEM)
            elif isinstance(event, DragItemBetweenInventorySlots):
                did_switch_succeed = self.game_engine.drag_item_between_inventory_slots(
                    event.from_slot, event.to_slot)
                if did_switch_succeed:
                    play_sound(SoundId.UI_ITEM_WAS_MOVED)
                else:
                    play_sound(SoundId.INVALID_ACTION)
            elif isinstance(event, DropItemOnGround):
                world_position = _get_mouse_world_pos(self.game_state,
                                                      event.screen_position)
                self.game_engine.drop_inventory_item_on_ground(
                    event.from_slot, world_position)
                play_sound(SoundId.UI_ITEM_WAS_DROPPED_ON_GROUND)
            elif isinstance(event, DragConsumableBetweenInventorySlots):
                self.game_engine.drag_consumable_between_inventory_slots(
                    event.from_slot, event.to_slot)
                play_sound(SoundId.UI_ITEM_WAS_MOVED)
            elif isinstance(event, DropConsumableOnGround):
                world_position = _get_mouse_world_pos(self.game_state,
                                                      event.screen_position)
                self.game_engine.drop_consumable_on_ground(
                    event.from_slot, world_position)
                play_sound(SoundId.UI_ITEM_WAS_DROPPED_ON_GROUND)
            elif isinstance(event, PickTalent):
                name_of_picked = pick_talent(self.game_state, event.tier_index,
                                             event.option_index)
                if not self.game_state.player_state.has_unpicked_talents():
                    self.ui_view.close_talent_window()
                self.ui_view.info_message.set_message("Talent picked: " +
                                                      name_of_picked)
                play_sound(SoundId.EVENT_PICKED_TALENT)
            elif isinstance(event, TrySwitchItemInInventory):
                did_switch_succeed = self.game_engine.try_switch_item_at_slot(
                    event.slot)
                if did_switch_succeed:
                    play_sound(SoundId.UI_ITEM_WAS_MOVED)
                else:
                    play_sound(SoundId.INVALID_ACTION)
            elif isinstance(event, ToggleSound):
                toggle_muted()
            elif isinstance(event, SaveGame):
                self._save_game()
            elif isinstance(event, ToggleFullscreen):
                self.toggle_fullscreen_callback()
            elif isinstance(event, ToggleWindow):
                play_sound(SoundId.UI_TOGGLE)
            else:
                raise Exception("Unhandled event: " + str(event))

        if transition_to_pause:
            return SceneTransition(
                PausedScene(self, self.world_view, self.ui_view,
                            self.game_state))
Пример #8
0
def item_id_key():
    # We defer calling this method as key item may not be registered yet otherwise
    return plain_item_id(ITEM_TYPE_KEY)
 def __init__(self, global_path_finder: GlobalPathFinder):
     super().__init__(global_path_finder, QUEST_ID,
                      plain_item_id(QUEST_ITEM_TYPE), QUEST_MIN_LEVEL)
     self.timer = PeriodicTimer(Millis(500))
     self.quest_timer = PeriodicTimer(Millis(1000))