Пример #1
0
    def __init__(self, sound_mixer):
        self.animation_loader_logger = LoggerMaster(
            self.__class__.__name__, LoggingLevelType.DEBUG.value)

        self.sound_mixer = sound_mixer
        self.sounds = dict()
        self.load_sound_sets()
Пример #2
0
class GameEngine:
    def __init__(self):
        self.run_game = True
        self.run_stage = True

        self.game_engine_logger = LoggerMaster(self.__class__.__name__,
                                               file_streamer=False,
                                               console_streamer=True)
        self.game_engine_logger.log_info_header(
            f'[ Starting {self.__class__.__name__} ]:')

        # Initializing Game Attributes, Sound Master, Animation Master
        self.game_attributes = GameAttributes()
        self.sound_master = SoundMaster()
        self.animation_master = AnimationMaster(self.game_attributes.surface)

        # Initializing Stage Initializer: This should call Stage Selector in the near future
        self.stage_initializer = StageInitializer(self.game_attributes,
                                                  self.animation_master,
                                                  self.sound_master)

    def run(self):
        while constants.globals.run_game:
            self.game_attributes.surface.fill(Color('Black'))
            self.stage_initializer.run_stage()
            event_controller.manage_events()
            display.update()
        quit()
    def __init__(self):
        self.animation_loader_logger = LoggerMaster(
            self.__class__.__name__, LoggingLevelType.DEBUG.value)

        self.environment_animation_sets = []
        self.unit_animation_sets = self.load_resource_sets(
            UNIT_ANIMATION_SETS, AnimationResourceType.UNITS.value)
        self.skill_animation_sets = self.load_resource_sets(
            SKILL_ANIMATION_SETS, AnimationResourceType.SKILLS.value)
Пример #4
0
    def __init__(self, player):
        self.experience_master_logger = LoggerMaster(
            'ExperienceMaster', LoggingLevelType.DEBUG.value)

        self.player = player
        self.experience = 0
        self.exp_level_break = 5

        self.experience_to_gain = 0
        self.previous_exp = 0
Пример #5
0
    def __init__(self):
        self.run_game = True
        self.run_stage = True

        self.game_engine_logger = LoggerMaster(self.__class__.__name__,
                                               file_streamer=False,
                                               console_streamer=True)
        self.game_engine_logger.log_info_header(
            f'[ Starting {self.__class__.__name__} ]:')

        # Initializing Game Attributes, Sound Master, Animation Master
        self.game_attributes = GameAttributes()
        self.sound_master = SoundMaster()
        self.animation_master = AnimationMaster(self.game_attributes.surface)

        # Initializing Stage Initializer: This should call Stage Selector in the near future
        self.stage_initializer = StageInitializer(self.game_attributes,
                                                  self.animation_master,
                                                  self.sound_master)
class StageTreeBuilder:
    def __init__(self):
        self.stage_tree_logger = LoggerMaster(__class__.__name__, level=LoggingLevelType.DEBUG.value)

    def roll_leaf_level_properties(self, stage_tree):
        pass

    def roll_node_level_properties(self, stage_tree, node_lvl):
        pass

    def build_tree(self, max_number_of_children):
        stage_tree = StageTree()
        self.stage_tree_logger.log_debug_header(f'[ {self.__class__.__name__} ]:'
                                                f' Building {stage_tree.__class__.__name__}')
        self.stage_tree_logger.log_debug_message()
        stage_root_node = stage_tree.add_node(root=True)
        self.build_branch(stage_tree, stage_root_node, max_number_of_children)
        return stage_tree

    def build_branch(self, stage_tree, parent_stage_node, max_number_of_children, diminishing=0):
        diminishing_list = [95, 75, 60, 20, 0]

        for child in range(0, max_number_of_children, 1):
            branch_chance = randint(1, 99) < diminishing_list[diminishing]
            if branch_chance:
                current_stage_node = stage_tree.add_node(parent_stage_node.node_lvl + 1, parent_stage_node.node_identifier)
                stage_tree.set_max_node_level(parent_stage_node.node_lvl + 1)
                self.stage_tree_logger.log_debug_message(f'[ {self.__class__.__name__} ]:'
                                                         f' Generate {current_stage_node.__class__.__name__}'
                                                         f' Parent Stage Level {parent_stage_node.node_lvl}'
                                                         f' Child Number {child}'
                                                         f' with {diminishing_list[diminishing]} diminishing'
                                                         f' CREATED')
                parent_stage_node.add_children(current_stage_node)
                self.build_branch(stage_tree, current_stage_node, max_number_of_children, diminishing + 1)
            else:
                self.stage_tree_logger.log_debug_message(f'[ {self.__class__.__name__} ]:'
                                                         f' Generate StageNode Parent Stage Level'
                                                         f' Parent Stage Level {parent_stage_node.node_lvl}'
                                                         f' Child Number {child}'
                                                         f' with {diminishing_list[diminishing]} diminishing'
                                                         f' FAILED')

    def build_node_properties(self):
        pass
