Merge branch 'feature/deployment'

This commit is contained in:
John 2015-08-31 00:03:21 +03:00
commit e2b8582261
120 changed files with 1469 additions and 977 deletions

2
.gitignore vendored
View file

@ -24,3 +24,5 @@ dependencies/config/local.prc
bson
gridfs
pymongo
Toon Bot
DNS

11
.gitmodules vendored
View file

@ -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

Binary file not shown.

View file

@ -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

View file

@ -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('<I', f.read(4))
data = f.read()
# TODO: Compression
dg = Datagram()
dg.addUint32(len(self.modules) + basesize)
dg.appendData(data)
dg.addUint32(len(self.modules))
for moduleName in self.modules:
data, size = self.modules[moduleName]
@ -167,19 +94,26 @@ class StridePackager(NiraiPackager):
dg.appendData(data)
data = dg.getMessage()
compressed = compressString(data, 9)
key = self.generate_key(100)
fixed = ''.join(chr((i ^ (5 * i + 7)) % ((i + 6) * 10)) for i in xrange(28))
rc4.rc4_setkey(key + fixed)
data = rc4.rc4(compressed)
return key + data
#compressed = compress_string(data, 9)
iv = self.generate_key(16)
key = self.generate_key(16)
fixed_key = ''.join(chr((i ^ (7 * i + 16)) % ((i + 5) * 3)) for i in xrange(16))
fixed_iv = ''.join(chr((i ^ (2 * i + 53)) % ((i + 9) * 6)) for i in xrange(16))
securekeyandiv = aes.encrypt(iv + key, fixed_key, fixed_iv)
return securekeyandiv + aes.encrypt(data, key, iv)
# 1. Make the NRI
# Compile the engine
if args.compile_cxx:
compiler = NiraiCompiler('stride.exe', libs=set(glob.glob('c:/repos/libpandadna/libpandadna.dir/Release/*.obj')))
compiler.add_nirai_files()
compiler.add_source('src/stride.cxx')
compiler.run()
# Compile the game data
if args.make_nri:
if not os.path.exists('built'):
os.mkdir('built')
pkg = StridePackager('built/stride.dist')
pkg = StridePackager('built/TTSData.bin')
pkg.add_source_dir('otp')
pkg.add_source_dir('toontown')
@ -187,19 +121,18 @@ if args.make_nri:
pkg.add_data_file('NiraiStart')
pkg.generate_niraidata()
pkg.write_out()
# 2. Compile CXX stuff
if args.compile_cxx:
if not os.path.exists('built'):
os.mkdir('built')
if args.make_mfs:
os.chdir('../resources')
cmd = ''
for phasenum in ['3', '3.5', '4', '5', '5.5', '6', '7', '8', '9', '10', '11', '12', '13']:
print 'phase_%s' % (phasenum)
cmd = 'multify -cf ../build/built/resources/default/phase_%s.mf phase_%s' % (phasenum, phasenum)
p = subprocess.Popen(cmd, stdout=sys.stdout, stderr=sys.stderr)
v = p.wait()
sys.path.append('../../../N2')
from niraitools import NiraiCompiler
compiler = NiraiCompiler('stride.exe', r'"C:\\Users\\Usuario\\workspace\\nirai-panda3d\\thirdparty\\win-libs-vc10"',
libs=set(glob.glob('libpandadna/libpandadna.dir/Release/*.obj')))
compiler.add_nirai_files()
compiler.add_source('src/stride.cxx')
compiler.run()
if v != 0:
print 'The following command returned non-zero value (%d): %s' % (v, cmd[:100] + '...')
sys.exit(1)

1
build/nirai/panda3d Submodule

@ -0,0 +1 @@
Subproject commit e4743737b0572feab80a08959f2b4d865ab3bc62

1
build/nirai/python Submodule

@ -0,0 +1 @@
Subproject commit d24aeac557165f986373fa6d59de128902b74112

1
build/nirai/src Submodule

@ -0,0 +1 @@
Subproject commit 3d29188a91b658f61cd2c3b3b8ada23050d4f230

Binary file not shown.

View file

@ -1,18 +1,17 @@
#include "nirai.h"
#include <datagram.h>
#include <datagramIterator.h>
#include <algorithm>
#include <string>
#include <compress_string.h>
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;
// Decompress and read
std::string decompressed = decompress_string(decrypted_data);
// Read
Datagram dg(decompressed);
// TODO: Compression
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);
}

Binary file not shown.

Binary file not shown.

View file

@ -51,7 +51,7 @@ roles:
max: 399999999
backend:
type: yaml
foldername: ../databases/astrondb
directory: ../databases/astrondb
- type: dbss
database: 4003

View file

@ -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);

BIN
dependencies/astron/mongoclient.dll vendored Normal file

Binary file not shown.

View file

@ -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/

View file

@ -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"]
}

View file

@ -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
#<dev>
@ -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
#</dev>
#<prod>
dont-destroy-crate #f
get-key-reward-always #f
get-crate-reward-always #f
want-lawbot-cogdo #f
#</prod>

View file

@ -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

View file

@ -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:

View file

@ -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)
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

View file

@ -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

View file

@ -115,10 +115,17 @@ 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

View file

@ -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()

View file

