This commit is contained in:
Headshot 2019-04-03 10:27:23 -04:30
commit 40f195f5c6
14 changed files with 3712 additions and 0 deletions

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
base/
chatlogs/
pybass/
build/
dist/
*.exe
bass.dll
bass24.zip
PyQt4-4.11.4-cp27-cp27m-win32.whl
*.pyc
pybass_055.zip

65
AO2XP.py Normal file
View File

@ -0,0 +1,65 @@
from PyQt4 import QtGui, QtCore
from pybass import *
import sys, thread, time
from os.path import exists
import ctypes
import gameview, mainmenu, options
class gamewindow(QtGui.QMainWindow):
def __init__(self):
super(gamewindow, self).__init__()
self.stackwidget = QtGui.QStackedWidget(self)
self.widget = mainmenu.lobby(self)
self.gamewidget = gameview.gui(self)
self.stackwidget.addWidget(self.widget)
self.stackwidget.addWidget(self.gamewidget)
self.setCentralWidget(self.stackwidget)
self.stackwidget.setCurrentWidget(self.widget)
self.setFixedSize(self.widget.lobbyimg.size().width(), self.widget.lobbyimg.size().height())
self.center()
self.setWindowTitle("AO2XP")
self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)
self.settingsgui = options.Settings()
def center(self):
frameGm = self.frameGeometry()
centerPoint = QtGui.QDesktopWidget().availableGeometry().center()
frameGm.moveCenter(centerPoint)
self.move(frameGm.topLeft())
def showGame(self, tcp, charlist, musiclist, background, evidence, areas, features=[], oocjoin=[], hplist=[]):
self.gamewidget.disconnectnow = False
self.gamewidget.startGame(tcp, charlist, musiclist, background, evidence, areas, features, oocjoin, hplist)
self.setFixedSize(714, 668)
self.stackwidget.setCurrentWidget(self.gamewidget)
def returnToMenu(self):
self.gamewidget.disconnectnow = True
self.setFixedSize(self.widget.lobbyimg.size().width(), self.widget.lobbyimg.size().height())
self.widget.onClicked_cancelconnect()
self.stackwidget.setCurrentWidget(self.widget)
self.setWindowTitle("AO2XP")
def showSettings(self):
self.settingsgui.showSettings()
debugmode = False
if len(sys.argv) > 1:
if sys.argv[1] == "debug":
debugmode = True
if not debugmode:
if not exists("base"):
ctypes.windll.user32.MessageBoxA(0, "i couldn't find the holy mother of all important folders that goes by the name of 'base'.\nto fix this, you can try:\n1. downloading a full vanilla copy of Attorney Online 2, and copy the 'base' folder over to this client's location\n2. making sure you extracted the client in the right location", "unable to launch game", 0)
sys.exit(1)
elif not exists("bass.dll"):
ctypes.windll.user32.MessageBoxA(0, "i couldn't find the file 'bass.dll'\nthis program needs this file in order to play sounds and music\nthe file is included in this client's zip file, make sure it's in the same folder as this EXE", "unable to launch game", 0)
sys.exit(1)
BASS_Init(-1, 44100, 0, 0, 0)
app = QtGui.QApplication(sys.argv)
shit = gamewindow()
shit.show()
sys.exit(app.exec_())

28
AO2XP.spec Normal file
View File

@ -0,0 +1,28 @@
# -*- mode: python -*-
block_cipher = None
a = Analysis(['AO2XP.py'],
pathex=['I:\\Documents and Settings\\Admin\\Desktop\\AOpy\\gui'],
binaries=[("bass.dll", ".")],
datas=None,
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='AO2XP',
debug=False,
strip=False,
upx=True,
console=False)

8
README.md Normal file
View File

@ -0,0 +1,8 @@
# AO2XP
This is an alternate Attorney Online 2 client, developed in Python 2.7, specifically made for older computers running Windows XP that cannot run the latest version of the AO2 client.
To edit the source code, you need Python 2.7.
You may run "quicksetup.py" to install the required libraries.
By Headshot#7237

195
buttons.py Normal file
View File

