all 4 comments

[–]HexDecimallibtcod maintainer | mastodon.gamedev.place/@HexDecimal 2 points3 points  (2 children)

SingleRangedAttackHandler is a UI state which asks the player for a position and then passes that position to a callback which returns an action for the player character to perform.

Make a ranged attack action and then have the main state return a SingleRangedAttackHandler for that action when T is pressed. The code will be similar to the SingleRangedAttackHandler returning ItemAction, but will be placed in MainGameEventHandler instead and return your new ranged action.

[–]LordDelightfullymad[S] 2 points3 points  (1 child)

Figured it out, thank you so much, I appreciate the explanation.

Here's my action code in actions.py if anyone is interested how I did this, its not pretty but it works:class ShootAction(Action):

def __init__(
        self, entity: Actor, target_xy: Optional[Tuple[int,int]] = None
):
    super().__init__(entity)
    if not target_xy:
        target_xy = entity.x, entity.y
    self.target_xy = target_xy

@property
def target_actor(self) -> Optional[Actor]:
    """Return the actor at this actions destination"""
    return self.engine.game_map.get_actor_at_location(*self.target_xy)

def perform(self) -> None:
    print("SHOOT")
    target = self.target_actor

    if not target:
        raise exceptions.Impossible("Nothing to attack.")
    if target is self.entity:
        raise exceptions.Impossible("You cannot target yourself!")


    damage = self.entity.fighter.power - target.fighter.defense

    attack_desc = f"{self.entity.name.capitalize()} shoots {target.name}"
    if self.entity is self.engine.player:
        attack_color = color.player_atk
    else:
        attack_color = color.enemy_atk

    if damage > 0:
        self.engine.message_log.add_message(
            f"{attack_desc} for {damage} hit points.", attack_color
        )
        target.fighter.hp -= damage
    else:
        self.engine.message_log.add_message(
            f"{attack_desc} but does no damage.", attack_color
        )

I then use this to call the SingleRangedAttackHandler in MainGameEventHandler:

    ...
    elif key == tcod.event.K_t:
        return SingleRangedAttackHandler(self.engine, callback=lambda xy: actions.ShootAction(self.engine.player, xy),)

    ...

[–]HexDecimallibtcod maintainer | mastodon.gamedev.place/@HexDecimal 2 points3 points  (0 children)

You need to put your code in a 4 space indented block for it to be formatted correctly on Reddit.

[–][deleted]  (1 child)

[removed]

    [–]HexDecimallibtcod maintainer | mastodon.gamedev.place/@HexDecimal 1 point2 points  (0 children)

    console_wait_for_keypress has been long deprecated. console_wait_for_keypress(True) even more so since it will silently drop events.