Beispiel #1
0
def command_ask_leave_loc(game):
    """
    Function that prompts player before actually leaving location
    :param game: a Game object
    """
    director = game_view.GameLoop.active_director
    flee = False
    text = _('Do you really want to leave this location?')
    for point in game_logic.circle_points(
            r=25, include_center=False):  # check for an enemy near player
        x = point[0] + game.player.position[0]
        y = point[1] + game.player.position[1]
        if game.current_loc.is_in_boundaries(x, y):
            if game.current_loc.cells[x][y].is_there_a(game_logic.Fighter):
                flee = True  # if there are an enemy - set flee flag on
                text += _(
                    '\n[color=red]WARNING: There are enemies nearby! If you choose to leave now, you will be chased, and probably lose some items while fleeing.'
                )
                break
    director.push_scene(
        game_view.MultiButtonMessageScene(buttons=[
            (_('Yes, head back to the camp.'), text,
             lambda g=game, f=flee: command_leave_loc(game=g, flee=f)),
            (_('No, stay here.'), text, None)
        ],
                                          title=_('Leaving location'),
                                          layout_options='intrinsic'))
Beispiel #2
0
def act_apply_timed_effect(action, register_call, target, effect, message_color):
    """ Applies an effect to target for ammount of time """
    if register_call:  # part executed when function is registered in ActionMgr
        target.effects.append(effect)  # apply effect
    else:  # part that is executed when action fires
        if target and effect in target.effects:  # if target still exists and effect too
            if isinstance(target, game_logic.Player):  # if Player was a target - inform about effect end
                game_logic.Game.add_message(message=
                                            _('{eff_name} effect fades away.').format(
                                                eff_name=_(effect.eff).replace('_', ' ').capitalize()),
                                            level='PLAYER', color=message_color)
            target.effects.remove(effect)  # remove effect
Beispiel #3
0
def command_player_dead(game):
    """ Command that is excutes if player dies """
    game_logic.Game.log.clear()
    director = game_view.GameLoop.active_director
    director.game = None
    del game
    director.push_scene(
        game_view.SingleButtonMessageScene(
            message=_('Horrors of the Desert City got you.'),
            title=_('You are dead.'),
            button_text=_('Return to main menu'),
            callback=lambda: command_return_to_main_menu(),
            layout_options='intrinsic'))
Beispiel #4
0
 def react_remove_effect(self, reaction, event_data):
     """ Reaction, that removes effects """
     reaction_result = {'success': False, 'removed_effects_count': 0}  # result dict
     # if there will be different reaction targets - specify here
     target = self.owner  # default
     if reaction['effects_number'] == 'all':  # if all effects has to be removed
         r = 0  # number of removed effects
         for effect in target.effects[:]:  # remove all such effects
             if effect.eff == reaction['effect'].eff:
                 target.effects.remove(effect)
                 r += 1
         if r > 0:  # if at least one effect removed - reaction successiful
             reaction_result['success'] = True
             reaction_result['removed_effects_count'] = r
         if isinstance(target, game_logic.Player):  # if player uses - inform him of effect
             game_logic.Game.add_message(message=
                 _('{ability_name}: removed all {eff_name} effects.').format(
                     ability_name=_(self.name).capitalize(),
                     eff_name=_(reaction['effect'].eff).upper()),
                 level='PLAYER', color=self.message_color)
     else:  # if specific number of effects has to be removed
         # choose needed effects
         needed_effects = [e for e in target.effects if e.eff == reaction['effect'].eff]
         if len(needed_effects) > 0:  # if there are
             r = 0  # number of removed effects
             # if effects to be removed number less than present effects
             if len(needed_effects) < reaction['effects_number']:
                 # remove random effects
                 for effect in random.sample(needed_effects, reaction['effects_number']):
                     target.effects.remove(effect)
                     r += 1
                 if isinstance(target, game_logic.Player):  # if player uses - inform him of effect
                     game_logic.Game.add_message(message=
                         _('{ability_name}: removed {eff_number} {eff_name} effects.').format(
                             ability_name=_(self.name).capitalize(),
                             eff_number=str(len(needed_effects)),
                             eff_name=_(reaction['effect'].eff).upper()),
                         level='PLAYER', color=self.message_color)
             else:  # if not
                 for effect in target.effects[:]:  # remove all such effects
                     if effect.eff == reaction['effect'].eff:
                         target.effects.remove(effect)
                         r += 1
                 if isinstance(target, game_logic.Player):  # if player uses - inform him of effect
                     game_logic.Game.add_message(message=
                         _('{ability_name}: removed all {eff_name} effects.').format(
                             ability_name=_(self.name).capitalize(),
                             eff_name=_(reaction['effect'].eff).upper()),
                         level='PLAYER', color=self.message_color)
             if r > 0:  # if at least one effect removed - reaction successiful
                 reaction_result['success'] = True
                 reaction_result['removed_effects_count'] = r
     return reaction_result