@ -0,0 +1,195 @@
from PyQt4 import QtCore, QtGui
import os
#AOpath = "base\\"
AOpath = "I:\\aovanilla1.7.5\\client\\base\\"
class RealizationButton(QtGui.QLabel):
pressed = False
def __init__(self, parent, x, y):
super(RealizationButton, self).__init__(parent)
self.parent = parent
self.setGeometry(x, y, 42, 42)
self.notpressed_pix = QtGui.QPixmap(AOpath+"themes\\default\\realization.png")
self.pressed_pix = QtGui.QPixmap(AOpath+"themes\\default\\realization_pressed.png")
self.setPixmap(self.notpressed_pix)
self.show()
def setPressed(self, on):
self.pressed = on
if on:
self.setPixmap(self.pressed_pix)
else:
self.setPixmap(self.notpressed_pix)
def isPressed(self):
return self.pressed
def mousePressEvent(self, event):
self.setPressed(not self.isPressed())
class CustomObjection(QtGui.QLabel):
pressed = False
def __init__(self, parent, x, y):
super(CustomObjection, self).__init__(parent)
self.parent = parent
self.setGeometry(x, y, 76, 28)
self.notpressed_pix = QtGui.QPixmap(AOpath+"themes\\default\\custom.png")
self.pressed_pix = QtGui.QPixmap(AOpath+"themes\\default\\custom_selected.png")
self.setPixmap(self.notpressed_pix)
self.show()
def setPressed(self, on):
self.pressed = on
if on:
self.setPixmap(self.pressed_pix)
else:
self.setPixmap(self.notpressed_pix)
def isPressed(self):
return self.pressed
def mousePressEvent(self, event):
self.setPressed(not self.isPressed())
self.parent.objectbtn.setPressed(False)
self.parent.holditbtn.setPressed(False)
self.parent.takethatbtn.setPressed(False)
class WTCEbuttons(QtGui.QLabel):
clicked = QtCore.pyqtSignal(int, int)
type = 0
variant = 0
def __init__(self, parent, x, y, type, variant=0):
super(WTCEbuttons, self).__init__(parent)
self.setGeometry(x, y, 85, 42)
if type == 0:
self.setPixmap(QtGui.QPixmap(AOpath+"themes\\default\\witnesstestimony.png"))
elif type == 1:
self.setPixmap(QtGui.QPixmap(AOpath+"themes\\default\\crossexamination.png"))
elif type == 2:
if variant == 0:
self.setPixmap(QtGui.QPixmap(AOpath+"themes\\default\\notguilty.png"))
elif variant == 1:
self.setPixmap(QtGui.QPixmap(AOpath+"themes\\default\\guilty.png"))
self.type = type
self.variant = variant
def mousePressEvent(self, event):
self.clicked.emit(self.type, self.variant)
class Objections(QtGui.QLabel):
pressed = False
type = 0
def __init__(self, parent, x, y, type):
super(Objections, self).__init__(parent)
self.parent = parent
self.type = type
self.setGeometry(x, y, 76, 28)
if type == 1:
self.notpressed_pix = QtGui.QPixmap(AOpath+"themes\\default\\holdit.png")
self.pressed_pix = QtGui.QPixmap(AOpath+"themes\\default\\holdit_selected.png")
elif type == 2:
self.notpressed_pix = QtGui.QPixmap(AOpath+"themes\\default\\objection.png")
self.pressed_pix = QtGui.QPixmap(AOpath+"themes\\default\\objection_selected.png")
elif type == 3:
self.notpressed_pix = QtGui.QPixmap(AOpath+"themes\\default\\takethat.png")
self.pressed_pix = QtGui.QPixmap(AOpath+"themes\\default\\takethat_selected.png")
self.setPixmap(self.notpressed_pix)
self.show()
def setPressed(self, on):
self.pressed = on
if on:
self.setPixmap(self.pressed_pix)
else:
self.setPixmap(self.notpressed_pix)
def isPressed(self):
return self.pressed
def mousePressEvent(self, event):
self.setPressed(not self.isPressed())
self.parent.customobject.setPressed(False)
if self.type == 1:
self.parent.objectbtn.setPressed(False)
self.parent.takethatbtn.setPressed(False)
elif self.type == 2:
self.parent.holditbtn.setPressed(False)
self.parent.takethatbtn.setPressed(False)
elif self.type == 3:
self.parent.objectbtn.setPressed(False)
self.parent.holditbtn.setPressed(False)
class PixmapButton(QtGui.QAbstractButton):
def __init__(self, parent, pixmap):
super(PixmapButton, self).__init__(parent)
self.pixmap = pixmap
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.drawPixmap(event.rect(), self.pixmap)
def sizeHint(self):
return self.pixmap.size()
def setPixmap(self, pixmap):
self.pixmap = pixmap
class PixmapButton2(QtGui.QLabel):
clicked = QtCore.pyqtSignal()
rightClicked = QtCore.pyqtSignal()
def __init__(self, parent, pixmap):
super(PixmapButton2, self).__init__(parent)
self.setPixmap(pixmap)
self.show()
def mousePressEvent(self, ev):
if ev.buttons() == QtCore.Qt.LeftButton:
self.clicked.emit()
elif ev.buttons() == QtCore.Qt.RightButton:
self.rightClicked.emit()
class PenaltyBars(QtGui.QLabel):
minusClicked = QtCore.pyqtSignal(int)
plusClicked = QtCore.pyqtSignal(int)
def __init__(self, parent, type):
super(PenaltyBars, self).__init__(parent)
self.penaltybars = []
self.type = type
self.health = 10
self.resize(84, 14)
if type == 1: #defense bar.
for i in range(11):
self.penaltybars.append(QtGui.QPixmap(AOpath+"themes\\default\\defensebar"+str(i)+".png"))
side = "def"
elif type == 2: #prosecution bar
for i in range(11):
self.penaltybars.append(QtGui.QPixmap(AOpath+"themes\\default\\prosecutionbar"+str(i)+".png"))
side = "pro"
self.minusbtn = PixmapButton(parent, QtGui.QPixmap(AOpath+"themes\\default\\"+side+"minus.png"))
self.plusbtn = PixmapButton(parent, QtGui.QPixmap(AOpath+"themes\\default\\"+side+"plus.png"))
self.minusbtn.clicked.connect(self.minusClick)
self.plusbtn.clicked.connect(self.plusClick)
self.setPixmap(self.penaltybars[10])
self.minusbtn.show()
self.plusbtn.show()
self.show()
def moveBar(self, x, y):
self.move(x, y)
self.minusbtn.move(x-(9/2), y+(14/2)-(9/2))
self.plusbtn.move(x+84-(9/2), y+(14/2)-(9/2))
def plusClick(self):
self.plusClicked.emit(self.type)
def minusClick(self):
self.minusClicked.emit(self.type)
def setHealth(self, health):
self.setPixmap(self.penaltybars[health])
self.health = health
def getHealth(self):
return self.health

127
charselect.py Normal file
View File

