Exemplo n.º 1
0
    def loadSprites(self):
        if not self.sprites_loaded_flag:
            self.sprites_loaded_flag = True
            # Handle grabbing normal sprites
            self.map_image = Engine.image_load(self.mapfilename, convert=True)
            Engine.set_colorkey(self.map_image, COLORKEY, rleaccel=True)
            # Auto-tiles
            auto_loc = self.levelfolder + '/Autotiles/'
            self.autotile_frame = 0
            if os.path.exists(auto_loc):
                files = sorted([
                    fp for fp in os.listdir(auto_loc)
                    if fp.startswith('autotile') and fp.endswith('.png')
                ],
                               key=lambda x: int(x[8:-4]))
                imageList = [
                    Engine.image_load(auto_loc + image, convert=True)
                    for image in files
                ]
                for image in imageList:
                    Engine.set_colorkey(image, COLORKEY, rleaccel=True)
                self.autotiles = imageList
            else:
                self.autotiles = []
            # Loose Tile Sprites
            lts_loc = self.levelfolder + '/LooseTileSprites/'
            if os.path.exists(lts_loc):
                itemnameList = [
                    image[:-4] for image in os.listdir(lts_loc)
                    if image.endswith('.png')
                ]
                imageList = [
                    Engine.image_load(lts_loc + image, convert=True)
                    for image in os.listdir(lts_loc) if image.endswith('.png')
                ]
                for image in imageList:
                    Engine.set_colorkey(image, COLORKEY, rleaccel=True)
                self.loose_tile_sprites = dict(zip(itemnameList, imageList))
            else:
                self.loose_tile_sprites = {}

            # Re-add escape highlights if necessary
            for position, tile_values in self.tile_info_dict.iteritems():
                if "Escape" in tile_values or "Arrive" in tile_values:
                    self.escape_highlights[position] = CustomObjects.Highlight(
                        GC.IMAGESDICT["YellowHighlight"])
                if "Formation" in tile_values:
                    self.formation_highlights[
                        position] = CustomObjects.Highlight(
                            GC.IMAGESDICT["BlueHighlight"])

            # Re-add associated status sprites
            for position, value in self.tile_info_dict.iteritems():
                if 'Status' in value:
                    for status in value['Status']:
                        status.loadSprites()
Exemplo n.º 2
0
def load_level(levelfolder, gameStateObj, metaDataObj):
    # Done at the beginning of a new level and ONLY then
    GC.U_ID = 100
    # Assorted Files
    unitfilename = levelfolder + '/UnitLevel.txt'

    unitFile = open(unitfilename, 'r')
    unitcontent = unitFile.readlines()
    unitFile.close()

    # For gameStateObj
    reinforceUnits, prefabs = {}, {}

    # Read overview file
    overview_filename = levelfolder + '/overview.txt'
    overview_dict = read_overview_file(overview_filename)
    # Get objective
    starting_objective = CustomObjects.Objective(
        overview_dict['display_name'], overview_dict['win_condition'],
        overview_dict['loss_condition'])

    # MetaDataObj holds unchanging information for the level
    # And general abstraction information
    get_metaDataObj(levelfolder, metaDataObj)

    starting_music = CustomObjects.PhaseMusic(overview_dict['player_phase_music'], overview_dict['enemy_phase_music'], \
                                              overview_dict['other_phase_music'] if 'other_phase_music' in overview_dict else None)

    # Get tiles
    currentMap = create_map(levelfolder, overview_dict)
    gameStateObj.start_map(currentMap)

    # === Process unit data ===
    current_mode = ['All']
    for line in unitcontent:
        # Process each line that was in the level file.
        line = line.strip()
        # Skip empty or comment lines
        if not line or line.startswith('#'):
            continue
        # Process line
        unitLine = line.split(';')
        current_mode = parse_unit_line(unitLine, current_mode,
                                       gameStateObj.allunits,
                                       gameStateObj.factions, reinforceUnits,
                                       prefabs, gameStateObj.triggers,
                                       metaDataObj, gameStateObj)

    handle_triggers(gameStateObj.allunits, reinforceUnits,
                    gameStateObj.triggers, gameStateObj.map)
    gameStateObj.start(allreinforcements=reinforceUnits,
                       prefabs=prefabs,
                       objective=starting_objective,
                       music=starting_music)
Exemplo n.º 3
0
    def __init__(self, i_id, name, spritetype, spriteid, components, value, RNG,
                 desc, aoe, weapontype, status, status_on_hold, status_on_equip,
                 droppable=False, locked=False, event_combat=False):
        self.spritetype = spritetype # Consumable, Sword, Used for spriting in list of sprites
        self.spriteid = spriteid # Number of sprite to be picked from spritesheet list
        
        self.id = i_id
        self.owner = 0
        self.name = str(name)
        self.value = int(value) # Value for one use of item, or for an infinite item
        self.RNG = parseRNG(RNG) # Comes in the form of looking like '1-2' or '1' or '2-3' or '3-10'
        self.strRNG = RNG # string version of RNG for display
        self.event_combat = event_combat
        self.droppable = droppable # Whether this item is given to its owner's killer upon death
        self.locked = locked # Whether this item can be traded, sold, or dropped.
        assert not(self.droppable == self.locked == True), "%s can't be both droppable and locked to a unit!" %(self.name)
        self.desc = desc # Text description of item
        # Status IDs
        self.status = status
        self.status_on_hold = status_on_hold
        self.status_on_equip = status_on_equip
        
        self.aoe = aoe
        self.TYPE = weapontype
        self.icons = []
        for weapon_type in self.TYPE:
            self.icons.append(CustomObjects.WeaponIcon(weapon_type))
        
        # Creates component slots
        self.components = components # Consumable, Weapon, Spell Bigger Picture
        for component_key, component_value in self.components.iteritems():
            self.__dict__[component_key] = component_value

        self.loadSprites()
Exemplo n.º 4
0
 def hide_layer(self, line, grid_manager=None):
     layer = int(line[1])
     # Image layer
     if len(self.layers) > layer:
         transition = line[2] if len(line) > 2 else None
         if transition == 'fade' or transition == 'destroy':
             self.layers[layer].show = False
             if transition == 'destroy':
                 for sprite in self.layers[layer]:
                     x, y = sprite.position
                     self.animations.append(
                         CustomObjects.Animation(
                             GC.IMAGESDICT['Snag'], (x, y - 1), (5, 13),
                             animation_speed=DESTRUCTION_ANIM_TIME //
                             (13 * 5)))
         else:
             self.layers[layer].show = False
             self.layers[layer].fade = 0
     # Terrain layer
     if len(self.terrain_layers) > layer:
         self.terrain_layers[layer].show = False
         self.true_tiles = None  # Reset tiles
         self.true_opacity_map = None
         if grid_manager:
             self.handle_grid_manager_with_layer(layer, grid_manager)
