예제 #1
0
    def __init__(self):
        BaseListOverlay.__init__(self, title="Raid Damage", size=(300, 150))

        self.Bind(wx.EVT_WINDOW_DESTROY, self.OnClose)

        analyzer = log_analyzer.get()
        analyzer.registerFrame(self)
        self.onAnalyzerTick(analyzer)
예제 #2
0
    def __init__(self):
        BaseOverlay.__init__(self, title="Healing Done")

        self.Bind(wx.EVT_WINDOW_DESTROY, self.OnClose)

        analyzer = log_analyzer.get()
        analyzer.registerFrame(self)
        self.onAnalyzerTick(analyzer)
예제 #3
0
    def __init__(self):
        BaseOverlay.__init__(self, title="Rolling DPS")

        self.Bind(wx.EVT_WINDOW_DESTROY, self.OnClose)

        analyzer = log_analyzer.get()
        analyzer.registerFrame(self)
        self.onAnalyzerTick(analyzer)
예제 #4
0
파일: tfb.py 프로젝트: TeamSWAP/swap
    def __init__(self):
        BaseListOverlay.__init__(self, title="Operator IX", size=(300, 150))

        self.Bind(wx.EVT_WINDOW_DESTROY, self.OnClose)

        analyzer = log_analyzer.get()
        analyzer.registerFrame(self)
        self.onAnalyzerTick(analyzer)
예제 #5
0
    def gotRaidUpdate(self, stream):
        prnt("RaidClient: Got raid update.")

        playerCount = stream.readByte()
        playerList = []
        for i in range(0, playerCount):
            player = {}
            player['name'] = stream.readString()
            player['connType'] = stream.readString()
            player['totalDamage'] = stream.readInt()
            player['totalDamageTaken'] = stream.readInt()
            player['avgDps'] = stream.readFloat()
            player['totalHealing'] = stream.readInt()
            player['totalHealingReceived'] = stream.readInt()
            player['avgHps'] = stream.readFloat()
            player['totalThreat'] = stream.readInt()

            # Mechanics
            player['tfbOrb'] = stream.readByte()

            playerList.append(player)

        raid.playerData = playerList
        log_analyzer.get().notifyFrames()
예제 #6
0
    def gotRaidUpdate(self, stream):
        prnt("RaidClient: Got raid update.")

        playerCount = stream.readByte()
        playerList = []
        for i in range(0, playerCount):
            player = {}
            player['name'] = stream.readString()
            player['connType'] = stream.readString()
            player['totalDamage'] = stream.readInt()
            player['totalDamageTaken'] = stream.readInt()
            player['avgDps'] = stream.readFloat()
            player['totalHealing'] = stream.readInt()
            player['totalHealingReceived'] = stream.readInt()
            player['avgHps'] = stream.readFloat()
            player['totalThreat'] = stream.readInt()

            # Mechanics
            player['tfbOrb'] = stream.readByte()

            playerList.append(player)

        raid.playerData = playerList
        log_analyzer.get().notifyFrames()
예제 #7
0
    def sendPlayerUpdate(self):
        prnt("RaidClient: Sending update...")
        analyzer = log_analyzer.get()
        stream = fuzion.ByteStream()
        stream.writeByte(pkt.PLAYER_UPDATE)
        if analyzer.parser.me:
            # TODO: Transition to sending only the name
            stream.writeString("@" + analyzer.parser.me.name)
        else:
            stream.writeString("@NoPlayer")
        stream.writeInt(analyzer.totalDamage)
        stream.writeInt(analyzer.totalDamageTaken)
        stream.writeFloat(analyzer.avgDps)
        stream.writeInt(analyzer.totalHealing)
        stream.writeInt(analyzer.totalHealingReceived)
        stream.writeFloat(analyzer.avgHps)
        stream.writeInt(analyzer.totalThreat)

        # Mechanics
        stream.writeByte(analyzer.tfbOrb)

        self.conn.send(stream)