@ -0,0 +1,127 @@
from PyQt4 import QtGui, QtCore
import socket, thread, time
from os.path import exists
from functools import partial
from buttons import PixmapButton
#AOpath = "base\\"
AOpath = "I:\\aovanilla1.7.5\\client\\base\\"
class CharIcon(QtGui.QLabel):
def __init__(self, parent, ind):
super(CharIcon, self).__init__(parent)
self.parent = parent
self.ind = ind
def mousePressEvent(self, event):
self.parent.onCharClicked(self.ind)
class charselect(QtGui.QWidget):
setBtnImage = QtCore.pyqtSignal(str, int)
def __init__(self, parent):
super(charselect, self).__init__(parent)
self.parent = parent
self.page = 0
self.image = QtGui.QLabel(self)
self.image.setPixmap(QtGui.QPixmap(AOpath+"themes\\default\\charselect_background.png"))
self.image.show()
self.quittolobby = QtGui.QPushButton(self)
self.quittolobby.setText("Disconnect")
self.quittolobby.resize(self.quittolobby.sizeHint())
self.quittolobby.clicked.connect(self.quitToLobby)
self.buttons = []
self.chartaken = []
#directly stolen from ao2 source code and default theme because i was stuck (i'm so sorry)
btn_width, btn_height = 60, 60
x_spacing, y_spacing = 7, 7
x_mod_count, y_mod_count = 0, 0
left, top = 25, 36
width, height = 663, 596
columns = (width - btn_width) / (x_spacing + btn_width) +1
rows = (height - btn_height) / (y_spacing + btn_height) +1
self.max_chars_on_page = columns * rows
for i in range(self.max_chars_on_page):
self.buttons.append(CharIcon(self, i))
self.chartaken.append(QtGui.QLabel(self))
self.chartaken[i].setPixmap(QtGui.QPixmap(AOpath+"themes\\default\\char_taken.png"))
self.chartaken[i].hide()
x_pos = (btn_width + x_spacing) * x_mod_count
y_pos = (btn_height + y_spacing) * y_mod_count
self.buttons[i].setGeometry(left+x_pos, top+y_pos, btn_width, btn_height)
self.chartaken[i].move(left+x_pos, top+y_pos)
self.buttons[i].show()
x_mod_count += 1
if x_mod_count == columns:
y_mod_count += 1
x_mod_count = 0
self.prevpage = PixmapButton(self, QtGui.QPixmap(AOpath+"themes\\default\\arrow_left.png"))
self.prevpage.move(left - self.prevpage.pixmap.size().width(), top + height)
self.prevpage.clicked.connect(self.prevPageButton)
self.prevpage.show()
self.nextpage = PixmapButton(self, QtGui.QPixmap(AOpath+"themes\\default\\arrow_right.png"))
self.nextpage.move(left + width, top + height)
self.nextpage.clicked.connect(self.nextPageButton)
self.nextpage.show()
self.setBtnImage.connect(self.setButtonImage)
def quitToLobby(self):
self.parent.gamewindow.returnToMenu()
def setPic(self, pixmap, ind):
self.buttons[ind].setPixmap(QtGui.QPixmap(pixmap))
def setCharList(self, charlist):
self.charlist = charlist
self.page = 0
self.showCharPage()
def nextPageButton(self):
self.page += 1
self.showCharPage()
def prevPageButton(self):
self.page -= 1
self.showCharPage()
def showCharPage(self):
for ind in range(self.page * self.max_chars_on_page, self.max_chars_on_page * (self.page+1)):
i = ind - (self.page * self.max_chars_on_page)
if ind >= len(self.charlist):
self.chartaken[i].hide()
self.buttons[i].hide()
self.nextpage.hide()
continue
else:
self.nextpage.show()
if self.page > 0:
self.prevpage.show()
else:
self.prevpage.hide()
if exists(AOpath+"characters\\"+self.charlist[ind][0]+"\\char_icon.png"): # AO2
self.setBtnImage.emit(AOpath+"characters\\"+self.charlist[ind][0]+"\\char_icon.png", i)
elif exists(AOpath+"misc\\demothings\\"+self.charlist[ind][0]+"_char_icon.png"): # AO 1.7.5/1.8
self.setBtnImage.emit(AOpath+"misc\\demothings\\"+self.charlist[ind][0]+"_char_icon.png", i)
else:
self.setBtnImage.emit("placeholder.png", i)
if self.charlist[ind][1] == 0: # free slot
self.chartaken[i].hide()
else:
self.chartaken[i].show()
self.buttons[i].show()
def setButtonImage(self, filename, ind):
self.buttons[ind].setPixmap(QtGui.QPixmap(filename))
def onCharClicked(self, ind):
self.parent.tcp.send("CC#0#"+str(ind+(self.page*self.max_chars_on_page))+"#ur mom gay#%")

2476
gameview.py Normal file

File diff suppressed because it is too large Load Diff

46
ini.py Normal file
View File

@ -0,0 +1,46 @@
from ConfigParser import ConfigParser
def read_ini(file, section, value, default=""):
if isinstance(file, str):
conf = ConfigParser()
conf.read(file)
else:
conf = file
values = conf.sections()
for val in values:
if val.lower() == section.lower():
for c in conf.options(val):
if c.lower() == value.lower():
return conf.get(val, c)
return default
def read_ini_bool(file, section, value, default=False):
if isinstance(file, str):
conf = ConfigParser()
conf.read(file)
else:
conf = file
values = conf.sections()
for val in values:
if val.lower() == section.lower():
for c in conf.options(val):
if c.lower() == value.lower():
return conf.getboolean(val, c)
return default
def read_ini_int(file, section, value, default=0):
if isinstance(file, str):
conf = ConfigParser()
conf.read(file)
else:
conf = file
values = conf.sections()
for val in values:
if val.lower() == section.lower():
for c in conf.options(val):
if c.lower() == value.lower():
return conf.getint(val, c)
return default

542
mainmenu.py Normal file
View File

