Merge branch '1.6.5-test' into public-server

This commit is contained in:
imayushsaini 2021-11-15 21:55:36 +05:30
commit 675e1940e3
28 changed files with 683 additions and 1199 deletions

View file

@ -576,7 +576,7 @@ class ServerManagerApp:
print(f'{Clr.CYN}Launching server subprocess...{Clr.RST}', flush=True)
binary_name = ('BallisticaCoreHeadless.exe'
if os.name == 'nt' else './ballisticacore_headless')
if os.name == 'nt' else './bombsquad_headless')
assert self._ba_root_path is not None
self._subprocess = None

View file

@ -347,9 +347,9 @@ def on_kick_vote_end() -> None:
pass
# print("kick vote end")
from tools import servercheck
def on_player_join(pb_id:str)-> None:
servercheck.on_player_join(pb_id)
pass
# print(pb_id+" joined python layer")

360
dist/ba_root/mods/CharacterChooser.py vendored Normal file
View file

@ -0,0 +1,360 @@
# ba_meta require api 6
'''
Character Chooser by Mr.Smoothy
This plugin will let you choose your character from lobby.
Install this plugin on your Phone/PC or on Server
If installed on server :- this will also let players choose server specific custom characters . so no more sharing of character file with all players,
just install this plugin on server ...and players can pick character from lobby .
Use:-
> select your profile (focus on color and name)
> press ready (punch)
> now use UP/DOWN buttons to scroll character list
> Press ready again (punch) to join the game
> or press Bomb button to go back to profile choosing menu
> END
Watch : https://www.youtube.com/watch?v=hNmv2l-NahE
Join : https://discord.gg/ucyaesh
Contact : discord mr.smoothy#5824
Share this plugin with your server owner /admins to use it online
:)
'''
from __future__ import annotations
from typing import TYPE_CHECKING
import ba,_ba
from bastd.actor.playerspaz import PlayerSpaz
from ba._error import print_exception, print_error, NotFoundError
from ba._gameutils import animate, animate_array
from ba._language import Lstr
from ba._generated.enums import SpecialChar, InputType
from ba._profile import get_player_profile_colors
if TYPE_CHECKING:
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
import weakref
import os,json
from ba import _lobby
from bastd.actor.spazappearance import *
from ba._lobby import ChangeMessage
from ba._lobby import PlayerReadyMessage
def __init__(self, vpos: float, sessionplayer: _ba.SessionPlayer,
lobby: 'Lobby') -> None:
self._deek_sound = _ba.getsound('deek')
self._click_sound = _ba.getsound('click01')
self._punchsound = _ba.getsound('punch01')
self._swish_sound = _ba.getsound('punchSwish')
self._errorsound = _ba.getsound('error')
self._mask_texture = _ba.gettexture('characterIconMask')
self._vpos = vpos
self._lobby = weakref.ref(lobby)
self._sessionplayer = sessionplayer
self._inited = False
self._dead = False
self._text_node: Optional[ba.Node] = None
self._profilename = ''
self._profilenames: List[str] = []
self._ready: bool = False
self._character_names: List[str] = []
self._last_change: Sequence[Union[float, int]] = (0, 0)
self._profiles: Dict[str, Dict[str, Any]] = {}
app = _ba.app
self.bakwas_chars=["Lee","Todd McBurton","Zola","Butch","Witch","warrior","Middle-Man","Alien","OldLady","Gladiator","Wrestler","Gretel","Robot"]
# Load available player profiles either from the local config or
# from the remote device.
self.reload_profiles()
for name in _ba.app.spaz_appearances:
if name not in self._character_names and name not in self.bakwas_chars:
self._character_names.append(name)
# Note: this is just our local index out of available teams; *not*
# the team-id!
self._selected_team_index: int = self.lobby.next_add_team
# Store a persistent random character index and colors; we'll use this
# for the '_random' profile. Let's use their input_device id to seed
# it. This will give a persistent character for them between games
# and will distribute characters nicely if everyone is random.
self._random_color, self._random_highlight = (
get_player_profile_colors(None))
# To calc our random character we pick a random one out of our
# unlocked list and then locate that character's index in the full
# list.
char_index_offset = app.lobby_random_char_index_offset
self._random_character_index = (
(sessionplayer.inputdevice.id + char_index_offset) %
len(self._character_names))
# Attempt to set an initial profile based on what was used previously
# for this input-device, etc.
self._profileindex = self._select_initial_profile()
self._profilename = self._profilenames[self._profileindex]
self._text_node = _ba.newnode('text',
delegate=self,
attrs={
'position': (-100, self._vpos),
'maxwidth': 190,
'shadow': 0.5,
'vr_depth': -20,
'h_align': 'left',
'v_align': 'center',
'v_attach': 'top'
})
animate(self._text_node, 'scale', {0: 0, 0.1: 1.0})
self.icon = _ba.newnode('image',
owner=self._text_node,
attrs={
'position': (-130, self._vpos + 20),
'mask_texture': self._mask_texture,
'vr_depth': -10,
'attach': 'topCenter'
})
animate_array(self.icon, 'scale', 2, {0: (0, 0), 0.1: (45, 45)})
# Set our initial name to '<choosing player>' in case anyone asks.
self._sessionplayer.setname(
Lstr(resource='choosingPlayerText').evaluate(), real=False)
# Init these to our rando but they should get switched to the
# selected profile (if any) right after.
self._character_index = self._random_character_index
self._color = self._random_color
self._highlight = self._random_highlight
self.characterchooser=False
self.update_from_profile()
self.update_position()
self._inited = True
self._set_ready(False)
def _set_ready(self, ready: bool) -> None:
# pylint: disable=cyclic-import
from bastd.ui.profile import browser as pbrowser
from ba._general import Call
profilename = self._profilenames[self._profileindex]
# Handle '_edit' as a special case.
if profilename == '_edit' and ready:
with _ba.Context('ui'):
pbrowser.ProfileBrowserWindow(in_main_menu=False)
# Give their input-device UI ownership too
# (prevent someone else from snatching it in crowded games)
_ba.set_ui_input_device(self._sessionplayer.inputdevice)
return
if ready==False:
self._sessionplayer.assigninput(
InputType.LEFT_PRESS,
Call(self.handlemessage, ChangeMessage('team', -1)))
self._sessionplayer.assigninput(
InputType.RIGHT_PRESS,
Call(self.handlemessage, ChangeMessage('team', 1)))
self._sessionplayer.assigninput(
InputType.BOMB_PRESS,
Call(self.handlemessage, ChangeMessage('character', 1)))
self._sessionplayer.assigninput(
InputType.UP_PRESS,
Call(self.handlemessage, ChangeMessage('profileindex', -1)))
self._sessionplayer.assigninput(
InputType.DOWN_PRESS,
Call(self.handlemessage, ChangeMessage('profileindex', 1)))
self._sessionplayer.assigninput(
(InputType.JUMP_PRESS, InputType.PICK_UP_PRESS,
InputType.PUNCH_PRESS),
Call(self.handlemessage, ChangeMessage('ready', 1)))
self._ready = False
self._update_text()
self._sessionplayer.setname('untitled', real=False)
elif ready == True:
self.characterchooser=True
self._sessionplayer.assigninput(
(InputType.LEFT_PRESS, InputType.RIGHT_PRESS,
InputType.UP_PRESS, InputType.DOWN_PRESS,
InputType.JUMP_PRESS, InputType.BOMB_PRESS,
InputType.PICK_UP_PRESS), self._do_nothing)
self._sessionplayer.assigninput(
(InputType.UP_PRESS),Call(self.handlemessage,ChangeMessage('characterchooser',-1)))
self._sessionplayer.assigninput(
(InputType.DOWN_PRESS),Call(self.handlemessage,ChangeMessage('characterchooser',1)))
self._sessionplayer.assigninput(
(InputType.BOMB_PRESS),Call(self.handlemessage,ChangeMessage('ready',0)))
self._sessionplayer.assigninput(
(InputType.JUMP_PRESS,InputType.PICK_UP_PRESS, InputType.PUNCH_PRESS),
Call(self.handlemessage, ChangeMessage('ready', 2)))
# Store the last profile picked by this input for reuse.
input_device = self._sessionplayer.inputdevice
name = input_device.name
unique_id = input_device.unique_identifier
device_profiles = _ba.app.config.setdefault(
'Default Player Profiles', {})
# Make an exception if we have no custom profiles and are set
# to random; in that case we'll want to start picking up custom
# profiles if/when one is made so keep our setting cleared.
special = ('_random', '_edit', '__account__')
have_custom_profiles = any(p not in special
for p in self._profiles)
profilekey = name + ' ' + unique_id
if profilename == '_random' and not have_custom_profiles:
if profilekey in device_profiles:
del device_profiles[profilekey]
else:
device_profiles[profilekey] = profilename
_ba.app.config.commit()
# Set this player's short and full name.
self._sessionplayer.setname(self._getname(),
self._getname(full=True),
real=True)
self._ready = True
self._update_text()
else:
# Inform the session that this player is ready.
_ba.getsession().handlemessage(PlayerReadyMessage(self))
def handlemessage(self, msg: Any) -> Any:
"""Standard generic message handler."""
if isinstance(msg, ChangeMessage):
self._handle_repeat_message_attack()
# If we've been removed from the lobby, ignore this stuff.
if self._dead:
print_error('chooser got ChangeMessage after dying')
return
if not self._text_node:
print_error('got ChangeMessage after nodes died')
return
if msg.what=='characterchooser':
_ba.playsound(self._click_sound)
# update our index in our local list of characters
self._character_index = ((self._character_index + msg.value) %
len(self._character_names))
self._update_text()
self._update_icon()
if msg.what == 'team':
sessionteams = self.lobby.sessionteams
if len(sessionteams) > 1:
_ba.playsound(self._swish_sound)
self._selected_team_index = (
(self._selected_team_index + msg.value) %
len(sessionteams))
self._update_text()
self.update_position()
self._update_icon()
elif msg.what == 'profileindex':
if len(self._profilenames) == 1:
# This should be pretty hard to hit now with
# automatic local accounts.
_ba.playsound(_ba.getsound('error'))
else:
# Pick the next player profile and assign our name
# and character based on that.
_ba.playsound(self._deek_sound)
self._profileindex = ((self._profileindex + msg.value) %
len(self._profilenames))
self.update_from_profile()
elif msg.what == 'character':
_ba.playsound(self._click_sound)
self.characterchooser=True
# update our index in our local list of characters
self._character_index = ((self._character_index + msg.value) %
len(self._character_names))
self._update_text()
self._update_icon()
elif msg.what == 'ready':
self._handle_ready_msg(msg.value)
def _update_text(self) -> None:
assert self._text_node is not None
if self._ready:
# Once we're ready, we've saved the name, so lets ask the system
# for it so we get appended numbers and stuff.
text = Lstr(value=self._sessionplayer.getname(full=True))
if self.characterchooser:
text = Lstr(value='${A}\n${B}',
subs=[('${A}', text),
('${B}', Lstr(value=""+self._character_names[self._character_index]))])
self._text_node.scale=0.8
else:
text = Lstr(value='${A} (${B})',
subs=[('${A}', text),
('${B}', Lstr(resource='readyText'))])
else:
text = Lstr(value=self._getname(full=True))
self._text_node.scale=1.0
can_switch_teams = len(self.lobby.sessionteams) > 1
# Flash as we're coming in.
fin_color = _ba.safecolor(self.get_color()) + (1, )
if not self._inited:
animate_array(self._text_node, 'color', 4, {
0.15: fin_color,
0.25: (2, 2, 2, 1),
0.35: fin_color
})
else:
# Blend if we're in teams mode; switch instantly otherwise.
if can_switch_teams:
animate_array(self._text_node, 'color', 4, {
0: self._text_node.color,
0.1: fin_color
})
else:
self._text_node.color = fin_color
self._text_node.text = text
# ba_meta export plugin
class HeySmoothy(ba.Plugin):
def __init__(self):
_lobby.Chooser.__init__=__init__
_lobby.Chooser._set_ready=_set_ready
_lobby.Chooser._update_text=_update_text
_lobby.Chooser.handlemessage=handlemessage

