Пример #1
0
import traceback

import requests
import asyncio
import keyboard
import websockets

from SCOFunctions.MFilePath import truePath
from SCOFunctions.MLogging import logclass
from SCOFunctions.ReplayAnalysis import analyse_replay


OverlayMessages = [] # Storage for all messages
globalOverlayMessagesSent = 0 # Global variable to keep track of messages sent. Useful when opening new overlay instances later.
lock = threading.Lock()
logger = logclass('MAIN','INFO')
initMessage = {'initEvent':True,'colors':['null','null','null','null'],'duration':60}
analysis_log_file = truePath('cache_replay_analysis.txt')
ReplayPosition = 0
AllReplays = dict()
player_winrate_data = dict()
PLAYER_HANDLES = set() # Set of handles of the main player
PLAYER_NAMES = set() # Set of names of the main player generated from handles and used in winrate notification
most_recent_playerdata = None
SETTINGS = dict()
CAnalysis = None
APP_CLOSING = False
session_games = {'Victory':0,'Defeat':0}
WEBPAGE = None
RNG_COMMANDER = dict()
Пример #2
0
import psutil
import traceback
from PyQt5 import QtCore, QtGui, QtWidgets

from SCOFunctions.MFilePath import innerPath
from SCOFunctions.MLogging import logclass

logger = logclass('SYS', 'INFO')