@ -0,0 +1,542 @@
# -*- coding: utf-8 -*-
from PyQt4 import QtGui, QtCore
import socket, thread, time, random
from os.path import exists
#AOpath = "base\\"
AOpath = "I:\\aovanilla1.7.5\\client\\base\\"
class PicButton(QtGui.QAbstractButton):
def __init__(self, pixmap, parent=None):
super(PicButton, self).__init__(parent)
self.pixmap = pixmap
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.drawPixmap(event.rect(), self.pixmap)
def sizeHint(self):
return self.pixmap.size()
def setPixmap(self, pixmap):
self.pixmap = pixmap
class lobby(QtGui.QWidget):
gamewindow = None
tcp = None
tab = 0
msgbox_signal = QtCore.pyqtSignal(int, str, str)
def __init__(self, parent=None):
super(lobby, self).__init__(parent)
self.can_connect = False
self.connecting = False
self.svclicked = None
self.gamewindow = parent
self.pix_lobby = QtGui.QPixmap(AOpath+'themes\\default\\lobbybackground.png')
self.pix_btn_public = QtGui.QPixmap(AOpath+'themes\\default\\publicservers.png')
self.pix_btn_favs = QtGui.QPixmap(AOpath+'themes\\default\\favorites.png')
self.pix_btn_refresh = QtGui.QPixmap(AOpath+'themes\\default\\refresh.png')
self.pix_btn_addfav = QtGui.QPixmap(AOpath+'themes\\default\\addtofav.png')
self.pix_btn_connect = QtGui.QPixmap(AOpath+'themes\\default\\connect.png')
self.pix_connecting = QtGui.QPixmap(AOpath+'themes\\default\\loadingbackground.png')
self.msgbox_signal.connect(self.showMessageBox)
if exists(AOpath+'serverlist.txt'):
with open(AOpath+'serverlist.txt') as file:
self.favoriteslist = [line.rstrip().split(':') for line in file]
else:
self.favoriteslist = ['127.0.0.1:27017:your server (port 27017)'.split(':'), '0.0.0.0:27017:serverlist.txt not found on base folder'.split(':')]
self.lobbyimg = QtGui.QLabel(self)
self.lobbyimg.setPixmap(self.pix_lobby)
self.lobbyimg.show()
self.connectingimg = QtGui.QLabel(self)
self.connectingimg.setPixmap(self.pix_connecting)
self.connectingimg.hide()
self.clientver = QtGui.QLabel(self)
self.clientver.setText('AO2XP 1.2 by Headshot')
self.clientver.resize(self.clientver.sizeHint())
self.clientver.move(self.pix_lobby.size().width() - self.clientver.size().width(), 0)
self.settingsbtn = QtGui.QPushButton(self)
self.settingsbtn.setText("Settings")
self.settingsbtn.resize(self.settingsbtn.sizeHint())
self.settingsbtn.move(self.clientver.x() - self.settingsbtn.size().width() - 8, 0)
self.settingsbtn.clicked.connect(self.onSettingsClicked)
self.btn_public = PicButton(self.pix_btn_public, self)
self.btn_public.resize(self.btn_public.sizeHint())
self.btn_public.move(46, 88)
self.btn_public.clicked.connect(self.onClicked_public)
self.btn_favs = PicButton(self.pix_btn_favs, self)
self.btn_favs.resize(self.btn_favs.sizeHint())
self.btn_favs.move(164, 88)
self.btn_favs.clicked.connect(self.onClicked_favs)
self.btn_refresh = PicButton(self.pix_btn_refresh, self)
self.btn_refresh.resize(self.btn_refresh.sizeHint())
self.btn_refresh.move(56, 381)
self.btn_refresh.clicked.connect(self.onClicked_refresh)
self.btn_addfav = PicButton(self.pix_btn_addfav, self)
self.btn_addfav.resize(self.btn_addfav.sizeHint())
self.btn_addfav.move(194, 381)
self.btn_addfav.clicked.connect(self.onClicked_addfav)
self.btn_connect = PicButton(self.pix_btn_connect, self)
self.btn_connect.resize(self.btn_connect.sizeHint())
self.btn_connect.move(332, 381)
self.btn_connect.clicked.connect(self.onClicked_connect)
self.serverlist = QtGui.QListWidget(self)
self.serverlist.resize(286, 240)
self.serverlist.move(20, 125)
self.serverlist.setStyleSheet("background-color: rgb(114, 114, 114)")
self.serverlist.itemClicked.connect(self.onClicked_serverlist)
self.onlineplayers = QtGui.QLabel(self)
self.onlineplayers.setStyleSheet('color: white')
self.onlineplayers.setAlignment(QtCore.Qt.AlignCenter | QtCore.Qt.AlignTop)
self.onlineplayers.setText(random.choice(['hi', 'oh, welcome back', 'hello', 'click on a server to begin', 'yo, how you doing?']))
self.onlineplayers.move(336, 91)
self.onlineplayers.resize(173, 16)
self.serverinfo = QtGui.QTextEdit(self)
self.serverinfo.setStyleSheet("color: white; background-color: black")
self.serverinfo.move(337, 109)
self.serverinfo.resize(173, 245)
self.connectcancel = QtGui.QPushButton(self)
self.connectcancel.setText('Cancel')
self.connectcancel.resize(80, 20)
self.connectcancel.move(220, 220)
self.connectcancel.clicked.connect(self.onClicked_cancelconnect)
self.connectcancel.hide()
self.actual_serverlist = []
self.lobbychatlog = QtGui.QTextEdit(self)
self.lobbychatlog.setReadOnly(True)
self.lobbychatlog.setGeometry(2, 445, 513, 198)
self.lobbychatlog.setStyleSheet('background-color: rgb(139, 139, 139);')
self.lobbychatlog.textChanged.connect(self.lobbychatlog_update)
self.whitecolor = QtGui.QColor(255, 255, 255)
self.font = QtGui.QFont()
self.font.setFamily(QtCore.QString.fromUtf8('Arial'))
self.font.setBold(True)
self.font.setPointSize(14)
self.connectprogress = QtGui.QLabel(self)
self.connectprogress.hide()
self.connectprogress.setStyleSheet('color: rgb(255, 128, 0);')
self.connectprogress.setFont(self.font)
self.connectprogress.setText('Connecting...')
self.connectprogress.resize(300, 95)
self.connectprogress.setAlignment(QtCore.Qt.AlignCenter | QtCore.Qt.AlignTop)
self.connectprogress.move(135-20, 92)
self.oocname = 'Name'
self.oocnameinput = QtGui.QLineEdit(self)
self.oocnameinput.setText(self.oocname)
self.oocnameinput.move(0, 646)
self.oocnameinput.resize(91, 19)
self.oocnameinput.setStyleSheet('background-color: rgb(87, 87, 87);')
self.oocnameinput.textChanged.connect(self.setoocname)
self.lobbychatinput = QtGui.QLineEdit(self)
self.lobbychatinput.setPlaceholderText("Say something...")
self.lobbychatinput.move(90, 646)
self.lobbychatinput.resize(427, 19)
self.lobbychatinput.setStyleSheet('background-color: rgb(87, 87, 87);')
self.lobbychatinput.returnPressed.connect(self.lobby_sendchat)
self.joinooc = []
thread.start_new_thread(self.connect_to_ms, ())
def onSettingsClicked(self):
self.gamewindow.showSettings()
def showMessageBox(self, type, title, message):
if type == 0: #critical
return QtGui.QMessageBox.critical(self, title, message)
elif type == 1: #information
return QtGui.QMessageBox.information(self, title, message)
elif type == 2: #question
return QtGui.QMessageBox.question(self, title, message)
elif type == 3: #warning
return QtGui.QMessageBox.warning(self, title, message)
def onClicked_public(self):
self.tab = 0
self.serverlist.clear()
for sv in self.actual_serverlist:
self.serverlist.addItem(QtGui.QListWidgetItem(sv[2]))
def onClicked_favs(self):
self.tab = 1
self.serverlist.clear()
self.serverinfo.setText("")
for sv in self.favoriteslist:
self.serverlist.addItem(QtGui.QListWidgetItem(sv[2]))
def onClicked_refresh(self):
self.serverlist.clear()
if self.tab == 0:
try:
self.ms_tcp.send('ALL#%')
except:
self.lobbychatlog.append('failed to refresh server list')
elif self.tab == 1:
if exists(AOpath+'serverlist.txt'):
with open(AOpath+'serverlist.txt') as file:
self.favoriteslist = [ line.rstrip().split(':') for line in file ]
else:
self.favoriteslist = ['127.0.0.1:27017:your server (port 27017)'.split(':'), '0.0.0.0:27017:serverlist.txt not found on base folder'.split(':')]
def onClicked_addfav(self):
if self.tab == 1 or not self.svclicked:
if self.tab == 1:
QtGui.QMessageBox.information(self, "???", "Wait. That's illegal.")
return
for i in range(self.serverlist.count()):
if self.serverlist.item(i) == self.svclicked:
ip = self.actual_serverlist[i][0]
port = str(self.actual_serverlist[i][1])
name = self.actual_serverlist[i][2]
for sv in self.favoriteslist:
if sv[0] == ip and sv[1] == port:
return QtGui.QMessageBox.information(self, "Error", "This server already exists in your favorites list, named '%s'" % sv[2])
self.favoriteslist.append([ip, port, name])
with open(AOpath+'serverlist.txt', "a") as file:
file.write("%s:%s:%s\n" % (ip, port, name))
file.close()
def onClicked_connect(self):
if not self.can_connect:
return
self.connectprogress.setText('Connecting...')
self.connecting = True
self.connectingimg.show()
self.connectcancel.show()
self.connectprogress.show()
self.btn_public.hide()
self.btn_favs.hide()
self.btn_refresh.hide()
self.btn_addfav.hide()
self.btn_connect.hide()
self.serverlist.hide()
self.onlineplayers.hide()
self.serverinfo.hide()
self.clientver.hide()
self.settingsbtn.hide()
self.tcp.send('askchaa#%')
def onClicked_cancelconnect(self):
self.connecting = False
self.connectingimg.hide()
self.connectcancel.hide()
self.connectprogress.hide()
self.btn_public.show()
self.btn_favs.show()
self.btn_refresh.show()
self.btn_addfav.show()
self.btn_connect.show()
self.serverlist.show()
self.onlineplayers.show()
self.serverinfo.show()
self.clientver.show()
self.settingsbtn.show()
def onClicked_serverlist(self, item):
self.svclicked = item
self.can_connect = False
if self.tcp:
self.tcp.close()
self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
args = (item, item)
thread.start_new_thread(self.get_sv_players, args)
self.onlineplayers.setText('Retrieving...')
for i in range(self.serverlist.count()):
if self.serverlist.item(i) == item and self.tab == 0:
self.serverinfo.setText(self.actual_serverlist[i][3])
def get_sv_players(self, item, *args, **kwargs):
tempdata = ""
hplist = []
areas = [[], [], [], []]
features = []
pingtimer = 150
readytick = -1
text = item.text()
print '[debug]', 'you clicked %s' % text
for i in range(self.serverlist.count()):
if self.serverlist.item(i) == item:
if self.tab == 0:
print '[debug]', 'ind: ' + str(i) + ', ip: ' + self.actual_serverlist[i][0] + ', port: ' + str(self.actual_serverlist[i][1])
try:
self.tcp.connect((self.actual_serverlist[i][0], self.actual_serverlist[i][1]))
except:
return self.onlineplayers.setText("couldn't retrieve players")
elif self.tab == 1:
print '[debug]', 'ind: ' + str(i) + ', ip: ' + self.favoriteslist[i][0] + ', port: ' + str(self.favoriteslist[i][1])
try:
self.tcp.connect((self.favoriteslist[i][0], int(self.favoriteslist[i][1])))
except:
return self.onlineplayers.setText("couldn't retrieve players")
self.tcp.settimeout(0.2)
while True:
pingtimer -= 1
if pingtimer == 0:
pingtimer = 150
self.tcp.send('CH#%')
if readytick > -1:
readytick -= 1
if readytick == 0:
readytick = -1
try:
self.move_to_game(self.tcp, charlist, musiclist, background, evidence, areas, features, self.joinooc, hplist)
except Exception as err:
self.msgbox_signal.emit(0, "Error caught while loading", str(err))
self.onClicked_cancelconnect()
return
self.gamewindow.setWindowTitle(text)
thread.exit()
try:
contents = self.tcp.recv(16384)
except (socket.timeout, socket.error) as err:
error = err.args[0]
if error == "timed out" or error == 10035:
continue
else:
if not got_stuff:
return self.onlineplayers.setText('something wrong happened')
thread.exit()
if not contents.endswith("%"):
tempdata += contents
continue
else:
if tempdata:
contents = tempdata + contents
tempdata = ""
totals = contents.split('%')
for g in totals:
network = g.split('#')
header = network[0]
if header == 'PN':
players = int(network[1])
maxplayers = int(network[2])
self.can_connect = True
self.onlineplayers.setText('%d/%d players online' % (players, maxplayers))
got_stuff = True
elif header == "decryptor":
self.tcp.send("HI#thanks for the back massage Maya. [IC] Adrian (MayaDA): hey ace#%")
elif header == "ID":
self.tcp.send("ID#AO2#69.1337.420#%") #need to send this to tsuserver3 servers in order to get feature list (FL)
elif header == "FL":
features = network[1:]
print features
elif header == 'BD':
reason = network[1].decode("utf-8") #new in AO2 2.6
self.onlineplayers.setText('Banned')
self.msgbox_signal.emit(0, "Banned", "Reason:\n"+reason)
self.tcp.close()
thread.exit()
elif header == 'SI':
if not self.connecting:
continue
maxchars = int(network[1])
maxevidence = int(network[2])
maxmusic = int(network[3])
self.connectprogress.setText('Requesting character list (%d)...' % maxchars)
self.tcp.send('RC#%')
print '[client]', '%d characters, %d pieces of evidence and %d songs' % (maxchars, maxevidence, maxmusic)
elif header == 'SC':
if not self.connecting:
continue
del network[0]
del network[len(network)-1]
charlist = [ [char.split('&')[0], -1, "male"] for char in network ]
self.connectprogress.setText('Requesting music list (%d)...' % maxmusic)
self.tcp.send('RM#%')
print '[client]', 'received characters (%d)' % len(charlist)
elif header == 'SM':
if not self.connecting:
continue
del network[0]
del network[len(network)-1]
musiclist = [ music for music in network ]
self.connectprogress.setText('Finishing...')
self.tcp.send('RD#%')
print '[client]', 'received songs (%d)' % len(musiclist)
elif header == 'CharsCheck':
if not self.connecting:
continue
network.pop(0)
network.pop(len(network)-1)
for i in range(len(network)):
charlist[i][1] = int(network[i])
elif header == 'BN':
if not self.connecting:
continue
background = network[1]
print '[client]', 'courtroom background: %s' % background
elif header == 'LE':
if not self.connecting:
continue
del network[0]
del network[len(network)-1]
if len(network) > 0:
if "<and>" in network[0]: #The Next Chapter actually does this sorcery...
evidence = [evi.split("<and>") for evi in network]
else:
evidence = [evi.split("&") for evi in network]
else:
evidence = []
for evi in evidence:
evi[0] = evi[0].decode("utf-8")
evi[1] = evi[1].decode("utf-8")
evi[2] = evi[2].decode("utf-8")
print '[client]', 'received evidence'
elif header == 'HP':
if not self.connecting:
continue
del network[0]
del network[len(network)-1]
type = int(network[0])
health = int(network[1])
hplist.append([type, health])
elif header == "ARUP": #AO2 2.6 new feature: area update
del network[0]
del network[len(network)-1]
type = int(network[0])
if type == 0: #player count
areas[type] = [network[i] for i in range(1, len(network))]
else: #area status, casemakers or locked area
areas[type] = [network[i] for i in range(1, len(network))]
elif header == 'DONE':
if not self.connecting:
continue
self.connectprogress.setText('Done, loading...')
self.connectcancel.hide()
print '[client]', 'finished requesting data, loading game...'
readytick = 4
elif header == 'CT':
if not self.connecting:
continue
del network[0]
del network[len(network)-1]
name = network[0].decode("utf-8").replace('<dollar>', '$').replace('<percent>', '%').replace('<and>', '&').replace('<num>', '#').replace('<pound>', '#')
chatmsg = network[1].decode("utf-8").replace('<dollar>', '$').replace('<percent>', '%').replace('<and>', '&').replace('<num>', '#').replace('<pound>', '#')
self.joinooc.append("%s: %s" % (name, chatmsg))
def move_to_game(self, tcp, charlist, musiclist, background, evidence, areas, features=[], oocjoin=[], hplist=[]):
self.gamewindow.showGame(tcp, charlist, musiclist, background, evidence, areas, features, oocjoin, hplist)
def lobby_sendchat(self):
text = self.lobbychatinput.text().toUtf8()
self.ms_tcp.send('CT#' +self.oocname+ '#' + text + '#%')
self.lobbychatinput.clear()
def setoocname(self):
self.oocname = self.oocnameinput.text().toUtf8()
def lobbychatlog_update(self):
self.lobbychatlog.verticalScrollBar().setValue(self.lobbychatlog.verticalScrollBar().maximum())
def connect_to_ms(self):
tempdata = ""
self.ms_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self.ms_tcp.connect(('master.aceattorneyonline.com', 27016))
except:
thread.exit()
while True:
contents = self.ms_tcp.recv(16384)
if len(contents) == 0:
print 'masterserver failure'
thread.exit()
if not contents.endswith("%"):
tempdata += contents
continue
else:
if tempdata:
contents = tempdata + contents
tempdata = ""
temp = contents.split('%')
for msg in temp:
network = msg.split('#')
header = network[0]
if header == "servercheok":
self.ms_tcp.send('HI#haha lol mods are gay#%ID#AO2XP by Headshot#1.2#%')
self.ms_tcp.send("ALL#%")
elif header == 'DOOM':
print 'banned from masterserver'
self.msgbox_signal.emit(0, "WHEEZE", "You've been exiled from AO.\nWow, great job, now everyone hates you lmao")
self.ms_tcp.close()
thread.exit()
elif header == 'ALL':
self.serverlist.clear()
self.actual_serverlist = []
network.pop(0)
network.pop(len(network) - 1)
for svcontent in network:
server = svcontent.split('&')
del server[len(server)-1]
name = server[0].decode('utf-8')
desc = server[1].decode('utf-8')
if len(server) <= 2:
ip = '0.0.0.0'
port = 0
elif len(server) == 3:
ip = server[2]
port = 27017
elif len(server) == 4:
ip = server[2]
port = int(server[3])
serveritem = QtGui.QListWidgetItem(name)
self.serverlist.addItem(serveritem)
self.actual_serverlist.append((ip, port, name, desc))
elif header == 'CT':
name = network[1].decode("utf-8").replace('<dollar>', '$').replace('<percent>', '%').replace('<and>', '&').replace('<num>', '#').replace('<pound>', '#')
chatmsg = network[2].decode("utf-8").replace('<dollar>', '$').replace('<percent>', '%').replace('<and>', '&').replace('<num>', '#').replace('<pound>', '#')
self.lobbychatlog.append('%s: %s' % (name, chatmsg))

