def drawSlide(self, surf): mainSlideSurf = MenuFunctions.CreateBaseMenuSurf( (GC.WINWIDTH + 8, 6 * GC.WINHEIGHT / 10 + 8), 'ClearMenuBackground') surf.blit(mainSlideSurf, (0 - 4, GC.WINHEIGHT / 5)) if self.state.getState() == 'Config' or ( self.state.getState() == 'TopMenu' and self.currentSelection == 0): config_font = GC.FONT['text_blue'] controls_font = GC.FONT['text_grey'] else: config_font = GC.FONT['text_grey'] controls_font = GC.FONT['text_blue'] configSlideSurf = MenuFunctions.CreateBaseMenuSurf( (GC.WINWIDTH / 2 - 8, 24), 'ClearMenuBackground') surf.blit(configSlideSurf, (4, 4)) config_position = (4 + configSlideSurf.get_width() / 2 - config_font.size('Config')[0] / 2, 16 - config_font.size('Config')[1] / 2) config_font.blit(cf.WORDS['Config'], surf, config_position) controlsSlideSurf = MenuFunctions.CreateBaseMenuSurf( (GC.WINWIDTH / 2 - 8, 24), 'ClearMenuBackground') surf.blit(controlsSlideSurf, (GC.WINWIDTH / 2 + 4, 4)) controls_position = (GC.WINWIDTH / 2 + 4 + controlsSlideSurf.get_width() / 2 - controls_font.size('Controls')[0] / 2, 16 - controls_font.size('Controls')[1] / 2) controls_font.blit(cf.WORDS['Controls'], surf, controls_position)
def draw(self, gameStateObj, metaDataObj): mapSurf = StateMachine.State.draw(self, gameStateObj, metaDataObj) mapSurf.blit(GC.IMAGESDICT['DebugBackground'], (0, GC.WINHEIGHT - (5 * 16))) for idx, command in enumerate(reversed(commands[-self.num_back:])): # GC.FONT['text_blue'].blit(command, mapSurf, (0, GC.WINHEIGHT - idx * 16 - 32)) MenuFunctions.OutlineFont(GC.BASICFONT, command, mapSurf, GC.COLORDICT['off_white'], GC.COLORDICT['off_black'], (0, GC.WINHEIGHT - idx * 16 - 32)) # GC.FONT['text_blue'].blit(self.current_command, mapSurf, (0, GC.WINHEIGHT - 16)) MenuFunctions.OutlineFont(GC.BASICFONT, self.current_command, mapSurf, GC.COLORDICT['off_white'], GC.COLORDICT['off_black'], (0, GC.WINHEIGHT - 16)) return mapSurf
def create_help_box(self): if self.weapon or self.spell: font1 = GC.FONT['text_blue'] font2 = GC.FONT['text_yellow'] if self.weapon: first_line_text = [' ', self.weapon.LVL, ' Mt ', str(self.weapon.MT), ' Hit ', str(self.weapon.HIT)] if cf.CONSTANTS['crit']: first_line_text += [' Crit ', str(self.crit) if self.crit else '--'] if self.weight: first_line_text += [' Wt ', str(self.weight)] first_line_text += [' Rng ', self.strRNG] first_line_font = [font1, font1, font2, font1, font2, font1] if cf.CONSTANTS['crit']: first_line_font += [font2, font1] if self.weight: first_line_font += [font2, font1] first_line_font += [font2, font1] elif self.spell: first_line_text = [' ', self.spell.LVL] first_line_font = [font1, font1] if self.damage is not None: first_line_text += [' Mt ', str(self.damage)] first_line_font += [font2, font1] if self.hit is not None: first_line_text += [' Hit ', str(self.hit)] first_line_font += [font2, font1] if cf.CONSTANTS['crit'] and self.crit is not None: first_line_text += [' Crit ', str(self.crit)] first_line_font += [font2, font1] first_line_text += [' Rng ', self.strRNG] first_line_font += [font2, font1] first_line_length = max(font1.size(''.join(first_line_text))[0] + 16 * len(self.TYPE) + 4, 112) # 112 was 96 if self.desc: output_desc_lines = MenuFunctions.line_wrap(MenuFunctions.line_chunk(self.desc), first_line_length, GC.FONT['convo_black']) else: output_desc_lines = '' size_x = first_line_length + 16 size_y = 24 + len(output_desc_lines)*16 help_surf = MenuFunctions.CreateBaseMenuSurf((size_x, size_y), 'MessageWindowBackground') self.drawType(help_surf, 4, 4) # Actually blit first line word_index = 4 + 16 * len(self.TYPE) for index, word in enumerate(first_line_text): first_line_font[index].blit(word, help_surf, (word_index, 4)) word_index += first_line_font[index].size(word)[0] for index, line in enumerate(output_desc_lines): GC.FONT['convo_black'].blit(''.join(line), help_surf, (4, GC.FONT['convo_black'].height*index + 4 + 16)) return help_surf else: return InfoMenu.create_help_box(self.desc)
def begin(self, gameStateObj, metaDataObj): if not self.started: # Get units to display self.units = [unit for unit in gameStateObj.allunits if unit.position and unit.team == 'player'] self.bg_surf = Image_Modification.flickerImageTranslucent(GC.IMAGESDICT['UnitMenuBackground'], 10) self.title_bg = Image_Modification.flickerImageTranslucent(GC.IMAGESDICT['TitleBar'], 10) self.background = MenuFunctions.MovingBackground(GC.IMAGESDICT['RuneBackground']) self.states = [('Character', ['Class', 'Lv', 'Exp', 'HP', 'Max'], [4, 66, 89, 113, 133]), ('Fighting Skill', ['STR', 'MAG', 'SKL', 'SPD', 'LCK', 'DEF', 'RES'], [4, 26, 48, 71, 94, 119, 142]), ('Equipment', ['Equip', 'Atk', 'Hit', 'Avoid'], [16, 72, 103, 136]), ('Personal Data', ['MOV', 'CON', 'Aid', 'Rat', 'Trv'], [4, 33, 60, 82, 106]), ('Weapon Level', Weapons.TRIANGLE.types, [9 + idx*16 for idx in range(len(Weapons.TRIANGLE.types))])] if cf.CONSTANTS['support']: self.states.append(('Support Chance', ['Ally'], [0])) self.state_index = 0 self.prev_state_index = 0 self.unit_index = 1 # 0 means on banner self.scroll_index = 1 self.banner_index = 0 self.num_per_page = 6 self.state_scroll = 0 self.scroll_direction = 0 self.weapon_icons = [Weapons.Icon(weapon) for weapon in Weapons.TRIANGLE.types] self.help_boxes = [] self.info = False self.scroll_bar = GUIObjects.ScrollBar((233, 59)) self.left_arrow = GUIObjects.ScrollArrow('left', (7, 41)) self.right_arrow = GUIObjects.ScrollArrow('right', (GC.WINWIDTH - 7 - 8, 41), 0.5) # For sort self.current_sort = 'Name' self.descending = False self.sort_surf = MenuFunctions.CreateBaseMenuSurf((64, 24)) self.sort_surf = Image_Modification.flickerImageTranslucent(self.sort_surf, 10) self.sort_arrow_counter = Counters.ArrowCounter() self.sort_arrow_counter.arrow_anim = [0, 1, 2] self.sort() # Transition in: gameStateObj.stateMachine.changeState("transition_in") return 'repeat' else: chosen_unit = gameStateObj.info_menu_struct['chosen_unit'] if chosen_unit and chosen_unit in self.units: self.move_to_unit(chosen_unit) gameStateObj.info_menu_struct['chosen_unit'] = None
def draw(self, surf, gameStateObj): self.write_index = 6 if not self.surf: bg_surf = MenuFunctions.CreateBaseMenuSurf( self.size, 'BaseMenuBackgroundOpaque') self.surf = Engine.create_surface( (self.size[0] + 2, self.size[1] + 4), convert=True, transparent=True) self.surf.blit(bg_surf, (2, 4)) self.surf.blit(GC.IMAGESDICT['SmallGem'], (0, 0)) Image_Modification.flickerImageTranslucent(self.surf, 10) BGSurf = self.surf.copy() # Center it pos = surf.get_width() // 2 - self.size[0] // 2 - 2, surf.get_height( ) // 2 - self.size[1] // 2 - 4 # Blit words for index, word in enumerate(self.banner): word_width = GC.FONT[self.banner_font[index]].size(word)[0] GC.FONT[self.banner_font[index]].blit( word, BGSurf, (self.write_index, self.size[1] // 2 - self.font_height // 2 + 4)) self.write_index += word_width # Blit item icon if self.item: self.item.draw(BGSurf, (self.size[0] - 6 - 16 - 2, 4 + 4), cooldown=False) surf.blit(BGSurf, pos)
def draw(self, gameStateObj): text_lines = self.split_string(self.eval_string(self.display_name_string, gameStateObj)) longest_surf_width = self.get_size(text_lines) if longest_surf_width != self.surf_width or len(text_lines) != self.num_lines: self.num_lines = len(text_lines) self.surf_width = longest_surf_width surf_height = 16 * self.num_lines + 8 # Blit background BGSurf = MenuFunctions.CreateBaseMenuSurf((self.surf_width + 16, surf_height), 'BaseMenuBackgroundOpaque') if self.num_lines == 1: BGSurf.blit(GC.IMAGESDICT['Shimmer1'], (BGSurf.get_width() - 1 - GC.IMAGESDICT['Shimmer1'].get_width(), 4)) elif self.num_lines == 2: BGSurf.blit(GC.IMAGESDICT['Shimmer2'], (BGSurf.get_width() - 1 - GC.IMAGESDICT['Shimmer2'].get_width(), 4)) self.BGSurf = Engine.create_surface((BGSurf.get_width(), BGSurf.get_height() + 3), transparent=True, convert=True) self.BGSurf.blit(BGSurf, (0, 3)) gem = GC.IMAGESDICT['BlueCombatGem'] self.BGSurf.blit(gem, (BGSurf.get_width()//2 - gem.get_width()//2, 0)) # Now make translucent self.BGSurf = Image_Modification.flickerImageTranslucent(self.BGSurf, 20) temp_surf = self.BGSurf.copy() for index, line in enumerate(text_lines): position = temp_surf.get_width()//2 - GC.FONT['text_white'].size(line)[0]//2, 16 * index + 6 GC.FONT['text_white'].blit(line, temp_surf, position) return temp_surf
def get_help_box(self): if self.weapon or self.spell: font1 = FONT['text_blue'] font2 = FONT['text_yellow'] if self.weapon: first_line_text = [' ', self.weapon.LVL, ' Mt ', str(self.weapon.MT), ' Hit ', str(self.weapon.HIT)] if self.WT: first_line_text += [' Wt ', str(self.WT)] first_line_text += [' Rng ', self.strRNG] first_line_font = [font1, font1, font2, font1, font2, font1] if self.WT: first_line_font += [font2, font1] first_line_font += [font2, font1] elif self.spell: first_line_text = [' ', self.spell.LVL] first_line_font = [font1, font1] if self.damage is not None: first_line_text += [' Mt ', str(self.damage)] first_line_font += [font2, font1] if self.hit is not None: first_line_text += [' Hit ', str(self.hit)] first_line_font += [font2, font1] first_line_text += [' Rng ', self.strRNG] first_line_font += [font2, font1] first_line_length = max(font1.size(''.join(first_line_text))[0] + 16 * len(self.TYPE) + 4, 96) output_desc_lines = MenuFunctions.line_wrap(MenuFunctions.line_chunk(self.desc), first_line_length, FONT['convo_black']) size_x = first_line_length + 16 size_y = 24 + len(output_desc_lines)*16 help_surf = MenuFunctions.CreateBaseMenuSurf((size_x, size_y), 'MessageWindowBackground') self.drawType(help_surf, 4, 4) # Actually blit first line word_index = 4 + 16 * len(self.TYPE) for index, word in enumerate(first_line_text): first_line_font[index].blit(word, help_surf, (word_index, 4)) word_index += first_line_font[index].size(word)[0] for index, line in enumerate(output_desc_lines): FONT['convo_black'].blit(''.join(line), help_surf, (4, FONT['convo_black'].height*index + 4 + 16)) return help_surf else: return InfoMenu.create_help_box(self.desc)
def drawInvalid(self, surf): size_of_text = GC.FONT['text_white'].size("Invalid Choice!") width = size_of_text[0] height = size_of_text[1] pop_up_surf = MenuFunctions.CreateBaseMenuSurf((width + 16 - width%8, height + 16 - height%8)) surf.blit(Image_Modification.flickerImageTranslucent(GC.IMAGESDICT['BlackBackground'].copy(), 60), (0, 0)) topleft = (GC.WINWIDTH//2 - pop_up_surf.get_width()//2, GC.WINHEIGHT//2 - pop_up_surf.get_height()//2) surf.blit(pop_up_surf, topleft) position = (GC.WINWIDTH//2 - width//2, GC.WINHEIGHT//2 - height//2) GC.FONT['text_white'].blit(cf.WORDS["Invalid Choice"], surf, position)
def begin(self, gameStateObj, metaDataObj): if not self.started: self.config = [('Animation', ['Always', 'Your Turn', 'Combat Only', 'Never'], cf.WORDS['Animation_desc'], 0), ('temp_Screen Size', ['1', '2', '3', '4', '5'], cf.WORDS['temp_Screen Size_desc'], 18), ('Unit Speed', list(reversed(range(15, 180, 15))), cf.WORDS['Unit Speed_desc'], 1), ('Text Speed', cf.text_speed_options, cf.WORDS['Text Speed_desc'], 2), ('Cursor Speed', list(reversed(range(0, 220, 20))), cf.WORDS['Cursor Speed_desc'], 8), ('Show Terrain', ['ON', 'OFF'], cf.WORDS['Show Terrain_desc'], 7), ('Show Objective', ['ON', 'OFF'], cf.WORDS['Show Objective_desc'], 6), ('Autocursor', ['ON', 'OFF'], cf.WORDS['Autocursor_desc'], 13), ('HP Map Team', ['All', 'Ally', 'Enemy'], cf.WORDS['HP Map Team_desc'], 10), ('HP Map Cull', ['None', 'Wounded', 'All'], cf.WORDS['HP Map Cull_desc'], 10), ('Music Volume', [x/10.0 for x in range(0, 11, 1)], cf.WORDS['Music Volume_desc'], 15), ('Sound Volume', [x/10.0 for x in range(0, 11, 1)], cf.WORDS['Sound Volume_desc'], 16), ('Autoend Turn', ['ON', 'OFF'], cf.WORDS['Autoend Turn_desc'], 14), ('Confirm End', ['ON', 'OFF'], cf.WORDS['Confirm End_desc'], 14), ('Display Hints', ['ON', 'OFF'], cf.WORDS['Display Hints_desc'], 3)] self.controls = {'key_SELECT': Engine.subsurface(GC.IMAGESDICT['Buttons'], (0, 66, 14, 13)), 'key_BACK': Engine.subsurface(GC.IMAGESDICT['Buttons'], (0, 82, 14, 13)), 'key_INFO': Engine.subsurface(GC.IMAGESDICT['Buttons'], (1, 149, 16, 9)), 'key_AUX': Engine.subsurface(GC.IMAGESDICT['Buttons'], (1, 133, 16, 9)), 'key_START': Engine.subsurface(GC.IMAGESDICT['Buttons'], (0, 165, 33, 9)), 'key_LEFT': Engine.subsurface(GC.IMAGESDICT['Buttons'], (1, 4, 13, 12)), 'key_RIGHT': Engine.subsurface(GC.IMAGESDICT['Buttons'], (1, 19, 13, 12)), 'key_DOWN': Engine.subsurface(GC.IMAGESDICT['Buttons'], (1, 34, 12, 13)), 'key_UP': Engine.subsurface(GC.IMAGESDICT['Buttons'], (1, 50, 12, 13))} self.currentSelection = 0 self.start_offset = 32 self.top_of_menu = 0 self.control_order = ['key_SELECT', 'key_BACK', 'key_INFO', 'key_AUX', 'key_LEFT', 'key_RIGHT', 'key_UP', 'key_DOWN', 'key_START'] self.background = MenuFunctions.MovingBackground(GC.IMAGESDICT['StatusBackground']) self.state = CustomObjects.StateMachine('TopMenu') Counters.CursorControl.__init__(self) self.up_arrow = GUIObjects.ScrollArrow('up', (GC.WINWIDTH//2 - 7, self.start_offset - 4), 0) self.down_arrow = GUIObjects.ScrollArrow('down', (GC.WINWIDTH//2 - 7, self.start_offset + 6*16 - 1), 0.5) self.left_arrow = GUIObjects.ScrollArrow('left', (0, 0), 0) self.right_arrow = GUIObjects.ScrollArrow('right', (0, 0), 0.5) self.backSurf = gameStateObj.generic_surf # Transition in: gameStateObj.stateMachine.changeState("transition_in") return 'repeat'
def __init__(self, item): self.last_time = self.start_time = 0 self.transition_in = self.transition_out = False self.item = item font1 = GC.FONT['text_blue'] font2 = GC.FONT['text_yellow'] if self.item.weapon: self.first_line_text = [' ', self.item.weapon.LVL, ' Mt ', str(self.item.weapon.MT), ' Hit ', str(self.item.weapon.HIT)] if cf.CONSTANTS['crit']: self.first_line_text += [' Crit ', str(self.item.crit) if self.item.crit is not None else '--'] if self.item.weight: self.first_line_text += [' Wt ', str(self.item.weight)] self.first_line_text += [' Rng ', self.item.strRNG] self.first_line_font = [font1, font1, font2, font1, font2, font1] if cf.CONSTANTS['crit']: self.first_line_font += [font2, font1] if self.item.weight: self.first_line_font += [font2, font1] self.first_line_font += [font2, font1] elif self.item.spell: self.first_line_text = [' ', self.item.spell.LVL] self.first_line_font = [font1, font1] if self.item.damage is not None: self.first_line_text += [' Mt ', str(self.item.damage)] self.first_line_font += [font2, font1] if self.item.hit is not None: self.first_line_text += [' Hit ', str(self.item.hit)] self.first_line_font += [font2, font1] if cf.CONSTANTS['crit'] and self.item.crit is not None: self.first_line_text += [' Crit ', str(self.item.crit)] self.first_line_font += [font2, font1] self.first_line_text += [' Rng ', self.item.strRNG] self.first_line_font += [font2, font1] first_line_length = max(font1.size(''.join(self.first_line_text))[0] + (16 if self.item.icon else 0) + 4, 112) # 112 was 96 if self.item.desc: self.output_desc_lines = TextChunk.line_wrap(TextChunk.line_chunk(self.item.desc), first_line_length, GC.FONT['convo_black']) self.output_desc_lines = [''.join(line) for line in self.output_desc_lines] else: self.output_desc_lines = [] size_x = first_line_length + 24 size_y = 32 + len(self.output_desc_lines)*16 self.help_surf = MenuFunctions.CreateBaseMenuSurf((size_x, size_y), 'MessageWindowBackground') self.h_surf = Engine.create_surface((size_x, size_y + 3), transparent=True)
def drawInfo(self, surf): mainInfoSurf = MenuFunctions.CreateBaseMenuSurf((GC.WINWIDTH - 32, 24), 'BaseMenuBackground') surf.blit(mainInfoSurf, (16, GC.WINHEIGHT - 24)) if self.state.getState() == "Config": info_text = self.config[self.currentSelection][2] elif self.state.getState() == "Controls": info_text = cf.WORDS['Controls_desc'] elif self.state.getState() == "Get_Input": info_text = cf.WORDS['Get_Input_desc'] elif self.state.getState() == "TopMenu": if self.currentSelection == 0: info_text = cf.WORDS['Config_desc'] else: info_text = cf.WORDS['Controls_desc'] else: return GC.FONT['text_white'].blit(info_text, surf, (32, GC.WINHEIGHT - 20))
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())
def update(self, gameStateObj, metaDataObj): # Don't do this if there is no exp change if not self.force_level and self.expNew == 0 or (self.unit.level%CONSTANTS['max_level'] == 0 and metaDataObj['class_dict'][self.unit.klass]['turns_into'] is None): return True # We're done here if self.instantiationTime is None: # First time update is called. self.instantiationTime = pygame.time.get_ticks() SOUNDDICT['Experience Gain'].play(-1) #print self.state.getState() #print self.expSet, self.expOld, self.expNew currentTime = pygame.time.get_ticks() if self.state.getState() == 'exp0': self.expSet = self.expOld + (currentTime - self.instantiationTime)/float(self.EXPTIME/100) # 100 is total exp self.expSet = int(min(self.expNew + self.expOld, self.expSet)) if self.expNew + self.expOld <= self.expSet: SOUNDDICT['Experience Gain'].stop() if self.expSet >= 100: if self.unit.level%CONSTANTS['max_level'] == 0: # If I would promote because I am level 20 SOUNDDICT['Experience Gain'].stop() if metaDataObj['class_dict'][self.unit.klass]['turns_into']: # If has at least one class to turn into self.expSet = 0 class_options = metaDataObj['class_dict'][self.unit.klass]['turns_into'] if len(class_options) > 1: gameStateObj.activeMenu = MenuFunctions.ChoiceMenu(self.unit, class_options, 'auto', gameStateObj) gameStateObj.stateMachine.changeState('levelpromote') elif len(class_options) == 1: self.unit.klass = class_options[0] self.state.changeState('promote') else: return True else: # Unit is at the highest point it can be. No more. self.unit.exp = 99 return True else: self.expSet = 0 self.unit.level += 1 self.levelup_list = self.unit.level_up(metaDataObj['class_dict'][self.unit.klass]) self.state.changeState('exp100') elif currentTime - self.instantiationTime >= self.EXPTIME: SOUNDDICT['Experience Gain'].stop() self.unit.exp += self.expNew return True elif self.state.getState() == 'exp100': # Problem... It is not counting time needed to get to this state. Should minus away that time - Time taken to get to this point in (100 - self.expOld)*float(self.EXPTIME/100) self.expSet = (currentTime - self.instantiationTime - (100 - self.expOld)*float(self.EXPTIME/100))/float(self.EXPTIME/100) self.expSet = int(min(self.expNew + self.expOld - 100, self.expSet)) if self.expNew + self.expOld - 100 <= self.expSet: SOUNDDICT['Experience Gain'].stop() if currentTime - self.instantiationTime >= self.EXPTIME: SOUNDDICT['Experience Gain'].stop() #MUSICTHREAD.pause() SOUNDDICT['Level Up'].play() self.state.changeState('levelUp') elif self.state.getState() == 'levelUp': if currentTime - self.instantiationTime >= self.LEVELANIMATIONTIME + self.EXPTIME: self.state.changeState('levelUpWait') else: time = currentTime - self.instantiationTime - self.EXPTIME marker1 = min(4, int(time/(self.LEVELANIMATIONTIME/5))) marker2 = min(4, int((time%(self.LEVELANIMATIONTIME/5))/(self.LEVELANIMATIONTIME/25))) self.animationMarker = (marker1, marker2) elif self.state.getState() == 'levelUpWait': if currentTime - self.instantiationTime >= self.LEVELANIMATIONTIME + self.WAITTIME + self.EXPTIME: self.state.changeState('levelScreen') #MUSICTHREAD.resume() else: self.animationMarker = (4, 4) # Set to last frame elif self.state.getState() == 'levelScreen': # Am i Done displaying? if currentTime - self.instantiationTime >= self.LEVELUPWAIT + self.get_num_sparks()*self.SPARKTIME + self.LEVELANIMATIONTIME + self.WAITTIME + self.EXPTIME: # Handle EXP when the user levels up self.unit.exp += self.expNew if self.unit.exp >= 100: self.unit.exp = self.expNew - (100 - self.expOld) # Remove animations self.animations = [] # check for skill gain for level_needed, class_skill in metaDataObj['class_dict'][self.unit.klass]['skills']: if self.unit.level%CONSTANTS['max_level'] == level_needed: if class_skill == 'Feat': gameStateObj.cursor.currentSelectedUnit = self.unit gameStateObj.stateMachine.changeState('feat_choice') else: skill = StatusObject.statusparser(class_skill) StatusObject.HandleStatusAddition(skill, self.unit) gameStateObj.banners.append(MenuFunctions.gainedSkillBanner(self.unit, skill)) gameStateObj.stateMachine.changeState('itemgain') return True elif self.state.getState() == 'promote': # Class should already have been changed by now in the levelpromote state # Here's where I change all the important information new_class = metaDataObj['class_dict'][self.unit.klass] self.unit.removeSprites() self.unit.loadSprites() # Reset Level - Don't! self.unit.level += 1 # Actually change class # Reset movement speed self.unit.stats['MOV'].base_stat = new_class['movement'] # Reset movement group self.unit.movement_group = new_class['movement_group'] # Add weapon exp gains from that class. self.unit.increase_wexp(new_class['wexp_gain'], gameStateObj) # Add any extra tags if new_class['tags']: # Add any necessary tags. Does not currently take away tags, although it may have to later self.unit.tags.append(new_class['tags'].split(',')) self.unit.tags = list(set(self.unit.tags)) # Remove duplicates # Give promotion self.levelup_list = self.unit.level_up(new_class, apply_level=False) # Level up once, then promote. self.levelup_list = [x + y for x, y in zip(self.levelup_list, new_class['promotion'])] # Add lists together current_stats = [self.unit.stats['HP'], self.unit.stats['STR'], self.unit.stats['MAG'], self.unit.stats['SKL'], self.unit.stats['SPD'], self.unit.stats['LCK'], self.unit.stats['DEF'], self.unit.stats['RES'], self.unit.stats['CON']] assert len(self.levelup_list) == len(new_class['max']) == len(current_stats), "%s %s %s"%(self.levelup_list, new_class['max'], current_stats) for index, stat in enumerate(self.levelup_list): self.levelup_list[index] = min(stat, new_class['max'][index] - current_stats[index]) self.unit.apply_levelup(self.levelup_list) self.state.changeState('levelScreen') self.instantiationTime = currentTime # Reset time so that it doesn't skip right over LevelScreen return False