class SystemInfo(QtWidgets.QWidget):
    """ This widget overlays system and StarCraft II information on-screen (CPU, RAM, Disk, Network,...) """
    def __init__(self, geometry=None, process_names=None, parent=None):
        super().__init__(parent)

        if geometry == None:
            self.setGeometry(0, 0, 260, 400)
            sg = QtWidgets.QDesktopWidget().screenGeometry(0)
            self.move(sg.width() - self.width() - 10, sg.top() + 210)
        else:
            self.setGeometry(*geometry)

        self.setWindowTitle('Performance overaly position')
        self.setWindowIcon(QtGui.QIcon(innerPath('src/OverlayIcon.ico')))

        # Move to top-right

        self.setStyleSheet('color: white')

        self.setWindowFlags(QtCore.Qt.FramelessWindowHint
                            | QtCore.Qt.WindowTransparentForInput
Пример #3
0
from functools import partial
from PyQt5 import QtWidgets, QtGui, QtCore
import SCOFunctions.MUserInterface as MUI
from SCOFunctions.MLogging import logclass

logger = logclass('STATS', 'INFO')


class StatsTab(QtWidgets.QWidget):
    def __init__(self, parent):
        super().__init__()
        self.p = parent
        self.stats_maps_UI_dict = dict()
        self.stats_region_UI_dict = dict()
        self.stats_mycommander_UI_dict = dict()
        self.stats_allycommander_UI_dict = dict()

        self.FR_Stats = QtWidgets.QFrame(self)
        self.FR_Stats.setGeometry(QtCore.QRect(10, 0, 964, 151))

        # Difficulty
        self.CH_DiffCasual = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_DiffCasual.setGeometry(QtCore.QRect(10, 20, 70, 17))
        self.CH_DiffCasual.setChecked(True)
        self.CH_DiffCasual.setText("Casual")
        self.CH_DiffCasual.stateChanged.connect(self.generate_stats)

        self.CH_DiffNormal = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_DiffNormal.setGeometry(QtCore.QRect(10, 40, 70, 17))
        self.CH_DiffNormal.setChecked(True)
        self.CH_DiffNormal.setText("Normal")
Пример #4
0
import html
import time
import random
import difflib
import socket
import traceback
from datetime import datetime
import xml.etree.ElementTree as ET

from SCOFunctions.MFilePath import truePath
from SCOFunctions.SC2Dictionaries import UnitNameDict, Mutators
from SCOFunctions.MLogging import logclass

logger = logclass('TWITCH', 'INFO')
all_unit_ids = {u.lower() for u in set(UnitNameDict.keys())}
mutator_set = {m.lower() for m in set(Mutators.keys())}


class TwitchBot:
    def __init__(self, twdict):
        self.channel = twdict['channel_name']
        self.bot_name = twdict['bot_name']
        self.bot_oauth = twdict['bot_oauth']
        self.host = twdict['host']
        self.port = int(twdict['port'])
        self.banks = twdict['bank_locations']
        self.responses = twdict['responses']
        self.greetings = twdict['greetings']
        self.banned_mutators = {m.lower() for m in twdict['banned_mutators']}
        self.banned_units = {u.lower() for u in twdict['banned_units']}
Пример #5
0
import os
from PyQt5 import QtWidgets, QtGui, QtCore

import SCOFunctions.MUserInterface as MUI
import SCOFunctions.MainFunctions as MF
from SCOFunctions.MRandomizer import randomize
from SCOFunctions.MFilePath import truePath
from SCOFunctions.SC2Dictionaries import prestige_names, CommanderMastery
from SCOFunctions.MLogging import logclass

logger = logclass('RNG', 'INFO')


class RngTab(QtWidgets.QWidget):
    def __init__(self, parent):
        super().__init__()
        self.p = parent

        # Generate button
        self.BT_RNG_Generate = QtWidgets.QPushButton(self)
        self.BT_RNG_Generate.setGeometry(QtCore.QRect(720, 90, 150, 40))
        self.BT_RNG_Generate.setText('Generate')
        self.BT_RNG_Generate.clicked.connect(self.randomize_commander)

        # Description
        self.BT_RNG_Description = QtWidgets.QLabel(self)
        self.BT_RNG_Description.setGeometry(QtCore.QRect(370, 20, 510, 60))
        self.BT_RNG_Description.setWordWrap(True)
        self.BT_RNG_Description.setEnabled(False)
        self.BT_RNG_Description.setText(
            'This commander randomizer randomly chooses a combination of commander, prestige and masteries.\
Пример #6
0
import os
import mpyq
import json
import time
import traceback

from s2protocol import versions
from s2protocol.build import game_version as protocol_build
from SCOFunctions.SC2Dictionaries import map_names, prestige_names
from SCOFunctions.IdentifyMutators import identify_mutators
from SCOFunctions.MLogging import logclass

logger = logclass('PARS', 'INFO')

diff_dict = {1: 'Casual', 2: 'Normal', 3: 'Hard', 4: 'Brutal'}
region_dict = {1: 'NA', 2: 'EU', 3: 'KR', 5: 'CN', 98: 'PTR'}
valid_protocols = {
    81102: 81433,
    80871: 81433,
    76811: 76114,
    80188: 78285,
    79998: 78285,
    81433: 82457
}
protocols = [
    15405, 16561, 16605, 16755, 16939, 17266, 17326, 18092, 18468, 18574,
    19132, 19458, 19595, 19679, 21029, 22612, 23260, 24944, 26490, 27950,
    28272, 28667, 32283, 51702, 52910, 53644, 54518, 55505, 55958, 56787,
    57507, 58400, 59587, 60196, 60321, 62347, 62848, 63454, 64469, 65094,
    65384, 65895, 66668, 67188, 67926, 69232, 70154, 71061, 71523, 71663,
    72282, 73286, 73559, 73620, 74071, 74456, 74741, 75025, 75689, 75800,
Пример #7
0
import os
import json
import traceback
from datetime import datetime

from SCOFunctions.MLogging import logclass
logger = logclass('SETT', 'INFO')


def update_with_defaults(loaded: dict, default: dict):
    """ Checks `loaded` dictionary, and fills all keys that are not present with values
    from `default` dictionary. This is done recursively for any dictionaries inside"""
    if not isinstance(default, dict) or not isinstance(loaded, dict):
        raise TypeError('default and loaded has to be dictionaries')

    for key in default:
        # If there is a new key
        if not key in loaded:
            loaded[key] = default[key]
        # If dictionary recursively do the same
        if isinstance(default[key], dict):
            update_with_defaults(loaded[key], default[key])


class CSettings:
    def __init__(self):
        self.filepath = None
        self.default_settings = {
            'start_with_windows': False,
            'start_minimized': False,
            'enable_logging': True,
import statistics
import threading
from pprint import pprint

import s2protocol

from SCOFunctions.MFilePath import truePath
from SCOFunctions.MLogging import logclass, catch_exceptions
from SCOFunctions.S2Parser import s2_parse_replay
from SCOFunctions.ReplayAnalysis import analyse_replay
from SCOFunctions.HelperFunctions import get_hash
from SCOFunctions.MainFunctions import find_names_and_handles, find_replays, names_fallback
from SCOFunctions.SC2Dictionaries import bonus_objectives, mc_units, prestige_names, map_names, units_to_stats
from SCOFunctions.MReplayData import replay_data

logger = logclass('MASS', 'INFO')
lock = threading.Lock()


def parse_replay(file):
    """ Parse replay with added exceptions and set key-arguments """
    try:
        return s2_parse_replay(file, try_lastest=True, parse_events=False, onlyBlizzard=True, withoutRecoverEnabled=True)
    except s2protocol.decoders.TruncatedError:
        return None
    except Exception:
        logger.error(f"{file}\n{traceback.format_exc()}")
        return None


def calculate_difficulty_data(ReplayData):
Пример #9
0
import traceback
from PyQt5 import QtWidgets, QtGui, QtCore
import SCOFunctions.MUserInterface as MUI
from SCOFunctions.MLogging import logclass
from SCOFunctions.Settings import Setting_manager as SM

logger = logclass('GT', 'INFO')


class GameTab(QtWidgets.QWidget):
    def __init__(self, parent, TabWidget):
        super().__init__()
        self.p = parent
        self.game_UI_dict = dict()

        # Scroll
        self.SC_GamesScrollArea = QtWidgets.QScrollArea(self)
        self.SC_GamesScrollArea.setGeometry(
            QtCore.QRect(0, 30,
                         TabWidget.frameGeometry().width() - 5,
                         TabWidget.frameGeometry().height() - 30))
        self.SC_GamesScrollArea.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.SC_GamesScrollArea.setFrameShadow(QtWidgets.QFrame.Plain)
        self.SC_GamesScrollArea.setWidgetResizable(True)

        self.SC_GamesScrollAreaContent = QtWidgets.QWidget()
        self.SC_GamesScrollAreaContent.setGeometry(QtCore.QRect(
            0, 0, 931, 561))
        self.SC_GamesScrollAreaContentLayout = QtWidgets.QVBoxLayout()
        self.SC_GamesScrollAreaContentLayout.setAlignment(QtCore.Qt.AlignTop)
        self.SC_GamesScrollAreaContentLayout.setContentsMargins(10, 0, 0, 0)
}
dont_include_units = {
    "SuperWarpGate", "VoidRiftUnselectable", "UnbuildableRocksUnit",
    "TrooperMengskWeaponAAPickup", "TrooperMengskWeaponFlamethrowerPickup",
    "TrooperMengskWeaponImprovedPickup", "PsiDisintegratorPowerLink",
    "ProtossDockingBayUnit", "PnPHybridVoidRift", "PlatformConnector",
    "MutatorAmonKaraxInvisiblePylon", "KorhalGateControl",
    "HybridStasisChamberA", "HybridHoldingCellSmallUnit",
    "HybridHoldingCellUnit", "GateControlUnit", "Food1000",
    "COOPTerrazineTank", "ExpeditionJumpGate", "EnemyPathingBlocker4x4",
    "CommanderPrestigeMengskTrooperBoom", "InvisibleEscortFlying",
    "DestructibleUmojanLabTestTube", 'AmonHostDeathBeamUnit',
    'DamagedMutatorLaserDrill'
}

logger = logclass('REPA', 'INFO')


def contains_skip_strings(pname):
    """ Checks if any of skip strings is in the pname """
    lowered_name = pname.lower()
    for item in skip_strings:
        if item in lowered_name:
            return True
    return False


def upgrade_is_in_mastery_upgrades(upgrade):
    """ Checks if the upgrade is in mastery upgrades, if yes, returns the Commnader and upgrade index"""
    for co in COMasteryUpgrades:
        if upgrade in COMasteryUpgrades[co]:
Пример #11
0
import json
import webbrowser
from PyQt5 import QtWidgets, QtGui, QtCore

import SCOFunctions.MainFunctions as MF
import SCOFunctions.HelperFunctions as HF
import SCOFunctions.MUserInterface as MUI
from SCOFunctions.MFilePath import innerPath
from SCOFunctions.MTheming import MColors
from SCOFunctions.Settings import Setting_manager as SM
from SCOFunctions.FastExpand import FastExpandSelector
from SCOFunctions.MLogging import logclass, catch_exceptions

logger = logclass('TABM', 'INFO')


class MainTab(QtWidgets.QWidget):
    def __init__(self, parent, APPVERSION):
        super().__init__()
        self.p = parent
        ch_distance = 20

        # Start with Windows
        self.CH_StartWithWindows = QtWidgets.QCheckBox(self)
        self.CH_StartWithWindows.setGeometry(
            QtCore.QRect(20, ch_distance, 230, 17))
        self.CH_StartWithWindows.setText("Start with Windows")
        self.CH_StartWithWindows.setToolTip(
            "The app will start automatically with Windows")

        # Start minimized
Пример #12
0
import os
import sys
import json
import string
import requests
import zipfile
import traceback
from pathlib import Path
import psutil
from SCOFunctions.MFilePath import truePath
from SCOFunctions.MLogging import logclass

logger = logclass('HELP', 'INFO')
version_link = 'https://raw.githubusercontent.com/FluffyMaguro/SC2_Coop_overlay/master/version.txt'


def isWindows():
    if os.name == 'nt':
        return True
    return False


# Use ctypes.wintypes and regirsty stuff only on windows platform
if isWindows():
    import ctypes.wintypes
    from SCOFunctions.MRegistry import reg_add_to_startup, reg_get_startup_field_value, reg_delete_startup_field
else:
    logger.info(
        "Not a Windows operation system, won't use ctypes.wintypes or winreg")

Пример #13
0
import traceback
import keyboard
import urllib.request
from PyQt5 import QtWidgets, QtCore, QtGui

from SCOFunctions.MFilePath import innerPath
from SCOFunctions.MLogging import logclass, catch_exceptions

logger = logclass('FAST', 'INFO')


class FastExpandSelector(QtWidgets.QWidget):
    # valid_maps and valid_commanders are used by outside functions
    valid_maps = {"Chain of Ascension", "Malwarfare", "Miner Evacuation", "Part and Parcel", "The Vermillion Problem"}
    valid_commanders = ("Alarak", "Karax", "Mengsk")
    padding = 6

    # Data will be received as [MapName, PlayerPosition]
    def __init__(self, parent=None):
        super().__init__()
        self.selectedMap = ""
        self.selectedCommander = ""
        self.selectedRace = ""
        self.playerPosition = 1
        self.hotkeys = []
        self.initUI()

    def initUI(self):
        layout = QtWidgets.QVBoxLayout()
        layout.setContentsMargins(self.padding, self.padding, self.padding, self.padding)
        spacer = 10
Пример #14
0
- Normal upgrades and research are not counted
- Mind-controlled units are not counted
- Calldowns and heroes don't have resource cost and aren't counted

Inaccuracies:
- Some units killed while morphing will not reduce the army value cost (could be fixed, but very messy since how different
implementations are used in SC2. Sometimes coccons are killed at the end of transformation, and sometimes not.)
- Dehaka army values can be a bit "spiky" because the parser is accounting for deaths of units in primal combat 
a bit faster (leading to bonus army value). These spikes are removed with a additional pass.

"""

from SCOFunctions.MLogging import logclass, catch_exceptions
from SCOFunctions.SC2Dictionaries import unit_base_costs, royal_guards, horners_units, tychus_base_upgrades, tychus_ultimate_upgrades, outlaws

logger = logclass('COUNT', 'INFO')
debug_negative_members = set()


class DroneIdentifier:
    """ Class for identifying when vespene drones were created and calculating bonus vespene rate"""
    def __init__(self, com1: str, com2: str):
        self.commanders = [com1, com2]
        self.recently_used = False  # Whether the ability was recently used and is now retargeting other Refineries
        self.drones = 0  # Number of Vespene Drones
        self.refineries = set()  # Locations of refineries with drones

    def event(self, event: dict):
        """ Checks the event if a Vespene Drone was used. """
        if event['_event'] not in {
                'NNet.Game.SCmdEvent', 'NNet.Game.SCmdUpdateTargetUnitEvent'