BIN
mod_call.wav Normal file

Binary file not shown.

159
options.py Normal file
View File

@ -0,0 +1,159 @@
from PyQt4 import QtGui, QtCore
from ConfigParser import ConfigParser
from os.path import exists
import ini
#AOpath = "base\\"
AOpath = "I:\\aovanilla1.7.5\\client\\base\\"
class Settings(QtGui.QWidget):
def __init__(self):
super(Settings, self).__init__()
self.inifile = ConfigParser()
self.setWindowTitle("Settings")
self.setFixedSize(320, 480)
self.hide()
main_layout = QtGui.QVBoxLayout(self)
save_layout = QtGui.QHBoxLayout()
self.tabs = QtGui.QTabWidget()
self.tabs.resize(320-16, 480-40)
self.tabs.move(8, 8)
general_tab = QtGui.QWidget()
callwords_tab = QtGui.QWidget()
general_layout = QtGui.QVBoxLayout(general_tab)
general_layout.setAlignment(QtCore.Qt.AlignTop)
callwords_layout = QtGui.QVBoxLayout(callwords_tab)
callwords_layout.setAlignment(QtCore.Qt.AlignTop)
savebtn = QtGui.QPushButton()
savebtn.setText("Save")
savebtn.clicked.connect(self.onSaveClicked)
cancelbtn = QtGui.QPushButton()
cancelbtn.setText("Cancel")
cancelbtn.clicked.connect(self.onCancelClicked)
separators = []
for i in range(2):
separator = QtGui.QFrame()
separator.setFixedSize(separator.size().width(), 16)
separators.append(separator)
###### General tab ######
self.savetolog = QtGui.QCheckBox()
self.savetolog.setText("Save chat logs to a file*")
self.savetolog.setChecked(False)
self.savetolog_combine = QtGui.QCheckBox()
self.savetolog_combine.setText("Combine OOC and IC chat logs in the same file*")
self.savetolog_combine.setChecked(False)
defaultoocname_layout = QtGui.QHBoxLayout()
defaultoocname_label = QtGui.QLabel("Default OOC name")
self.defaultoocname = QtGui.QLineEdit()
defaultoocname_layout.addWidget(defaultoocname_label)
defaultoocname_layout.addWidget(self.defaultoocname)
allowdownload = QtGui.QLabel()
allowdownload.setText("Automatically download or stream online from WebAO:")
allowdownload_layout = QtGui.QHBoxLayout()
self.allowdownload_chars = QtGui.QCheckBox("Characters")
self.allowdownload_sounds = QtGui.QCheckBox("Sounds")
self.allowdownload_music = QtGui.QCheckBox("Music")
self.allowdownload_evidence = QtGui.QCheckBox("Evidence")
allowdownload_layout.addWidget(self.allowdownload_chars)
allowdownload_layout.addWidget(self.allowdownload_sounds)
allowdownload_layout.addWidget(self.allowdownload_music)
allowdownload_layout.addWidget(self.allowdownload_evidence)
savechangeswarn = QtGui.QLabel()
savechangeswarn.setText("* Change takes effect upon restarting the client")
general_layout.addWidget(self.savetolog)
general_layout.addWidget(self.savetolog_combine, 0, QtCore.Qt.AlignRight)
general_layout.addWidget(separators[0])
general_layout.addLayout(defaultoocname_layout)
general_layout.addWidget(separators[1])
general_layout.addWidget(allowdownload)
general_layout.addLayout(allowdownload_layout)
general_layout.addWidget(savechangeswarn, 50, QtCore.Qt.AlignBottom)
###### Callwords tab ######
self.callwords_edit = QtGui.QTextEdit()
callwords_wordwrap = QtGui.QCheckBox("Word Wrap")
callwords_wordwrap.setChecked(True)
callwords_wordwrap.stateChanged.connect(self.callwordsWordWrapCheckbox)
callwords_instructions = QtGui.QLabel()
callwords_instructions.setText("Separate callwords with newlines (ENTER key).")
callwords_layout.addWidget(self.callwords_edit)
callwords_layout.addWidget(callwords_wordwrap, 0, QtCore.Qt.AlignRight)
callwords_layout.addWidget(callwords_instructions)
self.tabs.addTab(general_tab, "General")
self.tabs.addTab(callwords_tab, "Callwords")
save_layout.addWidget(savebtn, 100, QtCore.Qt.AlignRight)
save_layout.addWidget(cancelbtn, 0, QtCore.Qt.AlignRight)
main_layout.addWidget(self.tabs)
main_layout.addLayout(save_layout)
def showSettings(self):
if exists(AOpath+"AO2XP.ini"):
self.inifile.read(AOpath+"AO2XP.ini")
self.savetolog.setChecked(ini.read_ini_bool(self.inifile, "General", "save logs"))
self.savetolog_combine.setChecked(ini.read_ini_bool(self.inifile, "General", "combined logs"))
try:
self.defaultoocname.setText(ini.read_ini(self.inifile, "General", "OOC name").decode("utf-8"))
except:
self.defaultoocname.setText(ini.read_ini(self.inifile, "General", "OOC name"))
self.allowdownload_chars.setChecked(ini.read_ini_bool(self.inifile, "General", "download characters"))
self.allowdownload_sounds.setChecked(ini.read_ini_bool(self.inifile, "General", "download sounds"))
self.allowdownload_music.setChecked(ini.read_ini_bool(self.inifile, "General", "download music"))
self.allowdownload_evidence.setChecked(ini.read_ini_bool(self.inifile, "General", "download evidence"))
else:
self.savetolog.setChecked(False)
self.savetolog_combine.setChecked(False)
self.defaultoocname.setText("")
self.allowdownload_sounds.setChecked(True)
self.allowdownload_music.setChecked(True)
self.allowdownload_evidence.setChecked(True)
self.callwords_edit.clear()
if exists(AOpath+"callwords.ini"):
with open(AOpath+"callwords.ini") as f:
for line in f:
self.callwords_edit.append(line.rstrip().decode("utf-8"))
self.tabs.setCurrentIndex(0)
self.show()
def callwordsWordWrapCheckbox(self, newstate):
if newstate:
self.callwords_edit.setWordWrapMode(QtGui.QTextOption.WrapAtWordBoundaryOrAnywhere)
else:
self.callwords_edit.setWordWrapMode(0)
def onSaveClicked(self):
if not self.inifile.has_section("General"):
self.inifile.add_section("General")
self.inifile.set("General", "save logs", self.savetolog.isChecked())
self.inifile.set("General", "combined logs", self.savetolog_combine.isChecked())
self.inifile.set("General", "OOC name", self.defaultoocname.text().toUtf8())
self.inifile.set("General", "download characters", self.allowdownload_chars.isChecked())
self.inifile.set("General", "download sounds", self.allowdownload_sounds.isChecked())
self.inifile.set("General", "download music", self.allowdownload_music.isChecked())
self.inifile.set("General", "download evidence", self.allowdownload_evidence.isChecked())
self.inifile.write(open(AOpath+"AO2XP.ini", "w"))
with open(AOpath+"callwords.ini", "w") as f:
f.write(self.callwords_edit.toPlainText().toUtf8())
self.hide()
def onCancelClicked(self):
self.hide()

