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()
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
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")
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']}
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.\
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,
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):
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]:
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
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")
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
- 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'