Beispiel #5
0
 def react_deal_damage(self, reaction, event_data):
     """ Reaction, that deals damage """
     reaction_result = {'success': False, 'damage': 0, 'target': None}  # reaction result dict
     if 'strike_type' in reaction:  # determine strike type
         strike_type = reaction['strike_type']
     else:
         strike_type = 'default'
     strike = game_logic.Strike(strike_type=strike_type, damage=reaction['damage'], dmg_type=reaction['dmg_type'])
     if reaction['target'] == 'projectile_hit_entity':  # if target is hit by projectile
         target = event_data['target']
         attacker = event_data['attacker']
     elif reaction['target'] == 'mover':  # if target is mover
         target = event_data['entity']
         attacker = self.owner
     else:  # default target and attacker
         target = event_data['target']
         attacker = self.owner
     if isinstance(target, game_logic.BattleEntity):  # if target is a damageable BE
         damage_dealt = attacker.land_strike(strike=strike, target=target)  # land strike
         game_logic.Game.add_message(message=
             _('{ability_name}: {target_name} takes {damage} {dmg_type} damage!').format(ability_name=_(self.name),
                                                                                         target_name=str(target),
                                                                                         damage=str(damage_dealt),
                                                                                         dmg_type=
                                                                                         _(reaction['dmg_type'])),
             level='PLAYER', color=self.message_color)
         reaction_result['damage'] = damage_dealt
         reaction_result['target'] = target
         if damage_dealt > 0:
             reaction_result['success'] = True
     else:  # tried to deal damage to not BattleEntity
         game_logic.Game.add_message(
             self.name + ': attempted to deal damage to not BE.',
             'DEBUG', self.message_color)
     return reaction_result
Beispiel #6
0
 def description(self):
     kwargs = self.properties
     if self.eff in eff_descriptions:
         descr = eff_descriptions[self.eff]
     else:
         descr = self.eff
     return _(descr).format(magn=str(self.magnitude), **kwargs)
Beispiel #7
0
def act_pick_up_item(action, register_call, actor, item):
    """ Actor pick up item action """
    if register_call:  # part executed when function is registered in ActionMgr
        action.t_needed = actor.speed / 4  # pick up action is 1/4 speed
    else:  # part that is executed when action fires
        if isinstance(actor, game_logic.Player):
            msg = _('You pick up {item}.').format(item=str(item))
            game_logic.Game.add_message(message=msg, level='PLAYER', color=[255, 255, 255])
        actor.add_item(item)  # pick up item
        actor.actions.remove(action)  # remove performed action from actor's list
        actor.state = 'ready'  # return actor to ready state
Beispiel #8
0
 def react_deal_periodic_damage(self, reaction, event_data):
     """ Reaction, that applies periodic damage """
     # if there will be different reaction targets - specify here
     target = event_data['target']  # default target and attacker
     attacker = event_data['attacker']
     self.owner.location.action_mgr.register_action(1, actions.act_deal_periodic_damage,
                                                    self.owner.location.action_mgr, target,
                                                    pickle.loads(pickle.dumps(reaction['effect'])),
                                                    reaction['damage'],
                                                    reaction['dmg_type'], reaction['period'],
                                                    reaction['whole_time'], self.message_color,
                                                    reaction['stackable'])
     # doing pickle copy of effect to make every stack separate
     if isinstance(attacker, game_logic.Player):  # if player applies - inform him of effect
         game_logic.Game.add_message(message=
             _('{target_name} is {eff_name}.').format(
                 target_name=str(target).capitalize(),
                 eff_name=_(reaction['effect'].eff).lower()),
             level='PLAYER', color=self.message_color)
     return {'success': True}  # PLACEHOLDER applying periodic damage is always successiful now