Пример #7
0
class ExperienceMaster:
    def __init__(self, player):
        self.experience_master_logger = LoggerMaster(
            'ExperienceMaster', LoggingLevelType.DEBUG.value)

        self.player = player
        self.experience = 0
        self.exp_level_break = 5

        self.experience_to_gain = 0
        self.previous_exp = 0

    def next_experience_level_break(self):
        self.exp_level_break = round(self.exp_level_break * 1.3)
        self.experience_master_logger.log_debug_message(
            f'Next Level Break will be {self.exp_level_break}')

    def has_enough_experience(self):
        return self.experience >= self.exp_level_break

    def gain_experience(self):
        self.experience += self.experience_to_gain
        self.experience_to_gain = 0
        if self.has_enough_experience():
            self.experience_master_logger.log_debug_message(
                f'Player Has Enough Experience to Level Up')
            self.level_up()
            self.experience_master_logger.log_debug_message(
                f'Player Has {self.experience} Left')
            self.gain_experience()

    def level_up(self):
        strength_raise = randint(2, 3)
        dexterity_raise = randint(1, 2)
        magic_raise = randint(1, 3)
        vitality_raise = randint(2, 4)
        resilience_raise = randint(1, 2)
        luck_raise = randint(1, 2)

        self.level_up_stats(strength_raise, dexterity_raise, magic_raise,
                            vitality_raise, resilience_raise, luck_raise)

        self.previous_exp = self.experience
        self.experience = self.previous_exp - self.exp_level_break
        self.next_experience_level_break()
        self.player.level += 1

    def level_up_stats(self, strength_raise, dexterity_raise, magic_raise,
                       vitality_raise, resilience_raise, luck_raise):
        self.player.strength += strength_raise
        self.player.dexterity += dexterity_raise
        self.player.magic += magic_raise
        self.player.vitality += vitality_raise
        self.player.resilience += resilience_raise
        self.player.luck += luck_raise

        # This will be used when changing equipment to recover the raw value for the hero.
        self.player.raw_strength += strength_raise
        self.player.raw_dexterity += dexterity_raise
        self.player.raw_magic += magic_raise
        self.player.raw_vitality += vitality_raise
        self.player.raw_resilience += resilience_raise
        self.player.raw_luck += luck_raise

        self.player.attack_power = self.player.strength * 1
        self.player.attack_rating = self.player.dexterity * 1
        self.player.magic_power = self.player.magic * 1

        # calculate max hp and max mp
        self.player.max_hp = self.player.vitality * 3
        self.player.current_hp = self.player.current_hp + vitality_raise * 3
        self.player.max_mp = self.player.magic * 2 + self.player.resilience
        self.player.current_mp = self.player.current_mp + magic_raise * 2 + resilience_raise

        self.player.re_calculate_hero_stats()

    def evaluate_kill(self, target, text_sprite):
        if not target.alive:
            self.experience_to_gain += target.level
            damage_text.cast(self.player, "+EXP!", text_sprite)
            self.experience_master_logger.log_debug_message(
                f'Player Kills {target.__class__.__name__} '
                f'and Gains +{target.level} XP')

    def evaluate_group_kill(self, target_list, pre_target_list,
                            post_target_list, text_sprite):
        for index, target_unit in enumerate(post_target_list):
            if pre_target_list[index] is True and post_target_list[
                    index] is False:
                self.experience_to_gain += target_list[index].level
                self.experience_master_logger.log_debug_message(
                    f'Player Kills {target_list[index].__class__.__name__} '
                    f'and Gains +{target_list[index].level} XP')
                damage_text.cast(self.player, "+EXP!", text_sprite)
 def __init__(self):
     self.stage_tree_logger = LoggerMaster(__class__.__name__, level=LoggingLevelType.DEBUG.value)