예제 #8
0
    def sendPlayerUpdate(self):
        prnt("RaidClient: Sending update...")
        analyzer = log_analyzer.get()
        stream = fuzion.ByteStream()
        stream.writeByte(pkt.PLAYER_UPDATE)
        if analyzer.parser.me:
            # TODO: Transition to sending only the name
            stream.writeString("@" + analyzer.parser.me.name)
        else:
            stream.writeString("@NoPlayer")
        stream.writeInt(analyzer.totalDamage)
        stream.writeInt(analyzer.totalDamageTaken)
        stream.writeFloat(analyzer.avgDps)
        stream.writeInt(analyzer.totalHealing)
        stream.writeInt(analyzer.totalHealingReceived)
        stream.writeFloat(analyzer.avgHps)
        stream.writeInt(analyzer.totalThreat)

        # Mechanics
        stream.writeByte(analyzer.tfbOrb)

        self.conn.send(stream)
예제 #9
0
파일: tfb.py 프로젝트: TeamSWAP/swap
 def OnClose(self, event):
     if event.GetEventObject() == self:
         log_analyzer.get().unregisterFrame(self)
예제 #10
0
파일: swap.py 프로젝트: TeamSWAP/swap
 def onClose(self, event):
     if raid.isInRaid():
         raid.leaveRaid()
     log_analyzer.get().unregisterFrame(self)
     overlays.killAllOverlays()
     self.Destroy()
예제 #11
0
 def OnClose(self, event):
     log_analyzer.get().unregisterFrame(self)
예제 #12
0
파일: swap.py 프로젝트: TeamSWAP/swap
 def onFightBegin(self):
     self.fightSelector.SetSelection(0)
     self.dashboardFight = None
     self.onAnalyzerTick(log_analyzer.get())
예제 #13
0
 def OnClose(self, event):
     log_analyzer.get().unregisterFrame(self)