Beispiel #9
0
def command_reload(game, item):
    """ Command function for player wants to reload specific ranged weapon """
    director = game_view.GameLoop.active_director
    if isinstance(
            item,
            game_logic.ItemRangedWeapon):  # check if there is ranged weapon
        if len(item.ammo) < item.ammo_max:  # check if it is loaded
            # select appropriate ammo items
            ammos = [
                a for a in game.player.inventory
                if item.ammo_type in a.categories
            ]
            if ammos:
                if len(ammos) == 1:
                    game.player.perform(actions.act_reload, game.player, item,
                                        ammos[0])
                    game.start_update_thread()
                else:
                    director.push_scene(
                        game_view.AmmoItemSelectionScene(
                            items=ammos,
                            game=game,
                            ranged_weapon=item,
                            caption=_('Load ammo:'),
                            layout_options=LayoutOptions(top=0.30,
                                                         bottom=0.30,
                                                         left=0.30,
                                                         right=0.30)))
            else:
                game_logic.Game.add_message(
                    message=_('No {ammo_type} type ammunition.').format(
                        ammo_type=_(item.ammo_type)).capitalize(),
                    level='PLAYER',
                    color=[255, 255, 255])
        else:
            game_logic.Game.add_message(
                message=_('{item} is fully loaded.').format(
                    item=str(item)).capitalize(),
                level='PLAYER',
                color=[255, 255, 255])
Beispiel #10
0
 def react_apply_timed_effect(self, reaction, event_data):
     """ Reaction, that applies a timed effect """
     # if there will be different reaction targets - specify here
     target = self.owner  # default
     if reaction['target'] == 'projectile_hit_entity':
         target = event_data['target']
         if isinstance(event_data['attacker'], game_logic.Player):  # if player attacks - inform him of effect
             game_logic.Game.add_message(message=_('{ent_name} is now {eff_name}: {eff_descr} for {time} ticks.').
                                                                 format(ent_name=str(target), eff_name=
                                                                     _(reaction['effect'].eff).
                                                                     capitalize().replace('_', ' '),
                                                                     eff_descr=reaction['effect'].description,
                                                                     time=str(reaction['time'])),
                                         level='PLAYER', color=self.message_color)
     self.owner.location.action_mgr.register_action(reaction['time'], actions.act_apply_timed_effect,
                                                    target, reaction['effect'], self.message_color)
     if isinstance(target, game_logic.Player):  # if player uses - inform him of effect
         game_logic.Game.add_message(message=_('{eff_name}: {eff_descr} for {time} ticks.').format(eff_name=
                                                              _(reaction['effect'].eff).
                                                              capitalize().replace('_', ' '),
                                                              eff_descr=reaction['effect'].description,
                                                              time=str(reaction['time'])),
                                     level='PLAYER', color=self.message_color)
     if reaction['target'] == 'fired_ability_target':
         target = event_data['target']
         attacker = event_data['owner']
         try:
             attacker = event_data['owner'].launcher
         except AttributeError:
             pass
         if isinstance(attacker, game_logic.Player):  # if player attacks - inform him of effect
             game_logic.Game.add_message(message=_('{ent_name} is now {eff_name}: {eff_descr} for {time} ticks.').
                                         format(ent_name=str(target), eff_name=
             _(reaction['effect'].eff).
                                                capitalize().replace('_', ' '),
                                                eff_descr=reaction['effect'].description,
                                                time=str(reaction['time'])),
                                         level='PLAYER', color=self.message_color)
     self.owner.location.action_mgr.register_action(reaction['time'], actions.act_apply_timed_effect,
                                                    target, reaction['effect'], self.message_color)
     if isinstance(target, game_logic.Player):  # if player uses - inform him of effect
         game_logic.Game.add_message(message=_('{eff_name}: {eff_descr} for {time} ticks.').format(eff_name=
                                                                                                   _(reaction[
                                                                                                         'effect'].eff).
                                                                                                   capitalize().replace(
                                                                                                       '_', ' '),
                                                                                                   eff_descr=
                                                                                                   reaction[
                                                                                                       'effect'].description,
                                                                                                   time=str(reaction[
                                                                                                                'time'])),
                                     level='PLAYER', color=self.message_color)
     return {'success': True}  # PLACEHOLDER effect applying is always successiful now
