Jump to content
Korean Random

SoprachevAK

User
  • Posts

    433
  • Joined

  • Last visited

  • Days Won

    38

Everything posted by SoprachevAK

  1. Конечно это давно просится, но там есть большие вопросы к производительности, тк база данных отсортирована по танку, и надо пересортировать в другом порядке, а это надо создать новую таблицу и вставить в неё все данные из старой, это долгий и сложный процесс. Я хочу заодно немного привести таблицы в порядок, исправить например опечатки в названиях столбиков. Запланировано на обновление аналитики 2.0 Там и мод и база данных и сайт нужно будет синхронно обновить, по срокам пока не скажу Но я вот для реплеев потихоньку делаю новые удобные фильтры, они тоже станут частью 2.0
  2. Винрейт, средний урон и число боёв по всем танкам по всем игрокам в рандоме за прошлые 6 месяцев (для танков у которых 1000+ боёв), учитываются танки которые попадали в бои с игроками с модом. Прикрепляю гугл табличку и исходный CSV файл, если табличка протухнет Result_75.csv Бои дедуплицированы по arenaId, подсчитано число игроков для каждого танка
  3. Ого, реально) Думаю случайно, потому что там этот показатель можно было легко крутить, и я чисто на глаз подобрал погрешность которая меня устроила Там можно ещё более жёсткие требования выставлять, по типу что пинг менее 30мс, скорость башни < 0.0001, но тогда число выстрелов становятся сильно ниже, а погрешность не сильно меняется, лучшее что у меня получалось, это 0.02% за пределы круга, но там от всей выборки оставалось около 40к выстрелов
  4. Ну там в репозитории есть есть минимальная инструкция, но это чисто чтоб потыкать как F12 в браузере, инструкцию именно как моды делать попозже напишу в доку
  5. Написал мод имплементирующий chrome devtools protocol в танковый coherent gameface ui (то на чём написан весь новый интерфейс) Можно просто девтулзами chrome подключиться и смотреть дерево, редачить стили и вызывать js в контексте страницы. В теории на лесте должно работать, если адаптировать openwg gameface инжектор https://github.com/wotstat/wotstat-chrome-devtools-protocol
  6. Спасибо за отзыв, я рад что мод помогает! По сути я для себя делал когда был в такой же ситуации, вернулся, карты вроде знакомые, а куда играть непонятно. И мне тоже по началу мод очень помог наверстать, и потом уже сам всё помню и уверенно езжу. По поводу винрейта, у вотстата есть открытая база данных из которой можно вытащить если обладать навыками. Если не забуду завтра скину. Но там очевидно только среди игроков с модом, но их весь с много.
  7. Ну поиск по коду там и так работает, а с примерами тяжело. Я пока расписывал примеры этих двух модиков которые там есть, столько времени потратил, там такой говнокод был, что в том виде в котором он был, лучше не показывать даже Может когда нибудь в будущем можно будет скормить нейронке и попросить отрефакторить каждый.
  8. Создал доку по разработке модов, красивую, удобную, на markdown. https://docs.wotstat.info/ Заполнил то что сам знал, а в частности, всё вступление с нуля до графического мода. С примерами двух модов. Если кто нибудь захочет контрибьютить, то я только за, репа на гитхабе, авторство определяется по коммитам. Возможно, есть смысл переписать часть обучений с форума туда, но надо адаптировать под современные реалии. Скорее всего, гайды 2013-2016 года существенно устарели.
  9. А ещё было бы неплохо дождаться входа в ангар dependency.instance(IHangarSpace).onSpaceCreate += onHangarSpaceCreate dependency.instance(IHangarSpace).onSpaceDestroy += onHangarSpaceDestroy А ещё можно обрабатывать клики по кастомным ссылкам def new_handleAction(obj, *a, **k): old_handleAction(obj, *a, **k) old_handleAction = NotificationsActionsHandlers.handleAction NotificationsActionsHandlers.handleAction = new_handleAction И целиком получается вот так from typing import List, Tuple # noqa: F401 from Singleton import Singleton from constants import BigWorld from gui import SystemMessages from notification.actions_handlers import NotificationsActionsHandlers from helpers import dependency from skeletons.gui.shared.utils import IHangarSpace openWebBrowser = BigWorld.wg_openWebBrowser if hasattr(BigWorld, 'wg_openWebBrowser') else BigWorld.openWebBrowser CUSTOM_EVENT_OPEN_URL = 'CUSTOM_EVENT_OPEN_URL:' def new_handleAction(obj, *a, **k): Notifier.instance().events_handleAction(old_handleAction, obj, *a, **k) old_handleAction = NotificationsActionsHandlers.handleAction NotificationsActionsHandlers.handleAction = new_handleAction class Notifier(Singleton): @staticmethod def instance(): return Notifier() __isHangarLoaded = False __showTimer = None __notificationQueue = [] # type: List[Tuple[str, SystemMessages.SM_TYPE, str, any, any]] __hangarSpace = dependency.descriptor(IHangarSpace) # type: IHangarSpace def _singleton_init(self): self.__hangarSpace.onSpaceCreate += self.__onHangarSpaceCreate self.__hangarSpace.onSpaceDestroy += self.__onHangarSpaceDestroy def events_handleAction(self, oldHandler, obj, *a, **k): try: _, _, _, actionName = a if actionName.startswith(CUSTOM_EVENT_OPEN_URL): target = actionName.split(CUSTOM_EVENT_OPEN_URL)[1] print('Opening url %s' % target) openWebBrowser(target) else: oldHandler(obj, *a, **k) except: oldHandler(obj, *a, **k) def showNotification(self, text, type=SystemMessages.SM_TYPE.Information, priority=None, messageData=None, savedData=None): # type: (str, SystemMessages.SM_TYPE, str, any, any) -> None if self.__isHangarLoaded: print("Showing notification: [%s-%s] %s; Data: %s" % (type, priority, text, messageData)) SystemMessages.pushMessage(text, type, priority, messageData, savedData) else: self.__notificationQueue.append((text, type, priority, messageData, savedData)) def showNotificationFromData(self, message): # type: (dict) -> None text = message.get('text', None) if text is None: return self.showNotification(text, SystemMessages.SM_TYPE.of(message.get('type', 'Information')), message.get('priority', None), message.get('messageData', None), message.get('savedData', None)) def __onHangarSpaceCreate(self): if self.__isHangarLoaded: return self.__isHangarLoaded = True def showNotifications(): for notification in self.__notificationQueue: self.showNotification(notification[0], notification[1], notification[2], notification[3], notification[4]) self.__notificationQueue = [] self.__showTimer = None self.__showTimer = BigWorld.callback(1, showNotifications) def __onHangarSpaceDestroy(self, *a, **k): self.__isHangarLoaded = False if self.__showTimer: BigWorld.cancelCallback(self.__showTimer) self.__showTimer = None И использовать: Notifier.instance().showNotification( 'Чек браузера <a href="event:CUSTOM_EVENT_OPEN_URL:https://google.com">открыть гугл</a>', SystemMessages.SM_TYPE.InformationHeader, 'High', { 'header': 'TEST' } )
  10. Давно меня тут не было Я решил построить плотность распределения по выстрелам в идеальных условиях: - полное сведение и на клиентском и на серверном прицелах - неподвижный танк (скорости вращения корпуса, башни и перемещения < 0.1) - пинг менее 100мс - стрельба на дистанцию более 100 метров - снаряд упал не более чем в 100 метрах от маркера Получил, что за пределы круга сведения улетает всего 0.27% снарядов. Остальные 99.73% внутри сведения. Следовательно, погрешности вызванные рассинхронами минимальны И вот что я получил. Выглядит ну очень уж ДИСКРЕТНО. Единственное выбивается обратная волна на 1-10% разброса. Тут 180 миллионов выстрелов с RU клиента без версии 1.26.1 (График как описан тут: http://forum.tanki.su/index.php?/topic/1529130-всё-о-разбросе/
  11. Конечно) Ради ИИ в принципе затевался весь проект WotStat, и в том числе оверлей слои на миникарте. Просто пока ещё не дошли руки даже начать собирать данные для обучения. Пока не самая приоритетная задача, тк скорее всего такой мод запретят и он станет читом, а значит особого смысла тратить на него время здесь и сейчас нет. Но потом как нибудь когда доделаю всё остальное, обязательно сделаю, как минимум чисто в научных целях
  12. так это он и есть) То что на JS сделано через Coherent Gameface, и там да, чтоб что то делать, приходится редачить напрямую JS файлы, а не модики Мне это и было интересно, подумал может ты нашел способ как то добавить в него кнопку более легальным путём
  13. На сайте https://positions.wotstat.info Если он у тебя не открывается, то это РКН блочит и есть https://ru.positions.wotstat.info
  14. А расскажи как ты добавил эту кнопку? Там же интерфейс на Coherent'e
  15. Этот интерфейс на JS создаётся, в питоне его не найти
  16. Леста тоже как и вг начали давать пушке скиллы модифицировать вылетающий из неё снаряд. В частности модуль Расточка Каморы увеличивает базовый урон. Оно в игре не отображается нигде, кроме как инфы в ангаре. В ангаре и в бою, при наведении на снаряды, показывается базовое значение их ТТХ Из похожего нашел вот тут https://github.com/StranikS-Scan/WorldOfTanks-Decompiled/blob/21f74a3ba0cfabf817ad8409d4c76a622348f6c0/source/res/scripts/client/gui/shared/items_parameters/params.py#L612 И тут в xml оно же https://github.com/StranikS-Scan/WorldOfTanks-Decompiled/blob/21f74a3ba0cfabf817ad8409d4c76a622348f6c0/source/res/scripts/item_defs/vehicles/common/optional_devices/modernized_devices.xml#L750 Собственно вопрос как это вытащить в бою
  17. не, там просто счётчик был в инфе об аккаунте, а я хочу сам считать + тепловые карты + в разбивке по танку
  18. Yes, its still blocked, but also, everyone bypasses these blocks, and most likely, if a person knows what Discord is, then he knows how to bypass the blocking
  19. Какая из? Проверил на основном wotstat и снизу на сайте позиций, обе активны и работают https://discord.gg/7K8W9JE6xU
  20. Привет, удивительно что из всех мест ты написал именно сюда Напиши на почту [email protected] и разберёмся с твоей ситуацией. Вообще ключи всем приходят, они доступны сразу после покупки, дублируются на указанную почту, а ещё, можно через почту войти в личный кабинет и там найти историю покупок
  21. Ну в общем ответ на мой первоначальный вопрос как добавить слой на миникарту 1. Спавним AbstractView 2. Находим BaseBattlePage 3. Берём BaseBattlePage.minimap 4. Если это Minimap то кладём наш слой в minimap.entriesContainer и сдвигаем на minimap.entriesContainer.flags.width/2, если EpicMinimap то в epicMinimap.background и не сдивгаем 5. Размер миникарты в поинтах не зависит от зума и получить его можно их minimap.entriesContainer.flags и epicMinimap.background.originalWidth соответственно AS3 public class MinimapOverlay extends AbstractView { private var demo:Sprite = new Sprite(); override protected function configUI():void { super.configUI(); var battlePage:BaseBattlePage = getBattlePage(); if (battlePage == null) return; if (battlePage.minimap is Minimap) { var minimap:Minimap = battlePage.minimap as Minimap; var index:int = minimap.entriesContainer.getChildIndex(minimap.entriesContainer.flags); minimap.entriesContainer.addChildAt(demo, index); overlayWidth = minimap.entriesContainer.flags.width; overlayHeight = minimap.entriesContainer.flags.width; demo.x = -overlayWidth / 2; demo.y = -overlayHeight / 2; } else if (battlePage.minimap is EpicMinimap) { var epicMinimap:EpicMinimap = battlePage.minimap as EpicMinimap; epicMinimap.background.addChild(demo); overlayWidth = epicMinimap.background.originalWidth; overlayHeight = epicMinimap.background.originalHeight; } } private function getBattlePage():BaseBattlePage { var viewContainer:MainViewContainer = App.containerMgr.getContainer(LAYER_NAMES.LAYER_ORDER.indexOf(LAYER_NAMES.VIEWS)) as MainViewContainer; if (viewContainer == null) return null; for (var i:int = 0; i < viewContainer.numChildren; ++i) { var child:DisplayObject = viewContainer.getChildAt(i); if (child is BaseBattlePage) return child as BaseBattlePage; } return null; } } Python OVERLAY_VIEW = "WOTSTAT_POSITIONS_MINIMAP_OVERLAY_VIEW" def setup(): mainViewSettings = ViewSettings( OVERLAY_VIEW, MinimapOverlay, "wotstat.positions.minimapOverlay.swf", WindowLayer.WINDOW, None, ScopeTemplates.GLOBAL_SCOPE, ) g_entitiesFactories.addSettings(mainViewSettings) def onAppInitialized(event): if event.ns != APP_NAME_SPACE.SF_BATTLE: return app = ServicesLocator.appLoader.getApp(event.ns) # type: AppEntry if not app: return app.loadView(SFViewLoadParams(OVERLAY_VIEW)) g_eventBus.addListener(events.AppLifeCycleEvent.INITIALIZED, onAppInitialized, EVENT_BUS_SCOPE.GLOBAL) Но есть нюанс, XVM удаляет инстанс battlePage.minimap вместе с нашим слоем, и создаёт свою миникарту но уже без. Так что инжектить наш слой надо не на configUI, а на COMPONENT_REGISTERED и подчищать на COMPONENT_UNREGISTERED def onComponentRegistered(event): if event.alias == BATTLE_VIEW_ALIASES.MINIMAP: setup() def onComponentUnregistered(event): if event.alias == BATTLE_VIEW_ALIASES.MINIMAP: unSetup() g_eventBus.addListener(events.ComponentEvent.COMPONENT_REGISTERED, onComponentRegistered, scope=EVENT_BUS_SCOPE.GLOBAL) g_eventBus.addListener(events.ComponentEvent.COMPONENT_UNREGISTERED, onComponentUnregistered, scope=EVENT_BUS_SCOPE.GLOBAL) После всех этих манипуляций можно смело рисовать внутри нашего спрайта всё что захочется. Рисует оно векторно, так что проблем быть не должно. (скрин стального зашакален, других нет)
  22. Да, смотрел, но там нет подходящей комбинации Как я понял тут два выхода 1. Писать свой шейдер для ScaleForm (но они где то там в движке живут) 2. Вручную процессить bitmap после отрисовки и обратно делить на прозрачность, но флеш слишком медленный, чтоб это было оптимально. Как вариант можно наверное разбить картинку на чанки, и обрабатывать по одному чанку в кадр, но как то конечно костыльненько и я уже не запаривался
×
×
  • Create New...