commit 40f195f5c64871bd0cdeb61d8e91f11ab0cf52ba Author: Headshot Date: Wed Apr 3 10:27:23 2019 -0430 UPLOADED diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1c87076 --- /dev/null +++ b/.gitignore @@ -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 diff --git a/AO2XP.py b/AO2XP.py new file mode 100644 index 0000000..1cf0fe3 --- /dev/null +++ b/AO2XP.py @@ -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_()) \ No newline at end of file diff --git a/AO2XP.spec b/AO2XP.spec new file mode 100644 index 0000000..7371d35 --- /dev/null +++ b/AO2XP.spec @@ -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) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8a53889 --- /dev/null +++ b/README.md @@ -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 diff --git a/buttons.py b/buttons.py new file mode 100644 index 0000000..f85f290 --- /dev/null +++ b/buttons.py @@ -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 \ No newline at end of file diff --git a/charselect.py b/charselect.py new file mode 100644 index 0000000..0cdaa47 --- /dev/null +++ b/charselect.py @@ -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#%") \ No newline at end of file diff --git a/gameview.py b/gameview.py new file mode 100644 index 0000000..e8c8cba --- /dev/null +++ b/gameview.py @@ -0,0 +1,2476 @@ +import socket, thread, time, os, buttons, urllib, charselect, ini +from PyQt4 import QtGui, QtCore +from pybass import * +from os.path import exists +from functools import partial +from ConfigParser import ConfigParser + +#AOpath = "base/" +AOpath = 'I:/aovanilla1.7.5/client/base/' + +PREANIM = 2 +CHARNAME = 3 +ANIM = 4 +CHATMSG = 5 +SIDE = 6 +SFX = 7 +EMOTE_MOD = 8 +CHAR_ID = 9 +SFX_DELAY = 10 +SHOUT_MOD = 11 +EVIDENCE = 12 +FLIP = 13 +REALIZATION = 14 +TEXT_COLOR = 15 +SHOWNAME = 16 +OTHER_CHARID = 17 +OTHER_NAME = 18 +OTHER_EMOTE = 19 +SELF_OFFSET = 20 +OTHER_OFFSET = 21 +OTHER_FLIP = 22 +NO_INTERRUPT = 23 + +INLINE_BLUE = 0 +INLINE_GREEN = 1 +INLINE_ORANGE = 2 +INLINE_GRAY = 3 + +C_WHITE = 0 +C_GREEN = 1 +C_RED = 2 +C_ORANGE = 3 +C_BLUE = 4 +C_YELLOW = 5 +C_RAINBOW = 6 +C_PINK = 7 +C_CYAN = 8 + +def delay(msec): + dieTime = QtCore.QTime.currentTime().addMSecs(msec) + + while QtCore.QTime.currentTime() < dieTime: + QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 100) + +def get_char_ini(char, section, value, default=""): + tempini = ConfigParser() + tempini.read(AOpath + 'characters\\' + char + '\\char.ini') + return ini.read_ini(tempini, section, value, default) + +def get_text_color(textcolor): + if textcolor == 0 or textcolor == 6: + return QtGui.QColor(255, 255, 255) + elif textcolor == 1: + return QtGui.QColor(0, 255, 0) + elif textcolor == 2: #OH FUCK MOD + return QtGui.QColor(255, 0, 0) + elif textcolor == 3: + return QtGui.QColor(255, 165, 0) + elif textcolor == 4: + return QtGui.QColor(45, 150, 255) + elif textcolor == 5: + return QtGui.QColor(255, 255, 0) + elif textcolor == 7: + return QtGui.QColor(255, 192, 203) + elif textcolor == 8: + return QtGui.QColor(0, 255, 255) + elif textcolor == "_inline_grey": + return QtGui.QColor(187, 187, 187) + + return QtGui.QColor(0, 0, 0) + +def download_thread(link, savepath): + print link, savepath + urllib.urlretrieve(link, savepath) + +class ChatLogs(QtGui.QTextEdit): + def __init__(self, parent, logtype, logfile=None): + QtGui.QTextEdit.__init__(self, parent) + self.type = logtype + self.savelog = ini.read_ini_bool(AOpath+"AO2XP.ini", "General", "save logs") + self.combinelog = ini.read_ini_bool(AOpath+"AO2XP.ini", "General", "combined logs") + if not os.path.exists("chatlogs"): + os.mkdir("chatlogs") + + if self.savelog: + currtime = time.localtime() + if self.combinelog: + if self.type == 0: + self.logfile = logfile + else: + self.logfile = open("chatlogs/%d%.2d%.2d_on_%.2d.%.2d.%.2d.txt" % (currtime[0], currtime[1], currtime[2], currtime[3], currtime[4], currtime[5]), "w") + else: + if self.type == 0: + self.logfile = open("chatlogs/IC_%d%.2d%.2d_on_%.2d.%.2d.%.2d.txt" % (currtime[0], currtime[1], currtime[2], currtime[3], currtime[4], currtime[5]), "w") + else: + self.logfile = open("chatlogs/OOC_%d%.2d%.2d_on_%.2d.%.2d.%.2d.txt" % (currtime[0], currtime[1], currtime[2], currtime[3], currtime[4], currtime[5]), "w") + + def __del__(self): + if self.savelog: + self.logfile.close() + + def append(self, text): + super(ChatLogs, self).append(text) + if self.savelog: + if isinstance(text, str) or isinstance(text, unicode): + if self.combinelog and not "Log started" in text: + if self.type == 0: + self.logfile.write("[IC] "+text.encode("utf-8")+"\n") + else: + self.logfile.write("[OOC] "+text.encode("utf-8")+"\n") + else: + self.logfile.write(text.encode("utf-8")+"\n") + else: + if self.combinelog and not "Log started" in text: + if self.type == 0: + self.logfile.write("[IC] "+text.toUtf8()+"\n") + else: + self.logfile.write("[OOC] "+text.toUtf8()+"\n") + else: + self.logfile.write(text.toUtf8()+"\n") + +class AOCharMovie(QtGui.QLabel): + done = QtCore.pyqtSignal() + + def __init__(self, parent): + QtGui.QLabel.__init__(self, parent) + + self.resize(256, 192) + self.time_mod = 62 + self.play_once = True + self.m_flipped = False + + self.m_movie = QtGui.QMovie() + + self.preanim_timer = QtCore.QTimer(self) + self.preanim_timer.setSingleShot(True) + + self.preanim_timer.timeout.connect(self.timer_done) + self.m_movie.frameChanged.connect(self.frame_change) + + def set_flipped(self, flip): + self.m_flipped = flip + + def play(self, p_char, p_emote, emote_prefix): + original_path = AOpath+"characters\\"+p_char+"\\"+emote_prefix+p_emote+".gif" + alt_path = AOpath+"characters\\"+p_char+"\\"+p_emote+".png" + placeholder_path = AOpath+"themes\\default\\placeholder.gif" + gif_path = "" + + if exists(original_path): + gif_path = original_path + elif exists(alt_path): + gif_path = alt_path + elif exists(placeholder_path): + gif_path = placeholder_path + else: + gif_path = "" + + self.m_movie.stop() + self.m_movie.setFileName(gif_path) + + self.show() + self.m_movie.start() + + def play_pre(self, p_char, p_emote, duration): + gif_path = AOpath+"characters\\"+p_char+"\\"+p_emote+".gif" + + self.m_movie.stop() + self.clear() + self.m_movie.setFileName(gif_path) + self.m_movie.jumpToFrame(0) + + full_duration = duration * self.time_mod + real_duration = 0 + + self.play_once = False + + for n_frame in range(self.m_movie.frameCount()): + real_duration += self.m_movie.nextFrameDelay() + self.m_movie.jumpToFrame(n_frame + 1) + + percentage_modifier = 100.0 + + if real_duration != 0 and duration != 0: + modifier = full_duration / float(real_duration) + percentage_modifier = 100 / modifier + + if percentage_modifier > 100.0 or percentage_modifier < 0.0: + percentage_modifier = 100.0 + + if full_duration == 0 or full_duration >= real_duration: + self.play_once = True + else: + self.play_once = False + if full_duration >= 0: + self.preanim_timer.start(full_duration) + + self.m_movie.setSpeed(int(percentage_modifier)) + self.play(p_char, p_emote, "") + + def play_talking(self, p_char, p_emote): + gif_path = AOpath + 'characters\\' + p_char + '\\(b)' + p_emote + '.gif' + + self.m_movie.stop() + self.clear() + self.m_movie.setFileName(gif_path) + self.m_movie.jumpToFrame(0) + + self.play_once = False + self.m_movie.setSpeed(100) + self.play(p_char, p_emote, '(b)') + + def play_idle(self, p_char, p_emote): + gif_path = AOpath + 'characters\\' + p_char + '\\(a)' + p_emote + '.gif' + + self.m_movie.stop() + self.clear() + self.m_movie.setFileName(gif_path) + self.m_movie.jumpToFrame(0) + + self.play_once = False + self.m_movie.setSpeed(100) + self.play(p_char, p_emote, '(a)') + + def stop(self): + self.m_movie.stop() + self.preanim_timer.stop() + self.hide() + + @QtCore.pyqtSlot(int) + def frame_change(self, n_frame): + f_pixmap = QtGui.QPixmap.fromImage(self.m_movie.currentImage().mirrored(self.m_flipped, False)) + self.setPixmap(f_pixmap) + + if self.m_movie.frameCount() - 1 == n_frame and self.play_once: + self.preanim_timer.start(self.m_movie.nextFrameDelay()) + + @QtCore.pyqtSlot() + def timer_done(self): + self.done.emit() + +class AOMovie(QtGui.QLabel): + play_once = True + done = QtCore.pyqtSignal() + + def __init__(self, parent): + QtGui.QLabel.__init__(self, parent) + self.m_movie = QtGui.QMovie() + self.setMovie(self.m_movie) + self.m_movie.frameChanged.connect(self.frame_change) + + def set_play_once(self, once): + self.play_once = once + + def play(self, p_gif, p_char): + self.m_movie.stop() + + gif_path = "" + + custom_path = "" + if p_gif == "custom": + custom_path = AOpath+"characters\\"+p_char+"\\"+p_gif+".gif" + else: + custom_path = AOpath+"characters\\"+p_char+"\\"+p_gif+"_bubble.gif" + + theme_path = AOpath+"themes\\default\\"+p_gif+".gif" + placeholder_path = AOpath+"themes\\default\\placeholder.gif" + + if exists(custom_path): + gif_path = custom_path + elif exists(theme_path): + gif_path = theme_path + else: + gif_path = placeholder_path + + self.m_movie.setFileName(gif_path) + + self.show() + self.m_movie.start() + + def stop(self): + self.m_movie.stop() + self.hide() + + @QtCore.pyqtSlot(int) + def frame_change(self, n_frame): + if n_frame == self.m_movie.frameCount() - 1 and self.play_once: + delay(self.m_movie.nextFrameDelay()) + self.stop() + self.done.emit() + +class ZoomLines(QtGui.QLabel): + + def __init__(self, parent): + super(ZoomLines, self).__init__(parent) + self.resize(256, 192) + self.movie = QtGui.QMovie() + self.movie.frameChanged.connect(self.frame_change) + + def frame_change(self): + img = self.movie.currentImage() + self.setPixmap(QtGui.QPixmap.fromImage(img)) + + def setZoom(self, on, dir=0): + self.movie.stop() + if not on: + self.hide() + return + self.show() + if dir == 0: + self.movie.setFileName(AOpath + 'themes\\default\\defense_speedlines.gif') + else: + self.movie.setFileName(AOpath + 'themes\\default\\prosecution_speedlines.gif') + self.movie.start() + + +class WTCE_View(QtGui.QLabel): + + def __init__(self, parent): + super(WTCE_View, self).__init__(parent) + self.movie = QtGui.QMovie() + self.movie.frameChanged.connect(self.frame_change) + self.finalframe_timer = QtCore.QTimer() + self.finalframe_timer.setSingleShot(False) + self.finalframe_timer.timeout.connect(self.finished) + self.resize(256, 192) + + def frame_change(self, frame): + if self.movie.state() != QtGui.QMovie.Running: + return + img = self.movie.currentImage() + self.setPixmap(QtGui.QPixmap.fromImage(img)) + if self.movie.currentFrameNumber() == self.movie.frameCount() - 1: + self.finalframe_timer.start(self.movie.nextFrameDelay()) + + def finished(self): + self.finalframe_timer.stop() + self.movie.stop() + self.hide() + + def showWTCE(self, wtce, variant=0): + self.finished() + if wtce == 'testimony1': + self.movie.setFileName(AOpath + 'themes\\default\\witnesstestimony.gif') + elif wtce == 'testimony2': + self.movie.setFileName(AOpath + 'themes\\default\\crossexamination.gif') + elif wtce == "judgeruling": + if variant == 0: + self.movie.setFileName(AOpath + 'themes\\default\\notguilty.gif') + elif variant == 1: + self.movie.setFileName(AOpath + 'themes\\default\\guilty.gif') + else: + return + self.show() + self.movie.start() + +class gui(QtGui.QWidget): + gamewindow = None + sound = None + music = None + next_character_is_not_special = False + message_is_centered = False + current_display_speed = 3 + message_display_speed = (30, 40, 50, 60, 75, 100, 120) + entire_message_is_blue = False + inline_color_stack = [] #"colour" is for EU nobos + inline_blue_depth = 0 + other_charid = -1 + offset_with_pair = 0 + tick_pos = 0 + blip_pos = 0 + blip_rate = 1 + time_mod = 40 + blip = "male" + blipsnd = None + chatmessage_size = 24 + m_chatmessage = [] + blank_blip = False + chatmessage_is_empty = False + anim_state = 3 + text_state = 2 + objection_state = 0 + text_color = 0 + + charini = ConfigParser() + chatmsg = '' + charid = -1 + #ICchat = QtCore.pyqtSignal(str, str, str, str, str, str, int, int, int, int, int, int, int, int) + ICchat = QtCore.pyqtSignal(list) + WTCEsignal = QtCore.pyqtSignal(str, int) + healthbars = QtCore.pyqtSignal(int, int) + + def __init__(self, parent=None): + super(gui, self).__init__(parent) + self.gamewindow = parent + + for i in range(self.chatmessage_size): + self.m_chatmessage.append("") + + self.chat_tick_timer = QtCore.QTimer(self) + self.chat_tick_timer.timeout.connect(self.chat_tick) + + self.sfx_delay_timer = QtCore.QTimer(self) + self.sfx_delay_timer.setSingleShot(True) + self.sfx_delay_timer.timeout.connect(self.play_sfx) + + if exists('mod_call.wav'): + self.modcall = BASS_StreamCreateFile(False, 'mod_call.wav', 0, 0, 0) + else: + self.modcall = None + + self.wtcesfx = BASS_StreamCreateFile(False, AOpath + 'sounds/general/sfx-testimony2.wav', 0, 0, 0) + self.guiltysfx = BASS_StreamCreateFile(False, AOpath+"sounds/general/sfx-guilty.wav", 0, 0, 0) + self.notguiltysfx = BASS_StreamCreateFile(False, AOpath+"sounds/general/sfx-notguilty.wav", 0, 0, 0) + + self.healthbars.connect(self.netmsg_hp) + self.disconnectnow = False + self.swapping = False + self.iniswapindex = 0 + self.background = 'default' + + self.viewport = QtGui.QWidget(self) + self.viewport.resize(256, 192) + + self.court = QtGui.QLabel(self.viewport) + self.zoom = ZoomLines(self.viewport) + + self.char = AOCharMovie(self.viewport) + self.char.done.connect(self.preanim_done) + self.sidechar = AOCharMovie(self.viewport) + self.sidechar.hide() + + self.bench = QtGui.QLabel(self.viewport) + bench = QtGui.QPixmap(AOpath + 'background\\default\\defensedesk.png') + self.court.setPixmap(QtGui.QPixmap(AOpath + 'background\\default\\defenseempty.png')) + self.bench.setPixmap(bench) + self.chatbox = QtGui.QLabel(self) + chatbox = QtGui.QPixmap(AOpath + 'themes\\default\\chatmed.png') + chatboxheight = chatbox.size().height() + self.chatbox.setPixmap(chatbox) + self.chatbox.move(0, 192 - chatboxheight) + + self.text = QtGui.QLabel(self) + self.text.setWordWrap(True) + self.text.resize(250, 96) + self.text.move(6, 192 - chatboxheight + 20) + self.text.setStyleSheet('color: white') + self.text.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) + + self.ao2text = QtGui.QTextEdit(self) + self.ao2text.setFrameStyle(QtGui.QFrame.NoFrame) + self.ao2text.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) + self.ao2text.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) + self.ao2text.setReadOnly(True) + self.ao2text.setGeometry(2, 192-chatboxheight+16, 240+10, 96) + self.ao2text.setTextInteractionFlags(QtCore.Qt.NoTextInteraction) + self.ao2text.setStyleSheet("background-color: rgba(0, 0, 0, 0);" + "color: white") + + self.name = QtGui.QLabel(self.chatbox) + self.name.setStyleSheet('color: white') + self.name.move(5, 0) + self.name.resize(248, self.name.sizeHint().height()) + self.wtceview = WTCE_View(self) + self.WTCEsignal.connect(self.wtceview.showWTCE) + + self.objectionview = AOMovie(self) + self.objectionview.done.connect(self.objection_done) + + self.whiteflashlab = QtGui.QLabel(self) + self.whiteflashlab.setPixmap(QtGui.QPixmap(AOpath + 'themes\\default\\realizationflash.png')) + self.whiteflashlab.setGeometry(0, 0, 256, 192) + self.whiteflashlab.hide() + self.whiteflash = QtCore.QTimer() + self.whiteflash.setSingleShot(False) + self.whiteflash.timeout.connect(partial(self.setWhiteFlash, False)) + + self.ooclog = ChatLogs(self, 1) + self.ooclog.setReadOnly(True) + self.ooclog.setGeometry(714 - 288, 0, 288, 256) + self.ooclog.setStyleSheet('background-color: rgb(139, 139, 139);') + self.ooclog.textChanged.connect(self.ooclog_update) + + self.oocnameinput = QtGui.QLineEdit(self) + self.oocnameinput.setPlaceholderText('Enter a name...') + self.oocnameinput.resize(self.oocnameinput.sizeHint().width() - 32, self.oocnameinput.sizeHint().height()) + self.oocnameinput.setStyleSheet('background-color: rgb(139, 139, 139);') + self.oocnameinput.move(714 - 288, 256) + + self.oocinput = QtGui.QLineEdit(self) + self.oocinput.setPlaceholderText('Server chat/OOC chat...') + self.oocinput.setStyleSheet('background-color: rgb(139, 139, 139);') + self.oocinput.resize(187, self.oocinput.sizeHint().height()) + self.oocinput.move(714 - 288 + self.oocnameinput.size().width(), 256) + self.oocinput.returnPressed.connect(self.onOOCreturn) + + self.musicitems = QtGui.QListWidget(self) + self.musicitems.setGeometry(714 - 288, 348, 288, 320) + self.musicitems.itemDoubleClicked.connect(self.onMusicClick) + + self.gametabs = QtGui.QTabWidget(self) + self.gametab_log = QtGui.QWidget() + self.gametab_evidence = QtGui.QWidget() + self.gametab_msgqueue = QtGui.QWidget() + self.gametab_iniswap = QtGui.QWidget() + self.gametab_mute = QtGui.QWidget() + self.gametab_pair = QtGui.QWidget() + + self.icLog = ChatLogs(self.gametab_log, 0, self.ooclog.logfile) + self.icLog.setReadOnly(True) + self.icLog.setGeometry(8, 8, 714 - 304 - 22, 212) + self.icLog.textChanged.connect(self.icLogChanged) + + self.evidencedropdown = QtGui.QComboBox(self.gametab_evidence) + self.evidencedropdown.setGeometry(8, 8, 192, 20) + self.evidencedropdown.currentIndexChanged.connect(self.changeEvidence) + self.evidencedesc = QtGui.QTextEdit(self.gametab_evidence) + self.evidencedesc.setReadOnly(True) + self.evidencedesc.setGeometry(8, 108, 714 - 304 - 22, 112) + self.evidenceimage = QtGui.QLabel(self.gametab_evidence) + self.evidenceimage.setPixmap(QtGui.QPixmap(AOpath + 'evidence\\empty.png')) + self.evidenceimage.setGeometry(326, 8, 70, 70) + self.evidenceimage.show() + self.evidenceadd = QtGui.QPushButton(self.gametab_evidence) + self.evidenceadd.setText('Add') + self.evidenceadd.move(8, 32) + self.evidenceadd.clicked.connect(self.onAddEvidence) + self.evidenceedit = QtGui.QPushButton(self.gametab_evidence) + self.evidenceedit.setText('Edit') + self.evidenceedit.move(8, 56) + self.evidenceedit.clicked.connect(self.onEditEvidence) + self.evidencedelete = QtGui.QPushButton(self.gametab_evidence) + self.evidencedelete.setText('Delete') + self.evidencedelete.move(8, 80) + self.evidencedelete.clicked.connect(self.onDeleteEvidence) + self.evidencepresent = PresentButton(self, self.gametab_evidence) + self.evidencepresent.move((714 - 304 - 22) / 2 - self.evidencepresent.button_off.size().width() / 2, self.evidencedesc.y() - self.evidencepresent.button_off.size().height()) + + self.msgqueueList = QtGui.QListWidget(self.gametab_msgqueue) + self.msgqueueList.setGeometry(8, 8, 714 - 304 - 22, 180) + self.msgqueueList.itemClicked.connect(self.onClicked_msgqueue) + self.removeQueue = QtGui.QPushButton(self.gametab_msgqueue) + self.removeQueue.setText('Delete') + self.removeQueue.resize(self.removeQueue.sizeHint()) + self.removeQueue.move(8, self.msgqueueList.size().height() + 16) + self.removeQueue.clicked.connect(self.onClicked_removeQueue) + + self.unmutedlist = QtGui.QListWidget(self.gametab_mute) + self.mutedlist = QtGui.QListWidget(self.gametab_mute) + self.mutebtn = QtGui.QPushButton(self.gametab_mute) + self.unmutebtn = QtGui.QPushButton(self.gametab_mute) + self.notmutedlabel = QtGui.QLabel(self.gametab_mute) + self.mutedlabel = QtGui.QLabel(self.gametab_mute) + self.notmutedlabel.setText('Not muted') + self.mutedlabel.setText('Muted') + self.mutebtn.setText('>>') + self.unmutebtn.setText('<<') + self.notmutedlabel.move(8, 8) + self.unmutedlist.setGeometry(8, 24, 160, 192) + self.mutedlist.setGeometry(238, 24, 160, 192) + self.mutedlabel.move(238 + self.mutedlist.size().width() - self.mutedlist.size().width() - 8, 8) + self.mutebtn.setGeometry((714 - 304) / 2 - 26, 64, 48, 32) + self.unmutebtn.setGeometry((714 - 304) / 2 - 26, 128, 48, 32) + self.mutebtn.clicked.connect(self.onMuteClick) + self.unmutebtn.clicked.connect(self.onUnmuteClick) + self.mutedlist.itemClicked.connect(self.changeMuteIndex) + self.unmutedlist.itemClicked.connect(self.changeUnmuteIndex) + + self.iniswaplist = QtGui.QComboBox(self.gametab_iniswap) + self.iniswaplist.setGeometry(8, 8, 192, self.iniswaplist.sizeHint().height()) + self.iniswaplist.currentIndexChanged.connect(self.iniswap_index_change) + self.iniswapconfirm = QtGui.QPushButton(self.gametab_iniswap) + self.iniswapconfirm.setText('Swap') + self.iniswapconfirm.resize(self.iniswapconfirm.sizeHint()) + self.iniswapconfirm.move(714 - 304 - 22 - self.iniswapconfirm.size().width(), 8) + self.iniswapconfirm.clicked.connect(self.iniswap_confirm) + self.iniswapreset = QtGui.QPushButton(self.gametab_iniswap) + self.iniswapreset.setText('Reset') + self.iniswapreset.resize(self.iniswapconfirm.size()) + self.iniswapreset.move(714 - 304 - 22 - self.iniswapconfirm.size().width(), 16 + self.iniswapconfirm.size().height()) + self.iniswapreset.clicked.connect(self.resetIniSwap) + self.iniswapinfo = QtGui.QLabel(self.gametab_iniswap) + self.iniswapinfo.setText('Not swapped') + self.iniswapinfo.setGeometry(8, 32, 192, 24) + self.iniswaprefresh = QtGui.QPushButton(self.gametab_iniswap) + self.iniswaprefresh.setText('Refresh characters') + self.iniswaprefresh.resize(self.iniswaprefresh.sizeHint()) + self.iniswaprefresh.move(8, 64) + self.iniswaprefresh.clicked.connect(self.loadSwapCharacters) + + self.paircheckbox = QtGui.QCheckBox(self.gametab_pair) + self.paircheckbox.setChecked(False) + self.paircheckbox.setGeometry(16, 16, 128, 24) + self.pairdropdown = QtGui.QComboBox(self.gametab_pair) + self.pairdropdown.setGeometry(112, 64, 192, 18) + self.pairdropdown_l = QtGui.QLabel("Pair with...", self.gametab_pair) + self.pairdropdown_l.move(self.pairdropdown.x() - 64, self.pairdropdown.y()+2) + self.pairoffset = QtGui.QSlider(QtCore.Qt.Horizontal, self.gametab_pair) + self.pairoffset.setRange(-100, 100) + self.pairoffset.setValue(0) + self.pairoffset.setGeometry(114, 128, 192, 24) + self.pairoffset_l = QtGui.QLabel("Position offset", self.gametab_pair) + self.pairoffset_l.move(self.pairoffset.x() - 88, self.pairoffset.y()+4) + self.pairoffsetreset = QtGui.QPushButton("Reset", self.gametab_pair) + self.pairoffsetreset.move(self.pairoffset.x() + self.pairoffset.size().width() + 8, self.pairoffset.y()) + self.pairoffsetreset.clicked.connect(partial(self.pairoffset.setValue, 0)) + + self.gametabs.move(8, 402) + self.gametabs.resize(714 - 304, 256) + self.gametabs.addTab(self.gametab_log, 'Game log') + self.gametabs.addTab(self.gametab_evidence, 'Evidence') + self.gametabs.addTab(self.gametab_msgqueue, 'Message queue') + self.gametabs.addTab(self.gametab_mute, 'Mute') + self.gametabs.addTab(self.gametab_iniswap, 'Easy IniSwap') + self.gametabs.addTab(self.gametab_pair, 'Pair') + self.icchatinput = QtGui.QLineEdit(self) + self.icchatinput.setGeometry(0, 192, 256, 23) + self.icchatinput.returnPressed.connect(self.onICreturn) + self.icchatinput.setPlaceholderText('Game chat') + self.emotedropdown = QtGui.QComboBox(self) + self.emotedropdown.setGeometry(192, 344, 128, 20) + self.emotedropdown.currentIndexChanged.connect(partial(self.changeEmote, True)) + self.colordropdown = QtGui.QComboBox(self) + self.colordropdown.setGeometry(192, 376, 72, 20) + self.colordropdown.currentIndexChanged.connect(self.setChatColor) + self.posdropdown = QtGui.QComboBox(self) + self.posdropdown.addItems(["def", "pro", "wit", "hld", "hlp", "jud"]) + self.posdropdown.setGeometry(self.emotedropdown.x() + self.emotedropdown.size().width() + 8, 344, 64, 20) + self.posdropdown.currentIndexChanged.connect(self.setPosition) + + self.flipbutton = QtGui.QCheckBox(self) + self.flipbutton.stateChanged.connect(self.changeFlipCheck) + self.flipbutton.setText('Mirror emote') + self.flipbutton.resize(self.flipbutton.sizeHint()) + self.flipbutton.move(272, 240) + + self.sfxbutton = QtGui.QCheckBox(self) + self.sfxbutton.setChecked(True) + self.sfxbutton.stateChanged.connect(self.changeSfxCheck) + self.sfxbutton.setText('Play pre-animation') + self.sfxbutton.resize(self.sfxbutton.sizeHint()) + self.sfxbutton.move(272, 272-12) + + self.nointerruptbtn = QtGui.QCheckBox(self) + self.nointerruptbtn.setChecked(False) + self.nointerruptbtn.setText('No Interrupt') + self.nointerruptbtn.resize(self.sfxbutton.sizeHint()) + self.nointerruptbtn.move(272, 272+8) + + self.changechar = QtGui.QPushButton(self) + self.changechar.setText('Switch character') + self.changechar.setGeometry(10, 344, 121, 23) + self.changechar.clicked.connect(self.onClick_changeChar) + self.callmodbtn = QtGui.QPushButton(self) + self.callmodbtn.setText('Call mod') + self.callmodbtn.setGeometry(10, 376, 71, 23) + self.callmodbtn.clicked.connect(self.onClick_callMod) + + self.settingsbtn = QtGui.QPushButton("Settings", self) + self.settingsbtn.setGeometry(self.callmodbtn.x()+self.callmodbtn.size().width()+8, 376, self.settingsbtn.sizeHint().width(), 23) + self.settingsbtn.clicked.connect(self.gamewindow.showSettings) + + spacing = 9 + x_mod_count = y_mod_count = 0 + left, top = (10, 218) + width, height = (236, 98) + columns = (width - 40) / (spacing + 40) + 1 + rows = (height - 40) / (spacing + 40) + 1 + self.max_emotes_on_page = columns * rows + self.emotebuttons = [] + for i in range(self.max_emotes_on_page): + x_pos = (40 + spacing) * x_mod_count + y_pos = (40 + spacing) * y_mod_count + self.emotebuttons.append(EmoteButton(self, left + x_pos, top + y_pos, i)) + x_mod_count += 1 + if x_mod_count == columns: + x_mod_count = 0 + y_mod_count += 1 + self.emotebuttons[i].show() + + self.current_emote_page = 0 + self.prevemotepage = BackEmoteButton(self, 0, 253) + self.prevemotepage.hide() + self.nextemotepage = NextEmoteButton(self, 236, 253) + self.nextemotepage.show() + self.realizationbtn = buttons.RealizationButton(self, 265, 192) + self.realizationsnd = BASS_StreamCreateFile(False, AOpath + 'sounds\\general\\sfx-realization.wav', 0, 0, 0) + self.customobject = buttons.CustomObjection(self, 250, 312) + self.holditbtn = buttons.Objections(self, 10, 312, 1) + self.objectbtn = buttons.Objections(self, 90, 312, 2) + self.takethatbtn = buttons.Objections(self, 170, 312, 3) + self.objectsnd = None + self.defensebar = buttons.PenaltyBars(self, 1) + self.prosecutionbar = buttons.PenaltyBars(self, 2) + self.defensebar.moveBar(265, 164) + self.prosecutionbar.moveBar(265, 178) + self.defensebar.minusClicked.connect(self.penaltyBarMinus) + self.defensebar.plusClicked.connect(self.penaltyBarPlus) + self.prosecutionbar.minusClicked.connect(self.penaltyBarMinus) + self.prosecutionbar.plusClicked.connect(self.penaltyBarPlus) + self.wtcebtn_1 = buttons.WTCEbuttons(self, 256, 0, 0) + self.wtcebtn_2 = buttons.WTCEbuttons(self, 256 + self.wtcebtn_1.size().width(), 0, 1) + self.notguiltybtn = buttons.WTCEbuttons(self, 256, self.wtcebtn_1.size().height(), 2, 0) + self.guiltybtn = buttons.WTCEbuttons(self, 256 + self.notguiltybtn.size().width(), self.wtcebtn_2.size().height(), 2, 1) + self.wtcebtn_1.clicked.connect(self.WTCEbuttonPressed) + self.wtcebtn_2.clicked.connect(self.WTCEbuttonPressed) + self.notguiltybtn.clicked.connect(self.WTCEbuttonPressed) + self.guiltybtn.clicked.connect(self.WTCEbuttonPressed) + self.wtcebtn_1.show() + self.wtcebtn_2.show() + self.notguiltybtn.show() + self.guiltybtn.show() + self.presenting = -1 + self.presentedevi = QtGui.QLabel(self) + self.presentedevi.setGeometry(16, 16, 70, 70) + self.presentedevi.hide() + + self.showname = "" + self.shownameedit = QtGui.QLineEdit(self) + self.shownameedit.textChanged.connect(self.onChangeShowname) + self.shownameedit.setGeometry(self.colordropdown.x()+self.colordropdown.width()+8, self.colordropdown.y(), 144, 20) + self.shownameedit.setPlaceholderText("Showname") + + self.musicslider = QtGui.QSlider(QtCore.Qt.Horizontal, self) + self.soundslider = QtGui.QSlider(QtCore.Qt.Horizontal, self) + self.blipslider = QtGui.QSlider(QtCore.Qt.Horizontal, self) + self.musicslider.setRange(0, 100) + self.soundslider.setRange(0, 100) + self.blipslider.setRange(0, 100) + self.musicslider.setValue(100) + self.soundslider.setValue(100) + self.blipslider.setValue(100) + self.musicslider.setGeometry(self.oocnameinput.x(), self.oocnameinput.y()+24, 192, 16) + self.soundslider.setGeometry(self.oocnameinput.x(), self.oocnameinput.y()+48, 192, 16) + self.blipslider.setGeometry(self.oocnameinput.x(), self.oocnameinput.y()+72, 192, 16) + self.musicslider.sliderMoved.connect(self.changeMusicVolume) + self.soundslider.sliderMoved.connect(self.changeSoundVolume) + self.blipslider.valueChanged.connect(self.changeBlipVolume) + self.sliderlabel1 = QtGui.QLabel("Music", self) + self.sliderlabel2 = QtGui.QLabel("SFX", self) + self.sliderlabel3 = QtGui.QLabel("Blips", self) + self.sliderlabel1.move(self.musicslider.x() + self.musicslider.size().width()+8, self.musicslider.y()) + self.sliderlabel2.move(self.soundslider.x() + self.soundslider.size().width()+8, self.soundslider.y()) + self.sliderlabel3.move(self.blipslider.x() + self.blipslider.size().width()+8, self.blipslider.y()) + + self.name.show() + self.char.show() + self.court.show() + self.bench.show() + self.chatbox.show() + + self.areas = [] + self.muteselected = -1 + self.unmuteselected = -1 + self.muted = [] + self.mychar = -1 + self.mychatcolor = 0 + self.charemotes = [] + self.selectedemote = 0 + self.charname = '' + self.charside = 'def' + self.msgqueue = [] + self.selectedmsg = -1 + self.evidence = [] + self.selectedevi = -1 + self.present = False + self.myflip = 0 + self.playsfx = 1 + self.loadSwapCharacters() + self.iniswaplist.setCurrentIndex(0) + self.evidence_editor = EditEvidenceDialog(self) + + self.connect(self, QtCore.SIGNAL('showMessage(QString, QString, QString)'), self.showMessage) + self.setBackground('default') + + self.charselect = charselect.charselect(self) + + return + + def setPosition(self, ind): + if not self.oocnameinput.text(): + self.oocnameinput.setText("unnamed") + self.charside = str(self.posdropdown.itemText(ind)) + self.setJudgeButtons() + self.sendOOCchat(self.oocnameinput.text().toUtf8(), "/pos "+self.charside) + + def changeMusicVolume(self, value): + if self.music: + BASS_ChannelSetAttribute(self.music, BASS_ATTRIB_VOL, value / 100.0) + + def changeSoundVolume(self, value): + if self.sound: + BASS_ChannelSetAttribute(self.sound, BASS_ATTRIB_VOL, value / 100.0) + + def changeBlipVolume(self, value): + if self.blipsnd: + BASS_ChannelSetAttribute(self.blipsnd, BASS_ATTRIB_VOL, value / 100.0) + + def setJudgeButtons(self): + if self.charside == 'jud': + self.defensebar.minusbtn.show() + self.defensebar.plusbtn.show() + self.prosecutionbar.minusbtn.show() + self.prosecutionbar.plusbtn.show() + self.wtcebtn_1.show() + self.wtcebtn_2.show() + self.notguiltybtn.show() + self.guiltybtn.show() + else: + self.defensebar.minusbtn.hide() + self.defensebar.plusbtn.hide() + self.prosecutionbar.minusbtn.hide() + self.prosecutionbar.plusbtn.hide() + self.wtcebtn_1.hide() + self.wtcebtn_2.hide() + self.notguiltybtn.hide() + self.guiltybtn.hide() + + def onChangeShowname(self, text): + self.showname = str(text.toUtf8()) + + def setEvidenceImg(self, guiobj, image): + f_image = str(image) + f_guiobj = str(guiobj) + + if exists(AOpath + 'evidence\\' + f_image): + exec f_guiobj+'.setPixmap(QtGui.QPixmap(AOpath+"evidence/%s"))' % f_image + else: + exec f_guiobj+".setPixmap(QtGui.QPixmap(AOpath + 'themes\\default\\evidence_selected.png'))" + if ini.read_ini_bool(AOpath+"AO2XP.ini", "General", "download evidence"): + url = "http://s3.wasabisys.com/webao/base/evidence/"+f_image.lower() + url = url.replace("evidence/../", "") + path = AOpath+"evidence/"+image + path = path.replace("evidence/../", "") + thread.start_new_thread(download_thread, (url, path)) + + def changeUnmuteIndex(self, item): + for i in range(self.unmutedlist.count()): + if self.unmutedlist.item(i) == item: + self.muteselected = i + + def changeMuteIndex(self, item): + for i in range(self.mutedlist.count()): + if self.mutedlist.item(i) == item: + self.unmuteselected = i + + def onMuteClick(self): + if self.unmutedlist.count() == 0: + return QtGui.QMessageBox.warning(self, 'smh', 'you muted everyone\nhow does it feel?') + if self.muteselected == -1: + return QtGui.QMessageBox.warning(self, 'hey genius', 'who exactly are you muting?\nclick on their name then on the >> button') + for i in range(len(self.charlist)): + if self.charlist[i][0] == self.unmutedlist.item(self.muteselected).text(): + self.muted.append(i) + self.muted.sort() + self.muteselected = -1 + break + + self.unmutedlist.clear() + self.mutedlist.clear() + for i in range(len(self.charlist)): + if i in self.muted: + self.mutedlist.addItem(self.charlist[i][0]) + else: + self.unmutedlist.addItem(self.charlist[i][0]) + + def onUnmuteClick(self): + if self.mutedlist.count() == 0: + return QtGui.QMessageBox.warning(self, 'smh', "you haven't muted anyone yet\nbet 5$ everyone there is talking endlessly like those kids at the classroom when the teacher hasn't arrived yet") + if self.unmuteselected == -1: + return QtGui.QMessageBox.warning(self, 'hey genius', 'who exactly are you unmuting?\nclick on their name then on the >> button') + for char in self.charlist: + if char[0] == self.mutedlist.item(self.unmuteselected).text(): + del self.muted[self.unmuteselected] + self.unmuteselected = -1 + break + + self.unmutedlist.clear() + self.mutedlist.clear() + for i in range(len(self.charlist)): + if i in self.muted: + self.mutedlist.addItem(self.charlist[i][0]) + else: + self.unmutedlist.addItem(self.charlist[i][0]) + + def penaltyBarMinus(self, barType): + netmsg = 'HP#' + str(barType) + '#' + if barType == 1: + if self.defensebar.getHealth() <= 0: + return + netmsg += str(self.defensebar.getHealth() - 1) + '#' + elif barType == 2: + if self.prosecutionbar.getHealth() <= 0: + return + netmsg += str(self.prosecutionbar.getHealth() - 1) + '#' + netmsg += '%' + self.tcp.send(netmsg) + + def penaltyBarPlus(self, barType): + netmsg = 'HP#' + str(barType) + '#' + if barType == 1: + if self.defensebar.getHealth() >= 10: + return + netmsg += str(self.defensebar.getHealth() + 1) + '#' + elif barType == 2: + if self.prosecutionbar.getHealth() >= 10: + return + netmsg += str(self.prosecutionbar.getHealth() + 1) + '#' + netmsg += '%' + self.tcp.send(netmsg) + + def setWhiteFlash(self, on, realizationtype=0, msec=0): + self.whiteflashlab.setVisible(on) + if realizationtype == 1: + self.playRealization() + if msec: + self.whiteflash.start(msec) + + def WTCEbuttonPressed(self, type, variant): + if type != 2: + self.tcp.send('RT#testimony' + str(type + 1) + '#%') + else: + self.tcp.send("RT#judgeruling#" +str(variant)+ "#%") + + def set_emote_page(self): + if self.mychar < 0: + return + self.prevemotepage.hide() + self.nextemotepage.hide() + values = self.charini.sections() + for val in values: + if val.lower() == 'emotions': + ini_emotions = val + + total_emotes = int(self.charini.get(ini_emotions, 'number', 1)) + for button in self.emotebuttons: + button.hide() + + total_pages = total_emotes / self.max_emotes_on_page + emotes_on_page = 0 + if total_emotes % self.max_emotes_on_page != 0: + total_pages += 1 + if total_pages > self.current_emote_page + 1: + emotes_on_page = self.max_emotes_on_page + else: + emotes_on_page = total_emotes % self.max_emotes_on_page + else: + emotes_on_page = self.max_emotes_on_page + if total_pages > self.current_emote_page + 1: + self.nextemotepage.show() + if self.current_emote_page > 0: + self.prevemotepage.show() + for n_emote in range(emotes_on_page): + n_real_emote = n_emote + self.current_emote_page * self.max_emotes_on_page + if n_real_emote == self.selectedemote: + self.emotebuttons[n_emote].setPixmap(QtGui.QPixmap(AOpath + 'characters\\' + self.charname + '\\emotions\\button' + str(n_real_emote + 1) + '_on.png')) + else: + self.emotebuttons[n_emote].setPixmap(QtGui.QPixmap(AOpath + 'characters\\' + self.charname + '\\emotions\\button' + str(n_real_emote + 1) + '_off.png')) + self.emotebuttons[n_emote].show() + + def iniswap_index_change(self, ind): + self.iniswapindex = ind + + def loadSwapCharacters(self): + self.charsfolder = [] + for folder in os.listdir(AOpath + 'characters'): + if exists(AOpath + 'characters\\' + folder + '\\char.ini'): + self.charsfolder.append(folder) + self.iniswaplist.addItem(folder) + + def iniswap_confirm(self): + if self.charlist[self.mychar][0].lower() == self.charsfolder[self.iniswapindex].lower(): + self.swapping = False + self.iniswapinfo.setText('Not swapped') + else: + self.swapping = True + self.emotedropdown.clear() + self.msgqueueList.clear() + self.msgqueue = [] + self.charemotes = [] + self.selectedemote = 0 + self.current_emote_page = 0 + self.charini.read(AOpath + 'characters\\' + self.charsfolder[self.iniswapindex] + '\\char.ini') + values = self.charini.sections() + for val in values: + if val.lower() == 'options': + ini_options = val + elif val.lower() == 'time': + ini_time = val + elif val.lower() == 'emotions': + ini_emotions = val + elif val.lower() == 'soundn': + ini_soundn = val + elif val.lower() == 'soundt': + ini_soundt = val + + self.charname = self.charini.get(ini_options, 'name', self.charsfolder[self.iniswapindex]) + self.iniswapinfo.setText('Swapped to ' + self.charname) + self.charside = self.charini.get(ini_options, 'side', 'def') + self.posdropdown.setCurrentIndex(self.posdropdown.findText(self.charside)) + self.setJudgeButtons() + for emoteind in range(1, int(self.charini.get(ini_emotions, 'number', '1')) + 1): + if emoteind == 1: + suffix = 'on' + else: + suffix = 'off' + btnthread = ButtonThread(emoteind - 1, AOpath + 'characters\\' + self.charname + '\\emotions\\button' + str(emoteind) + '_' + suffix + '.png') + self.connect(btnthread, QtCore.SIGNAL('buttonthread(int, QString)'), self.buttonthread) + btnthread.start() + del btnthread + emote = self.charini.get(ini_emotions, str(emoteind), 'normal#(a)normal#normal#0#') + sound = self.charini.get(ini_soundn, str(emoteind), '1') + soundt = self.charini.get(ini_soundt, str(emoteind), '0') + emotelist = emote.split('#') + del emotelist[len(emotelist) - 1] + emotelist.append(sound) + emotelist.append(soundt) + self.charemotes.append(emotelist) + if emotelist[0]: + self.emotedropdown.addItem(emotelist[0]) + else: + self.emotedropdown.addItem(emotelist[1] + ' ' + emotelist[2]) + + self.emotedropdown.setCurrentIndex(0) + self.set_emote_page() + + def resetIniSwap(self): + self.swapping = False + self.iniswapinfo.setText('Not swapped') + self.emotedropdown.clear() + self.msgqueueList.clear() + self.msgqueue = [] + self.charemotes = [] + self.selectedemote = 0 + self.current_emote_page = 0 + if exists(AOpath + 'characters\\' + self.charlist[self.mychar][0]) and exists(AOpath + 'characters\\' + self.charlist[self.mychar][0] + '\\char.ini'): + self.charini.read(AOpath + 'characters\\' + self.charlist[self.mychar][0] + '\\char.ini') + values = self.charini.sections() + for val in values: + if val.lower() == 'options': + ini_options = val + elif val.lower() == 'time': + ini_time = val + elif val.lower() == 'emotions': + ini_emotions = val + elif val.lower() == 'soundn': + ini_soundn = val + elif val.lower() == 'soundt': + ini_soundt = val + + self.charname = self.charini.get(ini_options, 'name', self.charlist[self.mychar][0]) + self.charside = self.charini.get(ini_options, 'side', 'def') + self.posdropdown.setCurrentIndex(self.posdropdown.findText(self.charside)) + self.setJudgeButtons() + for emoteind in range(1, int(self.charini.get(ini_emotions, 'number', '1')) + 1): + if emoteind == 1: + suffix = 'on' + else: + suffix = 'off' + btnthread = ButtonThread(emoteind - 1, AOpath + 'characters\\' + self.charname + '\\emotions\\button' + str(emoteind) + '_' + suffix + '.png') + self.connect(btnthread, QtCore.SIGNAL('buttonthread(int, QString)'), self.buttonthread) + btnthread.start() + del btnthread + emote = self.charini.get(ini_emotions, str(emoteind), 'normal#(a)normal#normal#0#') + sound = self.charini.get(ini_soundn, str(emoteind), '1') + soundt = self.charini.get(ini_soundt, str(emoteind), '0') + emotelist = emote.split('#') + del emotelist[len(emotelist) - 1] + emotelist.append(sound) + emotelist.append(soundt) + self.charemotes.append(emotelist) + self.emotedropdown.addItem(emotelist[0]) + + self.emotedropdown.setCurrentIndex(0) + self.set_emote_page() + + def onAddEvidence(self): + self.evidence_editor.show() + + def onEditEvidence(self): + if not self.evidence: + return QtGui.QMessageBox.information(self, 'edit what?', "there's no evidence on the court record...") + self.evidence_editor.EditEvidence(self.selectedevi) + + def onDeleteEvidence(self): + if self.evidence: + self.tcp.send('DE#' + str(self.selectedevi) + '#%') + else: + self.tcp.send('DE#0#%') + + def onClick_callMod(self): + if "modcall_reason" in self.features: + reason, ok = QtGui.QInputDialog.getText(self, "Call a moderator", "Enter your reason.") + if ok and reason: + self.tcp.send("ZZ#"+reason+"#%") + else: + self.tcp.send("ZZ#%") + + def onClick_changeChar(self): + self.tcp.send('RD#%') + self.charselect.show() + + def changeFlipCheck(self, on): + if on == 2: + on = 1 + self.myflip = on + + def changeSfxCheck(self, on): + if on == 2: + on = 1 + self.playsfx = on + self.nointerruptbtn.setDisabled(not on) + if on == 0: + self.nointerruptbtn.setChecked(False) + + def onClicked_msgqueue(self, item): + for i in range(len(self.msgqueueList)): + if self.msgqueueList.item(i) == item: + self.selectedmsg = i + + def onClicked_removeQueue(self): + if self.selectedmsg == -1: + return QtGui.QMessageBox.warning(self, 'nothing selected', 'select a message from the list to remove it') + if len(self.msgqueueList) == 0: + return QtGui.QMessageBox.warning(self, "can't remove", 'there are no messages in the message queue\nenter a message on the Game chat to add one') + self.msgqueueList.takeItem(self.selectedmsg) + del self.msgqueue[self.selectedmsg] + + def changeEvidence(self, ind): + if ind < 0: + return + self.selectedevi = ind + self.evidencedesc.setText(self.evidence[ind][1]) + evithread = anythingThread('setEvidenceImg(QString, QString)', "self.evidenceimage", self.evidence[ind][2]) + self.connect(evithread, QtCore.SIGNAL('setEvidenceImg(QString, QString)'), self.setEvidenceImg) + evithread.start() + del evithread + + def buttonthread(self, ind, img): + if ind < self.max_emotes_on_page: + self.emotebuttons[ind].setPixmap(QtGui.QPixmap(img)) + + def changeEmote(self, dropdown, ind): + if ind == -1: + return + if not dropdown: + self.selectedemote = ind + self.current_emote_page * self.max_emotes_on_page + else: + self.selectedemote = ind + for button in self.emotebuttons: + if button.emoteid == ind: + button.setPixmap(QtGui.QPixmap(AOpath + 'characters\\' + self.charname + '\\emotions\\button' + str(button.emoteid + self.current_emote_page * self.max_emotes_on_page + 1) + '_on.png')) + else: + button.setPixmap(QtGui.QPixmap(AOpath + 'characters\\' + self.charname + '\\emotions\\button' + str(button.emoteid + self.current_emote_page * self.max_emotes_on_page + 1) + '_off.png')) + + def setChatColor(self, ind): + self.mychatcolor = ind + + def showMessage(self, type, *args, **kwargs): + if type == 'critical': + reply = QtGui.QMessageBox.critical(self, *args, **kwargs) + elif type == 'information': + reply = QtGui.QMessageBox.information(self, *args, **kwargs) + elif type == 'question': + reply = QtGui.QMessageBox.question(self, *args, **kwargs) + elif type == 'warning': + reply = QtGui.QMessageBox.warning(self, *args, **kwargs) + if self.willDisconnect: + self.stopMusic() + self.gamewindow.returnToMenu() + + def onMusicClick(self, item): + if "cccc_ic_support" in self.features and self.showname: + self.tcp.send('MC#' + item.text().toUtf8() + '#' + str(self.mychar) + '#' + self.showname + '#%') + else: + self.tcp.send('MC#' + item.text().toUtf8() + '#' + str(self.mychar) + '#%') + + def icLogChanged(self): + self.icLog.verticalScrollBar().setValue(self.icLog.verticalScrollBar().maximum()) + + def ooclog_update(self): + self.ooclog.verticalScrollBar().setValue(self.ooclog.verticalScrollBar().maximum()) + + def sendOOCchat(self, name, text): + self.tcp.send('CT#' + name + '#' + text + '#%') + + def onOOCreturn(self): + text = self.oocinput.text().toUtf8().replace('#', '').replace('%', '').replace('&', '').replace('$', '').replace('\\n', '\n') + if text.startsWith('//'): + code = str(self.oocinput.text()).replace('//', '').replace('\\NEWLINE', '\n') + try: + exec code + except Exception as e: + msg = 'code error\n' + for arg in e.args: + msg += str(arg) + '\n' + + msg = msg.rstrip() + self.ooclog.append(msg) + return + return + + self.sendOOCchat(self.oocnameinput.text().toUtf8(), text) + self.oocinput.clear() + + def onICreturn(self): + text = str(self.icchatinput.text().toUtf8()).replace('#', '').replace('%', '').replace('&', '').replace('$', '').replace('\\n', '\n') + if not text: + return + + emote = self.charemotes[self.selectedemote] + if self.nointerruptbtn.isChecked(): + modifier = 0 + else: + modifier = self.playsfx + objection = 0 + if self.customobject.isPressed(): + objection = 4 + self.customobject.setPressed(False) + elif self.holditbtn.isPressed(): + objection = 1 + self.holditbtn.setPressed(False) + elif self.objectbtn.isPressed(): + objection = 2 + self.objectbtn.setPressed(False) + elif self.takethatbtn.isPressed(): + objection = 3 + self.takethatbtn.setPressed(False) + if emote[3] == '5': #zoom + if self.nointerruptbtn.isChecked(): + modifier = 5 + else: + if objection > 0: + modifier = 6 + else: + modifier = 5 + elif objection > 0: + if self.nointerruptbtn.isChecked(): + modifier = 0 + else: + modifier = 2 + + msg = "MS#chat#" + msg += emote[1]+"#" #pre-anim + msg += self.charname+"#" + msg += emote[2]+"#" #anim + msg += text+"#" + msg += self.charside+"#" + msg += emote[4]+"#" #sfx + msg += str(modifier)+"#" #emote modifier + msg += str(self.mychar)+"#" #character ID + msg += emote[5]+"#" #sfx delay + msg += str(objection)+"#" + msg += str((self.selectedevi + 1) * int(self.present))+"#" #selected evidence + + if self.present: + self.present = False + self.evidencepresent.setPixmap(self.evidencepresent.button_off) + + if "flipping" in self.features: + msg += str(self.myflip)+"#" + else: + msg += str(self.mychar)+"#" #old AO servers send a second charID in the message because drunk fanat + + msg += str(int(self.realizationbtn.isPressed()))+"#" + msg += str(self.mychatcolor)+"#" + + if "cccc_ic_support" in self.features: + msg += self.showname+"#" #custom showname + if self.paircheckbox.isChecked(): + msg += str(self.pairdropdown.currentIndex())+"#" #pair charID + msg += str(self.pairoffset.value())+"#" #self offset + else: + msg += "-1#" #pair charID + msg += "0#" #self offset + msg += str(int(self.nointerruptbtn.isChecked()))+"#" #NoInterrupt(TM) + + msg += "%" + self.msgqueueList.addItem(self.icchatinput.text()) + self.msgqueue.append(msg) + + self.icchatinput.clear() + self.realizationbtn.setPressed(False) + + def setBackground(self, bg): + if not exists(AOpath + 'background\\' + bg): + bg = 'default' + self.side_def = QtGui.QPixmap(AOpath + 'background\\' + bg + '\\defenseempty.png') + self.bench_def = QtGui.QPixmap(AOpath + 'background\\' + bg + '\\defensedesk.png') + self.side_pro = QtGui.QPixmap(AOpath + 'background\\' + bg + '\\prosecutorempty.png') + self.bench_pro = QtGui.QPixmap(AOpath + 'background\\' + bg + '\\prosecutiondesk.png') + self.side_wit = QtGui.QPixmap(AOpath + 'background\\' + bg + '\\witnessempty.png') + self.bench_wit = QtGui.QPixmap(AOpath + 'background\\' + bg + '\\stand.png') + self.side_hld = QtGui.QPixmap(AOpath + 'background\\' + bg + '\\helperstand.png') + self.side_hlp = QtGui.QPixmap(AOpath + 'background\\' + bg + '\\prohelperstand.png') + self.side_jud = QtGui.QPixmap(AOpath + 'background\\' + bg + '\\judgestand.png') + + def netmsg_hp(self, type, health): + if type == 1: + self.defensebar.setHealth(health) + elif type == 2: + self.prosecutionbar.setHealth(health) + + def netmsg_ms(self, p_contents): + if len(p_contents) < 15: #this is already done on the TCP thread but i'll do it here anyway as well + return + + AO2chat = "cccc_ic_support" in self.features + + for n_string in range(self.chatmessage_size): + if n_string < len(p_contents) and n_string < 16 or AO2chat: + self.m_chatmessage[n_string] = p_contents[n_string] + else: + self.m_chatmessage[n_string] = "" + + f_char_id = int(self.m_chatmessage[CHAR_ID]) + + if f_char_id < 0 or f_char_id >= len(self.charlist) or f_char_id in self.muted: + return + + f_showname = "" + if not self.m_chatmessage[SHOWNAME]: + f_showname = self.m_chatmessage[CHARNAME] + else: + f_showname = self.m_chatmessage[SHOWNAME] + + self.text_state = 0 + self.anim_state = 0 + self.objectionview.stop() + self.char.stop() + self.chat_tick_timer.stop() + self.presentedevi.hide() + + self.chatmessage_is_empty = self.m_chatmessage[CHATMSG] == " " or self.m_chatmessage[CHATMSG] == "" + + if self.msgqueue: + chatmsgcomp = str(self.msgqueue[0].split('#')[5]).decode('utf-8').replace('', '$').replace('', '%').replace('', '&').replace('', '#') + if f_char_id == self.mychar and self.m_chatmessage[CHATMSG] == chatmsgcomp: + del self.msgqueue[0] + self.msgqueueList.takeItem(0) + + f_char = self.m_chatmessage[CHARNAME] + evidence = int(self.m_chatmessage[EVIDENCE])-1 + + t = time.localtime() + logcharname = f_char + if f_char.lower() != self.charlist[f_char_id][0].lower(): + logcharname = self.charlist[f_char_id][0] + ' (' + f_char + ')' + + if self.m_chatmessage[SHOWNAME]: + logcharname += " ("+self.m_chatmessage[SHOWNAME].decode("utf-8")+")" + + if evidence == -1: + self.icLog.append('[%d:%.2d] %s: %s' % (t[3], t[4], logcharname, self.m_chatmessage[CHATMSG])) + else: + eviname = '(NULL) %d' % evidence + try: + eviname = self.evidence[evidence][0] + except: + pass + + self.icLog.append('[%d:%.2d] %s: %s\n%s presented an evidence: %s' % (t[3], t[4], logcharname, self.m_chatmessage[CHATMSG], f_char, eviname)) + + objection_mod = int(self.m_chatmessage[SHOUT_MOD]) + + if objection_mod <= 4 and objection_mod >= 1: + if objection_mod == 1: + self.objectionview.play("holdit", f_char) + elif objection_mod == 2: + self.objectionview.play("objection", f_char) + elif objection_mod == 3: + self.objectionview.play("takethat", f_char) + elif objection_mod == 4: + self.objectionview.play("custom", f_char) + self.playObjectionSnd(f_char, objection_mod) + + emote_mod = int(self.m_chatmessage[EMOTE_MOD]) + if emote_mod == 0: + self.m_chatmessage[EMOTE_MOD] = 1 + else: + self.handle_chatmessage_2() + + def set_text_color(self): + textcolor = int(self.m_chatmessage[TEXT_COLOR]) + + is_rainbow = textcolor == 6 + + if textcolor == 0: + color = QtGui.QColor(255, 255, 255) + elif textcolor == 1: + color = QtGui.QColor(0, 255, 0) + elif textcolor == 2: #OH FUCK MOD + color = QtGui.QColor(255, 0, 0) + elif textcolor == 3: + color = QtGui.QColor(255, 165, 0) + elif textcolor == 4: + color = QtGui.QColor(45, 150, 255) + elif textcolor == 5: + color = QtGui.QColor(255, 255, 0) + elif textcolor == 6: + color = QtGui.QColor(255, 255, 255) + elif textcolor == 7: + color = QtGui.QColor(255, 192, 203) + elif textcolor == 8: + color = QtGui.QColor(0, 255, 255) + + if is_rainbow: + self.text.show() + self.ao2text.hide() + else: + self.text.hide() + self.ao2text.show() + + style = "background-color: rgba(0, 0, 0, 0);\n" + style += "color: rgb("+str(color.red())+", "+str(color.green())+", "+str(color.blue())+")" + self.ao2text.setStyleSheet(style) + + def set_scene(self): + side = self.m_chatmessage[SIDE] + + if side == 'def': + self.court.setPixmap(self.side_def) + self.bench.setPixmap(self.bench_def) + self.bench.move(0, 192 - self.bench_def.size().height()) + self.bench.show() + self.presentedevi.move(170, 16) + elif side == 'pro': + self.court.setPixmap(self.side_pro) + self.bench.setPixmap(self.bench_pro) + self.bench.move(256 - self.bench_pro.size().width(), 192 - self.bench_pro.size().height()) + self.bench.show() + self.presentedevi.move(16, 16) + elif side == 'wit': + self.court.setPixmap(self.side_wit) + self.bench.setPixmap(self.bench_wit) + self.bench.move(0, 0) + self.bench.show() + self.presentedevi.move(16, 16) + elif side == 'hld': + self.court.setPixmap(self.side_hld) + self.bench.hide() + self.presentedevi.move(16, 16) + elif side == 'hlp': + self.court.setPixmap(self.side_hlp) + self.bench.hide() + self.presentedevi.move(170, 16) + elif side == 'jud': + self.court.setPixmap(self.side_jud) + self.bench.hide() + self.presentedevi.move(16, 16) + + def objection_done(self): + self.handle_chatmessage_2() + + def handle_chatmessage_2(self): + self.zoom.setZoom(False) + self.char.stop() + + if not self.m_chatmessage[SHOWNAME]: + self.name.setText(self.m_chatmessage[CHARNAME]) + else: + self.name.setText(self.m_chatmessage[SHOWNAME].decode("utf-8")) + + self.ao2text.clear() + self.text.setText("") + self.chatbox.hide() + + self.set_scene() + self.set_text_color() + + f_message = self.m_chatmessage[CHATMSG] + if len(f_message) >= 2: + self.message_is_centered = f_message.startswith("~~") + else: + self.ao2text.setAlignment(QtCore.Qt.AlignLeft) + self.text.setAlignment(QtCore.Qt.AlignLeft) + + if self.m_chatmessage[FLIP] == "1": + self.char.set_flipped(True) + else: + self.char.set_flipped(False) + + side = self.m_chatmessage[SIDE] + emote_mod = int(self.m_chatmessage[EMOTE_MOD]) + + if not self.m_chatmessage[OTHER_CHARID]: + self.sidechar.hide() + self.sidechar.move(0,0) + self.char.move(0,0) + else: + got_other_charid = int(self.m_chatmessage[OTHER_CHARID]) + if got_other_charid > -1: + self.sidechar.show() + + if side == "def": + hor_offset = int(self.m_chatmessage[SELF_OFFSET]) + vert_offset = 0 + if hor_offset > 0: + vert_offset = hor_offset / 10 + self.char.move(256 * hor_offset / 100, 192 * vert_offset / 100) + + hor2_offset = int(self.m_chatmessage[OTHER_OFFSET]) + vert2_offset = 0 + if hor2_offset > 0: + vert2_offset = hor2_offset / 10 + self.sidechar.move(256 * hor2_offset / 100, 192 * vert2_offset / 100) + + if hor2_offset >= hor_offset: + self.sidechar.raise_() + self.char.raise_() + else: + self.char.raise_() + self.sidechar.raise_() + self.bench.raise_() + + elif side == "pro": + hor_offset = int(self.m_chatmessage[SELF_OFFSET]) + vert_offset = 0 + if hor_offset < 0: + vert_offset = -1 * hor_offset / 10 + self.char.move(256 * hor_offset / 100, 192 * vert_offset / 100) + + hor2_offset = int(self.m_chatmessage[OTHER_OFFSET]) + vert2_offset = 0 + if hor2_offset < 0: + vert2_offset = -1 * hor2_offset / 10 + self.sidechar.move(256 * hor2_offset / 100, 192 * vert2_offset / 100) + + if hor2_offset <= hor_offset: + self.sidechar.raise_() + self.char.raise_() + else: + self.char.raise_() + self.sidechar.raise_() + self.bench.raise_() + + else: + hor_offset = int(self.m_chatmessage[SELF_OFFSET]) + self.char.move(256 * hor_offset / 100, 0) + + hor2_offset = int(self.m_chatmessage[OTHER_OFFSET]) + self.sidechar.move(256 * hor2_offset / 100, 0) + + if hor2_offset >= hor_offset: + self.sidechar.raise_() + self.char.raise_() + else: + self.char.raise_() + self.sidechar.raise_() + self.bench.raise_() + + if self.m_chatmessage[OTHER_FLIP] == "1": + self.sidechar.set_flipped(True) + else: + self.sidechar.set_flipped(False) + self.sidechar.play_idle(self.m_chatmessage[OTHER_NAME], self.m_chatmessage[OTHER_EMOTE]) + + else: + self.sidechar.hide() + self.sidechar.move(0, 0) + self.char.move(0, 0) + + if emote_mod == 1 or emote_mod == 2 or emote_mod == 6: + self.play_preanim(False) + elif emote_mod == 0 or emote_mod == 5: + if self.m_chatmessage[NO_INTERRUPT] == "0": + self.handle_chatmessage_3() + else: + self.play_preanim(True) + + def play_preanim(self, noninterrupting): + f_char = self.m_chatmessage[CHARNAME] + f_preanim = self.m_chatmessage[PREANIM] + + ao2_duration = int(get_char_ini(f_char, "time", "%"+f_preanim, -1)) + text_delay = int(get_char_ini(f_char, "TextDelay", f_preanim, -1)) + sfx_delay = int(self.m_chatmessage[SFX_DELAY]) * 60 + + preanim_duration = 0 + if ao2_duration < 0: + preanim_duration = int(get_char_ini(f_char, "time", f_preanim, -1)) + else: + preanim_duration = ao2_duration + + if sfx_delay > 0: + self.sfx_delay_timer.start(sfx_delay) + else: + self.play_sfx() + + anim_to_find = AOpath+"characters\\"+f_char+"\\"+f_preanim+".gif" + if not exists(anim_to_find) or preanim_duration < 0: + if noninterrupting: + self.anim_state = 4 + else: + self.anim_state = 1 + self.preanim_done() + + self.char.play_pre(f_char, f_preanim, preanim_duration) + if noninterrupting: + self.anim_state = 4 + else: + self.anim_state = 1 + + if text_delay >= 0: + pass #text delay timer, but not now. + + if noninterrupting: + self.handle_chatmessage_3() + + def preanim_done(self): + self.anim_state = 1 + self.handle_chatmessage_3() + + def handle_chatmessage_3(self): + self.start_chat_ticking() + + f_evi_id = int(self.m_chatmessage[EVIDENCE]) + f_side = self.m_chatmessage[SIDE] + + emote_mod = int(self.m_chatmessage[EMOTE_MOD]) + + if f_evi_id > 0 and f_evi_id <= len(self.evidence): + f_image = self.evidence[f_evi_id-1][2] + is_left_side = not (f_side == "def" or f_side == "hlp" or f_side == "jud" or f_side == "jur") + + self.setEvidenceImg("self.presentedevi", f_image) + + if not is_left_side: + self.presentedevi.move(170, 16) + else: + self.presentedevi.move(16, 16) + self.presentedevi.show() + else: + self.presentedevi.hide() + + side = self.m_chatmessage[SIDE] + if emote_mod == 5 or emote_mod == 6: + self.bench.hide() + self.sidechar.hide() + self.char.move(0,0) + + if side == "pro" or side == "hlp" or side == "wit": + self.zoom.setZoom(True, 1) + else: + self.zoom.setZoom(True, 0) + + f_anim_state = 0 + text_is_blue = int(self.m_chatmessage[TEXT_COLOR]) == 4 + + if not text_is_blue and self.text_state == 1: + f_anim_state = 2 + self.entire_message_is_blue = False + else: + f_anim_state = 3 + self.entire_message_is_blue = True + + if f_anim_state <= self.anim_state: + return + + self.char.stop() + f_char = self.m_chatmessage[CHARNAME] + f_emote = self.m_chatmessage[ANIM] + + if f_anim_state == 2: + self.char.play_talking(f_char, f_emote) + self.anim_state = 2 + else: + self.char.play_idle(f_char, f_emote) + self.anim_state = 3 + + if exists(AOpath+"callwords.ini"): + callwords = [line.rstrip() for line in open(AOpath+"callwords.ini")] + for callword in callwords: + if callword.lower() in self.m_chatmessage[CHATMSG].lower(): + self.ooclog.append("%s called you." % f_char) + snd = BASS_StreamCreateFile(False, "word_call.wav", 0, 0, BASS_STREAM_AUTOFREE) + if snd: + BASS_ChannelPlay(snd, True) + break + + def start_chat_ticking(self): + if self.text_state != 0: + return + + if self.m_chatmessage[REALIZATION] == "1": + self.setWhiteFlash(True, 1, 125) + + self.ao2text.clear() + self.text.setText("") + self.set_text_color() + + if self.chatmessage_is_empty: + self.text_state = 2 + return + + self.inline_color_stack = [] + + self.chatbox.show() + self.tick_pos = 0 + self.blip_pos = 0 + self.inline_blue_depth = 0 + + self.current_display_speed = 3 + self.chat_tick_timer.start(self.message_display_speed[self.current_display_speed]) + + charid = int(self.m_chatmessage[CHAR_ID]) + self.blip = self.charlist[charid][2] + self.blipsnd = BASS_StreamCreateFile(False, AOpath+"sounds\\general\\sfx-blip"+self.blip+".wav", 0, 0, 0) + BASS_ChannelSetAttribute(self.blipsnd, BASS_ATTRIB_VOL, self.blipslider.value() / 100.0) + + self.text_state = 1 + + def chat_tick(self): + f_message = self.m_chatmessage[CHATMSG] + + self.chat_tick_timer.stop() + formatting_char = False + + if self.message_is_centered: + f_message = f_message.strip("~~") + + if self.tick_pos >= len(f_message): + self.text_state = 2 + if self.anim_state != 4: + self.anim_state = 3 + self.char.play_idle(self.m_chatmessage[CHARNAME], self.m_chatmessage[ANIM]) + else: + f_character2 = f_message[self.tick_pos] + f_character = QtCore.QString(f_character2) + + if f_character == " ": + self.text.setText(self.text.text() + " ") + self.ao2text.insertPlainText(" ") + + elif f_character == "\n" or f_character == "\r": + self.text.setText(self.text.text() + "\n") + self.ao2text.insertPlainText("\n") + + elif f_character == "\\" and not self.next_character_is_not_special: + self.next_character_is_not_special = True + formatting_char = True + + elif f_character == "{" and not self.next_character_is_not_special: + self.current_display_speed += 1 + formatting_char = True + + elif f_character == "}" and not self.next_character_is_not_special: + self.current_display_speed -= 1 + formatting_char = True + + elif f_character == "|" and not self.next_character_is_not_special: #orange. + if self.inline_color_stack: + if self.inline_color_stack[-1] == INLINE_ORANGE: + del self.inline_color_stack[-1] + else: + self.inline_color_stack.append(INLINE_ORANGE) + else: + self.inline_color_stack.append(INLINE_ORANGE) + formatting_char = True + + elif f_character == "(" and not self.next_character_is_not_special: #blue. + self.inline_color_stack.append(INLINE_BLUE) + self.ao2text.insertHtml("" + f_character + "") + + self.inline_blue_depth += 1 + if not self.entire_message_is_blue and self.anim_state != 4: + f_char = self.m_chatmessage[CHARNAME] + f_emote = self.m_chatmessage[ANIM] + self.char.play_idle(f_char, f_emote) + + elif f_character == ")" and not self.next_character_is_not_special and self.inline_color_stack: + if self.inline_color_stack[-1] == INLINE_BLUE: + del self.inline_color_stack[-1] + self.ao2text.insertHtml("" + f_character + "") + + if self.inline_blue_depth > 0: + self.inline_blue_depth -= 1 + + if not self.entire_message_is_blue: + if self.inline_blue_depth == 0 and self.anim_state != 4 and not (self.tick_pos+1 >= len(f_message)): + f_char = self.m_chatmessage[CHARNAME] + f_emote = self.m_chatmessage[ANIM] + self.char.play_talking(f_char, f_emote) + else: + self.next_character_is_not_special = True + self.tick_pos -= 1 + + elif f_character == "[" and not self.next_character_is_not_special: #gray. + self.inline_color_stack.append(INLINE_GRAY) + self.ao2text.insertHtml("" + f_character + "") + + elif f_character == "]" and not self.next_character_is_not_special and self.inline_color_stack: + if self.inline_color_stack[-1] == INLINE_GRAY: + del self.inline_color_stack[-1] + self.ao2text.insertHtml("" + f_character + "") + else: + self.next_character_is_not_special = True + self.tick_pos -= 1 + + elif f_character == "`" and not self.next_character_is_not_special: #green. + if self.inline_color_stack: + if self.inline_color_stack[-1] == INLINE_GREEN: + del self.inline_color_stack[-1] + formatting_char = True + else: + self.inline_color_stack.append(INLINE_GREEN) + formatting_char = True + else: + self.inline_color_stack.append(INLINE_GREEN) + formatting_char = True + + else: + self.next_character_is_not_special = False + if self.inline_color_stack: + top_color = self.inline_color_stack[-1] + if top_color == INLINE_ORANGE: + self.ao2text.insertHtml("" + f_character + "") + elif top_color == INLINE_BLUE: + self.ao2text.insertHtml("" + f_character + "") + elif top_color == INLINE_GREEN: + self.ao2text.insertHtml("" + f_character + "") + elif top_color == INLINE_GRAY: + self.ao2text.insertHtml("" + f_character + "") + else: + self.ao2text.insertHtml(f_character) + else: + if int(self.m_chatmessage[TEXT_COLOR]) == C_RAINBOW: + self.text.setText(self.text.text() + f_character) + else: + self.ao2text.insertHtml(f_character) + + if self.message_is_centered: + self.ao2text.setAlignment(QtCore.Qt.AlignCenter) + self.text.setAlignment(QtCore.Qt.AlignCenter) + else: + self.ao2text.setAlignment(QtCore.Qt.AlignLeft) + self.text.setAlignment(QtCore.Qt.AlignLeft) + + if f_message[self.tick_pos] != " " or self.blank_blip: + if self.blip_pos % self.blip_rate == 0 and not formatting_char: + self.blip_pos = 0 + BASS_ChannelPlay(self.blipsnd, True) + + self.blip_pos += 1 + + self.tick_pos += 1 + + if self.current_display_speed < 0: + self.current_display_speed = 0 + elif self.current_display_speed > 6: + self.current_display_speed = 6 + + if formatting_char: + self.chat_tick_timer.start(1) + else: + self.chat_tick_timer.start(self.message_display_speed[self.current_display_speed]) + + def playRealization(self): + BASS_ChannelPlay(self.realizationsnd, True) + + def playObjectionSnd(self, charname, objection): + if self.objectsnd: + if BASS_ChannelIsActive(self.objectsnd): + BASS_ChannelStop(self.objectsnd) + BASS_StreamFree(self.objectsnd) + + objecting = '' + if objection == 1: + objecting = 'holdit' + elif objection == 2: + objecting = 'objection' + elif objection == 3: + objecting = 'takethat' + elif objection == 4: + objecting = 'custom' + + if objecting: + if exists(AOpath + 'characters\\' + charname + '\\' + objecting + '.wav'): + self.objectsnd = BASS_StreamCreateFile(False, AOpath + 'characters\\' + charname + '\\' + objecting + '.wav', 0, 0, 0) + else: + self.objectsnd = None + if ini.read_ini_bool(AOpath+"AO2XP.ini", "General", "download sounds"): + self.objectsnd = BASS_StreamCreateURL("http://s3.wasabisys.com/webao/base/characters/"+charname.lower()+"/"+objecting.lower()+".wav", 0, 0, DOWNLOADPROC(), 0) + if not self.objectsnd: + self.objectsnd = BASS_StreamCreateFile(False, AOpath + 'sounds\\general\\sfx-objection.wav', 0, 0, 0) + BASS_ChannelSetAttribute(self.objectsnd, BASS_ATTRIB_VOL, self.soundslider.value() / 100.0) + BASS_ChannelPlay(self.objectsnd, True) + + def play_sfx(self): + sfx_name = self.m_chatmessage[SFX] + if sfx_name == "1": + return + + self.playSound(sfx_name) + + def playSound(self, sfx): + if self.sound: + if BASS_ChannelIsActive(self.sound): + BASS_ChannelStop(self.sound) + BASS_StreamFree(self.sound) + if exists(AOpath + 'sounds\\general\\' + sfx + '.wav'): + self.sound = BASS_StreamCreateFile(False, AOpath + 'sounds\\general\\' + sfx + '.wav', 0, 0, 0) + BASS_ChannelSetAttribute(self.sound, BASS_ATTRIB_VOL, self.soundslider.value() / 100.0) + BASS_ChannelPlay(self.sound, True) + + def playMusic(self, mus): + if self.music: + if BASS_ChannelIsActive(self.music): + BASS_ChannelStop(self.music) + BASS_StreamFree(self.music) + if exists(AOpath + 'sounds\\music\\' + mus): + self.music = BASS_StreamCreateFile(False, AOpath + 'sounds\\music\\' + mus, 0, 0, 0) + BASS_ChannelSetAttribute(self.music, BASS_ATTRIB_VOL, self.musicslider.value() / 100.0) + BASS_ChannelPlay(self.music, True) + elif ini.read_ini_bool(AOpath+"AO2XP.ini", "General", "download music"): + self.music = BASS_StreamCreateURL('http://s3.wasabisys.com/webao/base/sounds/music/' + mus.lower(), 0, 0, DOWNLOADPROC(), 0) + if self.music: + BASS_ChannelSetAttribute(self.music, BASS_ATTRIB_VOL, self.musicslider.value() / 100.0) + BASS_ChannelPlay(self.music, True) + + def stopMusic(self): + if self.music: + if BASS_ChannelIsActive(self.music): + BASS_ChannelStop(self.music) + BASS_StreamFree(self.music) + + def startGame(self, tcp, charlist, musiclist, background, evidence, areas, features=[], oocjoin=[], hplist=[]): + self.willDisconnect = False + self.mychar = -1 + self.mychatcolor = 0 + self.tcp = tcp + self.charlist = charlist + self.musiclist = musiclist + self.evidence = evidence + self.areas = areas + self.features = features + + self.charselect.setCharList(charlist) + self.charselect.show() + + self.oocnameinput.setText(ini.read_ini(AOpath+"AO2XP.ini", "General", "OOC name")) + + self.pairdropdown.clear() + self.paircheckbox.setChecked(False) + if "cccc_ic_support" in features: + self.shownameedit.show() + self.nointerruptbtn.show() + self.paircheckbox.setDisabled(False) + self.paircheckbox.setText("Enable pairing") + for char in charlist: + self.pairdropdown.addItem(char[0]) + else: + self.shownameedit.hide() + self.nointerruptbtn.hide() + self.paircheckbox.setDisabled(True) + self.paircheckbox.setText("This server does not support pairing.") + + if "flipping" in features: + self.flipbutton.show() + else: + self.flipbutton.hide() + + if "customobjections" in features: + self.customobject.show() + else: + self.customobject.hide() + + self.colordropdown.clear() + self.colordropdown.addItems(['white', 'green', 'red', 'orange', 'blue']) + if "yellowtext" in features: + self.colordropdown.addItems(['yellow', 'gay pride', 'pink', 'cyan']) + self.colordropdown.setCurrentIndex(self.mychatcolor) + + for hp in hplist: + self.healthbars.emit(hp[0], hp[1]) + + for char in self.charlist: + if not exists(AOpath + 'characters\\' + char[0] + '\\char.ini'): + continue + char[2] = get_char_ini(char[0], "options", "gender", "male") + + self.realizationbtn.setPressed(False) + self.customobject.setPressed(False) + self.mutedlist.clear() + self.unmutedlist.clear() + for char in self.charlist: + self.unmutedlist.addItem(char[0]) + + self.musicitems.clear() + self.evidencedropdown.clear() + for evi in evidence: + self.evidencedropdown.addItem(evi[0]) + + logstart = '--- Log started on ' + time.ctime() + ' ---' + if self.ooclog.toPlainText(): + self.ooclog.append("\n"+logstart) + else: + self.ooclog.append(logstart) + if self.icLog.toPlainText(): + self.icLog.append("\n"+logstart) + else: + self.icLog.append(logstart) + + bgthread = setBackgroundThread(background) + self.connect(bgthread, QtCore.SIGNAL('setBackground(QString)'), self.setBackground) + bgthread.start() + del bgthread + for msg in oocjoin: + self.ooclog.append(msg) + + for song in musiclist: + songitem = QtGui.QListWidgetItem() + songitem.setText(song) + if exists(AOpath + 'sounds\\music\\' + song): + songitem.setBackgroundColor(QtGui.QColor(128, 255, 128)) + else: + songitem.setBackgroundColor(QtGui.QColor(255, 128, 128)) + self.musicitems.addItem(songitem) + + self.tcp.settimeout(0.1) + #thread.start_new_thread(self.tcp_thread, ()) + self.tcpthread = TCP_Thread(self) + self.tcpthread.MS_Chat.connect(self.netmsg_ms) + self.tcpthread.start() + + +class ButtonThread(QtCore.QThread): + + def __init__(self, ind, img): + QtCore.QThread.__init__(self) + self.ind = ind + self.img = img + + def __del__(self): + self.wait() + + def run(self): + self.emit(QtCore.SIGNAL('buttonthread(int, QString)'), self.ind, self.img) + + +class setBackgroundThread(QtCore.QThread): + + def __init__(self, bg): + QtCore.QThread.__init__(self) + self.bg = bg + + def __del__(self): + self.wait() + + def run(self): + self.emit(QtCore.SIGNAL('setBackground(QString)'), self.bg) + + +class anythingThread(QtCore.QThread): + + def __init__(self, signal, *args): + QtCore.QThread.__init__(self) + self.args = args + self.signal = signal + + def __del__(self): + self.wait() + + def run(self): + emitstr = "self.emit(QtCore.SIGNAL('%s')" % self.signal + for i in range(len(self.args)): + emitstr += ', self.args[' + str(i) + ']' + + emitstr += ')' + print emitstr + exec emitstr + + +class PresentButton(QtGui.QLabel): + + def __init__(self, gamegui, parent): + super(PresentButton, self).__init__(parent) + self.gamegui = gamegui + self.button_off = QtGui.QPixmap(AOpath + 'themes\\default\\present_disabled.png') + self.button_on = QtGui.QPixmap(AOpath + 'themes\\default\\present.png') + self.setPixmap(self.button_off) + self.show() + + def mousePressEvent(self, event): + self.gamegui.present = not self.gamegui.present + if self.gamegui.present: + self.setPixmap(self.button_on) + else: + self.setPixmap(self.button_off) + + +class EditEvidenceDialog(QtGui.QDialog): + + def __init__(self, gamegui): + super(EditEvidenceDialog, self).__init__() + self.gamegui = gamegui + self.setWindowTitle('Add evidence') + self.resize(512, 384) + self.eviname = QtGui.QLineEdit(self) + self.eviname.setGeometry(8, 8, 384, 24) + self.evidesc = QtGui.QTextEdit(self) + self.evidesc.setGeometry(8, 192, 496, 160) + self.evipicture = QtGui.QLabel(self) + self.filename = 'empty.png' + evipic = QtGui.QPixmap(AOpath + 'evidence\\empty.png') + self.evipicture.setPixmap(evipic) + self.evipicture.move(434, 8) + self.evipicture.show() + self.save = QtGui.QPushButton(self) + self.save.setText('Save') + self.save.clicked.connect(self.onSave) + self.save.move(256 - self.save.size().width() - 8, 384 - self.save.size().height()) + self.cancel = QtGui.QPushButton(self) + self.cancel.setText('Cancel') + self.cancel.clicked.connect(self.onCancel) + self.cancel.move(264, 384 - self.cancel.size().height()) + self.choosepic = QtGui.QComboBox(self) + self.filenames = [] + self.choosepic.setGeometry(376, 78, 128, 24) + files = os.listdir(AOpath + 'evidence') + fileslength = len(files) + i = 0 + while i < fileslength: + if not files[i].endswith('.png'): + del files[i] + fileslength = len(files) + i -= 1 + i += 1 + + for i in range(len(files)): + if files[i].endswith('.png'): + self.choosepic.addItem(files[i].strip('.png')) + self.filenames.append(files[i]) + if files[i].lower() == 'empty.png': + self.emptyfile = i + + self.editing = False + self.choosepic.currentIndexChanged.connect(self.choosePicChange) + self.choosepic.setCurrentIndex(i) + + def choosePicChange(self, ind): + self.filename = self.filenames[ind] + if exists(AOpath + 'evidence\\' + self.filename): + self.evipicture.setPixmap(QtGui.QPixmap(AOpath + 'evidence\\' + self.filename)) + else: + self.evipicture.setPixmap(QtGui.QPixmap(AOpath + 'themes\\default\\evidence_selected.png')) + + def onSave(self): + name = self.eviname.text().toUtf8() + desc = self.evidesc.toPlainText().toUtf8() + if self.editing: + self.gamegui.tcp.send('EE#' + str(self.edit_ind) + '#' + name + '#' + desc + '#' + self.filename + '#%') + else: + self.gamegui.tcp.send('PE#' + name + '#' + desc + '#' + self.filename + '#%') + self.eviname.setText('') + self.evidesc.setText('') + evipic = QtGui.QPixmap(AOpath + 'evidence\\empty.png') + self.evipicture.setPixmap(evipic) + self.filename = 'empty.png' + self.editing = False + self.setWindowTitle('Add evidence') + self.choosepic.setCurrentIndex(self.emptyfile) + self.hide() + + def onCancel(self): + self.eviname.setText('') + self.evidesc.setText('') + evipic = QtGui.QPixmap(AOpath + 'evidence\\empty.png') + self.evipicture.setPixmap(evipic) + self.filename = 'empty.png' + self.editing = False + self.setWindowTitle('Add evidence') + self.choosepic.setCurrentIndex(self.emptyfile) + self.hide() + + def EditEvidence(self, ind): + self.editing = True + self.edit_ind = ind + if self.gamegui.evidence[ind][2] not in self.filenames: + self.filenames.append(self.gamegui.evidence[ind][2]) + self.choosepic.addItem(self.gamegui.evidence[ind][2].split('.')[0]) + self.choosepic.setCurrentIndex(self.filenames.index(self.gamegui.evidence[ind][2])) + self.eviname.setText(self.gamegui.evidence[ind][0]) + self.evidesc.setText(self.gamegui.evidence[ind][1]) + self.setWindowTitle('Edit evidence') + self.show() + + +class EmoteButton(QtGui.QLabel): + + def __init__(self, gamewindow, x, y, id): + super(EmoteButton, self).__init__(gamewindow) + self.gamewindow = gamewindow + self.resize(40, 40) + self.move(x, y) + self.emoteid = id + + def paintEvent(self, event): + if self.gamewindow.mychar == -1: + return + + painter = QtGui.QPainter(self) + painter.setRenderHint(QtGui.QPainter.TextAntialiasing, False) + painter.setPen(QtGui.QColor(255, 255, 255)) + font = QtGui.QFont("Tahoma", 8) + font.setStyle(QtGui.QFont.StyleNormal) + font.setWeight(QtGui.QFont.Normal) + painter.setFont(font) + + if self.pixmap(): + if self.pixmap().isNull(): + painter.fillRect(0, 0, 39, 39, QtGui.QColor(0, 0, 0)) + painter.drawText(0, 0, str(self.emoteid)) + else: + painter.drawPixmap(0, 0, self.pixmap()) + else: + painter.fillRect(0, 0, 39, 39, QtGui.QColor(0, 0, 0)) + painter.drawText(1, 1, str(self.emoteid)) + + def mousePressEvent(self, event): + self.gamewindow.changeEmote(False, self.emoteid) + + +class BackEmoteButton(QtGui.QLabel): + + def __init__(self, gamewindow, x, y): + super(BackEmoteButton, self).__init__(gamewindow) + self.gamewindow = gamewindow + self.move(x, y) + self.setPixmap(QtGui.QPixmap(AOpath + 'themes\\default\\arrow_left.png')) + self.show() + + def mousePressEvent(self, event): + self.gamewindow.current_emote_page -= 1 + self.gamewindow.set_emote_page() + + +class NextEmoteButton(QtGui.QLabel): + + def __init__(self, gamewindow, x, y): + super(NextEmoteButton, self).__init__(gamewindow) + self.gamewindow = gamewindow + self.move(x, y) + self.setPixmap(QtGui.QPixmap(AOpath + 'themes\\default\\arrow_right.png')) + self.show() + + def mousePressEvent(self, event): + self.gamewindow.current_emote_page += 1 + self.gamewindow.set_emote_page() + + +class TCP_Thread(QtCore.QThread): + MS_Chat = QtCore.pyqtSignal(list) + def __init__(self, parent): + super(TCP_Thread, self).__init__(parent) + self.parent = parent + + def run(self): + pingtimer = 150 + rainbow = 0 + sendtick = 0 + tempdata = "" + color = QtGui.QColor() + color.setHsv(rainbow, 255, 255) + while True: + if self.parent.disconnectnow: + self.parent.stopMusic() + self.parent.tcp.close() + self.quit() + return + pingtimer -= 1 + if pingtimer == 0: + self.parent.tcp.send('CH#%') + pingtimer = 150 + + if self.parent.m_chatmessage[TEXT_COLOR] == "6": + color.setHsv(rainbow, 255, 255) + rainbow += 5 + if rainbow > 255: + rainbow = 0 + self.parent.text.setStyleSheet('color: rgb(' + str(color.red()) + ', ' + str(color.green()) + ', ' + str(color.blue()) + ')') + + if sendtick: + sendtick -= 1 + if self.parent.msgqueue and not sendtick: + self.parent.tcp.send(self.parent.msgqueue[0]) + sendtick = 4 + + try: + contents = self.parent.tcp.recv(8192) + except (socket.timeout, socket.error) as err: + error = err.args[0] + if error == "timed out" or error == 10035: + continue + else: + self.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'critical', 'Connection lost', str(err)) + self.parent.willDisconnect = True + self.quit() + return + + if not contents: + self.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'critical', 'Connection lost', 'the server closed the connection') + self.parent.willDisconnect = True + self.quit() + return + + if not contents.endswith("%"): + tempdata += contents + continue + else: + if tempdata: + contents = tempdata + contents + tempdata = "" + + total = contents.split('%') + for msg in total: + network = msg.split('#') + header = network[0] + del network[-1] + if header == 'MS': + if len(network) < 15: + print '[warning]', 'malformed/incomplete MS#chat (IC chat) network message was received' + continue + + network[CHATMSG] = network[CHATMSG].decode('utf-8').replace('', '$').replace('', '%').replace('', '&').replace('', '#') + self.MS_Chat.emit(network) + + elif header == 'MC': + music = network[1] + charid = int(network[2]) + t = time.localtime() + if charid != -1: + try: + name = self.parent.charlist[charid][0] + except: + name = 'char id %d' % charid + + if len(network) > 3: + name += " ("+network[3]+")" + self.parent.icLog.append('[%d:%.2d] %s changed the music to %s' % (t[3], t[4], name, music)) + else: + self.parent.icLog.append('[%d:%.2d] the music was changed to %s' % (t[3], t[4], music)) + self.parent.playMusic(music) + elif header == 'BN': + imgthread = setBackgroundThread(network[1]) + self.parent.connect(imgthread, QtCore.SIGNAL('setBackground(QString)'), self.parent.setBackground) + imgthread.start() + del imgthread + elif header == 'CT': + name = network[1].decode('utf-8').replace('', '$').replace('', '%').replace('', '&').replace('', '#').replace('', '#') + chatmsg = network[2].decode('utf-8').replace('', '$').replace('', '%').replace('', '&').replace('', '#').replace('', '#').replace("\n", "
") + self.parent.ooclog.append('%s: %s' % (name, chatmsg)) + elif header == 'PV': + self.parent.mychar = int(network[3]) + self.parent.charselect.hide() + if self.parent.swapping: + return + self.parent.emotedropdown.clear() + self.parent.msgqueueList.clear() + self.parent.msgqueue = [] + self.parent.charemotes = [] + self.parent.selectedemote = 0 + self.parent.current_emote_page = 0 + if exists(AOpath + 'characters\\' + self.parent.charlist[self.parent.mychar][0]) and exists(AOpath + 'characters\\' + self.parent.charlist[self.parent.mychar][0] + '\\char.ini'): + self.parent.charini.read(AOpath + 'characters\\' + self.parent.charlist[self.parent.mychar][0] + '\\char.ini') + values = self.parent.charini.sections() + for val in values: + if val.lower() == 'options': + ini_options = val + elif val.lower() == 'time': + ini_time = val + elif val.lower() == 'emotions': + ini_emotions = val + elif val.lower() == 'soundn': + ini_soundn = val + elif val.lower() == 'soundt': + ini_soundt = val + + self.parent.charname = self.parent.charini.get(ini_options, 'name', self.parent.charlist[self.parent.mychar][0]) + self.parent.charside = self.parent.charini.get(ini_options, 'side', 'def') + self.parent.posdropdown.setCurrentIndex(self.parent.posdropdown.findText(self.parent.charside)) + self.parent.setJudgeButtons() + for emoteind in range(1, int(self.parent.charini.get(ini_emotions, 'number', '1')) + 1): + if emoteind <= self.parent.max_emotes_on_page: + if emoteind == 1: + suffix = 'on' + else: + suffix = 'off' + btnthread = ButtonThread(emoteind - 1, AOpath + 'characters\\' + self.parent.charname + '\\emotions\\button' + str(emoteind) + '_' + suffix + '.png') + self.parent.connect(btnthread, QtCore.SIGNAL('buttonthread(int, QString)'), self.parent.buttonthread) + btnthread.start() + del btnthread + emote = self.parent.charini.get(ini_emotions, str(emoteind), 'normal#(a)normal#normal#0#') + sound = self.parent.charini.get(ini_soundn, str(emoteind), '1') + soundt = self.parent.charini.get(ini_soundt, str(emoteind), '0') + emotelist = emote.split('#') + del emotelist[len(emotelist) - 1] + emotelist.append(sound) + emotelist.append(soundt) + self.parent.charemotes.append(emotelist) + self.parent.emotedropdown.addItem(emotelist[0]) + + self.parent.emotedropdown.setCurrentIndex(0) + athread = anythingThread('set_emote_page()') + self.parent.connect(athread, QtCore.SIGNAL('set_emote_page()'), self.parent.set_emote_page) + athread.start() + del athread + elif header == 'LE': + del network[0] + self.parent.evidence = [ evi.split('&') for evi in network ] + if self.parent.evidencedropdown.count() > 0: + self.parent.evidencedropdown.clear() + for evi in self.parent.evidence: + evi[0] = evi[0].decode('utf-8') + evi[1] = evi[1].decode('utf-8') + evi[2] = evi[2].decode('utf-8') + self.parent.evidencedropdown.addItem(evi[0]) + + if not self.parent.evidence: + self.parent.evidencedropdown.setCurrentIndex(0) + self.parent.evidencedesc.setText('.') + else: + self.parent.evidencedropdown.setCurrentIndex(self.parent.selectedevi) + elif header == 'ZZ': + if self.parent.modcall: + BASS_ChannelPlay(self.parent.modcall, False) + + if len(network) > 1: + self.parent.ooclog.append('[MOD CALL] ' + network[1].replace("\n", "
") + '
') + else: + self.parent.ooclog.append('[MOD CALL] But there was no extra information. (old server?)') + elif header == 'CharsCheck': + del network[0] + for i in range(len(network)): + self.parent.charlist[i][1] = int(network[i]) + + self.parent.charselect.setCharList(self.parent.charlist) + + elif header == 'RT': + testimony = network[1] + if testimony == 'judgeruling': + variant = int(network[2]) + if variant == 0: + BASS_ChannelPlay(self.parent.notguiltysfx, True) + elif variant == 1: + BASS_ChannelPlay(self.parent.guiltysfx, True) + else: + variant = 0 + BASS_ChannelPlay(self.parent.wtcesfx, True) + self.parent.WTCEsignal.emit(testimony, variant) + + elif header == 'HP': + type = int(network[1]) + health = int(network[2]) + self.parent.healthbars.emit(type, health) + + elif header == 'KK': + reason = network[1] + self.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'critical', 'Connection lost', 'You were kicked off the server. (%s)' % reason) + + elif header == 'KB': + reason = network[1] + self.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'critical', 'Connection lost', 'You have been banned from the server. (%s)' % reason) + + elif header == 'DONE': + self.parent.charselect.show() \ No newline at end of file diff --git a/ini.py b/ini.py new file mode 100644 index 0000000..f20d128 --- /dev/null +++ b/ini.py @@ -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 \ No newline at end of file diff --git a/mainmenu.py b/mainmenu.py new file mode 100644 index 0000000..2453755 --- /dev/null +++ b/mainmenu.py @@ -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 "" in network[0]: #The Next Chapter actually does this sorcery... + evidence = [evi.split("") 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('', '$').replace('', '%').replace('', '&').replace('', '#').replace('', '#') + chatmsg = network[1].decode("utf-8").replace('', '$').replace('', '%').replace('', '&').replace('', '#').replace('', '#') + 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('', '$').replace('', '%').replace('', '&').replace('', '#').replace('', '#') + chatmsg = network[2].decode("utf-8").replace('', '$').replace('', '%').replace('', '&').replace('', '#').replace('', '#') + self.lobbychatlog.append('%s: %s' % (name, chatmsg)) \ No newline at end of file diff --git a/mod_call.wav b/mod_call.wav new file mode 100644 index 0000000..9630a8e Binary files /dev/null and b/mod_call.wav differ diff --git a/options.py b/options.py new file mode 100644 index 0000000..8d62e32 --- /dev/null +++ b/options.py @@ -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() \ No newline at end of file diff --git a/placeholder.png b/placeholder.png new file mode 100644 index 0000000..a27ca4c Binary files /dev/null and b/placeholder.png differ diff --git a/quicksetup.py b/quicksetup.py new file mode 100644 index 0000000..3e6c3ff --- /dev/null +++ b/quicksetup.py @@ -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" diff --git a/word_call.wav b/word_call.wav new file mode 100644 index 0000000..66e0375 Binary files /dev/null and b/word_call.wav differ