class AnimationLoader:
    def __init__(self):
        self.animation_loader_logger = LoggerMaster(
            self.__class__.__name__, LoggingLevelType.DEBUG.value)

        self.environment_animation_sets = []
        self.unit_animation_sets = self.load_resource_sets(
            UNIT_ANIMATION_SETS, AnimationResourceType.UNITS.value)
        self.skill_animation_sets = self.load_resource_sets(
            SKILL_ANIMATION_SETS, AnimationResourceType.SKILLS.value)

    def get_skill_resource_animation_set(self, resource_type):
        return self.skill_animation_sets[resource_type]

    def get_unit_resource_animation_set(self, resource_type):
        return self.unit_animation_sets[resource_type]

    @staticmethod
    def generate_animation_callback(index):
        return lambda animation_set: (animation_set.set_action(index),
                                      animation_set.reset_frame_index())

    def load_resource_sets(self, animation_pool, resource_type):
        self.animation_loader_logger.log_debug_header(
            f'[ Loading {resource_type.title()} Animation Resources ]:')
        animation_sets = dict()
        # For Each AnimationSet present in AnimationSets: Environment, Skills, Units
        for animation_set_type in animation_pool:
            animation_set = []
            animation_set_callbacks = dict()
            # Load Each Animation Resource present in the Animation to be displayed
            self.animation_loader_logger.log_debug_message()
            self.animation_loader_logger.log_debug_message(
                f'Animation Resource Type: {animation_set_type.value}')
            self.animation_loader_logger.log_debug_message('------' * 10)
            for index, animation_resource in enumerate(
                    animation_pool[animation_set_type]):
                animation_set_callbacks[
                    animation_resource.animation_type.
                    value] = self.generate_animation_callback(index)
                # Load: Sequence Animations using Path to Resources
                self.animation_loader_logger.log_debug_message(
                    f'Animation Resource: {animation_resource.animation_type.value}'
                )
                animation_set.append(
                    self.load_resource_sequence(
                        resource_type, animation_set_type.value,
                        animation_resource.animation_type,
                        animation_resource.frames, animation_resource.scale_x,
                        animation_resource.scale_y))

            animation_sets[animation_set_type.value +
                           'CallBacks'] = animation_set_callbacks
            animation_sets[animation_set_type.value] = animation_set

        self.animation_loader_logger.log_debug_message()
        self.animation_loader_logger.log_debug_message('Done.')
        return animation_sets

    def load_resource_sequence(self, resource_type, name, animation,
                               sequence_length, x_scale, y_scale):
        # Load: Unit Animation Sequence based on Resource Type
        animation_sequence = []
        for index in range(sequence_length):
            animation_sequence.append(
                self.load_resource(resource_type, name, animation.value, index,
                                   x_scale, y_scale))
        return animation_sequence

    def load_resource(self, resource_type, unit_type, value, index, x_scale,
                      y_scale):
        image_path = f"resources/animation/{resource_type}/{unit_type.lower()}/sprites/{value}/{index}.png"
        self.animation_loader_logger.log_debug_message('> ' + image_path)
        loaded_image = image.load(image_path)
        normalized_image = transform.scale(
            loaded_image, (round(loaded_image.get_width() * x_scale),
                           round(loaded_image.get_height() * y_scale)))
        return normalized_image
