예제 #1
0
    def clean_up(self, gameStateObj, metaDataObj):
        # Remove combat state
        gameStateObj.stateMachine.back()
        # Reset states if you're not using a solo skill
        if self.skill_used and self.skill_used.active and self.skill_used.active.mode == 'Solo':
            self.attacker.hasTraded = True # Can still attack, can't move
            self.attacker.hasAttacked = False
        else:
            self.attacker.hasAttacked = True
            if not self.attacker.has_canto_plus() and not self.event_combat:
                gameStateObj.stateMachine.changeState('wait') # Event combats do not cause unit to wait

        # Handle items that were used
        a_broke_item, d_broke_item = False, False
        if self.item.uses and self.item.uses.uses <= 0:
            a_broke_item = True
        if self.defender and self.defender.getMainWeapon() and self.defender.getMainWeapon().uses and self.defender.getMainWeapon().uses.uses <= 0:
            d_broke_item = True

        # Handle skills that were used
        if self.skill_used:
            self.skill_used.active.current_charge = 0
            self.skill_used.active.reverse_mod()

        # Create all_units list
        all_units = [unit for unit in self.splash] + [self.attacker]
        if self.defender: all_units += [self.defender]

        # Handle death
        for unit in all_units:
            if unit.currenthp <= 0:
                unit.isDying = True

        # === HANDLE STATE STACK ==
        # Handle where we go at very end
        if self.event_combat:
            gameStateObj.message[-1].current_state = "Processing"
        else:
            if self.attacker.team == 'player':
                if not self.attacker.hasAttacked:
                    gameStateObj.stateMachine.changeState('menu')
                elif self.attacker.has_canto_plus() and not self.attacker.isDying:
                    gameStateObj.stateMachine.changeState('move')
                else:
                    #self.attacker.wait()
                    gameStateObj.stateMachine.clear()
                    gameStateObj.stateMachine.changeState('free')
                    gameStateObj.stateMachine.changeState('wait')
            #else:
                #gameStateObj.stateMachine.changeState('ai')

        ### Handle interact_script
        interact_script = Dialogue.Dialogue_Scene('Data/Level' + str(gameStateObj.currentLevelIndex) + '/interactScript.txt', self.attacker, event_flag=False)
        gameStateObj.message.append(interact_script)
        gameStateObj.stateMachine.changeState('dialogue')

        # Handle miracle
        for unit in all_units:
            if unit.isDying:
                if any(status.miracle and (not status.count or status.count.count > 0) for status in unit.status_effects):
                    unit.handle_miracle(gameStateObj)

        ### Handle item gain
        for unit in all_units:
            if unit.isDying and isinstance(unit, UnitObject.UnitObject):
                for item in unit.items:
                    if item.droppable:
                        item.droppable = False
                        if unit in self.splash or unit is self.defender:
                            self.attacker.add_item(item)
                            gameStateObj.banners.append(MenuFunctions.acquiredItemBanner(self.attacker, item))
                            gameStateObj.stateMachine.changeState('itemgain')
                        elif self.defender:
                            self.defender.add_item(item)
                            gameStateObj.banners.append(MenuFunctions.acquiredItemBanner(self.defender, item))
                            gameStateObj.stateMachine.changeState('itemgain')

        ### Handle item loss
        if a_broke_item and self.attacker.team == 'player' and not self.attacker.isDying:
            gameStateObj.banners.append(MenuFunctions.brokenItemBanner(self.attacker, self.item))
            gameStateObj.stateMachine.changeState('itemgain')
        if d_broke_item and self.defender.team == 'player' and not self.defender.isDying:
            gameStateObj.banners.append(MenuFunctions.brokenItemBanner(self.defender, self.defender.getMainWeapon()))
            gameStateObj.stateMachine.changeState('itemgain')

        ### Handle exp and stat gain
        if not self.event_combat and (self.item.weapon or self.item.spell):
            if self.attacker.team == 'player' and not self.attacker.isDying and not 'Mindless' in self.attacker.tags and not self.attacker.isSummon():
                if any(result.attacker is self.attacker and result.outcome for result in self.old_results):
                    self.attacker.increase_wexp(self.item, gameStateObj)

                my_exp = 0
                for other_unit in self.splash + [self.defender]:
                    if any(result.attacker is self.attacker and result.defender is other_unit and result.outcome for result in self.old_results):
                        if self.item.exp:
                            normal_exp = self.item.exp
                        elif self.item.weapon or not self.attacker.checkIfAlly(self.defender):
                            level_diff = max(0, other_unit.level - self.attacker.level + 20)
                            normal_exp = int(CONSTANTS['exp_magnitude']*level_diff**CONSTANTS['exp_curve'])
                        elif self.item.spell:
                            normal_exp = 15
                        else:
                            normal_exp = 0
                        if other_unit.isDying:
                            self.attacker.total_kills += 1
                            my_exp += int(CONSTANTS['kill_multiplier']*normal_exp) + (40 if 'Boss' in other_unit.tags else 0)
                        else:
                            my_exp += normal_exp
                        logger.debug('Attacker gained %s exp', my_exp)

                # No free exp for affecting myself or being affected by allies
                if self.attacker.checkIfAlly(self.defender):
                    my_exp = Utility.clamp(my_exp, 0, 100)
                else:
                    my_exp = Utility.clamp(my_exp, 1, 100)

                gameStateObj.levelUpScreen.append(LevelUp.levelUpScreen(gameStateObj, unit=self.attacker, exp=my_exp)) #Also handles actually adding the exp to the unit
                gameStateObj.stateMachine.changeState('expgain')

            if self.defender.team == 'player' and not self.defender.isDying and not self.defender is self.attacker and not 'Mindless' in self.defender.tags and not self.defender.isSummon():
                if any(result.attacker is self.defender and result.outcome for result in self.old_results):
                    self.defender.increase_wexp(self.defender.getMainWeapon(), gameStateObj)

                my_exp = 0
                if any(result.attacker is self.defender and result.outcome for result in self.old_results):
                    level_diff = max(0, self.attacker.level - self.defender.level + 20)
                    normal_exp = max(0, int(CONSTANTS['exp_magnitude']*level_diff**CONSTANTS['exp_curve']))
                    if self.attacker.isDying:
                        self.defender.total_kills += 1
                        my_exp += int(CONSTANTS['kill_multiplier']*normal_exp) + (40 if 'Boss' in self.attacker.tags else 0)
                    else:
                        my_exp += normal_exp 

                # No free exp for affecting myself or being affected by allies
                if self.attacker.checkIfAlly(self.defender):
                    my_exp = Utility.clamp(my_exp, 0, 100)
                else:
                    my_exp = Utility.clamp(my_exp, 1, 100)

                gameStateObj.levelUpScreen.append(LevelUp.levelUpScreen(gameStateObj, unit=self.defender, exp=my_exp)) #Also handles actually adding the exp to the unit
                gameStateObj.stateMachine.changeState('expgain')

        # Handle after battle statuses
        for status in self.attacker.status_effects:
            if status.status_after_battle and not self.attacker.isDying:
                for unit in [self.defender] + self.splash:
                    if isinstance(unit, UnitObject.UnitObject) and self.attacker.checkIfEnemy(unit) and not unit.isDying:
                        applied_status = StatusObject.statusparser(status.status_after_battle)
                        StatusObject.HandleStatusAddition(applied_status, unit)
            if status.lost_on_attack and not self.attacker.isDying and (self.item.weapon or self.item.detrimental):
                StatusObject.HandleStatusRemoval(status, self.attacker)
        if self.defender:
            for status in self.defender.status_effects:
                if status.status_after_battle and self.defender.checkIfEnemy(self.attacker) and not self.defender.isDying and not self.attacker.isDying:
                    applied_status = StatusObject.statusparser(status.status_after_battle)
                    StatusObject.HandleStatusAddition(applied_status, self.attacker)

        # Handle death
        for unit in all_units:
            if unit.isDying:
                logger.debug('%s is dying.', unit.name)
                if isinstance(unit, TileObject.TileObject):
                    gameStateObj.map.destroy(unit, gameStateObj)
                else:
                    gameStateObj.stateMachine.changeState('dying')
                    gameStateObj.message.append(Dialogue.Dialogue_Scene(metaDataObj['death_quotes'], unit, event_flag=False))
                    gameStateObj.stateMachine.changeState('dialogue')

        ### Actually remove items
        if a_broke_item:
            self.attacker.remove_item(self.item)
        if d_broke_item:
            self.defender.remove_item(self.defender.getMainWeapon())