@ -67,6 +67,7 @@ class Avatar(Actor, ShadowCaster):
self.__chatSet = 0
self.__chatLocal = 0
self.__currentDialogue = None
self.wantAdminTag = True
def delete(self):
try:
@ -173,6 +174,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:
return
@ -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()))
return 'Your current target is: %s [avId: %s, access: %s]' % (spellbook.getTarget().getName(), spellbook.getTarget().doId, spellbook.getTarget().getAdminAccess())

View file

@ -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():

View file

@ -1,5 +1,6 @@
from direct.distributed.DistributedObjectGlobal import DistributedObjectGlobal
from otp.ai.MagicWordGlobal import *
from otp.avatar import Avatar
class ChatAgent(DistributedObjectGlobal):

View file

@ -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()

View file

@ -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'])

View file

@ -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}

View file

@ -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

View file

@ -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.'],

@ -1 +1 @@
Subproject commit 769d26390634d17384aa28021cc7afd88306c4af
Subproject commit af09e769b860512c03de6fff4a585e96d674e89b

View file

@ -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

View file

@ -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

View file

@ -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]

View file

@ -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:

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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:

View file

@ -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))

View file

@ -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))

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -11,6 +11,9 @@ class DistributedKnockKnockDoorAI(DistributedAnimatedPropAI.DistributedAnimatedP
self.propId = propId
self.doLaterTask = None
def delete(self):
DistributedAnimatedPropAI.DistributedAnimatedPropAI.delete(self)
def enterOff(self):
DistributedAnimatedPropAI.DistributedAnimatedPropAI.enterOff(self)

View file

@ -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):

View file

@ -176,12 +176,13 @@ 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)
else:
if modelType in InteriorTypes:
elif modelType in InteriorTypes:
area = InteriorTypes[modelType]
base.localAvatar.setPosHpr(area[0], area[1], ToontownGlobals.FloorOffset, area[2], 0.0, 0.0)
else:

View file

@ -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])

View file

@ -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,

View file

@ -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):

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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])

View file

@ -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)

View file

@ -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):

View file

@ -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

View file

@ -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'):

View file

@ -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)

View file

@ -206,8 +206,5 @@ class DistributedClosetAI(DistributedFurnitureItemAI):
def setMovie(self, todo0, todo1, todo2):
pass
def resetItemLists(self):
pass
def setCustomerDNA(self, todo0, todo1):
pass

View file

@ -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

View file

@ -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()

View file

@ -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),
]

View file

@ -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

View file

@ -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()

View file

@ -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):

View file

@ -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)

View file

@ -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):

View file

@ -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:

View file

@ -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)

View file

@ -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):

View file

@ -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')

View file

@ -46,7 +46,20 @@ class TTSLauncher:
return self.getValue('TTS_PLAYCOOKIE')
def getGameServer(self):
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)

View file

@ -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

View file

@ -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))

View file

@ -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.updateMap()
def ignoreOnscreenHooks(self):
self.ignore(ToontownGlobals.MapHotkey)
self.ignore(ToontownGlobals.MapHotkeyOn)
self.ignore(ToontownGlobals.MapHotkeyOff)
self.obscureButton()

View file

@ -406,9 +406,12 @@ 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:
self.timeoutTrack = Sequence(*timeoutList)

View file

@ -73,12 +73,19 @@ 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):
geom = icon['geom']
@ -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}
@ -185,14 +191,31 @@ class QuestPoster(DirectFrame):
npcHood = ZoneUtil.getCanonicalHoodId(zoneId)
npcZone = hqZone.get(npcHood, 2520)
base.cr.buildingQueryMgr.d_isSuit(npcZone, lambda isSuit: self.teleportToShopCallback(npcZone, npcHood, isSuit))
cost = ToontownGlobals.getTeleportButtonCost(npcHood)
self.destroyDialog()
base.cr.playGame.getPlace().setState('stopped')
def teleportToShopCallback(self, npcZone, npcHood, flag):
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))
self.dialog.show()
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:

View file

@ -254,6 +254,7 @@ 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
TUTORIAL_ACK_DONE
LOCAL_CHAT_CONFIRM npc QuestScriptTutorialBlocker_7 "CFReversed"
LOCAL_CHAT_CONFIRM npc QuestScriptTutorialBlocker_8 1 "CFReversed"
LOOP_ANIM npc "walk"

View file

@ -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):
if tier == MM_TIER:
return 4001
elif tier == BR_TIER:
return 5247
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 seededRandomChoice(Tier2Reward2QuestsDict[tier][400])
return None
return None
bestQuest = None
trackAccess = av.getTrackAccess()
if tier == MM_TIER:
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:
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:
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),

View file

@ -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,

View file

@ -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:

View file

@ -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 ---

View file

@ -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()

View file

@ -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)

View file

@ -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()
@ -808,6 +822,34 @@ class ExtraOptionsTabPage(DirectFrame):
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']

View file

@ -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
@ -48,6 +47,11 @@ class ShtikerBook(DirectFrame, StateData.StateData):
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

View file

@ -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):
@ -48,24 +45,25 @@ class StatPage(ShtikerPage.ShtikerPage):
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()

View file

@ -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

View file

@ -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

View file

@ -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])

View file

@ -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:

View file

@ -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:

View file

@ -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)

View file

@ -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]

View file

@ -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

View file

@ -491,6 +491,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 = {}
for friendPair in NPCFriendsList:
@ -590,6 +593,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')
@ -1251,6 +1259,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:
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):
"""

View file

@ -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)
@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)
@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)
@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)

Some files were not shown because too many files have changed in this diff Show more