View file

@ -1,6 +1,5 @@
# Released under the MIT License. See LICENSE for details.
import ba, _ba
def isAbuse(msg):
pass

File diff suppressed because it is too large Load diff

View file

@ -3,13 +3,16 @@
from playersData import pdata
from serverData import serverdata
from chatHandle.ChatCommands import Main
from tools import Logger
from tools import Logger, servercheck
from chatHandle import chatFilter
import ba, _ba
import setting
settings = setting.get_settings_data()
def filter_chat_message(msg, client_id):
if client_id ==-1:
return msg
if msg.startswith("/"):
return Main.Command(msg, client_id)
@ -20,10 +23,11 @@ def filter_chat_message(msg, client_id):
Logger.log(acid+" | "+msg,"chat")
if acid in serverdata.clients:
if serverdata.clients[acid]["isMuted"]:
_ba.screenmessage("You are on mute", transient=True, clients=[client_id])
return None
elif serverdata.clients[acid]["accountAge"] < settings['minAgeToChatInHours']:
elif servercheck.get_account_age(serverdata.clients[acid]["accountAge"]) < settings['minAgeToChatInHours']:
_ba.screenmessage("New accounts not allowed to chat here", transient=True, clients=[client_id])
return None
else:
@ -32,12 +36,4 @@ def filter_chat_message(msg, client_id):
else:
_ba.screenmessage("Fetching your account info , Wait a minute", transient=True, clients=[client_id])
return None
"""
if chatfilter.isAbuse(msg):
pdata.warn(public_id(client_id))
return None
return msg
"""
return None