Beispiel #11
0
def command_throw_choose(game, main_scene):
    """ Command function for player wants to throw an item in hands - choose target """
    right = game.player.equipment['RIGHT_HAND']
    left = game.player.equipment['LEFT_HAND']
    items = [i for i in [right, left]
             if i is not None]  # pick equipment in hands
    if items:  # check if there are any
        if len(items) == 1:  # if one
            if game.player.get_throw_range(items[0]) > 0:
                main_scene.start_targeting(
                    range=game.player.get_throw_range(items[0]),
                    t_object=items[0],
                    eligible_types=(game_logic.BattleEntity, 'point'),
                    callback=command_throw,
                    player=game.player,
                    item=items[0])
            else:
                game_logic.Game.add_message(message=_(
                    '{item} is too heavy!'.format(
                        item=str(items[0])).capitalize()),
                                            level='PLAYER',
                                            color=[255, 255, 255])
        else:  # if multiple items in hands
            main_scene.director.push_scene(
                game_view.ThrowItemSelectionScene(items=items,
                                                  game=game,
                                                  caption=_('Throw item:'),
                                                  layout_options=LayoutOptions(
                                                      top=0.30,
                                                      bottom=0.30,
                                                      left=0.30,
                                                      right=0.30)))
    else:
        game_logic.Game.add_message(
            message=_('Take something in hand to throw it.'),
            level='PLAYER',
            color=[255, 255, 255])
Beispiel #12
0
def command_fire_choose(game):
    """ Command function for player wants to fire ranged weapon - choose target """
    director = game_view.GameLoop.active_director
    ranged_weapons = [
        w for w in list(game.player.equipment.values())
        if isinstance(w, game_logic.ItemRangedWeapon)
    ]  # pick ranged weapons in equipment
    if ranged_weapons:  # check if there are any
        if len(ranged_weapons) == 1:  # if one
            if len(ranged_weapons[0].ammo) > 0:  # if it has ammo loaded
                director.main_game_scene.start_targeting(
                    range=ranged_weapons[0].range,
                    t_object=ranged_weapons[0],
                    eligible_types=(game_logic.BattleEntity, 'point'),
                    callback=command_fire,
                    player=game.player,
                    weapon=ranged_weapons[0])
            else:
                game_logic.Game.add_message(
                    message=_("{weapon} isn't loaded!").format(
                        weapon=str(ranged_weapons[0]).capitalize()),
                    level='PLAYER',
                    color=[255, 255, 255])
        else:  # if multiple ranged equipped
            director.push_scene(
                game_view.FireItemSelectionScene(items=ranged_weapons,
                                                 game=game,
                                                 caption=_('Fire weapon:'),
                                                 layout_options=LayoutOptions(
                                                     top=0.30,
                                                     bottom=0.30,
                                                     left=0.30,
                                                     right=0.30)))
    else:
        game_logic.Game.add_message(message=_('Equip ranged weapon to fire.'),
                                    level='PLAYER',
                                    color=[255, 255, 255])
