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())