Пример #10
0
 def __init__(self, sound_master):
     self.combat_resolver_logger = LoggerMaster(
         'CombatResolver', LoggingLevelType.DEBUG.value)
     self.sound_master = sound_master
Пример #11
0
class CombatResolver:
    def __init__(self, sound_master):
        self.combat_resolver_logger = LoggerMaster(
            'CombatResolver', LoggingLevelType.DEBUG.value)
        self.sound_master = sound_master

    def resolve_attack(self,
                       caster,
                       target,
                       input_damage,
                       input_type,
                       text_sprite,
                       multi_strike=False):
        if not multi_strike:
            constants.globals.action_cooldown = 0

        self.combat_resolver_logger.log_debug_message(
            f'Caster {caster.__class__.__name__} performs Attack, '
            f'Target {target.__class__.__name__} '
            f'receives {input_type.value.title()} '
            f'for {input_damage}')

        # Activates Block Animation & Sound on the current Target
        if input_type is CombatTypeResolution.BLOCKED:
            target.use_animation('Block')
            self.sound_master.play_unit_fx_sound('block')

        # Activates Miss Animation & Sound on the current Target
        elif input_type is CombatTypeResolution.MISS:
            target.use_animation('Miss')
            self.sound_master.play_unit_fx_sound('miss')

        # Activates Hurt/Death Animation and Sound on the current Target
        else:
            if input_damage != 0:
                target.use_animation('Hurt')

                # Activates Critical Hit Sound
                if input_type is CombatTypeResolution.CRITICAL_HIT:
                    self.sound_master.play_unit_fx_sound('critical_hit')
                else:
                    self.sound_master.play_unit_fx_sound('hit_cut')

                # Updates current Target Health
                target.reduce_health(input_damage)

                if target.has_fury():
                    # Updates current Target Fury, Saves Previous for Sound Effect Condition
                    previous_fury = target.current_fury
                    target.gain_fury(input_damage)

                    # Only Play Sound of Ultimate Up if player reaches 50
                    if previous_fury < 50 and target.current_fury >= 50:
                        self.sound_master.play_unit_fx_sound('ultimate_up')
                    elif previous_fury < target.max_fury and target.current_fury == target.max_fury:
                        self.sound_master.play_unit_fx_sound('ultimate_up')

                # TODO Activates hurt sound
                # Evaluate Death: Target
                if target.is_dead():
                    self.combat_resolver_logger.log_debug_message(
                        f'Target {target.__class__.__name__} Dies')
                    target.death()
                    target.use_animation('Death')
                    constants.globals.clicked = False
                    if caster.has_experience():
                        caster.evaluate_kill(target, text_sprite)

        combat_text_resolver.resolve(target, input_damage, input_type,
                                     text_sprite)

    def resolve_aoe_attack(self, caster, target_list, input_damage_list,
                           input_damage_type_list, text_sprite):
        for index, target in enumerate(target_list):
            if target.alive:
                self.resolve_attack(caster, target, input_damage_list[index],
                                    input_damage_type_list[index], text_sprite,
                                    True)

    def resolve_multi_attack(self, caster, target_list, multi_strike,
                             text_sprite):
        alive_enemy = get_alive_targets(target_list)

        # TODO: pass de proper wait time instead of 90
        if self.multi_attacks_left >= 0:
            if constants.globals.action_cooldown >= 90:
                if len(alive_enemy) > 0:
                    target = alive_enemy[randint(0, len(alive_enemy) - 1)]
                    caster.use_animation('Attack')
                    caster.cast_attack(self, target, text_sprite, True)

                    self.multi_attacks_left -= 1
                    constants.globals.action_cooldown = 65

        else:
            self.multi_attacks_left = 7
            caster.ultimate_status = False
            # Action Delay: Next Enemy Action will be delayed after the ultimate cast
            constants.globals.action_cooldown = -40

    def resolve_fixed_damage_attack(self, target, input_damage, input_type,
                                    text_sprite):
        target.use_animation('Hurt')
        self.sound_master.play_unit_fx_sound('hit_cut')

        target.reduce_health(input_damage)

        if target.has_fury():
            target.gain_fury(input_damage)
            if target.has_enough_fury(50) or target.has_enough_fury():
                self.sound_master.play_unit_fx_sound('ultimate_up')

        if target.is_dead():
            target.death()
            target.use_animation('Death')
            constants.globals.clicked = False

        combat_text_resolver.resolve(target, input_damage, input_type,
                                     text_sprite)