Beispiel #13
0
def act_launch_projectile(action, register_call, projectile_type, launcher, target, message_color):
    """ Launches a projectile """
    if register_call:  # part executed when function is registered in ActionMgr
        pass  # nothing to do on action registration
    else:  # part that is executed when action fires
        if launcher and projectile_type:  # if all participants still exist
            # create new projectile copy
            projectile = dataset.get_entity(projectile_type, {'launcher': launcher,
                                                              'target': target})
            projectile.ai.owner = projectile  # set projectile ai component owner
            projectile.ai.target = target
            launcher.location.reg_entity(projectile)  # register projectile to location
            projectile.launch(launcher.position[0], launcher.position[1])
            game_logic.Game.add_message(message=
                                _('{launcher_name} launches a {projectile_name}!').format(
                                    launcher_name=str(launcher),
                                    projectile_name=str(projectile)),
                                level='PLAYER', color=message_color)
Beispiel #14
0
def command_execute_debug_line(line, game):
    """ Executes single debug command line """
    # unsafe, but will do for now
    director = game_view.GameLoop.active_director
    player = game.player
    loc = game.current_loc
    if game.player.position:
        x = game.player.position[0]
        y = game.player.position[1]
    try:
        exec(line, globals(), locals())
    except:
        game_logic.Game.add_message(
            message=_('Failed to execute line: {line}').format(
                line=line).capitalize(),
            level='DEBUG',
            color=[255, 0, 0])
        e = sys.exc_info()[0]
        print('WARNING! Failed to execute debug line: ' + line + '\n' + str(e))
Beispiel #15
0
def command_pick_up(game, dx, dy):
    """ Command function for player wants to pick up some items  """
    director = game_view.GameLoop.active_director
    player = game.player
    loc = game.current_loc
    x = player.position[0] + dx
    y = player.position[1] + dy
    if loc.is_in_boundaries(
            x, y):  # check if position of selected cell is in boundaries
        items = [
            i for i in loc.cells[x][y].entities
            if isinstance(i, game_logic.Item)
        ]  # select items in cell
        if items:  # check if there is an item
            if len(items) == 1:
                if isinstance(items[0], game_logic.ItemCharges) and\
                        'stackable' in items[0].categories and items[0].charges > 1:
                    director.push_scene(
                        game_view.NumberInputScene(
                            num_range=(1, items[0].charges),
                            num_start=items[0].charges,
                            title=str(items[0]),
                            callback=lambda text, item=items[0], game=game:
                            _split_stack_and_pick(text, item, game)))
                else:
                    player.perform(actions.act_pick_up_item, player, items[0])
            else:  # if there are multiple Items - ask which to pick up?
                director.push_scene(
                    game_view.PickUpItemSelectionScene(
                        items=items,
                        game=game,
                        caption=_('Pick up item:'),
                        layout_options=LayoutOptions(top=0.25,
                                                     bottom=0.25,
                                                     left=0.2,
                                                     right=0.2)))
Beispiel #16
0
def act_deal_periodic_damage(action, register_call, act_mgr, target, effect,
                             damage, dmg_type, period, whole_time, message_color, stackable=False):
    """ Periodically damages target while effect is on target """
    if register_call:  # part executed when function is registered in ActionMgr
        if stackable:  # if effect is stackable
            if effect in target.effects:  # if there is particularly this effect in
                pass  # do nothing, deal damage further
            else:
                act_mgr.register_action(whole_time, act_apply_timed_effect, target, effect, message_color)  # apply a new timed effect
                if isinstance(target, game_logic.Player):  # if Player was a target - inform about effect
                    game_logic.Game.add_message(message=
                                                _('{eff_name}!').format(eff_name=_(effect.eff)).capitalize(),
                                                level='PLAYER', color=message_color)
        else:  # if not stackable
            if effect in target.effects:  # if there is particularly this effect in
                pass  # do nothing, do damage further
            else:  # if no this effect, check for similar effects
                if target.get_effect(effect.eff) > 0:  # if there are such effect type
                    act_mgr.remove_action(action)  # stop action
                    return
                else:
                    act_mgr.register_action(whole_time, act_apply_timed_effect, target, effect, message_color)  # apply a new timed effect
                    if isinstance(target, game_logic.Player):  # if Player was a target - inform about effect
                        game_logic.Game.add_message(message=
                                                    _('{eff_name}!').format(eff_name=_(effect.eff)).capitalize(),
                                                    level='PLAYER', color=message_color)
        action.t_needed = period  # set needed time to 1 period of damage
    else:  # part that is executed when action fires
        if target and not target.dead:  # if target still exists
            if effect in target.effects:  # if effect still on target
                strike = game_logic.Strike(strike_type='periodic', damage=damage, dmg_type=dmg_type)
                damage_dealt = target.take_strike(strike=strike)  # strike
                if isinstance(target, game_logic.Player):  # if Player was a target - inform about effect
                    game_logic.Game.add_message(message=
                                                _('{eff_name}: {damage} damage.').format(
                                                    eff_name=_(effect.eff),
                                                    damage=str(damage_dealt)).capitalize(),
                                                level='PLAYER', color=message_color)
                act_mgr.register_action(whole_time, act_deal_periodic_damage, act_mgr, target, effect,
                                        damage, dmg_type, period, whole_time, message_color, stackable)  # apply next tick of damage