예제 #14
0
파일: swap.py 프로젝트: TeamSWAP/swap
    def __init__(self):
        wx.Frame.__init__(self, None, title="SWAP %s"%VERSION, size=(900, 520))

        if not util.isCombatLoggingEnabled():
            dlg = wx.MessageDialog(self, MSG_COMBAT_LOGGING_DISABLED_TEXT, MSG_COMBAT_LOGGING_DISABLED_TITLE, wx.OK | wx.CANCEL | wx.ICON_ERROR)
            result = dlg.ShowModal()
            dlg.Destroy()

            if result == wx.ID_OK:
                util.enableCombatLogging()

        # Check for changelog
        try:
            f = open('_changelog.txt', 'r')
        except IOError:
            pass
        else:
            with f:
                changelog = f.read()
            changelogDialog = ChangelogDialog(changelog)
            changelogDialog.ShowModal()
            changelogDialog.Destroy()
            os.remove('_changelog.txt')

        self.SetMinSize((900, 520))

        if IS_FROZEN:
            self.SetIcon(wx.Icon('swap.exe', wx.BITMAP_TYPE_ICO))
        else:
            self.SetIcon(wx.Icon('../etc/app.ico', wx.BITMAP_TYPE_ICO))

        # Setup menu bar
        menuBar = wx.MenuBar()
        self.SetMenuBar(menuBar)

        # File
        menu = wx.Menu()
        menuBar.Append(menu, "&File")
        m_exit = menu.Append(MENU_ID_EXIT, MENU_TITLE_EXIT, MENU_TIP_EXIT)
        self.Bind(wx.EVT_MENU, self.onClose, id=MENU_ID_EXIT)

        # Tools
        menu = wx.Menu()
        menuBar.Append(menu, "&Tools")

        m_preferences = menu.Append(MENU_ID_PREFERENCES, MENU_TITLE_PREFERENCES, MENU_TIP_PREFERENCES)
        self.Bind(wx.EVT_MENU, self.onPreferences, id=MENU_ID_PREFERENCES)

        menu.AppendSeparator()

        m_enrageTime = menu.Append(MENU_ID_ENRAGE_TIME, MENU_TITLE_ENRAGE_TIME, MENU_TIP_ENRAGE_TIME)
        self.Bind(wx.EVT_MENU, self.onSetEnrageTime, id=MENU_ID_ENRAGE_TIME)

        # Overlay
        menu = wx.Menu()
        menuBar.Append(menu, "&Overlay")

        categoryMenus = {}
        for category in overlays.getOverlayCategoryList():
            name = category['name']
            title = category['title']
            categoryMenus[name] = subMenu = wx.Menu()
            menu.AppendSubMenu(subMenu, title, "")

        self.m_overlays = {}
        for overlay in overlays.getOverlayList():
            targetMenu = menu
            if overlay['category'] != None:
                targetMenu = categoryMenus[overlay['category']]
            if overlay['name'] == '-':
                targetMenu.AppendSeparator()
                continue
            id = wx.NewId()
            self.m_overlays[id] = targetMenu.AppendCheckItem(id, overlay['title'], MENU_TIP_OVERLAY_SELECT)
            self.Bind(wx.EVT_MENU, (lambda n: lambda e: overlays.toggleOverlay(n))(overlay['name']), id=id)

        menu.AppendSeparator()
        m_dark = menu.AppendCheckItem(MENU_ID_OVERLAY_DARK, MENU_TITLE_OVERLAY_DARK, MENU_TIP_OVERLAY_DARK)
        m_dark.Check(overlays.isDarkTheme())
        self.Bind(wx.EVT_MENU, lambda e: overlays.toggleDarkTheme(), id=MENU_ID_OVERLAY_DARK)

        m_sizeToGrid = menu.AppendCheckItem(MENU_ID_OVERLAY_SIZE_TO_GRID, MENU_TITLE_OVERLAY_SIZE_TO_GRID, MENU_TIP_OVERLAY_SIZE_TO_GRID)
        m_sizeToGrid.Check(config.get("overlaySizeToGrid") == True)
        self.Bind(wx.EVT_MENU, lambda e: config.set("overlaySizeToGrid", m_sizeToGrid.IsChecked()), id=MENU_ID_OVERLAY_SIZE_TO_GRID)

        m_snapOverlays = menu.AppendCheckItem(MENU_ID_OVERLAY_SNAP, MENU_TITLE_OVERLAY_SNAP, MENU_TIP_OVERLAY_SNAP)
        m_snapOverlays.Check(config.get("overlaySnap") == True)
        self.Bind(wx.EVT_MENU, lambda e: config.set("overlaySnap", m_snapOverlays.IsChecked()), id=MENU_ID_OVERLAY_SNAP)

        m_clickThrough = menu.AppendCheckItem(MENU_ID_OVERLAY_CLICK_THROUGH, MENU_TITLE_OVERLAY_CLICK_THROUGH, MENU_TIP_OVERLAY_CLICK_THROUGH)
        m_clickThrough.Check(config.get("overlayClickThrough") == True)
        self.Bind(wx.EVT_MENU, lambda e: config.set("overlayClickThrough", m_clickThrough.IsChecked()), id=MENU_ID_OVERLAY_CLICK_THROUGH)

        menu.AppendSeparator()

        m_reset = menu.Append(MENU_ID_OVERLAY_RESET, MENU_TITLE_OVERLAY_RESET, MENU_TIP_OVERLAY_RESET)
        self.Bind(wx.EVT_MENU, self.onResetOverlays, id=MENU_ID_OVERLAY_RESET)

        m_close = menu.Append(MENU_ID_OVERLAY_CLOSE, MENU_TITLE_OVERLAY_CLOSE, MENU_TIP_OVERLAY_CLOSE)
        self.Bind(wx.EVT_MENU, self.onCloseOverlays, id=MENU_ID_OVERLAY_CLOSE)

        # Help
        menu = wx.Menu()
        menuBar.Append(menu, "&Help")
        m_checkUpdates = menu.Append(MENU_ID_HELP_UPDATES, MENU_TITLE_HELP_UPDATES, MENU_TIP_HELP_UPDATES)
        m_openLog = menu.Append(MENU_ID_HELP_LOG, MENU_TITLE_HELP_LOG, MENU_TIP_HELP_LOG)
        m_sendLog = menu.Append(MENU_ID_HELP_SEND_LOG, MENU_TITLE_HELP_SEND_LOG, MENU_TIP_HELP_SEND_LOG)
        menu.AppendSeparator()
        m_about = menu.Append(MENU_ID_HELP_ABOUT, MENU_TITLE_HELP_ABOUT, MENU_TIP_HELP_ABOUT)
        self.Bind(wx.EVT_MENU, self.onCheckUpdates, id=MENU_ID_HELP_UPDATES)
        self.Bind(wx.EVT_MENU, self.onOpenLog, id=MENU_ID_HELP_LOG)
        self.Bind(wx.EVT_MENU, self.onSendLog, id=MENU_ID_HELP_SEND_LOG)
        self.Bind(wx.EVT_MENU, self.onAbout, id=MENU_ID_HELP_ABOUT)

        # UI
        self.panel = wx.Panel(self)
        self.panel.SetDoubleBuffered(True)
        self.horzBox = wx.BoxSizer(wx.HORIZONTAL)
        self.box = wx.BoxSizer(wx.VERTICAL)
        self.horzBox.Add(self.box, 1, wx.EXPAND)

        # -----------------------------------
        # Header
        # -----------------------------------

        headerBox = wx.BoxSizer(wx.HORIZONTAL)

        self.keyText = wx.StaticText(self.panel, -1, "Key:")
        self.keyBox = wx.TextCtrl(self.panel, -1, "", size=(150, -1))

        lastRaidKey = config.get("lastRaidKey")
        if lastRaidKey:
            self.keyBox.SetValue(lastRaidKey)

        self.keyGenerateButton = wx.Button(self.panel, -1, "Generate")
        self.keyGenerateButton.Bind(wx.EVT_BUTTON, self.onGenerateButton)

        self.keyJoinButton = wx.Button(self.panel, -1, "Join Raid")
        self.keyJoinButton.Bind(wx.EVT_BUTTON, self.onJoinRaidButton)

        self.keyVanityCheck = wx.CheckBox(self.panel, -1, "Generate Vanity Key")
        self.keyStatus = wx.StaticText(self.panel, -1, "")

        self.fightSelector = wx.Choice(self.panel, -1)
        self.fightSelector.Append("Latest Fight", None)
        self.fightSelector.SetSelection(0)
        self.fightSelector.Bind(wx.EVT_CHOICE, self.onFightSelected)

        log_parser.get().registerObserver(log_parser.Parser.EVENT_FIGHT_BEGIN, util.wxFunc(self.onFightBegin))
        log_parser.get().registerObserver(log_parser.Parser.EVENT_FIGHT_END, util.wxFunc(self.onFightEnd))
        log_parser.get().registerObserver(log_parser.Parser.EVENT_NEW_LOG, util.wxFunc(self.onNewLog))
        log_parser.get().registerObserver(log_parser.Parser.EVENT_READY, util.wxFunc(self.onParserReady))

        if log_parser.get().ready:
            self.onParserReady()

        self.dashboardFight = None
        self.historicRaidFights = {}

        headerBox.Add(self.keyText, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 10)
        headerBox.Add(self.keyBox, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 10)
        headerBox.Add(self.keyGenerateButton, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
        headerBox.Add(self.keyJoinButton, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 10)
        headerBox.Add(self.keyVanityCheck, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT)
        headerBox.Add(self.keyStatus, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 10)
        headerBox.Add(self.fightSelector, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 10)
        self.box.Add(headerBox, 0, wx.EXPAND | wx.ALL, 10)

        # -----------------------------------
        # Tabs
        # -----------------------------------

        self.tabs = wx.Notebook(self.panel)

        # Create Overview tab
        self.overviewPanel = wx.Panel(self.tabs)
        self.overviewSizer = wx.BoxSizer(wx.VERTICAL)
        self.overviewPanel.SetSizer(self.overviewSizer)
        self.overviewPanel.Layout()
        self.createOverviewView(self.overviewSizer, self.overviewPanel)
        self.tabs.AddPage(self.overviewPanel, "Overview")

        # Create Report tab
        self.reportPanel = wx.Panel(self.tabs)
        self.reportSizer = wx.BoxSizer(wx.VERTICAL)
        self.reportPanel.SetSizer(self.reportSizer)
        self.reportPanel.Layout()
        self.createReportView(self.reportSizer, self.reportPanel)
        self.tabs.AddPage(self.reportPanel, "Report")

        # Create Raid tab
        self.raidPanel = wx.Panel(self.tabs)
        self.raidSizer = wx.BoxSizer(wx.VERTICAL)
        self.raidPanel.SetSizer(self.raidSizer)
        self.raidPanel.Layout()
        self.createRaidView(self.raidSizer, self.raidPanel)
        self.tabs.AddPage(self.raidPanel, "Raid")

        # Create Ability tab
        self.abilityPanel = wx.Panel(self.tabs)
        self.abilitySizer = wx.BoxSizer(wx.VERTICAL)
        self.abilityPanel.SetSizer(self.abilitySizer)
        self.abilityPanel.Layout()
        self.createAbilityView(self.abilitySizer, self.abilityPanel)
        self.tabs.AddPage(self.abilityPanel, "By Ability")

        # Create Targets tab
        self.targetsPanel = wx.Panel(self.tabs)
        self.targetsSizer = wx.BoxSizer(wx.VERTICAL)
        self.targetsPanel.SetSizer(self.targetsSizer)
        self.targetsPanel.Layout()
        self.createTargetsView(self.targetsSizer, self.targetsPanel)
        self.tabs.AddPage(self.targetsPanel, "By Target")

        self.box.Add(self.tabs, 1, wx.EXPAND | wx.ALL & ~wx.TOP, 10)

        # -----------------------------------
        # Console
        # -----------------------------------
        self.console = wx.TextCtrl(self.panel, style=wx.TE_MULTILINE |
             wx.TE_READONLY, size=(200, -1))
        self.console.SetFont(wx.Font(7, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
        self.horzBox.Add(self.console, 0, wx.EXPAND | wx.ALL & ~wx.LEFT, 10)

        self.panel.SetSizer(self.horzBox)
        self.panel.Layout()

        # Events
        self.Bind(wx.EVT_CLOSE, self.onClose)

        log_analyzer.get().registerFrame(self)

        self.addToConsole("SWAP %s started."%(VERSION))
예제 #15
0
 def OnClose(self, event):
     if event.GetEventObject() == self:
         log_analyzer.get().unregisterFrame(self)
예제 #16
0
파일: swap.py 프로젝트: TeamSWAP/swap
 def onFightSelected(self, event):
     self.dashboardFight = self.fightSelector.GetClientData(self.fightSelector.GetSelection())
     self.onAnalyzerTick(log_analyzer.get())
예제 #17
0
파일: swap.py 프로젝트: TeamSWAP/swap
 def onNewLog(self):
     for i in range(1, self.fightSelector.GetCount()):
         self.fightSelector.Delete(1)
     self.fightSelector.SetSelection(0)
     self.dashboardFight = None
     self.onAnalyzerTick(log_analyzer.get())
예제 #18
0
파일: log_parser.py 프로젝트: TeamSWAP/swap
    def run(self, hasStopped):
        prnt("Parser: Starting...")

        log = None
        try:
            if self.logLocation == None:
                raise Exception("No log location set. Did you forget to call getDocs?")

            logInfo = self.getNewestLog()
            if logInfo == None:
                prnt("Parser: Waiting for log...")
                while not hasStopped.isSet():
                    logInfo = self.getNewestLog()
                    if logInfo != None:
                        break
                    time.sleep(0.4)
                if hasStopped.isSet():
                    return True
            (logFile, logPath) = logInfo

            log = open(logPath, 'r')

            self.inCombat = False
            self.fights = []
            self.fight = None
            self.ready = False
            self.disappearEvent = None
            self._entityLookup = {}

            inUpdate = False

            logCursor = 0
            logDay = self.getMidnightTimestampForFile(logPath)
            logLastActionTime = 0

            prnt("Parser: Began parsing %s"%logFile)
            prnt("Parser: Log day is %s"%datetime.datetime.fromtimestamp(logDay))

            lastLogFileCheck = time.time()

            while not hasStopped.isSet():
                if time.time() - lastLogFileCheck > 1:
                    if logFile != self.getNewestLog(onlyFilename=True):
                        (logFile, logPath) = self.getNewestLog()

                        prnt("Parser: Switched to parsing %s"%logFile)

                        # Close previous log, and open new one.
                        log.close()
                        log = open(logPath, 'r')

                        # Reset vars
                        self.inCombat = False
                        self.fights = []
                        self.fight = None
                        self.ready = False
                        self.me = None
                        self.disappearEvent = None
                        self._entityLookup = {}

                        inUpdate = False

                        logCursor = 0
                        logDay = self.getMidnightTimestampForFile(logPath)
                        logLastActionTime = 0
                        prnt("Parser: Log day is %s"%datetime.datetime.fromtimestamp(logDay))

                        self.notifyEvent(Parser.EVENT_NEW_LOG)
                    lastLogFileCheck = time.time()
                logCursor = log.tell()
                line = log.readline()
                if line == "":
                    # Once we reach EOF mark us as ready for analyzation.
                    if not self.ready:
                        self.ready = True
                        self.notifyEvent(Parser.EVENT_READY)
                    if inUpdate:
                        inUpdate = False
                        analyzer = log_analyzer.get()
                        analyzer.updatePing.set()
                    time.sleep(.25)
                    continue
                inUpdate = True

                res = self.linePat.match(line)
                if res:
                    hour = int(res.group('hour'))
                    minute = int(res.group('minute'))
                    second = int(res.group('second'))
                    ms = int(res.group('ms'))
                    actor = res.group('actor')
                    target = res.group('target')
                    ability = res.group('ability')
                    abilityId = res.group('abilityid')
                    action = res.group('action')
                    actionId = res.group('actionid')
                    actionType = res.group('actiontype')
                    actionTypeId = res.group('actiontypeid')
                    result = res.group('result')
                    threat = int(res.group('threat')) if res.group('threat') else 0

                    actionTime = logDay + (hour * 3600) + (minute * 60) + second + (ms / 1000.0)
                    # Check for date rollover.
                    if actionTime < logLastActionTime and logLastActionTime - actionTime > 43200:
                        logDay += 86400
                        actionTime += 86400
                        prnt("Parser: Rollover, day is now %s"%datetime.datetime.fromtimestamp(logDay))
                    logLastActionTime = actionTime

                    for entity in (actor, target):
                        if entity not in self._entityLookup:
                            ent = Entity(entity)
                            self._entityLookup[entity] = ent
                        else:
                            ent = self._entityLookup[entity]
                        if self.fight and ent not in self.fight.entities:
                            self.fight.entities.append(ent)

                    actor = self._entityLookup[actor]
                    target = self._entityLookup[target]

                    # Serious introspection here, man
                    if (self.me == None and actor == target and not actor.companion and
                           not actor.mob):
                        prnt("Parser: Identified %s as me"%actor.name)
                        self.me = actor
                        self.notifyEvent(Parser.EVENT_PLAYER_IDENTIFIED)

                    event = GameEvent()
                    event.type = self.resolveEventType(actionId, actionTypeId)
                    event.actor = actor
                    event.target = target
                    event.ability = abilityId
                    event.abilityName = ability
                    event.actionType = actionTypeId
                    event.actionTypeName = actionType
                    event.inCombat = self.inCombat
                    event.time = actionTime
                    event.readTime = time.time()
                    event.threat = threat
                    event.enterEvent = False
                    event.exitEvent = False
                    event.recent = self.ready

                    if event.type == evt.ENTER_COMBAT:
                        event.enterEvent = True
                    elif event.type == evt.EXIT_COMBAT:
                        event.exitEvent = True
                    elif event.type == evt.DEATH and self.inCombat and event.target == self.me:
                        event.exitEvent = True
                    elif event.type == evt.APPLY_BUFF and event.actionType == '973870949466372' and self.inCombat:
                        # Safe Login Immunity
                        event.exitEvent = True

                    # Detect disappear
                    if self.fights and event.type == evt.ABILITY_ACTIVATE and event.ability in abl.DISAPPEAR:
                        lastFight = self.fights[-1]
                        exitBluff = False
                        # Look back for exit combat.
                        for e in reversed(lastFight.events):
                            if e.exitEvent:
                                e.exitEvent = False
                                exitBluff = True
                                break
                            if event.time - e.time > 0.100:
                                break
                        if exitBluff:
                            self.disappearEvent = event

                    # Clear disappear flag if out of grace period
                    if self.disappearEvent and event.time - self.disappearEvent.time > DISAPPEAR_GRACE:
                        self.disappearEvent = None

                    if event.enterEvent:
                        newFight = True
                        if self.disappearEvent:
                            # Continue fight if within grace period
                            if event.time - self.disappearEvent.time <= DISAPPEAR_GRACE:
                                self.fight = self.fights[-1]
                                self.inCombat = True
                                newFight = False
                            self.disappearEvent = None
                        if newFight:
                            fight = Fight()
                            fight.enterEvent = event
                            fight.enterTime = event.time
                            self.fights.append(fight)
                            self.fight = fight
                            self.inCombat = True
                            if self.ready:
                                self.notifyEvent(Parser.EVENT_FIGHT_BEGIN)
                    elif event.exitEvent:
                        self.inCombat = False

                    if event.type == evt.DAMAGE:
                        sp = result.split(' ')
                        if len(sp) > 2:
                            dmg = sp[0]
                            dmgType = sp[1]
                            dmgTypeId = sp[2]
                            if dmg.endswith('*'):
                                dmg = dmg[:-1]
                            dmg = int(dmg)
                            if len(sp) == 6:
                                fourth = sp[3]
                                fifth = sp[4]
                                sixth = sp[5]
                                if fifth == 'absorbed' and event.target == self.me:
                                    absorbAmount = int(fourth[1:])
                                    dmg -= absorbAmount
                        else:
                            dmg = 0
                        event.damage = dmg

                    if event.type == evt.HEAL:
                        heal = result
                        if heal.endswith('*'):
                            heal = heal[:-1]
                        event.healing = int(heal)

                    if self.fight:
                        for entity in (event.actor, event.target):
                            if entity == self.me or entity.companion:
                                continue
                            priority = event.damage + event.threat
                            if not priority:
                                continue
                            if entity in self.fight.priorityTargets:
                                self.fight.priorityTargets[entity] += priority
                                continue
                            self.fight.priorityTargets[entity] = priority

                    if self.fight != None:
                        self.fight.events.append(event)

                    if event.exitEvent and self.fight:
                        self.fight.exitEvent = event
                        self.fight.exitTime = event.time
                        self.fight = None
                        if self.ready:
                            self.notifyEvent(Parser.EVENT_FIGHT_END)
                elif line[-1] != '\n' and line[-1] != '\r':
                    log.seek(logCursor)
                    time.sleep(0.25)

                time.sleep(.0001)
        except Exception:
            if log != None:
                log.close()
            prnt(traceback.format_exc())
            return False
        log.close()
        prnt("Parser: Exiting normally...")
        return True