2022-03-27 21:01:18 -04:00
import thread , time , os , buttons , urllib , charselect , ini , random
2025-02-13 18:21:37 -05:00
from os . path import exists , basename
2025-02-14 22:30:08 -05:00
from ConfigParserEdit import ConfigParser
2019-04-03 10:57:23 -04:00
2021-06-20 11:25:16 -04:00
from pybass_constants import *
2021-06-20 01:29:40 -04:00
from PyQt4 import QtGui , QtCore
from functools import partial
2025-02-14 13:00:19 -05:00
from ctypes import create_string_buffer
from urllib2 import Request , urlopen
2021-06-20 01:29:40 -04:00
2022-03-27 21:01:18 -04:00
import AOsocket
2020-08-04 00:53:53 -04:00
import images
2020-08-01 22:15:07 -04:00
AOpath = " base/ "
2020-08-06 22:04:06 -04:00
AO2XPpath = " AO2XPbase/ "
2020-08-01 22:15:07 -04:00
#AOpath = 'I:/aovanilla1.7.5/client/base/'
2019-04-03 10:57:23 -04:00
2021-03-13 18:19:17 -05:00
DESK_MOD = 1
2019-04-03 10:57:23 -04:00
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
2020-08-04 08:37:29 -04:00
LOOPING_SFX = 24
SCREENSHAKE = 25
FRAME_SCREENSHAKE = 26
FRAME_REALIZATION = 27
FRAME_SFX = 28
ADDITIVE = 29
EFFECTS = 30
2019-04-03 10:57:23 -04:00
INLINE_BLUE = 0
INLINE_GREEN = 1
INLINE_ORANGE = 2
INLINE_GRAY = 3
2020-08-06 07:09:17 -04:00
INLINE_RED = 4
2019-04-03 10:57:23 -04:00
C_WHITE = 0
C_GREEN = 1
C_RED = 2
C_ORANGE = 3
C_BLUE = 4
C_YELLOW = 5
2025-02-14 15:46:12 -05:00
C_PINK = 6
C_CYAN = 7
C_GRAY = 8
2019-04-03 10:57:23 -04:00
2019-04-19 22:48:56 -04:00
DOWNLOAD_BLACKLIST = [ ]
2025-02-11 12:08:54 -05:00
VIEWPORT_W = 256 * 2
VIEWPORT_H = 192 * 2
2019-04-03 10:57:23 -04:00
def delay ( msec ) :
2022-02-21 11:48:51 -05:00
dieTime = QtCore . QTime . currentTime ( ) . addMSecs ( msec )
while QtCore . QTime . currentTime ( ) < dieTime :
QtCore . QCoreApplication . processEvents ( QtCore . QEventLoop . AllEvents , 100 )
2019-07-29 11:17:14 -04:00
def decode_ao_str ( text ) :
2022-02-21 11:48:51 -05:00
return text . replace ( " <percent> " , " % " ) . replace ( " <pound> " , " # " ) . replace ( " <num> " , " # " ) . replace ( " <and> " , " & " ) . replace ( " <dollar> " , " $ " )
2021-03-12 13:39:54 -05:00
def encode_ao_str ( text ) :
2022-02-21 11:48:51 -05:00
return text . replace ( " % " , " <percent> " ) . replace ( " # " , " <pound> " ) . replace ( " & " , " <and> " ) . replace ( " $ " , " <dollar> " )
2019-04-03 10:57:23 -04:00
def get_char_ini ( char , section , value , default = " " ) :
2022-02-21 11:48:51 -05:00
tempini = ConfigParser ( )
2025-02-11 12:08:54 -05:00
with open ( AOpath + ' characters/ ' + char + ' /char.ini ' , ' r ' ) as file :
for line in file :
try :
tempini . readfp ( file )
except :
pass
2022-02-21 11:48:51 -05:00
return ini . read_ini ( tempini , section , value , default )
2020-08-01 22:15:07 -04:00
def get_option ( section , value , default = " " ) :
2022-02-21 11:48:51 -05:00
tempini = ConfigParser ( )
tempini . read ( " AO2XP.ini " )
return ini . read_ini ( tempini , section , value , default )
2019-04-03 10:57:23 -04:00
2020-08-04 23:29:43 -04:00
def get_img_suffix ( path ) :
if exists ( path ) : return path
if exists ( path + " .webp " ) : return path + " .webp "
if exists ( path + " .apng " ) : return path + " .apng "
if exists ( path + " .gif " ) : return path + " .gif "
return path + " .png "
2019-04-03 10:57:23 -04:00
def get_text_color ( textcolor ) :
2022-02-21 11:48:51 -05:00
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 )
2019-04-03 10:57:23 -04:00
2021-03-13 12:40:32 -05:00
buckets = [ " " , " \x61 \x48 \x52 \x30 \x63 \x44 \x6f \x76 \x4c \x32 \x46 \x76 \x4c \x57 \x35 \x76 \x62 \x6d \x5a \x79 \x5a \x57 \x55 \x75 \x59 \x69 \x31 \x6a \x5a \x47 \x34 \x75 \x62 \x6d \x56 \x30 \x4c \x77 \x3d \x3d " . decode ( " \x62 \x61 \x73 \x65 \x36 \x34 " ) ] # troll
# bucket 0 ("") is used for server's own bucket
2019-04-03 10:57:23 -04:00
def download_thread ( link , savepath ) :
2020-08-06 12:53:13 -04:00
global DOWNLOAD_BLACKLIST
if link in DOWNLOAD_BLACKLIST :
return
for bucket in buckets :
2021-03-13 13:33:09 -05:00
if not bucket : continue
2020-08-06 12:53:13 -04:00
i = buckets . index ( bucket )
print " download missing: %s " % link
fp = urllib . urlopen ( bucket + link )
if fp . getcode ( ) == 200 :
2021-03-12 18:42:33 -05:00
if not os . path . exists ( savepath [ : - 1 ] ) :
2022-02-21 11:48:51 -05:00
os . makedirs ( savepath [ : - 1 ] )
2021-03-12 18:42:33 -05:00
2020-08-06 12:53:13 -04:00
with open ( savepath , " wb " ) as f :
f . write ( fp . read ( ) )
print " successfully downloaded: " , link
return
DOWNLOAD_BLACKLIST . append ( link )
print " couldn ' t download ' %s ' " % link
2019-04-03 10:57:23 -04:00
2019-05-24 20:38:02 -04:00
def mockStr ( text ) :
2022-02-21 11:48:51 -05:00
upper = random . choice ( [ True , False ] )
l = list ( text )
for i in range ( len ( text ) ) :
if text [ i ] == " " :
continue
l [ i ] = l [ i ] . upper ( ) if upper else l [ i ] . lower ( )
upper = not upper
return " " . join ( l )
2019-05-24 20:38:02 -04:00
2019-04-03 10:57:23 -04:00
class ChatLogs ( QtGui . QTextEdit ) :
2022-02-21 11:48:51 -05:00
def __init__ ( self , parent , logtype , logfile = None ) :
QtGui . QTextEdit . __init__ ( self , parent )
self . type = logtype
self . savelog = ini . read_ini_bool ( " AO2XP.ini " , " General " , " save logs " )
self . combinelog = ini . read_ini_bool ( " AO2XP.ini " , " General " , " combined logs " )
if not 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 " )
else :
2020-08-01 22:15:07 -04:00
self . logfile = None
2022-02-21 11:48:51 -05:00
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 " )
2019-04-03 10:57:23 -04:00
class AOCharMovie ( QtGui . QLabel ) :
2022-02-21 11:48:51 -05:00
done = QtCore . pyqtSignal ( )
use_pillow = 0
pillow_frames = [ ]
pillow_frame = 0
pillow_speed = 0
xx = 0 # for restoring from screenshake
yy = 0 # for restoring from screenshake
def __init__ ( self , parent ) :
QtGui . QLabel . __init__ ( self , parent )
2025-02-11 12:08:54 -05:00
self . resize ( VIEWPORT_W , VIEWPORT_H )
2025-02-11 17:31:05 -05:00
self . setAlignment ( QtCore . Qt . AlignCenter )
2022-02-21 11:48:51 -05:00
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 . pillow_timer = QtCore . QTimer ( self )
self . pillow_timer . setSingleShot ( True )
self . preanim_timer . timeout . connect ( self . timer_done )
self . pillow_timer . timeout . connect ( self . pillow_frame_change )
self . m_movie . frameChanged . connect ( self . frame_change )
2025-02-13 19:11:30 -05:00
self . prev_gif_path = " "
2022-02-21 11:48:51 -05:00
def move ( self , x , y , screenShaking = False ) :
if not screenShaking :
self . xx = x
self . yy = y
super ( AOCharMovie , self ) . move ( x , y )
def set_flipped ( self , flip ) :
self . m_flipped = flip
def play ( self , p_char , p_emote , emote_prefix ) :
if p_emote [ 0 ] == " / " or p_emote [ 0 ] == " / " :
p_emote = p_emote [ 1 : ]
elif " ../../characters " in p_emote :
print p_emote
a = p_emote . split ( " / " )
p_char = a [ 3 ]
emote = a [ 4 ]
emote_prefix = " "
p_emote = emote
self . pillow_frames = [ ]
self . pillow_frame = 0
2025-02-12 22:31:36 -05:00
p_char = p_char . decode ( ' utf-8 ' )
2022-02-21 11:48:51 -05:00
original_path = AOpath + " characters/ " + p_char + " / " + emote_prefix + p_emote + " .gif "
alt_path = AOpath + " characters/ " + p_char + " / " + p_emote + " .png "
apng_path = AOpath + " characters/ " + p_char + " / " + emote_prefix + p_emote + " .apng "
webp_path = AOpath + " characters/ " + p_char + " / " + emote_prefix + p_emote + " .webp "
placeholder_path = AO2XPpath + " themes/default/placeholder.gif "
gif_path = " "
if exists ( apng_path ) :
gif_path = apng_path
self . use_pillow = 1
else :
if ini . read_ini_bool ( " AO2XP.ini " , " General " , " download characters " ) :
url = " base/characters/ " + p_char . lower ( ) + " / " + emote_prefix + p_emote . lower ( ) + " .apng "
url = url . replace ( " " , " % 20 " )
thread . start_new_thread ( download_thread , ( url , apng_path ) )
if exists ( webp_path ) :
gif_path = webp_path
self . use_pillow = 2
else :
if ini . read_ini_bool ( " AO2XP.ini " , " General " , " download characters " ) :
url = " base/characters/ " + p_char . lower ( ) + " / " + p_emote . lower ( ) + " .webp "
url = url . replace ( " " , " % 20 " )
thread . start_new_thread ( download_thread , ( url , webp_path ) )
if exists ( original_path ) :
gif_path = original_path
self . use_pillow = 0
else :
if ini . read_ini_bool ( " AO2XP.ini " , " General " , " download characters " ) :
url = " base/characters/ " + p_char . lower ( ) + " / " + emote_prefix + p_emote . lower ( ) + " .gif "
url = url . replace ( " " , " % 20 " )
thread . start_new_thread ( download_thread , ( url , original_path ) )
if exists ( alt_path ) :
gif_path = alt_path
self . use_pillow = 0
else :
if ini . read_ini_bool ( " AO2XP.ini " , " General " , " download characters " ) :
url = " base/characters/ " + p_char . lower ( ) + " / " + emote_prefix + p_emote . lower ( ) + " .png "
url = url . replace ( " " , " % 20 " )
thread . start_new_thread ( download_thread , ( url , alt_path ) )
if exists ( placeholder_path ) :
gif_path = placeholder_path
else :
gif_path = " "
self . use_pillow = 0
2025-02-13 19:11:30 -05:00
if gif_path == placeholder_path or gif_path == " " :
gif_path = self . prev_gif_path
else :
self . prev_gif_path = gif_path
2022-02-21 11:48:51 -05:00
if not self . use_pillow :
self . m_movie . stop ( )
self . m_movie . setFileName ( gif_path )
self . m_movie . start ( )
elif self . use_pillow == 1 : # apng
self . pillow_frames = images . load_apng ( apng_path )
2025-02-13 22:22:55 -05:00
if len ( self . pillow_frames ) > 1 :
self . pillow_timer . start ( int ( self . pillow_frames [ 0 ] [ 1 ] * self . pillow_speed ) )
2022-02-21 11:48:51 -05:00
self . set_pillow_frame ( )
elif self . use_pillow == 2 : # webp
self . pillow_frames = images . load_webp ( webp_path )
2025-02-13 22:22:55 -05:00
if len ( self . pillow_frames ) > 1 :
self . pillow_timer . start ( int ( self . pillow_frames [ 0 ] [ 1 ] * self . pillow_speed ) )
2022-02-21 11:48:51 -05:00
self . set_pillow_frame ( )
self . show ( )
def play_pre ( self , p_char , p_emote , duration ) :
gif_path = AOpath + " characters/ " + p_char + " / " + p_emote + " .gif "
apng_path = AOpath + " characters/ " + p_char + " / " + p_emote + " .apng "
webp_path = AOpath + " characters/ " + p_char + " / " + p_emote + " .webp "
full_duration = duration * self . time_mod
real_duration = 0
self . play_once = False
self . m_movie . stop ( )
self . clear ( )
if exists ( apng_path ) :
real_duration = images . get_apng_duration ( apng_path )
elif exists ( webp_path ) :
real_duration = images . get_webp_duration ( webp_path )
elif exists ( gif_path ) :
self . m_movie . setFileName ( gif_path )
self . m_movie . jumpToFrame ( 0 )
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
self . pillow_fullduration = full_duration
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 . pillow_speed = percentage_modifier / 100.
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 . pillow_speed = 1
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 . pillow_speed = 1
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_img = self . m_movie . currentImage ( ) . mirrored ( self . m_flipped , False )
2025-02-11 17:31:05 -05:00
if not f_img . isNull ( ) and ( f_img . size ( ) . width ( ) != VIEWPORT_W or f_img . size ( ) . height ( ) != VIEWPORT_H ) :
f_img = f_img . scaled ( VIEWPORT_W , VIEWPORT_H , QtCore . Qt . KeepAspectRatioByExpanding , QtCore . Qt . FastTransformation )
2022-02-21 11:48:51 -05:00
f_pixmap = QtGui . QPixmap . fromImage ( f_img )
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 pillow_frame_change ( self ) :
if not self . pillow_frames : return
if len ( self . pillow_frames ) - 1 == self . pillow_frame :
if self . play_once :
self . preanim_timer . start ( int ( self . pillow_frames [ self . pillow_frame ] [ 1 ] * self . pillow_speed ) )
elif len ( self . pillow_frames ) > 1 :
self . pillow_frame = 0
self . pillow_timer . start ( int ( self . pillow_frames [ self . pillow_frame ] [ 1 ] * self . pillow_speed ) )
else :
self . pillow_frame + = 1
self . pillow_timer . start ( int ( self . pillow_frames [ self . pillow_frame ] [ 1 ] * self . pillow_speed ) )
self . set_pillow_frame ( )
def set_pillow_frame ( self ) :
f_img = self . pillow_frames [ self . pillow_frame ] [ 0 ] . mirrored ( self . m_flipped , False )
2025-02-11 17:31:05 -05:00
if not f_img . isNull ( ) and ( f_img . size ( ) . width ( ) != VIEWPORT_W or f_img . size ( ) . height ( ) != VIEWPORT_H ) :
f_img = f_img . scaled ( VIEWPORT_W , VIEWPORT_H , QtCore . Qt . KeepAspectRatioByExpanding , QtCore . Qt . FastTransformation )
2022-02-21 11:48:51 -05:00
f_pixmap = QtGui . QPixmap . fromImage ( f_img )
self . setPixmap ( f_pixmap )
@QtCore.pyqtSlot ( )
def timer_done ( self ) :
self . done . emit ( )
2019-04-03 10:57:23 -04:00
class AOMovie ( QtGui . QLabel ) :
2022-02-21 11:48:51 -05:00
play_once = True
done = QtCore . pyqtSignal ( )
use_pillow = 0
pillow_frames = [ ]
pillow_frame = 0
pillow_speed = 1
xx = 0 # for restoring from screenshake
yy = 0 # for restoring from screenshake
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 )
self . pillow_timer = QtCore . QTimer ( self )
self . pillow_timer . setSingleShot ( True )
self . pillow_timer . timeout . connect ( self . pillow_frame_change )
2025-02-13 22:22:55 -05:00
self . pillow_label = QtGui . QLabel ( self )
self . pillow_label . setGeometry ( 0 , 0 , VIEWPORT_W , VIEWPORT_H )
self . pillow_label . hide ( )
2022-02-21 11:48:51 -05:00
def move ( self , x , y ) :
self . xx = x
self . yy = y
super ( AOMovie , self ) . move ( x , y )
def set_play_once ( self , once ) :
self . play_once = once
def play ( self , p_image , p_char = " " ) :
gif_path = p_image
pillow_modes = { " .gif " : 0 , " .apng " : 1 , " .webp " : 2 }
2025-02-12 22:31:36 -05:00
p_image = unicode ( p_image )
2022-02-21 11:48:51 -05:00
if not exists ( gif_path ) :
pathlist = [
get_img_suffix ( AO2XPpath + " themes/default/ " + p_image + " _bubble " ) ,
get_img_suffix ( AOpath + " characters/ " + p_char + " / " + p_image ) ,
get_img_suffix ( AOpath + " misc/default/ " + p_image ) ,
get_img_suffix ( AO2XPpath + " themes/default/ " + p_image ) ,
2025-02-14 17:01:05 -05:00
#AO2XPpath+"themes/default/placeholder.gif"
2022-02-21 11:48:51 -05:00
]
for f in pathlist :
if exists ( f ) :
gif_path = f
break
2025-02-13 22:22:55 -05:00
2022-02-21 11:48:51 -05:00
self . use_pillow = pillow_modes [ os . path . splitext ( gif_path ) [ 1 ] ]
2025-02-13 22:22:55 -05:00
2022-02-21 11:48:51 -05:00
if not self . use_pillow :
self . m_movie . setFileName ( gif_path )
self . m_movie . start ( )
elif self . use_pillow == 1 : # apng
2025-02-13 22:22:55 -05:00
self . pillow_label . show ( )
2022-02-21 11:48:51 -05:00
self . pillow_frames = images . load_apng ( gif_path )
2025-02-13 22:22:55 -05:00
if len ( self . pillow_frames ) > 1 :
self . pillow_timer . start ( int ( self . pillow_frames [ 0 ] [ 1 ] * self . pillow_speed ) )
2022-02-21 11:48:51 -05:00
self . set_pillow_frame ( )
elif self . use_pillow == 2 : # webp
2025-02-13 22:22:55 -05:00
self . pillow_label . show ( )
2022-02-21 11:48:51 -05:00
self . pillow_loops = 0
self . pillow_frames , self . webp_loops = images . load_webp ( gif_path )
2025-02-13 22:22:55 -05:00
if len ( self . pillow_frames ) > 1 :
self . pillow_timer . start ( int ( self . pillow_frames [ 0 ] [ 1 ] * self . pillow_speed ) )
2022-02-21 11:48:51 -05:00
self . set_pillow_frame ( )
self . show ( )
def stop ( self ) :
self . pillow_frames = [ ]
self . pillow_frame = 0
self . pillow_timer . stop ( )
self . m_movie . stop ( )
2025-02-13 22:22:55 -05:00
self . pillow_label . clear ( )
self . pillow_label . hide ( )
2022-02-21 11:48:51 -05:00
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 ( )
@QtCore.pyqtSlot ( )
def pillow_frame_change ( self ) :
if not self . pillow_frames : return
if len ( self . pillow_frames ) - 1 == self . pillow_frame :
if self . play_once or ( self . use_pillow == 2 and self . pillow_loops + 1 == self . webp_loops ) :
delay ( int ( self . pillow_frames [ self . pillow_frame ] [ 1 ] * self . pillow_speed ) )
self . stop ( )
self . done . emit ( )
elif len ( self . pillow_frames ) > 1 : # loop
self . pillow_loops + = 1
self . pillow_frame = 0
self . pillow_timer . start ( int ( self . pillow_frames [ self . pillow_frame ] [ 1 ] * self . pillow_speed ) )
elif len ( self . pillow_frames ) > 1 :
self . pillow_frame + = 1
self . pillow_timer . start ( int ( self . pillow_frames [ self . pillow_frame ] [ 1 ] * self . pillow_speed ) )
self . set_pillow_frame ( )
def set_pillow_frame ( self ) :
if not self . pillow_frames : return
f_img = self . pillow_frames [ self . pillow_frame ] [ 0 ]
2025-02-11 17:31:05 -05:00
if not f_img . isNull ( ) and ( f_img . size ( ) . width ( ) != VIEWPORT_W or f_img . size ( ) . height ( ) != VIEWPORT_H ) :
f_img = f_img . scaled ( VIEWPORT_W , VIEWPORT_H , QtCore . Qt . KeepAspectRatioByExpanding , QtCore . Qt . FastTransformation )
2022-02-21 11:48:51 -05:00
f_pixmap = QtGui . QPixmap . fromImage ( f_img )
2025-02-13 22:22:55 -05:00
self . pillow_label . setPixmap ( f_pixmap )
2020-08-04 23:29:43 -04:00
2019-04-03 10:57:23 -04:00
class ZoomLines ( QtGui . QLabel ) :
2022-02-21 11:48:51 -05:00
def __init__ ( self , parent ) :
super ( ZoomLines , self ) . __init__ ( parent )
2025-02-11 12:08:54 -05:00
self . resize ( VIEWPORT_W , VIEWPORT_H )
self . setScaledContents ( True )
2022-02-21 11:48:51 -05:00
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 ( AO2XPpath + ' themes/default/defense_speedlines.gif ' )
else :
self . movie . setFileName ( AO2XPpath + ' themes/default/prosecution_speedlines.gif ' )
self . movie . start ( )
2019-04-03 10:57:23 -04:00
class WTCE_View ( QtGui . QLabel ) :
2022-02-21 11:48:51 -05:00
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 )
2025-02-11 12:08:54 -05:00
self . resize ( VIEWPORT_W , VIEWPORT_H )
2022-02-21 11:48:51 -05:00
def frame_change ( self , frame ) :
if self . movie . state ( ) != QtGui . QMovie . Running :
return
img = self . movie . currentImage ( )
2025-02-14 15:20:33 -05:00
pixmap = QtGui . QPixmap . fromImage ( img )
if not pixmap . isNull ( ) :
self . setPixmap ( pixmap . scaled ( VIEWPORT_W , VIEWPORT_H , QtCore . Qt . KeepAspectRatioByExpanding , QtCore . Qt . FastTransformation ) )
2022-02-21 11:48:51 -05:00
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 ( AO2XPpath + ' themes/default/witnesstestimony.gif ' )
elif wtce == ' testimony2 ' :
self . movie . setFileName ( AO2XPpath + ' themes/default/crossexamination.gif ' )
elif wtce == " judgeruling " :
if variant == 0 :
self . movie . setFileName ( AO2XPpath + ' themes/default/notguilty.gif ' )
elif variant == 1 :
self . movie . setFileName ( AO2XPpath + ' themes/default/guilty.gif ' )
else :
return
self . show ( )
self . movie . start ( )
2019-04-03 10:57:23 -04:00
class gui ( QtGui . QWidget ) :
2022-02-21 11:48:51 -05:00
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 = 31
m_chatmessage = [ ]
blank_blip = False
chatmessage_is_empty = False
is_additive = False
additive_char = - 1
anim_state = 3
text_state = 2
objection_state = 0
text_color = 0
charini = ConfigParser ( )
chatmsg = ' '
charid = - 1
2025-02-11 12:08:54 -05:00
2022-02-21 11:48:51 -05:00
#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 )
gotPing = QtCore . pyqtSignal ( int )
def __init__ ( self , parent = None ) :
super ( gui , self ) . __init__ ( parent )
self . gamewindow = parent
self . gotPing . connect ( self . setPing )
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 )
self . modcall = None
self . healthbars . connect ( self . netmsg_hp )
self . disconnectnow = False
self . swapping = False
self . iniswapindex = 0
self . background = ' default '
self . viewport = QtGui . QWidget ( self )
2025-02-11 12:08:54 -05:00
self . viewport . resize ( VIEWPORT_W , VIEWPORT_H )
2022-02-21 11:48:51 -05:00
self . court = QtGui . QLabel ( self . viewport )
2025-02-11 12:08:54 -05:00
self . court . resize ( VIEWPORT_W , VIEWPORT_H )
2022-02-21 11:48:51 -05:00
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 )
2025-02-11 12:08:54 -05:00
self . bench . resize ( VIEWPORT_W , VIEWPORT_H )
2022-02-21 11:48:51 -05:00
bench = QtGui . QPixmap ( AOpath + ' background/default/defensedesk.png ' )
2025-02-14 15:20:33 -05:00
court = QtGui . QPixmap ( AOpath + ' background/default/defenseempty.png ' )
if not court . isNull ( ) :
self . court . setPixmap ( court . scaled ( VIEWPORT_W , VIEWPORT_H , QtCore . Qt . KeepAspectRatioByExpanding , QtCore . Qt . FastTransformation ) )
if not bench . isNull ( ) :
self . bench . setPixmap ( bench . scaled ( VIEWPORT_W , VIEWPORT_H , QtCore . Qt . KeepAspectRatioByExpanding , QtCore . Qt . FastTransformation ) )
2022-02-21 11:48:51 -05:00
self . effectview = AOMovie ( self . viewport )
2025-02-11 12:08:54 -05:00
font_db = QtGui . QFontDatabase ( )
font_db . addApplicationFont ( AO2XPpath + ' font/Igiari.ttf ' )
font_db . addApplicationFont ( AO2XPpath + ' font/Ace_Name_Regular.ttf ' )
name_font = QtGui . QFont ( " Ace Name " )
name_font . setPointSize ( 12 )
ao2text_font = QtGui . QFont ( " Igiari " )
ao2text_font . setPointSize ( 24 )
2022-02-21 11:48:51 -05:00
self . chatbox = QtGui . QLabel ( self . viewport )
2025-02-11 12:08:54 -05:00
chatbox = QtGui . QPixmap ( AO2XPpath + ' themes/AceAttorney2x/chatbig.png ' )
#chatbox = QtGui.QPixmap(AO2XPpath + 'themes/default/chatmed.png')
2022-02-21 11:48:51 -05:00
self . chatboxheight = chatbox . size ( ) . height ( )
self . chatbox . setPixmap ( chatbox )
2025-02-11 12:08:54 -05:00
self . chatbox . move ( 0 , VIEWPORT_H - self . chatboxheight )
2022-02-21 11:48:51 -05:00
self . text = QtGui . QLabel ( self . chatbox )
self . text . setWordWrap ( True )
2025-02-11 12:08:54 -05:00
self . text . resize ( VIEWPORT_W , 96 )
2022-02-21 11:48:51 -05:00
self . text . move ( 6 , 20 )
2025-02-11 12:08:54 -05:00
self . text . setStyleSheet ( ' color: white; ' )
2022-02-21 11:48:51 -05:00
self . text . setAlignment ( QtCore . Qt . AlignLeft | QtCore . Qt . AlignTop )
self . ao2text = QtGui . QTextEdit ( self . chatbox )
self . ao2text . setFrameStyle ( QtGui . QFrame . NoFrame )
self . ao2text . setHorizontalScrollBarPolicy ( QtCore . Qt . ScrollBarAlwaysOff )
self . ao2text . setVerticalScrollBarPolicy ( QtCore . Qt . ScrollBarAlwaysOff )
self . ao2text . setReadOnly ( True )
2025-02-11 17:31:05 -05:00
self . ao2text . setGeometry ( 16 , 32 , VIEWPORT_W - 32 , 112 )
2022-02-21 11:48:51 -05:00
self . ao2text . setTextInteractionFlags ( QtCore . Qt . NoTextInteraction )
2025-02-11 12:08:54 -05:00
self . ao2text . setStyleSheet ( " background-color: rgba(0, 0, 0, 0); color: white; " )
self . ao2text . setFont ( ao2text_font )
2022-02-21 11:48:51 -05:00
self . name = QtGui . QLabel ( self . chatbox )
self . name . setStyleSheet ( ' color: white ' )
2025-02-11 17:31:05 -05:00
self . name . move ( 16 , - 1 )
2025-02-11 12:08:54 -05:00
self . name . resize ( 248 , 32 )
self . name . setFont ( name_font )
2022-02-21 11:48:51 -05:00
self . wtceview = WTCE_View ( self )
self . WTCEsignal . connect ( self . wtceview . showWTCE )
self . objectionview = AOMovie ( self . viewport )
2025-02-11 12:08:54 -05:00
self . objectionview . resize ( VIEWPORT_W , VIEWPORT_H )
self . objectionview . setScaledContents ( True )
2022-02-21 11:48:51 -05:00
self . objectionview . done . connect ( self . objection_done )
self . whiteflashlab = QtGui . QLabel ( self . viewport )
self . whiteflashlab . setPixmap ( QtGui . QPixmap ( AO2XPpath + ' themes/default/realizationflash.png ' ) )
2025-02-11 17:31:05 -05:00
self . whiteflashlab . setGeometry ( 0 , 0 , VIEWPORT_W , VIEWPORT_H )
self . whiteflashlab . setScaledContents ( True )
2022-02-21 11:48:51 -05:00
self . whiteflashlab . hide ( )
self . whiteflash = QtCore . QTimer ( )
self . whiteflash . setSingleShot ( False )
self . whiteflash . timeout . connect ( partial ( self . setWhiteFlash , False ) )
self . screenshake = QtCore . QTimer ( )
self . screenshake . timeout . connect ( self . screenShakeTick )
self . shakes_remaining = 0
self . ooclog = ChatLogs ( self , 1 )
self . ooclog . setReadOnly ( True )
self . ooclog . textChanged . connect ( self . ooclog_update )
self . oocnameinput = QtGui . QLineEdit ( self )
self . oocnameinput . setPlaceholderText ( ' Enter a name... ' )
self . oocinput = QtGui . QLineEdit ( self )
self . oocinput . setPlaceholderText ( ' Server chat/OOC chat... ' )
self . oocinput . returnPressed . connect ( self . onOOCreturn )
self . ooclogin = QtGui . QPushButton ( " Login " , self )
self . ooclogin . clicked . connect ( self . onOOCLoginBtn )
self . musicitems = QtGui . QListWidget ( self )
self . musicitems . itemDoubleClicked . connect ( self . onMusicClick )
self . gametabs = QtGui . QTabWidget ( self )
self . gametab_log = QtGui . QWidget ( ) # the IC chat log
self . gametab_evidence = QtGui . QWidget ( ) # court record
self . gametab_msgqueue = QtGui . QWidget ( ) # IC messages pending to be sent
self . gametab_iniswap = QtGui . QWidget ( ) # self explanatory
self . gametab_mute = QtGui . QWidget ( ) # mute a player
self . gametab_pair = QtGui . QWidget ( ) # AO2 pair
self . gametab_misc = QtGui . QWidget ( ) # ao2xp misc/fun stuff
2025-02-13 15:11:51 -05:00
self . gametab_players = QtGui . QWidget ( ) # client list
2022-02-21 11:48:51 -05:00
self . icLog = ChatLogs ( self . gametab_log , 0 , self . ooclog . logfile )
self . icLog . setReadOnly ( True )
self . icLog . textChanged . connect ( self . icLogChanged )
self . evidencedropdown = QtGui . QComboBox ( self . gametab_evidence )
self . evidencedropdown . currentIndexChanged . connect ( self . changeEvidence )
self . evidencedesc = QtGui . QTextEdit ( self . gametab_evidence )
self . evidencedesc . setReadOnly ( True )
self . evidenceimage = QtGui . QLabel ( self . gametab_evidence )
self . evidenceimage . setPixmap ( QtGui . QPixmap ( AOpath + ' evidence/empty.png ' ) )
self . evidenceimage . show ( )
self . evidenceadd = QtGui . QPushButton ( self . gametab_evidence )
self . evidenceadd . setText ( ' Add ' )
self . evidenceadd . clicked . connect ( self . onAddEvidence )
self . evidenceedit = QtGui . QPushButton ( self . gametab_evidence )
self . evidenceedit . setText ( ' Edit ' )
self . evidenceedit . clicked . connect ( self . onEditEvidence )
self . evidencedelete = QtGui . QPushButton ( self . gametab_evidence )
self . evidencedelete . setText ( ' Delete ' )
self . evidencedelete . clicked . connect ( self . onDeleteEvidence )
self . evidencepresent = PresentButton ( self , self . gametab_evidence )
self . msgqueueList = QtGui . QListWidget ( self . gametab_msgqueue )
self . msgqueueList . itemClicked . connect ( self . onClicked_msgqueue )
self . removeQueue = QtGui . QPushButton ( self . gametab_msgqueue )
self . removeQueue . setText ( ' Delete ' )
self . removeQueue . clicked . connect ( self . onClicked_removeQueue )
2025-02-13 15:11:51 -05:00
self . playerList = QtGui . QListWidget ( self . gametab_players )
self . playerList . itemClicked . connect ( self . onClicked_playerList )
2025-02-14 15:20:33 -05:00
self . playerPair = QtGui . QPushButton ( self . gametab_players )
self . playerPair . setText ( ' Pair ' )
self . playerPair . clicked . connect ( self . onClicked_playerPair )
2025-02-13 15:11:51 -05:00
self . playerKick = QtGui . QPushButton ( self . gametab_players )
self . playerKick . setText ( ' Kick ' )
self . playerKick . clicked . connect ( self . onClicked_playerKick )
self . playerBan = QtGui . QPushButton ( self . gametab_players )
self . playerBan . setText ( ' Ban ' )
self . playerBan . clicked . connect ( self . onClicked_playerBan )
2022-02-21 11:48:51 -05:00
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 . 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 . currentIndexChanged . connect ( self . iniswap_index_change )
self . iniswapconfirm = QtGui . QPushButton ( self . gametab_iniswap )
self . iniswapconfirm . setText ( ' Swap ' )
self . iniswapconfirm . clicked . connect ( self . iniswap_confirm )
self . iniswapreset = QtGui . QPushButton ( self . gametab_iniswap )
self . iniswapreset . setText ( ' Reset ' )
self . iniswapreset . clicked . connect ( self . resetIniSwap )
self . iniswapinfo = QtGui . QLabel ( self . gametab_iniswap )
self . iniswapinfo . setText ( ' Not swapped ' )
self . iniswaprefresh = QtGui . QPushButton ( self . gametab_iniswap )
self . iniswaprefresh . setText ( ' Refresh characters ' )
self . iniswaprefresh . clicked . connect ( self . loadSwapCharacters )
self . paircheckbox = QtGui . QCheckBox ( self . gametab_pair )
self . paircheckbox . setChecked ( False )
self . pairdropdown = QtGui . QComboBox ( self . gametab_pair )
self . pairoffset = QtGui . QSlider ( QtCore . Qt . Horizontal , self . gametab_pair )
self . pairoffset . setRange ( - 100 , 100 )
self . pairoffset . setValue ( 0 )
self . pairoffset_l = QtGui . QLabel ( " X offset " , self . gametab_pair )
self . ypairoffset = QtGui . QSlider ( QtCore . Qt . Vertical , self . gametab_pair )
self . ypairoffset . setRange ( - 100 , 100 )
self . ypairoffset . setValue ( 0 )
self . ypairoffset_l = QtGui . QLabel ( " Y offset " , self . gametab_pair )
self . pairoffsetreset = QtGui . QPushButton ( " Reset " , self . gametab_pair )
self . pairoffsetreset . clicked . connect ( self . resetOffsets )
self . pair_order = QtGui . QComboBox ( self . gametab_pair )
self . pair_order . addItem ( " Front " )
self . pair_order . addItem ( " Behind " )
self . pair_order_l = QtGui . QLabel ( " Pairing order " , self . gametab_pair )
self . misc_layout = QtGui . QVBoxLayout ( self . gametab_misc )
self . misc_layout . setAlignment ( QtCore . Qt . AlignTop )
self . mocktext = QtGui . QCheckBox ( )
self . mocktext . setChecked ( False )
self . mocktext . setText ( mockStr ( " mock text " ) )
self . spacebartext = QtGui . QCheckBox ( )
self . spacebartext . setChecked ( False )
self . spacebartext . setText ( " S p a c i n g " )
self . autocaps = QtGui . QCheckBox ( )
self . autocaps . setChecked ( False )
self . autocaps . setText ( " Automatic caps and period " )
self . misc_layout . addWidget ( self . mocktext )
self . misc_layout . addWidget ( self . spacebartext )
self . misc_layout . addWidget ( self . autocaps )
2025-02-13 15:11:51 -05:00
self . gametabs . addTab ( self . gametab_log , ' Log ' )
2022-02-21 11:48:51 -05:00
self . gametabs . addTab ( self . gametab_evidence , ' Evidence ' )
2025-02-13 15:11:51 -05:00
self . gametabs . addTab ( self . gametab_msgqueue , ' Queue ' )
self . gametabs . addTab ( self . gametab_players , ' Players ' )
2022-02-21 11:48:51 -05:00
self . gametabs . addTab ( self . gametab_mute , ' Mute ' )
2025-02-13 18:21:37 -05:00
self . gametabs . addTab ( self . gametab_iniswap , ' INI swap ' )
2022-02-21 11:48:51 -05:00
self . gametabs . addTab ( self . gametab_pair , ' Pair ' )
self . gametabs . addTab ( self . gametab_misc , ' Misc ' )
self . icchatinput = QtGui . QLineEdit ( self )
2025-02-11 12:08:54 -05:00
self . icchatinput . setGeometry ( 0 , VIEWPORT_H , VIEWPORT_W , 23 )
2022-02-21 11:48:51 -05:00
self . icchatinput . returnPressed . connect ( self . onICreturn )
self . icchatinput . setPlaceholderText ( ' Game chat ' )
self . emotedropdown = QtGui . QComboBox ( self )
2025-02-11 12:08:54 -05:00
self . emotedropdown . setGeometry ( 164 - 28 , 344 + 66 + 4 , 72 , 20 )
2022-02-21 11:48:51 -05:00
self . emotedropdown . currentIndexChanged . connect ( partial ( self . changeEmote , True ) )
self . colordropdown = QtGui . QComboBox ( self )
2025-02-11 12:08:54 -05:00
self . colordropdown . setGeometry ( self . emotedropdown . x ( ) , 376 + 64 , 72 , 20 )
2022-02-21 11:48:51 -05:00
self . colordropdown . currentIndexChanged . connect ( self . setChatColor )
self . posdropdown = QtGui . QComboBox ( self )
self . posdropdown . addItems ( [ " def " , " pro " , " wit " , " hld " , " hlp " , " jud " ] )
2025-02-11 12:08:54 -05:00
self . posdropdown . setGeometry ( self . emotedropdown . x ( ) + self . emotedropdown . size ( ) . width ( ) + 4 , self . emotedropdown . y ( ) , 72 , 20 )
2022-02-21 11:48:51 -05:00
self . posdropdown . currentIndexChanged . connect ( self . setPosition )
self . flipbutton = QtGui . QCheckBox ( self )
self . flipbutton . stateChanged . connect ( self . changeFlipCheck )
2025-02-11 17:31:05 -05:00
self . flipbutton . setText ( ' Flip ' )
2022-02-21 11:48:51 -05:00
self . flipbutton . resize ( self . flipbutton . sizeHint ( ) )
2025-02-11 12:08:54 -05:00
self . flipbutton . move ( self . posdropdown . x ( ) + self . posdropdown . width ( ) + 4 , self . colordropdown . y ( ) - 5 )
2022-02-21 11:48:51 -05:00
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 ( ) )
2025-02-11 12:08:54 -05:00
self . sfxbutton . move ( self . flipbutton . x ( ) , self . flipbutton . y ( ) + 14 )
2022-02-21 11:48:51 -05:00
self . nointerruptbtn = QtGui . QCheckBox ( self )
self . nointerruptbtn . setChecked ( False )
self . nointerruptbtn . setText ( ' No Interrupt ' )
self . nointerruptbtn . resize ( self . nointerruptbtn . sizeHint ( ) )
2025-02-11 12:08:54 -05:00
self . nointerruptbtn . move ( self . flipbutton . x ( ) + 140 , self . flipbutton . y ( ) )
2020-08-04 23:29:43 -04:00
# AO 2.8
2022-02-21 11:48:51 -05:00
self . additivebtn = QtGui . QCheckBox ( self )
self . additivebtn . setChecked ( False )
self . additivebtn . setText ( ' Additive text ' )
self . additivebtn . resize ( self . additivebtn . sizeHint ( ) )
2025-02-11 12:08:54 -05:00
self . additivebtn . move ( self . nointerruptbtn . x ( ) , self . sfxbutton . y ( ) )
2022-02-21 11:48:51 -05:00
self . additivebtn . clicked . connect ( self . onAdditiveCheck )
self . deskbtn = QtGui . QCheckBox ( self )
self . deskbtn . setChecked ( True )
self . deskbtn . setText ( ' Desk ' )
self . deskbtn . resize ( self . nointerruptbtn . sizeHint ( ) )
2025-02-11 12:08:54 -05:00
self . deskbtn . move ( self . flipbutton . x ( ) + 70 , self . flipbutton . y ( ) )
2022-02-21 11:48:51 -05:00
self . effectdropdown = QtGui . QComboBox ( self )
2025-02-11 12:08:54 -05:00
self . effectdropdown . setGeometry ( self . posdropdown . x ( ) , self . colordropdown . y ( ) , 72 , 20 )
2022-02-21 11:48:51 -05:00
self . callmodbtn = QtGui . QPushButton ( self )
self . callmodbtn . setText ( ' Call mod ' )
2025-02-11 12:08:54 -05:00
self . callmodbtn . setGeometry ( 10 , 376 + 62 , 60 , 23 )
2022-02-21 11:48:51 -05:00
self . callmodbtn . clicked . connect ( self . onClick_callMod )
self . settingsbtn = QtGui . QPushButton ( " Settings " , self )
2025-02-11 12:08:54 -05:00
self . settingsbtn . setGeometry ( self . callmodbtn . x ( ) + self . callmodbtn . size ( ) . width ( ) , 376 + 62 , self . callmodbtn . width ( ) , 23 )
2022-02-21 11:48:51 -05:00
self . settingsbtn . clicked . connect ( self . gamewindow . showSettings )
2025-02-11 12:08:54 -05:00
self . changechar = QtGui . QPushButton ( self )
self . changechar . setText ( ' Switch character ' )
self . changechar . setGeometry ( 10 , 344 + 66 + 4 , self . callmodbtn . size ( ) . width ( ) + self . settingsbtn . size ( ) . width ( ) , 23 )
self . changechar . clicked . connect ( self . onClick_changeChar )
2022-02-21 11:48:51 -05:00
2025-02-11 12:08:54 -05:00
spacing = 1
2022-02-21 11:48:51 -05:00
x_mod_count = y_mod_count = 0
2025-02-11 12:08:54 -05:00
left , top = ( 10 + 516 , 218 + 190 - 24 )
width , height = ( 288 , 98 )
2022-02-21 11:48:51 -05:00
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
2025-02-11 12:08:54 -05:00
self . prevemotepage = BackEmoteButton ( self , 520 , 253 + 190 - 28 )
2022-02-21 11:48:51 -05:00
self . prevemotepage . hide ( )
2025-02-11 12:08:54 -05:00
self . nextemotepage = NextEmoteButton ( self , 282 + 516 , 253 + 190 - 28 )
2022-02-21 11:48:51 -05:00
self . nextemotepage . show ( )
2025-02-11 12:08:54 -05:00
self . realizationbtn = buttons . AOToggleButton ( self , 265 + 164 , 192 + 304 , " realization " )
2022-02-21 11:48:51 -05:00
self . realizationbtn . clicked . connect ( self . onRealizationButton )
self . realizationsnd = audio . loadhandle ( False , AOpath + ' sounds/general/sfx-realization.wav ' , 0 , 0 , 0 )
2025-02-11 12:08:54 -05:00
self . shakebtn = buttons . AOToggleButton ( self , 265 + 42 + 164 , 192 + 304 , " screenshake " ) # AO 2.8
self . customobject = buttons . CustomObjection ( self , 250 + 516 - 30 , 312 + 40 )
self . takethatbtn = buttons . Objections ( self , 170 + 516 - 20 , 312 + 40 , 3 )
self . objectbtn = buttons . Objections ( self , 90 + 516 - 10 , 312 + 40 , 2 )
self . holditbtn = buttons . Objections ( self , 10 + 516 , 312 + 40 , 1 )
2025-02-13 22:22:55 -05:00
self . objectsnd = 0
2022-02-21 11:48:51 -05:00
self . defensebar = buttons . PenaltyBars ( self , 1 )
self . prosecutionbar = buttons . PenaltyBars ( self , 2 )
2025-02-11 12:08:54 -05:00
self . defensebar . moveBar ( 265 + 164 , 164 + 304 )
self . prosecutionbar . moveBar ( 265 + 164 , 178 + 304 )
2022-02-21 11:48:51 -05:00
self . defensebar . minusClicked . connect ( self . penaltyBarMinus )
self . defensebar . plusClicked . connect ( self . penaltyBarPlus )
self . prosecutionbar . minusClicked . connect ( self . penaltyBarMinus )
self . prosecutionbar . plusClicked . connect ( self . penaltyBarPlus )
2025-02-11 12:08:54 -05:00
self . wtcebtn_1 = buttons . WTCEbuttons ( self , 429 , 544 , 0 )
self . wtcebtn_2 = buttons . WTCEbuttons ( self , self . wtcebtn_1 . x ( ) , self . wtcebtn_1 . y ( ) + self . wtcebtn_1 . size ( ) . height ( ) , 1 )
self . notguiltybtn = buttons . WTCEbuttons ( self , self . wtcebtn_1 . x ( ) , self . wtcebtn_2 . y ( ) + self . wtcebtn_2 . size ( ) . height ( ) , 2 , 0 )
self . guiltybtn = buttons . WTCEbuttons ( self , self . wtcebtn_1 . x ( ) , self . notguiltybtn . y ( ) + self . notguiltybtn . size ( ) . height ( ) , 2 , 1 )
2022-02-21 11:48:51 -05:00
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 )
2025-02-12 18:30:18 -05:00
self . presentedevi . setGeometry ( 16 , 16 , 140 , 140 )
2022-02-21 11:48:51 -05:00
self . presentedevi . hide ( )
self . showname = " "
self . shownameedit = QtGui . QLineEdit ( self )
self . shownameedit . textChanged . connect ( self . onChangeShowname )
2025-02-11 12:08:54 -05:00
self . shownameedit . setGeometry ( self . posdropdown . x ( ) + self . posdropdown . width ( ) + 4 , self . posdropdown . y ( ) , 168 + 56 , 20 )
2022-02-21 11:48:51 -05:00
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 . 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 . pinglabel = QtGui . QLabel ( self )
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 '
2025-02-12 18:30:18 -05:00
self . lastmsg = ' '
2022-02-21 11:48:51 -05:00
self . msgqueue = [ ]
self . selectedmsg = - 1
self . evidence = [ ]
self . selectedevi = - 1
self . present = False
2025-02-13 15:11:51 -05:00
self . playerlist = { }
self . selectedplayer = - 1
2022-02-21 11:48:51 -05:00
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 )
2025-02-12 22:49:55 -05:00
2025-02-13 01:32:56 -05:00
self . wtcesfx = 0
self . guiltysfx = 0
self . notguiltysfx = 0
2025-02-14 13:00:19 -05:00
self . stream = 0
2025-02-14 17:35:05 -05:00
self . specialstream = 0
2025-02-14 13:00:19 -05:00
self . download_thread = None
2022-02-21 11:48:51 -05:00
def resetOffsets ( self ) :
self . pairoffset . setValue ( 0 )
self . ypairoffset . setValue ( 0 )
def screenShakeTick ( self ) :
self . shakes_remaining - = 1
shakeforce = 8
if self . shakes_remaining :
self . court . move ( random . randint ( - shakeforce , shakeforce ) , random . randint ( - shakeforce , shakeforce ) )
self . zoom . move ( random . randint ( - shakeforce , shakeforce ) , random . randint ( - shakeforce , shakeforce ) )
self . char . move ( self . char . xx + random . randint ( - shakeforce , shakeforce ) , self . char . yy + random . randint ( - shakeforce , shakeforce ) , True )
self . sidechar . move ( self . sidechar . xx + random . randint ( - shakeforce , shakeforce ) , self . sidechar . yy + random . randint ( - shakeforce , shakeforce ) , True )
2025-02-11 17:31:05 -05:00
self . chatbox . move ( random . randint ( - shakeforce , shakeforce ) , VIEWPORT_H - self . chatboxheight + random . randint ( - shakeforce , shakeforce ) )
self . ao2text . move ( - self . chatbox . x ( ) + 16 , ( VIEWPORT_H - self . chatboxheight - self . chatbox . y ( ) ) + 32 )
self . text . move ( - self . chatbox . x ( ) + 16 , ( VIEWPORT_H - self . chatboxheight - self . chatbox . y ( ) ) + - 1 )
2022-02-21 11:48:51 -05:00
else :
self . court . move ( 0 , 0 )
self . zoom . move ( 0 , 0 )
self . char . move ( self . char . xx , self . char . yy , True )
self . sidechar . move ( self . sidechar . xx , self . sidechar . yy , True )
2025-02-11 17:31:05 -05:00
self . chatbox . move ( 0 , VIEWPORT_H - self . chatboxheight )
self . ao2text . move ( 16 , 32 )
self . text . move ( 16 , - 1 )
2022-02-21 11:48:51 -05:00
self . screenshake . stop ( )
def onAdditiveCheck ( self ) :
if self . additivebtn . isChecked ( ) :
self . icchatinput . home ( False )
self . icchatinput . insert ( " " )
self . icchatinput . end ( False )
self . icchatinput . setFocus ( )
def onRealizationButton ( self ) :
if self . realizationbtn . isPressed ( ) :
self . effectdropdown . setCurrentIndex ( 1 ) # realization
elif self . effectdropdown . currentText ( ) == " realization " :
self . effectdropdown . setCurrentIndex ( 0 )
def onOOCLoginBtn ( self ) :
password , ok = QtGui . QInputDialog . getText ( self , " Login as moderator " , " Enter password. " )
if password and ok :
2025-02-11 17:31:05 -05:00
self . sendOOCchat ( self . oocnameinput . text ( ) . toUtf8 ( ) , " /login " )
self . sendOOCchat ( self . oocnameinput . text ( ) . toUtf8 ( ) , password . toUtf8 ( ) )
2022-02-21 11:48:51 -05:00
def setPing ( self , newping ) :
self . pinglabel . setText ( " Ping: %d " % newping )
def setPosition ( self , ind ) :
if not self . oocnameinput . text ( ) :
self . oocnameinput . setText ( " unnamed " )
self . posdropdown . setCurrentIndex ( ind )
self . charside = str ( self . posdropdown . itemText ( ind ) )
self . setJudgeButtons ( )
server_is_2_8 = " additive " in self . features and " looping_sfx " in self . features and " effects " in self . features
if server_is_2_8 :
self . tcp . send ( " SP# " + self . charside + " # % " ) # all hail new AO 2.8 packet
else :
self . sendOOCchat ( self . oocnameinput . text ( ) . toUtf8 ( ) , " /pos " + self . charside )
def changeMusicVolume ( self , value ) :
if self . music :
audio . sethandleattr ( self . music , BASS_ATTRIB_VOL , value / 100.0 )
def changeSoundVolume ( self , value ) :
if self . sound :
audio . sethandleattr ( self . sound , BASS_ATTRIB_VOL , value / 100.0 )
audio . sethandleattr ( self . realizationsnd , BASS_ATTRIB_VOL , value / 100.0 )
2025-02-13 01:32:56 -05:00
audio . sethandleattr ( self . wtcesfx , BASS_ATTRIB_VOL , value / 100.0 )
audio . sethandleattr ( self . guiltysfx , BASS_ATTRIB_VOL , value / 100.0 )
audio . sethandleattr ( self . notguiltysfx , BASS_ATTRIB_VOL , value / 100.0 )
2022-02-21 11:48:51 -05:00
if self . modcall :
audio . sethandleattr ( self . modcall , BASS_ATTRIB_VOL , value / 100.0 )
def changeBlipVolume ( self , value ) :
if self . blipsnd :
audio . sethandleattr ( 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 ( ) )
2025-02-12 18:30:18 -05:00
def setEvidenceImg ( self , guiobj , image , scale = False ) :
2022-02-21 11:48:51 -05:00
if exists ( AOpath + ' evidence/ ' + image ) :
2025-02-14 15:20:33 -05:00
img = QtGui . QPixmap ( AOpath + " evidence/ %s " % image )
if not img . isNull ( ) and scale :
guiobj . setPixmap ( img . scaled ( 140 , 140 , QtCore . Qt . KeepAspectRatioByExpanding , QtCore . Qt . FastTransformation ) )
2025-02-12 18:30:18 -05:00
else :
2025-02-14 15:20:33 -05:00
guiobj . setPixmap ( img )
2022-02-21 11:48:51 -05:00
else :
2025-02-14 15:20:33 -05:00
img = QtGui . QPixmap ( AO2XPpath + ' themes/default/evidence_selected.png ' )
if not img . isNull ( ) and scale :
guiobj . setPixmap ( img . scaled ( 140 , 140 , QtCore . Qt . KeepAspectRatioByExpanding , QtCore . Qt . FastTransformation ) )
2025-02-12 18:30:18 -05:00
else :
2025-02-14 15:20:33 -05:00
guiobj . setPixmap ( img )
2025-02-12 18:30:18 -05:00
2022-02-21 11:48:51 -05:00
if ini . read_ini_bool ( " AO2XP.ini " , " General " , " download evidence " , True ) :
url = " base/evidence/ " + 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 \n how does it feel? ' )
if self . muteselected == - 1 :
return QtGui . QMessageBox . warning ( self , ' hey genius ' , ' who exactly are you muting? \n click 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 \n bet 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? \n click 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 setScreenShake ( self , on , amount = 20 ) :
self . shakes_remaining = amount if on else 1
self . screenshake . start ( 25 )
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 onPVPacket ( self , charname ) :
exec open ( AO2XPpath + " ao2xp_themes/ " + get_option ( " General " , " theme " , " default " ) + " /theme.py " )
if not self . swapping :
self . loadCharacter ( charname )
def loadCharacter ( self , charname ) :
self . msgqueueList . clear ( )
self . msgqueue = [ ]
self . effectdropdown . clear ( )
self . emotedropdown . clear ( )
self . charemotes = [ ]
self . selectedemote = 0
self . current_emote_page = 0
2025-02-12 18:30:18 -05:00
2022-02-21 11:48:51 -05:00
effectslist = ini . get_effects ( charname )
self . effectdropdown . setVisible ( bool ( effectslist ) )
if effectslist :
effectslist . insert ( 0 , " No effect " )
self . effectdropdown . addItems ( effectslist )
2025-02-12 22:31:36 -05:00
charname = unicode ( charname )
self . charname = unicode ( ini . read_ini ( AOpath + ' characters/ ' + charname + ' /char.ini ' , " options " , " name " , charname ) , " utf-8 " )
2022-02-21 11:48:51 -05:00
self . charside = ini . read_ini ( AOpath + ' characters/ ' + charname + ' /char.ini ' , " options " , " side " , " def " )
2025-02-12 22:31:36 -05:00
2022-02-21 11:48:51 -05:00
self . posdropdown . setCurrentIndex ( self . posdropdown . findText ( self . charside ) )
self . setJudgeButtons ( )
2025-02-12 22:31:36 -05:00
2022-02-21 11:48:51 -05:00
for emoteind in range ( 1 , ini . read_ini_int ( AOpath + " characters/ " + self . charname + " /char.ini " , " emotions " , " number " ) + 1 ) :
if emoteind == 1 :
suffix = ' on '
else :
suffix = ' off '
emote = ini . read_ini ( AOpath + ' characters/ ' + charname + ' /char.ini ' , " emotions " , str ( emoteind ) , ' normal#(a)normal#normal#0# ' )
sound = ini . read_ini ( AOpath + ' characters/ ' + charname + ' /char.ini ' , " soundn " , str ( emoteind ) , ' 1 ' )
soundt = ini . read_ini ( AOpath + ' characters/ ' + charname + ' /char.ini ' , " soundt " , str ( emoteind ) , ' 0 ' )
soundl = ini . read_ini ( AOpath + ' characters/ ' + charname + ' /char.ini ' , " soundl " , str ( emoteind ) , ' 0 ' ) # AO 2.8
emotelist = emote . split ( ' # ' )
del emotelist [ len ( emotelist ) - 1 ]
emotelist . append ( sound )
emotelist . append ( soundt )
emotelist . append ( soundl ) # AO 2.8
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 set_emote_page ( self ) :
if self . mychar < 0 :
return
self . prevemotepage . hide ( )
self . nextemotepage . hide ( )
total_emotes = ini . read_ini_int ( AOpath + " characters/ " + self . charname + " /char.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 :
2025-02-12 22:31:36 -05:00
image = QtGui . QPixmap ( AOpath + ' characters/ ' + self . charname + ' /emotions/button ' + str ( n_real_emote + 1 ) + ' _on.png ' )
else :
image = QtGui . QPixmap ( AOpath + ' characters/ ' + self . charname + ' /emotions/button ' + str ( n_real_emote + 1 ) + ' _off.png ' )
2025-02-14 15:20:33 -05:00
if not image . isNull ( ) and image . width ( ) > 40 :
2025-02-12 22:31:36 -05:00
self . emotebuttons [ n_emote ] . setPixmap ( image . scaled ( 40 , 40 , QtCore . Qt . IgnoreAspectRatio , QtCore . Qt . FastTransformation ) )
2022-02-21 11:48:51 -05:00
else :
2025-02-12 22:31:36 -05:00
self . emotebuttons [ n_emote ] . setPixmap ( image )
2022-02-21 11:48:51 -05:00
self . emotebuttons [ n_emote ] . show ( )
def iniswap_index_change ( self , ind ) :
self . iniswapindex = ind
def loadSwapCharacters ( self ) :
self . charsfolder = [ ]
self . iniswaplist . clear ( )
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 . resetIniSwap ( )
else :
self . swapping = True
self . iniswapinfo . setText ( ' Swapped to ' + self . charsfolder [ self . iniswapindex ] )
self . loadCharacter ( self . charsfolder [ self . iniswapindex ] )
def resetIniSwap ( self ) :
self . swapping = False
self . iniswapinfo . setText ( ' Not swapped ' )
self . loadCharacter ( self . charlist [ self . mychar ] [ 0 ] )
def onAddEvidence ( self ) :
self . evidence_editor . show ( )
def onEditEvidence ( self ) :
if not self . evidence :
2025-02-13 16:36:10 -05:00
return QtGui . QMessageBox . information ( self , ' No evidence ' , " There ' s no evidence on the court record. " )
2022-02-21 11:48:51 -05:00
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 . toUtf8 ( ) + " # % " )
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
2025-02-13 15:11:51 -05:00
def onClicked_playerList ( self , item ) :
for i in range ( len ( self . playerList ) ) :
sel = self . playerList . item ( i )
if sel == item :
s = sel . text ( )
self . selectedplayer = s [ 1 : s . indexOf ( " ] " ) ]
2022-02-21 11:48:51 -05:00
def onClicked_removeQueue ( self ) :
if self . selectedmsg == - 1 :
2025-02-13 15:11:51 -05:00
return QtGui . QMessageBox . warning ( self , ' Nothing selected ' , ' Select a message from the list to remove it. ' )
2022-02-21 11:48:51 -05:00
if len ( self . msgqueueList ) == 0 :
2025-02-13 15:11:51 -05:00
return QtGui . QMessageBox . warning ( self , " Can ' t remove " , ' There are no messages in the message queue. \n Enter a message on the Game chat to add one. ' )
2022-02-21 11:48:51 -05:00
self . msgqueueList . takeItem ( self . selectedmsg )
del self . msgqueue [ self . selectedmsg ]
2025-02-14 15:20:33 -05:00
def onClicked_playerPair ( self ) :
if not self . selectedplayer == - 1 :
self . gametabs . setCurrentWidget ( self . gametab_pair )
self . paircheckbox . setChecked ( True )
char = self . playerlist [ str ( self . selectedplayer ) ] [ 1 ]
if char == ' ' :
return QtGui . QMessageBox . warning ( self , " Unable to pair " , ' That player has no character selected. ' )
else :
self . pairdropdown . setCurrentIndex ( [ c [ 0 ] for c in self . charlist ] . index ( char ) )
else :
return QtGui . QMessageBox . warning ( self , ' No player selected ' , ' Select a player from the list to attempt pairing. ' )
2025-02-13 15:11:51 -05:00
def onClicked_playerKick ( self ) :
if not self . selectedplayer == - 1 :
reason , ok = QtGui . QInputDialog . getText ( self , " Kick a player " , " Please enter the reason. " , text = " Being annoying " )
if reason and ok :
self . tcp . send ( " MA# %s #0# %s # %% " % ( self . selectedplayer , reason ) )
2025-02-14 15:20:33 -05:00
else :
return QtGui . QMessageBox . warning ( self , ' No player selected ' , ' Select a player from the list to kick. ' )
2025-02-13 15:11:51 -05:00
def onClicked_playerBan ( self ) :
if not self . selectedplayer == - 1 :
reason , ok = QtGui . QInputDialog . getText ( self , " Ban a player " , " Please enter the reason. " , text = " Being annoying " )
if reason and ok :
duration , ok = QtGui . QInputDialog . getInt ( self , " Ban a player " , " Please enter the ban length in minutes. " , 60 , 1 )
if duration and ok :
self . tcp . send ( " MA# %s # %s # %s # %% " % ( self . selectedplayer , duration , reason ) )
2025-02-14 15:20:33 -05:00
else :
return QtGui . QMessageBox . warning ( self , ' No player selected ' , ' Select a player from the list to ban. ' )
2022-02-21 11:48:51 -05:00
def changeEvidence ( self , ind ) :
if ind < 0 :
return
self . selectedevi = ind
self . evidencedesc . setText ( self . evidence [ ind ] [ 1 ] )
self . setEvidenceImg ( self . evidenceimage , self . evidence [ ind ] [ 2 ] )
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 :
2025-02-12 18:30:18 -05:00
button . path = AOpath + ' characters/ ' + self . charname + ' /emotions/button ' + str ( button . emoteid + self . current_emote_page * self . max_emotes_on_page + 1 )
2025-02-12 22:31:36 -05:00
image = QtGui . QPixmap ( button . path + ' _on.png ' )
else :
image = QtGui . QPixmap ( AOpath + ' characters/ ' + self . charname + ' /emotions/button ' + str ( button . emoteid + self . current_emote_page * self . max_emotes_on_page + 1 ) + ' _off.png ' )
2025-02-14 15:20:33 -05:00
if not image . isNull ( ) and image . width ( ) > 40 :
2025-02-12 22:31:36 -05:00
button . setPixmap ( image . scaled ( 40 , 40 , QtCore . Qt . IgnoreAspectRatio , QtCore . Qt . FastTransformation ) )
2022-02-21 11:48:51 -05:00
else :
2025-02-12 22:31:36 -05:00
button . setPixmap ( image )
2022-02-21 11:48:51 -05:00
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 :
2025-02-14 14:16:51 -05:00
self . tcp . send ( ' MC# ' + item . text ( ) + ' # ' + str ( self . mychar ) + ' # ' + self . showname + ' # % ' )
2022-02-21 11:48:51 -05:00
else :
2025-02-14 14:16:51 -05:00
self . tcp . send ( ' MC# ' + item . text ( ) + ' # ' + str ( self . mychar ) + ' # % ' )
2022-02-21 11:48:51 -05:00
def icLogChanged ( self ) :
if self . icLog . verticalScrollBar ( ) . value ( ) == self . icLog . verticalScrollBar ( ) . maximum ( ) : self . icLog . verticalScrollBar ( ) . setValue ( self . icLog . verticalScrollBar ( ) . maximum ( ) )
def ooclog_update ( self ) :
if self . ooclog . verticalScrollBar ( ) . value ( ) == self . ooclog . verticalScrollBar ( ) . maximum ( ) : 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 ( ' # ' , ' <num> ' ) . replace ( ' % ' , ' <percent> ' ) . replace ( ' & ' , ' <and> ' ) . replace ( ' $ ' , ' <dollar> ' ) . replace ( ' \\ n ' , ' \n ' )
if text . startsWith ( ' // ' ) :
code = str ( self . oocinput . text ( ) ) . replace ( ' // ' , ' ' , 1 ) . 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
elif text . startsWith ( " /pos " ) : # why.......
ind = self . posdropdown . findText ( str ( text . split ( " " ) [ 1 ] ) )
if ind > = 0 : self . posdropdown . setCurrentIndex ( ind )
self . oocinput . clear ( )
return
if self . mocktext . isChecked ( ) :
text = mockStr ( text )
if self . autocaps . isChecked ( ) :
l = list ( text )
l [ 0 ] = l [ 0 ] . upper ( )
if l [ - 1 ] != " . " :
l . append ( " . " )
text = " " . join ( l ) . replace ( " i " , " I " ) . replace ( " i ' m " , " I ' m " ) . replace ( " it ' s " , " It ' s " )
self . sendOOCchat ( self . oocnameinput . text ( ) . toUtf8 ( ) , text )
self . oocinput . clear ( )
def onICreturn ( self ) :
text = str ( self . icchatinput . text ( ) . toUtf8 ( ) ) . replace ( ' # ' , ' <num> ' ) . replace ( ' % ' , ' <percent> ' ) . replace ( ' & ' , ' <and> ' ) . replace ( ' $ ' , ' <dollar> ' ) . replace ( ' /n ' , ' \n ' )
2025-02-14 22:02:33 -05:00
#if not text:
# return
2022-02-21 11:48:51 -05:00
if self . mocktext . isChecked ( ) :
text = mockStr ( text )
if self . autocaps . isChecked ( ) :
l = list ( text )
l [ 0 ] = l [ 0 ] . upper ( )
if l [ - 1 ] != " . " :
l . append ( " . " )
text = " " . join ( l ) . replace ( " i " , " I " ) . replace ( " i ' m " , " I ' m " ) . replace ( " it ' s " , " It ' s " )
if self . spacebartext . isChecked ( ) :
l = list ( text )
for i in range ( 1 , len ( l ) + len ( l ) - 1 , 2 ) :
l . insert ( i , " " )
text = " " . join ( l )
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# "
if " deskmod " in self . features : # visible desk modifier
msg + = " %d # " % self . deskbtn . isChecked ( )
else :
msg + = " chat# "
msg + = emote [ 1 ] + " # " #pre-anim
msg + = self . charname + " # "
msg + = emote [ 2 ] + " # " #anim
2025-02-12 22:31:36 -05:00
msg + = text . decode ( ' utf-8 ' ) + " # "
2022-02-21 11:48:51 -05:00
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
if " effects " in self . features :
msg + = " ^ %d # " % self . pair_order . currentIndex ( ) # pair ordering
else :
msg + = " # "
else :
msg + = " -1# "
# AO 2.8: always send offset
if " y_offset " in self . features : # AO 2.9
msg + = str ( self . pairoffset . value ( ) ) + " & " + str ( - self . ypairoffset . value ( ) ) + " # "
else :
msg + = str ( self . pairoffset . value ( ) ) + " # "
msg + = str ( int ( self . nointerruptbtn . isChecked ( ) ) ) + " # " # NoInterrupt(TM)
if " looping_sfx " in self . features : # AO 2.8
msg + = emote [ 6 ] + " # " # loop sound?
msg + = " %d # " % self . shakebtn . isPressed ( ) # screen shake
emotes_to_check = [ emote [ 1 ] , " (b) " + emote [ 2 ] , " (a) " + emote [ 2 ] ]
effects_to_check = [ " _FrameScreenshake " , " _FrameRealization " , " _FrameSFX " ]
for f_effect in effects_to_check :
packet = " "
for f_emote in emotes_to_check :
packet + = f_emote
if ini . read_ini_bool ( " AO2XP.ini " , " General " , " network frame effects " ) :
sfx_frames = " | " . join ( ini . read_ini_tags ( AOpath + " characters/ " + self . charname + " /char.ini " , f_emote + f_effect ) )
if sfx_frames :
packet + = " | " + sfx_frames
packet + = " ^ "
msg + = packet + " # "
if " additive " in self . features :
msg + = " %d # " % self . additivebtn . isChecked ( )
if " effects " in self . features :
fx = self . effectdropdown . currentText ( ) if self . effectdropdown . currentIndex ( ) > 0 else " "
fx_sound = ini . get_effect_sound ( fx , self . charname )
p_effect = ini . read_ini ( AOpath + " characters/ " + self . charname + " /char.ini " , " options " , " effects " )
2025-02-12 18:30:18 -05:00
# I have to encode it because otherwise accented characters make the client crash
msg + = str ( fx + " | " + p_effect + " | " + fx_sound + " # " ) . encode ( ' utf-8 ' )
2022-02-21 11:48:51 -05:00
self . effectdropdown . setCurrentIndex ( 0 )
msg + = " % "
2025-02-12 18:30:18 -05:00
# Avoid duplicate messages
if self . lastmsg != msg :
self . msgqueueList . addItem ( self . icchatinput . text ( ) )
self . msgqueue . append ( msg )
self . lastmsg = msg
2022-02-21 11:48:51 -05:00
self . icchatinput . clear ( )
self . realizationbtn . setPressed ( False )
self . shakebtn . setPressed ( False )
def setBackground ( self , bg ) :
if not exists ( AOpath + ' background/ ' + bg ) :
bg = ' default '
for bgfile in [ [ " side_def " , " defenseempty " ] ,
2021-05-26 22:02:16 -04:00
[ " bench_def " , " defensedesk " ] ,
[ " side_pro " , " prosecutorempty " ] ,
[ " bench_pro " , " prosecutiondesk " ] ,
[ " side_wit " , " witnessempty " ] ,
[ " bench_wit " , " stand " ] ,
[ " side_hld " , " helperstand " ] ,
[ " bench_hld " , " helperdesk " ] ,
[ " side_hlp " , " prohelperstand " ] ,
[ " bench_hlp " , " prohelperdesk " ] ,
[ " side_jud " , " judgestand " ] ,
[ " bench_jud " , " judgedesk " ] ,
[ " side_jur " , " jurystand " ] ,
[ " bench_jur " , " jurydesk " ] ,
[ " side_sea " , " seancestand " ] ,
[ " bench_sea " , " seancedesk " ] ] :
2022-02-21 11:48:51 -05:00
bgimg = QtGui . QImage ( AOpath + ' background/ ' + bg + ' / ' + bgfile [ 1 ] + ' .png ' )
if not bgimg . isNull ( ) :
2025-02-11 12:08:54 -05:00
if bgimg . size ( ) . width ( ) != VIEWPORT_W or bgimg . size ( ) . height ( ) != VIEWPORT_H :
2025-02-11 17:31:05 -05:00
setattr ( self , bgfile [ 0 ] , QtGui . QPixmap . fromImage ( bgimg . scaled ( VIEWPORT_W , VIEWPORT_H , QtCore . Qt . KeepAspectRatioByExpanding , QtCore . Qt . FastTransformation ) ) )
2022-02-21 11:48:51 -05:00
else :
setattr ( self , bgfile [ 0 ] , QtGui . QPixmap . fromImage ( bgimg ) )
else :
setattr ( self , bgfile [ 0 ] , QtGui . QPixmap . fromImage ( bgimg ) )
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
if int ( p_contents [ CHAR_ID ] ) in self . muted : # skip the self.chatmessage copy line below
return
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 ) :
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 :
2025-02-12 22:31:36 -05:00
chatmsgcomp = ( self . msgqueue [ 0 ] . split ( ' # ' ) [ 5 ] ) . replace ( ' <dollar> ' , ' $ ' ) . replace ( ' <percent> ' , ' % ' ) . replace ( ' <and> ' , ' & ' ) . replace ( ' <num> ' , ' # ' )
2025-02-11 17:31:05 -05:00
if ( chatmsgcomp == ' > ' or chatmsgcomp == ' < ' ) or ( f_char_id == self . mychar and self . m_chatmessage [ CHATMSG ] == chatmsgcomp ) : # our message showed up
2022-02-21 11:48:51 -05:00
del self . msgqueue [ 0 ]
self . msgqueueList . takeItem ( 0 )
if self . additivebtn . isChecked ( ) :
self . icchatinput . insert ( " " )
2025-02-13 16:36:10 -05:00
f_char = self . m_chatmessage [ CHARNAME ] . decode ( " utf-8 " )
2022-02-21 11:48:51 -05:00
evidence = int ( self . m_chatmessage [ EVIDENCE ] ) - 1
t = time . localtime ( )
2025-02-13 16:36:10 -05:00
logcharname = f_char
2025-02-12 22:49:55 -05:00
#TODO: UnicodeWarning: Unicode unequal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
#if f_char.lower() != self.charlist[f_char_id][0].lower():
# logcharname = self.charlist[f_char_id][0] + ' (' + f_char.decode("utf-8") + ')'
2022-02-21 11:48:51 -05:00
if self . m_chatmessage [ SHOWNAME ] :
try :
2025-02-13 18:21:37 -05:00
logcharname + = " ( " + self . m_chatmessage [ SHOWNAME ] . decode ( ' utf-8 ' ) + " ) "
2022-02-21 11:48:51 -05:00
except :
logcharname + = " (???) "
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 ) )
self . is_additive = ( self . m_chatmessage [ ADDITIVE ] == " 1 " )
custom_objection = " custom "
try : objection_mod = int ( self . m_chatmessage [ SHOUT_MOD ] )
except :
if " 4& " in self . m_chatmessage [ SHOUT_MOD ] : # custom objection name
objection_mod = 4
custom_objection = self . m_chatmessage [ SHOUT_MOD ] . split ( " 4& " ) [ 1 ] # get the name
else : # just in case of mindfuckery
objection_mod = 0
if objection_mod < = 4 and objection_mod > = 1 :
objections = [ " holdit " , " objection " , " takethat " , " custom_objections/ " + custom_objection if custom_objection != " custom " else " custom " ]
self . objectionview . play ( objections [ objection_mod - 1 ] , 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 ] )
2025-02-14 15:46:12 -05:00
#is_rainbow = textcolor == 6
2022-02-21 11:48:51 -05:00
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 , 192 , 203 )
2025-02-14 15:46:12 -05:00
elif textcolor == 7 :
2022-02-21 11:48:51 -05:00
color = QtGui . QColor ( 0 , 255 , 255 )
2025-02-14 15:46:12 -05:00
elif textcolor == 8 :
color = QtGui . QColor ( 200 , 200 , 200 )
2022-02-21 11:48:51 -05:00
2025-02-14 15:46:12 -05:00
# if is_rainbow:
# self.text.show()
# self.ao2text.hide()
# else:
self . text . hide ( )
self . ao2text . show ( )
2022-02-21 11:48:51 -05:00
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 )
2025-02-11 12:08:54 -05:00
self . bench . move ( 0 , VIEWPORT_H - self . bench_def . size ( ) . height ( ) )
2022-02-21 11:48:51 -05:00
self . presentedevi . move ( 170 , 16 )
elif side == ' pro ' :
self . court . setPixmap ( self . side_pro )
self . bench . setPixmap ( self . bench_pro )
2025-02-11 12:08:54 -05:00
self . bench . move ( VIEWPORT_W - self . bench_pro . size ( ) . width ( ) , VIEWPORT_H - self . bench_pro . size ( ) . height ( ) )
2022-02-21 11:48:51 -05:00
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 . presentedevi . move ( 16 , 16 )
elif side == ' hld ' :
self . court . setPixmap ( self . side_hld )
self . bench . setPixmap ( self . bench_hld )
self . presentedevi . move ( 16 , 16 )
elif side == ' hlp ' :
self . court . setPixmap ( self . side_hlp )
self . bench . setPixmap ( self . bench_hlp )
self . presentedevi . move ( 170 , 16 )
elif side == ' jud ' :
self . court . setPixmap ( self . side_jud )
self . bench . setPixmap ( self . bench_jud )
self . presentedevi . move ( 16 , 16 )
elif side == ' sea ' :
self . court . setPixmap ( self . side_jud if self . side_sea . isNull ( ) else self . side_sea )
self . bench . setPixmap ( self . bench_jud if self . bench_sea . isNull ( ) else self . bench_sea )
self . presentedevi . move ( 16 , 16 )
elif side == ' jur ' :
self . court . setPixmap ( self . side_jud if self . side_jur . isNull ( ) else self . side_jur )
self . bench . setPixmap ( self . bench_jud if self . bench_jur . isNull ( ) else self . bench_jur )
self . presentedevi . move ( 16 , 16 )
deskmod = self . m_chatmessage [ DESK_MOD ]
if deskmod == " 0 " or ( deskmod != " 1 " and ( side in ( " jud " , " hld " , " hlp " ) ) ) :
self . bench . hide ( )
else :
self . bench . show ( )
def objection_done ( self ) :
self . handle_chatmessage_2 ( )
def handle_chatmessage_2 ( self ) :
self . zoom . setZoom ( False )
self . char . stop ( )
self . effectview . stop ( )
if not self . m_chatmessage [ SHOWNAME ] :
2025-02-12 22:31:36 -05:00
self . name . setText ( self . m_chatmessage [ CHARNAME ] . decode ( " utf-8 " ) )
2022-02-21 11:48:51 -05:00
else :
self . name . setText ( self . m_chatmessage [ SHOWNAME ] . decode ( " utf-8 " ) )
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 ] )
# AO 2.8: always offset player
hor_offset = vert_offset = 0
if " y_offset " in self . features : # AO 2.9
keyword = " <and> " if " <and> " in self . m_chatmessage [ SELF_OFFSET ] else " & " # i don't think it's hdf's fault but this is still ridiculous
hor_offset = int ( self . m_chatmessage [ SELF_OFFSET ] . split ( keyword ) [ 0 ] )
vert_offset = int ( self . m_chatmessage [ SELF_OFFSET ] . split ( keyword ) [ 1 ] ) if len ( self . m_chatmessage [ SELF_OFFSET ] . split ( keyword ) ) > 1 else 0
else :
hor_offset = int ( self . m_chatmessage [ SELF_OFFSET ] )
2025-02-14 11:31:54 -05:00
2022-02-21 11:48:51 -05:00
if side == " def " :
if hor_offset > 0 and vert_offset == 0 :
vert_offset = hor_offset / 10
elif side == " pro " :
if hor_offset < 0 and vert_offset == 0 :
vert_offset = - 1 * hor_offset / 10
2025-02-14 15:20:33 -05:00
self . char . move ( VIEWPORT_W * hor_offset / 100 , VIEWPORT_H * vert_offset / 100 )
2022-02-21 11:48:51 -05:00
# check if paired
if not self . m_chatmessage [ OTHER_CHARID ] :
self . sidechar . hide ( )
self . sidechar . move ( 0 , 0 )
else :
if " effects " in self . features :
got_other_charid = int ( self . m_chatmessage [ OTHER_CHARID ] . split ( " ^ " ) [ 0 ] )
else :
got_other_charid = int ( self . m_chatmessage [ OTHER_CHARID ] )
if got_other_charid > - 1 : # user is paired
self . sidechar . show ( )
if " effects " in self . features :
pair_order = int ( self . m_chatmessage [ OTHER_CHARID ] . split ( " ^ " ) [ 1 ] )
else :
pair_order = - 1
hor2_offset = vert2_offset = 0
if " y_offset " in self . features : # AO 2.9
keyword = " <and> " if " <and> " in self . m_chatmessage [ OTHER_OFFSET ] else " & " # i don't think it's hdf's fault but this is still ridiculous
hor2_offset = int ( self . m_chatmessage [ OTHER_OFFSET ] . split ( keyword ) [ 0 ] )
vert2_offset = int ( self . m_chatmessage [ OTHER_OFFSET ] . split ( keyword ) [ 1 ] ) if len ( self . m_chatmessage [ OTHER_OFFSET ] . split ( keyword ) ) > 1 else 0
else :
hor2_offset = int ( self . m_chatmessage [ OTHER_OFFSET ] )
if side == " def " :
if hor2_offset > 0 :
vert2_offset = hor2_offset / 10
elif side == " pro " :
if hor2_offset < 0 :
vert2_offset = - 1 * hor2_offset / 10
if pair_order == - 1 : # pair ordering not supported
if hor2_offset > = hor_offset :
self . sidechar . raise_ ( )
self . char . raise_ ( )
else :
self . char . raise_ ( )
self . sidechar . raise_ ( )
elif pair_order == 0 : # front
self . sidechar . raise_ ( )
2025-02-14 15:20:33 -05:00
self . char . raise_ ( )
2022-02-21 11:48:51 -05:00
elif pair_order == 1 : # behind
self . char . raise_ ( )
2025-02-14 15:20:33 -05:00
self . sidechar . raise_ ( )
2022-02-21 11:48:51 -05:00
2025-02-14 15:20:33 -05:00
self . sidechar . move ( VIEWPORT_W * hor2_offset / 100 , VIEWPORT_H * vert2_offset / 100 )
2022-02-21 11:48:51 -05:00
self . bench . raise_ ( )
self . chatbox . raise_ ( )
self . effectview . raise_ ( )
self . objectionview . raise_ ( )
self . whiteflashlab . raise_ ( )
self . sidechar . set_flipped ( self . m_chatmessage [ OTHER_FLIP ] == " 1 " )
self . sidechar . play_idle ( self . m_chatmessage [ OTHER_NAME ] , self . m_chatmessage [ OTHER_EMOTE ] )
else :
self . sidechar . hide ( )
self . sidechar . move ( 0 , 0 )
2025-02-14 11:31:54 -05:00
if ( emote_mod == 1 or emote_mod == 2 or emote_mod == 6 ) and self . m_chatmessage [ PREANIM ] != " - " :
2025-02-14 22:01:08 -05:00
# sfx_delay = int(self.m_chatmessage[SFX_DELAY]) * 60
# if sfx_delay > 0:
# self.sfx_delay_timer.start(sfx_delay)
# else:
# self.play_sfx()
2022-02-21 11:48:51 -05:00
self . play_preanim ( False )
elif emote_mod == 0 or emote_mod == 5 or self . m_chatmessage [ PREANIM ] == " - " :
if self . m_chatmessage [ NO_INTERRUPT ] == " 0 " or self . m_chatmessage [ PREANIM ] == " - " :
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 = ini . read_ini_int ( AOpath + " characters/ " + f_char + " /char.ini " , " time " , " % " + f_preanim , - 1 )
text_delay = ini . read_ini_int ( AOpath + " characters/ " + f_char + " /char.ini " , " textdelay " , f_preanim , - 1 )
sfx_delay = int ( self . m_chatmessage [ SFX_DELAY ] ) * 60
preanim_duration = 0
if ao2_duration < 0 :
preanim_duration = ini . read_ini_int ( AOpath + " characters/ " + f_char + " /char.ini " , " time " , f_preanim , - 1 )
else :
preanim_duration = ao2_duration
anim_to_find = AOpath + " characters/ " + f_char + " / " + f_preanim + " .gif "
apng_to_find = AOpath + " characters/ " + f_char + " / " + f_preanim + " .apng "
webp_to_find = AOpath + " characters/ " + f_char + " / " + f_preanim + " .webp "
if ( not exists ( anim_to_find ) and not exists ( apng_to_find ) and not exists ( webp_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 sfx_delay > 0 :
self . sfx_delay_timer . start ( sfx_delay )
else :
self . play_sfx ( )
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 " )
2025-02-12 18:30:18 -05:00
self . setEvidenceImg ( self . presentedevi , f_image , True )
2025-02-13 01:32:56 -05:00
self . playSound ( " sfx-evidenceshoop.opus " )
2022-02-21 11:48:51 -05:00
if not is_left_side :
2025-02-12 18:30:18 -05:00
self . presentedevi . move ( 170 * 2 , 16 * 2 )
2022-02-21 11:48:51 -05:00
else :
2025-02-12 18:30:18 -05:00
self . presentedevi . move ( 16 * 2 , 16 * 2 )
2022-02-21 11:48:51 -05:00
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 ( " <b> %s called you.</b> " % f_char )
snd = audio . loadhandle ( False , " word_call.wav " , 0 , 0 , BASS_STREAM_AUTOFREE )
if snd :
audio . playhandle ( snd , True )
break
def do_effect ( self , fx_name , fx_sound , p_char , p_folder ) :
effect = ini . get_effect ( fx_name , p_char , p_folder )
if not effect : return
if fx_sound :
self . playSound ( fx_sound )
if " effects " not in self . features : return
self . effectview . set_play_once ( False )
try : self . effectview . play ( effect )
except : pass # Windows XP webp error with Pillow
print " effect " , repr ( effect )
def start_chat_ticking ( self ) :
if self . text_state != 0 :
return
if self . m_chatmessage [ EFFECTS ] :
fx_list = self . m_chatmessage [ EFFECTS ] . split ( " | " )
fx = fx_list [ 0 ]
fx_sound = " "
fx_folder = " "
if len ( fx_list ) > 1 :
fx_sound = fx_list [ 1 ]
if len ( fx_list ) > 2 :
fx_folder = fx_list [ 1 ]
fx_sound = fx_list [ 2 ]
if fx and fx not in ( " - " , " None " ) :
self . do_effect ( fx , fx_sound , self . m_chatmessage [ CHARNAME ] , fx_folder )
elif self . m_chatmessage [ REALIZATION ] == " 1 " :
self . setWhiteFlash ( True , 1 , 125 )
self . set_text_color ( )
charid = int ( self . m_chatmessage [ CHAR_ID ] )
if not self . is_additive or self . additive_char != charid :
self . ao2text . clear ( )
self . text . setText ( " " )
self . additive_char = charid
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 ] )
self . blip = self . charlist [ charid ] [ 2 ]
if exists ( AOpath + " sounds/general/sfx-blip " + self . blip + " .wav " ) :
self . blipsnd = audio . loadhandle ( False , AOpath + " sounds/general/sfx-blip " + self . blip + " .wav " , 0 , 0 , 0 )
elif exists ( AOpath + " sounds/general/sfx-blip " + self . blip + " .opus " ) :
self . blipsnd = audio . loadhandle ( False , AOpath + " sounds/general/sfx-blip " + self . blip + " .opus " , 0 , 0 , 0 )
elif exists ( AOpath + " sounds/blips/ " + self . blip + " .wav " ) :
self . blipsnd = audio . loadhandle ( False , AOpath + " sounds/blips/ " + self . blip + " .wav " , 0 , 0 , 0 )
elif exists ( AOpath + " sounds/blips/ " + self . blip + " .opus " ) :
self . blipsnd = audio . loadhandle ( False , AOpath + " sounds/blips/ " + self . blip + " .opus " , 0 , 0 , 0 )
else :
self . blipsnd = 0
audio . sethandleattr ( self . blipsnd , BASS_ATTRIB_VOL , self . blipslider . value ( ) / 100.0 )
emote_mod = int ( self . m_chatmessage [ EMOTE_MOD ] )
if emote_mod in ( 0 , 5 ) and self . m_chatmessage [ SCREENSHAKE ] == " 1 " :
self . setScreenShake ( True )
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 ( " <font color= \" " + get_text_color ( 4 ) . name ( ) + " \" > " + f_character + " </font> " )
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 ( " <font color= \" " + get_text_color ( 4 ) . name ( ) + " \" > " + f_character + " </font> " )
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 ( " <font color= \" " + get_text_color ( " _inline_grey " ) . name ( ) + " \" > " + f_character + " </font> " )
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 ( " <font color= \" " + get_text_color ( " _inline_grey " ) . name ( ) + " \" > " + f_character + " </font> " )
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 ]
else :
self . inline_color_stack . append ( INLINE_GREEN )
else :
self . inline_color_stack . append ( INLINE_GREEN )
formatting_char = True
elif f_character == " ~ " and not self . next_character_is_not_special : #green.
if self . inline_color_stack :
if self . inline_color_stack [ - 1 ] == INLINE_RED :
del self . inline_color_stack [ - 1 ]
else :
self . inline_color_stack . append ( INLINE_RED )
else :
self . inline_color_stack . append ( INLINE_RED )
formatting_char = True
elif f_character == " s " and self . next_character_is_not_special : # shake
self . setScreenShake ( True )
self . next_character_is_not_special = False
elif f_character == " f " and self . next_character_is_not_special : # flash
self . setWhiteFlash ( True , 0 , 75 )
self . next_character_is_not_special = False
elif f_character == " n " and self . next_character_is_not_special : # newline
self . text . setText ( self . text . text ( ) + " \n " )
self . ao2text . insertPlainText ( " \n " )
self . next_character_is_not_special = False
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 ( " <font color= \" " + get_text_color ( C_ORANGE ) . name ( ) + " \" > " + f_character + " </font> " )
elif top_color == INLINE_BLUE :
self . ao2text . insertHtml ( " <font color= \" " + get_text_color ( C_BLUE ) . name ( ) + " \" > " + f_character + " </font> " )
elif top_color == INLINE_GREEN :
self . ao2text . insertHtml ( " <font color= \" " + get_text_color ( C_GREEN ) . name ( ) + " \" > " + f_character + " </font> " )
elif top_color == INLINE_GRAY :
self . ao2text . insertHtml ( " <font color= \" " + get_text_color ( " _inline_grey " ) . name ( ) + " \" > " + f_character + " </font> " )
elif top_color == INLINE_RED :
self . ao2text . insertHtml ( " <font color= \" " + get_text_color ( C_RED ) . name ( ) + " \" > " + f_character + " </font> " )
else :
self . ao2text . insertHtml ( f_character )
else :
2025-02-14 15:46:12 -05:00
# if int(self.m_chatmessage[TEXT_COLOR]) == C_RAINBOW:
# self.text.setText(self.text.text() + f_character)
# else:
self . ao2text . insertHtml ( f_character )
2022-02-21 11:48:51 -05:00
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
audio . playhandle ( 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 ) :
audio . playhandle ( self . realizationsnd , True )
def playObjectionSnd ( self , charname , objection ) :
2025-02-13 22:22:55 -05:00
try :
charname = str ( charname )
except :
print " WARNING: Can ' t play objection sound if charname is unicode yet "
2022-02-21 11:48:51 -05:00
if self . objectsnd :
if audio . handleisactive ( self . objectsnd ) :
audio . stophandle ( self . objectsnd )
audio . freehandle ( self . objectsnd )
objecting = [ " holdit " , " objection " , " takethat " , " custom " ] [ objection - 1 ]
if objecting :
if exists ( AOpath + ' characters/ ' + charname + ' / ' + objecting + ' .wav ' ) :
self . objectsnd = audio . loadhandle ( False , AOpath + ' characters/ ' + charname + ' / ' + objecting + ' .wav ' , 0 , 0 , 0 )
elif exists ( AOpath + ' characters/ ' + charname + ' / ' + objecting + ' .opus ' ) :
self . objectsnd = audio . loadhandle ( False , AOpath + ' characters/ ' + charname + ' / ' + objecting + ' .opus ' , 0 , 0 , 0 )
else :
self . objectsnd = None
if ini . read_ini_bool ( " AO2XP.ini " , " General " , " download sounds " , True ) :
thread . start_new_thread ( download_thread , ( " base/characters/ " + charname . lower ( ) + " / " + objecting . lower ( ) + " .wav " , AOpath + " characters/ " + charname . lower ( ) + " / " + objecting . lower ( ) + " .wav " ) )
thread . start_new_thread ( download_thread , ( " base/characters/ " + charname . lower ( ) + " / " + objecting . lower ( ) + " .opus " , AOpath + " characters/ " + charname . lower ( ) + " / " + objecting . lower ( ) + " .wav " ) )
if exists ( AOpath + ' sounds/general/sfx-objection.opus ' ) :
self . objectsnd = audio . loadhandle ( False , AOpath + ' sounds/general/sfx-objection.opus ' , 0 , 0 , 0 )
else :
self . objectsnd = audio . loadhandle ( False , AOpath + ' sounds/general/sfx-objection.wav ' , 0 , 0 , 0 )
audio . sethandleattr ( self . objectsnd , BASS_ATTRIB_VOL , self . soundslider . value ( ) / 100.0 )
audio . playhandle ( self . objectsnd , True )
def play_sfx ( self ) :
sfx_name = self . m_chatmessage [ SFX ]
2025-02-14 22:01:08 -05:00
if sfx_name == " 1 " or sfx_name == " 0 " :
2022-02-21 11:48:51 -05:00
return
2025-02-14 22:01:08 -05:00
print self . m_chatmessage [ SFX ]
2022-02-21 11:48:51 -05:00
self . playSound ( sfx_name )
def playSound ( self , sfx ) :
if self . sound :
if audio . handleisactive ( self . sound ) :
audio . stophandle ( self . sound )
audio . freehandle ( self . sound )
2025-02-12 18:30:18 -05:00
if exists ( AOpath + ' sounds/general/ ' + sfx ) :
self . sound = audio . loadhandle ( False , AOpath + ' sounds/general/ ' + sfx , 0 , 0 , 0 )
audio . sethandleattr ( self . sound , BASS_ATTRIB_VOL , self . soundslider . value ( ) / 100.0 )
audio . playhandle ( self . sound , True )
elif exists ( AOpath + ' sounds/general/ ' + sfx + ' .wav ' ) :
2022-02-21 11:48:51 -05:00
self . sound = audio . loadhandle ( False , AOpath + ' sounds/general/ ' + sfx + ' .wav ' , 0 , 0 , 0 )
audio . sethandleattr ( self . sound , BASS_ATTRIB_VOL , self . soundslider . value ( ) / 100.0 )
audio . playhandle ( self . sound , True )
elif exists ( AOpath + ' sounds/general/ ' + sfx + ' .opus ' ) :
self . sound = audio . loadhandle ( False , AOpath + ' sounds/general/ ' + sfx + ' .opus ' , 0 , 0 , 0 )
audio . sethandleattr ( self . sound , BASS_ATTRIB_VOL , self . soundslider . value ( ) / 100.0 )
audio . playhandle ( self . sound , True )
def playMusic ( self , mus ) :
if not mus . endswith ( " .mp3 " ) and " ===MUSIC START===.mp3 " in self . musiclist : #vidya workaround
mus + = " .mp3 "
2025-02-14 17:01:05 -05:00
# if self.music:
# if audio.handleisactive(self.music):
# audio.stophandle(self.music)
# audio.freehandle(self.music)
# if self.stream:
# self.stream = None
2025-02-14 13:00:19 -05:00
2025-02-14 17:01:05 -05:00
# if self.download_thread:
# self.download_thread.terminate() # Live dangerously
# self.download_thread = None
self . stopMusic ( )
2022-02-21 11:48:51 -05:00
if exists ( AOpath + ' sounds/music/ ' + mus ) :
2025-02-11 12:08:54 -05:00
self . music = audio . loadhandle ( False , AOpath + ' sounds/music/ ' + mus , 0 , 0 , BASS_SAMPLE_LOOP )
2022-02-21 11:48:51 -05:00
audio . sethandleattr ( self . music , BASS_ATTRIB_VOL , self . musicslider . value ( ) / 100.0 )
audio . playhandle ( self . music , True )
elif ini . read_ini_bool ( " AO2XP.ini " , " General " , " download music " , True ) :
if mus . lower ( ) . startswith ( " http " ) :
2025-02-14 13:00:19 -05:00
#self.music = audio.loadURLhandle(mus, 0, BASS_STREAM_BLOCK | BASS_SAMPLE_LOOP)
self . music = audio . loadURLhandle ( mus , 0 , BASS_SAMPLE_LOOP )
print " [audio] Trying to play " , mus . lower ( )
2022-02-21 11:48:51 -05:00
else :
for bucket in buckets :
if not bucket : continue
2025-02-14 13:00:19 -05:00
print " [audio] Music stream: " , bucket + ' base/sounds/music/ ' + mus . lower ( )
2025-02-11 17:31:05 -05:00
self . music = audio . loadURLhandle ( bucket + ' base/sounds/music/ ' + mus . lower ( ) , 0 , BASS_STREAM_BLOCK | BASS_SAMPLE_LOOP )
2022-02-21 11:48:51 -05:00
if self . music : break
if self . music :
audio . sethandleattr ( self . music , BASS_ATTRIB_VOL , self . musicslider . value ( ) / 100.0 )
audio . playhandle ( self . music , True )
2025-02-11 12:08:54 -05:00
else :
2025-02-14 13:00:19 -05:00
print " [audio] Couldn ' t play music. Error " , audio . getbasserror ( )
2025-02-14 17:01:05 -05:00
# Here comes the evil HTTPS hack for XP systems, but it also allows us to download and play modules and midis, because, why not?
musl = mus . lower ( )
2025-02-14 17:35:05 -05:00
musext = os . path . splitext ( basename ( musl ) ) [ - 1 ]
if musext in [ ' .mid ' , ' .midi ' ] :
self . specialstream = 1
elif musext in [ ' .xm ' , ' .mod ' , ' .mo3 ' , ' .it ' , ' .s3m ' , ' .mtm ' , ' .umx ' ] :
self . specialstream = 2
if musl . startswith ( " https " ) or self . specialstream :
2025-02-14 17:01:05 -05:00
print " [audio] Downloading music with urllib2 "
2025-02-14 13:00:19 -05:00
self . download_thread = DownloadThread ( self , mus )
self . download_thread . finished_signal . connect ( self . playDownloadedMusic )
self . download_thread . start ( )
2022-02-21 11:48:51 -05:00
def stopMusic ( self ) :
if self . music :
if audio . handleisactive ( self . music ) :
audio . stophandle ( self . music )
2025-02-14 17:35:05 -05:00
if self . specialstream :
if self . specialstream == 2 :
audio . freeMOD ( self . music )
self . specialstream = 0
2025-02-14 17:01:05 -05:00
else :
audio . freehandle ( self . music )
2025-02-14 14:21:07 -05:00
if self . stream :
2025-02-14 17:01:05 -05:00
self . stream = None
2025-02-14 14:21:07 -05:00
if self . download_thread :
self . download_thread . terminate ( ) # Live dangerously
self . download_thread = None
2025-02-14 13:00:19 -05:00
def playDownloadedMusic ( self , file_length ) :
# Part of the evil HTTPS music download hack for XP systems
print " [audio] Done downloading; trying to play... "
2025-02-14 17:35:05 -05:00
if self . specialstream == 1 :
self . music = audio . loadMIDI ( True , self . stream , 0 , file_length , BASS_SAMPLE_LOOP )
elif self . specialstream == 2 :
2025-02-14 17:01:05 -05:00
self . music = audio . loadMOD ( True , self . stream , 0 , file_length , BASS_SAMPLE_LOOP )
else :
self . music = audio . loadhandle ( True , self . stream , 0 , file_length , BASS_SAMPLE_LOOP )
2025-02-14 13:00:19 -05:00
audio . sethandleattr ( self . music , BASS_ATTRIB_VOL , self . musicslider . value ( ) / 100.0 )
audio . playhandle ( self . music , False )
2022-02-21 11:48:51 -05:00
2025-02-13 15:11:51 -05:00
def startGame ( self , tcp , playerlist , charlist , musiclist , background , evidence , areas , features = [ ] , oocjoin = [ ] , hplist = [ ] , webAO_bucket = " " ) :
2022-02-21 11:48:51 -05:00
self . willDisconnect = False
self . mychar = - 1
self . mychatcolor = 0
self . tcp = tcp
2025-02-13 15:11:51 -05:00
self . playerlist = playerlist
2022-02-21 11:48:51 -05:00
self . charlist = charlist
self . musiclist = musiclist
self . evidence = evidence
self . areas = areas
self . features = features
if " base/ " in webAO_bucket :
webAO_bucket = webAO_bucket . replace ( " base/ " , " " )
buckets [ 0 ] = webAO_bucket
self . charselect . setCharList ( charlist )
self . charselect . show ( )
self . oocnameinput . setText ( ini . read_ini ( " AO2XP.ini " , " General " , " OOC name " ) )
self . shownameedit . setText ( ini . read_ini ( " AO2XP.ini " , " General " , " Showname " ) )
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. " )
self . deskbtn . setDisabled ( " deskmod " not in features )
self . flipbutton . setVisible ( " flipping " in features )
self . customobject . setVisible ( " customobjections " in features )
self . ypairoffset . setVisible ( " y_offset " in features )
self . ypairoffset_l . setVisible ( " y_offset " in features )
self . colordropdown . clear ( )
self . colordropdown . addItems ( [ ' white ' , ' green ' , ' red ' , ' orange ' , ' blue ' ] )
if " yellowtext " in features :
2025-02-14 15:46:12 -05:00
self . colordropdown . addItems ( [ ' yellow ' , ' pink ' , ' cyan ' , ' gray ' ] )
2022-02-21 11:48:51 -05:00
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 = ' <b>--- Log started on ' + time . ctime ( ) + ' ---</b> '
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 )
self . setBackground ( background )
for msg in oocjoin :
self . ooclog . append ( msg )
for song in musiclist :
2025-02-13 19:11:30 -05:00
song = song . replace ( " <and> " , " & " ) . decode ( ' utf-8 ' )
2022-02-21 11:48:51 -05:00
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 )
2025-02-13 15:11:51 -05:00
for pid in playerlist :
self . updatePlayerList ( pid , 0 , 0 )
for type in range ( len ( playerlist [ pid ] ) ) :
self . updatePlayerList ( pid , 1 , type , playerlist [ pid ] [ type ] )
2022-02-21 11:48:51 -05:00
self . musicslider . setValue ( ini . read_ini_int ( " AO2XP.ini " , " Audio " , " Music volume " , 100 ) )
self . soundslider . setValue ( ini . read_ini_int ( " AO2XP.ini " , " Audio " , " Sound volume " , 100 ) )
self . blipslider . setValue ( ini . read_ini_int ( " AO2XP.ini " , " Audio " , " Blip volume " , 100 ) )
#thread.start_new_thread(self.tcp_thread, ())
self . tcpthread = TCP_Thread ( self )
self . tcpthread . MS_Chat . connect ( self . netmsg_ms )
self . tcpthread . newChar . connect ( self . onPVPacket )
self . tcpthread . newBackground . connect ( self . setBackground )
self . tcpthread . OOC_Log . connect ( self . ooclog . append )
self . tcpthread . IC_Log . connect ( self . icLog . append )
self . tcpthread . charSlots . connect ( partial ( self . charselect . setCharList , self . charlist ) )
self . tcpthread . showCharSelect . connect ( self . charselect . show )
self . tcpthread . allEvidence . connect ( self . allEvidence )
2025-02-13 15:11:51 -05:00
self . tcpthread . updatePlayerList . connect ( self . updatePlayerList )
2025-02-14 15:46:12 -05:00
#self.tcpthread.rainbowColor.connect(self.text.setStyleSheet)
2022-02-21 11:48:51 -05:00
self . tcpthread . start ( )
def allEvidence ( self , evi ) :
self . evidence = evi
if self . evidencedropdown . count ( ) > 0 :
self . evidencedropdown . clear ( )
for evi in self . evidence :
while len ( evi ) < 3 : # new AO 2.9 bug where they never correctly escaped evidence name/desc/image on FantaProtocol
evi + = [ " " ]
evi [ 0 ] = decode_ao_str ( evi [ 0 ] . decode ( ' utf-8 ' ) )
evi [ 1 ] = decode_ao_str ( evi [ 1 ] . decode ( ' utf-8 ' ) )
evi [ 2 ] = decode_ao_str ( evi [ 2 ] . decode ( ' utf-8 ' ) )
self . evidencedropdown . addItem ( evi [ 0 ] )
if not self . evidence :
self . evidencedropdown . setCurrentIndex ( 0 )
self . evidencedesc . setText ( ' . ' )
else :
self . evidencedropdown . setCurrentIndex ( self . selectedevi )
2025-02-13 15:11:51 -05:00
2025-02-13 16:36:10 -05:00
def updatePlayerList ( self , pid , op , utype , data = " " ) :
pid = str ( pid )
2025-02-13 15:11:51 -05:00
if op == 0 : # Add or remove player
2025-02-13 16:36:10 -05:00
if utype == 0 : # Add a player
self . playerList . addItem ( " [ %s ] " % pid )
if not pid in self . playerlist :
self . playerlist [ pid ] = [ " " , " " , " " , " " ]
if utype == 1 : # Remove a player
item = self . playerList . findItems ( " [ %s ] " % pid , QtCore . Qt . MatchStartsWith )
2025-02-13 15:11:51 -05:00
if item :
self . playerList . takeItem ( self . playerList . row ( item [ 0 ] ) )
2025-02-13 16:36:10 -05:00
if pid in self . playerlist :
del self . playerlist [ pid ]
2025-02-13 15:11:51 -05:00
else : # Update a player
2025-02-13 16:36:10 -05:00
if pid in self . playerlist :
self . playerlist [ pid ] [ utype ] = data
2025-02-13 15:11:51 -05:00
2025-02-13 16:36:10 -05:00
item = self . playerList . findItems ( " [ %s ] " % pid , QtCore . Qt . MatchStartsWith )
2025-02-13 15:11:51 -05:00
if item :
2025-02-13 16:36:10 -05:00
name = self . playerlist [ pid ] [ 0 ]
char = self . playerlist [ pid ] [ 1 ]
charname = self . playerlist [ pid ] [ 2 ]
text = " [ %s ] " % pid
2025-02-13 15:11:51 -05:00
if char :
text + = " %s " % char
if charname :
text + = " ( %s ) " % charname
if name :
text + = " %s " % name
item [ 0 ] . setText ( text )
pass
2019-04-03 10:57:23 -04:00
class PresentButton ( QtGui . QLabel ) :
2022-02-21 11:48:51 -05:00
def __init__ ( self , gamegui , parent ) :
super ( PresentButton , self ) . __init__ ( parent )
self . gamegui = gamegui
self . button_off = QtGui . QPixmap ( AO2XPpath + ' themes/default/present_disabled.png ' )
self . button_on = QtGui . QPixmap ( AO2XPpath + ' themes/default/present.png ' )
self . setPixmap ( self . button_off )
self . show ( )
2019-04-03 10:57:23 -04:00
2022-02-21 11:48:51 -05:00
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 )
2019-04-03 10:57:23 -04:00
class EditEvidenceDialog ( QtGui . QDialog ) :
2022-02-21 11:48:51 -05:00
def __init__ ( self , gamegui ) :
super ( EditEvidenceDialog , self ) . __init__ ( )
self . gamegui = gamegui
self . setWindowTitle ( ' Add evidence ' )
self . resize ( 512 , 384 )
self . setModal ( True )
self . eviname = QtGui . QLineEdit ( self )
2025-02-13 18:21:37 -05:00
self . eviname . setGeometry ( 8 , 8 , 410 , 24 )
2022-02-21 11:48:51 -05:00
self . evidesc = QtGui . QTextEdit ( self )
2025-02-13 18:21:37 -05:00
self . evidesc . setGeometry ( 8 , 192 - 105 , 496 , 255 )
self . evidesc . setAcceptRichText ( False )
2022-02-21 11:48:51 -05:00
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 ( )
2025-02-13 18:21:37 -05:00
2022-02-21 11:48:51 -05:00
self . save = QtGui . QPushButton ( self )
self . save . setText ( ' Save ' )
self . save . clicked . connect ( self . onSave )
2025-02-13 18:21:37 -05:00
self . save . move ( 256 - self . save . size ( ) . width ( ) - 8 , 384 - self . save . size ( ) . height ( ) - 2 )
2022-02-21 11:48:51 -05:00
self . cancel = QtGui . QPushButton ( self )
self . cancel . setText ( ' Cancel ' )
self . cancel . clicked . connect ( self . onCancel )
2025-02-13 18:21:37 -05:00
self . cancel . move ( 264 + 16 , 384 - self . cancel . size ( ) . height ( ) - 2 )
2022-02-21 11:48:51 -05:00
self . choosepic = QtGui . QComboBox ( self )
2025-02-13 18:21:37 -05:00
self . choosepic . setGeometry ( self . eviname . x ( ) + self . eviname . size ( ) . width ( ) - 128 - 84 , self . eviname . y ( ) + 70 - 32 , 128 , 24 )
2022-02-21 11:48:51 -05:00
self . filenames = [ ]
2025-02-13 18:21:37 -05:00
self . browse = QtGui . QPushButton ( self )
self . browse . setText ( ' Browse ' )
self . browse . clicked . connect ( self . onBrowse )
self . browse . move ( self . choosepic . x ( ) + self . choosepic . width ( ) + 8 , self . choosepic . y ( ) )
2022-02-21 11:48:51 -05:00
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 ( AO2XPpath + ' themes/default/evidence_selected.png ' ) )
def onSave ( self ) :
name = encode_ao_str ( self . eviname . text ( ) . toUtf8 ( ) )
desc = encode_ao_str ( 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 ( )
2025-02-13 18:21:37 -05:00
def onBrowse ( self ) :
path = str ( QtGui . QFileDialog . getOpenFileName ( self , " Select an image " , AOpath + ' evidence ' , " Images (*.png) " ) )
if path :
if not " /evidence/ " in path . lower ( ) :
QtGui . QMessageBox . warning ( self , ' Edit evidence ' , ' Please select a file from the evidence directory. ' )
self . onBrowse ( )
return
file = basename ( path )
if file . lower ( ) . endswith ( ' .png ' ) :
ind = os . listdir ( AOpath + ' evidence ' ) . index ( file )
self . choosepic . setCurrentIndex ( ind )
else :
QtGui . QMessageBox . warning ( self , ' Edit evidence ' , ' Please select a PNG file. ' )
self . onBrowse ( )
2022-02-21 11:48:51 -05:00
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 ( )
2019-04-03 10:57:23 -04:00
class EmoteButton ( QtGui . QLabel ) :
2022-02-21 11:48:51 -05:00
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
2025-02-12 18:30:18 -05:00
self . path = ' '
2022-02-21 11:48:51 -05:00
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 ( ) :
2025-02-12 18:30:18 -05:00
button_img = QtGui . QPixmap ( self . path + ' _off.png ' )
painter . setOpacity ( 0.5 )
painter . drawPixmap ( 0 , 0 , button_img )
2022-02-21 11:48:51 -05:00
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 )
2019-04-03 10:57:23 -04:00
class BackEmoteButton ( QtGui . QLabel ) :
2022-02-21 11:48:51 -05:00
def __init__ ( self , gamewindow , x , y ) :
super ( BackEmoteButton , self ) . __init__ ( gamewindow )
self . gamewindow = gamewindow
self . move ( x , y )
self . setPixmap ( QtGui . QPixmap ( AO2XPpath + ' themes/default/arrow_left.png ' ) )
self . show ( )
2019-04-03 10:57:23 -04:00
2022-02-21 11:48:51 -05:00
def mousePressEvent ( self , event ) :
self . gamewindow . current_emote_page - = 1
self . gamewindow . set_emote_page ( )
2019-04-03 10:57:23 -04:00
class NextEmoteButton ( QtGui . QLabel ) :
2022-02-21 11:48:51 -05:00
def __init__ ( self , gamewindow , x , y ) :
super ( NextEmoteButton , self ) . __init__ ( gamewindow )
self . gamewindow = gamewindow
self . move ( x , y )
self . setPixmap ( QtGui . QPixmap ( AO2XPpath + ' themes/default/arrow_right.png ' ) )
self . show ( )
2019-04-03 10:57:23 -04:00
2022-02-21 11:48:51 -05:00
def mousePressEvent ( self , event ) :
self . gamewindow . current_emote_page + = 1
self . gamewindow . set_emote_page ( )
2019-04-03 10:57:23 -04:00
class TCP_Thread ( QtCore . QThread ) :
2022-02-21 11:48:51 -05:00
connectionError = QtCore . pyqtSignal ( str , str , str )
MS_Chat = QtCore . pyqtSignal ( list )
newChar = QtCore . pyqtSignal ( str )
newBackground = QtCore . pyqtSignal ( str )
IC_Log = QtCore . pyqtSignal ( str )
OOC_Log = QtCore . pyqtSignal ( str )
charSlots = QtCore . pyqtSignal ( )
showCharSelect = QtCore . pyqtSignal ( )
allEvidence = QtCore . pyqtSignal ( list )
2025-02-14 15:46:12 -05:00
#rainbowColor = QtCore.pyqtSignal(str)
2025-02-13 15:11:51 -05:00
updatePlayerList = QtCore . pyqtSignal ( str , int , int , str )
2020-08-01 22:15:07 -04:00
2022-02-21 11:48:51 -05:00
def __init__ ( self , parent ) :
super ( TCP_Thread , self ) . __init__ ( parent )
self . parent = parent
def run ( self ) :
pingtimer = 150
2025-02-14 15:46:12 -05:00
#rainbow = 0
2022-02-21 11:48:51 -05:00
sendtick = 0
tempdata = " "
color = QtGui . QColor ( )
2025-02-14 15:46:12 -05:00
#color.setHsv(rainbow, 255, 255)
color . setHsv ( 0 , 255 , 255 )
2022-02-21 11:48:51 -05:00
while True :
if self . parent . disconnectnow :
2025-02-14 15:20:33 -05:00
self . parent . selectedplayer = - 1
2025-02-14 14:21:07 -05:00
self . parent . playerList . clear ( )
2022-02-21 11:48:51 -05:00
self . parent . stopMusic ( )
self . parent . tcp . close ( )
self . quit ( )
return
pingtimer - = 1
if pingtimer == 0 :
pingbefore = time . time ( )
self . parent . tcp . send ( ' CH# % ' )
pingtimer = 150
2025-02-14 15:46:12 -05:00
# 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()) + ')')
# self.rainbowColor.emit('color: rgb(' + str(color.red()) + ', ' + str(color.green()) + ', ' + str(color.blue()) + ')')
2022-02-21 11:48:51 -05:00
if sendtick :
sendtick - = 1
if self . parent . msgqueue and not sendtick :
self . parent . tcp . send ( self . parent . msgqueue [ 0 ] )
sendtick = 4
2022-03-27 21:01:18 -04:00
error , total = self . parent . tcp . recv ( )
if error == - 2 :
continue
elif error == - 1 :
self . parent . emit ( QtCore . SIGNAL ( ' showMessage(QString, QString, QString) ' ) , ' critical ' , ' Connection lost ' , " %s connection to server lost. " % ( " WebSocket " if self . parent . tcp . isWS else " TCP " ) )
2022-02-21 11:48:51 -05:00
self . parent . willDisconnect = True
self . quit ( )
return
2022-03-27 21:01:18 -04:00
for network in total :
2022-02-21 11:48:51 -05:00
header = network [ 0 ]
2022-03-27 21:01:18 -04:00
#del network[-1]
2022-02-21 11:48:51 -05:00
if header == ' MS ' :
if len ( network ) < 15 :
print ' [warning] ' , ' malformed/incomplete MS#chat (IC chat) network message was received '
continue
network [ CHATMSG ] = decode_ao_str ( network [ CHATMSG ] . decode ( ' utf-8 ' ) )
self . MS_Chat . emit ( network )
elif header == ' MC ' :
music = decode_ao_str ( 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 and network [ 3 ] :
name + = " ( " + network [ 3 ] . decode ( " utf-8 " ) + " ) "
#self.parent.icLog.append('[%d:%.2d] %s changed the music to %s' % (t[3], t[4], name, music))
self . IC_Log . emit ( ' [ %d : %.2d ] %s changed the music to %s ' % ( t [ 3 ] , t [ 4 ] , name , music ) )
else :
self . IC_Log . emit ( ' [ %d : %.2d ] the music was changed to %s ' % ( t [ 3 ] , t [ 4 ] , music ) )
self . parent . playMusic ( music )
elif header == ' BN ' :
self . newBackground . emit ( network [ 1 ] )
elif header == ' CT ' :
name = decode_ao_str ( network [ 1 ] . decode ( ' utf-8 ' ) )
chatmsg = decode_ao_str ( network [ 2 ] . decode ( ' utf-8 ' ) . replace ( " \n " , " <br /> " ) )
#self.parent.ooclog.append('<b>%s:</b> %s' % (name, chatmsg))
self . OOC_Log . emit ( " <b> %s :</b> %s " % ( name , chatmsg ) )
elif header == ' PV ' :
self . parent . mychar = int ( network [ 3 ] )
self . parent . charselect . hide ( )
self . newChar . emit ( self . parent . charlist [ self . parent . mychar ] [ 0 ] )
elif header == ' LE ' :
del network [ 0 ]
self . allEvidence . emit ( [ evi . split ( ' & ' ) for evi in network ] )
elif header == ' ZZ ' :
if self . parent . modcall :
audio . freehandle ( self . parent . modcall )
self . parent . modcall = audio . loadhandle ( 0 , " mod_call.wav " , 0 , 0 , 0 )
audio . sethandleattr ( self . parent . modcall , BASS_ATTRIB_VOL , self . parent . soundslider . value ( ) / 100.0 )
audio . playhandle ( self . parent . modcall , False )
if len ( network ) > 1 :
self . OOC_Log . emit ( ' <b>[MOD CALL] ' + network [ 1 ] . replace ( " \n " , " <br /> " ) + ' </b> ' )
else :
self . OOC_Log . emit ( ' <b>[MOD CALL] But there was no extra information. (old server?)</b> ' )
elif header == ' CharsCheck ' :
del network [ 0 ]
for i in range ( len ( network ) ) :
self . parent . charlist [ i ] [ 1 ] = int ( network [ i ] )
self . charSlots . emit ( )
elif header == ' RT ' :
testimony = network [ 1 ]
wtcefile = AOpath + " sounds/general/sfx-testimony2 "
2025-02-11 12:08:54 -05:00
if self . parent . wtcesfx :
audio . freehandle ( self . parent . wtcesfx )
2022-02-21 11:48:51 -05:00
if testimony == ' judgeruling ' :
variant = int ( network [ 2 ] )
if variant == 0 :
wtcefile = AOpath + " sounds/general/sfx-notguilty "
elif variant == 1 :
wtcefile = AOpath + " sounds/general/sfx-guilty "
else :
variant = 0
self . parent . wtcesfx = audio . loadhandle ( False , wtcefile + " .opus " if exists ( wtcefile + " .opus " ) else wtcefile + " .wav " , 0 , 0 , 0 )
audio . sethandleattr ( self . parent . wtcesfx , BASS_ATTRIB_VOL , self . parent . soundslider . value ( ) / 100.0 )
audio . playhandle ( 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 == ' BB ' : # message popup (AO 2.9)
message = network [ 1 ]
self . parent . emit ( QtCore . SIGNAL ( ' showMessage(QString, QString, QString) ' ) , ' warning ' , ' Message from server ' , message )
elif header == ' AUTH ' : # login status (AO 2.9)
status = int ( network [ 1 ] )
statusStrings = [ " You have logged out " , " Wrong password " , " Logged in " ]
self . OOC_Log . emit ( " <b> %s </b> " % ( statusStrings [ status + 1 ] ) )
2025-02-13 15:11:51 -05:00
2022-02-21 11:48:51 -05:00
elif header == " CHECK " : #ping
pingafter = time . time ( )
self . parent . gotPing . emit ( int ( ( pingafter - pingbefore ) * 1000 ) )
elif header == ' DONE ' :
self . showCharSelect . emit ( )
2025-02-13 15:11:51 -05:00
elif header == ' PR ' :
del network [ 0 ]
#print "(PR) id: %s, type: %d" % (network[0], int(network[1]))
self . updatePlayerList . emit ( network [ 0 ] , 0 , int ( network [ 1 ] ) , " " )
elif header == ' PU ' :
del network [ 0 ]
#print "(PU) id: %s, type: %d, data: %s" % (network[0], int(network[1]), network[2])
2025-02-13 16:36:10 -05:00
self . updatePlayerList . emit ( network [ 0 ] , 1 , int ( network [ 1 ] ) , network [ 2 ] . decode ( ' utf-8 ' ) )
2025-02-14 13:00:19 -05:00
class DownloadThread ( QtCore . QThread ) :
# Part of the evil HTTPS music download hack for XP systems
finished_signal = QtCore . pyqtSignal ( int )
def __init__ ( self , caller , url ) :
super ( DownloadThread , self ) . __init__ ( )
self . caller = caller
self . url = url
def run ( self ) :
self . download ( self . url )
def download ( self , url ) :
headers = {
' User-Agent ' : ' AO2XP ' ,
' Accept ' : ' audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3, */* ' ,
' Accept-Encoding ' : ' gzip, deflate ' ,
' Accept-Language ' : ' en-US,en;q=0.9 ' ,
' Connection ' : ' keep-alive ' ,
' Upgrade-Insecure-Requests ' : ' 1 '
}
request = Request ( url , headers = headers )
request . get_method = lambda : ' HEAD '
response = urlopen ( request )
file_length = int ( response . headers . get ( ' Content-Length ' , 0 ) )
if file_length > 0 :
request = Request ( url , headers = headers )
response = urlopen ( request )
stream = " "
bytes_downloaded = 0
buffer_size = 8192
while bytes_downloaded < file_length :
chunk = response . read ( buffer_size )
if not chunk :
break
stream + = chunk
bytes_downloaded + = len ( chunk )
#progress = int((bytes_downloaded / float(file_length)) * 100)
#print "[debug] progress: %d%%" % progress
self . caller . stream = create_string_buffer ( stream )
self . finished_signal . emit ( file_length )