# Path: combat/enums.py
# class DamageType(Enum):
#     Blunt = 0
#     Slash = 1
#     Pierce = 2
# 
# Path: stats/enums.py
# class StatsEnum(Enum):
#     Health = 'health'
#     Mana = 'mana'
#     Strength = 'strength'
#     Dexterity = 'dexterity'
#     Constitution = 'constitution'
#     Intelligence = 'intelligence'
#     Charisma = 'charisma'
#     Wisdom = 'wisdom'
#     Sharpness = 'sharpness'
#     Hardness = 'hardness'
#     Weight = 'weight'
#     Size = 'size'
#     Potency = 'potency'
#     MaxDamage = 'max_damage'
#     MinDamage = 'min_damage'
#     ArmorClass = 'armor_class'
# 
# Path: managers/echo.py
# class EchoService(object):
# class MessageVariables(Enum):
#     def __init__(self, console, game_context):
#     def combat_context_echo(self, message, attacker=None, defender=None,
#                             attacker_weapon=None, defender_weapon=None, defender_bodypart=None):
# def his_her_it(target, **kwargs):
# def him_her_it(target, **kwargs):
# def he_her_it(target, **kwargs):
# def name_or_you(target, **kwargs):
# 
# Path: util/check_roller.py
# def d20_check_roll(difficulty_class, modifiers=0, advantage=None):
# def roll_damage(dice_stacks, modifiers, critical=False):
# 
# Path: util/dice.py
# class DiceStack(object):
#     __slots__ = ['amount', 'dice']
# 
#     def __init__(self, amount, dice):
#         self.amount = amount
#         self.dice = dice
# 
# class Dice(object):
#     __slots__ = ['sides']
# 
#     def __init__(self, sides):
#         self.sides = sides


import abc
from combat.enums import DamageType
from stats.enums import StatsEnum
from managers import echo
from util import check_roller
from util.dice import DiceStack, Dice
from . import enums
            attacker=attacker,
            defender=defender,
            **kwargs
        )
        return attack_result

    def make_hit_roll(self, attacker, defender, **kwargs):
        target_ac = defender.get_armor_class()
        success, critical, natural_roll, total_hit_roll = check_roller.d20_check_roll(
            difficulty_class=target_ac,
            modifiers=self.get_hit_bonus(attacker)
        )
        return AttackResult(success, critical, defender, target_ac, natural_roll, total_hit_roll)

    def make_damage_roll(self, attacker, attack_result, **kwargs):
        total_damage = check_roller.roll_damage(
            dice_stacks=[self.get_damage_dice(**kwargs)],
            modifiers=self.get_damage_bonus(attacker, **kwargs),
            critical=attack_result.critical
        )
        attack_result.total_damage = total_damage
        attack_result.separated_damage = [(total_damage, self.get_damage_type(**kwargs))]

        return attack_result


class UnarmedAttackTemplate(AttackTemplate):
    # TODO I admit, this looks ugly.
    def __init__(self, name, description, message, basic_damage_dice=DiceStack(1, Dice(3)), bodypart_id_needed="humanoid_hand",
                 target_type=enums.TargetType.Single, attack_range=0, modifiers=None, hit_stat_used=StatsEnum.Strength,

# Path: combat/enums.py
# class DamageType(Enum):
#     Blunt = 0
#     Slash = 1
#     Pierce = 2
# 
# Path: stats/enums.py
# class StatsEnum(Enum):
#     Health = 'health'
#     Mana = 'mana'
#     Strength = 'strength'
#     Dexterity = 'dexterity'
#     Constitution = 'constitution'
#     Intelligence = 'intelligence'
#     Charisma = 'charisma'
#     Wisdom = 'wisdom'
#     Sharpness = 'sharpness'
#     Hardness = 'hardness'
#     Weight = 'weight'
#     Size = 'size'
#     Potency = 'potency'
#     MaxDamage = 'max_damage'
#     MinDamage = 'min_damage'
#     ArmorClass = 'armor_class'
# 
# Path: managers/echo.py
# class EchoService(object):
# class MessageVariables(Enum):
#     def __init__(self, console, game_context):
#     def combat_context_echo(self, message, attacker=None, defender=None,
#                             attacker_weapon=None, defender_weapon=None, defender_bodypart=None):
# def his_her_it(target, **kwargs):
# def him_her_it(target, **kwargs):
# def he_her_it(target, **kwargs):
# def name_or_you(target, **kwargs):
# 
# Path: util/check_roller.py
# def d20_check_roll(difficulty_class, modifiers=0, advantage=None):
# def roll_damage(dice_stacks, modifiers, critical=False):
# 
# Path: util/dice.py
# class DiceStack(object):
#     __slots__ = ['amount', 'dice']
# 
#     def __init__(self, amount, dice):
#         self.amount = amount
#         self.dice = dice
# 
# class Dice(object):
#     __slots__ = ['sides']
# 
#     def __init__(self, sides):
#         self.sides = sides


# Path: combat/attack.py
import abc
from combat.enums import DamageType
from stats.enums import StatsEnum
from managers import echo
from util import check_roller
from util.dice import DiceStack, Dice
from . import enums

            attacker=attacker,
            defender=defender,
            **kwargs
        )
        return attack_result

    def make_hit_roll(self, attacker, defender, **kwargs):
        target_ac = defender.get_armor_class()
        success, critical, natural_roll, total_hit_roll = check_roller.d20_check_roll(
            difficulty_class=target_ac,
            modifiers=self.get_hit_bonus(attacker)
        )
        return AttackResult(success, critical, defender, target_ac, natural_roll, total_hit_roll)

    def make_damage_roll(self, attacker, attack_result, **kwargs):
        total_damage = check_roller.roll_damage(
            dice_stacks=[self.get_damage_dice(**kwargs)],
            modifiers=self.get_damage_bonus(attacker, **kwargs),
            critical=attack_result.critical
        )
        attack_result.total_damage = total_damage
        attack_result.separated_damage = [(total_damage, self.get_damage_type(**kwargs))]

        return attack_result


class UnarmedAttackTemplate(AttackTemplate):
    # TODO I admit, this looks ugly.
    def __init__(self, name, description, message, basic_damage_dice=DiceStack(1, Dice(3)), bodypart_id_needed="humanoid_hand",
                 target_type=enums.TargetType.Single, attack_range=0, modifiers=None, hit_stat_used=StatsEnum.Strength,

                 damage_stat_used=StatsEnum.Strength, damage_type=enums.DamageType.Blunt, requirements=None):