diff --git a/.gitignore b/.gitignore index e7a97233..a9076e4b 100755 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,6 @@ dependencies/config/local.prc # PyMongo bson gridfs -pymongo \ No newline at end of file +pymongo +Toon Bot +DNS \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index e444c24f..00311dfa 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,12 @@ [submodule "resources"] path = resources - url = git@Repo.Ez-webz.com:Stride/resources.git + url = http://Repo.Ez-webz.com/Stride/resources.git +[submodule "build/nirai/src"] + path = build/nirai/src + url = https://github.com/nirai-compiler/src +[submodule "build/nirai/panda3d"] + path = build/nirai/panda3d + url = https://github.com/nirai-compiler/panda3d +[submodule "build/nirai/python"] + path = build/nirai/python + url = https://github.com/nirai-compiler/python diff --git a/build/base.dg b/build/base.dg deleted file mode 100644 index 8157b37c..00000000 Binary files a/build/base.dg and /dev/null differ diff --git a/build/data/NiraiStart.py b/build/data/NiraiStart.py index 4140161f..15bd7159 100644 --- a/build/data/NiraiStart.py +++ b/build/data/NiraiStart.py @@ -1,14 +1,13 @@ from panda3d.core import * -import __builtin__, os -import rc4 +import __builtin__, os, sys +import aes import niraidata # Config prc = niraidata.CONFIG -key, prc = prc[:32], prc[32:] -rc4.rc4_setkey(key) -prc = rc4.rc4(prc) +iv, key, prc = prc[:16], prc[16:32], prc[32:] +prc = aes.decrypt(prc, key, iv) for line in prc.split('\n'): line = line.strip() @@ -16,43 +15,37 @@ for line in prc.split('\n'): loadPrcFileData('nirai config', line) del prc +del iv +del key # DC __builtin__.dcStream = StringStream() dc = niraidata.DC -key, dc = dc[:32], dc[32:] -rc4.rc4_setkey(key) -dc = rc4.rc4(dc) +iv, key, dc = dc[:16], dc[16:32], dc[32:] +dc = aes.decrypt(dc, key, iv) dcStream.setData(dc) del dc -rc4.rc4_setkey('\0\0\0\0') +del iv +del key + +# The VirtualFileSystem, which has already initialized, doesn't see the mount +# directives in the config(s) yet. We have to force it to load those manually: +#from panda3d.core import VirtualFileSystem, ConfigVariableList, Filename +vfs = VirtualFileSystem.getGlobalPtr() +mounts = ConfigVariableList('vfs-mount') +for mount in mounts: + mountfile, mountpoint = (mount.split(' ', 2) + [None, None, None])[:2] + vfs.mount(Filename(mountfile), Filename(mountpoint), 0) # Resources -# TO DO: Sign and verify the phases to prevent editing. - -vfs = VirtualFileSystem.getGlobalPtr() -mfs = (3, 3.5, 4, 5, 5.5, 6, 7, 8, 9, 10, 11, 12, 13) +# TO DO: Sign and verify the phases to prevent edition abort = False -for mf in mfs: - filename = 'resources/default/phase_%s.mf' % mf - if not os.path.isfile(filename): - print 'Phase %s not found' % filename - abort = True - break - - mf = Multifile() - mf.openRead(filename) - - if not vfs.mount(mf, '../resources', 0): - print 'Unable to mount %s' % filename - abort = True - break - # Packs pack = os.environ.get('TT_STRIDE_CONTENT_PACK') +import glob if pack and pack != 'default': print 'Loading content pack', pack for file in glob.glob('resources/%s/*.mf' % pack): @@ -61,15 +54,9 @@ if pack and pack != 'default': names = mf.getSubfileNames() for name in names: ext = os.path.splitext(name)[1] - if ext not in ('.jpg', '.jpeg', '.ogg', '.rgb'): + if ext not in ['.jpg', '.jpeg', '.ogg', '.rgb']: mf.removeSubfile(name) - - mf.flush() - - if not vfs.mount(mf, '../resources', 0): - print 'Unable to mount %s' % filename - abort = True - break + vfs.mount(mf, Filename('/'), 0) if not abort: # Run diff --git a/build/make.py b/build/make.py index 65b0aa42..49ec7293 100644 --- a/build/make.py +++ b/build/make.py @@ -1,126 +1,57 @@ from panda3d.core import * -import argparse, marshal, struct -import glob, sys, os -import rc4 +import argparse, struct +import sys, glob +import os + +sys.path.append('nirai/src') + +from niraitools import * parser = argparse.ArgumentParser() parser.add_argument('--compile-cxx', '-c', action='store_true', - help='Compile the CXX codes and generate Nirai.exe into built.') + help='Compile the CXX codes and generate stride.exe into built.') parser.add_argument('--make-nri', '-n', action='store_true', help='Generate stride NRI.') +parser.add_argument('--make-mfs', '-m', action='store_true', + help='Make multifiles') args = parser.parse_args() -# BEGIN (STRIPPED AND MODIFIED) COPY FROM niraitools.py -class NiraiPackager: - HEADER = 'NRI\n' +if not os.path.exists('built'): + os.mkdir('built') - def __init__(self, outfile): - self.modules = {} - self.outfile = outfile +def niraicall_obfuscate(code): + # We'll obfuscate if len(code) % 4 == 0 + # This way we make sure both obfuscated and non-obfuscated code work. + if len(code) % 4: + return False, None - def __read_file(self, filename, mangler=None): - with open(filename, 'rb') as f: - data = f.read() + # Reverse + code = code[::-1] - base = filename.rsplit('.', 1)[0].replace('\\', '/').replace('/', '.') - pkg = base.endswith('.__init__') - moduleName = base.rsplit('.', 1)[0] if pkg else base + # XOR + key = ['B', 'A', 'Q', 'J', 'R', 'P', 'Z', 'P', 'A', 'H', 'U', 'T'] + output = [] - name = moduleName - if mangler is not None: - name = mangler(name) + for i in range(len(code)): + xor_num = ord(code[i]) ^ ord(key[i % len(key)]) + output.append(chr(xor_num)) - if not name: - return '', ('', 0) + code = ''.join(output) - try: - data = self.compile_module(name, data) + return True, code - except: - print 'WARNING: Failed to compile', filename - return '', ('', 0) - - size = len(data) * (-1 if pkg else 1) - return name, (data, size) - - def compile_module(self, name, data): - return marshal.dumps(compile(data, name, 'exec')) - - def add_module(self, moduleName, data, size=None, compile=False): - if compile: - data = self.compile_module(moduleName, data) - - if size is None: - size = len(data) - - self.modules[moduleName] = (data, size) - - def add_file(self, filename, mangler=None): - print 'Adding file', filename - moduleName, (data, size) = self.__read_file(filename, mangler) - if moduleName: - moduleName = os.path.basename(filename).rsplit('.', 1)[0] - self.add_module(moduleName, data, size) - - def add_directory(self, dir, mangler=None): - print 'Adding directory', dir - - def _recurse_dir(dir): - for f in os.listdir(dir): - f = os.path.join(dir, f) - - if os.path.isdir(f): - _recurse_dir(f) - - elif f.endswith('py'): - moduleName, (data, size) = self.__read_file(f, mangler) - if moduleName: - self.add_module(moduleName, data, size) - - _recurse_dir(dir) - - def get_mangle_base(self, *path): - return len(os.path.join(*path).rsplit('.', 1)[0].replace('\\', '/').replace('/', '.')) + 1 - - def write_out(self): - f = open(self.outfile, 'wb') - f.write(self.HEADER) - f.write(self.process_modules()) - f.close() - - def generate_key(self, size=256): - return os.urandom(size) - - def dump_key(self, key): - for k in key: - print ord(k), - - print - - def process_modules(self): - # Pure virtual - raise NotImplementedError('process_datagram') - - def get_file_contents(self, filename, keysize=0): - with open(filename, 'rb') as f: - data = f.read() - - if keysize: - key = self.generate_key(keysize) - rc4.rc4_setkey(key) - data = key + rc4.rc4(data) - - return data -# END COPY FROM niraitools.py +niraimarshal.niraicall_obfuscate = niraicall_obfuscate class StridePackager(NiraiPackager): - HEADER = 'STRIDETT' + HEADER = 'TTSTRIDE' BASEDIR = '..' + os.sep def __init__(self, outfile): NiraiPackager.__init__(self, outfile) self.__manglebase = self.get_mangle_base(self.BASEDIR) + self.add_panda3d_dirs() + self.add_default_lib() def add_source_dir(self, dir): self.add_directory(self.BASEDIR + dir, mangler=self.__mangler) @@ -131,7 +62,7 @@ class StridePackager(NiraiPackager): def __mangler(self, name): if name.endswith('AI') or name.endswith('UD') or name in ('ToontownAIRepository', 'ToontownUberRepository', - 'ToontownInternalRepository'): + 'ToontownInternalRepository', 'ServiceStart'): if not 'NonRepeatableRandomSource' in name: return '' @@ -139,26 +70,22 @@ class StridePackager(NiraiPackager): def generate_niraidata(self): print 'Generating niraidata' + # Config + config = self.get_file_contents('../deployment/public_client.prc') - config = self.get_file_contents('../dependencies/config/release/en.prc') - config += '\n\n' + self.get_file_contents('../dependencies/config/general.prc') - key = self.generate_key(128) - rc4.rc4_setkey(key) - config = key + rc4.rc4(config) - + config_iv = self.generate_key(16) + config_key = self.generate_key(16) + config = config_iv + config_key + aes.encrypt(config, config_key, config_iv) niraidata = 'CONFIG = %r' % config - niraidata += '\nDC = %r' % self.get_file_contents('../dependencies/astron/dclass/stride.dc', 128) + + # DC + niraidata += '\nDC = %r' % self.get_file_contents('../dependencies/astron/dclass/stride.dc', True) self.add_module('niraidata', niraidata, compile=True) def process_modules(self): - with open('base.dg', 'rb') as f: - basesize, = struct.unpack(' #include +#include +#include #include -string rc4(const char* data, const char* key, int ds, int ks); - extern "C" __declspec(dllexport) void initlibpandadna(); void init_libpandadna(); -const char* header = "STRIDETT"; +const char* header = "TTSTRIDE"; const int header_size = 8; -const int keysize = 100; -const int fixedsize = 28; +const int key_and_iv_size = 16; int niraicall_onPreStart(int argc, char* argv[]) { @@ -24,7 +23,7 @@ int niraicall_onLoadGameData() fstream gd; // Open the file - gd.open("stride.dist", ios_base::in | ios_base::binary); + gd.open("TTSData.bin", ios_base::in | ios_base::binary); if (!gd.is_open()) { std::cerr << "Unable to open game file!" << std::endl; @@ -43,31 +42,61 @@ int niraicall_onLoadGameData() delete[] read_header; - // Extract the key - char* key = new char[keysize + fixedsize]; - char* fixed = new char[keysize]; - - for (int i = 0; i < fixedsize; ++i) - fixed[i] = (i ^ (5 * i + 7)) % ((i + 6) * 10); - - gd.read(key, keysize); - memcpy(&key[keysize], fixed, fixedsize); - + // Decrypt std::stringstream ss; + ss << gd.rdbuf(); gd.close(); - // Decrypt - std::string rawdata = ss.str(); - std::string decrypted_data = rc4(rawdata.c_str(), key, rawdata.size(), - keysize + fixedsize); + std::string brawdata = ss.str(); + + // Decrypted the encrypted key and iv + std::string enckeyandiv = brawdata.substr(0, (key_and_iv_size * 2) + key_and_iv_size); + + unsigned char* deckeyandiv = new unsigned char[enckeyandiv.size()]; + unsigned char* fixed_key = new unsigned char[key_and_iv_size]; + unsigned char* fixed_iv = new unsigned char[key_and_iv_size]; + + // Create fixed key and iv + + for (int i = 0; i < key_and_iv_size; ++i) + fixed_key[i] = (i ^ (7 * i + 16)) % ((i + 5) * 3); + + for (int i = 0; i < key_and_iv_size; ++i) + fixed_iv[i] = (i ^ (2 * i + 53)) % ((i + 9) * 6); + + int deckeyandivsize = AES_decrypt((unsigned char*)enckeyandiv.c_str(), enckeyandiv.size(), fixed_key, fixed_iv, deckeyandiv); + + delete[] fixed_key; + delete[] fixed_iv; + + unsigned char* key = new unsigned char[key_and_iv_size]; + unsigned char* iv = new unsigned char[key_and_iv_size]; + + // Move the decrypted key and iv into their subsequent char + + for (int i = 0; i < key_and_iv_size; ++i) + iv[i] = deckeyandiv[i]; + + for (int i = 0; i < key_and_iv_size; ++i) + key[i] = deckeyandiv[i + key_and_iv_size]; + + delete[] deckeyandiv; + + // Decrypt the game data + std::string rawdata = brawdata.substr((key_and_iv_size * 2) + key_and_iv_size); + unsigned char* decrypted_data = new unsigned char[rawdata.size()]; + + int decsize = AES_decrypt((unsigned char*)rawdata.c_str(), rawdata.size(), key, iv, decrypted_data); // Assumes no error + delete[] key; - delete[] fixed; + delete[] iv; + + // Read - // Decompress and read - std::string decompressed = decompress_string(decrypted_data); + // TODO: Compression - Datagram dg(decompressed); + Datagram dg(decrypted_data, decsize); DatagramIterator dgi(dg); unsigned int num_modules = dgi.get_uint32(); @@ -102,12 +131,30 @@ int niraicall_onLoadGameData() return 1; } + delete[] decrypted_data; + memset(&fzns[num_modules], 0, sizeof(_frozen)); PyImport_FrozenModules = fzns; - + + delete[] &fzns; + // libpandadna init_libpandadna(); initlibpandadna(); return 0; } + +extern "C" PyObject* niraicall_deobfuscate(char* code, Py_ssize_t size) +{ + std::string codestr(code, size); + + const char key[12] = {'B', 'A', 'Q', 'J', 'R', 'P', 'Z', 'P', 'A', 'H', 'U', 'T'}; + std::string output = codestr; + + for (int i = 0; i < codestr.size(); i++) + output[i] = codestr[i] ^ key[i % (sizeof(key) / sizeof(char))]; + + std::reverse(output.begin(), output.end()); + return PyString_FromStringAndSize(output.data(), size); +} diff --git a/dependencies/astron/astrond b/dependencies/astron/astrond index a1bf9fab..1ffd4e28 100755 Binary files a/dependencies/astron/astrond and b/dependencies/astron/astrond differ diff --git a/dependencies/astron/astrond.exe b/dependencies/astron/astrond.exe index a055fb03..4fdfc6dc 100755 Binary files a/dependencies/astron/astrond.exe and b/dependencies/astron/astrond.exe differ diff --git a/dependencies/astron/config/cluster.yml b/dependencies/astron/config/cluster.yml index 63ea9f74..ba1c9049 100644 --- a/dependencies/astron/config/cluster.yml +++ b/dependencies/astron/config/cluster.yml @@ -51,7 +51,7 @@ roles: max: 399999999 backend: type: yaml - foldername: ../databases/astrondb + directory: ../databases/astrondb - type: dbss database: 4003 diff --git a/dependencies/astron/dclass/stride.dc b/dependencies/astron/dclass/stride.dc index bc053e3c..5cc646c6 100644 --- a/dependencies/astron/dclass/stride.dc +++ b/dependencies/astron/dclass/stride.dc @@ -133,7 +133,7 @@ dclass DistributedAvatar : DistributedSmoothNode { friendsNotify(DoId avId, int8 status) ownrecv airecv; checkAvOnShard(DoId) clsend airecv; confirmAvOnShard(DoId avId, int8 isOnShard); - setTalk(string(0-400) chat) broadcast; + setTalk(string(0-400) chat) broadcast ram; setTalkWhisper(uint32 avId, string(0-400) chat) ownrecv clsend; }; @@ -590,8 +590,8 @@ dclass DistributedToon : DistributedPlayer { setTrackAccess(uint16[] = [0,0,0,0,1,1,0]) required broadcast ownrecv db; setTrackProgress(int8 = -1, uint32 = 0) required ownrecv db; setTrackBonusLevel(int8[] = [-1,-1,-1,-1,-1,-1,-1]) required broadcast ownrecv db; - setInventory(blob = [0*7, 0*7, 0*7, 0*7, 0, 0*6, 0, 0*6, 0*7]) required ownrecv db; - setNPCFriendsDict(FriendEntry[] = []) required ownrecv db; + setInventory(blob = [0*7, 0*7, 0*7, 0*7, 0, 0*6, 0, 0*6, 0*7]) required broadcast ownrecv db; + setNPCFriendsDict(FriendEntry[] = []) required broadcast ownrecv db; setDefaultShard(uint32 = 0) required ownrecv broadcast db; setDefaultZone(uint32 = 0) required ownrecv broadcast db; setHoodsVisited(uint32[] = [ 2000 ]) required ownrecv db; @@ -755,6 +755,7 @@ dclass DistributedToon : DistributedPlayer { requestNametagStyle(uint8) airecv ownsend; requestFishingRod(uint8) airecv ownsend; wipeStats() airecv ownsend; + takeMoney(int16) airecv ownsend; }; dclass DistributedPartyGate : DistributedObject { @@ -2048,7 +2049,6 @@ dclass DistributedCloset : DistributedFurnitureItem { setDNA(blob, int8, uint8) airecv clsend; setState(uint8, uint32, uint32, string, uint8[], uint8[]) broadcast ram; setMovie(uint8, uint32, int16) broadcast ram; - resetItemLists() broadcast ram; setCustomerDNA(uint32, blob) broadcast ram; }; @@ -3202,7 +3202,7 @@ dclass TTSFriendsManager : DistributedObjectGlobal { goingOffline(uint32 avId); getAvatarDetails(uint32) clsend; - friendDetails(uint32, blob, uint16[], int16, int16, uint32, uint32, blob, blob, int8[]); + friendDetails(uint32, blob, uint16[], int16, int16, uint32, uint32, blob, blob, int8[], FriendEntry[]); getPetDetails(uint32) clsend; petDetails(uint32, uint32, string, uint32, uint32, uint16/1000[], PetTrait[], int8[], uint32); diff --git a/dependencies/astron/mongoclient.dll b/dependencies/astron/mongoclient.dll new file mode 100644 index 00000000..c06f12b3 Binary files /dev/null and b/dependencies/astron/mongoclient.dll differ diff --git a/dependencies/config/release/dev.prc b/dependencies/config/release/dev.prc index b1db0ec3..2a5a03ef 100644 --- a/dependencies/config/release/dev.prc +++ b/dependencies/config/release/dev.prc @@ -25,6 +25,8 @@ accountdb-type developer shard-low-pop 50 shard-mid-pop 100 +game-type developer + # RPC: want-rpc-server #f rpc-server-endpoint http://localhost:8080/ diff --git a/deployment/deploy.json b/deployment/deploy.json index 6e6eb8c3..0105cd1a 100644 --- a/deployment/deploy.json +++ b/deployment/deploy.json @@ -1,8 +1,8 @@ { "__fyi__": "If you use anything other than the first 7 characters of the git hash, you just broke everything", - "astron": "6b769e6", + "astron": "696a6c4", "panda3d": "b924139", "libpandadna": "a0047ce", - "version-prefix": "ttstride-alpha-", + "version-prefix": "stride-beta-", "server-resources": ["pdna", "txt", "dat", "bam", "ttf"] } diff --git a/deployment/public_client.prc b/deployment/public_client.prc index f7190d31..e3c03fe6 100644 --- a/deployment/public_client.prc +++ b/deployment/public_client.prc @@ -3,17 +3,25 @@ # Config.prc should be reproduced here. # Client settings -window-title Toontown Stride +window-title Toontown Stride [Beta] server-version SERVER_VERSION_HERE -audio-library-name p3openal_audio video-library-name p3ffmpeg want-dev #f preload-avatars #t +game-type remote + +# Graphics: +aux-display pandagl +aux-display pandadx9 +aux-display p3tinydisplay + # Textures: texture-anisotropic-degree 16 +server-timezone EST/EDT/-5 + # Resources settings model-path / @@ -43,7 +51,6 @@ default-model-extension .bam want-pets #t want-parties #f want-cogdominiums #t -want-lawbot-cogdo #t want-anim-props #t want-game-tables #t want-find-four #t @@ -51,9 +58,9 @@ want-chinese-checkers #t want-checkers #t want-house-types #t want-gifting #t -want-top-toons #f +want-top-toons #t want-language-selection #t -estate-day-night #t +estate-day-night #f want-mat-all-tailors #t @@ -67,14 +74,12 @@ want-dev #f want-pstats 0 -# Crates: -dont-destroy-crate #t -get-key-reward-always #t -get-crate-reward-always #t - - # Chat: -want-whitelist #t +want-whitelist #f +want-sequence-list #f + +want-emblems #f +cogdo-want-barrel-room #f # @@ -84,5 +89,20 @@ want-instant-delivery #t cogdo-pop-factor 1.5 cogdo-ratio 0.5 default-directnotify-level info + +# Core features: +want-lawbot-cogdo #f + +# Crates: +dont-destroy-crate #t +get-key-reward-always #t +get-crate-reward-always #t # +# +dont-destroy-crate #f +get-key-reward-always #f +get-crate-reward-always #f +want-lawbot-cogdo #f +# + diff --git a/deployment/server.prc b/deployment/server.prc index 657b5f75..0d5c3337 100644 --- a/deployment/server.prc +++ b/deployment/server.prc @@ -12,7 +12,6 @@ cogsuit-hack-prevent #t want-pets #t want-parties #f want-cogdominiums #t -want-lawbot-cogdo #t want-anim-props #t want-game-tables #t want-find-four #t @@ -20,13 +19,32 @@ want-chinese-checkers #t want-checkers #t want-house-types #t want-gifting #t -want-top-toons #f +want-top-toons #t want-language-selection #t -estate-day-night #t +estate-day-night #f want-mat-all-tailors #t is-server #t +# Developer options: +show-population #t +want-instant-parties #t +want-instant-delivery #t +cogdo-pop-factor 1.5 +cogdo-ratio 0.5 +default-directnotify-level info + +# Crates: +dont-destroy-crate #t +get-key-reward-always #t +get-crate-reward-always #t +want-lawbot-cogdo #f + +server-timezone EST/EDT/-5 + +want-emblems #f +cogdo-want-barrel-room #f + # Chat Settings -want-whitelist #t -want-sequence-list #t +want-whitelist #f +want-sequence-list #f diff --git a/deployment/toontown/ai/ServiceStart.py b/deployment/toontown/ai/ServiceStart.py index 9f1451de..b90fbb76 100644 --- a/deployment/toontown/ai/ServiceStart.py +++ b/deployment/toontown/ai/ServiceStart.py @@ -51,11 +51,12 @@ if ':' in host: port = int(port) simbase.air.connect(host, port) +gc.enable() + isServer = config.GetBool('is-server', False) try: run() - gc.enable() except SystemExit: raise except Exception: diff --git a/deployment/toontown/uberdog/ServiceStart.py b/deployment/toontown/uberdog/ServiceStart.py index 5c48e920..bce3f3e8 100644 --- a/deployment/toontown/uberdog/ServiceStart.py +++ b/deployment/toontown/uberdog/ServiceStart.py @@ -50,6 +50,11 @@ if ':' in host: port = int(port) simbase.air.connect(host, port) +isServer = config.GetBool('is-server', False) + +if isServer: + import datetime + try: run() except SystemExit: @@ -57,4 +62,9 @@ except SystemExit: except Exception: info = describeException() simbase.air.writeServerEvent('uberdog-exception', simbase.air.getAvatarIdFromSender(), simbase.air.getAccountIdFromSender(), info) - raise + + if isServer: + with open(config.GetString('ud-crash-log-name', '/opt/var/log/Uberdog-crash-%s.txt' % (datetime.datetime.now())), 'w+') as file: + file.write(info + "\n") + + raise \ No newline at end of file diff --git a/dev/win32/start-game.bat b/dev/win32/start-game.bat index 908e6c45..76089c1c 100755 --- a/dev/win32/start-game.bat +++ b/dev/win32/start-game.bat @@ -8,6 +8,7 @@ echo #1 - Localhost echo #2 - Dev Server echo #3 - Custom echo #4 - Local RemoteDB +echo #5 - Prod Server echo. :selection @@ -21,6 +22,8 @@ if %INPUT%==1 ( set TTS_GAMESERVER=167.114.220.172 ) else if %INPUT%==4 ( set TTS_GAMESERVER=127.0.0.1 +) else if %INPUT%==5 ( + SET TTS_GAMESERVER=lw2.ez-webz.com:7198 ) else if %INPUT%==3 ( echo. set /P TTS_GAMESERVER=Gameserver: @@ -59,6 +62,7 @@ echo =============================== cd ../../ +:main if %INPUT%==2 ( "C:\Panda3D-1.10.0\python\ppython.exe" -m toontown.toonbase.ToontownStartRemoteDB ) else if %INPUT%==4 ( @@ -66,5 +70,6 @@ if %INPUT%==2 ( ) else ( "C:\Panda3D-1.10.0\python\ppython.exe" -m toontown.toonbase.ToontownStart ) - pause + +goto main diff --git a/otp/ai/AIBase.py b/otp/ai/AIBase.py index 1f8b82b8..009ea062 100755 --- a/otp/ai/AIBase.py +++ b/otp/ai/AIBase.py @@ -115,9 +115,16 @@ class AIBase: self.taskMgr.add(self.__resetPrevTransform, 'resetPrevTransform', priority=-51) self.taskMgr.add(self.__ivalLoop, 'ivalLoop', priority=20) self.taskMgr.add(self.__igLoop, 'igLoop', priority=50) + if self.config.GetBool('garbage-collect-states', 1): + self.taskMgr.add(self.__garbageCollectStates, 'garbageCollectStates', priority=46) if self.AISleep >= 0 and (not self.AIRunningNetYield or self.AIForceSleep): self.taskMgr.add(self.__sleepCycleTask, 'aiSleep', priority=55) self.eventMgr.restart() + + def __garbageCollectStates(self, state): + TransformState.garbageCollect() + RenderState.garbageCollect() + return Task.cont def getRepository(self): return self.air diff --git a/otp/ai/AIBaseGlobal.py b/otp/ai/AIBaseGlobal.py index e58a89cb..10bc58c9 100755 --- a/otp/ai/AIBaseGlobal.py +++ b/otp/ai/AIBaseGlobal.py @@ -29,4 +29,4 @@ vfs = VirtualFileSystem.getGlobalPtr() mounts = ConfigVariableList('vfs-mount') for mount in mounts: mountfile, mountpoint = (mount.split(' ', 2) + [None, None, None])[:2] - vfs.mount(Filename(mountfile), Filename(mountpoint), 0) + vfs.mount(Filename(mountfile), Filename(mountpoint), 0) \ No newline at end of file diff --git a/otp/ai/BanManagerAI.py b/otp/ai/BanManagerAI.py index a008615e..ba5fd020 100755 --- a/otp/ai/BanManagerAI.py +++ b/otp/ai/BanManagerAI.py @@ -10,7 +10,7 @@ from direct.showbase.DirectObject import DirectObject class BanFSM(FSM): - def __init__(self, air, avId, comment, duration): + def __init__(self, air, avId, comment, duration, banner): FSM.__init__(self, 'banFSM-%s' % avId) self.air = air self.avId = avId @@ -21,10 +21,11 @@ class BanFSM(FSM): self.DISLid = None self.accountId = None self.avName = None + self.banner = banner def performBan(self, duration): executeHttpRequest('ban', username=self.accountId, start=int(time.time()), - duration=duration, reason=self.comment, bannedby='todo') + duration=duration, reason=self.comment, bannedby=self.banner) def ejectPlayer(self): av = self.air.doId2do.get(self.avId) @@ -41,7 +42,7 @@ class BanFSM(FSM): simbase.air.send(datagram) def dbCallback(self, dclass, fields): - if dclass != self.air.dclassesByName['AccountAI']: + if dclass != simbase.air.dclassesByName['AccountAI']: return self.accountId = fields.get('ACCOUNT_ID') @@ -99,8 +100,8 @@ class BanManagerAI(DirectObject): self.air = air self.banFSMs = {} - def ban(self, avId, duration, comment): - self.banFSMs[avId] = BanFSM(self.air, avId, comment, duration) + def ban(self, avId, duration, comment, banner): + self.banFSMs[avId] = BanFSM(self.air, avId, comment, duration, banner) self.banFSMs[avId].request('Start') self.acceptOnce(self.air.getAvatarExitEvent(avId), self.banDone, [avId]) @@ -136,5 +137,6 @@ def ban(reason, duration): return "You can't ban yourself!" if reason not in ('hacking', 'language', 'other'): return "'%s' is not a valid reason." % reason - simbase.air.banManager.ban(target.doId, duration, reason) + banner = spellbook.getInvoker().DISLid + simbase.air.banManager.ban(target.doId, duration, reason, banner) return "Banned %s from the game server!" % target.getName() diff --git a/otp/avatar/Avatar.py b/otp/avatar/Avatar.py index d9db1a27..75e7a584 100755 --- a/otp/avatar/Avatar.py +++ b/otp/avatar/Avatar.py @@ -67,6 +67,7 @@ class Avatar(Actor, ShadowCaster): self.__chatSet = 0 self.__chatLocal = 0 self.__currentDialogue = None + self.wantAdminTag = True def delete(self): try: @@ -172,6 +173,12 @@ class Avatar(Actor, ShadowCaster): def getType(self): return self.avatarType + + def setWantAdminTag(self, bool): + self.wantAdminTag = bool + + def getWantAdminTag(self): + return self.wantAdminTag def setName(self, name): if hasattr(self, 'isDisguised') and self.isDisguised: @@ -194,7 +201,7 @@ class Avatar(Actor, ShadowCaster): self.nametag.setName(name) - if hasattr(self, 'adminAccess') and self.isAdmin(): + if hasattr(self, 'adminAccess') and self.isAdmin() and self.getWantAdminTag(): access = self.getAdminAccess() if access in OTPLocalizer.AccessToString: @@ -553,11 +560,9 @@ class Avatar(Actor, ShadowCaster): return sequence -@magicWord(category=CATEGORY_COMMUNITY_MANAGER, types=[]) +@magicWord(category=CATEGORY_COMMUNITY_MANAGER) def target(): """ Returns the current Spellbook target. """ - target = spellbook.getTarget() - - return 'Target: %s-%d [%d]' % (target.getName(), int(target.doId), int(target.getAdminAccess())) \ No newline at end of file + return 'Your current target is: %s [avId: %s, access: %s]' % (spellbook.getTarget().getName(), spellbook.getTarget().doId, spellbook.getTarget().getAdminAccess()) \ No newline at end of file diff --git a/otp/avatar/LocalAvatar.py b/otp/avatar/LocalAvatar.py index 36a4a29b..b19d5672 100755 --- a/otp/avatar/LocalAvatar.py +++ b/otp/avatar/LocalAvatar.py @@ -1125,9 +1125,6 @@ class LocalAvatar(DistributedAvatar.DistributedAvatar, DistributedSmoothNode.Dis def d_setParent(self, parentToken): DistributedSmoothNode.DistributedSmoothNode.d_setParent(self, parentToken) - def canChat(self): - return 0 - @magicWord(category=CATEGORY_COMMUNITY_MANAGER) def run(): diff --git a/otp/chat/ChatAgent.py b/otp/chat/ChatAgent.py index cd0a539b..37d69a2a 100755 --- a/otp/chat/ChatAgent.py +++ b/otp/chat/ChatAgent.py @@ -1,5 +1,6 @@ from direct.distributed.DistributedObjectGlobal import DistributedObjectGlobal from otp.ai.MagicWordGlobal import * +from otp.avatar import Avatar class ChatAgent(DistributedObjectGlobal): diff --git a/otp/chat/ChatAgentUD.py b/otp/chat/ChatAgentUD.py index 1ece070f..5b816f13 100755 --- a/otp/chat/ChatAgentUD.py +++ b/otp/chat/ChatAgentUD.py @@ -11,7 +11,7 @@ OFFENSE_MSGS = ('-- DEV CHAT -- word blocked: %s', 'Watch your language! This is class ChatAgentUD(DistributedObjectGlobalUD): notify = DirectNotifyGlobal.directNotify.newCategory('ChatAgentUD') - WantWhitelist = config.GetBool('want-whitelist', True) + wantWhitelist = config.GetBool('want-whitelist', True) chatMode2channel = { 1 : OtpDoGlobals.OTP_MOD_CHANNEL, @@ -36,17 +36,12 @@ class ChatAgentUD(DistributedObjectGlobalUD): 'Account sent chat without an avatar', message) return - if chatMode == 0: + if chatMode == 0 and self.wantWhitelist: if self.detectBadWords(self.air.getMsgSender(), message): return self.air.writeServerEvent('chat-said', sender, message) - - DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD'] - dg = DistributedAvatar.aiFormatUpdate('setTalk', sender, sender, - self.air.ourChannel, - [message]) - self.air.send(dg) + self.air.send(self.air.dclassesByName['DistributedAvatarUD'].aiFormatUpdate('setTalk', sender, sender, self.air.ourChannel, [message])) def detectBadWords(self, sender, message): words = message.split() diff --git a/otp/chat/ChatManager.py b/otp/chat/ChatManager.py index f7ec7676..05779a5f 100755 --- a/otp/chat/ChatManager.py +++ b/otp/chat/ChatManager.py @@ -123,7 +123,7 @@ class ChatManager(DirectObject.DirectObject): def enterMainMenu(self): self.checkObscurred() - if self.localAvatar.canChat(): + if base.cr.wantTypedChat(): if self.wantBackgroundFocus: self.chatInputNormal.chatEntry['backgroundFocus'] = 1 self.acceptOnce('enterNormalChat', self.fsm.request, ['normalChat']) diff --git a/otp/distributed/OTPClientRepository.py b/otp/distributed/OTPClientRepository.py index 8bce5800..72abea04 100755 --- a/otp/distributed/OTPClientRepository.py +++ b/otp/distributed/OTPClientRepository.py @@ -18,6 +18,7 @@ from otp.otpbase import OTPGlobals, OTPLocalizer from otp.otpgui import OTPDialog from otp.nametag.NametagConstants import * import sys, time, types, random +import __builtin__ class OTPClientRepository(ClientRepositoryBase): notify = directNotify.newCategory('OTPClientRepository') @@ -222,7 +223,7 @@ class OTPClientRepository(ClientRepositoryBase): if dcFileNames == None: try: # For Nirai - readResult = dcFile.read(dcStream, '__dc__') + readResult = dcFile.read(dcStream) del __builtin__.dcStream except NameError: @@ -468,7 +469,7 @@ class OTPClientRepository(ClientRepositoryBase): self.handler = self.handleMessageType messenger.send('connectionIssue') url = self.serverList[0] - self.notify.warning('Failed to connect to %s (%s %s). Notifying user.' % (url.cStr(), statusCode, statusString)) + self.notify.warning('Failed to connect to %s (%s %s). Notifying user.' % (config.GetString('TTS_GAMESERVER'), statusCode, statusString)) dialogClass = OTPGlobals.getGlobalDialogClass() self.failedToConnectBox = dialogClass(message=OTPLocalizer.CRNoConnectTryAgain % (url.getServer(), url.getPort()), doneEvent='failedToConnectAck', text_wordwrap=18, style=OTPDialog.TwoChoice) self.failedToConnectBox.show() @@ -624,7 +625,7 @@ class OTPClientRepository(ClientRepositoryBase): else: message = OTPLocalizer.CRLostConnection reconnect = 1 - if self.bootedIndex in (152, 127): + if self.bootedIndex in (152, 127, 124, 101, 102, 103): reconnect = 0 if self.bootedIndex == 152: message = message % {'name': self.bootedText} diff --git a/otp/otpbase/OTPGlobals.py b/otp/otpbase/OTPGlobals.py index 8c989807..a80d95a7 100755 --- a/otp/otpbase/OTPGlobals.py +++ b/otp/otpbase/OTPGlobals.py @@ -76,8 +76,8 @@ InterfaceFont = None InterfaceFontPath = None SignFont = None SignFontPath = None -FancyFont = None -FancyFontPath = None +ChalkFont = None +ChalkFontPath = None NametagFonts = {} NametagFontPaths = {} DialogClass = None @@ -115,20 +115,20 @@ def setSignFont(path): global SignFontPath SignFontPath = path -def getFancyFont(): - global FancyFontPath - global FancyFont - if FancyFont == None: - if FancyFontPath == None: +def getChalkFont(): + global ChalkFontPath + global ChalkFont + if ChalkFont == None: + if ChalkFontPath == None: InterfaceFont = TextNode.getDefaultFont() - FancyFont = TextNode.getDefaultFont() + ChalkFont = TextNode.getDefaultFont() else: - FancyFont = loader.loadFont(FancyFontPath, lineHeight=1.0) - return FancyFont + ChalkFont = loader.loadFont(ChalkFontPath, lineHeight=1.0) + return ChalkFont -def setFancyFont(path): - global FancyFontPath - FancyFontPath = path +def setChalkFont(path): + global ChalkFontPath + ChalkFontPath = path def getNametagFont(index): global NametagFontPaths diff --git a/otp/otpbase/OTPLocalizerEnglish.py b/otp/otpbase/OTPLocalizerEnglish.py index 71a80095..7878f6f8 100755 --- a/otp/otpbase/OTPLocalizerEnglish.py +++ b/otp/otpbase/OTPLocalizerEnglish.py @@ -132,6 +132,7 @@ CRBootedReasons = {100: 'You have been disconnected because someone else just lo 102: 'You are not authorized to use administrator privileges.', 103: 'You were banned by a moderator.\n\nBehave next time!', 105: 'Toontown Stride is now temporarily closed for maintenance. Everyone who was playing has been disconnected from the game.\n\nFor more information, please visit the Toontown Stride website.', + 124: 'Your installed files are out of date! Use the official launcher to download the newest version, or contact Toontown Stride Support if the problem persists.', 153: 'The district you were playing on has been reset. Everyone who was playing on that district has been disconnected. However, you should be able to connect again and go right back into the game.', 166: 'You were disconnected to prevent a district reset.'} CRBootedReasonUnknownCode = 'An unexpected problem has occurred (error code %s). Your connection has been lost, but you should be able to connect again and go right back into the game.' @@ -291,7 +292,6 @@ EmoteList = ['Wave', 'Delighted', 'Furious', 'Laugh', - 'Taunt', 'Rage'] EmoteWhispers = ['%s waves.', '%s is happy.', @@ -318,7 +318,6 @@ EmoteWhispers = ['%s waves.', '%s is delighted.', '%s is furious.', '%s is laughing.', - '%s taunts you.', '%s is raging.'] EmoteFuncDict = {'Wave': 0, 'Happy': 1, @@ -345,8 +344,7 @@ EmoteFuncDict = {'Wave': 0, 'Delighted': 22, 'Furious': 23, 'Laugh': 24, - 'Taunt': 25, - 'Rage': 26} + 'Rage': 25} SuitBrushOffs = {'f': ["I'm late for a meeting."], 'p': ['Push off.'], 'ym': ['Yes Man says NO.'], diff --git a/resources b/resources index 769d2639..af09e769 160000 --- a/resources +++ b/resources @@ -1 +1 @@ -Subproject commit 769d26390634d17384aa28021cc7afd88306c4af +Subproject commit af09e769b860512c03de6fff4a585e96d674e89b diff --git a/toontown/ai/DistributedReportMgrAI.py b/toontown/ai/DistributedReportMgrAI.py index 02122868..7fd4724d 100755 --- a/toontown/ai/DistributedReportMgrAI.py +++ b/toontown/ai/DistributedReportMgrAI.py @@ -3,6 +3,12 @@ from direct.distributed.DistributedObjectAI import DistributedObjectAI from toontown.uberdog.ClientServicesManagerUD import executeHttpRequestAndLog import ReportGlobals, threading, time +# TODO: FIX + +''' +THREADING.TIMER CAUSES CONTROL C NOT TO WORK, AND FOR THE AI NOT TO DIE +''' + class DistributedReportMgrAI(DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedReportMgrAI") @@ -10,10 +16,10 @@ class DistributedReportMgrAI(DistributedObjectAI): DistributedObjectAI.__init__(self, air) self.reports = [] self.interval = config.GetInt('report-interval', 600) - self.scheduleReport() + #self.scheduleReport() - def scheduleReport(self): - threading.Timer(self.interval, self.sendAllReports).start() + #def scheduleReport(self): + # threading.Timer(self.interval, self.sendAllReports).start() def sendReport(self, avId, category): if not ReportGlobals.isValidCategoryName(category) or not len(str(avId)) == 9: @@ -28,7 +34,7 @@ class DistributedReportMgrAI(DistributedObjectAI): self.reports.append('%s|%s|%s|%s' % (timestamp, reporter.doId, avId, category)) def sendAllReports(self): - self.scheduleReport() + #self.scheduleReport() if not self.reports or config.GetString('accountdb-type', 'developer') != 'remote': return diff --git a/toontown/ai/HolidayGlobals.py b/toontown/ai/HolidayGlobals.py index 4935d6af..4910516b 100644 --- a/toontown/ai/HolidayGlobals.py +++ b/toontown/ai/HolidayGlobals.py @@ -28,8 +28,10 @@ Holidays = { 'endMessage': TTLocalizer.SillySaturdayEnd }, ToontownGlobals.BLACK_CAT_DAY: { - 'startDay': 13, - 'endDay': 13, + 'startMonth': 10, + 'startDay': 31, + 'endMonth': 10, + 'endDay': 31, 'startMessage': TTLocalizer.BlackCatHolidayStart, 'ongoingMessage': TTLocalizer.BlackCatHolidayStart, 'endMessage': TTLocalizer.BlackCatHolidayEnd diff --git a/toontown/ai/NewsManagerAI.py b/toontown/ai/NewsManagerAI.py index f55a8eaf..f4f97419 100755 --- a/toontown/ai/NewsManagerAI.py +++ b/toontown/ai/NewsManagerAI.py @@ -47,7 +47,7 @@ class NewsManagerAI(DistributedObjectAI): return self.activeHolidays def __checkHolidays(self, task=None): - date = datetime.datetime.utcnow().replace(tzinfo=HolidayGlobals.TIME_ZONE) + date = datetime.datetime.now(HolidayGlobals.TIME_ZONE) for id in HolidayGlobals.Holidays: holiday = HolidayGlobals.Holidays[id] diff --git a/toontown/ai/QuestManagerAI.py b/toontown/ai/QuestManagerAI.py index 8be875d0..c7a50c95 100755 --- a/toontown/ai/QuestManagerAI.py +++ b/toontown/ai/QuestManagerAI.py @@ -81,7 +81,7 @@ class QuestManagerAI: # If it's a TrackChoiceQuest then present their track choices. if isinstance(questClass, Quests.TrackChoiceQuest): - npc.presentTrackChoice(avId, questId, questClass.getChoices(av)) + npc.presentTrackChoice(avId, questId, questClass.getChoices()) break # If there is another part to this quest then give them that. if Quests.getNextQuest(questId, npc, av)[0] != Quests.NA: diff --git a/toontown/ai/ServiceStart.py b/toontown/ai/ServiceStart.py index d606d6f5..4899cc4c 100755 --- a/toontown/ai/ServiceStart.py +++ b/toontown/ai/ServiceStart.py @@ -62,11 +62,10 @@ if ':' in host: port = int(port) simbase.air.connect(host, port) -isServer = config.GetBool('is-server', False) +gc.enable() try: run() - gc.enable() except SystemExit: raise except Exception: @@ -74,9 +73,4 @@ except Exception: simbase.air.writeServerEvent('ai-exception', avId=simbase.air.getAvatarIdFromSender(), accId=simbase.air.getAccountIdFromSender(), exception=info) - if isServer: - import datetime - with open(config.GetString('ai-crash-log-name', '/opt/var/log/%s-ai-crash-%s.txt' % (config.GetString('district-name', 'Devhaven'), datetime.datetime.now())), 'w+') as file: - file.write(info + "\n") - raise diff --git a/toontown/ai/ToontownAIRepository.py b/toontown/ai/ToontownAIRepository.py index f42a45b6..958e3f1c 100755 --- a/toontown/ai/ToontownAIRepository.py +++ b/toontown/ai/ToontownAIRepository.py @@ -52,6 +52,7 @@ from toontown.tutorial.TutorialManagerAI import TutorialManagerAI from toontown.uberdog.DistributedPartyManagerAI import DistributedPartyManagerAI from toontown.uberdog.TopToonsManagerAI import TopToonsManagerAI #from toontown.uberdog.DistributedLobbyManagerAI import DistributedLobbyManagerAI +import threading class ToontownAIRepository(ToontownInternalRepository): def __init__(self, baseChannel, stateServerChannel, districtName): @@ -180,6 +181,9 @@ class ToontownAIRepository(ToontownInternalRepository): def handleConnected(self): ToontownInternalRepository.handleConnected(self) + threading.Thread(target=self.startDistrict).start() + + def startDistrict(self): self.districtId = self.allocateChannel() self.notify.info('Creating ToontownDistrictAI(%d)...' % self.districtId) self.distributedDistrict = ToontownDistrictAI(self) diff --git a/toontown/battle/BattleBase.py b/toontown/battle/BattleBase.py index 4500b89c..c3797665 100755 --- a/toontown/battle/BattleBase.py +++ b/toontown/battle/BattleBase.py @@ -229,8 +229,8 @@ class BattleBase: posA] suitSpeed = 4.8 toonSpeed = 8.0 - maxTimeToon = 10.0 - maxTimeSuit = 11.0 + maxTimeToon = 3.0 + maxTimeSuit = 4.0 def __init__(self): self.pos = Point3(0, 0, 0) diff --git a/toontown/battle/DistributedBattleBaseAI.py b/toontown/battle/DistributedBattleBaseAI.py index 95228535..3c1b31cc 100755 --- a/toontown/battle/DistributedBattleBaseAI.py +++ b/toontown/battle/DistributedBattleBaseAI.py @@ -993,6 +993,7 @@ class DistributedBattleBaseAI(DistributedObjectAI.DistributedObjectAI, BattleBas self.notify.warning('requestAttack() - no toon: %d' % toonId) return validResponse = 1 + self.npcAttacks = {k:v for k, v in self.npcAttacks.iteritems() if v != toonId} if track == SOS: self.notify.debug('toon: %d calls for help' % toonId) self.air.writeServerEvent('friendSOS', toonId, '%s' % av) @@ -1007,7 +1008,7 @@ class DistributedBattleBaseAI(DistributedObjectAI.DistributedObjectAI, BattleBas npcCollision = 0 if av in self.npcAttacks: callingToon = self.npcAttacks[av] - if self.activeToons.count(callingToon) == 1: + if callingToon != toonId and self.activeToons.count(callingToon) == 1: self.toonAttacks[toonId] = getToonAttack(toonId, track=PASS) npcCollision = 1 if npcCollision == 0: diff --git a/toontown/battle/MovieUtil.py b/toontown/battle/MovieUtil.py index 9590761e..be47b06b 100755 --- a/toontown/battle/MovieUtil.py +++ b/toontown/battle/MovieUtil.py @@ -255,17 +255,13 @@ def createSuitReviveTrack(suit, toon, battle, npcs = []): if hasattr(suit, 'battleTrapProp') and suit.battleTrapProp and suit.battleTrapProp.getName() == 'traintrack' and not suit.battleTrapProp.isHidden(): suitTrack.append(createTrainTrackAppearTrack(suit, toon, battle, npcs)) deathSuit = suit.getLoseActor() - suitTrack.append(Func(notify.debug, 'before insertDeathSuit')) suitTrack.append(Func(insertReviveSuit, suit, deathSuit, battle, suitPos, suitHpr)) - suitTrack.append(Func(notify.debug, 'before actorInterval lose')) suitTrack.append(ActorInterval(deathSuit, 'lose', duration=SUIT_LOSE_REVIVE_DURATION)) - suitTrack.append(Func(notify.debug, 'before removeDeathSuit')) suitTrack.append(Func(removeReviveSuit, suit, deathSuit, name='remove-death-suit')) - suitTrack.append(Func(notify.debug, 'after removeDeathSuit')) suitTrack.append(ActorInterval(suit, 'slip-forward', startTime=2.48, duration=0.1)) suitTrack.append(ActorInterval(suit, 'slip-forward', startTime=2.58)) suitTrack.append(Func(suit.loop, 'neutral')) - suitTrack.append(Func(messenger.send, suit.uniqueName('hpChange'))) + suitTrack.append(Func(suit.setHP, suit.getMaxHP())) spinningSound = base.loadSfx('phase_3.5/audio/sfx/Cog_Death.ogg') deathSound = base.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart_%s.ogg' % random.randint(1, 6)) deathSoundTrack = Sequence(Wait(0.8), SoundInterval(spinningSound, duration=1.2, startTime=1.5, volume=0.2), SoundInterval(spinningSound, duration=3.0, startTime=0.6, volume=0.8), SoundInterval(deathSound, volume=0.32)) diff --git a/toontown/battle/RewardPanel.py b/toontown/battle/RewardPanel.py index 625cd61e..3acc9dd7 100755 --- a/toontown/battle/RewardPanel.py +++ b/toontown/battle/RewardPanel.py @@ -434,10 +434,10 @@ class RewardPanel(DirectFrame): def getTrackIntervalList(self, toon, track, origSkill, earnedSkill, hasUber): if hasUber < 0: print (toon.doId, 'Reward Panel received an invalid hasUber from an uberList') - tickDelay = 1.0 / 60 + tickDelay = 0.1 intervalList = [] intervalList.append(Func(self.showTrackIncLabel, track, earnedSkill)) - barTime = 0.5 + barTime = math.log(earnedSkill + 0.5) numTicks = int(math.ceil(barTime / tickDelay)) for i in xrange(numTicks): t = (i + 1) / float(numTicks) @@ -463,9 +463,9 @@ class RewardPanel(DirectFrame): uberSkill = ToontownBattleGlobals.UberSkill + ToontownBattleGlobals.Levels[track][ToontownBattleGlobals.LAST_REGULAR_GAG_LEVEL + 1] if currentSkill >= uberSkill and not hasUber > 0: intervalList += self.getUberGagIntervalList(toon, track, ToontownBattleGlobals.LAST_REGULAR_GAG_LEVEL + 1) - intervalList.append(Wait(0.1)) + intervalList.append(Wait(0.3)) skillDiff = currentSkill - ToontownBattleGlobals.Levels[track][ToontownBattleGlobals.LAST_REGULAR_GAG_LEVEL + 1] - barTime = math.log(skillDiff + 1) + barTime = math.log(skillDiff + 0.5) numTicks = int(math.ceil(barTime / tickDelay)) displayedSkillDiff = skillDiff if displayedSkillDiff > ToontownBattleGlobals.UberSkill: @@ -477,18 +477,18 @@ class RewardPanel(DirectFrame): intervalList.append(Func(self.incrementExp, track, newValue, toon)) intervalList.append(Wait(tickDelay * 0.5)) - intervalList.append(Wait(0.1)) + intervalList.append(Wait(0.3)) return intervalList def getMeritIntervalList(self, toon, dept, origMerits, earnedMerits): - tickDelay = 1.0 / 60 + tickDelay = 0.08 intervalList = [] totalMerits = CogDisguiseGlobals.getTotalMerits(toon, dept) neededMerits = 0 if totalMerits and origMerits != totalMerits: neededMerits = totalMerits - origMerits intervalList.append(Func(self.showMeritIncLabel, dept, min(neededMerits, earnedMerits))) - barTime = 0.5 + barTime = math.log(earnedMerits + 1) numTicks = int(math.ceil(barTime / tickDelay)) for i in xrange(numTicks): t = (i + 1) / float(numTicks) @@ -497,10 +497,10 @@ class RewardPanel(DirectFrame): intervalList.append(Wait(tickDelay)) intervalList.append(Func(self.resetMeritBarColor, dept)) - intervalList.append(Wait(0.1)) + intervalList.append(Wait(0.3)) if toon.cogLevels[dept] < ToontownGlobals.MaxCogSuitLevel: if neededMerits and toon.readyForPromotion(dept): - intervalList.append(Wait(0.4)) + intervalList.append(Wait(0.3)) intervalList += self.getPromotionIntervalList(toon, dept) return intervalList @@ -621,7 +621,7 @@ class RewardPanel(DirectFrame): if earned > 0: earned = min(earned, quest.getNumQuestItems() - questDesc[4]) if earned > 0 or base.localAvatar.tutorialAck == 0 and num == 1: - barTime = 0.5 + barTime = math.log(earned + 1) numTicks = int(math.ceil(barTime / tickDelay)) for i in xrange(numTicks): t = (i + 1) / float(numTicks) @@ -683,19 +683,19 @@ class RewardPanel(DirectFrame): if meritList[dept]: track += self.getMeritIntervalList(toon, dept, origMeritList[dept], meritList[dept]) - track.append(Wait(0.75)) + track.append(Wait(1.0)) itemInterval = self.getItemIntervalList(toon, itemList) if itemInterval: track.append(Func(self.initItemFrame, toon)) - track.append(Wait(0.25)) + track.append(Wait(1.0)) track += itemInterval - track.append(Wait(0.5)) + track.append(Wait(1.0)) missedItemInterval = self.getMissedItemIntervalList(toon, missedItemList) if missedItemInterval: track.append(Func(self.initMissedItemFrame, toon)) - track.append(Wait(0.25)) + track.append(Wait(1.0)) track += missedItemInterval - track.append(Wait(0.5)) + track.append(Wait(1.0)) self.notify.debug('partList = %s' % partList) newPart = 0 for part in partList: @@ -707,9 +707,9 @@ class RewardPanel(DirectFrame): partList = self.getCogPartIntervalList(toon, partList) if partList: track.append(Func(self.initCogPartFrame, toon)) - track.append(Wait(0.25)) + track.append(Wait(1.0)) track += partList - track.append(Wait(0.5)) + track.append(Wait(1.0)) questList = self.getQuestIntervalList(toon, deathList, toonList, origQuestsList, itemList, helpfulToonsList) if questList: avQuests = [] @@ -717,9 +717,9 @@ class RewardPanel(DirectFrame): avQuests.append(origQuestsList[i:i + 5]) track.append(Func(self.initQuestFrame, toon, copy.deepcopy(avQuests))) - track.append(Wait(0.25)) + track.append(Wait(1.0)) track += questList - track.append(Wait(0.5)) + track.append(Wait(2.0)) track.append(Wait(0.25)) if trackEnded: track.append(Func(self.vanishFrames)) diff --git a/toontown/battle/SuitBattleGlobals.py b/toontown/battle/SuitBattleGlobals.py index 36c9cdb3..df0c9b73 100755 --- a/toontown/battle/SuitBattleGlobals.py +++ b/toontown/battle/SuitBattleGlobals.py @@ -3170,3 +3170,18 @@ def getAttackTaunt(attackName, index = None): SuitAttackTaunts = TTLocalizer.SuitAttackTaunts +DisabledAttacks = ('Gavel', 'SongAndDance', 'SandTrap', 'FloodTheMarket', 'FiveOClockShadow') + +def getAttacksByType(attributes): + groupAttacks = [] + singleAttacks = [] + + for attack in sorted(attributes['attacks'], key=lambda x: x[0]): + if attack[0] in DisabledAttacks: + continue + if SuitAttacks[attack[0]][1] == ATK_TGT_GROUP: + groupAttacks.append(attack) + else: + singleAttacks.append(attack) + + return groupAttacks, singleAttacks \ No newline at end of file diff --git a/toontown/building/DistributedElevator.py b/toontown/building/DistributedElevator.py index 83b244fc..8f0ad08a 100755 --- a/toontown/building/DistributedElevator.py +++ b/toontown/building/DistributedElevator.py @@ -465,7 +465,6 @@ class DistributedElevator(DistributedObject.DistributedObject): del self.elevatorFSM elevator.signalDone(doneStatus) base.camLens.setMinFov(ToontownGlobals.CBElevatorFov/(4./3.)) - return def getElevatorModel(self): self.notify.error('getElevatorModel: pure virtual -- inheritors must override') @@ -530,10 +529,7 @@ class DistributedElevator(DistributedObject.DistributedObject): return self.offsetNP.getPos(render) def canHideBoardingQuitBtn(self, avId): - if avId == localAvatar.doId and hasattr(localAvatar, 'boardingParty') and localAvatar.boardingParty and localAvatar.boardingParty.groupPanel: - return True - else: - return False + return avId == localAvatar.doId and hasattr(localAvatar, 'boardingParty') and localAvatar.boardingParty and localAvatar.boardingParty.groupPanel def getBoardingTrack(self, toon, seatIndex, wantToonRotation): self.boardingGroupShow = BoardingGroupShow.BoardingGroupShow(toon) diff --git a/toontown/building/DistributedKnockKnockDoor.py b/toontown/building/DistributedKnockKnockDoor.py index a1bdde91..ac28c792 100755 --- a/toontown/building/DistributedKnockKnockDoor.py +++ b/toontown/building/DistributedKnockKnockDoor.py @@ -53,11 +53,7 @@ class DistributedKnockKnockDoor(DistributedAnimatedProp.DistributedAnimatedProp) def avatarExit(self, avatarId): if avatarId == self.avatarId: - for track in self.avatarTracks: - track.finish() - DelayDelete.cleanupDelayDeletes(track) - - self.avatarTracks = [] + self.stopTracks() def knockKnockTrack(self, avatar, duration): if avatar is None: @@ -96,7 +92,7 @@ class DistributedKnockKnockDoor(DistributedAnimatedProp.DistributedAnimatedProp) return track def cleanupTrack(self): - avatar = self.cr.doId2do.get(self.avatarId, None) + avatar = self.cr.doId2do.get(self.avatarId) if avatar: avatar.clearChat() if self.nametag: @@ -105,7 +101,6 @@ class DistributedKnockKnockDoor(DistributedAnimatedProp.DistributedAnimatedProp) self.nametag.destroy() self.nametag = None self.nametagNP = None - return def enterOff(self): DistributedAnimatedProp.DistributedAnimatedProp.enterOff(self) @@ -132,9 +127,13 @@ class DistributedKnockKnockDoor(DistributedAnimatedProp.DistributedAnimatedProp) def exitPlaying(self): DistributedAnimatedProp.DistributedAnimatedProp.exitPlaying(self) + self.stopTracks() + + def stopTracks(self): for track in self.avatarTracks: - track.finish() + track.pause() DelayDelete.cleanupDelayDeletes(track) + self.cleanupTrack() self.avatarTracks = [] self.avatarId = 0 diff --git a/toontown/building/DistributedKnockKnockDoorAI.py b/toontown/building/DistributedKnockKnockDoorAI.py index cc4ee465..67c6983e 100755 --- a/toontown/building/DistributedKnockKnockDoorAI.py +++ b/toontown/building/DistributedKnockKnockDoorAI.py @@ -10,6 +10,9 @@ class DistributedKnockKnockDoorAI(DistributedAnimatedPropAI.DistributedAnimatedP self.fsm.setName('DistributedKnockKnockDoor') self.propId = propId self.doLaterTask = None + + def delete(self): + DistributedAnimatedPropAI.DistributedAnimatedPropAI.delete(self) def enterOff(self): DistributedAnimatedPropAI.DistributedAnimatedPropAI.enterOff(self) diff --git a/toontown/building/DistributedSuitInterior.py b/toontown/building/DistributedSuitInterior.py index 8d7688dd..78386e6b 100755 --- a/toontown/building/DistributedSuitInterior.py +++ b/toontown/building/DistributedSuitInterior.py @@ -365,6 +365,7 @@ class DistributedSuitInterior(DistributedObject.DistributedObject): def enterResting(self, ts = 0): base.playMusic(self.waitMusic, looping=1, volume=0.7) + base.localAvatar.questMap.stop() self.__closeInElevator() def exitResting(self): diff --git a/toontown/building/ToonInterior.py b/toontown/building/ToonInterior.py index 0e39640d..fb2f05d8 100755 --- a/toontown/building/ToonInterior.py +++ b/toontown/building/ToonInterior.py @@ -176,16 +176,17 @@ class ToonInterior(Place.Place): def enterTeleportIn(self, requestStatus): modelType = DistributedToonInterior.DistributedToonInterior(base.cr).getModelType(self.getZoneId()) - if ZoneUtil.isHQ(self.zoneId): + if self.zoneId == ToontownGlobals.ToonHall: + base.localAvatar.setPosHpr(-63.5, 30.5, ToontownGlobals.FloorOffset, 90.0, 0.0, 0.0) + elif ZoneUtil.isHQ(self.zoneId): base.localAvatar.setPosHpr(-5.5, -1.5, ToontownGlobals.FloorOffset, 0.0, 0.0, 0.0) elif ZoneUtil.isPetshop(self.zoneId): base.localAvatar.setPosHpr(0, 0, ToontownGlobals.FloorOffset, 45.0, 0.0, 0.0) + elif modelType in InteriorTypes: + area = InteriorTypes[modelType] + base.localAvatar.setPosHpr(area[0], area[1], ToontownGlobals.FloorOffset, area[2], 0.0, 0.0) else: - if modelType in InteriorTypes: - area = InteriorTypes[modelType] - base.localAvatar.setPosHpr(area[0], area[1], ToontownGlobals.FloorOffset, area[2], 0.0, 0.0) - else: - base.localAvatar.setPosHpr(2.5, 11.5, ToontownGlobals.FloorOffset, 45.0, 0.0, 0.0) + base.localAvatar.setPosHpr(2.5, 11.5, ToontownGlobals.FloorOffset, 45.0, 0.0, 0.0) Place.Place.enterTeleportIn(self, requestStatus) def enterTeleportOut(self, requestStatus): diff --git a/toontown/catalog/CatalogFurnitureItem.py b/toontown/catalog/CatalogFurnitureItem.py index 089c403a..adb8a9e2 100755 --- a/toontown/catalog/CatalogFurnitureItem.py +++ b/toontown/catalog/CatalogFurnitureItem.py @@ -1059,7 +1059,7 @@ class CatalogFurnitureItem(CatalogAtticItem.CatalogAtticItem): return 24 * 60 def getPicture(self, avatar): - model = self.loadModel(animate=0) + model = self.loadModel() spin = 1 flags = self.getFlags() if flags & FLRug: @@ -1095,7 +1095,7 @@ class CatalogFurnitureItem(CatalogAtticItem.CatalogAtticItem): def getBasePrice(self): return FurnitureTypes[self.furnitureType][FTBasePrice] - def loadModel(self, animate=1): + def loadModel(self): type = FurnitureTypes[self.furnitureType] model = loader.loadModel(type[FTModelName]) self.applyColor(model, type[FTColor]) diff --git a/toontown/catalog/CatalogGenerator.py b/toontown/catalog/CatalogGenerator.py index 618f01d2..2de0d885 100755 --- a/toontown/catalog/CatalogGenerator.py +++ b/toontown/catalog/CatalogGenerator.py @@ -535,13 +535,12 @@ MonthlySchedule = ((7, CatalogClothingItem(1606, 0, True), CatalogClothingItem(1603, 0, True), CatalogClothingItem(1600, 0, True), - CatalogEmoteItem(25, True), - CatalogEmoteItem(26, True), CatalogEmoteItem(20, True), CatalogEmoteItem(21, True), CatalogEmoteItem(22, True), CatalogEmoteItem(23, True), CatalogEmoteItem(24, True), + CatalogEmoteItem(25, True), CatalogClothingItem(1821, 0, True))), (5, 26, diff --git a/toontown/chat/ToontownChatManager.py b/toontown/chat/ToontownChatManager.py index 80301e3f..b0b89382 100755 --- a/toontown/chat/ToontownChatManager.py +++ b/toontown/chat/ToontownChatManager.py @@ -130,15 +130,9 @@ class ToontownChatManager(ChatManager.ChatManager): if avatarId: self.enterWhisperChat(avatarName, avatarId) self.whisperFrame.hide() - return def enterNormalChat(self): - if not base.cr.wantTypedChat(): - self.fsm.request('mainMenu') - return - result = ChatManager.ChatManager.enterNormalChat(self) - if result == None: - self.notify.warning('something went wrong in enterNormalChat, falling back to main menu') + if not base.cr.wantTypedChat() or not base.localAvatar.getTutorialAck() or not ChatManager.ChatManager.enterNormalChat(self): self.fsm.request('mainMenu') def enterWhisperChat(self, avatarName, avatarId): diff --git a/toontown/cogdominium/CogdoBarrelRoom.py b/toontown/cogdominium/CogdoBarrelRoom.py index 04a2147e..2d1ab2d1 100755 --- a/toontown/cogdominium/CogdoBarrelRoom.py +++ b/toontown/cogdominium/CogdoBarrelRoom.py @@ -23,7 +23,6 @@ class CogdoBarrelRoom: self.fog = None self.defaultFar = None self.stomperSfx = None - return def destroy(self): self.unload() @@ -71,7 +70,6 @@ class CogdoBarrelRoom: taskMgr.remove(self.rewardUiTaskName) taskMgr.remove(self.rewardCameraTaskName) self._isLoaded = False - return def isLoaded(self): return self._isLoaded diff --git a/toontown/cogdominium/DistributedCogdoInterior.py b/toontown/cogdominium/DistributedCogdoInterior.py index 837c3e3e..c599e426 100755 --- a/toontown/cogdominium/DistributedCogdoInterior.py +++ b/toontown/cogdominium/DistributedCogdoInterior.py @@ -113,7 +113,6 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): self._movie = None self.SOSToonName = None self.FOType = None - return def setShopOwnerNpcId(self, npcId): self.shopOwnerNpcId = npcId @@ -202,13 +201,11 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): self.shopOwnerNpc.removeActive() self.shopOwnerNpc.delete() self.shopOwnerNpc = None - return def __cleanupPenthouseIntro(self): if hasattr(self, '_movie') and self._movie: self._movie.unload() self._movie = None - return def delete(self): self._stashEntranceElevatorFC.destroy() @@ -223,13 +220,9 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): del self.fsm base.localAvatar.inventory.setBattleCreditMultiplier(1) DistributedObject.DistributedObject.delete(self) - return def isBossFloor(self, floorNum): - if not self.layout.hasBossBattle(): - return False - - return (self.layout.getBossBattleFloor() + 0) == floorNum + return self.layout.hasBossBattle() and (self.layout.getBossBattleFloor() + 0) == floorNum def __cleanup(self): self.toons = [] @@ -251,7 +244,6 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): self.rightDoorIn = None self.leftDoorOut = None self.rightDoorOut = None - return def __addToon(self, toon): self.accept(toon.uniqueName('disable'), self.__handleUnexpectedExit, extraArgs=[toon]) @@ -404,7 +396,6 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): def enterWaitForAllToonsInside(self, ts = 0): base.transitions.fadeOut(0) - return None def exitWaitForAllToonsInside(self): return None @@ -568,7 +559,6 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): self._movie.end() self.__cleanupPenthouseIntro() self.__finishInterval(self.elevatorName) - return None def __setupBarrelRoom(self): self.currentFloor += 1 @@ -607,7 +597,6 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): self.barrelRoomIntroTrack.finish() DelayDelete.cleanupDelayDeletes(self.barrelRoomIntroTrack) self.barrelRoomIntroTrack = None - return def __handleLocalToonLeftBarrelRoom(self): self.notify.info('Local toon teleported out of barrel room.') @@ -620,6 +609,7 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): self.acceptOnce('localToonLeft', self.__handleLocalToonLeftBarrelRoom) self.barrelRoom.activate() base.playMusic(self.waitMusic, looping=1, volume=0.7) + base.localAvatar.questMap.stop() def exitCollectBarrels(self): if self._wantBarrelRoom and not self.isBossFloor(self.currentFloor): @@ -675,13 +665,11 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): self.__playCloseElevatorOut(self.uniqueName('close-out-elevator')) camera.setPos(0, -15, 6) camera.headsUp(self.elevatorModelOut) - return None def exitBattle(self): if self.elevatorOutOpen == 1: self.__finishInterval(self.uniqueName('close-out-elevator')) self.elevatorOutOpen = 0 - return None def __playReservesJoining(self, ts, name, callback): index = 0 @@ -698,7 +686,6 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): def enterReservesJoining(self, ts = 0): self.__playReservesJoining(ts, self.uniqueName('reserves-joining'), self.__handleReserveJoinDone) - return None def __handleReserveJoinDone(self): self.joiningReserves = [] @@ -707,7 +694,6 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): def exitReservesJoining(self): self.__finishInterval(self.uniqueName('reserves-joining')) - return None def enterResting(self, ts = 0): self._showExitElevator() @@ -734,7 +720,6 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): self.penthouseOutroTrack.start(ts) else: self.exitCogdoBuilding() - return None def exitReward(self): self.notify.debug('exitReward') @@ -747,16 +732,13 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): self.__outroPenthouseChatDone() self.penthouseOutroChatDoneTrack.finish() self.penthouseOutroChatDoneTrack = None - return def enterFailed(self, ts = 0): self.exitCogdoBuilding() - return None def exitFailed(self): self.notify.debug('exitFailed()') self.exitCogdoBuilding() - return None def exitCogdoBuilding(self): if base.localAvatar.hp < 0: @@ -771,7 +753,6 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): 'avId': -1, 'bldgDoId': self.distBldgDoId} messenger.send('DSIDoneEvent', [request]) - return def displayBadges(self): numFloors = self.layout.getNumGameFloors() @@ -796,9 +777,8 @@ class DistributedCogdoInterior(DistributedObject.DistributedObject): track = Parallel(name=trackName) base.cr.playGame.getPlace().fsm.request('stopped') - if self.FOType == "l": + if self.FOType == 'l': speech = TTLocalizer.CogdoExecutiveSuiteToonThankYouLawbot - else: speech = TTLocalizer.CogdoExecutiveSuiteToonThankYou % self.SOSToonName diff --git a/toontown/coghq/CogHQExterior.py b/toontown/coghq/CogHQExterior.py index 4e186469..62a87610 100755 --- a/toontown/coghq/CogHQExterior.py +++ b/toontown/coghq/CogHQExterior.py @@ -99,7 +99,7 @@ class CogHQExterior(BattlePlace.BattlePlace): base.localAvatar.setTeleportAvailable(0) self.ignore('teleportQuery') base.localAvatar.laffMeter.stop() - base.localAvatar.obscureMoveFurnitureButton(-1) + base.localAvatar.obscureMoveFurnitureButton(0) def enterTunnelOut(self, requestStatus): fromZoneId = self.zoneId - self.zoneId % 100 diff --git a/toontown/distributed/ToontownClientRepository.py b/toontown/distributed/ToontownClientRepository.py index f2aba06a..dd35209b 100755 --- a/toontown/distributed/ToontownClientRepository.py +++ b/toontown/distributed/ToontownClientRepository.py @@ -63,7 +63,7 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository): self._playerAvDclass = self.dclassesByName['DistributedToon'] setInterfaceFont(TTLocalizer.InterfaceFont) setSignFont(TTLocalizer.SignFont) - setFancyFont(TTLocalizer.FancyFont) + setChalkFont(TTLocalizer.ChalkFont) for i in xrange(len(TTLocalizer.NametagFonts)): setNametagFont(i, TTLocalizer.NametagFonts[i]) diff --git a/toontown/distributed/ToontownInternalRepository.py b/toontown/distributed/ToontownInternalRepository.py index 40a65d40..78566901 100755 --- a/toontown/distributed/ToontownInternalRepository.py +++ b/toontown/distributed/ToontownInternalRepository.py @@ -4,6 +4,7 @@ from toontown.distributed.ToontownNetMessengerAI import ToontownNetMessengerAI from direct.distributed.PyDatagram import PyDatagram import traceback import sys +import urlparse class ToontownInternalRepository(AstronInternalRepository): GameGlobalsId = OTP_DO_ID_TOONTOWN @@ -21,13 +22,19 @@ class ToontownInternalRepository(AstronInternalRepository): self.__messenger = ToontownNetMessengerAI(self) if self.wantMongo: import pymongo - self.dbConn = pymongo.MongoClient(config.GetString('mongodb-url', 'localhost')) - self.dbGlobalCursor = self.dbConn.toontownstride - self.dbCursor = self.dbGlobalCursor['air-%d' % self.ourChannel] + mongourl = config.GetString('mongodb-url', 'mongodb://localhost') + replicaset = config.GetString('mongodb-replicaset', '') + db = (urlparse.urlparse(mongourl).path or '/Astron_Dev')[1:] + if replicaset: + self.dbConn = pymongo.MongoClient(mongourl, replicaset=replicaset) + else: + self.dbConn = pymongo.MongoClient(mongourl) + self.database = self.dbConn[db] + self.dbGlobalCursor = self.database.toontownstride else: self.dbConn = None + self.database = None self.dbGlobalCursor = None - self.dbCursor = None def sendNetEvent(self, message, sentArgs=[]): self.__messenger.send(message, sentArgs) diff --git a/toontown/dna/DNAParser.py b/toontown/dna/DNAParser.py index dd2e866f..44368b40 100755 --- a/toontown/dna/DNAParser.py +++ b/toontown/dna/DNAParser.py @@ -16,21 +16,21 @@ class DNABulkLoader: def loadDNABulk(dnaStorage, file): dnaLoader = DNALoader() - fileu = 'resources/' + file - dnaLoader.loadDNAFile(dnaStorage, fileu) + file = '/' + file + dnaLoader.loadDNAFile(dnaStorage, file) def loadDNAFile(dnaStorage, file): print 'Reading DNA file...', file dnaLoader = DNALoader() - fileu = 'resources/' + file - node = dnaLoader.loadDNAFile(dnaStorage, fileu) + file = '/' + file + node = dnaLoader.loadDNAFile(dnaStorage, file) if node.node().getNumChildren() > 0: return node.node() def loadDNAFileAI(dnaStorage, file): dnaLoader = DNALoader() - fileu = 'resources/' + file - data = dnaLoader.loadDNAFileAI(dnaStorage, fileu) + file = '/' + file + data = dnaLoader.loadDNAFileAI(dnaStorage, file) return data def setupDoor(a, b, c, d, e, f): diff --git a/toontown/estate/ClosetGUI.py b/toontown/estate/ClosetGUI.py index 94814a61..40c52089 100755 --- a/toontown/estate/ClosetGUI.py +++ b/toontown/estate/ClosetGUI.py @@ -11,7 +11,7 @@ from toontown.toonbase import TTLocalizer class ClosetGUI(ClothesGUI.ClothesGUI): notify = directNotify.newCategory('ClosetGUI') - def __init__(self, isOwner, doneEvent, cancelEvent, swapEvent, deleteEvent, topList = None, botList = None): + def __init__(self, isOwner, doneEvent, cancelEvent, swapEvent, deleteEvent, topList = None, botList = None, maxClothes = 0): ClothesGUI.ClothesGUI.__init__(self, ClothesGUI.CLOTHES_CLOSET, doneEvent, swapEvent) self.toon = None self.topsList = topList @@ -20,29 +20,31 @@ class ClosetGUI(ClothesGUI.ClothesGUI): self.deleteEvent = deleteEvent self.cancelEvent = cancelEvent self.genderChange = 0 + self.maxClothes = maxClothes self.verify = None - return def load(self): ClothesGUI.ClothesGUI.load(self) self.gui = loader.loadModel('phase_3/models/gui/create_a_toon_gui') self.cancelButton = DirectButton(relief=None, image=(self.gui.find('**/CrtAtoon_Btn2_UP'), self.gui.find('**/CrtAtoon_Btn2_DOWN'), self.gui.find('**/CrtAtoon_Btn2_RLLVR')), pos=(0.15, 0, -0.85), command=self.__handleCancel, text=('', TTLocalizer.MakeAToonCancel, TTLocalizer.MakeAToonCancel), text_font=ToontownGlobals.getInterfaceFont(), text_scale=0.08, text_pos=(0, -0.03), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1)) self.cancelButton.hide() + self.countFrame = DirectFrame(parent=self.parentFrame, image=self.shuffleFrame, image_scale=(-0.6, 0.6, 0.6), relief=None, pos=(0, 0, -0.125), scale=1.2, frameColor=(1, 1, 1, 1), text=TTLocalizer.ClothesGUICount % (0, 0), text_scale=0.0575, text_pos=(-0.001, -0.015), text_fg=(1, 1, 1, 1)) if self.isOwner: - trashcanGui = loader.loadModel('phase_3/models/gui/trashcan_gui.bam') + trashcanGui = loader.loadModel('phase_3/models/gui/trashcan_gui') trashImage = (trashcanGui.find('**/TrashCan_CLSD'), trashcanGui.find('**/TrashCan_OPEN'), trashcanGui.find('**/TrashCan_RLVR')) self.trashPanel = DirectFrame(parent=aspect2d, image=DGG.getDefaultDialogGeom(), image_color=(1, 1, 0.75, 0.8), image_scale=(0.36, 0, 0.75), pos=(-.86, 0, -.05), relief=None) self.topTrashButton = DirectButton(parent=self.trashPanel, image=trashImage, relief=None, pos=(-0.09, 0, 0.2), command=self.__handleDelete, extraArgs=[ClosetGlobals.SHIRT], scale=(0.5, 0.5, 0.5), text=TTLocalizer.ClosetDeleteShirt, text_font=ToontownGlobals.getInterfaceFont(), text_scale=0.12, text_pos=(0.3, 0), text_fg=(0.8, 0.2, 0.2, 1), text_shadow=(0, 0, 0, 1), textMayChange=0) self.bottomTrashButton = DirectButton(parent=self.trashPanel, image=trashImage, relief=None, textMayChange=1, pos=(-0.09, 0, -0.2), command=self.__handleDelete, extraArgs=[ClosetGlobals.SHORTS], scale=(0.5, 0.5, 0.5), text=TTLocalizer.ClosetDeleteShorts, text_font=ToontownGlobals.getInterfaceFont(), text_scale=0.12, text_pos=(0.3, 0), text_fg=(0.8, 0.2, 0.2, 1), text_shadow=(0, 0, 0, 1)) self.button = DirectButton(relief=None, image=(self.gui.find('**/CrtAtoon_Btn1_UP'), self.gui.find('**/CrtAtoon_Btn1_DOWN'), self.gui.find('**/CrtAtoon_Btn1_RLLVR')), pos=(-0.15, 0, -0.85), command=self.__handleButton, text=('', TTLocalizer.MakeAToonDone, TTLocalizer.MakeAToonDone), text_font=ToontownGlobals.getInterfaceFont(), text_scale=0.08, text_pos=(0, -0.03), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1)) trashcanGui.removeNode() - return def unload(self): self.ignore('verifyDone') ClothesGUI.ClothesGUI.unload(self) self.cancelButton.destroy() del self.cancelButton + self.countFrame.destroy() + del self.countFrame if self.isOwner: self.topTrashButton.destroy() self.bottomTrashButton.destroy() @@ -108,7 +110,10 @@ class ClosetGUI(ClothesGUI.ClothesGUI): if self.isOwner: self.updateTrashButtons() self.setupButtons() - return + self.updateCount() + + def updateCount(self, clothes, maxClothes): + self.countFrame['text'] = TTLocalizer.ClothesGUICount % (clothes, maxClothes) def updateTrashButtons(self): if len(self.tops) < 2: @@ -124,6 +129,11 @@ class ClosetGUI(ClothesGUI.ClothesGUI): self.bottomTrashButton['text'] = TTLocalizer.ClosetDeleteSkirt else: self.bottomTrashButton['text'] = TTLocalizer.ClosetDeleteShorts + self.updateCount() + + def updateCount(self): + clothes = (len(self.tops) + len(self.bottoms)) - 2 + self.countFrame['text'] = TTLocalizer.ClothesGUICount % (clothes, self.maxClothes) def setGender(self, gender): self.ownerGender = gender diff --git a/toontown/estate/DistributedCannon.py b/toontown/estate/DistributedCannon.py index 3ac57e63..2678a704 100755 --- a/toontown/estate/DistributedCannon.py +++ b/toontown/estate/DistributedCannon.py @@ -864,7 +864,6 @@ class DistributedCannon(DistributedObject.DistributedObject): def removeAvFromCannon(self): place = base.cr.playGame.getPlace() - print 'removeAvFromCannon' self.notify.debug('self.inWater = %s' % self.inWater) if place: if not hasattr(place, 'fsm'): diff --git a/toontown/estate/DistributedCloset.py b/toontown/estate/DistributedCloset.py index 0045c648..e16cd9ce 100755 --- a/toontown/estate/DistributedCloset.py +++ b/toontown/estate/DistributedCloset.py @@ -13,6 +13,7 @@ from direct.task.Task import Task import ClosetGlobals import DistributedFurnitureItem from toontown.toonbase import TTLocalizer +from toontown.catalog import CatalogFurnitureItem class DistributedCloset(DistributedFurnitureItem.DistributedFurnitureItem): notify = directNotify.newCategory('DistributedCloset') @@ -235,7 +236,8 @@ class DistributedCloset(DistributedFurnitureItem.DistributedFurnitureItem): if self.isOwner: self.accept(self.deleteEvent, self.__handleDelete) if not self.closetGUI: - self.closetGUI = ClosetGUI.ClosetGUI(self.isOwner, self.purchaseDoneEvent, self.cancelEvent, self.swapEvent, self.deleteEvent, self.topList, self.botList) + maxClothes = CatalogFurnitureItem.ClosetToClothes.get(self.item.furnitureType) + self.closetGUI = ClosetGUI.ClosetGUI(self.isOwner, self.purchaseDoneEvent, self.cancelEvent, self.swapEvent, self.deleteEvent, self.topList, self.botList, maxClothes) self.closetGUI.load() if self.gender != self.ownerGender: self.closetGUI.setGender(self.ownerGender) @@ -320,14 +322,6 @@ class DistributedCloset(DistributedFurnitureItem.DistributedFurnitureItem): else: self.notify.warning("cant delete this item(type = %s), since we don't have a replacement" % t_or_b) - def resetItemLists(self): - self.topList = self.oldTopList[0:] - self.botList = self.oldBotList[0:] - self.closetGUI.tops = self.topList - self.closetGUI.bottoms = self.botList - self.topDeleted = 0 - self.bottomDeleted = 0 - def __proceedToCheckout(self): if self.topDeleted or self.bottomDeleted: self.__popupAreYouSurePanel() @@ -360,7 +354,6 @@ class DistributedCloset(DistributedFurnitureItem.DistributedFurnitureItem): self.av.swapToonTorso(self.av.style.torso, genClothes=0) self.av.loop('neutral', 0) self.av.generateToonClothes() - return def printInfo(self): print 'avid: %s, gender: %s' % (self.av.doId, self.av.style.gender) @@ -425,7 +418,6 @@ class DistributedCloset(DistributedFurnitureItem.DistributedFurnitureItem): DirectButton(self.popupInfo, image=okButtonImage, relief=None, text=TTLocalizer.ClosetPopupOK, text_scale=0.05, text_pos=(0.0, -0.1), textMayChange=0, pos=(0.0, 0.0, -0.16), command=self.__handleTimeoutMessageOK) buttons.removeNode() self.popupInfo.reparentTo(aspect2d) - return def __handleTimeoutMessageOK(self): self.popupInfo.reparentTo(hidden) diff --git a/toontown/estate/DistributedClosetAI.py b/toontown/estate/DistributedClosetAI.py index fcd79408..bb72ea6f 100755 --- a/toontown/estate/DistributedClosetAI.py +++ b/toontown/estate/DistributedClosetAI.py @@ -206,8 +206,5 @@ class DistributedClosetAI(DistributedFurnitureItemAI): def setMovie(self, todo0, todo1, todo2): pass - def resetItemLists(self): - pass - def setCustomerDNA(self, todo0, todo1): pass diff --git a/toontown/estate/DistributedFurnitureManagerAI.py b/toontown/estate/DistributedFurnitureManagerAI.py index 5aab2dda..149fa16a 100755 --- a/toontown/estate/DistributedFurnitureManagerAI.py +++ b/toontown/estate/DistributedFurnitureManagerAI.py @@ -317,7 +317,7 @@ class DistributedFurnitureManagerAI(DistributedObjectAI): self.air.writeServerEvent('suspicious', avId=self.air.getAvatarIdFromSender(), issue='Invalid wallpaper at index %s' % index) return ToontownGlobals.FM_InvalidIndex - if room > 1: + if room > 3: self.air.writeServerEvent('suspicious', avId=self.air.getAvatarIdFromSender(), issue='Tried to apply a wallpaper in an invalid room %d!' % room) return ToontownGlobals.FM_InvalidItem interiorIndex = room*4 @@ -354,7 +354,7 @@ class DistributedFurnitureManagerAI(DistributedObjectAI): def moveWindowFromAttic(self, index, slot): retcode = ToontownGlobals.FM_MovedItem window = self.getAtticFurniture(self.atticWindows, index) - if slot > 5: + if slot > 7: self.air.writeServerEvent('suspicious', avId=self.air.getAvatarIdFromSender(), issue='Tried to move window to invalid slot %d!' % slot) return ToontownGlobals.FM_HouseFull @@ -373,7 +373,7 @@ class DistributedFurnitureManagerAI(DistributedObjectAI): window = self.getWindow(fromSlot) if window is None: return ToontownGlobals.FM_InvalidIndex - if toSlot > 5: + if toSlot > 7: self.air.writeServerEvent('suspicious', avId=self.air.getAvatarIdFromSender(), issue='DistributedfTried to move window to invalid slot %d!' % toSlot) return ToontownGlobals.FM_HouseFull diff --git a/toontown/estate/DistributedHouseInterior.py b/toontown/estate/DistributedHouseInterior.py index 10f49473..f62a67d6 100755 --- a/toontown/estate/DistributedHouseInterior.py +++ b/toontown/estate/DistributedHouseInterior.py @@ -14,8 +14,8 @@ from toontown.catalog import CatalogFlooringItem from toontown.catalog import CatalogMouldingItem from toontown.catalog import CatalogWainscotingItem from toontown.dna.DNAParser import * -WindowPlugNames = ('**/windowcut_a*', '**/windowcut_b*', '**/windowcut_c*', '**/windowcut_d*', '**/windowcut_e*', '**/windowcut_f*') -RoomNames = ('**/group2', '**/group1') +WindowPlugNames = ['**/windowcut_%s*' % x for x in ('b', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i')] +RoomNames = ['**/group%s' % x for x in ( 4, 3, 2, 1)] WallNames = ('ceiling*', 'wall_side_middle*', 'wall_front_middle*', 'windowcut_*') MouldingNames = ('wall_side_top*', 'wall_front_top*') FloorNames = ('floor*',) @@ -35,7 +35,6 @@ class DistributedHouseInterior(DistributedObject.DistributedObject): self.houseIndex = 0 self.interior = None self.exteriorWindowsHidden = 0 - return def generate(self): DistributedObject.DistributedObject.generate(self) @@ -83,8 +82,9 @@ class DistributedHouseInterior(DistributedObject.DistributedObject): plug.flattenLight() self.windowSlots.append((plug, viewBase)) - self.windowSlots[2][1].setPosHpr(16.0, -12.0, 5.51, -90, 0, 0) - self.windowSlots[4][1].setPosHpr(-12.0, 26.0, 5.51, 0, 0, 0) + self.windowSlots[2][1].setPosHpr(-21.28, -37.15, 16.25, -90.4, 0, 0) + self.windowSlots[6][1].setPosHpr(-12.0, 26.0, 5.51, 0, 0, 0) + self.windowSlots[4][1].setPosHpr(16.0, -12.0, 5.51, -90, 0, 0) self.__colorWalls() self.__setupWindows() messenger.send('houseInteriorLoaded-%d' % self.zoneId) @@ -185,19 +185,3 @@ class DistributedHouseInterior(DistributedObject.DistributedObject): self.windows = CatalogItemList.CatalogItemList(items, store=CatalogItem.Customization | CatalogItem.WindowPlacement) if self.interior: self.__setupWindows() - - def testWallpaperCombo(self, wallpaperType, wallpaperColorIndex, borderIndex, borderColorIndex, mouldingType, mouldingColorIndex, flooringType, flooringColorIndex, wainscotingType, wainscotingColorIndex): - wallpaperItem = CatalogWallpaperItem.CatalogWallpaperItem(wallpaperType, wallpaperColorIndex, borderIndex, borderColorIndex) - mouldingItem = CatalogMouldingItem.CatalogMouldingItem(mouldingType, mouldingColorIndex) - flooringItem = CatalogFlooringItem.CatalogFlooringItem(flooringType, flooringColorIndex) - wainscotingItem = CatalogWainscotingItem.CatalogWainscotingItem(wainscotingType, wainscotingColorIndex) - self.wallpaper = CatalogItemList.CatalogItemList([wallpaperItem, - mouldingItem, - flooringItem, - wainscotingItem, - wallpaperItem, - mouldingItem, - flooringItem, - wainscotingItem], store=CatalogItem.Customization) - if self.interior: - self.__colorWalls() diff --git a/toontown/estate/DistributedHouseInteriorAI.py b/toontown/estate/DistributedHouseInteriorAI.py index 1805f1f0..124bd0fa 100755 --- a/toontown/estate/DistributedHouseInteriorAI.py +++ b/toontown/estate/DistributedHouseInteriorAI.py @@ -22,7 +22,7 @@ houseInteriors = [ ] defaultWindows = [ - CatalogWindowItem(20, placement=2), CatalogWindowItem(20, placement=4) + CatalogWindowItem(20, placement=2), CatalogWindowItem(20, placement=4), CatalogWindowItem(20, placement=6) ] defaultWallpaper = [ @@ -34,6 +34,14 @@ defaultWallpaper = [ CatalogMouldingItem(1000, 2), CatalogFlooringItem(1000, 4), CatalogWainscotingItem(1010, 4), + CatalogWallpaperItem(1110, 0, 1010, 0), + CatalogMouldingItem(1000, 2), + CatalogFlooringItem(1000, 4), + CatalogWainscotingItem(1010, 4), + CatalogWallpaperItem(1110, 0, 1010, 0), + CatalogMouldingItem(1000, 2), + CatalogFlooringItem(1000, 4), + CatalogWainscotingItem(1010, 4), ] diff --git a/toontown/estate/DistributedPhone.py b/toontown/estate/DistributedPhone.py index ca461e18..02813ca7 100755 --- a/toontown/estate/DistributedPhone.py +++ b/toontown/estate/DistributedPhone.py @@ -177,6 +177,7 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): self.notify.debug('Entering Phone Sphere....') taskMgr.remove(self.uniqueName('ringDoLater')) + base.localAvatar.obscureMoveFurnitureButton(1) self.cr.playGame.getPlace().detectedPhoneCollision() self.hasLocalAvatar = 1 self.sendUpdate('avatarEnter', []) @@ -184,6 +185,7 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): def __handlePhoneDone(self): self.sendUpdate('avatarExit', []) self.ignore(self.phoneGuiDoneEvent) + base.localAvatar.obscureMoveFurnitureButton(0) self.setPos(self.getPos()) self.phoneGui = None diff --git a/toontown/estate/DistributedTrunk.py b/toontown/estate/DistributedTrunk.py index 8dbadb8b..66c94ba4 100755 --- a/toontown/estate/DistributedTrunk.py +++ b/toontown/estate/DistributedTrunk.py @@ -231,20 +231,6 @@ class DistributedTrunk(DistributedCloset.DistributedCloset): else: self.notify.warning("cant delete this item(type = %s), since we don't have a replacement" % which) - def resetItemLists(self): - self.hatList = self.oldHatList[0:] - self.glassesList = self.oldGlassesList[0:] - self.backpackList = self.oldBackpackList[0:] - self.shoesList = self.oldShoesList[0:] - self.closetGUI.hat = self.hatList - self.closetGUI.glasses = self.glassesList - self.closetGUI.backpack = self.backpackList - self.closetGUI.shoes = self.shoesList - self.hatDeleted = 0 - self.glassesDeleted = 0 - self.backpackDeleted = 0 - self.shoesDeleted = 0 - def __proceedToCheckout(self): if self.hatDeleted or self.glassesDeleted or self.backpackDeleted or self.shoesDeleted: self.__popupAreYouSurePanel() diff --git a/toontown/estate/House.py b/toontown/estate/House.py index 7e896de7..25f04538 100755 --- a/toontown/estate/House.py +++ b/toontown/estate/House.py @@ -164,7 +164,7 @@ class House(Place.Place): base.localAvatar.setTeleportAvailable(0) self.ignore('teleportQuery') base.localAvatar.laffMeter.stop() - base.localAvatar.obscureMoveFurnitureButton(-1) + base.localAvatar.obscureMoveFurnitureButton(0) base.localAvatar.stopSleepWatch() def enterBanking(self): diff --git a/toontown/estate/TrunkGUI.py b/toontown/estate/TrunkGUI.py index 7a26e96a..2a3017bb 100755 --- a/toontown/estate/TrunkGUI.py +++ b/toontown/estate/TrunkGUI.py @@ -31,25 +31,24 @@ class TrunkGUI(StateData.StateData): self.cancelEvent = cancelEvent self.genderChange = 0 self.verify = None - return def load(self): - self.gui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui') - guiRArrowUp = self.gui.find('**/tt_t_gui_mat_arrowUp') - guiRArrowRollover = self.gui.find('**/tt_t_gui_mat_arrowUp') - guiRArrowDown = self.gui.find('**/tt_t_gui_mat_arrowDown') - guiRArrowDisabled = self.gui.find('**/tt_t_gui_mat_arrowDisabled') - guiArrowRotateUp = self.gui.find('**/tt_t_gui_mat_arrowRotateUp') - guiArrowRotateDown = self.gui.find('**/tt_t_gui_mat_arrowRotateDown') - shuffleFrame = self.gui.find('**/tt_t_gui_mat_shuffleFrame') - shuffleArrowUp = self.gui.find('**/tt_t_gui_mat_shuffleArrowUp') - shuffleArrowDown = self.gui.find('**/tt_t_gui_mat_shuffleArrowDown') - shuffleArrowRollover = self.gui.find('**/tt_t_gui_mat_shuffleArrowUp') - shuffleArrowDisabled = self.gui.find('**/tt_t_gui_mat_shuffleArrowDisabled') - self.parentFrame = DirectFrame(relief=DGG.RAISED, pos=(0.98, 0, 0.416), frameColor=(1, 0, 0, 0)) + self.matGui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui') + guiRArrowUp = self.matGui.find('**/tt_t_gui_mat_arrowUp') + guiRArrowRollover = self.matGui.find('**/tt_t_gui_mat_arrowUp') + guiRArrowDown = self.matGui.find('**/tt_t_gui_mat_arrowDown') + guiRArrowDisabled = self.matGui.find('**/tt_t_gui_mat_arrowDisabled') + guiArrowRotateUp = self.matGui.find('**/tt_t_gui_mat_arrowRotateUp') + guiArrowRotateDown = self.matGui.find('**/tt_t_gui_mat_arrowRotateDown') + self.shuffleFrame = self.matGui.find('**/tt_t_gui_mat_shuffleFrame') + shuffleArrowUp = self.matGui.find('**/tt_t_gui_mat_shuffleArrowUp') + shuffleArrowDown = self.matGui.find('**/tt_t_gui_mat_shuffleArrowDown') + shuffleArrowRollover = self.matGui.find('**/tt_t_gui_mat_shuffleArrowUp') + shuffleArrowDisabled = self.matGui.find('**/tt_t_gui_mat_shuffleArrowDisabled') + self.parentFrame = DirectFrame(relief=DGG.RAISED, pos=(0.98, 0, 0.216), frameColor=(1, 0, 0, 0)) def addFrame(posZ, text): - return DirectFrame(parent=self.parentFrame, image=shuffleFrame, image_scale=halfButtonInvertScale, relief=None, pos=(0, 0, posZ), hpr=(0, 0, 3), scale=1.2, frameColor=(1, 1, 1, 1), text=text, text_scale=0.0575, text_pos=(-0.001, -0.015), text_fg=(1, 1, 1, 1)) + return DirectFrame(parent=self.parentFrame, image=self.shuffleFrame, image_scale=halfButtonInvertScale, relief=None, pos=(0, 0, posZ), hpr=(0, 0, 3), scale=1.2, frameColor=(1, 1, 1, 1), text=text, text_scale=0.0575, text_pos=(-0.001, -0.015), text_fg=(1, 1, 1, 1)) def addButton(parent, scale, hoverScale, posX, command, extraArg): return DirectButton(parent=parent, relief=None, image=(shuffleArrowUp, @@ -57,6 +56,7 @@ class TrunkGUI(StateData.StateData): shuffleArrowRollover, shuffleArrowDisabled), image_scale=scale, image1_scale=hoverScale, image2_scale=hoverScale, pos=(posX, 0, 0), command=command, extraArgs=[extraArg]) + self.countFrame = addFrame(0.37, TTLocalizer.ClothesGUICount % (0, 0)) self.hatFrame = addFrame(0.1, TTLocalizer.TrunkHatGUI) self.hatLButton = addButton(self.hatFrame, halfButtonScale, halfButtonHoverScale, -0.2, self.swapHat, -1) self.hatRButton = addButton(self.hatFrame, halfButtonInvertScale, halfButtonInvertHoverScale, 0.2, self.swapHat, 1) @@ -103,7 +103,6 @@ class TrunkGUI(StateData.StateData): self.shoesTrashButton = addTrashButton(-0.4, TTLocalizer.TrunkDeleteShoes, ToonDNA.SHOES) self.button = DirectButton(relief=None, image=(self.gui.find('**/CrtAtoon_Btn1_UP'), self.gui.find('**/CrtAtoon_Btn1_DOWN'), self.gui.find('**/CrtAtoon_Btn1_RLLVR')), pos=(-0.15, 0, -0.85), command=self.__handleButton, text=('', TTLocalizer.MakeAToonDone, TTLocalizer.MakeAToonDone), text_font=ToontownGlobals.getInterfaceFont(), text_scale=0.08, text_pos=(0, -0.03), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1)) trashcanGui.removeNode() - return def unload(self): taskMgr.remove(self.taskName('rotateL')) @@ -111,7 +110,11 @@ class TrunkGUI(StateData.StateData): self.ignore('verifyDone') self.gui.removeNode() del self.gui + self.matGui.removeNode() + del self.matGui + del self.shuffleFrame self.parentFrame.destroy() + self.countFrame.destroy() self.hatFrame.destroy() self.glassesFrame.destroy() self.backpackFrame.destroy() @@ -124,6 +127,7 @@ class TrunkGUI(StateData.StateData): self.backpackRButton.destroy() self.shoesLButton.destroy() self.shoesRButton.destroy() + del self.countFrame del self.parentFrame del self.hatFrame del self.glassesFrame @@ -286,7 +290,7 @@ class TrunkGUI(StateData.StateData): self.swapShoes(0) self.updateTrashButtons() self.setupButtons() - return + self.updateCountFrame() def updateTrashButtons(self): if not self.isOwner: @@ -307,6 +311,11 @@ class TrunkGUI(StateData.StateData): self.shoesTrashButton['state'] = DGG.DISABLED else: self.shoesTrashButton['state'] = DGG.NORMAL + self.updateCountFrame() + + def updateCountFrame(self): + accessories = (len(self.hats) + len(self.glasses) + len(self.backpacks) + len(self.shoes)) - 4 + self.countFrame['text'] = TTLocalizer.ClothesGUICount % (accessories, ToontownGlobals.MaxAccessories) def rotateToonL(self, task): self.toon.setH(self.toon.getH() - 4) diff --git a/toontown/estate/houseDesign.py b/toontown/estate/houseDesign.py index ac271eef..f87110ab 100755 --- a/toontown/estate/houseDesign.py +++ b/toontown/estate/houseDesign.py @@ -1328,12 +1328,20 @@ class ObjectManager(NodePath, DirectObject): if self.deleteMode: self.requestDelete(item, itemIndex, self.deleteWallpaperFromAttic) return - if base.localAvatar.getY() < 2.3: - room = 0 - else: - room = 1 + room = self.getRoom() self.furnitureManager.moveWallpaperFromAttic(itemIndex, room, self.__bringWallpaperFromAtticCallback) + def getRoom(self): + x, y, z = base.localAvatar.getPos() + + if (x <= -13.5 and y <= -7.6 and y >= 0.0) or (z >= 4.5 and z <= 10): + return 0 + elif base.localAvatar.getZ() > 5.0: + return 1 + elif base.localAvatar.getY() < 2.3: + return 2 + return 3 + def __bringWallpaperFromAtticCallback(self, retcode, itemIndex, room): self.__enableItemButtons(1) if retcode < 0: @@ -1367,10 +1375,10 @@ class ObjectManager(NodePath, DirectObject): if self.deleteMode: self.requestDelete(item, itemIndex, self.deleteWindowFromAttic) return - if base.localAvatar.getY() < 2.3: - slot = 2 - else: - slot = 4 + room = self.getRoom() + if room == 0: + room = 1 + slot = room * 2 self.furnitureManager.moveWindowFromAttic(itemIndex, slot, self.__bringWindowFromAtticCallback) def __bringWindowFromAtticCallback(self, retcode, itemIndex, slot): diff --git a/toontown/fishing/DistributedFishingPond.py b/toontown/fishing/DistributedFishingPond.py index dd2db7bf..5bb8bef4 100755 --- a/toontown/fishing/DistributedFishingPond.py +++ b/toontown/fishing/DistributedFishingPond.py @@ -90,7 +90,7 @@ class DistributedFishingPond(DistributedObject.DistributedObject): return self.pondBingoMgr def hasPondBingoManager(self): - return (self.pondBingoMgr and [1] or [0])[0] + return self.pondBingoMgr is not None def handleBingoCatch(self, catch): if self.pondBingoMgr: diff --git a/toontown/friends/TTSFriendsManager.py b/toontown/friends/TTSFriendsManager.py index 0366fec4..5349865f 100755 --- a/toontown/friends/TTSFriendsManager.py +++ b/toontown/friends/TTSFriendsManager.py @@ -27,7 +27,7 @@ class TTSFriendsManager(DistributedObjectGlobal): def d_getAvatarDetails(self, avId): self.sendUpdate('getAvatarDetails', [avId]) - def friendDetails(self, avId, inventory, trackAccess, hp, maxHp, defaultShard, lastHood, dnaString, experience, trackBonusLevel): + def friendDetails(self, avId, inventory, trackAccess, hp, maxHp, defaultShard, lastHood, dnaString, experience, trackBonusLevel, npcFriends): fields = [ ['setExperience' , experience], ['setTrackAccess' , trackAccess], @@ -38,6 +38,7 @@ class TTSFriendsManager(DistributedObjectGlobal): ['setDefaultShard' , defaultShard], ['setLastHood' , lastHood], ['setDNAString' , dnaString], + ['setNPCFriendsDict', npcFriends] ] base.cr.n_handleGetAvatarDetailsResp(avId, fields=fields) @@ -71,6 +72,12 @@ class TTSFriendsManager(DistributedObjectGlobal): if not hasattr(base.localAvatar, 'getTeleportAvailable') or not hasattr(base.localAvatar, 'ghostMode'): self.sendUpdate('teleportResponse', [ fromId, 0, 0, 0, 0 ]) return + if not base.localAvatar.acceptingTeleport: + self.sendUpdate('teleportResponse', [ fromId, 3, 0, 0, 0 ]) + return + if base.localAvatar.isIgnored(fromId): + self.sendUpdate('teleportResponse', [ fromId, 2, 0, 0, 0 ]) + return friend = base.cr.identifyFriend(fromId) diff --git a/toontown/friends/TTSFriendsManagerUD.py b/toontown/friends/TTSFriendsManagerUD.py index d8a9d76e..8237cf43 100755 --- a/toontown/friends/TTSFriendsManagerUD.py +++ b/toontown/friends/TTSFriendsManagerUD.py @@ -198,8 +198,9 @@ class TTSFriendsManagerUD(DistributedObjectGlobalUD): dnaString = fields['setDNAString'][0] experience = fields['setExperience'][0] trackBonusLevel = fields['setTrackBonusLevel'][0] + npcFriends = fields['setNPCFriendsDict'][0] - self.sendUpdateToAvatarId(senderId, 'friendDetails', [avId, inventory, trackAccess, hp, maxHp, defaultShard, lastHood, dnaString, experience, trackBonusLevel]) + self.sendUpdateToAvatarId(senderId, 'friendDetails', [avId, inventory, trackAccess, hp, maxHp, defaultShard, lastHood, dnaString, experience, trackBonusLevel, npcFriends]) self.air.dbInterface.queryObject(self.air.dbId, avId, handleToon) def getPetDetails(self, avId): diff --git a/toontown/hood/Place.py b/toontown/hood/Place.py index 21aca716..c501bb8c 100755 --- a/toontown/hood/Place.py +++ b/toontown/hood/Place.py @@ -187,7 +187,6 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): base.localAvatar.invPage.hideInventoryOnscreen() base.localAvatar.questMap.hide() base.localAvatar.questMap.ignoreOnscreenHooks() - return def handleWalkDone(self, doneStatus): mode = doneStatus['mode'] @@ -293,7 +292,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): self.ignore('bookDone') base.localAvatar.setTeleportAvailable(0) self.ignore('teleportQuery') - base.localAvatar.obscureMoveFurnitureButton(-1) + base.localAvatar.obscureMoveFurnitureButton(0) target = base.cr.doFind('DistributedTarget') if target: target.showGui() @@ -445,13 +444,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def exitDoorIn(self): NametagGlobals.setMasterArrowsOn(1) - base.localAvatar.obscureMoveFurnitureButton(-1) + base.localAvatar.obscureMoveFurnitureButton(0) def enterDoorOut(self): base.localAvatar.obscureMoveFurnitureButton(1) def exitDoorOut(self): - base.localAvatar.obscureMoveFurnitureButton(-1) + base.localAvatar.obscureMoveFurnitureButton(0) base.localAvatar.stopQuestMap() def handleDoorDoneEvent(self, requestStatus): @@ -495,7 +494,6 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): self.accept('tunnelOutMovieDone', self.__tunnelOutMovieDone) base.localAvatar.tunnelOut(tunnelOrigin) base.localAvatar.stopQuestMap() - return def __tunnelOutMovieDone(self): self.ignore('tunnelOutMovieDone') @@ -512,7 +510,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def exitTeleportOut(self): base.localAvatar.laffMeter.stop() base.localAvatar.stopQuestMap() - base.localAvatar.obscureMoveFurnitureButton(-1) + base.localAvatar.obscureMoveFurnitureButton(0) def enterDied(self, requestStatus, callback = None): if callback == None: @@ -529,7 +527,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def exitDied(self): base.localAvatar.laffMeter.stop() - base.localAvatar.obscureMoveFurnitureButton(-1) + base.localAvatar.obscureMoveFurnitureButton(0) def getEstateZoneAndGoHome(self, requestStatus): self.doneStatus = requestStatus @@ -647,7 +645,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): self._tiToken = None NametagGlobals.setMasterArrowsOn(1) base.localAvatar.laffMeter.stop() - base.localAvatar.obscureMoveFurnitureButton(-1) + base.localAvatar.obscureMoveFurnitureButton(0) base.localAvatar.stopUpdateSmartCamera() base.localAvatar.detachCamera() base.localAvatar.stopPosHprBroadcast() @@ -692,7 +690,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): base.localAvatar.setTeleportAvailable(0) self.ignore('teleportQuery') base.localAvatar.laffMeter.stop() - base.localAvatar.obscureMoveFurnitureButton(-1) + base.localAvatar.obscureMoveFurnitureButton(0) def enterPurchase(self): base.localAvatar.b_setAnimState('neutral', 1) @@ -705,7 +703,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): base.localAvatar.setTeleportAvailable(0) self.ignore('teleportQuery') base.localAvatar.laffMeter.stop() - base.localAvatar.obscureMoveFurnitureButton(-1) + base.localAvatar.obscureMoveFurnitureButton(0) def enterFishing(self): base.localAvatar.b_setAnimState('neutral', 1) @@ -736,7 +734,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): base.localAvatar.setTeleportAvailable(0) self.ignore('teleportQuery') base.localAvatar.laffMeter.stop() - base.localAvatar.obscureMoveFurnitureButton(-1) + base.localAvatar.obscureMoveFurnitureButton(0) base.localAvatar.stopSleepWatch() def enterPhone(self): @@ -757,7 +755,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): base.localAvatar.setTeleportAvailable(0) self.ignore('teleportQuery') base.localAvatar.laffMeter.stop() - base.localAvatar.obscureMoveFurnitureButton(-1) + base.localAvatar.obscureMoveFurnitureButton(0) base.localAvatar.stopSleepWatch() def enterStopped(self): @@ -783,7 +781,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): base.localAvatar.setTeleportAvailable(0) self.ignore('teleportQuery') base.localAvatar.laffMeter.stop() - base.localAvatar.obscureMoveFurnitureButton(-1) + base.localAvatar.obscureMoveFurnitureButton(0) base.localAvatar.stopSleepWatch() messenger.send('exitingStoppedState') diff --git a/toontown/launcher/TTSLauncher.py b/toontown/launcher/TTSLauncher.py index 38886271..dc7227d3 100755 --- a/toontown/launcher/TTSLauncher.py +++ b/toontown/launcher/TTSLauncher.py @@ -46,7 +46,20 @@ class TTSLauncher: return self.getValue('TTS_PLAYCOOKIE') def getGameServer(self): - return self.getValue('TTS_GAMESERVER') + if config.GetString('game-type', 'developer') != 'remote': + return self.getValue('TTS_GAMESERVER') + return self.getServer(self.getValue('TTS_GAMESERVER')) + + def getServer(self, gameserver): + import DNS + DNS.DiscoverNameServers() + srv_req = DNS.Request(qtype = 'srv') + srv_result = srv_req.req('_toontown._tcp.'+ gameserver) + + for result in srv_result.answers: + if result['typename'] == 'SRV': + data = result['data'] + return data[3] + ":" + str(data[2]) def getValue(self, key, default = None): return os.environ.get(key, default) diff --git a/toontown/makeatoon/ClothesGUI.py b/toontown/makeatoon/ClothesGUI.py index 22136c98..1d4ea4b5 100755 --- a/toontown/makeatoon/ClothesGUI.py +++ b/toontown/makeatoon/ClothesGUI.py @@ -25,20 +25,20 @@ class ClothesGUI(StateData.StateData): return def load(self): - self.gui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui') - guiRArrowUp = self.gui.find('**/tt_t_gui_mat_arrowUp') - guiRArrowRollover = self.gui.find('**/tt_t_gui_mat_arrowUp') - guiRArrowDown = self.gui.find('**/tt_t_gui_mat_arrowDown') - guiRArrowDisabled = self.gui.find('**/tt_t_gui_mat_arrowDisabled') - shuffleFrame = self.gui.find('**/tt_t_gui_mat_shuffleFrame') - shuffleArrowUp = self.gui.find('**/tt_t_gui_mat_shuffleArrowUp') - shuffleArrowDown = self.gui.find('**/tt_t_gui_mat_shuffleArrowDown') - shuffleArrowRollover = self.gui.find('**/tt_t_gui_mat_shuffleArrowUp') - shuffleArrowDisabled = self.gui.find('**/tt_t_gui_mat_shuffleArrowDisabled') + self.matGui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui') + guiRArrowUp = self.matGui.find('**/tt_t_gui_mat_arrowUp') + guiRArrowRollover = self.matGui.find('**/tt_t_gui_mat_arrowUp') + guiRArrowDown = self.matGui.find('**/tt_t_gui_mat_arrowDown') + guiRArrowDisabled = self.matGui.find('**/tt_t_gui_mat_arrowDisabled') + self.shuffleFrame = self.matGui.find('**/tt_t_gui_mat_shuffleFrame') + shuffleArrowUp = self.matGui.find('**/tt_t_gui_mat_shuffleArrowUp') + shuffleArrowDown = self.matGui.find('**/tt_t_gui_mat_shuffleArrowDown') + shuffleArrowRollover = self.matGui.find('**/tt_t_gui_mat_shuffleArrowUp') + shuffleArrowDisabled = self.matGui.find('**/tt_t_gui_mat_shuffleArrowDisabled') self.parentFrame = DirectFrame(relief=DGG.RAISED, pos=(0.98, 0, 0.416), frameColor=(1, 0, 0, 0)) self.parentFrame.setPos(-0.36, 0, -0.5) self.parentFrame.reparentTo(base.a2dTopRight) - self.shirtFrame = DirectFrame(parent=self.parentFrame, image=shuffleFrame, image_scale=halfButtonInvertScale, relief=None, pos=(0, 0, -0.4), hpr=(0, 0, 3), scale=1.2, frameColor=(1, 1, 1, 1), text=TTLocalizer.ClothesShopShirt, text_scale=0.0575, text_pos=(-0.001, -0.015), text_fg=(1, 1, 1, 1)) + self.shirtFrame = DirectFrame(parent=self.parentFrame, image=self.shuffleFrame, image_scale=halfButtonInvertScale, relief=None, pos=(0, 0, -0.4), hpr=(0, 0, 3), scale=1.2, frameColor=(1, 1, 1, 1), text=TTLocalizer.ClothesShopShirt, text_scale=0.0575, text_pos=(-0.001, -0.015), text_fg=(1, 1, 1, 1)) self.topLButton = DirectButton(parent=self.shirtFrame, relief=None, image=(shuffleArrowUp, shuffleArrowDown, shuffleArrowRollover, @@ -47,7 +47,7 @@ class ClothesGUI(StateData.StateData): shuffleArrowDown, shuffleArrowRollover, shuffleArrowDisabled), image_scale=halfButtonInvertScale, image1_scale=halfButtonInvertHoverScale, image2_scale=halfButtonInvertHoverScale, pos=(0.2, 0, 0), command=self.swapTop, extraArgs=[1]) - self.bottomFrame = DirectFrame(parent=self.parentFrame, image=shuffleFrame, image_scale=halfButtonInvertScale, relief=None, pos=(0, 0, -0.65), hpr=(0, 0, -2), scale=1.2, frameColor=(1, 1, 1, 1), text=TTLocalizer.ColorShopToon, text_scale=0.0575, text_pos=(-0.001, -0.015), text_fg=(1, 1, 1, 1)) + self.bottomFrame = DirectFrame(parent=self.parentFrame, image=self.shuffleFrame, image_scale=halfButtonInvertScale, relief=None, pos=(0, 0, -0.65), hpr=(0, 0, -2), scale=1.2, frameColor=(1, 1, 1, 1), text=TTLocalizer.ColorShopToon, text_scale=0.0575, text_pos=(-0.001, -0.015), text_fg=(1, 1, 1, 1)) self.bottomLButton = DirectButton(parent=self.bottomFrame, relief=None, image=(shuffleArrowUp, shuffleArrowDown, shuffleArrowRollover, @@ -59,11 +59,10 @@ class ClothesGUI(StateData.StateData): self.parentFrame.hide() self.shuffleFetchMsg = 'ClothesShopShuffle' self.shuffleButton = ShuffleButton.ShuffleButton(self, self.shuffleFetchMsg) - return def unload(self): - self.gui.removeNode() - del self.gui + self.matGui.removeNode() + del self.matGui self.parentFrame.destroy() self.shirtFrame.destroy() self.bottomFrame.destroy() @@ -71,6 +70,7 @@ class ClothesGUI(StateData.StateData): self.topRButton.destroy() self.bottomLButton.destroy() self.bottomRButton.destroy() + del self.shuffleFrame del self.parentFrame del self.shirtFrame del self.bottomFrame diff --git a/toontown/makeatoon/ColorShop.py b/toontown/makeatoon/ColorShop.py index 9ed310cb..c9bf9adc 100755 --- a/toontown/makeatoon/ColorShop.py +++ b/toontown/makeatoon/ColorShop.py @@ -91,7 +91,7 @@ class ColorShop(StateData.StateData): self.pickContainer.setTransparency(True) self.pickImage = PNMImage(int((ToontownGlobals.COLOR_SATURATION_MAX - ToontownGlobals.COLOR_SATURATION_MIN) * 100), int((ToontownGlobals.COLOR_VALUE_MAX - ToontownGlobals.COLOR_VALUE_MIN) * 100)) self.hueSlider = DirectSlider(parent=self.advancedFrame, relief=None, image='phase_3/maps/color_picker_hue.jpg', scale=0.3, pos=(-0.05, 0, -0.43), image_scale=(0.1, 1.0, 1.0), pageSize=5, orientation=DGG.VERTICAL, command=self.__chooseHue) - self.pickButton = DirectButton(parent=self.advancedFrame, relief=None, image='phase_3/maps/color_picker_empty.png', scale=0.3, pos=(-0.45, 0, -0.43), frameColor=(1, 1, 1, 0.1), pressEffect=0) + self.pickButton = DirectButton(parent=self.advancedFrame, relief=None, image='phase_3/maps/invisible.png', scale=0.3, pos=(-0.45, 0, -0.43), frameColor=(1, 1, 1, 0.1), pressEffect=0) self.pickButton.bind(DGG.B1PRESS, self.__startPickColor) self.pickButton.bind(DGG.B1RELEASE, self.__stopPickColor) self.partsFrame = DirectFrame(parent=self.advancedFrame, image=shuffleFrame, image_scale=halfButtonInvertScale, relief=None, pos=(-0.395, 0, -0.85), hpr=(0, 0, -2), scale=0.9, frameColor=(1, 1, 1, 1), text=TTLocalizer.ColorAll, text_scale=0.0625, text_pos=(-0.001, -0.015), text_fg=(1, 1, 1, 1)) diff --git a/toontown/quest/QuestMap.py b/toontown/quest/QuestMap.py index 038601c7..1cb2dbab 100755 --- a/toontown/quest/QuestMap.py +++ b/toontown/quest/QuestMap.py @@ -30,9 +30,6 @@ class QuestMap(DirectFrame): self.cogInfoFrame.setPos(0, 0, 0.6) self.buildingMarkers = [] self.av = av - self.wantToggle = False - if base.config.GetBool('want-toggle-quest-map', True): - self.wantToggle = True self.updateMarker = True self.cornerPosInfo = None self.hqPosInfo = None @@ -47,8 +44,6 @@ class QuestMap(DirectFrame): tracks = currHoodInfo[SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_TRACK] self.suitPercentage[currHoodInfo[SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_ZONE]] = tracks - return - def load(self): gui = loader.loadModel('phase_4/models/questmap/questmap_gui') icon = gui.find('**/tt_t_gui_qst_arrow') @@ -279,7 +274,6 @@ class QuestMap(DirectFrame): self.obscureButton() self.ignore('questPageUpdated') taskMgr.remove('questMapUpdate') - return def handleMarker(self): if hasattr(base.cr.playGame.getPlace(), 'isInterior') and base.cr.playGame.getPlace().isInterior: @@ -288,15 +282,9 @@ class QuestMap(DirectFrame): self.updateMarker = True def acceptOnscreenHooks(self): - if self.wantToggle: - self.accept(ToontownGlobals.MapHotkey, self.toggle) - else: - self.accept(ToontownGlobals.MapHotkeyOn, self.show) - self.accept(ToontownGlobals.MapHotkeyOff, self.hide) + self.accept(ToontownGlobals.MapHotkey, self.toggle) self.updateMap() def ignoreOnscreenHooks(self): self.ignore(ToontownGlobals.MapHotkey) - self.ignore(ToontownGlobals.MapHotkeyOn) - self.ignore(ToontownGlobals.MapHotkeyOff) self.obscureButton() diff --git a/toontown/quest/QuestParser.py b/toontown/quest/QuestParser.py index db41baba..fbe13bc4 100755 --- a/toontown/quest/QuestParser.py +++ b/toontown/quest/QuestParser.py @@ -406,8 +406,11 @@ class NPCMoviePlayer(DirectObject.DirectObject): self.closePreviousChapter(iList) chapterList = [] self.currentEvent = nextEvent + elif command == 'TUTORIAL_ACK_DONE': + iList.append(Func(base.localAvatar.setTutorialAck, True)) else: notify.warning('Unknown command token: %s for scriptId: %s on line: %s' % (command, self.scriptId, lineNum)) + self.closePreviousChapter(chapterList) if timeoutList: diff --git a/toontown/quest/QuestPoster.py b/toontown/quest/QuestPoster.py index aeeb23ea..9ccb40cf 100755 --- a/toontown/quest/QuestPoster.py +++ b/toontown/quest/QuestPoster.py @@ -73,11 +73,18 @@ class QuestPoster(DirectFrame): self.teleportButton = DirectButton(parent=self.questFrame, relief=None, image=circleModel, text=TTLocalizer.TeleportButton, text_scale=0.035, text_pos=(-0.0025, -0.015), pos=(0.175, 0, 0.125), scale=0.75) #, text_bg=(0, 0.75, 1, 1) self.teleportButton.hide() self.laffMeter = None - return + self.dialog = None def destroy(self): self._deleteGeoms() + self.destroyDialog() DirectFrame.destroy(self) + + def destroyDialog(self, extra=None): + if self.dialog: + self.dialog.destroy() + self.dialog = None + base.cr.playGame.getPlace().setState('walk') def _deleteGeoms(self): for icon in (self.lQuestIcon, self.rQuestIcon): @@ -153,11 +160,7 @@ class QuestPoster(DirectFrame): def loadElevator(self, building, numFloors): elevatorNodePath = hidden.attachNewNode('elevatorNodePath') elevatorModel = loader.loadModel('phase_4/models/modules/elevator') - floorIndicator = [None, - None, - None, - None, - None] + floorIndicator = [None] * 5 npc = elevatorModel.findAllMatches('**/floor_light_?;+s') for i in xrange(npc.getNumPaths()): np = npc.getPath(i) @@ -174,6 +177,9 @@ class QuestPoster(DirectFrame): elevatorNodePath.setPosHpr(0, 0, 0, 0, 0, 0) def teleportToShop(self, npcId): + if base.cr.playGame.getPlace().getState() != 'walk': + return + npcZone = NPCToons.getNPCZone(npcId) npcHood = ZoneUtil.getCanonicalHoodId(npcZone) hqZone = {2000:2520, 1000:1507, 3000:3508, 4000:4504, 5000:5502, 7000:7503, 9000:9505} @@ -184,15 +190,32 @@ class QuestPoster(DirectFrame): zoneId = 2000 npcHood = ZoneUtil.getCanonicalHoodId(zoneId) npcZone = hqZone.get(npcHood, 2520) + + cost = ToontownGlobals.getTeleportButtonCost(npcHood) + self.destroyDialog() + base.cr.playGame.getPlace().setState('stopped') + + if base.localAvatar.getTotalMoney() < cost: + self.dialog = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=TTLocalizer.TeleportButtonNoMoney % cost, command=self.destroyDialog) + else: + self.dialog = TTDialog.TTDialog(style=TTDialog.YesNo, text=TTLocalizer.TeleportButtonConfirm % cost, command=lambda value: self.teleportToShopConfirm(npcZone, npcHood, cost, value)) - base.cr.buildingQueryMgr.d_isSuit(npcZone, lambda isSuit: self.teleportToShopCallback(npcZone, npcHood, isSuit)) + self.dialog.show() - def teleportToShopCallback(self, npcZone, npcHood, flag): + def teleportToShopConfirm(self, npcZone, npcHood, cost, value): + self.destroyDialog() + + if value > 0: + base.cr.buildingQueryMgr.d_isSuit(npcZone, lambda isSuit: self.teleportToShopCallback(npcZone, npcHood, cost, isSuit)) + + def teleportToShopCallback(self, npcZone, npcHood, cost, flag): if flag: - self.teleportButton.setColorScale(0.3, 0.3, 0.3, 1.0) + base.cr.playGame.getPlace().setState('stopped') + self.dialog = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=TTLocalizer.TeleportButtonTakenOver, command=self.destroyDialog) + self.dialog.show() return - self.teleportButton.setColorScale(1.0, 1.0, 1.0, 1.0) + base.localAvatar.takeMoney(cost) base.cr.playGame.getPlace().requestTeleport(npcHood, npcZone, base.localAvatar.defaultShard, -1) def fitGeometry(self, geom, fFlip = 0, dimension = 0.8): @@ -228,6 +251,7 @@ class QuestPoster(DirectFrame): self.rPictureFrame.hide() self.questProgress.hide() self.teleportButton.hide() + self.destroyDialog() if hasattr(self, 'chooseButton'): self.chooseButton.destroy() del self.chooseButton @@ -419,8 +443,8 @@ class QuestPoster(DirectFrame): elif quest.getType() == Quests.TrackChoiceQuest: frameBgColor = 'green' invModel = loader.loadModel('phase_3.5/models/gui/inventory_icons') - track1, track2 = quest.getChoices(base.localAvatar) + track1, track2 = quest.getChoices() lIconGeom = invModel.find('**/' + AvPropsNew[track1][1]) if not fComplete: diff --git a/toontown/quest/QuestScripts.py b/toontown/quest/QuestScripts.py index 18d1b2da..77f59772 100755 --- a/toontown/quest/QuestScripts.py +++ b/toontown/quest/QuestScripts.py @@ -253,7 +253,8 @@ WAIT 0.5 WRTREPARENTTO chatNormalButton topLeft LERP_POS chatNormalButton 0.068 0 -0.072 0.6 LERP_SCALE chatNormalButton 1.179 1.179 1.179 0.6 -WAIT 0.6 +WAIT 0.6 +TUTORIAL_ACK_DONE LOCAL_CHAT_CONFIRM npc QuestScriptTutorialBlocker_7 "CFReversed" LOCAL_CHAT_CONFIRM npc QuestScriptTutorialBlocker_8 1 "CFReversed" LOOP_ANIM npc "walk" diff --git a/toontown/quest/Quests.py b/toontown/quest/Quests.py index b1d503fd..ce631be8 100755 --- a/toontown/quest/Quests.py +++ b/toontown/quest/Quests.py @@ -289,6 +289,9 @@ class Quest: elif holderType == 'track': self.check(holder in self._cogTracks, 'invalid recovery item holder: %s for holderType: %s' % (holder, holderType)) + def checkTrackChoice(self, option): + self.check(option >= ToontownBattleGlobals.MIN_TRACK_INDEX and option <= ToontownBattleGlobals.MAX_TRACK_INDEX, 'invalid track option: %s' % option) + def checkNumFriends(self, num): self.check(1, 'invalid number of friends: %s' % num) @@ -1499,24 +1502,11 @@ class RecoverItemQuest(LocationBasedQuest): class TrackChoiceQuest(Quest): def __init__(self, id, quest): Quest.__init__(self, id, quest) + self.checkTrackChoice(self.quest[0]) + self.checkTrackChoice(self.quest[1]) - def getChoices(self, av): - trackAccess = av.getTrackAccess() - first = None - second = None - - for i in xrange(len(trackAccess)): - if trackAccess[i] == 0: - if first is None: - first = i - elif second is None: - second = i - break - - if first is None or second is None: - return (0, 1) - - return (first, second) + def getChoices(self): + return (self.quest[0], self.quest[1]) def getCompletionStatus(self, av, questDesc, npc = None): questId, fromNpcId, toNpcId, rewardId, toonProgress = questDesc @@ -1532,7 +1522,7 @@ class TrackChoiceQuest(Quest): return NotChosenString def getObjectiveStrings(self): - trackA, trackB = self.getChoices(base.localAvatar) + trackA, trackB = self.getChoices() trackAName = ToontownBattleGlobals.Tracks[trackA].capitalize() trackBName = ToontownBattleGlobals.Tracks[trackB].capitalize() return [trackAName, trackBName] @@ -1542,7 +1532,7 @@ class TrackChoiceQuest(Quest): 'trackB': self.getObjectiveStrings()[1]} def getSCStrings(self, toNpcId, progress): - trackA, trackB = self.getChoices(base.localAvatar) + trackA, trackB = self.getChoices() trackAName = ToontownBattleGlobals.Tracks[trackA].capitalize() trackBName = ToontownBattleGlobals.Tracks[trackB].capitalize() return [TTLocalizer.QuestsTrackChoiceQuestSCString % {'trackA': trackAName, @@ -1740,7 +1730,7 @@ QuestDict = { 170: (TT_TIER + 1, Cont, (VisitQuest,), Same, 2005, NA, 400, TTLocalizer.QuestDialogDict[170]), 171: (TT_TIER + 1, Cont, (VisitQuest,), Same, 2311, NA, 400, TTLocalizer.QuestDialogDict[171]), 172: (TT_TIER + 1, Cont, (VisitQuest,), Same, 2119, NA, 400, TTLocalizer.QuestDialogDict[172]), - 400: (TT_TIER + 1, Cont, (TrackChoiceQuest,), Same, Same, 400, NA, TTLocalizer.QuestDialogDict[400]), + 400: (TT_TIER + 1, Cont, (TrackChoiceQuest, ToontownBattleGlobals.SOUND_TRACK, ToontownBattleGlobals.HEAL_TRACK), Same, Same, 400, NA, TTLocalizer.QuestDialogDict[400]), 1001: (TT_TIER + 2, Start, (CogQuest, ToontownGlobals.ToontownCentral, 3, Any), Any, ToonHQ, Any, NA, DefaultDialog), 1002: (TT_TIER + 2, Start, (CogQuest, ToontownGlobals.ToontownCentral, 4, Any), Any, ToonHQ, Any, NA, DefaultDialog), 1003: (TT_TIER + 2, Start, (CogQuest, ToontownGlobals.ToontownCentral, 5, Any), Any, ToonHQ, Any, NA, DefaultDialog), @@ -1846,7 +1836,7 @@ QuestDict = { 1210: (TT_TIER + 3, Start, (CogQuest, Anywhere, 4, 'pp'), Any, ToonHQ, Any, NA, DefaultDialog), 1211: (TT_TIER + 3, Start, (CogQuest, Anywhere, 4, 'cc'), Any, ToonHQ, Any, NA, DefaultDialog), 1212: (TT_TIER + 3, Start, (CogQuest, Anywhere, 4, 'tm'), Any, ToonHQ, Any, NA, DefaultDialog), - 401: (DD_TIER, Start, (TrackChoiceQuest,), Any, ToonHQ, 400, NA, TTLocalizer.QuestDialogDict[401]), + 401: (DD_TIER, Start, (TrackChoiceQuest, ToontownBattleGlobals.DROP_TRACK, ToontownBattleGlobals.LURE_TRACK), Any, ToonHQ, 400, NA, TTLocalizer.QuestDialogDict[401]), 2001: (DD_TIER, Start, (CogQuest, Anywhere, 3, Any), Any, ToonHQ, Any, NA, DefaultDialog), 2002: (DD_TIER, Start, (CogQuest, Anywhere, 4, Any), Any, ToonHQ, Any, NA, DefaultDialog), 2003: (DD_TIER, Start, (CogQuest, Anywhere, 5, Any), Any, ToonHQ, Any, NA, DefaultDialog), @@ -2106,7 +2096,8 @@ QuestDict = { 3501: (DG_TIER, Cont, (DeliverItemQuest, 1000), Any, 5007, 1000, NA, DefaultDialog), 3502: (DG_TIER, Start, (RescueQuest, InVP, 1), Any, ToonHQ, Any, NA, DefaultDialog), 3503: (DG_TIER, Start, (RescueQuest, InFO, 2), Any, ToonHQ, Any, NA, DefaultDialog), - 4001: (MM_TIER, Start, (TrackChoiceQuest,), Any, ToonHQ, 400, NA, TTLocalizer.QuestDialogDict[4001]), + 4001: (MM_TIER, Start, (TrackChoiceQuest, ToontownBattleGlobals.TRAP_TRACK, ToontownBattleGlobals.HEAL_TRACK), Any, ToonHQ, 400, NA, TTLocalizer.QuestDialogDict[4001]), + 4002: (MM_TIER, Start, (TrackChoiceQuest, ToontownBattleGlobals.TRAP_TRACK, ToontownBattleGlobals.SOUND_TRACK), Any, ToonHQ, 400, NA, TTLocalizer.QuestDialogDict[4002]), 4010: (MM_TIER, Start, (CogQuest, Anywhere, 16, Any), Any, ToonHQ, Any, NA, DefaultDialog), 4011: (MM_TIER, Start, (CogQuest, Anywhere, 18, Any), Any, ToonHQ, Any, NA, DefaultDialog), 4012: (MM_TIER, Start, (CogQuest, Anywhere, 20, Any), Any, ToonHQ, Any, NA, DefaultDialog), @@ -2280,10 +2271,18 @@ QuestDict = { 5247: (BR_TIER, Start, (VisitQuest,), Any, 3112, NA, 5248, TTLocalizer.QuestDialogDict[5247]), 5248: (BR_TIER, Start, (CogLevelQuest, Anywhere, 10, 8), 3112, Same, NA, 5249, TTLocalizer.QuestDialogDict[5248]), 5249: (BR_TIER, Cont, (RecoverItemQuest, Anywhere, 3, 3018, VeryHard, AnyFish), Same, Same, NA, (5250, 5258, 5259, 5260), TTLocalizer.QuestDialogDict[5249]), - 5250: (BR_TIER, Cont, (BuildingQuest, Anywhere, 2, 'l', 4, 0), Same, Same, 408, NA, TTLocalizer.QuestDialogDict[5250]), - 5258: (BR_TIER, Cont, (BuildingQuest, Anywhere, 2, 'c', 4, 0), Same, Same, 408, NA, TTLocalizer.QuestDialogDict[5258]), - 5259: (BR_TIER, Cont, (BuildingQuest, Anywhere, 2, 'm', 4, 0), Same, Same, 408, NA, TTLocalizer.QuestDialogDict[5259]), - 5260: (BR_TIER, Cont, (BuildingQuest, Anywhere, 2, 's', 4, 0), Same, Same, 408, NA, TTLocalizer.QuestDialogDict[5260]), + 5250: (BR_TIER, Cont, (BuildingQuest, Anywhere, 2, 'l', 4, 0), Same, Same, NA, (5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008), TTLocalizer.QuestDialogDict[5250]), + 5258: (BR_TIER, Cont, (BuildingQuest, Anywhere, 2, 'c', 4, 0), Same, Same, NA, (5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008), TTLocalizer.QuestDialogDict[5258]), + 5259: (BR_TIER, Cont, (BuildingQuest, Anywhere, 2, 'm', 4, 0), Same, Same, NA, (5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008), TTLocalizer.QuestDialogDict[5259]), + 5260: (BR_TIER, Cont, (BuildingQuest, Anywhere, 2, 's', 4, 0), Same, Same, NA, (5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008), TTLocalizer.QuestDialogDict[5260]), + 5001: (BR_TIER, Cont, (TrackChoiceQuest, ToontownBattleGlobals.SOUND_TRACK, ToontownBattleGlobals.DROP_TRACK), Same, Same, 400, NA, TTLocalizer.TheBrrrghTrackQuestDict), + 5002: (BR_TIER, Cont, (TrackChoiceQuest, ToontownBattleGlobals.SOUND_TRACK, ToontownBattleGlobals.LURE_TRACK), Same, Same, 400, NA, TTLocalizer.TheBrrrghTrackQuestDict), + 5003: (BR_TIER, Cont, (TrackChoiceQuest, ToontownBattleGlobals.HEAL_TRACK, ToontownBattleGlobals.DROP_TRACK), Same, Same, 400, NA, TTLocalizer.TheBrrrghTrackQuestDict), + 5004: (BR_TIER, Cont, (TrackChoiceQuest, ToontownBattleGlobals.HEAL_TRACK, ToontownBattleGlobals.LURE_TRACK), Same, Same, 400, NA, TTLocalizer.TheBrrrghTrackQuestDict), + 5005: (BR_TIER, Cont, (TrackChoiceQuest, ToontownBattleGlobals.TRAP_TRACK, ToontownBattleGlobals.SOUND_TRACK), Same, Same, 400, NA, TTLocalizer.TheBrrrghTrackQuestDict), + 5006: (BR_TIER, Cont, (TrackChoiceQuest, ToontownBattleGlobals.TRAP_TRACK, ToontownBattleGlobals.HEAL_TRACK), Same, Same, 400, NA, TTLocalizer.TheBrrrghTrackQuestDict), + 5007: (BR_TIER, Cont, (TrackChoiceQuest, ToontownBattleGlobals.TRAP_TRACK, ToontownBattleGlobals.DROP_TRACK), Same, Same, 400, NA, TTLocalizer.TheBrrrghTrackQuestDict), + 5008: (BR_TIER, Cont, (TrackChoiceQuest, ToontownBattleGlobals.TRAP_TRACK, ToontownBattleGlobals.LURE_TRACK), Same, Same, 400, NA, TTLocalizer.TheBrrrghTrackQuestDict), 5020: (BR_TIER, Start, (CogQuest, Anywhere, 36, Any), Any, ToonHQ, Any, NA, DefaultDialog), 5021: (BR_TIER, Start, (CogQuest, Anywhere, 38, Any), Any, ToonHQ, Any, NA, DefaultDialog), 5022: (BR_TIER, Start, (CogQuest, Anywhere, 40, Any), Any, ToonHQ, Any, NA, DefaultDialog), @@ -3317,12 +3316,55 @@ def filterQuests(entireQuestPool, currentNpc, av): def chooseTrackChoiceQuest(tier, av, fixed = 0): + + def fixAndCallAgain(): + if not fixed and av.fixTrackAccess(): + notify.info('av %s trackAccess fixed: %s' % (av.getDoId(), trackAccess)) + return chooseTrackChoiceQuest(tier, av, fixed=1) + else: + return None + return None + + bestQuest = None + trackAccess = av.getTrackAccess() if tier == MM_TIER: - return 4001 + if trackAccess[ToontownBattleGlobals.HEAL_TRACK] == 1: + bestQuest = 4002 + elif trackAccess[ToontownBattleGlobals.SOUND_TRACK] == 1: + bestQuest = 4001 + else: + notify.warning('av %s has bogus trackAccess: %s' % (av.getDoId(), trackAccess)) + return fixAndCallAgain() elif tier == BR_TIER: - return 5247 + if trackAccess[ToontownBattleGlobals.SOUND_TRACK] + trackAccess[ToontownBattleGlobals.DROP_TRACK] == 0: + bestQuest = 5001 + elif trackAccess[ToontownBattleGlobals.SOUND_TRACK] + trackAccess[ToontownBattleGlobals.LURE_TRACK] == 0: + bestQuest = 5002 + elif trackAccess[ToontownBattleGlobals.HEAL_TRACK] + trackAccess[ToontownBattleGlobals.DROP_TRACK] == 0: + bestQuest = 5003 + elif trackAccess[ToontownBattleGlobals.HEAL_TRACK] + trackAccess[ToontownBattleGlobals.LURE_TRACK] == 0: + bestQuest = 5004 + elif trackAccess[ToontownBattleGlobals.TRAP_TRACK] + trackAccess[ToontownBattleGlobals.SOUND_TRACK] == 0: + bestQuest = 5005 + elif trackAccess[ToontownBattleGlobals.TRAP_TRACK] + trackAccess[ToontownBattleGlobals.HEAL_TRACK] == 0: + bestQuest = 5006 + elif trackAccess[ToontownBattleGlobals.TRAP_TRACK] + trackAccess[ToontownBattleGlobals.DROP_TRACK] == 0: + bestQuest = 5007 + elif trackAccess[ToontownBattleGlobals.TRAP_TRACK] + trackAccess[ToontownBattleGlobals.LURE_TRACK] == 0: + bestQuest = 5008 + else: + notify.warning('av %s has bogus trackAccess: %s' % (av.getDoId(), trackAccess)) + return fixAndCallAgain() else: - return seededRandomChoice(Tier2Reward2QuestsDict[tier][400]) + if notify.getDebug(): + notify.debug('questPool for reward 400 had no dynamic choice, tier: %s' % tier) + bestQuest = seededRandomChoice(Tier2Reward2QuestsDict[tier][400]) + if notify.getDebug(): + notify.debug('chooseTrackChoiceQuest: avId: %s trackAccess: %s tier: %s bestQuest: %s' % (av.getDoId(), + trackAccess, + tier, + bestQuest)) + return bestQuest def chooseMatchingQuest(tier, validQuestPool, rewardId, npc, av): @@ -3790,26 +3832,21 @@ class TrackTrainingReward(Reward): def __init__(self, id, reward): Reward.__init__(self, id, reward) - def getTrack(self, av): + def getTrack(self): track = self.reward[0] if track == None: track = 0 - trackAccess = av.getTrackAccess() - - for i in xrange(len(trackAccess)): - if trackAccess[i] == 0: - return i return track def sendRewardAI(self, av): - av.b_setTrackProgress(self.getTrack(av), 0) + av.b_setTrackProgress(self.getTrack(), 0) def countReward(self, qrc): - qrc.trackProgressId = self.getTrack(base.localAvatar) + qrc.trackProgressId = self.getTrack() qrc.trackProgress = 0 def getString(self): - trackName = ToontownBattleGlobals.Tracks[self.getTrack(base.localAvatar)].capitalize() + trackName = ToontownBattleGlobals.Tracks[self.getTrack()].capitalize() return TTLocalizer.QuestsTrackTrainingReward % trackName def getPosterString(self): @@ -4160,7 +4197,6 @@ RewardDict = { 405: (TrackTrainingReward, ToontownBattleGlobals.THROW_TRACK), 406: (TrackTrainingReward, ToontownBattleGlobals.SQUIRT_TRACK), 407: (TrackTrainingReward, ToontownBattleGlobals.DROP_TRACK), - 408: (TrackTrainingReward, None), 500: (MaxQuestCarryReward, 2), 501: (MaxQuestCarryReward, 3), 502: (MaxQuestCarryReward, 4), diff --git a/toontown/racing/DistributedRace.py b/toontown/racing/DistributedRace.py index 8a55d038..035354a1 100755 --- a/toontown/racing/DistributedRace.py +++ b/toontown/racing/DistributedRace.py @@ -551,14 +551,14 @@ class DistributedRace(DistributedObject.DistributedObject): newLapT = (newT - self.startT) / self.curve.getMaxT() % 1.0 if newLapT - self.currLapT < -0.5: self.laps += 1 - self.changeMusicTempo(1 + self.laps * 0.33) + self.changeMusicTempo(1 + self.laps * 0.5) self.notify.debug('crossed the start line: %s, %s, %s, %s' % (self.laps, self.startT, self.currT, newT)) elif newLapT - self.currLapT > 0.5: self.laps -= 1 - self.changeMusicTempo(1 + self.laps * 0.33) + self.changeMusicTempo(1 + self.laps * 0.5) self.notify.debug('crossed the start line - wrong way: %s, %s, %s, %s' % (self.laps, self.startT, self.currT, diff --git a/toontown/racing/DistributedRaceAI.py b/toontown/racing/DistributedRaceAI.py index a4cb502f..1791149d 100755 --- a/toontown/racing/DistributedRaceAI.py +++ b/toontown/racing/DistributedRaceAI.py @@ -33,6 +33,7 @@ class DistributedRaceAI(DistributedObjectAI, FSM): self.livingGags = [] self.currentlyAffectedByAnvil = {} self.avatarProgress = {} + self.startTime = globalClockDelta.networkToLocalTime(globalClockDelta.getRealNetworkTime()) + 3 def generate(self): for avatar in self.avatars: diff --git a/toontown/rpc/ToontownRPCHandler.py b/toontown/rpc/ToontownRPCHandler.py index 737e1dcc..ff16e881 100755 --- a/toontown/rpc/ToontownRPCHandler.py +++ b/toontown/rpc/ToontownRPCHandler.py @@ -2,7 +2,7 @@ import datetime from direct.distributed.MsgTypes import CLIENTAGENT_EJECT from direct.distributed.PyDatagram import PyDatagram from direct.stdpy import threading2 -import re +import re, json from otp.distributed import OtpDoGlobals from toontown.distributed.ShardStatusReceiver import ShardStatusReceiver @@ -437,8 +437,14 @@ class ToontownRPCHandler(ToontownRPCHandlerBase): On success: 100000000 On failure: None """ - if str(userId) in self.air.csm.accountDB.dbm: - return int(self.air.csm.accountDB.dbm[str(userId)]) + response = executeHttpRequest('accountid', username=str(userId)) + if response is not None: + response = json.loads(response) + if response['success'] is True: + return int(response['accountId']) + else: + print response['error'] + return False @rpcmethod(accessLevel=MODERATOR) def rpc_getUserAvatars(self, userId): @@ -642,8 +648,9 @@ class ToontownRPCHandler(ToontownRPCHandlerBase): dna.makeFromNetString(fields['setDNAString'][0]) result['species'] = ToonDNA.getSpeciesName(dna.head) - result['head-color'] = dna.headColor - result['max-hp'] = fields['setMaxHp'][0] + result['head_color'] = dna.headColor + result['max_hp'] = fields['setMaxHp'][0] + result['hp'] = fields['setHp'][0] result['online'] = (avId in self.air.friendsManager.onlineToons) return result @@ -661,13 +668,13 @@ class ToontownRPCHandler(ToontownRPCHandlerBase): Example response: [100000001, ...] """ - if not config.GetBool('want-mongo-client', False): + if not config.GetBool('want-mongo', False): return [] if not needle: return [] - self.air.mongodb.astron.objects.ensure_index('fields.setName') + self.air.database.astron.objects.ensure_index('fields.setName') exp = re.compile('.*%s.*' % needle, re.IGNORECASE) - result = self.air.mongodb.astron.objects.find({'fields.setName._0': exp}) + result = self.air.database.astron.objects.find({'fields.setName._0': exp}) return [avatar['_id'] for avatar in result] # --- SHARDS --- diff --git a/toontown/safezone/DistributedFishingSpot.py b/toontown/safezone/DistributedFishingSpot.py index 078f197f..d4a4e1d4 100755 --- a/toontown/safezone/DistributedFishingSpot.py +++ b/toontown/safezone/DistributedFishingSpot.py @@ -568,6 +568,7 @@ class DistributedFishingSpot(DistributedObject.DistributedObject): self.sellFishConfirmDialog.hide() self.brokeDialog.hide() self.howToDialog.hide() + self.exitButton.hide() self.castButton.unbind(DGG.B1PRESS) self.castButton.unbind(DGG.B3PRESS) self.castButton.unbind(DGG.B1RELEASE) @@ -592,7 +593,7 @@ class DistributedFishingSpot(DistributedObject.DistributedObject): self.castGui.setPos(0, 1, 0) for nodeName in ('bucket', 'jar', 'display_bucket', 'display_jar'): self.castGui.find('**/' + nodeName).reparentTo(self.castGui) - self.exitButton = DirectButton(parent=self.castGui, relief=None, text=('', TTLocalizer.FishingExit, TTLocalizer.FishingExit), text_align=TextNode.ACenter, text_scale=0.1, text_fg=Vec4(1, 1, 1, 1), text_shadow=Vec4(0, 0, 0, 1), text_pos=(0.0, -0.12), pos=(1.75*(4./3.), 0, -1.33), textMayChange=0, image=(self.castGui.find('**/exit_buttonUp'), self.castGui.find('**/exit_buttonDown'), self.castGui.find('**/exit_buttonRollover')), command=self.__userExit) + self.exitButton = DirectButton(parent=base.a2dBottomRight, relief=None, text=('', TTLocalizer.FishingExit, TTLocalizer.FishingExit), text_align=TextNode.ACenter, text_scale=0.1, text_fg=Vec4(1, 1, 1, 1), text_shadow=Vec4(0, 0, 0, 1), text_pos=(0.0, -0.12), pos=(-0.218, 0, 0.11), scale=0.8, textMayChange=0, image=(self.castGui.find('**/exit_buttonUp'), self.castGui.find('**/exit_buttonDown'), self.castGui.find('**/exit_buttonRollover')), command=self.__userExit) self.castGui.find('**/exitButton').removeNode() self.castButton = DirectButton(parent=self.castGui, relief=None, text=TTLocalizer.FishingCast, text_align=TextNode.ACenter, text_scale=(3, 3 * 0.75, 3 * 0.75), text_fg=Vec4(1, 1, 1, 1), text_shadow=Vec4(0, 0, 0, 1), text_pos=(0, -4), image=self.castGui.find('**/castButton'), image0_color=(1, 0, 0, 1), image1_color=(0, 1, 0, 1), image2_color=(1, 1, 0, 1), image3_color=(0.8, 0.5, 0.5, 1), pos=(0, -0.05, -0.666), scale=(0.036, 1, 0.048)) self.castGui.find('**/castButton').removeNode() @@ -1050,9 +1051,4 @@ class DistributedFishingSpot(DistributedObject.DistributedObject): self.fsm.request('waiting', [False]) def __allowSellFish(self): - if base.wantBingo: - if self.pond.hasPondBingoManager(): - hoodId = base.cr.playGame.getPlaceId() - if hoodId == ToontownGlobals.MyEstate: - return True - return False + return base.wantBingo and self.pond.hasPondBingoManager() diff --git a/toontown/safezone/TTSafeZoneLoader.py b/toontown/safezone/TTSafeZoneLoader.py index b6e5b245..ae73f407 100755 --- a/toontown/safezone/TTSafeZoneLoader.py +++ b/toontown/safezone/TTSafeZoneLoader.py @@ -16,8 +16,11 @@ class TTSafeZoneLoader(SafeZoneLoader.SafeZoneLoader): 'phase_4/audio/sfx/SZ_TC_bird2.ogg', 'phase_4/audio/sfx/SZ_TC_bird3.ogg']) bank = self.geom.find('**/*toon_landmark_TT_bank_DNARoot') + library = self.geom.find('**/library/square_drop_shadow') doorTrigger = bank.find('**/door_trigger*') doorTrigger.setY(doorTrigger.getY() - 1.5) + library.find('**/building_front').setY(0.3) + library.find('**/front_entrance_flag').setY(0.1) def unload(self): SafeZoneLoader.SafeZoneLoader.unload(self) diff --git a/toontown/shtiker/OptionsPage.py b/toontown/shtiker/OptionsPage.py index c7f92c29..cda4d2f5 100755 --- a/toontown/shtiker/OptionsPage.py +++ b/toontown/shtiker/OptionsPage.py @@ -731,25 +731,31 @@ class ExtraOptionsTabPage(DirectFrame): self.fov_label = DirectLabel(parent=self, relief=None, text=TTLocalizer.FieldOfViewLabel, text_align=TextNode.ALeft, text_scale=options_text_scale, text_wordwrap=16, pos=(leftMargin, 0, textStartHeight)) self.cogInterface_label = DirectLabel(parent=self, relief=None, text='', text_align=TextNode.ALeft, text_scale=options_text_scale, text_wordwrap=16, pos=(leftMargin, 0, textStartHeight - textRowHeight)) self.tpTransition_label = DirectLabel(parent=self, relief=None, text='', text_align=TextNode.ALeft, text_scale=options_text_scale, text_wordwrap=16, pos=(leftMargin, 0, textStartHeight - 2 * textRowHeight)) + self.fpsMeter_label = DirectLabel(parent=self, relief=None, text='', text_align=TextNode.ALeft, text_scale=options_text_scale, text_wordwrap=16, pos=(leftMargin, 0, textStartHeight - 3 * textRowHeight)) + self.teleport_label = DirectLabel(parent=self, relief=None, text='', text_align=TextNode.ALeft, text_scale=options_text_scale, text_wordwrap=16, pos=(leftMargin, 0, textStartHeight - 4 * textRowHeight)) self.fov_slider = DirectSlider(parent=self, pos=(buttonbase_xcoord, 0.0, buttonbase_ycoord), value=settings['fov'], pageSize=5, range=(ToontownGlobals.DefaultCameraFov, ToontownGlobals.MaxCameraFov), command=self.__doFov, thumb_geom=(circleModel.find('**/tt_t_gui_mat_namePanelCircle')), thumb_relief=None, thumb_geom_scale=2) self.fov_slider.setScale(0.25) self.cogInterface_toggleButton = DirectButton(parent=self, relief=None, image=button_image, image_scale=button_image_scale, text='', text_scale=options_text_scale, text_pos=button_textpos, pos=(buttonbase_xcoord, 0.0, buttonbase_ycoord - textRowHeight), command=self.__doToggleCogInterface) self.tpTransition_toggleButton = DirectButton(parent=self, relief=None, image=button_image, image_scale=button_image_scale, text='', text_scale=options_text_scale, text_pos=button_textpos, pos=(buttonbase_xcoord, 0.0, buttonbase_ycoord - 2 * textRowHeight), command=self.__doToggleTpTransition) + self.fpsMeter_toggleButton = DirectButton(parent=self, relief=None, image=button_image, image_scale=button_image_scale, text='', text_scale=options_text_scale, text_pos=button_textpos, pos=(buttonbase_xcoord, 0.0, buttonbase_ycoord - 3 * textRowHeight), command=self.__doToggleFpsMeter) + self.teleport_toggleButton = DirectButton(parent=self, relief=None, image=button_image, image_scale=button_image_scale, text='', text_scale=options_text_scale, text_pos=button_textpos, pos=(buttonbase_xcoord, 0.0, buttonbase_ycoord - 4 * textRowHeight), command=self.__doToggleTeleport) self.bugReportButton = DirectButton(parent=self, relief=None, text=TTLocalizer.BugReportButton, image=button_image, image_scale=button_image_scale, text_pos=(0, -0.01), text_fg=(0, 0, 0, 1), command=self.showReportNotice, pos=(0.0, 0.0, -0.6), text_scale=(0.045)) guiButton.removeNode() circleModel.removeNode() - self.optionChoosers['pole'] = OptionChooser.OptionChooser(self, TTLocalizer.FishingPoleLabel, 3, self.__updateFishingPole, [False], self.__applyFishingPole) - self.optionChoosers['nametag_style'] = OptionChooser.OptionChooser(self, TTLocalizer.NametagStyleLabel, 4, self.__updateNametagStyle, [False], self.__applyNametagStyle) + self.optionChoosers['pole'] = OptionChooser.OptionChooser(self, TTLocalizer.FishingPoleLabel, 5, self.__updateFishingPole, [False], self.__applyFishingPole) + self.optionChoosers['nametag_style'] = OptionChooser.OptionChooser(self, TTLocalizer.NametagStyleLabel, 6, self.__updateNametagStyle, [False], self.__applyNametagStyle) def enter(self): self.show() self.settingsChanged = 0 self.__setCogInterfaceButton() self.__setTpTransitionButton() + self.__setFpsMeterButton() + self.__setTeleportButton() self.__updateNametagStyle() self.__updateFishingPole() self.accept('refreshNametagStyle', self.__updateNametagStyle) @@ -776,6 +782,14 @@ class ExtraOptionsTabPage(DirectFrame): del self.tpTransition_label self.tpTransition_toggleButton.destroy() del self.tpTransition_toggleButton + self.fpsMeter_label.destroy() + del self.fpsMeter_label + self.fpsMeter_toggleButton.destroy() + del self.fpsMeter_toggleButton + self.teleport_label.destroy() + del self.teleport_label + self.teleport_toggleButton.destroy() + del self.teleport_toggleButton self.bugReportButton.destroy() del self.bugReportButton self.destroyReportNotice() @@ -807,6 +821,34 @@ class ExtraOptionsTabPage(DirectFrame): def __setTpTransitionButton(self): self.tpTransition_label['text'] = TTLocalizer.TpTransitionLabelOn if settings['tpTransition'] else TTLocalizer.TpTransitionLabelOff self.tpTransition_toggleButton['text'] = TTLocalizer.OptionsPageToggleOff if settings['tpTransition'] else TTLocalizer.OptionsPageToggleOn + + def __doToggleFpsMeter(self): + messenger.send('wakeup') + settings['fpsMeter'] = not settings['fpsMeter'] + base.setFrameRateMeter(settings['fpsMeter']) + self.settingsChanged = 1 + self.__setFpsMeterButton() + + def __setFpsMeterButton(self): + self.fpsMeter_label['text'] = TTLocalizer.FpsMeterLabelOn if settings['fpsMeter'] else TTLocalizer.FpsMeterLabelOff + self.fpsMeter_toggleButton['text'] = TTLocalizer.OptionsPageToggleOff if settings['fpsMeter'] else TTLocalizer.OptionsPageToggleOn + + def __doToggleTeleport(self): + messenger.send('wakeup') + acceptingTeleport = settings.get('acceptingTeleport', {}) + if base.localAvatar.acceptingTeleport: + base.localAvatar.acceptingTeleport = 0 + acceptingTeleport[str(base.localAvatar.doId)] = False + else: + base.localAvatar.acceptingTeleport = 1 + acceptingTeleport[str(base.localAvatar.doId)] = True + settings['acceptingTeleport'] = acceptingTeleport + self.settingsChanged = 1 + self.__setTeleportButton() + + def __setTeleportButton(self): + self.teleport_label['text'] = TTLocalizer.TeleportLabelOn if base.localAvatar.acceptingTeleport else TTLocalizer.TeleportLabelOff + self.teleport_toggleButton['text'] = TTLocalizer.OptionsPageToggleOff if base.localAvatar.acceptingTeleport else TTLocalizer.OptionsPageToggleOn def __updateNametagStyle(self, resetIndex=True): chooser = self.optionChoosers['nametag_style'] diff --git a/toontown/shtiker/ShtikerBook.py b/toontown/shtiker/ShtikerBook.py index 0874ac99..baddb5e7 100755 --- a/toontown/shtiker/ShtikerBook.py +++ b/toontown/shtiker/ShtikerBook.py @@ -21,8 +21,7 @@ class ShtikerBook(DirectFrame, StateData.StateData): self.pages = [] self.pageTabs = [] self.currPageTabIndex = None - self.pageTabFrame = DirectFrame(parent=self, relief=None, pos=(0.93, 1, 0.575), scale=1.25) - self.pageTabFrame.hide() + self.pageTabFrames = [self.createPageTabFrame(x) for x in (-0.93, 0.93)] self.currPageIndex = None self.entered = 0 self.safeMode = 0 @@ -47,6 +46,11 @@ class ShtikerBook(DirectFrame, StateData.StateData): TTLocalizer.PhotoPageTitle, TTLocalizer.EventsPageName, TTLocalizer.StatPageTitle] + + def createPageTabFrame(self, x): + frame = DirectFrame(parent=self, relief=None, pos=(x, 0, 0.66), scale=1.25) + frame.hide() + return frame def setSafeMode(self, setting): self.safeMode = setting @@ -76,7 +80,8 @@ class ShtikerBook(DirectFrame, StateData.StateData): self.accept('shtiker-page-done', self.__pageDone) self.accept(ToontownGlobals.StickerBookHotkey, self.__close) self.accept(ToontownGlobals.OptionsPageHotkey, self.__close) - self.pageTabFrame.show() + for tab in self.pageTabFrames: + tab.show() self.pages[self.currPageIndex].enter() def exit(self): @@ -106,7 +111,8 @@ class ShtikerBook(DirectFrame, StateData.StateData): self.hide() self.hideButton() cleanupDialog('globalDialog') - self.pageTabFrame.hide() + for tab in self.pageTabFrames: + tab.hide() self.ignore('shtiker-page-done') self.ignore(ToontownGlobals.StickerBookHotkey) self.ignore(ToontownGlobals.OptionsPageHotkey) @@ -178,7 +184,7 @@ class ShtikerBook(DirectFrame, StateData.StateData): if base.config.GetBool('want-qa-regression', 0): self.notify.info('QA-REGRESSION: SHTICKERBOOK: Browse tabs %s' % page.pageName) - yOffset = 0.07 * pageIndex + yOffset = 0.07 * (pageIndex % 16) iconGeom = None iconImage = None iconScale = 1 @@ -257,13 +263,14 @@ class ShtikerBook(DirectFrame, StateData.StateData): iconModels.detachNode() if pageName == TTLocalizer.OptionsPageTitle: pageName = TTLocalizer.OptionsTabTitle - pageTab = DirectButton(parent=self.pageTabFrame, relief=DGG.RAISED, frameSize=(-0.575, + rightSide = pageIndex < 16 + pageTab = DirectButton(parent=self.pageTabFrames[rightSide], relief=DGG.RAISED, frameSize=(-0.575, 0.575, -0.575, 0.575), borderWidth=(0.05, 0.05), text=('', '', pageName, - ''), text_align=TextNode.ALeft, text_pos=(1, -0.2), text_scale=TTLocalizer.SBpageTab, text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), image=iconImage, image_scale=iconScale, geom=iconGeom, geom_scale=iconScale, geom_color=iconColor, pos=(0, 0, -yOffset), scale=0.06, command=buttonPressedCommand, extraArgs=extraArgs) + ''), text_align=TextNode.ALeft, text_pos=(1 if rightSide else -4, -0.2), text_scale=TTLocalizer.SBpageTab, text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), image=iconImage, image_scale=iconScale, geom=iconGeom, geom_scale=iconScale, geom_color=iconColor, pos=(0, 0, -yOffset), scale=0.06, command=buttonPressedCommand, extraArgs=extraArgs) self.pageTabs.insert(pageIndex, pageTab) return diff --git a/toontown/shtiker/StatPage.py b/toontown/shtiker/StatPage.py index 9c38a7f8..a945aae3 100644 --- a/toontown/shtiker/StatPage.py +++ b/toontown/shtiker/StatPage.py @@ -1,24 +1,21 @@ from direct.gui.DirectGui import * -from toontown.toonbase import TTLocalizer +from toontown.toonbase import TTLocalizer, ToontownGlobals from toontown.toontowngui import TTDialog import ShtikerPage -STATS = ['cog', 'v2', 'skele', 'beanSpent', 'beanEarnt', 'task', 'vp', 'cfo', 'cj', 'ceo', 'sad', 'bldg', 'cogdo', 'item', 'fish', 'flower', 'race', 'golf', 'sos', 'unite', 'slip', 'gag'] - class StatPage(ShtikerPage.ShtikerPage): - def __init__(self): + ShtikerPage.ShtikerPage.__init__(self) self.dialog = None + self.chunkCount = 11 def load(self): guiButton = loader.loadModel('phase_3/models/gui/quit_button') - self.rows = [None] * 2 - self.title = DirectLabel(parent=self, relief=None, text=TTLocalizer.StatPageTitle, text_scale=0.12, textMayChange=0, pos=(0, 0, 0.6)) - self.rows[0] = DirectLabel(parent=self, relief=None, text_align=TextNode.ALeft, text='', text_scale=0.06, text_wordwrap=16, pos=(-0.8, 0, 0.515)) - self.rows[1] = DirectLabel(parent=self, relief=None, text_align=TextNode.ALeft, text='', text_scale=0.06, text_wordwrap=16, pos=(0.05, 0, 0.515)) - self.resetButton = empty = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=(1.1, 1, 1), text='Reset stats', text_scale=0.055, text_pos=(0, -0.02), pos=(-0.55, 0.0, 0.65), command=self.__showDialog) + self.rows = [self.createRow(pos) for pos in ((-0.8, 0, 0.435), (0.08, 0, 0.435))] + self.title = DirectLabel(parent=self, relief=None, text=TTLocalizer.StatPageTitle, text_scale=0.12, textMayChange=0, pos=(-0.625, 0, 0.625)) + self.resetButton = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=(1.1, 1, 1), text=TTLocalizer.StatPageClear, text_scale=0.055, text_pos=(0, -0.02), pos=(0.605, 0, 0.66), command=self.__showDialog) guiButton.removeNode() def enter(self): @@ -47,25 +44,26 @@ class StatPage(ShtikerPage.ShtikerPage): if self.dialog: self.dialog.destroy() self.dialog = None + + def createRow(self, pos): + row = DirectLabel(parent=self, relief=None, text_align=TextNode.ALeft, text='', text_scale=0.045, text_wordwrap=16, text_font=ToontownGlobals.getChalkFont(), text_fg=(1, 1, 1, 1), image='phase_3/maps/stat_board.png', image_scale=(0.42, 0, 0.6), image_pos=(0.35, 0, -0.45)) + row.setPos(pos) + return row def cutToChunks(self, list, size): for i in xrange(0, len(list), size): yield list[i:i+size] def updateStats(self): - dict = {} stats = base.localAvatar.stats - - for i, string in enumerate(STATS): - dict[string] = "{:,}".format(stats[i]) - - textChunks = list(self.cutToChunks(TTLocalizer.Stats, 11)) + allStats = [TTLocalizer.Stats[i] % '{:,}'.format(stats[i]) for i in xrange(len(stats))] + textChunks = list(self.cutToChunks(allStats, self.chunkCount)) for i, chunk in enumerate(textChunks): - self.rows[i]['text'] = '\n\n'.join(chunk) % dict + self.rows[i]['text'] = '\n\n'.join(chunk) def __showDialog(self): - self.dialog = TTDialog.TTDialog(style=TTDialog.TwoChoice, text=TTLocalizer.StatResetAsk, text_wordwrap=15, command=self.__handleDialogResponse) + self.dialog = TTDialog.TTDialog(style=TTDialog.TwoChoice, text=TTLocalizer.StatPageClearAsk, text_wordwrap=15, command=self.__handleDialogResponse) self.dialog.show() def __handleDialogResponse(self, response): @@ -75,5 +73,5 @@ class StatPage(ShtikerPage.ShtikerPage): return base.localAvatar.wipeStats() - self.dialog = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=TTLocalizer.StatResetDone, text_wordwrap=15, command=self.unloadDialog) + self.dialog = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=TTLocalizer.StatPageClearDone, text_wordwrap=15, command=self.unloadDialog) self.dialog.show() \ No newline at end of file diff --git a/toontown/shtiker/SuitPage.py b/toontown/shtiker/SuitPage.py index ef2c27c5..b4606f0f 100755 --- a/toontown/shtiker/SuitPage.py +++ b/toontown/shtiker/SuitPage.py @@ -75,8 +75,8 @@ SHADOW_SCALE_POS = ((1.225, 0, 10, -0.01), - (0.9, - 0.005, + (1.05, + 0, 10, -0.01), (0.95, @@ -230,6 +230,7 @@ class SuitPage(ShtikerPage.ShtikerPage): self.legalRadarButton.destroy() self.moneyRadarButton.destroy() self.salesRadarButton.destroy() + self.rolloverFrame.destroy() for panel in self.panels: panel.destroy() del self.panels @@ -335,6 +336,12 @@ class SuitPage(ShtikerPage.ShtikerPage): yStart = -0.18 xOffset = 0.199 yOffset = 0.284 + gui = loader.loadModel('phase_3.5/models/gui/suit_detail_panel') + gui.find('**/avatar_panel/shadow').setColor(1, 1, 1, 0.5) + self.rolloverFrame = DirectFrame(parent=self.panelNode, relief=None, geom=gui.find('**/avatar_panel'), geom_color=(0.5, 0.5, 0.5, 1), geom_scale=(0.59, 0, 0.21), text_scale=0.06, text_pos=(0, 0.35), text='', text_fg=(1, 1, 1, 1), text_font=ToontownGlobals.getSuitFont(), pos=(0.8, 0, 0)) + self.rolloverFrame.setBin('gui-popup', 0) + self.rolloverFrame.hide() + gui.removeNode() for dept in xrange(0, len(SuitDNA.suitDepts)): row = [] color = PANEL_COLORS[dept] @@ -347,10 +354,20 @@ class SuitPage(ShtikerPage.ShtikerPage): panel.shadow = None panel.count = 0 panel.summonButton = None + panel.hoverButton = DirectButton(parent=panel, relief=None, image_scale=(0.15, 0, 0.225), image='phase_3/maps/invisible.png', pressEffect=0) + panel.hoverButton.setTransparency(True) + panel.hoverButton.panel = panel self.addCogRadarLabel(panel) self.panels.append(panel) base.panels.append(panel) - return + + def showInfo(self, panel, text, extra): + self.rolloverFrame.reparentTo(panel) + self.rolloverFrame.show() + self.rolloverFrame['text'] = text + + def hideInfo(self, extra): + self.rolloverFrame.hide() def addQuotaLabel(self, panel): index = self.panels.index(panel) @@ -405,7 +422,6 @@ class SuitPage(ShtikerPage.ShtikerPage): index = self.panels.index(panel) if not base.localAvatar.hasCogSummons(index): panel.summonButton.hide() - return def addBuildingRadarLabel(self, button): gui = loader.loadModel('phase_3.5/models/gui/suit_detail_panel') @@ -413,7 +429,6 @@ class SuitPage(ShtikerPage.ShtikerPage): buildingRadarLabel = DirectLabel(parent=button, relief=None, pos=(0.225, 0.0, zPos), state=DGG.DISABLED, image=gui.find('**/avatar_panel'), image_hpr=(0, 0, 90), image_scale=(0.05, 1, 0.1), image_pos=(0, 0, 0.015), text=TTLocalizer.SuitPageBuildingRadarP % '0', text_scale=0.05, text_fg=(1, 0, 0, 1), text_font=ToontownGlobals.getSuitFont()) gui.removeNode() button.buildingRadarLabel = buildingRadarLabel - return def resetPanel(self, dept, type): panel = self.panels[dept * SuitDNA.suitsPerDept + type] @@ -428,6 +443,9 @@ class SuitPage(ShtikerPage.ShtikerPage): panel.shadow.hide() if panel.summonButton: panel.summonButton.hide() + self.rolloverFrame.hide() + panel.hoverButton.unbind(DGG.ENTER) + panel.hoverButton.unbind(DGG.EXIT) color = PANEL_COLORS[dept] panel['image_color'] = color for button in self.radarButtons: @@ -467,6 +485,19 @@ class SuitPage(ShtikerPage.ShtikerPage): panel['image_color'] = PANEL_COLORS_COMPLETE1[index / SuitDNA.suitsPerDept] elif status == COG_COMPLETE2: panel['image_color'] = PANEL_COLORS_COMPLETE2[index / SuitDNA.suitsPerDept] + if status in (COG_DEFEATED, COG_COMPLETE1, COG_COMPLETE2): + name = SuitDNA.suitHeadTypes[index] + attributes = SuitBattleGlobals.SuitAttributes[name] + level = attributes['level'] + groupAttacks, singleAttacks = SuitBattleGlobals.getAttacksByType(attributes) + info = TTLocalizer.SuitPageAttackFormat % (level + 1, level + 5, self.getAttackStrings(groupAttacks), self.getAttackStrings(singleAttacks)) + + panel.hoverButton.bind(DGG.ENTER, self.showInfo, extraArgs=[panel, info]) + panel.hoverButton.bind(DGG.EXIT, self.hideInfo) + + def getAttackStrings(self, attacks): + string = '\n'.join(['%s %s' % (TTLocalizer.SuitAttackNames[attack[0]], '-'.join(str(x) for x in attack[1])) for attack in attacks]) + return string if string else TTLocalizer.SuitPageNoAttacks def updateAllCogs(self, status): for index in xrange(0, len(base.localAvatar.cogs)): @@ -572,4 +603,3 @@ class SuitPage(ShtikerPage.ShtikerPage): taskMgr.doMethodLater(RADAR_DELAY * SuitDNA.suitsPerDept, showLabel, 'showBuildingRadarLater', extraArgs=(button,)) else: button.buildingRadarLabel.hide() - return diff --git a/toontown/suit/BossCog.py b/toontown/suit/BossCog.py index 3c96a4f0..e247384a 100755 --- a/toontown/suit/BossCog.py +++ b/toontown/suit/BossCog.py @@ -461,7 +461,8 @@ class BossCog(Avatar.Avatar): self.doAnimate(None, raised=1, happy=1, queueNeutral=1) ival = Sequence() if self.dna.dept == 'm': - ival.append(Parallel(SoundInterval(self.warningSfx, node=self), Wait(5.0))) + ival.append(Func(self.loop, 'Ff_neutral')) + ival.append(Parallel(SoundInterval(self.warningSfx, node=self, volume=2.0), Wait(3.0))) ival.append(Parallel(ActorInterval(self, 'Fb_jump'), Sequence(Func(self.setChatAbsolute, random.choice(TTLocalizer.JumpBossTaunts[self.dna.dept]), CFSpeech | CFTimeout), SoundInterval(self.swishSfx, duration=1.1, node=self), SoundInterval(self.boomSfx, duration=1.9)), Sequence(Wait(1.21), Func(self.announceAreaAttack)))) if self.twoFaced: self.happy = 0 diff --git a/toontown/suit/DistributedBossCogAI.py b/toontown/suit/DistributedBossCogAI.py index 7d82d1f3..c790e670 100755 --- a/toontown/suit/DistributedBossCogAI.py +++ b/toontown/suit/DistributedBossCogAI.py @@ -561,7 +561,7 @@ class DistributedBossCogAI(DistributedAvatarAI.DistributedAvatarAI): damage *= self.getDamageMultiplier() self.damageToon(toon, damage) currState = self.getCurrentOrNextState() - if attackCode == ToontownGlobals.BossCogElectricFence and (currState == 'RollToBattleTwo' or currState == 'BattleThree'): + if attackCode == ToontownGlobals.BossCogElectricFence and (currState == 'RollToBattleTwo' or currState == 'BattleThree') and self.attackCode not in (ToontownGlobals.BossCogDizzy, ToontownGlobals.BossCogDizzyNow): if bpy < 0 and abs(bpx / bpy) > 0.5: if bpx < 0: self.b_setAttackCode(ToontownGlobals.BossCogSwatRight) @@ -600,7 +600,6 @@ class DistributedBossCogAI(DistributedAvatarAI.DistributedAvatarAI): if self.dept == 'm' and attackCode == ToontownGlobals.BossCogAreaAttack: delayTime += 5.0 self.waitForNextAttack(delayTime) - return def d_setAttackCode(self, attackCode, avId = 0): self.sendUpdate('setAttackCode', [attackCode, avId]) diff --git a/toontown/suit/DistributedCashbotBossAI.py b/toontown/suit/DistributedCashbotBossAI.py index 4dd14e16..77e8535a 100755 --- a/toontown/suit/DistributedCashbotBossAI.py +++ b/toontown/suit/DistributedCashbotBossAI.py @@ -145,7 +145,7 @@ class DistributedCashbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS def doNextAttack(self, task): if random.random() <= 0.2: self.b_setAttackCode(ToontownGlobals.BossCogAreaAttack) - taskMgr.doMethodLater(9.36, self.__reviveGoons, self.uniqueName('reviveGoons')) + taskMgr.doMethodLater(7.36, self.__reviveGoons, self.uniqueName('reviveGoons')) else: self.__doDirectedAttack() if self.heldObject == None and not self.waitingForHelmet: diff --git a/toontown/suit/DistributedLawbotBoss.py b/toontown/suit/DistributedLawbotBoss.py index 2ee4b9da..279af16b 100755 --- a/toontown/suit/DistributedLawbotBoss.py +++ b/toontown/suit/DistributedLawbotBoss.py @@ -23,10 +23,9 @@ from toontown.building import ElevatorConstants from toontown.building import ElevatorUtils from toontown.coghq import CogDisguiseGlobals from toontown.distributed import DelayDelete -from otp.nametag import NametagGroup from otp.nametag.NametagConstants import * from otp.nametag import NametagGlobals -from toontown.toon import Toon +from toontown.toon import NPCToons from toontown.toonbase import TTLocalizer from toontown.toonbase import ToontownBattleGlobals from toontown.toonbase import ToontownGlobals @@ -1567,15 +1566,11 @@ class DistributedLawbotBoss(DistributedBossCog.DistributedBossCog, FSM.FSM): return bossTrack def __makeWitnessToon(self): - dnaNetString = 't\x1b\x00\x01\x01\x00\x03\x00\x03\x01\x10\x13\x00\x13\x13' - npc = Toon.Toon() - npc.setDNAString(dnaNetString) - npc.setName(TTLocalizer.WitnessToonName) - npc.setPickable(0) - npc.setPlayerType(NametagGroup.CCNonPlayer) - npc.animFSM.request('Sit') - self.witnessToon = npc + if self.witnessToon: + return + self.witnessToon = NPCToons.createLocalNPC(13002) self.witnessToon.setPosHpr(*ToontownGlobals.LawbotBossWitnessStandPosHpr) + self.witnessToon.animFSM.request('Sit') def __cleanupWitnessToon(self): self.__hideWitnessToon() @@ -1583,7 +1578,6 @@ class DistributedLawbotBoss(DistributedBossCog.DistributedBossCog, FSM.FSM): self.witnessToon.removeActive() self.witnessToon.delete() self.witnessToon = None - return def __showWitnessToon(self): if not self.witnessToonOnstage: diff --git a/toontown/suit/DistributedSellbotBossAI.py b/toontown/suit/DistributedSellbotBossAI.py index 40f42cfa..de4b6abf 100755 --- a/toontown/suit/DistributedSellbotBossAI.py +++ b/toontown/suit/DistributedSellbotBossAI.py @@ -30,7 +30,6 @@ class DistributedSellbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS self.bossMaxDamage = ToontownGlobals.SellbotBossMaxDamage self.recoverRate = 0 self.recoverStartTime = 0 - self.punishedToons = [] def delete(self): return DistributedBossCogAI.DistributedBossCogAI.delete(self) @@ -197,13 +196,6 @@ class DistributedSellbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS return self.invokeSuitPlanner(10, 1) def removeToon(self, avId): - av = self.air.doId2do.get(avId) - if not av is None: - if av.getHp() <= 0: - if avId not in self.punishedToons: - self.air.cogSuitMgr.removeParts(av, self.deptIndex) - self.punishedToons.append(avId) - toon = simbase.air.doId2do.get(avId) if toon: toon.b_setNumPies(0) diff --git a/toontown/suit/Suit.py b/toontown/suit/Suit.py index 004f8f7b..ca0db861 100755 --- a/toontown/suit/Suit.py +++ b/toontown/suit/Suit.py @@ -235,12 +235,12 @@ def loadDialog(level): SuitDialogFiles = ['COG_VO_grunt', 'COG_VO_murmur', 'COG_VO_statement', - 'COG_VO_question'] + 'COG_VO_question', + 'COG_VO_exclaim'] for file in SuitDialogFiles: SuitDialogArray.append(base.loadSfx(loadPath + file + '.ogg')) SuitDialogArray.append(SuitDialogArray[2]) - SuitDialogArray.append(SuitDialogArray[2]) def loadSkelDialog(): @@ -252,11 +252,12 @@ def loadSkelDialog(): murmur = loader.loadSfx('phase_5/audio/sfx/Skel_COG_VO_murmur.ogg') statement = loader.loadSfx('phase_5/audio/sfx/Skel_COG_VO_statement.ogg') question = loader.loadSfx('phase_5/audio/sfx/Skel_COG_VO_question.ogg') + exclaim = loader.loadSfx('phase_5/audio/sfx/Skel_COG_VO_exclaim.ogg') SkelSuitDialogArray = [grunt, murmur, statement, question, - statement, + exclaim, statement] diff --git a/toontown/suit/SuitGlobals.py b/toontown/suit/SuitGlobals.py index e5043702..0af7b59d 100755 --- a/toontown/suit/SuitGlobals.py +++ b/toontown/suit/SuitGlobals.py @@ -19,7 +19,7 @@ suitProperties = {'f': (4.0 / cSize, SuitDNA.corpPolyColor, ['flunky', 'glasses' 'p': (3.35 / bSize, SuitDNA.corpPolyColor, ['pencilpusher'], '', 5.0), 'ym': (4.125 / aSize, SuitDNA.corpPolyColor, ['yesman'], '', 5.28), 'mm': (2.5 / cSize, SuitDNA.corpPolyColor, ['micromanager'], '', 3.25), - 'ds': (4.5 / bSize, SuitDNA.corpPolyColor, ['beancounter'], '', 6.08), + 'ds': (4.5 / bSize, VBase4(0.8, 0.7, 0.7, 1.0), ['downsizer', 'hatjp187187'], '', 6.08), 'hh': (6.5 / aSize, SuitDNA.corpPolyColor, ['headhunter'], '', 7.45), 'cr': (6.75 / cSize, VBase4(0.85, 0.55, 0.55, 1.0), ['flunky'], 'corporate-raider.jpg', 8.23), 'tbc': (7.0 / aSize, VBase4(0.75, 0.95, 0.75, 1.0), ['bigcheese'], '', 9.34), @@ -29,7 +29,7 @@ suitProperties = {'f': (4.0 / cSize, SuitDNA.corpPolyColor, ['flunky', 'glasses' 'dt': (4.25 / aSize, SuitDNA.legalPolyColor, ['twoface'], 'double-talker.jpg', 5.63), 'ac': (4.35 / bSize, SuitDNA.legalPolyColor, ['ambulancechaser'], '', 6.39), 'bs': (4.5 / aSize, SuitDNA.legalPolyColor, ['backstabber'], '', 6.71), - 'sd': (5.65 / bSize, VBase4(0.5, 0.8, 0.75, 1.0), ['telemarketer'], 'spin-doctor.jpg', 7.9), + 'sd': (5.65 / bSize, VBase4(0.8, 0.9, 0.7, 1.0), ['spindoctor', 'scopejp187187', 'bandjp187187'], '', 7.9), 'le': (7.125 / aSize, VBase4(0.25, 0.25, 0.5, 1.0), ['legaleagle'], '', 8.27), 'bw': (7.0 / aSize, SuitDNA.legalPolyColor, ['bigwig'], '', 8.69), # Cashbots diff --git a/toontown/toon/DistributedToon.py b/toontown/toon/DistributedToon.py index 3401332d..794a85fe 100755 --- a/toontown/toon/DistributedToon.py +++ b/toontown/toon/DistributedToon.py @@ -490,6 +490,9 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute def getNPCFriendsDict(self): return self.NPCFriendsDict + + def getNPCFriendCount(self, npcId): + return self.NPCFriendsDict.get(npcId, 0) def setNPCFriendsDict(self, NPCFriendsList): NPCFriendsDict = {} @@ -589,6 +592,9 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute def setTutorialAck(self, tutorialAck): self.tutorialAck = tutorialAck + + def getTutorialAck(self): + return self.tutorialAck def setEarnedExperience(self, earnedExp): self.earnedExperience = earnedExp @@ -1176,6 +1182,8 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute DistributedSmoothNode.DistributedSmoothNode.d_setParent(self, parentToken) def setEmoteAccess(self, bits): + if bits[26]: + bits.remove(bits[26]) self.emoteAccess = bits if self == base.localAvatar: messenger.send('emotesChanged') @@ -1250,6 +1258,9 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute def getTotalMoney(self): return self.getBankMoney() + self.getMoney() + + def takeMoney(self, money): + self.sendUpdate('takeMoney', [money]) def setEmblems(self, emblems): if self.emblems != emblems: @@ -2448,6 +2459,18 @@ def blackCat(): """ base.cr.blackCatMgr.requestBlackCatTransformation() +@magicWord(category=CATEGORY_COMMUNITY_MANAGER) +def toggleGM(): + invoker = spellbook.getInvoker() + if invoker.gmIcon: + invoker.setWantAdminTag(False) + invoker.removeGMIcon() + invoker.setNametagName()#setName(invoker.getName()) + else: + invoker.setWantAdminTag(True) + invoker.setGMIcon(invoker.getAdminAccess()) + invoker.setNametagName()#setName(invoker.getName()) + @magicWord(category=CATEGORY_COMMUNITY_MANAGER, types=[str]) def showParticle(name): """ diff --git a/toontown/toon/DistributedToonAI.py b/toontown/toon/DistributedToonAI.py index 0f52a725..2c3f9fef 100755 --- a/toontown/toon/DistributedToonAI.py +++ b/toontown/toon/DistributedToonAI.py @@ -1951,6 +1951,10 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo return anyChanged def b_setEmoteAccess(self, bits): + if bits[26]: + bits.remove(bits[26]) + if self.emoteAccess[26]: + self.emoteAccess.remove(self.emoteAccess[26]) self.setEmoteAccess(bits) self.d_setEmoteAccess(bits) @@ -1958,6 +1962,10 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo self.sendUpdate('setEmoteAccess', [bits]) def setEmoteAccess(self, bits): + if bits[26]: + bits.remove(bits[26]) + if self.emoteAccess[26]: + self.emoteAccess.remove(self.emoteAccess[26]) maxBitCount = len(self.emoteAccess) bits = bits[:maxBitCount] bitCount = len(bits) @@ -3126,6 +3134,24 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo self.zoneId)) return ['success', suitIndex, building.doId] + def doToonBuildingTakeover(self): + streetId = ZoneUtil.getBranchZone(self.zoneId) + if streetId not in self.air.suitPlanners: + self.notify.warning('Street %d is not known.' % streetId) + return ['badlocation', 'notknownstreet', 0] + sp = self.air.suitPlanners[streetId] + bm = sp.buildingMgr + building = self.findClosestSuitDoor() + if building == None: + return ['badlocation', 'nobuilding', 0] + if building.isToonBlock(): + return ['badlocation', 'toonblock', 0] + building.toonTakeOver() + self.notify.warning('toonTakeOverFromStreet %s %d' % (building.block, + self.zoneId)) + + return ['success', building.doId] + def doCogdoTakeOver(self, suitIndex): if suitIndex >= len(SuitDNA.suitHeadTypes): self.notify.warning('Bad suit index: %s' % suitIndex) @@ -3298,6 +3324,31 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo return None + def findClosestSuitDoor(self): + zoneId = self.zoneId + streetId = ZoneUtil.getBranchZone(zoneId) + sp = self.air.suitPlanners[streetId] + if not sp: + return None + bm = sp.buildingMgr + if not bm: + return None + zones = [zoneId, + zoneId - 1, + zoneId + 1, + zoneId - 2, + zoneId + 2] + for zone in zones: + for i in bm.getSuitBlocks(): + building = bm.getBuilding(i) + extZoneId, intZoneId = building.getExteriorAndInteriorZoneId() + if not NPCToons.isZoneProtected(intZoneId): + if hasattr(building, 'elevator'): + if building.elevator.zoneId == zone: + return building + + return None + def b_setGardenTrophies(self, trophyList): self.setGardenTrophies(trophyList) self.d_setGardenTrophies(trophyList) @@ -4213,20 +4264,20 @@ def cheesyEffect(value, hood=0, expire=0): return 'Invalid cheesy effect value: %d' % value if (hood != 0) and (not 1000 <= hood < ToontownGlobals.DynamicZonesBegin): return 'Invalid hood ID: %d' % hood - invoker = spellbook.getInvoker() - invoker.b_setCheesyEffect(value, hood, expire) - return 'Set your cheesy effect to: %d' % value + target = spellbook.getTarget() + target.b_setCheesyEffect(value, hood, expire) + return 'Set %s\'s cheesy effect to: %d' % (target.getName(), value) @magicWord(category=CATEGORY_PROGRAMMER, types=[int]) def hp(hp): """ - Modify the invoker's current HP. + Modify the target's current HP. """ - invoker = spellbook.getInvoker() - maxHp = invoker.getMaxHp() + target = spellbook.getTarget() + maxHp = target.getMaxHp() if not -1 <= hp <= maxHp: return 'HP must be in range (-1-%d).' % maxHp - invoker.b_setHp(hp) + target.b_setHp(hp) return 'Set your HP to: %d' % hp @magicWord(category=CATEGORY_PROGRAMMER, types=[int]) @@ -4253,24 +4304,24 @@ def textColor(color): @magicWord(category=CATEGORY_MODERATOR, types=[str]) def allSummons(): """ - Max the invoker's summons + Max the target's summons """ - invoker = spellbook.getInvoker() + target = spellbook.getTarget() numSuits = len(SuitDNA.suitHeadTypes) fullSetForSuit = 1 | 2 | 4 | 8 | 16 | 32 allSummons = numSuits * [fullSetForSuit] - invoker.b_setCogSummonsEarned(allSummons) + target.b_setCogSummonsEarned(allSummons) return 'Lots of summons!' @magicWord(category=CATEGORY_PROGRAMMER, types=[str]) def maxToon(missingTrack=None): """ - Max the invoker's stats for end-level gameplay. + Max the target's stats for end-level gameplay. """ - invoker = spellbook.getInvoker() + target = spellbook.getTarget() - # First, unlock the invoker's Gag tracks: + # First, unlock the target's Gag tracks: gagTracks = [1, 1, 1, 1, 1, 1, 1] if missingTrack is not None: try: @@ -4281,23 +4332,23 @@ def maxToon(missingTrack=None): if index in (4, 5): return 'You are required to have Throw and Squirt.' gagTracks[index] = 0 - invoker.b_setTrackAccess(gagTracks) - invoker.b_setMaxCarry(80) + target.b_setTrackAccess(gagTracks) + target.b_setMaxCarry(80) # Next, max out their experience for the tracks they have: - experience = Experience.Experience(invoker.getExperience(), invoker) - for i, track in enumerate(invoker.getTrackAccess()): + experience = Experience.Experience(target.getExperience(), target) + for i, track in enumerate(target.getTrackAccess()): if track: experience.experience[i] = ( Experience.MaxSkill - Experience.UberSkill) - invoker.b_setExperience(experience.makeNetString()) + target.b_setExperience(experience.makeNetString()) # Max out their Laff: - invoker.b_setMaxHp(ToontownGlobals.MaxHpLimit) - invoker.toonUp(invoker.getMaxHp() - invoker.hp) + target.b_setMaxHp(ToontownGlobals.MaxHpLimit) + target.toonUp(target.getMaxHp() - target.hp) # Unlock all of the emotes: - emotes = list(invoker.getEmoteAccess()) + emotes = list(target.getEmoteAccess()) for emoteId in OTPLocalizer.EmoteFuncDict.values(): if emoteId >= len(emotes): continue @@ -4306,10 +4357,10 @@ def maxToon(missingTrack=None): if emoteId in (17, 18, 19): continue emotes[emoteId] = 1 - invoker.b_setEmoteAccess(emotes) + target.b_setEmoteAccess(emotes) # Max out their Cog suits: - invoker.b_setCogParts( + target.b_setCogParts( [ CogDisguiseGlobals.PartsPerSuitBitmasks[0], # Bossbot CogDisguiseGlobals.PartsPerSuitBitmasks[1], # Lawbot @@ -4317,58 +4368,58 @@ def maxToon(missingTrack=None): CogDisguiseGlobals.PartsPerSuitBitmasks[3] # Sellbot ] ) - invoker.b_setCogLevels([49] * 4) - invoker.b_setCogTypes([7, 7, 7, 7]) + target.b_setCogLevels([49] * 4) + target.b_setCogTypes([7, 7, 7, 7]) # Max their Cog gallery: deptCount = len(SuitDNA.suitDepts) - invoker.b_setCogCount(list(CogPageGlobals.COG_QUOTAS[1]) * deptCount) + target.b_setCogCount(list(CogPageGlobals.COG_QUOTAS[1]) * deptCount) cogStatus = [CogPageGlobals.COG_COMPLETE2] * SuitDNA.suitsPerDept - invoker.b_setCogStatus(cogStatus * deptCount) - invoker.b_setCogRadar([1, 1, 1, 1]) - invoker.b_setBuildingRadar([1, 1, 1, 1]) + target.b_setCogStatus(cogStatus * deptCount) + target.b_setCogRadar([1, 1, 1, 1]) + target.b_setBuildingRadar([1, 1, 1, 1]) # Max out their racing tickets: - invoker.b_setTickets(99999) + target.b_setTickets(99999) # Give them teleport access everywhere (including Cog HQs): hoods = list(ToontownGlobals.HoodsForTeleportAll) - invoker.b_setHoodsVisited(hoods) - invoker.b_setTeleportAccess(hoods) + target.b_setHoodsVisited(hoods) + target.b_setTeleportAccess(hoods) # Max their quest carry limit: - invoker.b_setQuestCarryLimit(4) + target.b_setQuestCarryLimit(4) # Complete their quests: - invoker.b_setQuests([]) - invoker.b_setRewardHistory(Quests.ELDER_TIER, []) + target.b_setQuests([]) + target.b_setRewardHistory(Quests.ELDER_TIER, []) # Max their money: - invoker.b_setMaxMoney(250) - invoker.b_setMaxBankMoney(30000) - invoker.b_setMoney(invoker.getMaxMoney()) - invoker.b_setBankMoney(invoker.getMaxBankMoney()) + target.b_setMaxMoney(250) + target.b_setMaxBankMoney(30000) + target.b_setMoney(target.getMaxMoney()) + target.b_setBankMoney(target.getMaxBankMoney()) # Finally, unlock all of their pet phrases: if simbase.wantPets: - invoker.b_setPetTrickPhrases(range(7)) + target.b_setPetTrickPhrases(range(7)) return 'Maxed your Toon!' @magicWord(category=CATEGORY_PROGRAMMER) def unlocks(): """ - Unlocks the invoker's teleport access, emotions, and pet trick phrases. + Unlocks the target's teleport access, emotions, and pet trick phrases. """ - invoker = spellbook.getInvoker() + target = spellbook.getTarget() # First, unlock their teleport access: hoods = list(ToontownGlobals.HoodsForTeleportAll) - invoker.b_setHoodsVisited(hoods) - invoker.b_setTeleportAccess(hoods) + target.b_setHoodsVisited(hoods) + target.b_setTeleportAccess(hoods) # Next, unlock all of their emotions: - emotes = list(invoker.getEmoteAccess()) + emotes = list(target.getEmoteAccess()) for emoteId in OTPLocalizer.EmoteFuncDict.values(): if emoteId >= len(emotes): continue @@ -4377,20 +4428,20 @@ def unlocks(): if emoteId in (17, 18, 19): continue emotes[emoteId] = 1 - invoker.b_setEmoteAccess(emotes) + target.b_setEmoteAccess(emotes) # Finally, unlock all of their pet phrases: if simbase.wantPets: - invoker.b_setPetTrickPhrases(range(7)) + target.b_setPetTrickPhrases(range(7)) return 'Unlocked teleport access, emotions, and pet trick phrases!' @magicWord(category=CATEGORY_PROGRAMMER, types=[int, str]) def sos(count, name): """ - Modifies the invoker's specified SOS card count. + Modifies the target's specified SOS card count. """ - invoker = spellbook.getInvoker() + target = spellbook.getTarget() if not 0 <= count <= 100: return 'Your SOS count must be in range (0-100).' for npcId, npcName in TTLocalizer.NPCToonNames.items(): @@ -4400,43 +4451,43 @@ def sos(count, name): break else: return 'SOS card %s was not found!' % name - if (count == 0) and (npcId in invoker.NPCFriendsDict): - del invoker.NPCFriendsDict[npcId] + if (count == 0) and (npcId in target.NPCFriendsDict): + del target.NPCFriendsDict[npcId] else: - invoker.NPCFriendsDict[npcId] = count - invoker.d_setNPCFriendsDict(invoker.NPCFriendsDict) - return "You were given %d %s SOS cards." % (count, name) + target.NPCFriendsDict[npcId] = count + target.d_setNPCFriendsDict(target.NPCFriendsDict) + return "%s was given %d %s SOS cards." % (target.getName(), count, name) @magicWord(category=CATEGORY_PROGRAMMER, types=[int]) def unites(value=32767): """ Restock all resistance messages. """ - invoker = spellbook.getInvoker() + target = spellbook.getTarget() value = min(value, 32767) - invoker.restockAllResistanceMessages(value) - return 'Restocked %d unites!' % value + target.restockAllResistanceMessages(value) + return 'Restocked %d unites for %s!' % (value, target.getName()) @magicWord(category=CATEGORY_PROGRAMMER, types=[int]) def fires(count): """ - Modifies the invoker's pink slip count. + Modifies the target's pink slip count. """ - invoker = spellbook.getInvoker() + target = spellbook.getTarget() if not 0 <= count <= 255: return 'Your fire count must be in range (0-255).' - invoker.b_setPinkSlips(count) - return 'You were given %d fires.' % count + target.b_setPinkSlips(count) + return '%s was given %d fires.' % (target.getName(), count) @magicWord(category=CATEGORY_PROGRAMMER, types=[int]) def crateKeys(count): """ Modifies the invoker's crate key count. """ - invoker = spellbook.getInvoker() + target = spellbook.getTarget() if not 0 <= count <= 255: return 'Your crate key must be in range (0-255).' - invoker.b_setCrateKeys(count) + target.b_setCrateKeys(count) return 'You were given %d crate keys.' % count @magicWord(category=CATEGORY_PROGRAMMER, types=[int]) @@ -4534,66 +4585,54 @@ def squish(laff): @magicWord(category=CATEGORY_CREATIVE, types=[int, int]) def hat(hatIndex, hatTex=0): """ - Modify the invoker's hat. + Modify the target's hat. """ if not 0 <= hatIndex < len(ToonDNA.HatModels): return 'Invalid hat index.' if not 0 <= hatTex < len(ToonDNA.HatTextures): return 'Invalid hat texture.' - invoker = spellbook.getInvoker() target = spellbook.getTarget() - if target != invoker: - target.b_setHat(hatIndex, hatTex, 0) - return "Set %s's hat to %d, %d!" % (target.getName(), hatIndex, hatTex) - invoker.b_setHat(hatIndex, hatTex, 0) - return "Set %s's hat to %d, %d!" % (invoker.getName(), hatIndex, hatTex) + target.b_setHat(hatIndex, hatTex, 0) + return "Set %s's hat to %d, %d!" % (target.getName(), hatIndex, hatTex) @magicWord(category=CATEGORY_CREATIVE, types=[int, int]) def glasses(glassesIndex, glassesTex=0): """ - Modify the invoker's glasses. + Modify the target's glasses. """ if not 0 <= glassesIndex < len(ToonDNA.GlassesModels): return 'Invalid glasses index.' if not 0 <= glassesTex < len(ToonDNA.GlassesTextures): return 'Invalid glasses texture.' - invoker = spellbook.getInvoker() target = spellbook.getTarget() - if target != invoker: - target.b_setGlasses(glassesIndex, glassesTex, 0) - return "Set %s's glasses to %d, %d!" % (target.getName(), glassesIndex, glassesTex) - invoker.b_setGlasses(glassesIndex, glassesTex, 0) - return "Set %s's glasses to %d, %d!" % (invoker.getName(), glassesIndex, glassesTex) + target.b_setGlasses(glassesIndex, glassesTex, 0) + return "Set %s's glasses to %d, %d!" % (target.getName(), glassesIndex, glassesTex) @magicWord(category=CATEGORY_CREATIVE, types=[int, int]) def backpack(backpackIndex, backpackTex=0): """ - Modify the invoker's backpack. + Modify the target's backpack. """ if not 0 <= backpackIndex < len(ToonDNA.BackpackModels): return 'Invalid backpack index.' if not 0 <= backpackTex < len(ToonDNA.BackpackTextures): return 'Invalid backpack texture.' - invoker = spellbook.getInvoker() - invoker.b_setBackpack(backpackIndex, backpackTex, 0) - return "Set %s's backpack to %d, %d!" % (invoker.getName(), backpackIndex, backpackTex) + target = spellbook.getTarget() + target.b_setBackpack(backpackIndex, backpackTex, 0) + return "Set %s's backpack to %d, %d!" % (target.getName(), backpackIndex, backpackTex) @magicWord(category=CATEGORY_CREATIVE, types=[int, int]) def shoes(shoesIndex, shoesTex=0): """ - Modify the invoker's shoes. + Modify the target's shoes. """ if not 0 <= shoesIndex < len(ToonDNA.ShoesModels): return 'Invalid shoes index.' if not 0 <= shoesTex < len(ToonDNA.ShoesTextures): return 'Invalid shoes texture.' - invoker = spellbook.getInvoker() target = spellbook.getTarget() - if target != invoker: - target.b_setShoes(shoesIndex, shoesTex, 0) - return "Set %s's shoes to %d, %d!" % (target.getName(), shoesIndex, shoesTex) - invoker.b_setShoes(shoesIndex, shoesTex, 0) - return "Set %s's shoes to %d, %d!" % (invoker.getName(), shoesIndex, shoesTex) + target.b_setShoes(shoesIndex, shoesTex, 0) + return "Set %s's shoes to %d, %d!" % (target.getName(), shoesIndex, shoesTex) @magicWord(category=CATEGORY_COMMUNITY_MANAGER) def ghost(): @@ -4646,8 +4685,8 @@ def cogIndex(index): @magicWord(category=CATEGORY_PROGRAMMER, types=[str, int, int]) def inventory(a, b=None, c=None): - invoker = spellbook.getInvoker() - inventory = invoker.inventory + target = spellbook.getTarget() + inventory = target.inventory if a == 'reset': maxLevelIndex = b or 5 if not 0 <= maxLevelIndex < len(ToontownBattleGlobals.Levels[0]): @@ -4658,7 +4697,7 @@ def inventory(a, b=None, c=None): for track in xrange(0, len(ToontownBattleGlobals.Tracks)): if (targetTrack == -1) or (track == targetTrack): inventory.inventory[track][:maxLevelIndex + 1] = [0] * (maxLevelIndex+1) - invoker.b_setInventory(inventory.makeNetString()) + target.b_setInventory(inventory.makeNetString()) if targetTrack == -1: return 'Inventory reset.' else: @@ -4670,10 +4709,10 @@ def inventory(a, b=None, c=None): targetTrack = -1 or c if not -1 <= targetTrack < len(ToontownBattleGlobals.Tracks): return 'Invalid target track index: ' + str(targetTrack) - if (targetTrack != -1) and (not invoker.hasTrackAccess(targetTrack)): + if (targetTrack != -1) and (not target.hasTrackAccess(targetTrack)): return "You don't have target track index: " + str(targetTrack) inventory.NPCMaxOutInv(targetTrack=targetTrack, maxLevelIndex=maxLevelIndex) - invoker.b_setInventory(inventory.makeNetString()) + target.b_setInventory(inventory.makeNetString()) if targetTrack == -1: return 'Inventory restocked.' else: @@ -4683,23 +4722,23 @@ def inventory(a, b=None, c=None): targetTrack = int(a) except: return 'Invalid first argument.' - if not invoker.hasTrackAccess(targetTrack): + if not target.hasTrackAccess(targetTrack): return "You don't have target track index: " + str(targetTrack) maxLevelIndex = b or 6 if not 0 <= maxLevelIndex < len(ToontownBattleGlobals.Levels[0]): return 'Invalid max level index: ' + str(maxLevelIndex) for _ in xrange(c): inventory.addItem(targetTrack, maxLevelIndex) - invoker.b_setInventory(inventory.makeNetString()) + target.b_setInventory(inventory.makeNetString()) return 'Restored %d Gags to: %d, %d' % (c, targetTrack, maxLevelIndex) @magicWord(category=CATEGORY_CREATIVE, types=[str, str]) def dna(part, value): - """Modify a DNA part on the invoker.""" - invoker = spellbook.getInvoker() + """Modify a DNA part on the target.""" + target = spellbook.getTarget() dna = ToonDNA.ToonDNA() - dna.makeFromNetString(invoker.getDNAString()) + dna.makeFromNetString(target.getDNAString()) part = part.lower() if part.endswith('color') or part.endswith('tex') or part.endswith('size'): @@ -4709,7 +4748,7 @@ def dna(part, value): if value not in ('m', 'f', 'male', 'female'): return 'Invalid gender: ' + value dna.gender = value[0] - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Gender set to: ' + dna.gender if part in ('head', 'species'): @@ -4723,7 +4762,7 @@ def dna(part, value): if value not in ToonDNA.toonSpeciesTypes: return 'Invalid species: ' + value dna.head = value + dna.head[1:3] - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Species set to: ' + dna.head[0] if part == 'headsize': @@ -4731,7 +4770,7 @@ def dna(part, value): if not 0 <= value <= len(sizes): return 'Invalid head size index: ' + str(value) dna.head = dna.head[0] + sizes[value] - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Head size index set to: ' + dna.head[1:] if part == 'torso': @@ -4743,7 +4782,7 @@ def dna(part, value): if (dna.gender == 'f') and (not 3 <= value <= 8): return 'Female torso index out of range (3-8).' dna.torso = ToonDNA.toonTorsoTypes[value] - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Torso set to: ' + dna.torso if part == 'legs': @@ -4751,28 +4790,28 @@ def dna(part, value): if not 0 <= value <= len(ToonDNA.toonLegTypes): return 'Legs index out of range (0-%d).' % len(ToonDNA.toonLegTypes) dna.legs = ToonDNA.toonLegTypes[value] - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Legs set to: ' + dna.legs if part == 'headcolor': if value not in ToonDNA.defaultColorList: return 'Invalid head color index: ' + str(value) dna.headColor = value - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Head color index set to: ' + str(dna.headColor) if part == 'armcolor': if value not in ToonDNA.defaultColorList: return 'Invalid arm color index: ' + str(value) dna.armColor = value - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Arm color index set to: ' + str(dna.armColor) if part == 'legcolor': if value not in ToonDNA.defaultColorList: return 'Invalid leg color index: ' + str(value) dna.legColor = value - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Leg color index set to: ' + str(dna.legColor) if part == 'color': @@ -4785,41 +4824,41 @@ def dna(part, value): dna.headColor = value dna.armColor = value dna.legColor = value - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Color index set to: ' + str(dna.headColor) if part == 'gloves': value = int(value) dna.gloveColor = value - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Glove color set to: ' + str(dna.gloveColor) if part == 'toptex': if not 0 <= value <= len(ToonDNA.Shirts): return 'Top texture index out of range (0-%d).' % len(ToonDNA.Shirts) dna.topTex = value - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Top texture index set to: ' + str(dna.topTex) if part == 'toptexcolor': if not 0 <= value <= len(ToonDNA.ClothesColors): return 'Top texture color index out of range(0-%d).' % len(ToonDNA.ClothesColors) dna.topTexColor = value - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Top texture color index set to: ' + str(dna.topTexColor) if part == 'sleevetex': if not 0 <= value <= len(ToonDNA.Sleeves): return 'Sleeve texture index out of range(0-%d).' % len(ToonDNA.Sleeves) dna.sleeveTex = value - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Sleeve texture index set to: ' + str(dna.sleeveTex) if part == 'sleevetexcolor': if not 0 <= value <= len(ToonDNA.ClothesColors): return 'Sleeve texture color index out of range(0-%d).' % len(ToonDNA.ClothesColors) dna.sleeveTexColor = value - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Sleeve texture color index set to: ' + str(dna.sleeveTexColor) if part == 'bottex': @@ -4832,14 +4871,14 @@ def dna(part, value): if not 0 <= value <= len(bottoms): return 'Bottom texture index out of range (0-%d).' % len(bottoms) dna.botTex = value - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Bottom texture index set to: ' + str(dna.botTex) if part == 'bottexcolor': if not 0 <= value <= len(ToonDNA.ClothesColors): return 'Bottom texture color index out of range(0-%d).' % len(ToonDNA.ClothesColors) dna.botTexColor = value - invoker.b_setDNAString(dna.makeNetString()) + target.b_setDNAString(dna.makeNetString()) return 'Bottom texture color index set to: ' + str(dna.botTexColor) if part == 'show': @@ -4926,7 +4965,7 @@ def track(command, track, value=None): return 'Invalid command.' @magicWord(category=CATEGORY_ADMINISTRATOR, types=[str, str]) -def suit(command, suitName): +def suit(command, suitName = 'f'): invoker = spellbook.getInvoker() command = command.lower() if suitName not in SuitDNA.suitHeadTypes: @@ -4942,6 +4981,11 @@ def suit(command, suitName): if returnCode[0] == 'success': return 'Successfully spawned a Cog building with: ' + suitFullName return "Couldn't spawn a Cog building with: " + suitFullName + elif command == 'nobuilding': + returnCode = invoker.doToonBuildingTakeover() + if returnCode[0] == 'success': + return 'Toons took over the cog building!' + return "Couldn't allow toons to take over cog building because " + returnCode[1] else: return 'Invalid command.' @@ -4996,6 +5040,18 @@ def unlimitedGags(): av.setUnlimitedGags(not av.unlimitedGags) return 'Toggled unlimited gags %s for %s' % ('ON' if av.unlimitedGags else 'OFF', av.getName()) +@magicWord(category=CATEGORY_PROGRAMMER) +def maxCogPage(): + """ Max the target's discovered cogs. """ + target = spellbook.getTarget() + deptCount = len(SuitDNA.suitDepts) + target.b_setCogCount(list(CogPageGlobals.COG_QUOTAS[1]) * deptCount) + cogStatus = [CogPageGlobals.COG_COMPLETE2] * SuitDNA.suitsPerDept + target.b_setCogStatus(cogStatus * deptCount) + target.b_setCogRadar([1, 1, 1, 1]) + target.b_setBuildingRadar([1, 1, 1, 1]) + return 'Maxed %s\'s discovered cogs!' % (target.getName()) + @magicWord(category=CATEGORY_PROGRAMMER) def immortal(): """ Make target (if 500+) or self (if 499-) immortal. """ @@ -5013,7 +5069,7 @@ def summoncogdo(track="s", difficulty=5): av = spellbook.getInvoker() building = av.findClosestDoor() if building == None: - return "No bldg found!" + return "No Toon building found!" building.cogdoTakeOver(difficulty, 2, track) return 'Successfully spawned cogdo with track %s and difficulty %d' % (track, difficulty) diff --git a/toontown/toon/InventoryNew.py b/toontown/toon/InventoryNew.py index 5e2585a8..2cdf5d26 100755 --- a/toontown/toon/InventoryNew.py +++ b/toontown/toon/InventoryNew.py @@ -7,6 +7,7 @@ from toontown.quest import BlinkingArrows from direct.interval.IntervalGlobal import * from direct.directnotify import DirectNotifyGlobal from toontown.toonbase import ToontownGlobals +from toontown.toontowngui import TTDialog from otp.otpbase import OTPGlobals class InventoryNew(InventoryBase.InventoryBase, DirectFrame): @@ -159,6 +160,8 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): del self.detailAmountLabel del self.detailDataLabel del self.totalLabel + self.cleanupDialog() + for row in self.trackRows: row.destroy() @@ -172,7 +175,11 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): del self.buttons InventoryBase.InventoryBase.unload(self) DirectFrame.destroy(self) - return + + def cleanupDialog(self): + if self.dialog: + self.dialog.cleanup() + self.dialog = None def load(self): self.notify.debug('Loading Inventory for %d' % self.toon.doId) @@ -200,7 +207,7 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): trashcanGui = loader.loadModel('phase_3/models/gui/trashcan_gui') trashcanImage = (trashcanGui.find('**/TrashCan_CLSD'), trashcanGui.find('**/TrashCan_OPEN'), trashcanGui.find('**/TrashCan_RLVR')) self.deleteEnterButton = DirectButton(parent=self.invFrame, image=trashcanImage, text=('', TTLocalizer.InventoryDelete, TTLocalizer.InventoryDelete), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), text_scale=0.1, text_pos=(0, -0.1), text_font=getInterfaceFont(), textMayChange=0, relief=None, pos=(-1, 0, -0.35), scale=1.0) - self.deleteAllButton = DirectButton(parent=self.invFrame, image=trashcanImage, text=('', TTLocalizer.InventoryDeleteAll, TTLocalizer.InventoryDeleteAll), text_fg=(1, 0, 0, 1), text_shadow=(1, 1, 1, 1), text_scale=0.1, text_pos=(0, -0.1), text_font=getInterfaceFont(), textMayChange=0, relief=None, pos=(-0.3, 0, -0.91), scale=0.75, command=self.__zeroInvAndUpdate) + self.deleteAllButton = DirectButton(parent=self.invFrame, image=trashcanImage, text=('', TTLocalizer.InventoryDeleteAll, TTLocalizer.InventoryDeleteAll), text_fg=(1, 0, 0, 1), text_shadow=(1, 1, 1, 1), text_scale=0.1, text_pos=(0, -0.1), text_font=getInterfaceFont(), textMayChange=0, relief=None, pos=(-0.3, 0, -0.91), scale=0.75, command=self.__zeroInvConfirm) self.deleteExitButton = DirectButton(parent=self.invFrame, image=(trashcanGui.find('**/TrashCan_OPEN'), trashcanGui.find('**/TrashCan_CLSD'), trashcanGui.find('**/TrashCan_RLVR')), text=('', TTLocalizer.InventoryDone, TTLocalizer.InventoryDone), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), text_scale=0.1, text_pos=(0, -0.1), text_font=getInterfaceFont(), textMayChange=0, relief=None, pos=(-1, 0, -0.35), scale=1.0) trashcanGui.removeNode() self.deleteHelpText = DirectLabel(parent=self.invFrame, relief=None, pos=(0.272, 0.3, -0.907), text=TTLocalizer.InventoryDeleteHelp, text_fg=(0, 0, 0, 1), text_scale=0.08, textMayChange=0) @@ -212,6 +219,7 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.detailCreditLabel = DirectLabel(parent=self.detailFrame, text=TTLocalizer.InventorySkillCreditNone, text_fg=(0.05, 0.14, 0.4, 1), scale=0.04, pos=(-0.22, 0, -0.365), text_font=getInterfaceFont(), text_align=TextNode.ALeft, relief=None) self.detailCreditLabel.hide() self.totalLabel = DirectLabel(text='', parent=self.detailFrame, pos=(0, 0, -0.095), scale=0.05, text_fg=(0.05, 0.14, 0.4, 1), text_font=getInterfaceFont(), relief=None) + self.dialog = None self.updateTotalPropsText() self.trackRows = [] self.trackNameLabels = [] @@ -277,9 +285,17 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): def __handleBackToPlayground(self): messenger.send('inventory-back-to-playground') - def __zeroInvAndUpdate(self): - self.zeroInv() - self.updateGUI() + def __zeroInvConfirm(self): + self.cleanupDialog() + self.dialog = TTDialog.TTDialog(style=TTDialog.YesNo, text=TTLocalizer.InventoryDeleteConfirm, command=self.__zeroInvAndUpdate) + self.dialog.show() + + def __zeroInvAndUpdate(self, value): + self.cleanupDialog() + + if value > 0: + self.zeroInv() + self.updateGUI() def showDetail(self, track, level, event = None): self.totalLabel.hide() @@ -391,6 +407,7 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.enableUberGags() def deactivateButtons(self): + self.cleanupDialog() if self.previousActivateMode == 'purchaseDelete': self.purchaseDeleteDeactivateButtons() elif self.previousActivateMode == 'purchase': @@ -411,6 +428,7 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.plantTreeDeactivateButtons() def __activateButtons(self): + self.cleanupDialog() if hasattr(self, 'activateMode'): if self.activateMode == 'book': self.bookActivateButtons() diff --git a/toontown/toon/LocalToon.py b/toontown/toon/LocalToon.py index 6a54f2fe..7e80bb59 100755 --- a/toontown/toon/LocalToon.py +++ b/toontown/toon/LocalToon.py @@ -150,6 +150,7 @@ class LocalToon(DistributedToon.DistributedToon, LocalAvatar.LocalAvatar): self.createSystemMsgAckGui() self.acceptingNewFriends = True self.acceptingNonFriendWhispers = True + self.acceptingTeleport = True self.physControls.event.addAgainPattern('again%in') self.oldPos = None self.questMap = None @@ -214,14 +215,19 @@ class LocalToon(DistributedToon.DistributedToon, LocalAvatar.LocalAvatar): acceptingNewFriends = settings.get('acceptingNewFriends', {}) acceptingNonFriendWhispers = settings.get('acceptingNonFriendWhispers', {}) + acceptingTeleport = settings.get('acceptingTeleport', {}) if str(self.doId) not in acceptingNewFriends: acceptingNewFriends[str(self.doId)] = True settings['acceptingNewFriends'] = acceptingNewFriends if str(self.doId) not in acceptingNonFriendWhispers: acceptingNonFriendWhispers[str(self.doId)] = True settings['acceptingNonFriendWhispers'] = acceptingNonFriendWhispers + if str(self.doId) not in acceptingTeleport: + acceptingTeleport[str(self.doId)] = True + settings['acceptingTeleport'] = acceptingTeleport self.acceptingNewFriends = acceptingNewFriends[str(self.doId)] self.acceptingNonFriendWhispers = acceptingNonFriendWhispers[str(self.doId)] + self.acceptingTeleport = acceptingTeleport[str(self.doId)] def disable(self): self.laffMeter.destroy() @@ -422,9 +428,6 @@ class LocalToon(DistributedToon.DistributedToon, LocalAvatar.LocalAvatar): def isLocal(self): return 1 - def canChat(self): - return 1 - def startChat(self): if self.tutorialAck: self.notify.info('calling LocalAvatar.startchat') @@ -932,8 +935,8 @@ class LocalToon(DistributedToon.DistributedToon, LocalAvatar.LocalAvatar): self.friendsListButtonObscured += increment self.refreshOnscreenButtons() - def obscureMoveFurnitureButton(self, increment): - self.moveFurnitureButtonObscured += increment + def obscureMoveFurnitureButton(self, obscured): + self.moveFurnitureButtonObscured = obscured self.refreshOnscreenButtons() def obscureClarabelleButton(self, increment): @@ -968,7 +971,10 @@ class LocalToon(DistributedToon.DistributedToon, LocalAvatar.LocalAvatar): self.__catalogNotifyDialog = None else: self.newCatalogNotify() - if self.moveFurnitureButtonObscured <= 0: + if self.moveFurnitureButtonObscured: + if self.__furnitureGui: + self.__furnitureGui.hide() + else: if self.furnitureManager != None and self.furnitureDirector == self.doId: self.loadFurnitureGui() self.__furnitureGui.setPos(0.155, -0.6, -1.045) diff --git a/toontown/toon/NPCToons.py b/toontown/toon/NPCToons.py index db772e0d..5932afd9 100755 --- a/toontown/toon/NPCToons.py +++ b/toontown/toon/NPCToons.py @@ -864,7 +864,8 @@ NPCToonDict = { 11001: (11000, lnames[11001], 'r', 'm', 0, NPC_LAFF_RESTOCK), 12001: (12000, lnames[12001], 'r', 'm', 0, NPC_LAFF_RESTOCK), 12002: (-1, lnames[12002], ('pls', 'ls', 'l', 'f', 3, 0, 3, 3, 111, 27, 97, 27, 45, 27), 'f', 0, NPC_REGULAR), - 13001: (13000, lnames[13001], 'r', 'f', 0, NPC_LAFF_RESTOCK) + 13001: (13000, lnames[13001], 'r', 'f', 0, NPC_LAFF_RESTOCK), + 13002: (-1, lnames[13002], ('bss', 'ss', 'm', 'm', 19, 0, 19, 19, 0, 3, 0, 3, 1, 16), 'm', 0, NPC_REGULAR) } if config.GetBool('want-new-toonhall', 1): diff --git a/toontown/toon/TTEmote.py b/toontown/toon/TTEmote.py index 666b7d40..c0770046 100755 --- a/toontown/toon/TTEmote.py +++ b/toontown/toon/TTEmote.py @@ -316,18 +316,6 @@ def doLaugh(toon, volume = 1): exitTrack = Sequence(Func(toon.hideLaughMuzzle), Func(toon.blinkEyes), Func(stopAnim)) return (track, 2, exitTrack) - -def doTaunt(toon, volume=1): - duration = toon.getDuration('angry', 'torso') - sfx = base.loadSfx('phase_4/audio/sfx/avatar_emotion_taunt.ogg') - track = Sequence( - Func(toon.blinkEyes), - Func(toon.play, 'taunt'), - Func(base.playSfx, sfx, volume=volume, node=toon) - ) - duration = toon.getDuration('taunt') - return (track, duration, None) - def doRage(toon, volume=1): sfx = base.loadSfx('phase_4/audio/sfx/furious_03.ogg') track = Sequence( @@ -372,7 +360,6 @@ EmoteFunc = [[doWave, 0], [doDelighted, 0], [doFurious, 0], [doLaugh, 0], - [doTaunt, 0], [doRage, 0]] class TTEmote(Emote.Emote): @@ -401,8 +388,7 @@ class TTEmote(Emote.Emote): 22, 23, 24, - 25, - 26] + 25] self.headEmotes = [2, 17, 18, diff --git a/toontown/toon/Toon.py b/toontown/toon/Toon.py index 9778f10d..dd547c97 100755 --- a/toontown/toon/Toon.py +++ b/toontown/toon/Toon.py @@ -124,8 +124,7 @@ Phase4AnimList = (('sit', 'sit'), ('scientistJealous', 'scientistJealous'), ('scientistEmcee', 'scientistEmcee'), ('scientistWork', 'scientistWork'), - ('scientistGame', 'scientistGame'), - ('taunt', 'taunt')) + ('scientistGame', 'scientistGame')) Phase5AnimList = (('water-gun', 'water-gun'), ('hold-bottle', 'hold-bottle'), ('firehose', 'firehose'), diff --git a/toontown/toon/ToonAvatarDetailPanel.py b/toontown/toon/ToonAvatarDetailPanel.py index 5e28dff0..e60517d1 100755 --- a/toontown/toon/ToonAvatarDetailPanel.py +++ b/toontown/toon/ToonAvatarDetailPanel.py @@ -1,6 +1,7 @@ from panda3d.core import * from toontown.toonbase.ToontownGlobals import * from direct.gui.DirectGui import * +from direct.interval.IntervalGlobal import * from direct.showbase import DirectObject from direct.fsm import ClassicFSM, State from direct.fsm import State @@ -8,10 +9,10 @@ from direct.directnotify import DirectNotifyGlobal import DistributedToon from toontown.friends import FriendInviter import ToonTeleportPanel -from toontown.toonbase import TTLocalizer +from toontown.toonbase import TTLocalizer, ToontownGlobals from toontown.hood import ZoneUtil from toontown.toonbase.ToontownBattleGlobals import Tracks, Levels, getAvPropDamage -from toontown.toon import Toon +import Toon, NPCFriendPanel globalAvatarDetail = None def showAvatarDetail(avId, avName): @@ -44,6 +45,7 @@ class ToonAvatarDetailPanel(DirectFrame): def __init__(self, avId, avName, parent = base.a2dTopRight, **kw): buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui') gui = loader.loadModel('phase_3.5/models/gui/avatar_panel_gui') + sosGui = loader.loadModel('phase_3.5/models/gui/playingCard') detailPanel = gui.find('**/avatarInfoPanel') textScale = 0.095 textWrap = 16.4 @@ -72,11 +74,20 @@ class ToonAvatarDetailPanel(DirectFrame): FriendInviter.hideFriendInviter() self.bCancel = DirectButton(self, image=(buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr')), image_scale=1.1, relief=None, text=TTLocalizer.AvatarDetailPanelCancel, text_scale=TTLocalizer.TADPbCancel, text_pos=(0.12, -0.01), pos=TTLocalizer.TADPbCancelPos, scale=2.0, command=self.__handleCancel) self.bCancel.hide() + self.sosButton = DirectButton(self, relief=None, image=sosGui.find('**/card_back'), scale=0.05, pos=(0.3, 0, -0.76), text=('', TTLocalizer.DetailPanelSOS, TTLocalizer.DetailPanelSOS, ''), text_fg=(1, 1, 0.5, 1), text_shadow=(0, 0, 0, 1), text_scale=2, text_pos=(0, -3.4), text_align=TextNode.ACenter, state=DGG.NORMAL, command=self.__toggleSOSGui) + self.sosButton.hide() + self.sosFrame = DirectFrame(self, relief=None, image=DGG.getDefaultDialogGeom(), image_scale=(2.6, 1, 1.87), image_color=ToontownGlobals.GlobalDialogColor, pos=(0.2, 0, 0.8)) + self.sosFrame.setBin('background', 10) + self.sosFrame.setScale(0.5) + self.sosPage = NPCFriendPanel.NPCFriendPanel(parent=self.sosFrame, callable=False) + self.sosPage.setScale(0.18) + self.sosPage.setPos(0, 0, 0.05) self.initialiseoptions(ToonAvatarDetailPanel) self.fsm.enterInitialState() self.fsm.request('begin') buttons.removeNode() gui.removeNode() + sosGui.removeNode() def cleanup(self): if self.fsm: @@ -87,7 +98,6 @@ class ToonAvatarDetailPanel(DirectFrame): self.avatar.delete() self.createdAvatar = None self.destroy() - return def enterOff(self): pass @@ -110,6 +120,7 @@ class ToonAvatarDetailPanel(DirectFrame): def enterQuery(self): self.dataText['text'] = TTLocalizer.AvatarDetailPanelLookup % self.avName + self.sosButton.hide() self.bCancel.show() self.avatar = base.cr.doId2do.get(self.avId) if self.avatar != None and not self.avatar.ghostMode: @@ -165,10 +176,12 @@ class ToonAvatarDetailPanel(DirectFrame): else: text = TTLocalizer.AvatarDetailPanelOffline % {'identifier': identifier} self.dataText['text'] = text + self.sosButton.show() self.__addToonModel() self.__updateTrackInfo() self.__updateTrophyInfo() self.__updateLaffInfo() + self.__updateSOSPage() def __addToonModel(self): toon = Toon.Toon() @@ -191,13 +204,14 @@ class ToonAvatarDetailPanel(DirectFrame): yOffset = 0.1 ySpacing = -0.115 inventory = self.avatar.inventory + self.inventoryFrame = DirectFrame(parent=self, relief=None) inventoryModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') - rolloverFrame = DirectFrame(parent=self, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=(0, 0.5, 1, 1), geom_scale=(0.5, 0.3, 0.2), text_scale=0.05, text_pos=(0, 0.0125), text='', text_fg=(1, 1, 1, 1)) + rolloverFrame = DirectFrame(parent=self.inventoryFrame, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=(0, 0.5, 1, 1), geom_scale=(0.5, 0.3, 0.2), text_scale=0.05, text_pos=(0, 0.0125), text='', text_fg=(1, 1, 1, 1)) rolloverFrame.setBin('gui-popup', 0) rolloverFrame.hide() buttonModel = inventoryModels.find('**/InventoryButtonUp') for track in xrange(0, len(Tracks)): - DirectLabel(parent=self, relief=None, text=TextEncoder.upper(TTLocalizer.BattleGlobalTracks[track]), text_scale=TTLocalizer.TADPtrackLabel, text_align=TextNode.ALeft, pos=(-0.9, 0, TTLocalizer.TADtrackLabelPosZ + track * ySpacing)) + DirectLabel(parent=self.inventoryFrame, relief=None, text=TextEncoder.upper(TTLocalizer.BattleGlobalTracks[track]), text_scale=TTLocalizer.TADPtrackLabel, text_align=TextNode.ALeft, pos=(-0.9, 0, TTLocalizer.TADtrackLabelPosZ + track * ySpacing)) if self.avatar.hasTrackAccess(track): curExp, nextExp = inventory.getCurAndNextExpValues(track) for item in xrange(0, len(Levels[track])): @@ -215,7 +229,7 @@ class ToonAvatarDetailPanel(DirectFrame): image_color = Vec4(0, 0.6, 1, 1) geom_color = None pos = (xOffset + item * xSpacing, 0, yOffset + track * ySpacing) - label = DirectLabel(parent=self, image=buttonModel, image_scale=(0.92, 1, 1), image_color=image_color, geom=inventory.invModels[track][item], geom_color=geom_color, geom_scale=0.6, relief=None, pos=pos, state=DGG.NORMAL) + label = DirectLabel(parent=self.inventoryFrame, image=buttonModel, image_scale=(0.92, 1, 1), image_color=image_color, geom=inventory.invModels[track][item], geom_color=geom_color, geom_scale=0.6, relief=None, pos=pos, state=DGG.NORMAL) label.bind(DGG.ENTER, self.showInfo, extraArgs=[rolloverFrame, track, int(getAvPropDamage(track, item, curExp, organic)), numItems, (pos[0] + 0.37, pos[1], pos[2])]) label.bind(DGG.EXIT, self.hideInfo, extraArgs=[rolloverFrame]) else: @@ -245,4 +259,35 @@ class ToonAvatarDetailPanel(DirectFrame): star = gui.find('**/avatarStar') self.star = DirectLabel(parent=self, image=star, image_color=color, pos=(0.610165, 0, -0.760678), scale=0.9, relief=None) gui.removeNode() - return + + def __updateSOSPage(self): + self.sosPage.setFriends(self.avatar.NPCFriendsDict) + self.sosPage.update() + + def __toggleSOSGui(self): + self.sosButton['state'] = DGG.DISABLED + + if self.sosFrame.getScale() == 0.5: + pos = (-0.4, 0, -1.88) + scale = 1.0 + else: + pos = (0, 0, 0.05) + scale = 0.5 + self.sosFrame.setBin('background', 10) + + Sequence( + Parallel( + self.sosFrame.posInterval(1.0, pos, blendType='easeOut'), + self.sosFrame.scaleInterval(1.0, scale, blendType='easeOut') + ), + Func(self.__enableSOSButton) + ).start() + + def __enableSOSButton(self): + try: + self.sosButton['state'] = DGG.NORMAL + + if self.sosFrame.getScale() == 1.0: + self.sosFrame.clearBin() + except: + pass \ No newline at end of file diff --git a/toontown/toon/ToonTeleportPanel.py b/toontown/toon/ToonTeleportPanel.py index b26a676d..43005fc4 100755 --- a/toontown/toon/ToonTeleportPanel.py +++ b/toontown/toon/ToonTeleportPanel.py @@ -62,6 +62,9 @@ class ToonTeleportPanel(DirectFrame): State.State('ignored', self.enterIgnored, self.exitIgnored), + State.State('noTeleport', + self.enterNoTeleport, + self.exitNoTeleport), State.State('notOnline', self.enterNotOnline, self.exitNotOnline), @@ -148,11 +151,18 @@ class ToonTeleportPanel(DirectFrame): self.bOk.hide() def enterIgnored(self): - self['text'] = TTLocalizer.TeleportPanelNotAvailable % self.avName + self['text'] = TTLocalizer.TeleportPanelIgnored % self.avName self.bOk.show() def exitIgnored(self): self.bOk.hide() + + def enterNoTeleport(self): + self['text'] = TTLocalizer.TeleportPanelNoTeleport % self.avName + self.bOk.show() + + def exitNoTeleport(self): + self.bOk.hide() def enterNotOnline(self): self['text'] = TTLocalizer.TeleportPanelNotOnline % self.avName @@ -270,6 +280,8 @@ class ToonTeleportPanel(DirectFrame): elif available == 2: teleportNotify.debug('__teleportResponse: ignored') self.fsm.request('ignored') + elif available == 3: + self.fsm.request('noTeleport') elif shardId != base.localAvatar.defaultShard: teleportNotify.debug('__teleportResponse: otherShard') self.fsm.request('otherShard', [shardId, hoodId, zoneId]) diff --git a/toontown/toonbase/TTLocalizerEnglish.py b/toontown/toonbase/TTLocalizerEnglish.py index 5e4ad456..57d71e14 100755 --- a/toontown/toonbase/TTLocalizerEnglish.py +++ b/toontown/toonbase/TTLocalizerEnglish.py @@ -12,7 +12,7 @@ ToonFont = 'phase_3/models/fonts/ImpressBT.ttf' SuitFont = 'phase_3/models/fonts/vtRemingtonPortable.ttf' SignFont = 'phase_3/models/fonts/MickeyFont' MinnieFont = 'phase_3/models/fonts/MinnieFont' -FancyFont = 'phase_3/models/fonts/Comedy' +ChalkFont = 'phase_3/models/fonts/Chawp.ttf' BuildingNametagFont = 'phase_3/models/fonts/MickeyFont' BuildingNametagShadow = None NametagFonts = ( @@ -551,6 +551,12 @@ INCOMPLETE_PROGRESS = 3 INCOMPLETE_WRONG_NPC = 4 COMPLETE = 5 LEAVING = 6 +TheBrrrghTrackQuestDict = {GREETING: '', + QUEST: 'Now you are ready.\x07Go out and walk the earth until you know which track you would like to choose.\x07Choose wisely, because this is your final track.\x07When you are certain, return to me.', + INCOMPLETE_PROGRESS: 'Choose wisely.', + INCOMPLETE_WRONG_NPC: 'Choose wisely.', + COMPLETE: 'Very wise choice!', + LEAVING: 'Good luck. Return to me when you have mastered your new skill.'} QuestDialog_3225 = {QUEST: "Oh, thanks for coming, _avName_!\x07The Cogs in the neighborhood frightened away my delivery person.\x07I don't have anyone to deliver this salad to _toNpcName_!\x07Can you do it for me? Thanks so much!_where_"} QuestDialog_2910 = {QUEST: 'Back so soon?\x07Great job on the spring.\x07The final item is a counter weight.\x07Stop by and see _toNpcName_ and bring back whatever you can get._where_'} QuestDialogDict = { @@ -600,7 +606,7 @@ QuestDialogDict = { COMPLETE: 'Hope you have fun ordering things from Clarabelle!\x07I just finished redecorating my house. It looks Toontastic!\x07Keep doing ToonTasks to get more rewards!', LEAVING: QuestsDefaultLeaving}, 400: {GREETING: '', - QUEST: 'You will need more gags to fight higher level Cogs.\x07When you team up with other Toons against the Cogs, you can combine attacks for even more damage.\x07Try different combinations of gags to see what works best.\x07When you are ready to decide, come back here and choose.', + QUEST: 'Throw and Squirt are great, but you will need more gags to fight higher level Cogs.\x07When you team up with other Toons against the Cogs, you can combine attacks for even more damage.\x07Try different combinations of gags to see what works best.\x07For your next track, choose between Sound and Toonup.\x07Sound is special because when it hits, it damages all Cogs.\x07Toonup lets you heal other Toons in battle.\x07When you are ready to decide, come back here and choose.', INCOMPLETE_PROGRESS: 'Back so soon? Okay, are you ready to choose?', INCOMPLETE_WRONG_NPC: 'Think about your decision before choosing.', COMPLETE: 'Good decision. Now before you can use those gags, you must train for them.\x07You must complete a series of ToonTasks for training.\x07Each task will give you a single frame of your gag attack animation.\x07When you collect all 15, you can get the Final Gag Training task that will allow you to use your new gags.\x07You can check your progress in the Shticker Book.', @@ -966,22 +972,18 @@ QuestDialogDict = { INCOMPLETE_PROGRESS: 'It seems you may not be so clever with the rod and reel.'}, 5250: {GREETING: '', LEAVING: '', - COMPLETE: 'Now you are ready.\x07Good luck. Return to me when you have mastered your new skill.', QUEST: 'Aha! These dice will look great hanging from the rearview mirror of my ox cart!\x07Now, show me that you can tell your enemies from one another.\x07Return when you have restored two of the tallest Lawbot buildings.', INCOMPLETE_PROGRESS: 'Do the buildings give you trouble?'}, 5258: {GREETING: '', LEAVING: '', - COMPLETE: 'Now you are ready.\x07Good luck. Return to me when you have mastered your new skill.', QUEST: 'Aha! These dice will look great hanging from the rearview mirror of my ox cart!\x07Now, show me that you can tell your enemies from one another.\x07Return when you have restored two of the tallest Bossbot buildings.', INCOMPLETE_PROGRESS: 'Do the buildings give you trouble?'}, 5259: {GREETING: '', LEAVING: '', - COMPLETE: 'Now you are ready.\x07Good luck. Return to me when you have mastered your new skill.', QUEST: 'Aha! These dice will look great hanging from the rearview mirror of my ox cart!\x07Now, show me that you can tell your enemies from one another.\x07Return when you have restored two of the tallest Cashbot buildings.', INCOMPLETE_PROGRESS: 'Do the buildings give you trouble?'}, 5260: {GREETING: '', LEAVING: '', - COMPLETE: 'Now you are ready.\x07Good luck. Return to me when you have mastered your new skill.', QUEST: 'Aha! These dice will look great hanging from the rearview mirror of my ox cart!\x07Now, show me that you can tell your enemies from one another.\x07Return when you have restored two of the tallest Sellbot buildings.', INCOMPLETE_PROGRESS: 'Do the buildings give you trouble?'}, 5200: {QUEST: 'Those sneaky Cogs are at it again.\x07_toNpcName_ has reported another missing item. Stop by and see if you can straighten it out._where_'}, @@ -3976,7 +3978,6 @@ EmoteHappy = 'Happy' EmoteSad = 'Sad' EmoteAnnoyed = 'Annoyed' EmoteSleep = 'Sleepy' -StatPageTitle = 'Statistics' SuitBaseNameWithLevel = '%(name)s\n%(dept)s\nLevel %(level)s' HealthForceAcknowledgeMessage = 'You cannot leave the playground until your Laff meter is smiling!' InventoryTotalGags = 'Total gags\n%d / %d' @@ -3985,7 +3986,6 @@ InventoryPinkSlip = '1 Pink Slip' InventoryCrateKeys = '%s Crate Keys' InventoryCrateKey = '1 Crate Key' InventoryDelete = 'DELETE' -InventoryDeleteAll = 'DELETE ALL' InventoryDone = 'DONE' InventoryDeleteHelp = 'Click on a gag to DELETE it.' InventorySkillCredit = 'Skill credit: %s' @@ -5610,7 +5610,7 @@ NPCToonNames = {20000: 'Tutorial Tom', 2018: 'Doctor Surlee', 2019: 'Doctor Dimm', 2020: 'Professor Prepostera', - 2021: 'Painter Joey', + 2021: 'Painter Eddy', 2101: 'Dentist Daniel', 2102: 'Sheriff Sherry', 2103: 'Sneezy Kitty', @@ -6270,7 +6270,8 @@ NPCToonNames = {20000: 'Tutorial Tom', 11001: 'Healer Gabriel', 12001: 'Healer Bill', 12002: 'Mata Hairy', - 13001: 'Healer Clover'} + 13001: 'Healer Clover', + 13002: 'Bumpy Bumblebehr'} zone2TitleDict = {2513: ('Toon Hall', ''), 2514: ('Toontown Bank', ''), 2516: ('Toontown School House', ''), @@ -7594,7 +7595,6 @@ LawbotBossTaunts = ['%s, I find you in contempt of court!', 'Strike that from the record.', 'Your appeal has been rejected. I sentence you to sadness!', 'Order in the court!'] -WitnessToonName = 'Bumpy Bumblebehr' WitnessToonPrepareBattleTwo = "Oh no! They're putting only Cogs on the jury!\x07Quick, use the cannons and shoot some Toon jurors into the jury chairs.\x07We need %d to get a balanced scale." WitnessToonNoJuror = 'Oh oh, no Toon jurors. This will be a tough trial.' WitnessToonOneJuror = 'Cool! There is 1 Toon in the jury!' @@ -8528,9 +8528,12 @@ def convertSecondsToDate(seconds): return '%d:%02d:%02d' % (h, m, s) ToonDefeatedMessage = '%s was defeated!' + BugReportButton = 'Report a Bug' BugReportNotice = 'Attention!\n\nThis button will open a browser which will send you to a third party bug tracker website. This site requires an Ubuntu One account to login. It may ask you to create an account.\n\nAre you sure you want to continue?' + CodeRedemptionWarning = 'NOTICE: All codes can only be entered once!' + CogInterfaceLabelOn = 'The cog battle interface is on.' CogInterfaceLabelOff = 'The cog battle interface is off.' TpTransitionLabelOn = 'The teleport transition is on.' @@ -8538,6 +8541,7 @@ TpTransitionLabelOff = 'The teleport transition is off.' FieldOfViewLabel = 'Field of View:' NametagStyleLabel = 'Nametag Style:' FishingPoleLabel = 'Fishing Rod:' + BossLocations = { 'c': 'Bossbot Clubhouse\nBanquet', 'l': "Lawbot Courthouse\nBumpy Bumblebehr's Trial", @@ -8654,31 +8658,33 @@ CrateClothingPrize = "Congratulations! You've received a new clothing item. Chec CrateAccessoryPrize = 'Congratulations! You found a new accessory for your Toon. Check your mailbox and rock it!' Stats = [ - 'Cogs defeated: %(cog)s', - 'V2.0 cogs defeated: %(v2)s', - 'Skelecogs defeated: %(skele)s', - 'Jellybeans spent: %(beanSpent)s', - 'Jellybeans earnt: %(beanEarnt)s', - 'Tasks completed: %(task)s', - 'Total VP defeats: %(vp)s', - 'Total CFO defeats: %(cfo)s', - 'Total CJ defeats: %(cj)s', - 'Total CEO defeats: %(ceo)s', - 'Gone sad: %(sad)s times', - 'Buildings liberated: %(bldg)s', - 'Field Offices defeated: %(cogdo)s', - 'Items purchased: %(item)s', - 'Fish caught: %(fish)s', - 'Flowers picked: %(flower)s', - 'Races completed: %(race)s', - 'Golf holes played: %(golf)s', - 'Total SOS cards: %(sos)s', - 'Total unites: %(unite)s', - 'Total pink slips: %(slip)s', - 'Total gags used: %(gag)s' + 'Cogs defeated: %s', + 'V2.0 cogs defeated: %s', + 'Skelecogs defeated: %s', + 'Jellybeans spent: %s', + 'Jellybeans earnt: %s', + 'Tasks completed: %s', + 'Total VP defeats: %s', + 'Total CFO defeats: %s', + 'Total CJ defeats: %s', + 'Total CEO defeats: %s', + 'Gone sad: %s times', + 'Buildings liberated: %s', + 'Offices defeated: %s', + 'Items ordered: %s', + 'Fish caught: %s', + 'Flowers picked: %s', + 'Races completed: %s', + 'Golf holes played: %s', + 'Total SOS cards: %s', + 'Total unites: %s', + 'Total pink slips: %s', + 'Total gags used: %s' ] -StatResetAsk = 'Are you sure you want to reset your stats? This is an irreversible action!' -StatResetDone = 'Your stats have been reset.' +StatPageTitle = 'Statistics' +StatPageClear = 'Clear' +StatPageClearAsk = 'Are you sure you want to clear your stats? This is an irreversible action!' +StatPageClearDone = 'Your stats have been cleared.' ChairAskToUse = 'Would you like to sit on this chair?' @@ -8725,6 +8731,38 @@ ShardPageShardTitle = '%s Population: %s' ShardPageTeleport = 'Teleport to\n%s' TeleportButton = 'Teleport' +TeleportButtonNoMoney = 'Sorry, but you need %s jellybeans to teleport!' +TeleportButtonConfirm = 'Would you like to spend %s jellybeans to teleport?' +TeleportButtonTakenOver = 'Sorry, but this shop has been taken over by the Cogs!' + +BattleCogPopup = '\x01androidGreen\x01Group attacks:\x02\n%s\n\n\x01androidGreen\x01Regular attacks:\x02\n%s' +BattleCogPopupAttack = '%s %s HP' +BattleCogPopupAttackDanger = '\x01red\x01' + BattleCogPopupAttack + '\x02' +BattleCogPopupDanger = '\x01red\x01Dangerous!\x02\n\n' +BattleCogPopupDangerColor = '\x01red' + +SuitPageAttackFormat = 'Levels: %s-%s\n\n' + BattleCogPopup +SuitPageNoAttacks = 'None' + +BattleGagPopup = '%s: %s\nGags left: %s' +BattleSOSPopup = '\x01azure\x01%s\x02\n%s\n%s%s stars\nSOS left: %s' +BattleSOSPopupHeal = 'Heals' +BattleSOSPopupHarm = 'Deals' +BattleSOSPopupHP = '%s %s HP\n' + +DetailPanelSOS = 'SOS Cards' + +TeleportLabelOn = 'Accepting teleports.' +TeleportLabelOff = 'Not accepting teleports.' +TeleportPanelNoTeleport = '%s needs some time alone right now.' + +InventoryDeleteAll = 'DELETE ALL' +InventoryDeleteConfirm = "Are you sure you want to delete all your gags? Don't worry, your level 7 gags are safe!" + +ClothesGUICount = '%s/%s' + +FpsMeterLabelOn = 'The frame rate meter is on.' +FpsMeterLabelOff = 'The frame rate meter is off.' Blacklist = [ "$1ut", diff --git a/toontown/toonbase/TTLocalizerEnglishProperty.py b/toontown/toonbase/TTLocalizerEnglishProperty.py index 16038f24..c41398de 100755 --- a/toontown/toonbase/TTLocalizerEnglishProperty.py +++ b/toontown/toonbase/TTLocalizerEnglishProperty.py @@ -298,3 +298,33 @@ SellbotFactoryPosPart1 = (0, -0.25) SellbotFactoryScalePart1 = 0.075 SellbotFactoryPosPart2 = (0, -0.34) SellbotFactoryScalePart2 = 0.12 +BattleHoverCog = 0 +BattleHoverGag = 1 +BattleHoverSos = 2 + +BattleHoverAttributes = { + BattleHoverCog: { + 'geom_scale': (0.4, 0, 0.18), + 'text_pos': (0, 0.29), + 'geom_color': (0.5, 0.5, 0.5, 1), + 'pos': (0.6, 0, 0.05), + 'text_fg': (1, 1, 1, 1), + 'suit': True + }, + BattleHoverGag: { + 'geom_scale': (0.5, 0, 0.2), + 'text_pos': (0, 0.0125), + 'geom_color': (0.6, 1.0, 0.4, 1), + 'pos': (0.4, 0, 0), + 'text_fg': (0, 0, 0, 1), + 'suit': False + }, + BattleHoverSos: { + 'geom_scale': (0.5, 0, 0.3), + 'text_pos': (0, 0.08), + 'geom_color': (0.6, 1.0, 0.4, 1), + 'pos': (0.4, 0, 0.1), + 'text_fg': (0, 0, 0, 1), + 'suit': False + } +} \ No newline at end of file diff --git a/toontown/toonbase/ToonBase.py b/toontown/toonbase/ToonBase.py index e4aa8e80..52f7a1bb 100755 --- a/toontown/toonbase/ToonBase.py +++ b/toontown/toonbase/ToonBase.py @@ -27,6 +27,21 @@ from toontown.toonbase import TTLocalizer from toontown.toonbase import ToontownBattleGlobals from toontown.toontowngui import TTDialog +tempdir = tempfile.mkdtemp() +vfs = VirtualFileSystem.getGlobalPtr() +searchPath = DSearchPath() +if __debug__: + searchPath.appendDirectory(Filename('resources/phase_3/etc')) +searchPath.appendDirectory(Filename('/phase_3/etc')) + +for filename in ['toonmono.cur', 'icon.ico']: + p3filename = Filename(filename) + found = vfs.resolveFilename(p3filename, searchPath) + if not found: + continue + with open(os.path.join(tempdir, filename), 'wb') as f: + f.write(vfs.readFile(p3filename, False)) +loadPrcFileData('Window: icon', 'icon-filename %s' % Filename.fromOsSpecific(os.path.join(tempdir, 'icon.ico'))) class ToonBase(OTPBase.OTPBase): notify = DirectNotifyGlobal.directNotify.newCategory('ToonBase') @@ -148,23 +163,7 @@ class ToonBase(OTPBase.OTPBase): return result def setCursorAndIcon(self): - tempdir = tempfile.mkdtemp() atexit.register(shutil.rmtree, tempdir) - vfs = VirtualFileSystem.getGlobalPtr() - - searchPath = DSearchPath() - if __debug__: - searchPath.appendDirectory(Filename('resources/phase_3/etc')) - searchPath.appendDirectory(Filename('/phase_3/etc')) - - for filename in ['toonmono.cur', 'icon.ico']: - p3filename = Filename(filename) - found = vfs.resolveFilename(p3filename, searchPath) - if not found: - return # Can't do anything past this point. - - with open(os.path.join(tempdir, filename), 'wb') as f: - f.write(vfs.readFile(p3filename, False)) wp = WindowProperties() wp.setCursorFilename(Filename.fromOsSpecific(os.path.join(tempdir, 'toonmono.cur'))) diff --git a/toontown/toonbase/ToontownGlobals.py b/toontown/toonbase/ToontownGlobals.py index 5250a993..baa76345 100755 --- a/toontown/toonbase/ToontownGlobals.py +++ b/toontown/toonbase/ToontownGlobals.py @@ -2,8 +2,6 @@ import TTLocalizer from otp.otpbase.OTPGlobals import * from direct.showbase.PythonUtil import Enum, invertDict from pandac.PandaModules import BitMask32, Vec4 -MapHotkeyOn = 'alt' -MapHotkeyOff = 'alt-up' MapHotkey = 'alt' CogHQCameraFov = 60.0 BossBattleCameraFov = 72.0 @@ -1690,4 +1688,17 @@ TV_OK = 2 COLOR_SATURATION_MIN = 0.5 COLOR_SATURATION_MAX = 0.8 COLOR_VALUE_MIN = 0.5 -COLOR_VALUE_MAX = 0.8 \ No newline at end of file +COLOR_VALUE_MAX = 0.8 + +TELEPORT_BUTTON_DEFAULT_COST = 50 +TELEPORT_BUTTON_COSTS = { + ToontownCentral: 5, + DonaldsDock: 15, + DaisyGardens: 30, + MinniesMelodyland: 45, + TheBrrrgh: 60, + DonaldsDreamland: 75 +} + +def getTeleportButtonCost(hoodId): + return TELEPORT_BUTTON_COSTS.get(hoodId, TELEPORT_BUTTON_DEFAULT_COST) \ No newline at end of file diff --git a/toontown/toonbase/ToontownStart.py b/toontown/toonbase/ToontownStart.py index ed572136..d620890f 100644 --- a/toontown/toonbase/ToontownStart.py +++ b/toontown/toonbase/ToontownStart.py @@ -19,15 +19,13 @@ sys.path.append( # Temporary hack patch: __builtin__.__dict__.update(__import__('pandac.PandaModules', fromlist=['*']).__dict__) -from direct.extensions_native import HTTPChannel_extensions -from direct.extensions_native import Mat3_extensions -from direct.extensions_native import VBase3_extensions -from direct.extensions_native import VBase4_extensions -from direct.extensions_native import NodePath_extensions from panda3d.core import loadPrcFile +if not os.path.exists('user/'): + os.mkdir('user/') + if __debug__: try: @@ -71,14 +69,15 @@ from direct.directnotify.DirectNotifyGlobal import directNotify notify = directNotify.newCategory('ToontownStart') notify.setInfo(True) -# The VirtualFileSystem, which has already initialized, doesn't see the mount -# directives in the config(s) yet. We have to force it to load those manually: -from panda3d.core import VirtualFileSystem, ConfigVariableList, Filename -vfs = VirtualFileSystem.getGlobalPtr() -mounts = ConfigVariableList('vfs-mount') -for mount in mounts: - mountfile, mountpoint = (mount.split(' ', 2) + [None, None, None])[:2] - vfs.mount(Filename(mountfile), Filename(mountpoint), 0) +if __debug__: + # The VirtualFileSystem, which has already initialized, doesn't see the mount + # directives in the config(s) yet. We have to force it to load those manually: + from panda3d.core import VirtualFileSystem, ConfigVariableList, Filename + vfs = VirtualFileSystem.getGlobalPtr() + mounts = ConfigVariableList('vfs-mount') + for mount in mounts: + mountfile, mountpoint = (mount.split(' ', 2) + [None, None, None])[:2] + vfs.mount(Filename(mountfile), Filename(mountpoint), 0) from otp.settings.Settings import Settings from otp.otpbase import OTPGlobals @@ -107,12 +106,18 @@ if 'language' not in settings: settings['language'] = 'English' if 'cogInterface' not in settings: settings['cogInterface'] = True +if 'speedchatPlus' not in settings: + settings['speedchatPlus'] = True +if 'trueFriends' not in settings: + settings['trueFriends'] = True if 'tpTransition' not in settings: settings['tpTransition'] = True if 'fov' not in settings: settings['fov'] = OTPGlobals.DefaultCameraFov if 'talk2speech' not in settings: settings['talk2speech'] = False +if 'fpsMeter' not in settings: + settings['fpsMeter'] = False loadPrcFileData('Settings: res', 'win-size %d %d' % tuple(settings['res'])) loadPrcFileData('Settings: fullscreen', 'fullscreen %s' % settings['fullscreen']) @@ -186,6 +191,7 @@ cr = ToontownClientRepository.ToontownClientRepository(serverVersion) cr.music = music del music base.initNametagGlobals() +base.setFrameRateMeter(settings['fpsMeter']) base.cr = cr loader.endBulkLoad('init') from otp.friends import FriendManager diff --git a/toontown/toonbase/ToontownStartRemoteDB.py b/toontown/toonbase/ToontownStartRemoteDB.py index 5ac9ce8e..976b6353 100644 --- a/toontown/toonbase/ToontownStartRemoteDB.py +++ b/toontown/toonbase/ToontownStartRemoteDB.py @@ -1,19 +1,31 @@ -import json -import os -import requests +import json, os, sys +import urllib, urllib2, cookielib, socket from panda3d.core import * +req_version = (2,7,9) +cur_version = sys.version_info +if cur_version < req_version: + print 'Your version of python is too old. Please upgrade to 2.7.9.' + sys.exit() + username = os.environ['ttsUsername'] password = os.environ['ttsPassword'] +distribution = 'qa' accountServerEndpoint = 'https://toontownstride.com/api/' -request = requests.post( - accountServerEndpoint + 'login/', - data={'username': username, 'password': password, 'distribution': 'qa'}) + +data = urllib.urlencode({'username': username, 'password': password, 'distribution': distribution, 'version': 'dev'}) +cookie_jar = cookielib.LWPCookieJar() +cookie = urllib2.HTTPCookieProcessor(cookie_jar) +opener = urllib2.build_opener(cookie) +req = urllib2.Request(accountServerEndpoint + 'login', data, + headers={"Content-Type" : "application/x-www-form-urlencoded"}) +req.get_method = lambda: "POST" +_response = opener.open(req).read() try: - response = json.loads(request.text) + response = json.loads(_response) except ValueError: print "Couldn't verify account credentials." else: @@ -24,4 +36,4 @@ else: os.environ['TTS_GAMESERVER'] = response['gameserver'] # Start the game: - import toontown.toonbase.ToontownStart + import toontown.toonbase.ToontownStart \ No newline at end of file diff --git a/toontown/toontowngui/ToontownLoadingScreen.py b/toontown/toontowngui/ToontownLoadingScreen.py index 1f336db9..00671845 100755 --- a/toontown/toontowngui/ToontownLoadingScreen.py +++ b/toontown/toontowngui/ToontownLoadingScreen.py @@ -11,7 +11,7 @@ class ToontownLoadingScreen: def __init__(self): self.__expectedCount = 0 self.__count = 0 - self.textures = [(loader.loadTexture('phase_3.5/maps/loading/toon.jpg'), ToontownGlobals.getSignFont(), (0.2, 0.6, 0.9, 1)), + self.textures = [(loader.loadTexture('phase_3.5/maps/loading/toon.jpg'), ToontownGlobals.getInterfaceFont(), (0, 0, 0.5, 1)), (loader.loadTexture('phase_3.5/maps/loading/cog.jpg'), ToontownGlobals.getSuitFont(), (1.0, 1.0, 1.0, 1)), (loader.loadTexture('phase_3.5/maps/loading/default.jpg'), ToontownGlobals.getInterfaceFont(), (0, 0, 0.5, 1)) ] diff --git a/toontown/town/TownBattle.py b/toontown/town/TownBattle.py index b44cdc32..cba7b4c0 100755 --- a/toontown/town/TownBattle.py +++ b/toontown/town/TownBattle.py @@ -14,11 +14,10 @@ import TownBattleCogPanel from toontown.toontowngui import TTDialog from direct.directnotify import DirectNotifyGlobal from toontown.battle import BattleBase -from toontown.toonbase import ToontownTimer from direct.showbase import PythonUtil -from toontown.toonbase import TTLocalizer +from toontown.toonbase import TTLocalizer, ToontownGlobals, ToontownTimer from toontown.pets import PetConstants -from direct.gui.DirectGui import DGG +from direct.gui.DirectGui import * from toontown.battle import FireCogPanel class TownBattle(StateData.StateData): @@ -43,10 +42,7 @@ class TownBattle(StateData.StateData): self.track = -1 self.level = -1 self.target = 0 - self.toonAttacks = [(-1, 0, 0), - (-1, 0, 0), - (-1, 0, 0), - (-1, 0, 0)] + self.toonAttacks = [(-1, 0, 0)] * 4 self.fsm = ClassicFSM.ClassicFSM('TownBattle', [ State.State('Off', self.enterOff, @@ -122,8 +118,13 @@ class TownBattle(StateData.StateData): self.SOSPetInfoPanel = TownBattleSOSPetInfoPanel.TownBattleSOSPetInfoPanel(self.SOSPetInfoPanelDoneEvent) self.fireCogPanelDoneEvent = 'fire-cog-panel-done' self.FireCogPanel = FireCogPanel.FireCogPanel(self.fireCogPanelDoneEvent) - self.toonPanels = [TownBattleToonPanel.TownBattleToonPanel(i) for i in xrange(4)] - self.cogPanels = [TownBattleCogPanel.TownBattleCogPanel(i) for i in xrange(4)] + self.rolloverFrame = DirectFrame(aspect2d, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=(0.6, 1.0, 0.4, 1), geom_scale=(0.5, 0.3, 0.2), text_scale=0.05, text_pos=(0, 0.0125), text='', text_fg=(0, 0, 0, 1), pos=(0.4, 0, 0)) + self.rolloverFrame.setBin('gui-popup', 0) + self.rolloverFrame.hide() + self.suitGui = loader.loadModel('phase_3.5/models/gui/suit_detail_panel') + self.suitGui.find('**/avatar_panel/shadow').setColor(1, 1, 1, 0.5) + self.toonPanels = [TownBattleToonPanel.TownBattleToonPanel(self) for i in xrange(4)] + self.cogPanels = [TownBattleCogPanel.TownBattleCogPanel(self) for i in xrange(4)] self.timer = ToontownTimer.ToontownTimer() self.timer.posInTopRightCorner() self.timer.setScale(0.4) @@ -143,6 +144,7 @@ class TownBattle(StateData.StateData): del self.FireCogPanel del self.SOSPetSearchPanel del self.SOSPetInfoPanel + del self.rolloverFrame for panel in self.toonPanels + self.cogPanels: panel.cleanup() @@ -150,6 +152,8 @@ class TownBattle(StateData.StateData): del self.toonPanels del self.cogPanels self.timer.destroy() + self.suitGui.removeNode() + del self.suitGui del self.timer del self.toons @@ -214,6 +218,34 @@ class TownBattle(StateData.StateData): self.time = time self.timer.setTime(time) return None + + def showRolloverFrame(self, parent, type, text, extra=None): + dict = TTLocalizer.BattleHoverAttributes[type] + + for key, value in dict.iteritems(): + if key == 'pos': + self.rolloverFrame.setPos(value) + elif key == 'suit': + if value: + self.rolloverFrame['text_font'] = ToontownGlobals.getSuitFont() + self.rolloverFrame['geom'] = self.suitGui.find('**/avatar_panel') + else: + self.rolloverFrame['text_font'] = ToontownGlobals.getInterfaceFont() + self.rolloverFrame['geom'] = DGG.getDefaultDialogGeom() + else: + self.rolloverFrame[key] = value + + self.rolloverFrame.reparentTo(parent) + self.rolloverFrame.show() + self.rolloverFrame['text'] = text + + def hideRolloverFrame(self, extra=None): + self.rolloverFrame.hide() + + def isAttackDangerous(self, hp): + for panel in self.toonPanels: + if panel.hasAvatar() and panel.avatar.getHp() <= hp: + return True def __enterPanels(self, num, localNum): self.notify.debug('enterPanels() num: %d localNum: %d' % (num, localNum)) @@ -227,6 +259,7 @@ class TownBattle(StateData.StateData): for cogPanel in self.cogPanels: cogPanel.hide() cogPanel.updateHealthBar() + cogPanel.updateRolloverBind() cogPanel.setPos(0, 0, 0.62) self.positionPanels(num, self.cogPanels) @@ -292,20 +325,14 @@ class TownBattle(StateData.StateData): def enterOff(self): if self.isLoaded: - for toonPanel in self.toonPanels: - toonPanel.hide() + for panel in self.toonPanels + self.cogPanels: + panel.hide() - for cogPanel in self.cogPanels: - cogPanel.hide() - - self.toonAttacks = [(-1, 0, 0), - (-1, 0, 0), - (-1, 0, 0), - (-1, 0, 0)] + self.toonAttacks = [(-1, 0, 0)] * 4 self.target = 0 + if hasattr(self, 'timer'): self.timer.hide() - return None def exitOff(self): if self.isLoaded: @@ -316,17 +343,14 @@ class TownBattle(StateData.StateData): self.track = -1 self.level = -1 self.target = 0 - return None def enterAttack(self): self.attackPanel.enter() self.accept(self.attackPanelDoneEvent, self.__handleAttackPanelDone) - return None def exitAttack(self): self.ignore(self.attackPanelDoneEvent) self.attackPanel.exit() - return None def __handleAttackPanelDone(self, doneStatus): self.notify.debug('doneStatus: %s' % doneStatus) @@ -419,7 +443,7 @@ class TownBattle(StateData.StateData): self.notify.debug('adjustCogsAndToons() numCogs: %s self.numCogs: %s' % (numCogs, self.numCogs)) self.notify.debug('adjustCogsAndToons() luredIndices: %s self.luredIndices: %s' % (luredIndices, self.luredIndices)) self.notify.debug('adjustCogsAndToons() trappedIndices: %s self.trappedIndices: %s' % (trappedIndices, self.trappedIndices)) - toonIds = map(lambda toon: toon.doId, toons) + toonIds = [toon.doId for toon in toons] self.notify.debug('adjustCogsAndToons() toonIds: %s self.toons: %s' % (toonIds, self.toons)) maxSuitLevel = 0 for cog in cogs: @@ -436,16 +460,18 @@ class TownBattle(StateData.StateData): self.numToons = len(toons) self.localNum = toons.index(base.localAvatar) currStateName = self.fsm.getCurrentState().getName() + + if settings['cogInterface']: + self.__enterCogPanels(self.numCogs) + + for i in xrange(len(cogs)): + self.cogPanels[i].setSuit(cogs[i]) + if resetActivateMode: self.__enterPanels(self.numToons, self.localNum) for i in xrange(len(toons)): self.toonPanels[i].setLaffMeter(toons[i]) - if settings['cogInterface']: - self.__enterCogPanels(self.numCogs) - for i in xrange(len(cogs)): - self.cogPanels[i].setSuit(cogs[i]) - if currStateName == 'ChooseCog': self.chooseCogPanel.adjustCogs(self.numCogs, self.luredIndices, self.trappedIndices, self.track) elif currStateName == 'ChooseToon': @@ -458,12 +484,10 @@ class TownBattle(StateData.StateData): self.cog = 0 self.chooseCogPanel.enter(self.numCogs, luredIndices=self.luredIndices, trappedIndices=self.trappedIndices, track=self.track) self.accept(self.chooseCogPanelDoneEvent, self.__handleChooseCogPanelDone) - return None def exitChooseCog(self): self.ignore(self.chooseCogPanelDoneEvent) self.chooseCogPanel.exit() - return None def __handleChooseCogPanelDone(self, doneStatus): mode = doneStatus['mode'] @@ -511,12 +535,10 @@ class TownBattle(StateData.StateData): self.toon = 0 self.chooseToonPanel.enter(self.numToons, localNum=self.localNum) self.accept(self.chooseToonPanelDoneEvent, self.__handleChooseToonPanelDone) - return None def exitChooseToon(self): self.ignore(self.chooseToonPanelDoneEvent) self.chooseToonPanel.exit() - return None def __handleChooseToonPanelDone(self, doneStatus): mode = doneStatus['mode'] @@ -553,12 +575,10 @@ class TownBattle(StateData.StateData): canHeal, canTrap, canLure = self.checkHealTrapLure() self.FireCogPanel.enter(self.numCogs, luredIndices=self.luredIndices, trappedIndices=self.trappedIndices, track=self.track) self.accept(self.fireCogPanelDoneEvent, self.__handleCogFireDone) - return None def exitFire(self): self.ignore(self.fireCogPanelDoneEvent) self.FireCogPanel.exit() - return None def __handleCogFireDone(self, doneStatus): mode = doneStatus['mode'] @@ -579,12 +599,10 @@ class TownBattle(StateData.StateData): canHeal, canTrap, canLure = self.checkHealTrapLure() self.SOSPanel.enter(canLure, canTrap) self.accept(self.SOSPanelDoneEvent, self.__handleSOSPanelDone) - return None def exitSOS(self): self.ignore(self.SOSPanelDoneEvent) self.SOSPanel.exit() - return None def __handleSOSPanelDone(self, doneStatus): mode = doneStatus['mode'] @@ -618,13 +636,11 @@ class TownBattle(StateData.StateData): self.accept(self.proxyGenerateMessage, self.__handleProxyGenerated) self.accept(self.SOSPetSearchPanelDoneEvent, self.__handleSOSPetSearchPanelDone) messenger.send(self.battleEvent, [response]) - return None def exitSOSPetSearch(self): self.ignore(self.proxyGenerateMessage) self.ignore(self.SOSPetSearchPanelDoneEvent) self.SOSPetSearchPanel.exit() - return None def __handleSOSPetSearchPanelDone(self, doneStatus): mode = doneStatus['mode'] @@ -639,12 +655,10 @@ class TownBattle(StateData.StateData): def enterSOSPetInfo(self): self.SOSPetInfoPanel.enter(self.petId) self.accept(self.SOSPetInfoPanelDoneEvent, self.__handleSOSPetInfoPanelDone) - return None def exitSOSPetInfo(self): self.ignore(self.SOSPetInfoPanelDoneEvent) self.SOSPetInfoPanel.exit() - return None def __handleSOSPetInfoPanelDone(self, doneStatus): mode = doneStatus['mode'] @@ -660,15 +674,10 @@ class TownBattle(StateData.StateData): self.fsm.request('SOS') def __isCogChoiceNecessary(self): - if self.numCogs > 1 and not self.__isGroupAttack(self.track, self.level): - return 1 - else: - return 0 + return self.numCogs > 1 and not self.__isGroupAttack(self.track, self.level) def __isGroupAttack(self, trackNum, levelNum): - retval = BattleBase.attackAffectsGroup(trackNum, levelNum) - return retval + return BattleBase.attackAffectsGroup(trackNum, levelNum) def __isGroupHeal(self, levelNum): - retval = BattleBase.attackAffectsGroup(HEAL_TRACK, levelNum) - return retval + return self.__isGroupAttack(HEAL_TRACK, levelNum) diff --git a/toontown/town/TownBattleCogPanel.py b/toontown/town/TownBattleCogPanel.py index f68b00c7..8335ac2b 100755 --- a/toontown/town/TownBattleCogPanel.py +++ b/toontown/town/TownBattleCogPanel.py @@ -1,31 +1,37 @@ from direct.gui.DirectGui import * +from toontown.battle import SuitBattleGlobals from toontown.suit import Suit, SuitHealthBar from toontown.toonbase import TTLocalizer class TownBattleCogPanel(DirectFrame): - def __init__(self, id): + def __init__(self, battle): gui = loader.loadModel('phase_3.5/models/gui/battle_gui') DirectFrame.__init__(self, relief=None, image=gui.find('**/ToonBtl_Status_BG'), image_color=(0.86, 0.86, 0.86, 0.7), scale=0.8) self.initialiseoptions(TownBattleCogPanel) + self.battle = battle self.levelText = DirectLabel(parent=self, text='', pos=(-0.06, 0, -0.075), text_scale=0.055) self.typeText = DirectLabel(parent=self, text='', pos=(0.12, 0, -0.075), text_scale=0.045) self.healthBar = SuitHealthBar.SuitHealthBar() self.generateHealthBar() + self.hoverButton = DirectButton(parent=self, relief=None, image_scale=(0.07, 0, 0.06), pos=(0.105, 0, 0.05), image='phase_3/maps/invisible.png', pressEffect=0) + self.hoverButton.setTransparency(True) + self.hoverButton.bind(DGG.EXIT, self.battle.hideRolloverFrame) self.suit = None self.suitHead = None self.hide() gui.removeNode() def cleanup(self): - self.ignoreAll() self.cleanupHead() self.levelText.removeNode() self.typeText.removeNode() self.healthBar.delete() + self.hoverButton.removeNode() del self.levelText del self.typeText del self.healthBar + del self.hoverButton DirectFrame.destroy(self) def cleanupHead(self): @@ -35,17 +41,39 @@ class TownBattleCogPanel(DirectFrame): def setSuit(self, suit): if self.suit == suit: - messenger.send(self.suit.uniqueName('hpChange')) return - self.ignoreAll() self.cleanupHead() self.suit = suit self.generateSuitHead(suit.getStyleName()) self.updateHealthBar() self.levelText['text'] = TTLocalizer.CogPanelLevel % suit.getActualLevel() self.typeText['text'] = suit.getTypeText() - self.accept(suit.uniqueName('hpChange'), self.updateHealthBar) + self.updateRolloverBind() + + def updateRolloverBind(self): + if not self.suit: + return + + attributes = SuitBattleGlobals.SuitAttributes[self.suit.getStyleName()] + groupAttacks, singleAttacks = SuitBattleGlobals.getAttacksByType(attributes) + level = self.suit.getLevel() + info = TTLocalizer.BattleCogPopup % (self.getAttackStrings(groupAttacks, level), self.getAttackStrings(singleAttacks, level)) + + if TTLocalizer.BattleCogPopupDangerColor in info: + info = TTLocalizer.BattleCogPopupDanger + info + + self.hoverButton.bind(DGG.ENTER, self.battle.showRolloverFrame, extraArgs=[self, TTLocalizer.BattleHoverCog, info]) + + def getAttackStrings(self, attacks, level): + attackStrings = [] + + for attack in attacks: + hp = attack[1][level] + attackString = TTLocalizer.BattleCogPopupAttackDanger if self.battle.isAttackDangerous(hp) else TTLocalizer.BattleCogPopupAttack + attackStrings.append(attackString % (TTLocalizer.SuitAttackNames[attack[0]], hp)) + + return '\n'.join(attackStrings) if attackStrings else TTLocalizer.SuitPageNoAttacks def generateSuitHead(self, name): self.suitHead = Suit.attachSuitHead(self, name) diff --git a/toontown/town/TownBattleToonPanel.py b/toontown/town/TownBattleToonPanel.py index 388ec7c6..03c7ba6b 100755 --- a/toontown/town/TownBattleToonPanel.py +++ b/toontown/town/TownBattleToonPanel.py @@ -3,7 +3,7 @@ from toontown.toonbase import ToontownGlobals from toontown.toonbase.ToontownBattleGlobals import * from direct.directnotify import DirectNotifyGlobal import string -from toontown.toon import LaffMeter +from toontown.toon import LaffMeter, NPCToons from toontown.battle import BattleBase from direct.gui.DirectGui import * from toontown.toonbase import TTLocalizer @@ -11,19 +11,19 @@ from toontown.toon.NPCFriendPanel import createNPCToonHead class TownBattleToonPanel(DirectFrame): notify = DirectNotifyGlobal.directNotify.newCategory('TownBattleToonPanel') + sosTracks = Tracks + NPCTracks - def __init__(self, id): + def __init__(self, battle): gui = loader.loadModel('phase_3.5/models/gui/battle_gui') DirectFrame.__init__(self, relief=None, image=gui.find('**/ToonBtl_Status_BG'), image_color=Vec4(0.5, 0.9, 0.5, 0.7)) self.setScale(0.8) self.initialiseoptions(TownBattleToonPanel) + self.battle = battle self.avatar = None self.sosText = DirectLabel(parent=self, relief=None, pos=(0.1, 0, 0.015), text=TTLocalizer.TownBattleToonSOS, text_scale=0.06) self.sosText.hide() self.fireText = DirectLabel(parent=self, relief=None, pos=(0.1, 0, 0.015), text=TTLocalizer.TownBattleToonFire, text_scale=0.06) self.fireText.hide() - self.roundsText = DirectLabel(parent=self, relief=None, pos=(0.16, 0, -0.07), text='', text_scale=0.045) - self.roundsText.hide() self.sosHead = None self.undecidedText = DirectLabel(parent=self, relief=None, pos=(0.1, 0, 0.015), text=TTLocalizer.TownBattleUndecided, text_scale=0.1) self.healthText = DirectLabel(parent=self, text='', pos=(-0.06, 0, -0.075), text_scale=0.055) @@ -39,29 +39,37 @@ class TownBattleToonPanel(DirectFrame): passGui.reparentTo(self.passNode) self.passNode.hide() self.laffMeter = None - self.whichText = DirectLabel(parent=self, text='', pos=(0.1, 0, -0.08), text_scale=0.05) + self.whichText = DirectLabel(parent=self, relief=None, text='', pos=(0.1, 0, -0.08), text_scale=0.05) + self.hoverButton = DirectButton(parent=self, relief=None, image_scale=(0.07, 0, 0.06), pos=(0.105, 0, 0.05), image='phase_3/maps/invisible.png', pressEffect=0) + self.hoverButton.setTransparency(True) + self.hoverButton.bind(DGG.EXIT, self.battle.hideRolloverFrame) self.hide() gui.removeNode() + + def hasAvatar(self): + return self.avatar is not None def setLaffMeter(self, avatar): self.notify.debug('setLaffMeter: new avatar %s' % avatar.doId) + if self.avatar == avatar: messenger.send(self.avatar.uniqueName('hpChange'), [avatar.hp, avatar.maxHp, 1]) - return None - else: - if self.avatar or self.laffMeter: - self.cleanupLaffMeter() - self.avatar = avatar - self.laffMeter = LaffMeter.LaffMeter(avatar.style, avatar.hp, avatar.maxHp) - self.laffMeter.setAvatar(self.avatar) - self.laffMeter.reparentTo(self) - self.laffMeter.setPos(-0.06, 0, 0.05) - self.laffMeter.setScale(0.045) - self.laffMeter.start() - self.setHealthText(avatar.hp, avatar.maxHp) - self.hpChangeEvent = self.avatar.uniqueName('hpChange') - self.accept(self.hpChangeEvent, self.setHealthText) - return None + return + + if self.avatar or self.laffMeter: + self.cleanupLaffMeter() + self.cleanupSosHead() + + self.avatar = avatar + self.laffMeter = LaffMeter.LaffMeter(avatar.style, avatar.hp, avatar.maxHp) + self.laffMeter.setAvatar(self.avatar) + self.laffMeter.reparentTo(self) + self.laffMeter.setPos(-0.06, 0, 0.05) + self.laffMeter.setScale(0.045) + self.laffMeter.start() + self.setHealthText(avatar.hp, avatar.maxHp) + self.hpChangeEvent = self.avatar.uniqueName('hpChange') + self.accept(self.hpChangeEvent, self.setHealthText) def setHealthText(self, hp, maxHp, quietly = 0): self.healthText['text'] = TTLocalizer.TownBattleHealthText % {'hitPoints': hp, @@ -92,13 +100,11 @@ class TownBattleToonPanel(DirectFrame): self.undecidedText.hide() self.sosText.hide() self.fireText.hide() - self.roundsText.hide() self.gagNode.hide() self.whichText.hide() self.passNode.hide() self.cleanupSosHead() - self.whichText.setPos(0.1, 0, -0.08) - self.whichText['text_scale'] = 0.05 + self.hoverButton.unbind(DGG.ENTER) if self.hasGag: self.gag.removeNode() self.hasGag = 0 @@ -115,6 +121,22 @@ class TownBattleToonPanel(DirectFrame): self.sosHead.reparentTo(self) self.sosHead.setPos(0.1, 0, 0.045) self.sosHead.setScale(0.24) + track, level, hp, rarity = NPCToons.getNPCTrackLevelHpRarity(targetIndex) + sosType = self.sosTracks[track] + + if track == NPC_RESTOCK_GAGS: + if level == -1: + sosType += ' All' + else: + sosType += ' ' + self.sosTracks[level] + + if hp: + hpString = TTLocalizer.BattleSOSPopupHP % (TTLocalizer.BattleSOSPopupHeal if track == HEAL_TRACK else TTLocalizer.BattleSOSPopupHarm, hp) + + sosType = TextEncoder.upper(sosType) + count = max(0, self.avatar.getNPCFriendCount(targetIndex) - 1) + info = TTLocalizer.BattleSOSPopup % (sosType, NPCToons.getNPCName(targetIndex), hpString if hp else '', rarity, count) + self.hoverButton.bind(DGG.ENTER, self.battle.showRolloverFrame, extraArgs=[self, TTLocalizer.BattleHoverSos, info]) elif track == BattleBase.SOS or track == BattleBase.PETSOS: self.sosText.show() elif track >= MIN_TRACK_INDEX and track <= MAX_TRACK_INDEX: @@ -126,22 +148,19 @@ class TownBattleToonPanel(DirectFrame): self.gag.setScale(0.8) self.gag.setPos(0, 0, 0.02) self.hasGag = 1 - if self.avatar is not None and self.avatar.checkGagBonus(track, level): - self.gag.setColor((1, 0, 0, 1) if track == 1 and level == 5 else (0, 1, 0, 1)) + if self.avatar: + curExp, nextExp = self.avatar.inventory.getCurAndNextExpValues(track) + organic = self.avatar.checkGagBonus(track, level) + damage = int(getAvPropDamage(track, level, curExp, organic)) + numItems = max(0, self.avatar.inventory.numItem(track, level) - 1) + info = TTLocalizer.BattleGagPopup % (self.avatar.inventory.getToonupDmgStr(track, 0), damage, numItems) + self.hoverButton.bind(DGG.ENTER, self.battle.showRolloverFrame, extraArgs=[self, TTLocalizer.BattleHoverGag, info]) + + if self.avatar.checkGagBonus(track, level): + self.gag.setColor((1, 0, 0, 1) if track == 1 and level == 5 else (0, 1, 0, 1)) if numTargets is not None and targetIndex is not None and localNum is not None: self.whichText.show() self.whichText['text'] = self.determineWhichText(numTargets, targetIndex, localNum, index) - self.roundsText.setPos(0.16, 0, -0.07) - self.roundsText['text_scale'] = 0.045 - elif track == LURE_TRACK: - self.roundsText['text_scale'] = 0.05 - self.roundsText.setPos(0.1, 0, -0.08) - if track == LURE_TRACK: - self.roundsText.show() - self.roundsText['text'] = str(NumRoundsLured[level]) - self.whichText.setPos(0.085, 0, -0.07) - self.whichText['text_scale'] = 0.045 - else: self.notify.error('Bad track value: %s' % track) @@ -149,6 +168,7 @@ class TownBattleToonPanel(DirectFrame): returnStr = '' targetList = range(numTargets) targetList.reverse() + for i in targetList: if targetIndex == -1: returnStr += 'X' @@ -175,6 +195,8 @@ class TownBattleToonPanel(DirectFrame): del self.gag self.gagNode.removeNode() del self.gagNode + self.hoverButton.removeNode() + del self.hoverButton self.cleanupSosHead() DirectFrame.destroy(self) @@ -184,9 +206,8 @@ class TownBattleToonPanel(DirectFrame): self.sosHead = None def cleanupLaffMeter(self): - self.notify.debug('Cleaning up laffmeter!') self.ignore(self.hpChangeEvent) + if self.laffMeter: self.laffMeter.destroy() self.laffMeter = None - return diff --git a/toontown/town/TutorialStreet.py b/toontown/town/TutorialStreet.py index 1385f1db..8d8af0e3 100755 --- a/toontown/town/TutorialStreet.py +++ b/toontown/town/TutorialStreet.py @@ -19,4 +19,4 @@ class TutorialStreet(TTStreet.TTStreet): TTStreet.TTStreet.handleEnterTunnel(self, requestStatus, collEntry) def exitDoorIn(self): - base.localAvatar.obscureMoveFurnitureButton(-1) + base.localAvatar.obscureMoveFurnitureButton(0) diff --git a/toontown/uberdog/ClientServicesManagerUD.py b/toontown/uberdog/ClientServicesManagerUD.py index 0538b596..2bd953e3 100755 --- a/toontown/uberdog/ClientServicesManagerUD.py +++ b/toontown/uberdog/ClientServicesManagerUD.py @@ -16,6 +16,7 @@ from panda3d.core import * import hashlib, hmac, json import anydbm, math, os import urllib2, time, urllib +import cookielib, socket def rejectConfig(issue, securityIssue=True, retarded=True): print @@ -72,17 +73,21 @@ minAccessLevel = config.GetInt('min-access-level', 100) def executeHttpRequest(url, **extras): # TO DO: THIS IS QUITE DISGUSTING # MOVE THIS TO ToontownInternalRepository (this might be interesting for AI) + ##### USE PYTHON 2.7.9 ON PROD WITH SSL AND CLOUDFLARE ##### _data = {} if len(extras.items()) != 0: for k, v in extras.items(): _data[k] = v signature = hashlib.sha512(json.dumps(_data) + apiSecret).hexdigest() data = urllib.urlencode({'data': json.dumps(_data), 'hmac': signature}) - req = urllib2.Request('https://toontownstride.com/api/' + url, data, + cookie_jar = cookielib.LWPCookieJar() + cookie = urllib2.HTTPCookieProcessor(cookie_jar) + opener = urllib2.build_opener(cookie) + req = urllib2.Request('http://192.168.1.212/api/' + url, data, headers={"Content-Type" : "application/x-www-form-urlencoded"}) req.get_method = lambda: "POST" try: - return urllib2.urlopen(req).read() + return opener.open(req).read() except: return None @@ -236,7 +241,12 @@ class RemoteAccountDB: Token = BASE64(H + X) ''' + cookie_check = executeHttpRequest('cookie', cookie=token) + try: + check = json.loads(cookie_check) + if check['success'] is not True: + raise ValueError(check['error']) token = token.decode('base64') hash, token = token[:hashSize], token[hashSize:] correctHash = hashAlgo(token + accountServerSecret).digest() @@ -252,29 +262,35 @@ class RemoteAccountDB: token = json.loads(token.decode('base64')[::-1].decode('rot13')) + if token['notAfter'] < int(time.time()): + raise ValueError('Expired token.') except: resp = {'success': False} callback(resp) return resp - return self.lookup_account(token, callback) - - def lookup_account(self, data, callback): - userId = data['userId'] + return self.account_lookup(token, callback) + def account_lookup(self, data, callback): data['success'] = True data['accessLevel'] = max(data['accessLevel'], minAccessLevel) - data['accountId'] = int(data['accountId']) callback(data) return data - + def storeAccountID(self, userId, accountId, callback): - r = executeHttpRequest('associateUser', username=str(userId), accountId=str(accountId)) - if r: - return 'SUCCESS' - return 'FAILURE' + r = executeHttpRequest('associateuser', username=str(userId), accountId=str(accountId)) + try: + r = json.loads(r) + if r['success']: + callback(True) + else: + self.notify.warning('Unable to associate user %s with account %d, got the return message of %s!' % (userId, accountId, r['error'])) + callback(False) + except: + self.notify.warning('Unable to associate user %s with account %d!' % (userId, accountId)) + callback(False) # --- FSMs ---