View file

@ -3,6 +3,14 @@ import ba
import _ba
from chatHandle import handlechat
import setting
from tools import servercheck
import _thread
from stats import mystats
from datetime import datetime
from ba import _activity
settings = setting.get_settings_data()
def filter_chat_message(msg, client_id):
return handlechat.filter_chat_message(msg, client_id)
@ -12,6 +20,8 @@ def on_app_launch():
from tools import whitelist
whitelist.Whitelist()
bootstraping()
servercheck.checkserver().start()
#something
@ -28,13 +38,15 @@ def playerspaz_init(player):
def bootstraping():
print("starting server configuration")
#_ba.disconnect_client=new_disconnect
settings = setting.get_settings_data()
_ba.set_server_device_name(settings["HostDeviceName"])
_ba.set_server_name(settings["HostName"])
_ba.set_transparent_kickvote(settings["ShowKickVoteStarterName"])
_ba.set_kickvote_msg_type(settings["KickVoteMsgType"])
_thread.start_new_thread(mystats.refreshStats,())
@ -42,3 +54,25 @@ def new_disconnect(clid,duration=120):
print("new new_disconnect")
_ba.ban_client(clid,duration)
org_begin=ba._activity.Activity.on_begin
def new_begin(self):
org_begin(self)
night_mode()
ba._activity.Activity.on_begin=new_begin
def night_mode():
if(settings['autoNightMode']['enable']):
start=datetime.strptime(settings['autoNightMode']['startTime'],"%H:%M")
end=datetime.strptime(settings['autoNightMode']['endTime'],"%H:%M")
now=datetime.now()
if now.time() > start.time() or now.time() < end.time():
activity = _ba.get_foreground_host_activity()
activity.globalsnode.tint = (0.5, 0.7, 1.0)

View file

@ -48,7 +48,7 @@ def registercharacter(name,char):
class HeySmoothy(ba.Plugin):
def __init__(self):
print("custom character importer")
path=os.path.join(_ba.env()["python_directory_user"],"CustomCharacters" + os.sep)
if not os.path.isdir(path):

View file

@ -1,7 +1,7 @@
# Released under the MIT License. See LICENSE for details.
import _ba, os, json
from serverData import serverdata
import time
roles = {}
data = {}
@ -12,7 +12,6 @@ data_path = os.path.join(_ba.env()['python_directory_user'],"playersData" + os.s
# ============== player data =======================
def get_info(id):
with open(data_path+'profiles.json', 'r') as f:
profiles = json.load(f)
if id in profiles:
@ -41,6 +40,8 @@ def add_profile(id,display_string,currentname,age):
"isBan":False,
"isMuted":False,
"accountAge":age,
"registerOn":time.time(),
"canStartKickVote":True,
"totaltimeplayer":0,
"lastseen":0}

View file