Пример #12
0
class SoundLoader:
    def __init__(self, sound_mixer):
        self.animation_loader_logger = LoggerMaster(
            self.__class__.__name__, LoggingLevelType.DEBUG.value)

        self.sound_mixer = sound_mixer
        self.sounds = dict()
        self.load_sound_sets()

    def load_sound_sets(self):
        self.animation_loader_logger.log_debug_header(
            '[ Loading Sound Resources ]:')
        sound_type = dict()
        # For Each AnimationSet present in AnimationSets: Environment, Skills, Units
        for sound_resource_type in SOUND_POOL:
            sound_subtype = dict()
            self.animation_loader_logger.log_debug_message()
            self.animation_loader_logger.log_debug_message(
                f'Sound Type: {sound_resource_type.value}')
            self.animation_loader_logger.log_debug_message('------' * 10)
            for index, sound_set in enumerate(SOUND_POOL[sound_resource_type]):
                sound_resource = dict()
                self.animation_loader_logger.log_debug_message(
                    f'Sound Sub Type: {sound_set.value}')
                for sound in SOUND_POOL[sound_resource_type][sound_set]:
                    sound_resource[sound.sound_name] = self.load_resource(
                        sound_resource_type.value, sound_set.value,
                        sound.sound_name, sound.file_extension, sound.volume)
                sound_subtype[sound_set.value.lower()] = sound_resource
            sound_type[sound_resource_type.value.lower()] = sound_subtype

        self.animation_loader_logger.log_debug_message()
        self.animation_loader_logger.log_debug_message('Done')
        self.sounds = sound_type

    def load_resource(self, resource_type, sound_set, sound_name,
                      sound_file_extension, sound_volume):
        sound_path = f'resources/sound/{resource_type.lower()}/{sound_set.lower()}/{sound_name.lower()}.{sound_file_extension.value}'
        self.animation_loader_logger.log_debug_message('> ' + sound_path)
        sound_resource = WrappedSound(sound_path)
        sound_resource.set_volume(sound_volume)
        return sound_resource
Пример #13
0
 def __init__(self, sound_master):
     self.loot_master_logger = LoggerMaster(self.__class__.__name__,
                                            LoggingLevelType.DEBUG.value)
     self.sound_master = sound_master
