Jump to content
Korean Random

StranikS_Scan

Premium Member
  • Content Count

    7,769
  • Joined

  • Last visited

  • Days Won

    236

Everything posted by StranikS_Scan

  1. Там всё через токены application_id, разница только в ограничениях. Автономные приложения могут слать запросы с любых айпи, ибо будут запускаться разными юзверами. А серверное только с фиксированных, заранее перечисленных в кабинете, айпи. И для серверного токена больше лимит по запросам в секунду (вроде). Про компрометацию, это я не понял о чем ты. Если про перехват, то API - публичный, какие вопросы перехвата тут могут быть?
  2. Это не моды жы. ------------------------ По модам, XVM раньше писал на сайте о кол-во активных юзверов (как реклама), последний раз когда видел лейбл, было вроде написано об 3+ млн, из них думаю не менее 50% ставят его через толстые модпаки, так что 1-1,5 млн активного онлайна точно юзают модпаки. Если смотреть тот же сайт вгмодс, счетчик скачивания толстых модпаков, то там цифры побольше будут, но цифра скачивания совершенно не значит, что онлайн именно такой. Жовопак ~ 12 млн Корбен ~ 0,5 млн Юшапак - 11 + 19 +1 = 31 млн Трамвай - 3,5 млн Вспышка - 0,5 млн ... дальше мелочь. Итого: ~47,5 млн, если добрать мелочь, то будет красивая цифра 50 млн. Из этой цифры активноиграющие игорьки, это 10%, что получаем 5 млн. Что вроде бы говорит о том, что они могут юзать потенциально твой мод, если модпакеры решат его включить в свой паки. Но есть один важный момент, который ломает эту картинку, это % игроков с запрещенными модами и паками. Из активного онлайна, кто рубится в тынки, 40-60% всегда играет с какой-то запрещенкой, большинство по мелочи, аля "мине нада тока тундру остальное фигня", а кто-то и по крупному с платными модпаками. Эти товарищи наоборот - будут избегать юзать твой мод, ибо он сливает инфу на твой сервер. Что в сухом остатке, думаю , если (SoprachevAK) договоришься с @Yusha и мод будет в модпаке, то 5-10 тыс. онлайна вполне может появится и база начнет быстро расти.
  3. Ну типа шансов меньше сбить гуслю, если у врага закалка.
  4. Зачем вообще эта информация о том, есть закалка или нет, если она сводится только к добавке к ХП, а эту добавку мы видим и так?
  5. Понимает dds-формат. Однако нет никакого смысла юзать GUI, он кривой, не красивый и очень неудобный. Юзай GUIFlash. Все на нем сидят.
  6. Нормально. Приходишь на форум отвлечься после рабочего дня, а тут какой-то аноним возмущен, что ты не хочешь сделать ему мод за пару тугриков, которые он со школьных завтраков скопил. Мы, уважаемый, это так видим со свей колокольни, от того и нет в нас энтузиазма.
  7. Ты столько не напуляешь, чтоб выборка стала репрезентативной. Помню на раковом один дед-грибоед, КРОТ его знает, на Тигре собирал выборки. Создавал акк, накатывал до тигра и на нем играл. Потом опять новый акк и т.д. Ну и конечно же у него на разных акка статистики отличались.
  8. @KPOT2338 как у Задорного про Ельцина "ты чего это мне мои счета показываешь..." )))) Сервер же всё знает, какая разница что там приходит или нет на клиент игры ))))
  9. Ну круто, курил что было, а видос с трешевым названием типа "Сенсация! Угнетают!" таки запилил. Дык мог не париться просто наврать в видео да и всё. Просмотры бы все равно собрал. Ты уж извини, но я вашего брата называю ютуберы-балаболы, вот именно из-за такого контента. А реплеи сейчас собираешь откуда? Если с какого-нибудь wotreplays.ru выгружаешь, то опять не репрезентативно, ибо их туда заливают потому что они особенные для тех, кто их залил.
  10. 152 выстрела? Это не репрезентативная выборка. Она ровным счетом ничего не показывает. Нужно 15к выстрелов и рандомные игроки.
  11. А на графике дистанция какому конкретно параметру в пайтон-коде соответствует? Почему нет? Мерить то можно. Круг отрисовки - это круг отображения моделей.
  12. А САУ то как тогда в аркадном наводится будет. У неё дистанция 10 км. Ну и дальномер в игре используют также чтобы и расстояния мерить.
  13. Колеса загрузки и картинки - это флэшки. Это не Python.
  14. Обновление 1.3.1 1. Добавлено получение и отображение количества игроков на серверах игры 2. На случай проблем с доступом к GitHub в ресурсы exe-файла добавлена локальная копия списка серверов 3. Добавлено запоминание столбца сортировки в окне сводных параметров 4. Внесены правки в интерфейс 5. Обновлен список серверов на GitHub ИНФОРМАЦИЯ ДЛЯ МОДОДЕЛОВ Для получения онлайна игроков, программа использует открытый api-сервис с моего сайта http://straniks.ru/pub/api/v1/wot_online.php?online=all. На сайте данные обновляются каждые 30 сек. Возвращаемый результат имеет вид: {"RU1":37005,"RU2":37580,"RU3":5677,"RU4":20522,"RU5":27002,"RU6":26905,"RU7":19271,"RU8":26119,"RU9":11411,"RU10":1523,"RU11":563,"EU1":27883,"EU2":24220,"USC":1225,"LATAM":1204,"HK":13250,"ANZ":1346} Поддерживаются аргументы all, ru, eu, na, asia. Получение данных о китайских серверах не реализовано т.к. то ли у них не все функции api работают из-за смены партнера у ВГ, то ли я не смог до конца разобраться как их получить.
  15. Результаты боев приходят в кэш и надо его оттуда дергать. Кэш, это файлы вот тут .../AppData/Roaming/Wargaming.net/WorldOfTanks\battle_results\..... А дергать если правильно помню в модах делают это через BigWorld.player().battleResultsCache. Ниже очередной чей-то древний код из моей библиотеки, что насобирал, он думаю тебе поможет. Это как дергать через battleResultsCache # -*- coding: utf-8 -*- import BigWorld, threading from Queue import Queue from functools import partial from PlayerEvents import g_playerEvents from messenger.formatters.service_channel import BattleResultsFormatter Threads = True ArenaIDQueue = Queue() ResultsQueue = Queue() old_format = BattleResultsFormatter.format def init(): g_playerEvents.onAvatarReady += IntoBattle g_playerEvents.onAccountBecomePlayer += self.onAccountBecomePlayer def onAccountBecomePlayer(): Results.ResultsAvailable.set() def IntoBattle(): Results.ResultsAvailable.clear() def format(self, message, *args): arenaUniqueID = message.data.get('arenaUniqueID', 0) ArenaIDQueue.put(arenaUniqueID) return old_format(self, message, *args) def fini(): Threads = False class BattleResultParser(object): def __init__(self): self.ResultsCache = [] self.ResultsAvailable = threading.Event() self.thread = threading.Thread(target = self.WaitResult) self.thread.setDaemon(True) self.thread.setName('WaitResult') self.thread.start() def CheckCallback(self, ArenaUniqueID, ErrorCode, Result): if ErrorCode in [-3, -5]: BigWorld.callback(1.0, lambda: ArenaIDQueue.put(ArenaUniqueID)) elif ErrorCode >= 0: if ArenaUniqueID in self.ResultsCache: return print Result.get('arenaUniqueID') print Result.get('personal') print Result.get('common') def WaitResult(self): while Threads: ArenaUniqueID = ArenaIDQueue.get() self.ResultsAvailable.wait() try: BigWorld.player().battleResultsCache.get(ArenaUniqueID, partial(self.CheckCallback, ArenaUniqueID)) except: pass BattleResultsFormatter.format = format Results = BattleResultParser() А тут вручную этот файл перехватывают и дампят, зачем, я хз import BigWorld import Math from gui.shared.utils.requesters import StatsRequester import AccountCommands import cPickle import zlib import os import base64 from battle_results_shared import * from messenger.proto.bw import ServiceChannelManager from functools import partial from gui import ClientHangarSpace from debug_utils import * BATTLE_RESULTS_VERSION = 1 CACHE_DIR = os.path.join(os.path.dirname(unicode(BigWorld.wg_getPreferencesFilePath(), 'utf-8', errors='ignore')), 'battle_results') todolist = [] waiting = False def new_valueResponse(self, responseCode, value = None, revision = 0): if responseCode < 0: LOG_NOTE('Battleresult not available or already retrieved. Response Code=%s' % responseCode) elif StatsRequester.__callback: StatsRequester.__callback(value) def fetchresult(arenaUID): global waiting if arenaUID: waiting = True proxy = partial(__onGetResponse, new_valueResponse) BigWorld.player()._doCmdInt3(AccountCommands.CMD_REQ_BATTLE_RESULTS, arenaUID, 0, 0, proxy) def __onGetResponse(callback, requestID, resultID, errorStr, ext = {}): global waiting if resultID != AccountCommands.RES_STREAM: waiting = False if callback is not None: try: callback(resultID, None) except: LOG_CURRENT_EXCEPTION() else: BigWorld.player()._subscribeForStream(requestID, partial(__onStreamComplete, callback)) def __onStreamComplete(callback, isSuccess, data): try: battleResults = cPickle.loads(zlib.decompress(data)) save(BigWorld.player().name, battleResults) except: LOG_CURRENT_EXCEPTION() if callback is not None: callback(AccountCommands.RES_FAILURE, None) def getFolderName(accountName, arenaUniqueID): battleStartTime = arenaUniqueID & 4294967295L battleStartDay = battleStartTime / 86400 return os.path.join(CACHE_DIR, base64.b32encode('%s;%s' % (accountName, battleStartDay))) def save(accountName, battleResults): fileHandler = None try: arenaUniqueID = battleResults[0] LOG_NOTE('Saving results of arenaUniqueID:', arenaUniqueID) folderName = getFolderName(accountName, arenaUniqueID) LOG_NOTE('Savefile Folder:', folderName) if not os.path.isdir(folderName): os.makedirs(folderName) fileName = os.path.join(folderName, '%s.dat' % arenaUniqueID) fileHandler = open(fileName, 'wb') cPickle.dump((BATTLE_RESULTS_VERSION, battleResults), fileHandler, -1) except: LOG_CURRENT_EXCEPTION() if fileHandler is not None: fileHandler.close() old_msg = ServiceChannelManager._ServiceChannelManager__addServerMessage def new_msg(self, message): global todolist LOG_NOTE('Message:', message) if message.type == 2: try: todolist.append(message.data.get('arenaUniqueID', 0)) except: LOG_CURRENT_EXCEPTION() old_msg(self, message) ServiceChannelManager._ServiceChannelManager__addServerMessage = new_msg old_setup = ClientHangarSpace._VehicleAppearance._VehicleAppearance__doFinalSetup def new_setup(self, buildIdx, model, delModel): global todolist if todolist: LOG_NOTE('Start work on my ToDoList:', todolist) while todolist: if waiting: time.delay(0.5) else: temp = todolist.pop() fetchresult(int(temp)) old_setup(self, buildIdx, model, delModel) ClientHangarSpace._VehicleAppearance._VehicleAppearance__doFinalSetup = new_setup
  16. Гугл аналитик у них и там у всех подключен. Не думаю, что раскрывать свою статистику кто-то будет. Иначе бы давно её публиковали бы. Я думаю тебе стоит не распыляться, а сосредоточится на первоочередных задачах.
  17. Дык о какой полноте может идти речь, если выборка изначально неполна и субъективна? Ты же собираешь не первичные данные, типа чисел на выходе ГПСЧ, а координаты попадания снарядов. У тебя изначально нет и не будет никакой "полной исходной последовательности", только её отголоски.
  18. И как результат забьешь БД мусором, а потом получишь интегральные показатели, которые ничего не показывают. Качество анализа напрямую зависит от качества исходных данных. Тут не все так однозначно. Ведь качество собранного материала, а точнее точность с которой определен разброс выстрела модом очень разнится в зависимости от ситуации.
  19. Их нужно игнорировать. Они бессмысленны. Снаряд пропадает. Надо тоже игнорировать. Ну должно быть три типа выстрела: - в небо, перелёт, пропал, пулемётные танки: эти игнорируем - попадание в ландшафт: грузим на сервер с пометкой вида - попадание в коллижен: грузим на сервер с пометкой вида
  20. Тогда уж мод, который бы по нажатию кнопки или комбинации клавиш выбирал случайно слот с танком в карусели.
  21. Все понятно было сразу, я так и написал - у каждого блохера и юпубера должен быть свой мудпак. Перепроверь )))
  22. У каждого блохера должно быть свой мудпак и точка! А по существу - ну она же хочет чтобы её обсуждали, вот мы её и обсуждаем. Все честно. А негатив или позитив это уже личное дело каждого.
  23. А другого способа нет. Только та информация, что прислал сервер. from Avatar import PlayerAvatar from Vehicle import Vehicle from VehicleEffects import DamageFromShotDecoder from Math import Matrix, Vector3 @BigWorld.new_overrideLib.registerEvent(Vehicle, 'showDamageFromShot', DEBUG_MAIN) def new_showDamageFromShot(self, attackerID, points, effectsIndex, *a, **k): #Это попадание в модель танка .... #Декодирование точки и вектора попадания выглядит так decodedPoints = DamageFromShotDecoder.decodeHitPoints(points, self.appearance.collisions) if decodedPoints: firstHitPoint = decodedPoints[0] compMatrix = Matrix(self.appearance.compoundModel.node(firstHitPoint.componentName)) firstHitDirLocal = firstHitPoint.matrix.applyToAxis(2) firstHitDir = compMatrix.applyVector(firstHitDirLocal) firstHitDir.normalise() firstHitPos = compMatrix.applyPoint(firstHitPoint.matrix.translation) @BigWorld.new_overrideLib.registerEvent(PlayerAvatar, 'explodeProjectile', DEBUG_MAIN) def new_explodeProjectile(self, shotID, effectsIndex, effectMaterialIndex, endPoint, velocityDir, *a, **k): #Попадание снаряда в землю #Декодирование не требуется, т.к. endPoint, velocityDir и есть точка и вектор попадания Все верно, только если игра запущена и мод смог перехватить onBattleResultsReceived. Ниже древний пример, когда-то давно делал мод, что-то может изменилось, но не принципиально. import BigWorld __version__ = 'V1.1 P2.7 W0.9.10 26.10.2015' __author__ = 'StranikS_Scan' # Protected code ----------------------------------------------------------------- # WPG-mode ---------------------------------------------------------------- from os import path import BattleReplay from gui.shared.utils.HangarSpace import g_hangarSpace from gui import SystemMessages from PlayerEvents import g_playerEvents import constants from gui.battle_control.arena_info import getArenaGuiTypeLabel from helpers import isPlayerAccount, getFullClientVersion from ConnectionManager import connectionManager from datetime import datetime from functools import partial def WPG_PrintMessage(msg, INF): if len(msg)>0: if g_hangarSpace is not None and g_hangarSpace.inited: msg = '<textformat><font color="#E2D2A2" size="15"><b>WPG:</b></font><br><br>' + \ ('<font color="#E2D2A2" size="14">%s</font></textformat>' % msg) SystemMessages.pushMessage(msg, INF) else: BigWorld.callback(1.0, partial(WPG_PrintMessage, msg, INF)) class WPG_ResultDump(object): def __init__(self): g_playerEvents.onAccountBecomePlayer += self.__onAccountBecomePlayer g_playerEvents.onAvatarReady += self.__onAvatarReady g_playerEvents.onBattleResultsReceived += self.__onBattleResultsReceived self.Info = {} self.LogPath = './wpg_log' def __onAccountBecomePlayer(self): if not isPlayerAccount(): return else: player = BigWorld.player() if player.databaseID is None: BigWorld.callback(0.1, self.__onAccountBecomePlayer) else: self.Info['PlayerID'] = player.databaseID return def __onAvatarReady(self): def getBattleCount(accountDBID): import urllib2 import json request = 'http://api.worldoftanks.ru/wot/account/info/?application_id=demo&fields=statistics.all&account_id=%s' % accountDBID data = json.loads(urllib2.urlopen(request).read())['data'] player = data.get(str(accountDBID), None) if player != None: return int(player['statistics']['all']['battles']) return -1 if not BattleReplay.isPlaying() or 'PlayerID' in self.Info: player = BigWorld.player() self.Info['PlayerName'] = player.name self.Info['BattleNo'] = getBattleCount(self.Info['PlayerID']) + 1 self.Info['PlayerVehicleID'] = player.playerVehicleID self.Info['VehicleName'] = BigWorld.entities[player.playerVehicleID].typeDescriptor.name.replace(':', '-') arenaName = player.arena.arenaType.geometry i = arenaName.find('/') if i != -1: arenaName = arenaName[i+1:] self.Info['MapName'] = '%s(%s)' % (player.arena.arenaType.name, arenaName) self.Info['BattleType'] = getArenaGuiTypeLabel() self.Info['BattleLevel'] = player.arena.extraData.get('battleLevel') now = datetime.now() self.Info['Date'] = '%02d.%02d.%04d %02d:%02d:%02d' % (now.day, now.month, now.year, now.hour, now.minute, now.second) self.Info['ServerName'] = connectionManager.serverUserName self.Info['RegionCode'] = constants.AUTH_REALM self.Info['ClientVersion'] = getFullClientVersion() return def __onBattleResultsReceived(self, isPlayerVehicle, results): if not BattleReplay.isPlaying(): import json, copy from random import randint from struct import pack from os import path, mkdir if isPlayerVehicle and 'PlayerID' in self.Info: try: self.Info['BattleStatistics'] = BigWorld.player().arena.statistics vehicles = {} for k, v in BigWorld.player().arena.vehicles.iteritems(): vehicle = copy.copy(v) vehicle['vehicleType'] = v['vehicleType'].name if v['vehicleType'] is not None else '' del vehicle['forbidInBattleInvitations'] del vehicle['prebattleID'] del vehicle['isPrebattleCreator'] del vehicle['isAvatarReady'] del vehicle['potapovQuestIDs'] del vehicle['igrType'] del vehicle['events'] vehicles[k] = vehicle self.Info['ArenaVehiclesInfo'] = vehicles modifiedResults = copy.deepcopy(results) allPlayersVehicles = modifiedResults.get('vehicles', None) if allPlayersVehicles is not None: for playerVehicles in allPlayersVehicles.itervalues(): for vehicle in playerVehicles: vehicle['damageEventList'] = None personals = modifiedResults.get('personal', None) if personals is not None: for personal in personals.itervalues(): for field in ('damageEventList', 'xpReplay', 'creditsReplay', 'tmenXPReplay', 'fortResourceReplay', 'goldReplay', 'freeXPReplay'): personal[field] = None details = personal.pop('details', None) if details is not None: modifiedDetails = dict() for key, value in details.iteritems(): modifiedDetails[str(key)] = value personal['details'] = modifiedDetails self.Info['BattleResults'] = modifiedResults dump = [] dump.append('========================================================') dump.append(' WPG - BATTLE RESULT ') dump.append(" DON'T REWRITE OR MODIFIED THIS FILE ") dump.append('========================================================') dump.append('') dump.append('PlayerName: %s' % self.Info['PlayerName']) dump.append('PlayerID: %s' % self.Info['PlayerID']) dump.append('BattleNo: %s' % self.Info['BattleNo']) dump.append('') dump.append('PlayerVehicleID: %s' % self.Info['PlayerVehicleID']) dump.append('VehicleName: %s' % self.Info['VehicleName']) dump.append('MapName: %s' % self.Info['MapName']) dump.append('BattleType: %s' % self.Info['BattleType']) dump.append('BattleLevel: %s' % self.Info['BattleLevel']) dump.append('') dump.append('Date: %s' % self.Info['Date']) dump.append('ServerName: %s' % self.Info['ServerName']) dump.append('RegionCode: %s' % self.Info['RegionCode']) dump.append('') dump.append('ClientVersion: %s' % self.Info['ClientVersion']) dump.append('WPGVersion: %s' % __version__) dump.append('') dump.append('BattleStatistics:') dump.append(json.dumps(self.Info['BattleStatistics'], sort_keys=True).replace(',',',\n')) dump.append('') dump.append('ArenaVehiclesInfo:') dump.append(json.dumps(self.Info['ArenaVehiclesInfo'], indent=2, sort_keys=True)) dump.append('') dump.append('BattleResults:') dump.append(json.dumps(self.Info['BattleResults'], indent=2, sort_keys=True)) dump.append('') dump.append('') dump = '\n'.join(dump) self.LogFile = '%s_%d_%s.wpgr' % (self.Info['PlayerName'], self.Info['BattleNo'], self.Info['Date'].replace('.','').replace(':','').replace(' ','_')) except Exception as E: WPG_PrintMessage('Work was interrupted by the error!\n\n%s' % E, SystemMessages.SM_TYPE.Error) else: try: if not path.exists(self.LogPath): mkdir(self.LogPath) with open(self.LogPath+'/'+self.LogFile,'w') as f: f.write(dump) except Exception as E: WPG_PrintMessage('Was unable to save the wpgr-file!\n\n%s' % E, SystemMessages.SM_TYPE.Error) else: WPG_PrintMessage('Battle result saved in %s' % self.LogFile, SystemMessages.SM_TYPE.GameGreeting) self.Info = {} return __WPG_ResultDump = WPG_ResultDump() WPG_PrintMessage('- Statistics mode loaded successfully;\n'+\ '- Do not leave the battle before its completion;\n'+\ '- Files with results will be saved as \'%s/*.wpgr\'.' % __WPG_ResultDump.LogPath.replace('.',''),\ SystemMessages.SM_TYPE.GameGreeting)
×
×
  • Create New...