Exemplo n.º 5
0
    def start_map(self, tilemap):
        self.map = tilemap

        # Set up blitting surface
        mapSurfWidth = max(self.map.width * GC.TILEWIDTH, GC.WINWIDTH)
        mapSurfHeight = max(self.map.height * GC.TILEHEIGHT, GC.WINHEIGHT)
        self.mapSurf = Engine.create_surface((mapSurfWidth, mapSurfHeight))

        self.grid_manager = AStar.Grid_Manager(self.map)
        self.boundary_manager = CustomObjects.BoundaryManager(self.map)
Exemplo n.º 6
0
 def __init__(self, unit, wexp, weapon_type):
     Banner.__init__(self)
     self.unit = unit
     self.item = CustomObjects.WeaponIcon(weapon_type)
     self.banner = [
         unit.name, ' reached rank ',
         CustomObjects.WEAPON_EXP.number_to_letter(wexp)
     ]
     self.banner_font = ['text_blue', 'text_white', 'text_blue']
     self.figure_out_size()
     self.sound = GC.SOUNDDICT['Item']
Exemplo n.º 7
0
 def parse_tile_line(self, coord, property_list):
     if property_list:
         for tile_property in property_list:
             property_name, property_value = tile_property.split('=')
             # Handle special cases...
             if property_name == 'Status':  # Treasure does not need to be split. It is split by the itemparser function itself.
                 # Turn these string of ids into a list of status objects
                 status_list = []
                 for status in property_value.split(','):
                     status_list.append(StatusObject.statusparser(status))
                 property_value = status_list
             elif property_name in ["Escape", "Arrive"]:
                 self.escape_highlights[coord] = CustomObjects.Highlight(
                     GC.IMAGESDICT["YellowHighlight"])
             elif property_name == "Formation":
                 self.formation_highlights[coord] = CustomObjects.Highlight(
                     GC.IMAGESDICT["BlueHighlight"])
             self.tile_info_dict[coord][property_name] = property_value
     else:
         self.tile_info_dict[coord] = {'Status': []}  # Empty Dictionary
Exemplo n.º 8
0
    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', CustomObjects.WEAPON_TRIANGLE.types, [9 + idx*16 for idx in xrange(len(CustomObjects.WEAPON_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 = [CustomObjects.WeaponIcon(weapon) for weapon in CustomObjects.WEAPON_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
Exemplo n.º 9
0
    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'
Exemplo n.º 10
0
 def hide_layer(self, line):
     layer = int(line[1])
     transition = line[2] if len(line) > 2 else None
     if transition == 'fade' or transition == 'destroy':
         self.layers[layer].show = False
         if transition == 'destroy':
             for sprite in self.layers[layer]:
                 x, y = sprite.position
                 self.animations.append(
                     CustomObjects.Animation(
                         GC.IMAGESDICT['Snag'], (x, y - 1), (5, 13),
                         animation_speed=DESTRUCTION_ANIM_TIME / (13 * 5)))
     else:
         self.layers[layer].show = False
         self.layers[layer].fade = 0