Beispiel #17
0
def command_leave_loc(game, flee=False):
    """
    Function to execute when player wants to leave location
    :param game: a Game object
    :param flee: flee flag - if fleeing, some penalties take place
    """
    director = game_view.GameLoop.active_director
    old_loc = game.current_loc
    player = game.player
    raid_report_text = ''
    # fleeing report section
    if flee:  # check if player is fleeing from enemies
        lost_items = []
        for item in player.inventory:
            if game_logic.weighted_choice([(True, 50), (False, 50)
                                           ]):  # lose some inventory items
                lost_items.append(item)
                player.discard_item(item=item)
        for item in [sl for sl in list(player.equipment.values())
                     if sl]:  # lose some equipped items
            if game_logic.weighted_choice([(True, 25), (False, 75)]):
                lost_items.append(item)
                player.unequip_item(item=item)
                player.discard_item(item=item)
        if len(lost_items) > 0:
            raid_report_text += _(
                'You fled from the enemies, but lost some items in the process:\n'
            )
            for item in lost_items:
                raid_report_text += _('{item}, ').format(item=str(item))
                del item
            raid_report_text = raid_report_text[:-2] + '.\n'  # a hack, replace last , with .\n
        else:
            raid_report_text += _(
                'You fled from the enemies and kept all of your items. Lucky!\n'
            )
    # treasures report section
    treasures = {}
    for item in player.inventory:
        if 'relic' in item.categories:  # if there'll be other types of treasure - add here
            if isinstance(item, game_logic.ItemCharges):
                count = item.charges
            else:
                count = 1
            if item.name in treasures:
                treasures[str(item)][0] += count
            else:
                treasures[str(item)] = [count, item.properties['value']]
    if len(treasures) > 0:
        raid_report_text += _('You obtained some treasures:\n\n')
        total = 0
        for tr in treasures.keys():
            raid_report_text += _(
                '{tr_name} x{tr_count} * {tr_value} = {tr_total}\n').format(
                    tr_name=tr,
                    tr_count=str(treasures[tr][0]),
                    tr_value=str(treasures[tr][1]),
                    tr_total=str(treasures[tr][0] * treasures[tr][1]))
            total += treasures[tr][0] * treasures[tr][1]
        raid_report_text += _('\nTotal treasures value: {total} coins.\n '
                              ).format(total=str(total))
    else:
        raid_report_text += _(
            'You escaped the City with nothing of value in your pockets. At least you managed to stay alive.\n'
        )
    # actual leaving location section
    player.location.remove_entity(player)
    player.effects.clear()  # simply clear list for now. Needs testing
    game.remove_location(old_loc)
    game.enter_camp()
    game.equipment_merchant.restock()
    director.pop_scene()
    director.push_scene(
        game_view.SingleButtonMessageScene(
            message=raid_report_text + '\n \n ',
            title=_('Successful raid.'),
            layout_options='intrinsic',
            close_on_esc=False,
            callback=lambda: (director.pop_scene(
            ), director.push_scene(game_view.CampMenuScene(game=game)))))