@ -8,53 +8,17 @@
"totaltimeplayer": 0,
"lastseen": 0
},
"pb-IF4TVWwZUQ=d=": {
"pb-IF5XUm9eAg==": {
"display_string": [
"\ue030Android48444292",
"\ue030PC295588"
"\ue030PC402015"
],
"profiles": [],
"name": "\ue030PC295588",
"name": "\ue030PC402015",
"isBan": false,
"isMuted": false,
"accountAge": 8231.662564509445,
"totaltimeplayer": 0,
"lastseen": 0
},
"pb-IF4TVWwZUQ==": {
"display_string": [
"\ue030Android48444292",
"\ue030PC295588"
],
"profiles": [],
"name": "\ue030PC295588",
"isBan": false,
"isMuted": false,
"accountAge": 8231.7627117525,
"totaltimeplayer": 0,
"lastseen": 0
},
"pb-IF4oUmwDFQ==": {
"display_string": [
"\ue030PC401824"
],
"profiles": [],
"name": "\ue030PC401824",
"isBan": false,
"isMuted": false,
"accountAge": 0.15915736722222223,
"totaltimeplayer": 0,
"lastseen": 0
},
"pb-IF4dUmwsIg==": {
"display_string": [
"\ue030PC401877"
],
"profiles": [],
"name": "\ue030PC401877",
"isBan": false,
"isMuted": false,
"accountAge": 0.01221103722222222,
"accountAge": "2021-11-12 20:30:30",
"registerOn": 1636801177.809589,
"canStartKickVote":true,
"totaltimeplayer": 0,
"lastseen": 0
}

View file

@ -15,19 +15,26 @@
"textonmap": {
"top watermark": "Welcome to server \n ip 192.168.0.1",
"bottom left watermark": "Search Hey Smoothy on Youtube",
"bottom left watermark": "Owner : <owner-name> \nEditor : <bablu>\nScripts : BCS1.3.2",
"center highlights": [
"message 1",
"message 2",
"message 3"
]
},
"autoNightMode":{
"enable":true,
"startTime":"18:30",
"endTime":"06:00"
},
"HostDeviceName":"v1.3.1",
"HostName":"BCS",
"ShowKickVoteStarterName":true,
"KickVoteMsgType":"chat",
"minAgeToChatInHours":78,
"minAgeToJoinInHours":48,
"minAgeToJoinInHours":24,
"maxWarnCount":2,
"WarnCooldownMinutes":30,
"enabletags": true,
"enablehptag": true,
"enablerank": true,

View file

@ -5,6 +5,7 @@ mystats module for BombSquad version 1.5.29
Provides functionality for dumping player stats to disk between rounds.
"""
ranks=[]
top3Name=[]
import threading,json,os,urllib.request,ba,_ba,setting
from ba._activity import Activity
from ba._music import setmusic, MusicType
@ -15,7 +16,7 @@ from typing import Any, Dict, Optional
from ba._lobby import JoinInfo
from ba import _activitytypes as ba_actypes
from ba._activitytypes import *
import urllib.request
#variables
our_settings = setting.get_settings_data()
# where our stats file and pretty html output will go
@ -136,11 +137,14 @@ def refreshStats():
</table>
</body>
</html>''')
f.close()
global ranks
ranks=_ranks
dump_stats(pStats)
updateTop3Names(toppersIDs[0:3])
from playersData import pdata
pdata.update_toppers(toppersIDs)
@ -245,3 +249,23 @@ def getRank(acc_id):
refreshStats()
if acc_id in ranks:
return ranks.index(acc_id)+1
def updateTop3Names(ids):
global top3Name
names=[]
for id in ids:
url="http://bombsquadgame.com/bsAccountInfo?buildNumber=20258&accountID="+id
data=urllib.request.urlopen(url)
if data is not None:
try:
name=json.loads(data.read())["profileDisplayString"]
except ValueError:
names.append("???")
else:
names.append(name)
top3Name=names

View file

@ -1,6 +1,6 @@
{
"pb-IF4VAk4a": {
"rank": 64,
"rank": 65,
"name": "pb-IF4VAk4a",
"scores": 0,
"total_damage": 0.0,
@ -18,9 +18,9 @@
"total_damage": 0.0,
"kills": 1,
"deaths": 73,
"games": 54,
"games": 55,
"kd": 0.013,
"avg_score": 11.296,
"avg_score": 11.09,
"aid": "pb-IF4TVWwZUQ=="
},
"pb-JiNJARBaXEFBVF9HFkNXXF1EF0ZaRlZE": {
@ -120,7 +120,7 @@
"aid": "pb-IF4VVUgJVw=="
},
"pb-IF4gVU0BCg==": {
"rank": 52,
"rank": 53,
"name": "\ue020Dewanggaming",
"scores": 43,
"total_damage": 0.0,
@ -132,7 +132,7 @@
"aid": "pb-IF4gVU0BCg=="
},
"pb-IF4FVXkZDQ==": {
"rank": 26,
"rank": 27,
"name": "\ue020lllBOLTlll",
"scores": 151,
"total_damage": 0.0,
@ -156,7 +156,7 @@
"aid": "pb-IF42VUpaDg=="
},
"pb-IF4iVUNSIw==": {
"rank": 47,
"rank": 48,
"name": "default",
"scores": 56,
"total_damage": 0.0,
@ -168,7 +168,7 @@
"aid": "pb-IF4iVUNSIw=="
},
"pb-IF4PVGcSJw==": {
"rank": 41,
"rank": 42,
"name": "\ue030Android29104233",
"scores": 84,
"total_damage": 0.0,
@ -180,7 +180,7 @@
"aid": "pb-IF4PVGcSJw=="
},
"pb-IF4eVVMkMw==": {
"rank": 29,
"rank": 30,
"name": "\ue030Android52887552",
"scores": 101,
"total_damage": 0.0,
@ -204,7 +204,7 @@
"aid": "pb-IF4vNnMJ"
},
"pb-IF4qV3c8Hw==": {
"rank": 62,
"rank": 63,
"name": "\ue020kankeisan1284578554",
"scores": 0,
"total_damage": 0.0,
@ -228,7 +228,7 @@
"aid": "pb-IF4mVHFcLQ=="
},
"pb-IF4PVVIeHw==": {
"rank": 68,
"rank": 69,
"name": "\ue020VoraceMan",
"scores": 0,
"total_damage": 0.0,
@ -240,7 +240,7 @@
"aid": "pb-IF4PVVIeHw=="
},
"pb-IF4AVXAmPA==": {
"rank": 49,
"rank": 50,
"name": "\ue020ESZ\u4e5bOptimusOp\u4e44",
"scores": 56,
"total_damage": 0.0,
@ -252,7 +252,7 @@
"aid": "pb-IF4AVXAmPA=="
},
"pb-IF4AVVEPNw==": {
"rank": 30,
"rank": 31,
"name": "\ue020StealthyFelicity14",
"scores": 96,
"total_damage": 0.0,
@ -264,7 +264,7 @@
"aid": "pb-IF4AVVEPNw=="
},
"pb-IF4SVU4MFw==": {
"rank": 65,
"rank": 66,
"name": "\ue020K\u211da\u03c4o\u0eae",
"scores": 0,
"total_damage": 0.0,
@ -288,7 +288,7 @@
"aid": "pb-IF4DVEkPEg=="
},
"pb-IF4TVVNeMg==": {
"rank": 45,
"rank": 46,
"name": "\ue030Android52880740",
"scores": 61,
"total_damage": 0.0,
@ -312,7 +312,7 @@
"aid": "pb-IF4yVUcgBg=="
},
"pb-IF4IVUUJMg==": {
"rank": 39,
"rank": 40,
"name": "\ue030Android51464300",
"scores": 90,
"total_damage": 0.0,
@ -336,7 +336,7 @@
"aid": "pb-IF4tVUwGVA=="
},
"pb-IF48NmQO": {
"rank": 58,
"rank": 59,
"name": "default",
"scores": 6,
"total_damage": 0.0,
@ -348,7 +348,7 @@
"aid": "pb-IF48NmQO"
},
"pb-IF4UVUQaAw==": {
"rank": 40,
"rank": 41,
"name": "\ue020LikelyTour25",
"scores": 85,
"total_damage": 0.0,
@ -360,7 +360,7 @@
"aid": "pb-IF4UVUQaAw=="
},
"pb-IF4wVRECLg==": {
"rank": 61,
"rank": 62,
"name": "\ue020gogugu",
"scores": 0,
"total_damage": 0.0,
@ -372,7 +372,7 @@
"aid": "pb-IF4wVRECLg=="
},
"pb-JiNJARBcV0FDXV1DGU5ZXV1FEUFWRVJC": {
"rank": 67,
"rank": 68,
"name": "\ue020appyfizz510",
"scores": 0,
"total_damage": 0.0,
@ -384,7 +384,7 @@
"aid": "pb-JiNJARBcV0FDXV1DGU5ZXV1FEUFWRVJC"
},
"pb-IF4OVVMsDQ==": {
"rank": 48,
"rank": 49,
"name": "\ue030Android52893090",
"scores": 56,
"total_damage": 0.0,
@ -396,7 +396,7 @@
"aid": "pb-IF4OVVMsDQ=="
},
"pb-IF5VVU4aFg==": {
"rank": 70,
"rank": 71,
"name": "default",
"scores": 0,
"total_damage": 0.0,
@ -408,7 +408,7 @@
"aid": "pb-IF5VVU4aFg=="
},
"pb-IF4SVW9dEg==": {
"rank": 50,
"rank": 51,
"name": "\ue020PROFFESOR9",
"scores": 48,
"total_damage": 0.0,
@ -420,7 +420,7 @@
"aid": "pb-IF4SVW9dEg=="
},
"pb-IF4SVVMtDg==": {
"rank": 37,
"rank": 38,
"name": "\ue020OrtigozaRafa2000",
"scores": 92,
"total_damage": 0.0,
@ -432,7 +432,7 @@
"aid": "pb-IF4SVVMtDg=="
},
"pb-IF4cVVMhKg==": {
"rank": 28,
"rank": 29,
"name": "\ue020jonyteoba100",
"scores": 106,
"total_damage": 0.0,
@ -456,7 +456,7 @@
"aid": "pb-IF4gVRlbXQ=="
},
"pb-IF4dVVAMUg==": {
"rank": 38,
"rank": 39,
"name": "\ue030Android52657984",
"scores": 91,
"total_damage": 0.0,
@ -468,7 +468,7 @@
"aid": "pb-IF4dVVAMUg=="
},
"pb-JiNJVxFfUEFDWFtCFEdXVl1FF0FaTllC": {
"rank": 57,
"rank": 58,
"name": "default",
"scores": 10,
"total_damage": 0.0,
@ -480,7 +480,7 @@
"aid": "pb-JiNJVxFfUEFDWFtCFEdXVl1FF0FaTllC"
},
"pb-IF40VU4TAQ==": {
"rank": 35,
"rank": 36,
"name": "default",
"scores": 96,
"total_damage": 0.0,
@ -504,7 +504,7 @@
"aid": "pb-IF5QVVUkLw=="
},
"pb-IF5RVUkZKg==": {
"rank": 56,
"rank": 57,
"name": "\ue020ThreateningOddball34",
"scores": 16,
"total_damage": 0.0,
@ -516,7 +516,7 @@
"aid": "pb-IF5RVUkZKg=="
},
"pb-IF5VVVEnVQ==": {
"rank": 46,
"rank": 47,
"name": "\ue030Android52446817",
"scores": 59,
"total_damage": 0.0,
@ -528,7 +528,7 @@
"aid": "pb-IF5VVVEnVQ=="
},
"pb-JiNJARBaVUpHWl1BGUBVVFZAEkZeR1FE": {
"rank": 32,
"rank": 33,
"name": "\ue020CreepyJourney52261",
"scores": 96,
"total_damage": 0.0,
@ -540,7 +540,7 @@
"aid": "pb-JiNJARBaVUpHWl1BGUBVVFZAEkZeR1FE"
},
"pb-IF5QVVZTAA==": {
"rank": 44,
"rank": 45,
"name": "default",
"scores": 64,
"total_damage": 0.0,
@ -552,7 +552,7 @@
"aid": "pb-IF5QVVZTAA=="
},
"pb-IF5dVU0tPw==": {
"rank": 36,
"rank": 37,
"name": "\ue030Android52110513",
"scores": 93,
"total_damage": 0.0,
@ -564,7 +564,7 @@
"aid": "pb-IF5dVU0tPw=="
},
"pb-IF4PVUovCQ==": {
"rank": 54,
"rank": 55,
"name": "\ue020Phriedbean",
"scores": 20,
"total_damage": 0.0,
@ -576,7 +576,7 @@
"aid": "pb-IF4PVUovCQ=="
},
"pb-IF4sVRU8IA==": {
"rank": 60,
"rank": 61,
"name": "\ue02099\u30e1KAMY",
"scores": 0,
"total_damage": 0.0,
@ -588,7 +588,7 @@
"aid": "pb-IF4sVRU8IA=="
},
"pb-IF4zVUYjPA==": {
"rank": 25,
"rank": 26,
"name": "\ue030Android51693156",
"scores": 152,
"total_damage": 0.0,
@ -600,7 +600,7 @@
"aid": "pb-IF4zVUYjPA=="
},
"pb-IF4PVVJSNg==": {
"rank": 34,
"rank": 35,
"name": "default",
"scores": 96,
"total_damage": 0.0,
@ -612,7 +612,7 @@
"aid": "pb-IF4PVVJSNg=="
},
"pb-IF4qVVMuIA==": {
"rank": 31,
"rank": 32,
"name": "\ue020TacitAnthropology26",
"scores": 96,
"total_damage": 0.0,
@ -636,7 +636,7 @@
"aid": "pb-IF4nVVFaEA=="
},
"pb-IF4-VWItPA==": {
"rank": 59,
"rank": 60,
"name": "default",
"scores": 0,
"total_damage": 0.0,
@ -648,7 +648,7 @@
"aid": "pb-IF4-VWItPA=="
},
"pb-IF5VVxI5Fg==": {
"rank": 43,
"rank": 44,
"name": "\ue020JinaYumnam1234",
"scores": 76,
"total_damage": 0.0,
@ -660,7 +660,7 @@
"aid": "pb-IF5VVxI5Fg=="
},
"pb-IF4lVUskVg==": {
"rank": 66,
"rank": 67,
"name": "\ue030Android52111807",
"scores": 0,
"total_damage": 0.0,
@ -672,7 +672,7 @@
"aid": "pb-IF4lVUskVg=="
},
"pb-IF4vVVAiKw==": {
"rank": 33,
"rank": 34,
"name": "default",
"scores": 96,
"total_damage": 0.0,
@ -696,7 +696,7 @@
"aid": "pb-IF5RVU0vKg=="
},
"pb-IF4JVWseCg==": {
"rank": 42,
"rank": 43,
"name": "\ue020CapillaryJaguar7",
"scores": 77,
"total_damage": 0.0,
@ -720,7 +720,7 @@
"aid": "pb-IF4HVVAkEg=="
},
"pb-JiNJARFTUUBCXFhJE0NUVFdCEERbT1dK": {
"rank": 55,
"rank": 56,
"name": "\ue020snehil7701",
"scores": 20,
"total_damage": 0.0,
@ -744,7 +744,7 @@
"aid": "pb-IF43VUwlAg=="
},
"pb-IF4uVUwsVQ==": {
"rank": 69,
"rank": 70,
"name": "\ue020VindictivePick10",
"scores": 0,
"total_damage": 0.0,
@ -768,7 +768,7 @@
"aid": "pb-IF4NVVNZMw=="
},
"pb-IF40VVMMPA==": {
"rank": 63,
"rank": 64,
"name": "\ue020SAM1133g1",
"scores": 0,
"total_damage": 0.0,
@ -804,7 +804,7 @@
"aid": "pb-IF5cVEMNNA=="
},
"pb-IF4PVEEnBA==": {
"rank": 27,
"rank": 28,
"name": "\ue020Deadly\u30c4TusKeR",
"scores": 128,
"total_damage": 0.0,
@ -816,7 +816,7 @@
"aid": "pb-IF4PVEEnBA=="
},
"pb-IF4RVVMDVQ==": {
"rank": 53,
"rank": 54,
"name": "\ue030Android52942930",
"scores": 37,
"total_damage": 0.0,
@ -828,7 +828,7 @@
"aid": "pb-IF4RVVMDVQ=="
},
"pb-IF43VVJSAg==": {
"rank": 51,
"rank": 52,
"name": "\ue020RANDOMGOD2011",
"scores": 44,
"total_damage": 0.0,
@ -838,5 +838,17 @@
"kd": 0.75,
"avg_score": 22.0,
"aid": "pb-IF43VVJSAg=="
},
"pb-IF5XUm9eAg==": {
"rank": 25,
"name": "\ue030PC402015",
"scores": 152,
"total_damage": 0.0,
"kills": 0,
"deaths": 10,
"games": 21,
"kd": 0.0,
"avg_score": 7.238,
"aid": "pb-IF5XUm9eAg=="
}
}

View file

@ -47,7 +47,7 @@
<td>610</td>
<td>1</td>
<td>73</td>
<td>54</td>
<td>55</td>
</tr>
<tr>
<td>5</td>
@ -211,6 +211,14 @@
</tr>
<tr>
<td>25</td>
<td style="text-align:center">PC402015</td>
<td>152</td>
<td>0</td>
<td>10</td>
<td>21</td>
</tr>
<tr>
<td>26</td>
<td style="text-align:center">Android51693156</td>
<td>152</td>
<td>0</td>
@ -218,7 +226,7 @@
<td>3</td>
</tr>
<tr>
<td>26</td>
<td>27</td>
<td style="text-align:center">lllBOLTlll</td>
<td>151</td>
<td>9</td>
@ -226,7 +234,7 @@
<td>3</td>
</tr>
<tr>
<td>27</td>
<td>28</td>
<td style="text-align:center">DeadlyツTusKeR</td>
<td>128</td>
<td>3</td>
@ -234,7 +242,7 @@
<td>3</td>
</tr>
<tr>
<td>28</td>
<td>29</td>
<td style="text-align:center">jonyteoba100</td>
<td>106</td>
<td>2</td>
@ -242,7 +250,7 @@
<td>4</td>
</tr>
<tr>
<td>29</td>
<td>30</td>
<td style="text-align:center">Android52887552</td>
<td>101</td>
<td>0</td>
@ -250,7 +258,7 @@
<td>6</td>
</tr>
<tr>
<td>30</td>
<td>31</td>
<td style="text-align:center">StealthyFelicity14</td>
<td>96</td>
<td>0</td>
@ -258,24 +266,16 @@
<td>1</td>
</tr>
<tr>
<td>31</td>
<td>32</td>
<td style="text-align:center">TacitAnthropology26</td>
<td>96</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>32</td>
<td style="text-align:center">CreepyJourney52261</td>
<td>96</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>33</td>
<td style="text-align:center">default</td>
<td style="text-align:center">CreepyJourney52261</td>
<td>96</td>
<td>0</td>
<td>0</td>
@ -299,6 +299,14 @@
</tr>
<tr>
<td>36</td>
<td style="text-align:center">default</td>
<td>96</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>37</td>
<td style="text-align:center">Android52110513</td>
<td>93</td>
<td>0</td>
@ -306,7 +314,7 @@
<td>2</td>
</tr>
<tr>
<td>37</td>
<td>38</td>
<td style="text-align:center">OrtigozaRafa2000</td>
<td>92</td>
<td>4</td>
@ -314,7 +322,7 @@
<td>4</td>
</tr>
<tr>
<td>38</td>
<td>39</td>
<td style="text-align:center">Android52657984</td>
<td>91</td>
<td>0</td>
@ -322,7 +330,7 @@
<td>2</td>
</tr>
<tr>
<td>39</td>
<td>40</td>
<td style="text-align:center">Android51464300</td>
<td>90</td>
<td>0</td>
@ -330,7 +338,7 @@
<td>2</td>
</tr>
<tr>
<td>40</td>
<td>41</td>
<td style="text-align:center">LikelyTour25</td>
<td>85</td>
<td>11</td>
@ -338,7 +346,7 @@
<td>2</td>
</tr>
<tr>
<td>41</td>
<td>42</td>
<td style="text-align:center">Android29104233</td>
<td>84</td>
<td>7</td>
@ -346,7 +354,7 @@
<td>2</td>
</tr>
<tr>
<td>42</td>
<td>43</td>
<td style="text-align:center">CapillaryJaguar7</td>
<td>77</td>
<td>7</td>
@ -354,7 +362,7 @@
<td>3</td>
</tr>
<tr>
<td>43</td>
<td>44</td>
<td style="text-align:center">JinaYumnam1234</td>
<td>76</td>
<td>0</td>
@ -362,7 +370,7 @@
<td>1</td>
</tr>
<tr>
<td>44</td>
<td>45</td>
<td style="text-align:center">default</td>
<td>64</td>
<td>0</td>
@ -370,7 +378,7 @@
<td>1</td>
</tr>
<tr>
<td>45</td>
<td>46</td>
<td style="text-align:center">Android52880740</td>
<td>61</td>
<td>0</td>
@ -378,7 +386,7 @@
<td>2</td>
</tr>
<tr>
<td>46</td>
<td>47</td>
<td style="text-align:center">Android52446817</td>
<td>59</td>
<td>2</td>
@ -386,7 +394,7 @@
<td>2</td>
</tr>
<tr>
<td>47</td>
<td>48</td>
<td style="text-align:center">default</td>
<td>56</td>
<td>2</td>
@ -394,7 +402,7 @@
<td>1</td>
</tr>
<tr>
<td>48</td>
<td>49</td>
<td style="text-align:center">Android52893090</td>
<td>56</td>
<td>0</td>
@ -402,7 +410,7 @@
<td>2</td>
</tr>
<tr>
<td>49</td>
<td>50</td>
<td style="text-align:center">ESZ乛OptimusOp乄</td>
<td>56</td>
<td>0</td>
@ -410,7 +418,7 @@
<td>2</td>
</tr>
<tr>
<td>50</td>
<td>51</td>
<td style="text-align:center">PROFFESOR9</td>
<td>48</td>
<td>0</td>
@ -418,7 +426,7 @@
<td>5</td>
</tr>
<tr>
<td>51</td>
<td>52</td>
<td style="text-align:center">RANDOMGOD2011</td>
<td>44</td>
<td>3</td>
@ -426,7 +434,7 @@
<td>2</td>
</tr>
<tr>
<td>52</td>
<td>53</td>
<td style="text-align:center">Dewanggaming</td>
<td>43</td>
<td>3</td>
@ -434,7 +442,7 @@
<td>3</td>
</tr>
<tr>
<td>53</td>
<td>54</td>
<td style="text-align:center">Android52942930</td>
<td>37</td>
<td>1</td>
@ -442,7 +450,7 @@
<td>1</td>
</tr>
<tr>
<td>54</td>
<td>55</td>
<td style="text-align:center">Phriedbean</td>
<td>20</td>
<td>2</td>
@ -450,7 +458,7 @@
<td>2</td>
</tr>
<tr>
<td>55</td>
<td>56</td>
<td style="text-align:center">snehil7701</td>
<td>20</td>
<td>2</td>
@ -458,7 +466,7 @@
<td>1</td>
</tr>
<tr>
<td>56</td>
<td>57</td>
<td style="text-align:center">ThreateningOddball34</td>
<td>16</td>
<td>1</td>
@ -466,31 +474,31 @@
<td>2</td>
</tr>
<tr>
<td>57</td>
<td>58</td>
<td style="text-align:center">default</td>
<td>10</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>58</td>
<td style="text-align:center">default</td>
<td>6</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>59</td>
<td style="text-align:center">default</td>
<td>0</td>
<td>0</td>
<td>6</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>60</td>
<td style="text-align:center">default</td>
<td>0</td>
<td>0</td>
<td>6</td>
<td>1</td>
</tr>
<tr>
<td>61</td>
<td style="text-align:center">99メKAMY</td>
<td>0</td>
<td>0</td>
@ -498,7 +506,7 @@
<td>1</td>
</tr>
<tr>
<td>61</td>
<td>62</td>
<td style="text-align:center">gogugu</td>
<td>0</td>
<td>0</td>
@ -506,7 +514,7 @@
<td>2</td>
</tr>
<tr>
<td>62</td>
<td>63</td>
<td style="text-align:center">kankeisan1284578554</td>
<td>0</td>
<td>0</td>
@ -514,7 +522,7 @@
<td>1</td>
</tr>
<tr>
<td>63</td>
<td>64</td>
<td style="text-align:center">SAM1133g1</td>
<td>0</td>
<td>0</td>
@ -522,7 +530,7 @@
<td>1</td>
</tr>
<tr>
<td>64</td>
<td>65</td>
<td style="text-align:center">pb-IF4VAk4a</td>
<td>0</td>
<td>0</td>
@ -530,7 +538,7 @@
<td>18</td>
</tr>
<tr>
<td>65</td>
<td>66</td>
<td style="text-align:center">Kaτoຮ</td>
<td>0</td>
<td>0</td>
@ -538,7 +546,7 @@
<td>2</td>
</tr>
<tr>
<td>66</td>
<td>67</td>
<td style="text-align:center">Android52111807</td>
<td>0</td>
<td>0</td>
@ -546,7 +554,7 @@
<td>1</td>
</tr>
<tr>
<td>67</td>
<td>68</td>
<td style="text-align:center">appyfizz510</td>
<td>0</td>
<td>0</td>
@ -554,7 +562,7 @@
<td>1</td>
</tr>
<tr>
<td>68</td>
<td>69</td>
<td style="text-align:center">VoraceMan</td>
<td>0</td>
<td>0</td>
@ -562,7 +570,7 @@
<td>1</td>
</tr>
<tr>
<td>69</td>
<td>70</td>
<td style="text-align:center">VindictivePick10</td>
<td>0</td>
<td>0</td>
@ -570,7 +578,7 @@
<td>1</td>
</tr>
<tr>
<td>70</td>
<td>71</td>
<td style="text-align:center">default</td>
<td>0</td>
<td>0</td>

View file

@ -56,15 +56,36 @@ import setting
# pdata.update_profile(serverdata.cachedclients[player])
class checkserver(object):
def start(self):
self.players=[]
self.t1=ba.timer(1, ba.Call(self.check),repeat=True)
def check(self):
newPlayers=[]
for ros in _ba.get_game_roster():
newPlayers.append(ros['account_id'])
if ros['account_id'] not in self.players and ros['client_id'] !=-1:
if ros['account_id'] != None:
LoadProfile(ros['account_id']).start()
self.players=newPlayers
settings = setting.get_settings_data()
def on_player_join(pbid):
def on_player_join_server(pbid,player_data):
player_data=pdata.get_info(pbid)
#player_data=pdata.get_info(pbid)
if player_data!=None:
device_strin=""
if player_data["isBan"] or player_data["accountAge"] < settings["minAgeToJoinInHours"]:
if player_data["isBan"] or get_account_age(player_data["accountAge"]) < settings["minAgeToJoinInHours"]:
for ros in _ba.get_game_roster():
if ros['account_id']==pbid:
if not player_data["isBan"]:
@ -74,6 +95,10 @@ def on_player_join(pbid):
else:
serverdata.clients[pbid]=player_data
serverdata.clients[pbid]["warnCount"]=0
serverdata.clients[pbid]["lastWarned"]=time.time()
if not player_data["canStartKickVote"]:
_ba.disable_kickvote(pbid)
verify_account(pbid,player_data)
@ -126,7 +151,7 @@ def _make_request_safe(request, retries=2, raise_err=True):
if raise_err:
raise
def get_account_age_in_hours(pb_id):
def get_account_creation_date(pb_id):
# thanks rikko
account_creation_url = "http://bombsquadgame.com/accountquery?id=" + pb_id
account_creation = _make_request_safe(lambda: urllib.request.urlopen(account_creation_url))
@ -141,11 +166,11 @@ def get_account_age_in_hours(pb_id):
creation_time = datetime.datetime.strptime("/".join(creation_time), "%Y/%m/%d/%H/%M/%S")
# Convert to IST
creation_time += datetime.timedelta(hours=5, minutes=30)
print(creation_time)
now = datetime.datetime.now()
delta = now - creation_time
delta_hours = delta.total_seconds() / (60 * 60)
return delta_hours
return str(creation_time)
# now = datetime.datetime.now()
# delta = now - creation_time
# delta_hours = delta.total_seconds() / (60 * 60)
# return delta_hours
def get_device_accounts(pb_id):
url="http://bombsquadgame.com/bsAccountInfo?buildNumber=20258&accountID="+pb_id
@ -161,6 +186,25 @@ def get_device_accounts(pb_id):
# ======= yes fucking threading code , dont touch ==============
# ============ file I/O =============
class LoadProfile(threading.Thread):
def __init__(self,pb_id):
threading.Thread.__init__(self)
self.pbid=pb_id
def run(self):
player_data=pdata.get_info(self.pbid)
_ba.pushcall(Call(on_player_join_server,self.pbid,player_data),from_other_thread=True)
# ================ http ================
class FetchThread(threading.Thread):
def __init__(self,target, callback=None,pb_id="ji",display_string="XXX"):
@ -178,7 +222,7 @@ class FetchThread(threading.Thread):
def my_acc_age(pb_id):
return get_account_age_in_hours(pb_id)
return get_account_creation_date(pb_id)
def save_age(age, pb_id,display_string):
@ -193,7 +237,7 @@ def save_age(age, pb_id,display_string):
display_string=display_string
)
thread2.start()
if age < settings["minAgeToJoinInHours"]:
if get_account_age(age) < settings["minAgeToJoinInHours"]:
msg="New Accounts not allowed to play here , come back tmrw."
_ba.pushcall(Call(kick_by_pb_id,pb_id,msg),from_other_thread=True)
@ -202,6 +246,7 @@ def save_ids(ids,pb_id,display_string):
pdata.update_displayString(pb_id,ids)
if display_string not in ids:
msg="Spoofed Id detected , Goodbye"
_ba.pushcall(Call(kick_by_pb_id,pb_id,msg),from_other_thread=True)
@ -219,3 +264,12 @@ def kick_by_pb_id(pb_id,msg):
def get_account_age(ct):
creation_time=datetime.datetime.strptime(ct,"%Y-%m-%d %H:%M:%S")
now = datetime.datetime.now()
delta = now - creation_time
delta_hours = delta.total_seconds() / (60 * 60)
return delta_hours

View file

@ -5,19 +5,29 @@
from ba._generated.enums import TimeType
import ba, _ba
import setting
from stats import mystats
from datetime import datetime
class textonmap:
def __init__(self):
data = setting.get_settings_data()['textonmap']
setti=setting.get_settings_data()
data = setti['textonmap']
left = data['bottom left watermark']
top = data['top watermark']
nextMap=_ba.get_foreground_host_session().get_next_game_description().evaluate()
self.index = 0
self.highlights = data['center highlights']
self.left_watermark(left)
self.top_message(top)
self.nextGame(nextMap)
self.leaderBoard()
self.timer = ba.timer(8, ba.Call(self.highlights_), repeat=True)
def highlights_(self):
@ -42,10 +52,24 @@ class textonmap:
'flatness': 1.0,
'h_align': 'left',
'v_attach':'bottom',
'scale':1,
'position':(-480,20),
'color':(1,1,1)
'h_attach':'left',
'scale':0.7,
'position':(25,67),
'color':(0.7,0.7,0.7)
})
def nextGame(self,text):
node = _ba.newnode('text',
attrs={
'text':"Next : "+text,
'flatness':1.0,
'h_align':'right',
'v_attach':'bottom',
'h_attach':'right',
'scale':0.7,
'position':(-25,18),
'color':(0.5,0.5,0.5)
})
def top_message(self, text):
node = _ba.newnode('text',
@ -58,3 +82,15 @@ class textonmap:
'position':(0,138),
'color':(1,1,1)
})
def leaderBoard(self):
if len(mystats.top3Name) >2:
self.ss1=ba.newnode('image',attrs={'scale':(300,30),'texture':ba.gettexture('bar'),'position':(0,-80),'attach':'topRight','opacity':0.5,'color':(0.7,0.1,0)})
self.ss1a=ba.newnode('text',attrs={'text':"#1 "+mystats.top3Name[0][:10]+"...",'flatness':1.0,'h_align':'left','h_attach':'right','v_attach':'top','v_align':'center','position':(-140,-80),'scale':0.7,'color':(0.7,0.4,0.3)})
self.ss1=ba.newnode('image',attrs={'scale':(300,30),'texture':ba.gettexture('bar'),'position':(0,-115),'attach':'topRight','opacity':0.5,'color':(0.6,0.6,0.6)})
self.ss1a=ba.newnode('text',attrs={'text':"#2 "+mystats.top3Name[1][:10]+"...",'flatness':1.0,'h_align':'left','h_attach':'right','v_attach':'top','v_align':'center','position':(-140,-115),'scale':0.7,'color':(0.8,0.8,0.8)})
self.ss1=ba.newnode('image',attrs={'scale':(300,30),'texture':ba.gettexture('bar'),'position':(0,-150),'attach':'topRight','opacity':0.5,'color':(0.1,0.3,0.1)})
self.ss1a=ba.newnode('text',attrs={'text':"#3 "+mystats.top3Name[2][:10]+"...",'flatness':1.0,'h_align':'left','h_attach':'right','v_attach':'top','v_align':'center','position':(-140,-150),'scale':0.7,'color':(0.2,0.6,0.2)})