Пример #14
0
class LootMaster:
    def __init__(self, sound_master):
        self.loot_master_logger = LoggerMaster(self.__class__.__name__,
                                               LoggingLevelType.DEBUG.value)
        self.sound_master = sound_master

    def loot(self, caster, target, text_sprite):
        if type(target) is Bandit or type(target) is BoneWizard or type(
                target) is Lizard:
            self.roll_basic_loot(caster, target, text_sprite)
        elif type(target) is BanditChief or type(target) is SmallDragon \
                or type(target) is Djinn or type(target) is Dragon \
                or type(target) is Demon or type(target) is Medusa:
            self.roll_boss_loot(caster, target, text_sprite)

    def roll_basic_loot(self, caster, target, text_sprite):
        loot_chance = randint(0, 5)

        if not target.is_looted():
            if loot_chance == 0:
                self.sound_master.play_item_fx_sound('empty')
                damage_text.warning(target, f'Empty!', text_sprite)
                self.loot_master_logger.log_debug_message(
                    f'Player Loots {target.__class__.__name__} '
                    f'Receiving Nothing')

            elif loot_chance == 1:
                self.sound_master.play_item_fx_sound('health_potion')
                caster.stash.add_healing_potion(1)
                damage_text.warning(target, f'x1 Health Potion Found!',
                                    text_sprite)
                self.loot_master_logger.log_debug_message(
                    f'Player Loots {target.__class__.__name__} '
                    f'Receiving Health Potion')

            elif loot_chance == 2:
                self.sound_master.play_item_fx_sound('health_potion')
                caster.stash.add_mana_potion(1)
                damage_text.warning(target, f'x1 Mana Potion Found!',
                                    text_sprite)
                self.loot_master_logger.log_debug_message(
                    f'Player Loots {target.__class__.__name__} '
                    f'Receiving Mana Potion')

            elif loot_chance == 3:
                quality_roll = randint(0, 50)
                if quality_roll > target.level:
                    damage_text.warning(target, f'Food Found!', text_sprite)
                    BREAD.consume(caster, text_sprite)
                    self.sound_master.play_item_fx_sound('eat')
                    self.loot_master_logger.log_debug_message(
                        f'Player Loots {target.__class__.__name__} '
                        f'Receiving Bread')
                else:
                    damage_text.warning(target, f'Large Food Found!',
                                        text_sprite)
                    LARGE_BREAD.consume(caster, text_sprite)
                    self.sound_master.play_item_fx_sound('eat')
                    self.loot_master_logger.log_debug_message(
                        f'Player Loots {target.__class__.__name__} '
                        f'Receiving Large Bread')

            elif loot_chance == 4:
                quality_roll = randint(0, 50)
                if quality_roll > target.level:
                    damage_text.warning(target, f'Drink Found!', text_sprite)
                    DRINK.consume(caster, text_sprite)
                    self.sound_master.play_item_fx_sound('drink')
                    self.sound_master.play_item_fx_sound('eat')
                    self.loot_master_logger.log_debug_message(
                        f'Player Loots {target.__class__.__name__}'
                        f' Receiving Drink')
                else:
                    damage_text.warning(target, f'Large Drink Found!',
                                        text_sprite)
                    LARGE_DRINK.consume(caster, text_sprite)
                    self.sound_master.play_item_fx_sound('drink')
                    self.loot_master_logger.log_debug_message(
                        f'Player Loots {target.__class__.__name__}'
                        f' Receiving Large Drink')

            elif loot_chance == 5:
                gold = randint(1, 9) + target.level
                caster.stash.add_gold(gold)
                damage_text.cast(target, f'{gold} Gold Found!', text_sprite)
                self.sound_master.play_item_fx_sound('gold')
                self.loot_master_logger.log_debug_message(
                    f'Player Loots {target.__class__.__name__}'
                    f' Receiving {gold} Gold')

            target.update_looted_status()
        else:
            self.loot_error(target, text_sprite)

    def roll_boss_loot(self, caster, target, text_sprite):
        item_generator = EquipmentGenerator()
        if not target.is_looted():
            self.sound_master.play_item_fx_sound('drum_roll')
            # Todo: Proper setup for loot boss, based on level
            roll_item = item_generator.get_item(30, 1000)
            item_name = roll_item.get_item_name()
            damage_text.heal(target, f'{item_name}', text_sprite)
            self.loot_master_logger.log_debug_message(
                f'Player Loots {target.__class__.__name__}'
                f' Receiving {item_name.title()}')
            target.update_looted_status()

            # Note: Temporary Approach
            caster.backpack.add_item(roll_item)

        else:
            self.loot_error(target, text_sprite)
        caster.re_calculate_hero_stats()

    def loot_error(self, target, text_sprite):
        # Todo: Init with -30y
        damage_text.warning(target, f'ALREADY LOOTED!', text_sprite)
        self.sound_master.play_item_fx_sound('error')