def equip(self, no_message=False): if self.is_equipped: return # already equipped old_equipment = None if self.slot == 'ring': rings = main.get_equipped_in_slot(self.holder.fighter.inventory, self.slot) if len(rings) >= 2: options_ex = collections.OrderedDict() options_ex['a'] = {'option': {'text': rings[0].name}} options_ex['b'] = {'option': {'text': rings[1].name}} index = ui.menu_ex("Unequip which ring?", options_ex, 40, return_as_char=True) old_equipment = rings[ord(index) - ord('a')].equipment else: old_equipment = main.get_equipped_in_slot( self.holder.fighter.inventory, self.slot) # First check weight if self.holder is player.instance: old_weight = 0 if old_equipment is not None: old_weight = old_equipment.weight if self.holder.fighter.equip_weight + self.weight - old_weight > self.holder.fighter.max_equip_weight: ui.message('That is too heavy.', libtcod.orange) return # Attempt to dequip if self.slot == 'both hands': rh = main.get_equipped_in_slot(self.holder.fighter.inventory, 'right hand') lh = main.get_equipped_in_slot(self.holder.fighter.inventory, 'left hand') if not ((rh is None or rh.dequip() != 'cancelled') and (lh is None or lh.dequip() != 'cancelled')): return 'cancelled' else: if old_equipment is not None: if old_equipment.dequip(self.holder) == 'cancelled': return 'cancelled' self.is_equipped = True if self.holder is player.instance and not no_message: ui.message('Equipped ' + self.owner.name + '.', libtcod.orange) if self.status_effect is not None and self.holder.fighter is not None: self.holder.fighter.apply_status_effect(self.status_effect(None)) if self.category == 'book' and self.holder == player.instance: for spell, level in self.get_active_spells().items(): if self.spell_charges[spell] < spells.library[ spell].max_spell_charges(level): player.instance.fighter.apply_status_effect( effects.meditate()) break return 'success'
def ranged_attack(actor, target, context): spent = actor.fighter.adjust_ammo(-1) if spent != 0 and actor.fighter is not None: weapon = main.get_equipped_in_slot(actor.fighter.inventory, 'right hand') ui.render_projectile((actor.x, actor.y), (target.x, target.y), libtcod.white) result = combat.attack_ex(actor.fighter, target, 0, verb=("shoot", "shoots"), weapon=weapon, ranged=True) if result == 'failed': actor.fighter.adjust_ammo(-spent, False) # Refund ammo return 'didnt-take-turn' if result == 'miss' or target.fighter is None: # ammo lands on the ground main.drop_ammo(target.x, target.y, -spent) else: # target was hit, ammo sticks in them if hasattr(target, 'recoverable_ammo'): target.recoverable_ammo += -spent else: target.recoverable_ammo = -spent else: return 'didnt-take-turn'
def disarm(target): if target is None or target.fighter is None: return 'failure' weapon = main.get_equipped_in_slot(target.fighter.inventory, 'right hand') if weapon is None: return 'failure' weapon.dequip(no_message=True) possible_tiles = [] for x in range(target.x - 1, target.x + 2): for y in range(target.y - 1, target.y + 2): if not main.is_blocked( x, y, from_coord=(target.x, target.y), movement_type=1): possible_tiles.append((x, y)) if len(possible_tiles) == 0: selected_tile = main.find_closest_open_tile(target.x, target.y) else: selected_tile = possible_tiles[libtcod.random_get_int( 0, 0, len(possible_tiles) - 1)] weapon.owner.item.drop(no_message=True) weapon.owner.x = selected_tile[0] weapon.owner.y = selected_tile[1] ui.message( '%s %s disarmed!' % (syntax.name(target).capitalize(), syntax.conjugate(target is player.instance, ('are', 'is'))), libtcod.red) return 'success'
def pickaxe_dig(dx, dy): result = common.dig(player.instance.x + dx, player.instance.y + dy) if result == 'failed': ui.message('You cannot dig there.', libtcod.orange) else: item = main.get_equipped_in_slot(player.instance.fighter.inventory, 'right hand') if item is not None: main.check_breakage(item)
def summon_equipment(actor, item): if actor is player.instance and len( player.instance.fighter.inventory) >= 26: ui.message('You are carrying too many items to summon another.') return 'didnt-take-turn' summoned_equipment = main.create_item(item, material='', quality='') if summoned_equipment is None: return expire_ticker = main.Ticker(15, summon_equipment_on_tick) equipped_item = None expire_ticker.old_left = None if summoned_equipment.equipment.slot == 'both hands': equipped_item = main.get_equipped_in_slot(actor.fighter.inventory, 'right hand') expire_ticker.old_left = main.get_equipped_in_slot( actor.fighter.inventory, 'left hand') elif summoned_equipment.equipment.slot == 'floating shield': #can't stack two shields equipped_item = actor.fighter.get_equipped_shield() else: equipped_item = main.get_equipped_in_slot( actor.fighter.inventory, summoned_equipment.equipment.slot) expire_ticker.old_equipment = equipped_item if equipped_item is not None: equipped_item.dequip() summoned_equipment.item.pick_up(actor, True) expire_ticker.equipment = summoned_equipment effect = effects.StatusEffect('summoned equipment', expire_ticker.max_ticks + 1, summoned_equipment.color) actor.fighter.apply_status_effect(effect) expire_ticker.effect = effect expire_ticker.owner = actor main.current_map.tickers.append(expire_ticker) if actor is player.instance: ui.message("A {} appears!".format(summoned_equipment.name), libtcod.white) return 'success'
def bow_shot(actor, target, context): weapon = main.get_equipped_in_slot(actor.fighter.inventory, 'right hand') ui.render_projectile((actor.x, actor.y), (target.x, target.y), libtcod.white) combat.attack_ex(actor.fighter, target, 0, verb=("shoot", "shoots"), weapon=weapon, ranged=True)
def sweep_attack(actor, target, context): weapon = main.get_equipped_in_slot(actor.fighter.inventory, 'right hand') if weapon is None or weapon.subtype != 'polearm': ui.message('You need a polearm to use this ability') return 'didnt-take-turn' targets = main.get_objects(actor.x,actor.y,distance=2, condition=lambda o: o.fighter is not None and o.fighter.team != 'ally') targets = [t for t in targets if (abs(t.x - actor.x) == 2 or abs(t.y - actor.y) == 2)] if len(targets) > 0: for enemy in targets: combat.attack_ex(actor.fighter,enemy,0, verb=('sweep','sweeps')) actor.fighter.adjust_stamina(-(weapon.stamina_cost * context['stamina_multiplier'])) return True else: ui.message('There are no targets in range') return 'didnt-take-turn'
def mace_stun(attacker, target, damage): scaling_factor = 1 stun_duration = 1 if target.fighter is None: return if (attacker is player.instance): scaling_factor = attacker.player_stats.str / 10 if main.has_skill('ringing_blows'): scaling_factor *= 1.5 stun_duration = 2 if libtcod.random_get_float(0, 0.0, 1.0) * scaling_factor > 0.85: if attacker == player.instance: ui.message( "Your " + main.get_equipped_in_slot(player.instance.fighter.inventory, 'right hand').owner.name.title() + " rings out!", libtcod.blue) target.fighter.apply_status_effect(effects.stunned(stun_duration))
def boomerang(actor, target, context): sprites = ['<', 'v', '>', '^'] ui.render_projectile((actor.x, actor.y), (target.x, target.y), libtcod.yellow, sprites) attack_result = actor.fighter.attack(target) if attack_result == 'failed': return 'didnt-take-turn' catch_skill = 30 if actor.player_stats: catch_skill = actor.player_stats.agi if main.roll_dice('1d' + str(catch_skill)) >= 10: #catch boomerang ui.render_projectile((target.x, target.y), (actor.x, actor.y), libtcod.yellow, sprites) if actor is player.instance: ui.message('You catch the boomerang as it returns to you', libtcod.gray) else: possible_tiles = [] for y in range(actor.y - 2, actor.y + 2): for x in range(actor.x - 2, actor.x + 2): if x >= 0 and y >= 0 and x < consts.MAP_WIDTH and y < consts.MAP_HEIGHT and not main.is_blocked( x, y): possible_tiles.append((x, y)) if len(possible_tiles) == 0: selected_tile = main.find_closest_open_tile(target.x, target.y) else: selected_tile = possible_tiles[libtcod.random_get_int( 0, 0, len(possible_tiles) - 1)] ui.render_projectile((target.x, target.y), (selected_tile[0], selected_tile[1]), libtcod.yellow, sprites) weapon = main.get_equipped_in_slot(actor.fighter.inventory, 'right hand') weapon.owner.item.drop(no_message=True) weapon.owner.x = selected_tile[0] weapon.owner.y = selected_tile[1] if actor is player.instance or fov.player_can_see(actor.x, actor.y): ui.message( '%s boomerang falls to the ground.' % syntax.name(target, possesive=True).capitalize(), libtcod.gray) libtcod.console_flush()
def invoke_ability(ability_key, actor, target_override=None, spell_context=None): import abilities if actor is None: raise Exception('Missing parameter: actor') info = abilities.data[ability_key] if info is None: raise Exception("Invalid action key: {}".format(ability_key)) function = info.get('function') if function is None: raise Exception("No function for action {}".format(ability_key)) if spell_context is not None: for key in spell_context.keys(): if spell_context[key] is not None: info[key] = spell_context[key] #info = dict(info.items() + spell_context.items()) if 'require_weapon' in info.keys(): weapon = main.get_equipped_in_slot(actor.fighter.inventory, 'right hand') if weapon is None or weapon.subtype != info['require_weapon']: ui.message( 'You need a {} to use this ability'.format( info['require_weapon']), libtcod.gray) return 'didnt-take-turn' if 'stamina_cost' in info.keys(): if actor is player.instance and actor.fighter.stamina < info[ 'stamina_cost']: ui.message("You don't have enough stamina to use that ability.", libtcod.gray) return 'didnt-take-turn' if 'cast_time' in info.keys(): pretargeted = False if info.get('warning', False): targets = _get_ability_target(actor, info, target_override) if targets is None: return 'didnt-take-turn' info['warning_particles'] = _spawn_warning(actor, targets) pretargeted = targets if 'pre_cast' in info.keys(): info['pre_cast'](actor, target_override) elif not info.get('suppress_cast_notif', False): ui.message_flush( syntax.conjugate( actor is player.instance, ['You begin', actor.name.capitalize() + ' begins']) + ' to cast ' + info['name']) delegate = lambda: _invoke_ability_continuation( info, actor, target_override, function, pretargeted=pretargeted) if actor is player.instance: player.delay(info['cast_time'], delegate, 'channel-spell') else: actor.behavior.behavior.queue_action(delegate, info['cast_time']) return 'success' else: return _invoke_ability_continuation(info, actor, target_override, function)
def vanguard_attack(actor,target): weapon = main.get_equipped_in_slot(actor.fighter.inventory, 'right hand') if weapon is not None and weapon.subtype == 'polearm': common.attack(actor,target)