Exemplo n.º 11
0
 def change_tile_sprites(self, coord, image_filename, transition=None):
     image = self.loose_tile_sprites[image_filename]
     size = image.get_width()//GC.TILEWIDTH, image.get_height()//GC.TILEHEIGHT
     for x in range(coord[0], coord[0] + size[0]):
         for y in range(coord[1], coord[1] + size[1]):
             pos = (x - coord[0], y - coord[1])
             self.tile_sprites[(x, y)] = TileSprite(None, (x, y), self)
             if transition:
                 self.tile_sprites[(x, y)].new_image_name = image_filename
                 self.tile_sprites[(x, y)].new_position = pos
                 self.tile_sprites[(x, y)].loadNewSprites()
                 if transition == 'destroy':
                     # To be moved to global during next update
                     self.animations.append(CustomObjects.Animation(GC.IMAGESDICT['Snag'], (x, y - 1), (5, 13), animation_speed=DESTRUCTION_ANIM_TIME//(13*5)))
             else:
                 self.tile_sprites[(x, y)].image_name = image_filename
                 self.tile_sprites[(x, y)].position = pos
                 self.tile_sprites[(x, y)].loadSprites()
Exemplo n.º 12
0
 def no_damage(self):
     # print('No Damage!')
     if self.right:
         position = (52, 21)
     else:
         position = (110, 21)  # Enemy's position
     team = self.owner.right.team if self.right else self.owner.left.team
     image = GC.IMAGESDICT['NoDamageBlue' if team ==
                           'player' else 'NoDamageRed']
     anim = CustomObjects.Animation(image,
                                    position, (5, 5),
                                    ignore_map=True,
                                    set_timing=(1, 1, 1, 1, 1, 1, 1, 1, 1,
                                                1, 1, 1, 1, 1, 1, 1, 1, 1,
                                                1, 1, 1, 1, 1, 1, 48))
     self.animations.append(anim)
     # Also offset self by [-1, -2, -3, -2, -1]
     self.lr_offset = [-1, -2, -3, -2, -1]
Exemplo n.º 13
0
    def __init__(self, gameStateObj, upkeep=True):
        # Initial setup
        self.upkeep = upkeep  # Whether I'm running this on upkeep or on endstep
        self.current_phase = gameStateObj.phase.get_current_phase()
        self.previous_phase = gameStateObj.phase.get_previous_phase()
        affected_units = [
            unit for unit in gameStateObj.allunits
            if unit.position and unit.status_effects
        ]
        if self.upkeep:
            self.units = [
                unit for unit in affected_units
                if unit.team == self.current_phase
            ]
        else:
            self.units = [
                unit for unit in affected_units
                if unit.team == self.previous_phase
            ]
        logger.info('Building Status_Processor: %s %s %s', self.upkeep,
                    self.current_phase, self.previous_phase)

        # State control
        self.current_unit = None
        self.current_unit_statuses = []
        self.current_status = None
        self.status_index = 0
        self.state = CustomObjects.StateMachine('begin')
        self.state_buffer = False

        # Animation properties
        self.time_spent_on_each_status = 1200  # Only if it has a onetime animation
        self.start_time_for_this_status = Engine.get_time()

        # Health bar
        self.health_bar = Interaction.HealthBar('splash', None, None)

        # Waiting timer
        self.wait_time = 200
        self.started_waiting = Engine.get_time()
Exemplo n.º 14
0
 def update_statistics(self, metaDataObj):
     self.statistics.append(CustomObjects.LevelStatistic(self, metaDataObj))
     for unit in self.allunits:
         unit.records = unit.default_records()
Exemplo n.º 15
0
    def generic(self):
        logger.info("Generic")
        lord_units = [
            unit for unit in self.allunits
            if unit.position and 'Lord' in unit.tags and unit.team == 'player'
        ]
        lord_position = lord_units[0].position if lord_units else (0, 0)
        # Certain variables change if this is being initialized at beginning of game, and not a save state
        self.phase = CustomObjects.Phase(self)
        self.statedict = {
            'previous_cursor_position': lord_position,
            'levelIsComplete': False,  # Whether the level is complete
            'outroScriptDone': False
        }  # Whether the outro script has been played
        # For hiding menus
        self.hidden_active = None
        self.hidden_child = None
        self.main_menu = None
        # Combat slots
        self.combatInstance = None
        self.levelUpScreen = []
        # Banner slots
        self.banners = []
        # Status slots
        self.status = None
        # AI slots
        self.ai_current_unit = None
        self.ai_unit_list = None
        self.ai_build_flag = True
        # Movement manager
        self.moving_units = set()

        # Handle cursor
        if any(unit.team == 'player' and unit.position
               for unit in self.allunits):
            # cursor_position = [unit.position for unit in self.allunits if unit.team == 'player' and unit.position][0]
            cursor_position = lord_position
        else:
            cursor_position = (0, 0)
        self.cursor = CustomObjects.Cursor('Cursor', cursor_position)
        self.fake_cursors = []
        self.tutorial_mode = False

        # Handle cameraOffset
        # Track how much camera has moved in pixels:
        self.cameraOffset = CustomObjects.CameraOffset(self.cursor.position[0],
                                                       self.cursor.position[1])
        self.cursor.autocursor(self, force=True)
        # Other slots
        self.highlight_manager = CustomObjects.HighlightController()
        self.allarrows = []
        self.allanimations = []

        # Reset the units updates on load
        # And have the units arrive on map
        for unit in self.allunits:
            unit.resetUpdates()
            if unit.position:
                unit.place_on_map(self)
                unit.arrive(self, serializing=False)

        self.info_menu_struct = {
            'current_state': 0,
            'scroll_units': [],
            'one_unit_only': False,
            'chosen_unit': None
        }
Exemplo n.º 16
0
    def load(self, load_info):
        logger.info("Load")
        # Rebuild gameStateObj
        self.allunits = [
            UnitObject.UnitObject(info) for info in load_info['allunits']
        ]
        self.factions = load_info['factions'] if 'factions' in load_info else (
            load_info['groups'] if 'groups' in load_info else {})
        self.allreinforcements = load_info['allreinforcements']
        self.prefabs = load_info['prefabs']
        self.triggers = load_info.get('triggers', dict())
        map_info = load_info['map']
        self.playtime = load_info['playtime']
        self.convoy = [
            ItemMethods.deserialize(item_dict)
            for item_dict in load_info['convoy']
        ]
        self.convoy = [item for item in self.convoy if item]
        self.turncount = load_info['turncount']
        self.game_constants = load_info['game_constants']
        self.level_constants = load_info['level_constants']
        self.objective = CustomObjects.Objective.deserialize(
            load_info['objective']) if load_info['objective'] else None
        self.phase_music = CustomObjects.PhaseMusic.deserialize(
            load_info['phase_music']) if load_info['phase_music'] else None
        support_dict = load_info['support']
        self.talk_options = load_info['talk_options']
        self.base_conversations = load_info['base_conversations']
        self.stateMachine = StateMachine.StateMachine(
            load_info['state_list'][0], load_info['state_list'][1])
        self.statistics = load_info['statistics']
        # self.message = [Dialogue.Dialogue_Scene(scene) for scene in load_info['message']]
        self.message = []
        self.unlocked_lore = load_info['unlocked_lore']
        self.market_items = load_info.get('market_items', set())
        self.mode = load_info.get('mode', self.default_mode())

        # Map
        self.map = SaveLoad.create_map('Data/Level' +
                                       str(self.game_constants['level']))
        if map_info:
            self.map.replay_commands(map_info['command_list'],
                                     self.game_constants['level'])
            self.map.command_list = map_info['command_list']
            for position, current_hp in map_info['HP']:
                self.map.tiles[position].set_hp(current_hp)

        # Statuses
        for index, info in enumerate(load_info['allunits']):
            for s_dict in info['status_effects']:
                if isinstance(s_dict, dict):
                    StatusObject.deserialize(s_dict, self.allunits[index],
                                             self)
                else:
                    self.allunits[index].status_effects.append(s_dict)

        # Support
        if cf.CONSTANTS['support']:
            self.support = Support.Support_Graph('Data/support_nodes.txt',
                                                 'Data/support_edges.txt')
            self.support.deserialize(support_dict)
        else:
            self.support = None

        # Set up blitting surface
        if self.map:
            mapSurfWidth = self.map.width * GC.TILEWIDTH
            mapSurfHeight = self.map.height * GC.TILEHEIGHT
            self.mapSurf = Engine.create_surface((mapSurfWidth, mapSurfHeight))

            self.grid_manager = AStar.Grid_Manager(self.map)
            self.boundary_manager = CustomObjects.BoundaryManager(self.map)

            for unit in self.allunits:
                if unit.position:
                    self.grid_manager.set_unit_node(unit.position, unit)

        self.generic()
        if 'phase_info' in load_info:
            self.phase.current, self.phase.previous = load_info['phase_info']
Exemplo n.º 17
0
 def parse_line(self, line):
     # print(self.right, line)
     self.base_state = False
     # === TIMING AND IMAGES ===
     if line[0] == 'f':
         self.frame_count = 0
         self.num_frames = self.get_frames(line[1])
         self.current_frame = self.frame_directory[line[2]]
         self.processing = False
         if line[2] == 'Stand':
             self.base_state = True
         if len(line) > 3 and line[3]:  # Under frame
             self.under_frame = self.frame_directory[line[3]]
         else:
             self.under_frame = None
         self.over_frame = None
         if len(line) > 4 and line[4]:
             self.personal_offset = tuple(
                 int(num) for num in line[4].split(','))
     elif line[0] == 'of':
         self.frame_count = 0
         self.num_frames = self.get_frames(line[1])
         self.under_frame = None
         self.processing = False
         self.over_frame = self.frame_directory[line[2]]
         if len(line) > 3:  # Current frame
             self.current_frame = self.frame_directory[line[3]]
         else:
             self.current_frame = None
     elif line[0] == 'uf':
         self.frame_count = 0
         self.num_frames = self.get_frames(line[1])
         self.current_frame = None
         self.over_frame = None
         self.under_frame = self.frame_directory[line[2]]
         self.processing = False
         if len(line) > 3:
             self.personal_offset = tuple(
                 int(num) for num in line[3].split(','))
     elif line[0] == 'wait':
         self.frame_count = 0
         self.num_frames = self.get_frames(line[1])
         self.current_frame = None
         self.under_frame = None
         self.over_frame = None
         self.processing = False
     # === SFX ===
     elif line[0] == 'sound':
         sound = random.choice(line[1:])
         GC.SOUNDDICT[sound].play()
     elif line[0] == 'stop_sound':
         sound = random.choice(line[1:])
         GC.SOUNDDICT[sound].stop()
     # === COMBAT HIT ===
     elif line[0] == 'start_hit':
         if 'no_shake' not in line:
             if self.owner.outcome() == 2:
                 self.owner.shake(4)  # Critical
             elif self.owner.def_damage() > 0:
                 self.owner.shake(1)
             else:  # No Damage -- Hit spark handles anim
                 self.owner.shake(2)
         self.owner.start_hit('no_sound' not in line)
         # Also offset partner by [-1, -2, -3, -2, -1]
         if self.partner:
             self.partner.lr_offset = [-1, -2, -3, -2, -1]
     elif line[0] == 'wait_for_hit':
         if self.wait_for_hit:
             if len(line) > 1:
                 self.current_frame = self.frame_directory[line[1]]
             else:
                 self.current_frame = None
             if len(line) > 2:
                 self.under_frame = self.frame_directory[line[2]]
             else:
                 self.under_frame = None
             self.over_frame = None
             self.state = 'Wait'
             self.processing = False
             self.base_state = True
     elif line[0] == 'spell_hit':
         # To handle ruin item
         if not self.item.half or self.owner.def_damage() > 0:
             self.owner.start_hit('no_sound' not in line,
                                  self.owner.outcome() == 0)
             self.state = 'Wait'
             self.processing = False
             if self.owner.def_damage() > 0:
                 if 'no_shake' not in line:
                     if self.owner.outcome() == 2:  # Crit
                         self.owner.shake(4)
                     else:
                         self.owner.shake(3)
             elif self.owner.def_damage() == 0:
                 if 'no_shake' not in line:
                     self.owner.shake(2)
                 if self.item and (self.item.weapon or
                                   (self.item.spell and self.item.damage)):
                     self.no_damage()
     elif line[0] == 'miss':
         if self.right:
             position = (72, 21)
         else:
             position = (128, 21)  # Enemy's position
         team = self.owner.right.team if self.right else self.owner.left.team
         image = GC.IMAGESDICT['MissBlue' if team ==
                               'player' else 'MissRed']
         anim = CustomObjects.Animation(image,
                                        position, (5, 4),
                                        ignore_map=True,
                                        set_timing=(1, 1, 1, 1, 1, 1, 1, 1,
                                                    1, 1, 1, 1, 1, 1, 1, 1,
                                                    1, 1, 1, 23))
         self.animations.append(anim)
         if not self.item.half:  # Spell hit handles this
             self.owner.start_hit('no_sound' not in line, True)  # Miss
         if self.partner:
             self.partner.dodge()
     # === FLASHING ===
     elif line[0] == 'parent_tint_loop':
         num_frames = self.get_frames(line[1])
         color = [
             tuple([int(num) for num in color.split(',')])
             for color in line[2:]
         ]
         if self.parent:
             self.parent.flash(num_frames, color)
     elif line[0] == 'parent_tint':
         num_frames = self.get_frames(line[1])
         color = tuple([int(num) for num in line[2].split(',')])
         if self.parent:
             self.parent.flash(num_frames, color)
     elif line[0] == 'enemy_tint':
         num_frames = self.get_frames(line[1])
         color = tuple([int(num) for num in line[2].split(',')])
         if self.partner:
             self.partner.flash(num_frames, color)
     elif line[0] == 'enemy_gray':
         num_frames = self.get_frames(line[1])
         if self.partner:
             self.partner.flash(num_frames, 'gray')
     elif line[0] == 'enemy_flash_white':
         num_frames = self.get_frames(line[1])
         if self.partner:
             self.partner.flash(num_frames, (248, 248, 248))
     elif line[0] == 'self_flash_white':
         num_frames = self.get_frames(line[1])
         self.flash(num_frames, (248, 248, 248))
     elif line[0] == 'screen_flash_white':
         num_frames = self.get_frames(line[1])
         if len(line) > 2:
             fade_out = self.get_frames(line[2])
         else:
             fade_out = 0
         self.owner.flash_color(num_frames, fade_out, color=(248, 248, 248))
     elif line[0] == 'screen_blend':
         num_frames = self.get_frames(line[1])
         color = tuple(int(num) for num in line[2].split(','))
         self.owner.flash_color(num_frames, color=color)
     elif line[0] == 'foreground_blend':
         self.foreground_frames = self.get_frames(line[1])
         color = tuple([int(num) for num in line[2].split(',')])
         self.foreground = GC.IMAGESDICT['BlackBackground'].copy()
         self.foreground.fill(color)
     elif line[0] == 'background_blend':
         self.background_frames = self.get_frames(line[1])
         color = tuple([int(num) for num in line[2].split(',')])
         self.background = GC.IMAGESDICT['BlackBackground'].copy()
         self.background.fill(color)
     elif line[0] == 'darken':
         self.owner.darken()
     elif line[0] == 'lighten':
         self.owner.lighten()
     elif line[0] == 'platform_shake':
         self.owner.platform_shake()
     elif line[0] == 'screen_shake':
         self.owner.shake(1)
     # === ANIMATIONS ===
     elif line[0] == 'hit_spark':
         if self.owner.def_damage() > 0:
             if self.right:
                 position = (-110, -30)
             else:
                 position = (-40, -30)  # Enemy's position
             image = GC.IMAGESDICT['HitSpark']
             anim = CustomObjects.Animation(image,
                                            position, (3, 5),
                                            14,
                                            ignore_map=True,
                                            set_timing=(-1, 2, 2, 2, 2, 2,
                                                        2, 1, 1, 1, 1, 1, 1,
                                                        1, 1))
             self.animations.append(anim)
         else:  # No Damage
             self.no_damage()
     elif line[0] == 'crit_spark':
         if self.owner.def_damage() > 0:
             image = GC.IMAGESDICT['CritSpark']
             if not self.right:
                 image = Engine.flip_horiz(
                     image
                 )  # If on the left, then need to swap so enemy can have it
             anim = CustomObjects.Animation(image, (-40, -30), (3, 5),
                                            15,
                                            ignore_map=True,
                                            set_timing=(-1, 1, 1, 1, 1, 1,
                                                        1, 1, 1, 1, 1, 1, 1,
                                                        1, 1, 1))
             self.animations.append(anim)
         else:  # No Damage
             self.no_damage()
     # === EFFECTS ===
     elif line[0] == 'effect':
         image, script = GC.ANIMDICT.get_effect(line[1], self.palette_name)
         # print('Effect', script)
         child_effect = BattleAnimation(self.unit, image, script,
                                        self.palette_name, self.item)
         child_effect.awake(self.owner,
                            self.partner,
                            self.right,
                            self.at_range,
                            parent=self)
         if len(line) > 2:
             child_effect.effect_offset = tuple(
                 int(num) for num in line[2].split(','))
         child_effect.start_anim(self.current_pose)
         self.children.append(child_effect)
     elif line[0] == 'under_effect':
         image, script = GC.ANIMDICT.get_effect(line[1], self.palette_name)
         # print('Effect', script)
         child_effect = BattleAnimation(self.unit, image, script,
                                        self.palette_name, self.item)
         child_effect.awake(self.owner,
                            self.partner,
                            self.right,
                            self.at_range,
                            parent=self)
         if len(line) > 2:
             child_effect.effect_offset = tuple(
                 int(num) for num in line[2].split(','))
         child_effect.start_anim(self.current_pose)
         self.under_children.append(child_effect)
     elif line[0] == 'enemy_effect':
         image, script = GC.ANIMDICT.get_effect(line[1], self.palette_name)
         child_effect = BattleAnimation(self.partner.unit, image, script,
                                        self.palette_name, self.item)
         # Opposite effects
         child_effect.awake(self.owner,
                            self.parent,
                            not self.right,
                            self.at_range,
                            parent=self.parent.partner)
         if len(line) > 2:
             child_effect.effect_offset = tuple(
                 int(num) for num in line[2].split(','))
         child_effect.start_anim(self.current_pose)
         self.partner.children.append(child_effect)
     elif line[0] == 'enemy_under_effect':
         image, script = GC.ANIMDICT.get_effect(line[1], self.palette_name)
         child_effect = BattleAnimation(self.partner.unit, image, script,
                                        self.palette_name, self.item)
         # Opposite effects
         child_effect.awake(self.owner,
                            self.parent,
                            not self.right,
                            self.at_range,
                            parent=self.parent.partner)
         if len(line) > 2:
             child_effect.effect_offset = tuple(
                 int(num) for num in line[2].split(','))
         child_effect.start_anim(self.current_pose)
         self.partner.under_children.append(child_effect)
     elif line[0] == 'clear_all_effects':
         self.clear_all_effects()
     elif line[0] == 'blend':
         if self.blend:
             self.blend = None
         else:
             self.blend = Engine.BLEND_RGB_ADD
     elif line[0] == 'spell':
         if len(line) > 1:
             item_id = line[1]
         else:
             item_id = self.item.id
         image, script = GC.ANIMDICT.get_effect(item_id, self.palette_name)
         child_effect = BattleAnimation(self.unit, image, script,
                                        self.palette_name, self.item)
         child_effect.awake(self.owner,
                            self.partner,
                            self.right,
                            self.at_range,
                            parent=self)
         child_effect.start_anim(self.current_pose)
         self.children.append(child_effect)
     elif line[0] == 'static':
         self.static = not self.static
     elif line[0] == 'over_static':
         self.over_static = not self.over_static
     elif line[0] == 'under_static':
         self.under_static = not self.under_static
     elif line[0] == 'ignore_pan':
         self.ignore_pan = not self.ignore_pan
     elif line[0] == 'opacity':
         self.opacity = int(line[1])
     elif line[0] == 'set_parent_opacity':
         self.parent.opacity = int(line[1])
     # === LOOPING ===
     elif line[0] == 'start_loop':
         if self.end_next_loop > 0:
             self.end_next_loop -= 1
         else:
             self.loop = Loop(self.script_index)
     elif line[0] == 'end_loop':
         if self.loop:
             self.loop.end_index = self.script_index
             self.script_index = self.loop.start_index  # re-loop
     elif line[0] == 'end_parent_loop':
         self.parent.end_loop()
     elif line[0] == 'end_child_loop':
         for child in self.children:
             child.end_loop()
         for child in self.under_children:
             child.end_loop()
     elif line[0] == 'defer':
         num_frames = int(line[1])
         rest_of_line = line[2:]
         self.deferred_commands.append((num_frames, rest_of_line))
     # === CONDITIONALS ===
     elif line[0] == 'if_range':
         if not self.at_range:
             self.script_index += int(line[1])
     elif line[0] == 'nif_range':
         if self.at_range:
             self.script_index += int(line[1])
     # === MOVEMENT ===
     elif line[0] == 'pan':
         self.pan_away = not self.pan_away
         if self.pan_away:
             self.owner.pan_away()
         else:
             self.owner.pan_back()
     else:
         print('%s is not supported command' % (line[0]))
Exemplo n.º 18
0
def HandleStatusUpkeep(status, unit, gameStateObj):
    oldhp = unit.currenthp
    if status.time:
        status.time.decrement()
        logger.info('Time Status %s to %s at %s. Time left: %s', status.id,
                    unit.name, unit.position, status.time.time_left)
        if status.time.time_left <= 0:
            return "Remove"  # Don't process. Status has no more effect on unit

    elif status.remove_range:
        p_unit = gameStateObj.get_unit_from_id(status.parent_id)
        if not p_unit or not p_unit.position or not unit.position or Utility.calculate_distance(
                p_unit.position, unit.position) > status.remove_range:
            return "Remove"

    if status.hp_percentage:
        hp_change = int(
            int(unit.stats['HP']) * status.hp_percentage.percentage / 100.0)
        old_hp = unit.currenthp
        unit.change_hp(hp_change)
        # unit.currenthp += hp_change
        # unit.currenthp = Utility.clamp(unit.currenthp, 0, unit.stats['HP'])
        if unit.currenthp > old_hp:
            GC.SOUNDDICT['heal'].play()

    if status.upkeep_stat_change:
        unit.apply_stat_change(status.upkeep_stat_change.stat_change)
        status.upkeep_stat_change.count += 1

    if status.rhythm_stat_change:
        status.rhythm_stat_change.count += 1
        if status.rhythm_stat_change.count > status.rhythm_stat_change.limit:
            status.rhythm_stat_change.count = 0
            unit.apply_stat_change(status.rhythm_stat_change.reset)
        else:
            unit.apply_stat_change(status.rhythm_stat_change.change)

    if status.upkeep_animation and unit.currenthp != oldhp:
        stota = status.upkeep_animation
        if not stota.sprite:
            logger.error('Missing upkeep animation sprite for %s', status.name)
        else:
            anim = CustomObjects.Animation(
                stota.sprite, (unit.position[0], unit.position[1] - 1),
                (stota.x, stota.y),
                stota.num_frames,
                on=False)
            gameStateObj.allanimations.append(anim)

    if status.upkeeps_movement:
        if unit.team.startswith('enemy'):
            gameStateObj.boundary_manager._remove_unit(unit, gameStateObj)
            if unit.position:
                gameStateObj.boundary_manager._add_unit(unit, gameStateObj)

    unit.change_hp(0)  # Just check bounds
    # if unit.currenthp > int(unit.stats['HP']):
    #     unit.currenthp = int(unit.stats['HP'])
    if unit.movement_left > int(unit.stats['MOV']):
        unit.movement_left = max(0, int(unit.stats['MOV']))

    return oldhp, unit.currenthp
Exemplo n.º 19
0
    def __init__(self,
                 gameStateObj,
                 unit,
                 exp,
                 force_level=None,
                 force_promote=False,
                 in_combat=False):
        self.unit = unit
        # if cf.OPTIONS['debug']:
        #     print('LevelUpScreen: ', exp)

        self.expNew = min(100, exp)
        self.expOld = self.unit.exp
        self.expSet = self.expOld

        self.force_level = force_level or force_promote
        self.in_combat = in_combat
        self.prev_level = self.unit.level
        self.new_wexp = None  # For promotion

        # spriting
        self.levelUpScreen = GC.IMAGESDICT['LevelScreen']
        if self.in_combat:
            topleft = (0, 6)
            timing = [1 for _ in range(19)] + [10, 1, 1, 1, 1, 1] + [
                2 for _ in range(15)
            ] + [-1] + [1 for _ in range(12)]
            self.levelUpAnimation = CustomObjects.Animation(
                GC.IMAGESDICT['LevelUpBattle'],
                topleft, (5, 11),
                52,
                ignore_map=True,
                set_timing=timing)
        else:
            if unit.position:
                x, y = unit.position
                topleft = (x - gameStateObj.cameraOffset.x -
                           2) * GC.TILEWIDTH, (y - gameStateObj.cameraOffset.y
                                               - 1) * GC.TILEHEIGHT
            else:
                topleft = GC.WINWIDTH // 2, GC.WINHEIGHT // 2
            timing = [1 for _ in range(24)] + [44]
            self.levelUpAnimation = CustomObjects.Animation(
                GC.IMAGESDICT['LevelUpMap'],
                topleft, (5, 5),
                ignore_map=True,
                set_timing=timing)
        self.statupanimation = GC.IMAGESDICT['StatUpSpark']
        self.statunderline = GC.IMAGESDICT['StatUnderline']
        self.uparrow = GC.IMAGESDICT['LevelUpArrow']
        self.numbers = GC.IMAGESDICT['LevelUpNumber']

        self.exp_bar = None

        self.levelup_list = force_level
        self.sparkCounter = -1  # Where we are in the levelScreen spark display section
        self.lastSparkUpdate = Engine.get_time()
        self.first_spark_flag = False
        self.unit_scroll_offset = 80
        self.screen_scroll_offset = self.levelUpScreen.get_width() + 32
        self.underline_offset = 0
        self.state = CustomObjects.StateMachine('init')
        self.animations, self.arrow_animations, self.number_animations = [], [], []
        if force_level:
            # Need to prevent from going over max
            current_stats = list(self.unit.stats.values())
            klass = gameStateObj.metaDataObj['class_dict'][self.unit.klass]
            for index, stat in enumerate(self.levelup_list):
                self.levelup_list[index] = min(
                    stat, klass['max'][index] - current_stats[index].base_stat)
            self.unit.apply_levelup(self.levelup_list, exp == 0)
            self.state.changeState('levelScreen')
            self.state_time = Engine.get_time()
        if force_promote:
            self.state.changeState('item_promote')
            self.state_time = Engine.get_time()

        # TIMING
        self.total_time_for_exp = self.expNew * GC.FRAMERATE  # exp rate is 16
        self.level_up_sound_played = False
        self.SPARKTIME = 320
        self.LEVELUPWAIT = 1660
Exemplo n.º 20
0
    def draw(self, surf, gameStateObj):
        currentTime = Engine.get_time()
        # if should be displaying exp bar OR should be displaying level Up screen
        if self.state.getState() in [
                'exp_wait', 'exp_leave', 'exp0', 'exp100', 'init',
                'prepare_promote'
        ]:
            if self.exp_bar:
                self.exp_bar.draw(surf)

        elif self.state.getState() == 'levelUp':
            self.levelUpAnimation.draw(surf, gameStateObj)
            """
            marker1 = self.animationMarker[0]
            marker2 = self.animationMarker[1]
            LvlSurf = Engine.subsurface(self.levelUpAnimation, (marker2*78, marker1*16, 78, 16))
            x, y = self.unit.position
            topleft = (x-gameStateObj.cameraOffset.x-2)*GC.TILEWIDTH, (y-gameStateObj.cameraOffset.y-1)*GC.TILEHEIGHT
            surf.blit(LvlSurf, topleft)
            """

        elif self.state.getState() == 'levelScreen':
            # Highlight underline -- yellow, blue
            new_color = Image_Modification.color_transition2((88, 16, -40),
                                                             (-80, -32, 40))
            # Scroll out
            if currentTime - self.state_time > self.LEVELUPWAIT + (
                    self.get_num_sparks() + 1) * self.SPARKTIME + 300:
                self.unit_scroll_offset += 10
                self.screen_scroll_offset += 20
                self.animations = []
            else:  # scroll in
                if self.unit_scroll_offset:
                    self.lastSparkUpdate = currentTime - 300  # add 300 extra milliseconds of waiting at beginning
                self.unit_scroll_offset -= 10
                self.unit_scroll_offset = max(0, self.unit_scroll_offset)
                self.screen_scroll_offset -= 20
                self.screen_scroll_offset = max(0, self.screen_scroll_offset)

            DisplayWidth = self.levelUpScreen.get_width()
            DisplayHeight = self.levelUpScreen.get_height()
            # Level up screen
            LevelUpSurface = Engine.create_surface(
                (DisplayWidth, DisplayHeight), transparent=True, convert=True)
            # Create background
            LevelSurf = self.levelUpScreen
            LevelUpSurface.blit(LevelSurf, (0, 0))

            # Render top banner text
            long_name = gameStateObj.metaDataObj['class_dict'][
                self.unit.klass]['long_name']
            GC.FONT['text_white'].blit(long_name, LevelUpSurface, (12, 3))
            GC.FONT['text_yellow'].blit(
                cf.WORDS['Lv'], LevelUpSurface,
                (LevelUpSurface.get_width() / 2 + 12, 3))
            if self.first_spark_flag or self.force_level:
                level = str(self.unit.level)
            elif self.unit.level == 1:
                level = str(self.prev_level)
            else:
                level = str(self.unit.level - 1)
            GC.FONT['text_blue'].blit(level, LevelUpSurface,
                                      (LevelUpSurface.get_width() / 2 + 50 -
                                       GC.FONT['text_blue'].size(level)[0], 3))

            # Blit first spark
            if self.force_level and not self.first_spark_flag:
                self.first_spark_flag = True
                self.lastSparkUpdate = currentTime
            elif self.screen_scroll_offset == 0 and not self.first_spark_flag and currentTime - self.lastSparkUpdate > self.SPARKTIME + 500:
                position = (87, 27)
                spark_animation = CustomObjects.Animation(self.statupanimation,
                                                          position, (11, 1),
                                                          animation_speed=32,
                                                          ignore_map=True)
                self.animations.append(spark_animation)
                self.first_spark_flag = True
                self.lastSparkUpdate = currentTime
                # Sound
                GC.SOUNDDICT['Level_Up_Level'].play()

            # Add sparks to animation list one at a time
            if self.first_spark_flag and currentTime - self.lastSparkUpdate > self.SPARKTIME:
                self.sparkCounter += 1
                self.sparkUp = True  # Whether the sparkCounter was actually incremented or not
                if self.sparkCounter > 7:
                    self.sparkCounter = 7
                    self.sparkUp = False
                else:
                    while self.levelup_list[self.sparkCounter] == 0:
                        self.sparkCounter += 1
                        self.sparkUp = True
                        if self.sparkCounter > 7:
                            self.sparkCounter = 7
                            self.sparkUp = False
                            break

                if self.sparkUp:
                    self.underline_offset = 36  # for underline growing
                    # Add animations and Sound
                    # Animations
                    if self.sparkCounter >= 4:
                        position = (88,
                                    (self.sparkCounter - 4) * GC.TILEHEIGHT +
                                    61)
                    else:
                        position = (24, self.sparkCounter * GC.TILEHEIGHT + 61)
                    arrow_animation = CustomObjects.Animation(
                        self.uparrow, (position[0] + 31, position[1] - 37),
                        (10, 1),
                        animation_speed=32,
                        ignore_map=True,
                        hold=True)
                    self.arrow_animations.append(arrow_animation)
                    spark_animation = CustomObjects.Animation(
                        self.statupanimation,
                        position, (11, 1),
                        animation_speed=32,
                        ignore_map=True)
                    self.animations.append(spark_animation)
                    # Only 1-7 are supported increases for a levelup right now
                    # assert 8 > self.levelup_list[self.sparkCounter] > 0, "%s %s"%(self.levelup_list, self.levelup_list[self.sparkCounter])
                    if 1 <= self.levelup_list[self.sparkCounter] <= 4:
                        row = Engine.subsurface(
                            self.numbers,
                            (0,
                             (self.levelup_list[self.sparkCounter] - 1) * 24,
                             10 * 28, 24))
                        number_animation = CustomObjects.Animation(
                            row, (position[0] + 29, position[1] + 23), (10, 1),
                            animation_speed=32,
                            ignore_map=True,
                            hold=True)
                    else:
                        row = Engine.subsurface(
                            self.numbers, (0, (Utility.clamp(
                                self.levelup_list[self.sparkCounter], 1, 7) -
                                               1) * 24, 2 * 28, 24))
                        number_animation = CustomObjects.Animation(
                            row, (position[0] + 29, position[1] + 23), (2, 1),
                            animation_speed=32,
                            ignore_map=True,
                            hold=True)
                    number_animation.frameCount = -5  # delay this animation for 5 frames
                    self.animations.append(number_animation)
                    # Sound
                    GC.SOUNDDICT['Stat Up'].play()

                self.lastSparkUpdate = currentTime  # Reset the last update time.

            # HP, Str, Mag, Skl, Spd, Luck, Def, Res
            new_underline_surf = Image_Modification.change_image_color(
                self.statunderline, new_color)
            for num in range(len(self.levelup_list[0:self.sparkCounter + 1])):
                if self.levelup_list[
                        num] > 0:  # IE it should be updated, since it leveled up
                    if num == self.sparkCounter:
                        rect = (self.underline_offset, 0,
                                new_underline_surf.get_width() -
                                self.underline_offset, 3)
                        new_underline_surf = Engine.subsurface(
                            new_underline_surf, rect)
                        self.underline_offset -= 6
                        self.underline_offset = max(0, self.underline_offset)
                        if num >= 4:
                            topleft = (76 + self.underline_offset // 2,
                                       45 + GC.TILEHEIGHT * (num - 4))
                        else:
                            topleft = (12 + self.underline_offset // 2,
                                       45 + GC.TILEHEIGHT * (num))
                    else:
                        if num >= 4:
                            topleft = (76, 45 + GC.TILEHEIGHT * (num - 4))
                        else:
                            topleft = (12, 45 + GC.TILEHEIGHT * (num))
                    LevelUpSurface.blit(new_underline_surf, topleft)

            # Update and draw arrow animations
            self.arrow_animations = [
                animation for animation in self.arrow_animations
                if not animation.update(gameStateObj)
            ]
            for animation in self.arrow_animations:
                animation.draw(LevelUpSurface, gameStateObj, blend=new_color)
            # Update and draw number animations
            self.number_animations = [
                animation for animation in self.number_animations
                if not animation.update(gameStateObj)
            ]
            for animation in self.number_animations:
                animation.draw(LevelUpSurface, gameStateObj, blend=new_color)

            GC.FONT['text_yellow'].blit('HP', LevelUpSurface, (10, 35))
            GC.FONT['text_yellow'].blit(cf.WORDS['STR'], LevelUpSurface,
                                        (10, GC.TILEHEIGHT + 35))
            GC.FONT['text_yellow'].blit(cf.WORDS['MAG'], LevelUpSurface,
                                        (10, GC.TILEHEIGHT * 2 + 35))
            GC.FONT['text_yellow'].blit(cf.WORDS['SKL'], LevelUpSurface,
                                        (10, GC.TILEHEIGHT * 3 + 35))
            GC.FONT['text_yellow'].blit(
                cf.WORDS['SPD'], LevelUpSurface,
                (LevelUpSurface.get_width() / 2 + 8, 35))
            GC.FONT['text_yellow'].blit(
                cf.WORDS['LCK'], LevelUpSurface,
                (LevelUpSurface.get_width() / 2 + 8, GC.TILEHEIGHT + 35))
            GC.FONT['text_yellow'].blit(
                cf.WORDS['DEF'], LevelUpSurface,
                (LevelUpSurface.get_width() / 2 + 8, GC.TILEHEIGHT * 2 + 35))
            GC.FONT['text_yellow'].blit(
                cf.WORDS['RES'], LevelUpSurface,
                (LevelUpSurface.get_width() / 2 + 8, GC.TILEHEIGHT * 3 + 35))

            hp_text = self.unit.stats['HP'].base_stat - (
                self.levelup_list[0] if self.sparkCounter < 0 else 0)
            str_text = self.unit.stats['STR'].base_stat - (
                self.levelup_list[1] if self.sparkCounter < 1 else 0)
            mag_text = self.unit.stats['MAG'].base_stat - (
                self.levelup_list[2] if self.sparkCounter < 2 else 0)
            skl_text = self.unit.stats['SKL'].base_stat - (
                self.levelup_list[3] if self.sparkCounter < 3 else 0)
            spd_text = self.unit.stats['SPD'].base_stat - (
                self.levelup_list[4] if self.sparkCounter < 4 else 0)
            lck_text = self.unit.stats['LCK'].base_stat - (
                self.levelup_list[5] if self.sparkCounter < 5 else 0)
            def_text = self.unit.stats['DEF'].base_stat - (
                self.levelup_list[6] if self.sparkCounter < 6 else 0)
            res_text = self.unit.stats['RES'].base_stat - (
                self.levelup_list[7] if self.sparkCounter < 7 else 0)

            GC.FONT['text_blue'].blit(
                str(hp_text), LevelUpSurface,
                (50 - GC.FONT['text_blue'].size(str(hp_text))[0], 35))
            GC.FONT['text_blue'].blit(
                str(str_text), LevelUpSurface,
                (50 - GC.FONT['text_blue'].size(str(str_text))[0],
                 GC.TILEHEIGHT + 35))
            GC.FONT['text_blue'].blit(
                str(mag_text), LevelUpSurface,
                (50 - GC.FONT['text_blue'].size(str(mag_text))[0],
                 GC.TILEHEIGHT * 2 + 35))
            GC.FONT['text_blue'].blit(
                str(skl_text), LevelUpSurface,
                (50 - GC.FONT['text_blue'].size(str(skl_text))[0],
                 GC.TILEHEIGHT * 3 + 35))
            GC.FONT['text_blue'].blit(
                str(spd_text), LevelUpSurface,
                (LevelUpSurface.get_width() / 2 + 48 -
                 GC.FONT['text_blue'].size(str(spd_text))[0], 35))
            GC.FONT['text_blue'].blit(
                str(lck_text), LevelUpSurface,
                (LevelUpSurface.get_width() / 2 + 48 -
                 GC.FONT['text_blue'].size(str(lck_text))[0],
                 GC.TILEHEIGHT + 35))
            GC.FONT['text_blue'].blit(
                str(def_text), LevelUpSurface,
                (LevelUpSurface.get_width() / 2 + 48 -
                 GC.FONT['text_blue'].size(str(def_text))[0],
                 GC.TILEHEIGHT * 2 + 35))
            GC.FONT['text_blue'].blit(
                str(res_text), LevelUpSurface,
                (LevelUpSurface.get_width() / 2 + 48 -
                 GC.FONT['text_blue'].size(str(res_text))[0],
                 GC.TILEHEIGHT * 3 + 35))
            """
            # HP, Str, Mag, Skl, Spd, Luck, Def, Res
            for num in range(len(self.levelup_list[0:self.sparkCounter])):
                if self.levelup_list[num] != 0: # IE it should be updated, since it leveled up
                    # Blit number
                    if num >= 4:
                        topleft = (LevelUpSurface.get_width()/2+50, GC.TILEHEIGHT * (num - 4) + 33)
                    else:
                        topleft = (52, GC.TILEHEIGHT * num + 33)
                    change = str(self.levelup_list[num])
                    if self.levelup_list[num] > 0:
                        change = '+' + change
                    GC.FONT['stat_white'].blit(change, LevelUpSurface, topleft)
            """
            pos = (6 - self.screen_scroll_offset,
                   GC.WINHEIGHT - 8 - LevelUpSurface.get_height())
            surf.blit(LevelUpSurface, pos)

            # Blit unit's pic
            BigPortraitSurf = self.unit.bigportrait
            pos = (GC.WINWIDTH - BigPortraitSurf.get_width() - 4,
                   GC.WINHEIGHT + self.unit_scroll_offset -
                   BigPortraitSurf.get_height())
            surf.blit(BigPortraitSurf, pos)

        # Update and draw animations
        self.animations = [
            animation for animation in self.animations
            if not animation.update(gameStateObj)
        ]
        for animation in self.animations:
            animation.draw(surf, gameStateObj)