BIN
placeholder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

55
quicksetup.py Normal file
View File

@ -0,0 +1,55 @@
import urllib2
import zipfile
import subprocess
import sys
import os
def pip_install(package):
subprocess.call([sys.executable, "-m", "pip", "install", package])
print "downloading pybass"
filedata = urllib2.urlopen('https://datapacket.dl.sourceforge.net/project/pybass/pybass_055.zip')
datatowrite = filedata.read()
with open('pybass_055.zip', 'wb') as f:
f.write(datatowrite)
f.close()
print "extracting pybass"
zip_ref = zipfile.ZipFile('pybass_055.zip', 'r')
zip_ref.extractall()
zip_ref.close()
print "renaming pybass.py"
os.remove('pybass/__init__.py')
os.rename('pybass/pybass.py', 'pybass/__init__.py')
print "downloading bass"
filedata = urllib2.urlopen('http://us.un4seen.com/files/bass24.zip')
datatowrite = filedata.read()
with open('bass24.zip', 'wb') as f:
f.write(datatowrite)
f.close()
print "extracting bass"
zip_ref = zipfile.ZipFile('bass24.zip', 'r')
zip_ref.extract('bass.dll')
zip_ref.close()
print "downloading pyqt4"
filedata = urllib2.urlopen('https://download.lfd.uci.edu/pythonlibs/u2hcgva4/PyQt4-4.11.4-cp27-cp27m-win32.whl')
datatowrite = filedata.read()
with open('PyQt4-4.11.4-cp27-cp27m-win32.whl', 'wb') as f:
f.write(datatowrite)
f.close()
print "installing pyqt4"
pip_install('PyQt4-4.11.4-cp27-cp27m-win32.whl')
print "installing pyinstaller"
pip_install('pyinstaller')
print "done"

BIN
word_call.wav Normal file

Binary file not shown.