This commit is contained in:
Michael G 2025-01-28 04:49:54 -05:00 committed by GitHub
commit f3b9142084
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
80 changed files with 3378 additions and 1894 deletions

View File

@ -619,6 +619,7 @@ dclass DistributedToon : DistributedPlayer {
setNeverStartedPartyRefunded(uint64, int8, uint16) ownrecv;
setDISLname(string) ram;
setDISLid(uint32) ram db airecv;
toggleSleep() ownrecv;
};
dclass DistributedCCharBase : DistributedObject {
@ -2873,6 +2874,9 @@ dclass ToontownFriendsManager : DistributedObject {
makeFriendsResponse(uint32, uint32, uint8, uint32) airecv;
removeFriend(uint32) clsend;
requestSecret(uint32);
submitSecret(uint32, string);
requestSecretResponse(uint8, string, uint32) airecv;
submitSecretResponse(uint8, uint32, uint32) airecv;
};
dclass TTSpeedchatRelay : SpeedchatRelay {

View File

@ -61,6 +61,7 @@ class LocalAvatar(DistributedAvatar.DistributedAvatar, DistributedSmoothNode.Dis
self.soundRun = None
self.soundWalk = None
self.sleepFlag = 0
self.noSleep = 0
self.isDisguised = 0
self.movingFlag = 0
self.swimmingFlag = 0
@ -984,7 +985,7 @@ class LocalAvatar(DistributedAvatar.DistributedAvatar, DistributedSmoothNode.Dis
return
def gotoSleep(self):
if not self.sleepFlag:
if not self.sleepFlag and not self.noSleep:
self.b_setAnimState('Sleep', self.animMultiplier)
self.sleepFlag = 1

View File

@ -18,6 +18,11 @@ class FriendManagerAI(DistributedObjectGlobalAI):
# forget who has declined friendships from whom.
DeclineFriendshipTimeout = 600.0
# This is the length of time, in seconds, to sit on a secret guess
# # before processing it. This serves to make it difficult to guess
# # passwords at random.
SecretDelay = 1.0
# This subclass is used to record currently outstanding
# in-the-game invitation requests.
class Invite:
@ -50,9 +55,13 @@ class FriendManagerAI(DistributedObjectGlobalAI):
# will be sent in response to secret requests to the database,
# via the AIR.
self.accept("makeFriendsReply", self.makeFriendsReply)
self.accept("requestSecretReply", self.requestSecretReply)
self.accept('submitSecretReply', self.submitSecretReply)
def delete(self):
self.ignore("makeFriendsReply")
self.ignore("requestSecretReply")
self.ignore('submitSecretReply')
DistributedObjectGlobalAI.delete(self)
### Messages sent from inviter client to AI
@ -221,6 +230,51 @@ class FriendManagerAI(DistributedObjectGlobalAI):
self.sendUpdateToAvatarId(recipient, "friendResponse", [yesNoMaybe, context])
self.notify.debug("AI: friendResponse(%d, %d)" % (yesNoMaybe, context))
def submitSecret(self, secret):
"""submitSecret(self, string secret)
Sent by the client to the AI to submit a "secret" typed in by
the user.
"""
avId = self.air.getAvatarIdFromSender()
# We have to sit on this request for a few seconds before
# processing it. This delay is solely to discourage password
# guessing.
taskName = "secret-" + str(avId)
taskMgr.remove(taskName)
if FriendManagerAI.SecretDelay:
taskMgr.doMethodLater(FriendManagerAI.SecretDelay,
self.continueSubmission,
taskName,
extraArgs = (avId, secret))
else:
# No delay
self.continueSubmission(avId, secret)
def continueSubmission(self, avId, secret):
"""continueSubmission(self, avId, secret)
Finishes the work of submitSecret, a short time later.
"""
self.air.submitSecret(avId, secret)
def submitSecretReply(self, result, recipient, avId):
self.down_submitSecretResponse(recipient, result, avId)
def down_submitSecretResponse(self, recipient, result, avId):
"""submitSecret(self, int8 result, int32 avId)
Sent by the AI to the client in response to submitSecret().
result is one of:
0 - Failure. The secret is unknown or has timed out.
1 - Success. You are now friends with the indicated avId.
2 - Failure. One of the avatars has too many friends already.
3 - Failure. You just used up your own secret.
"""
self.sendUpdateToAvatarId(recipient, 'submitSecretResponse', [result, avId])
### Support methods
def newInvite(self, inviterId, inviteeId):
@ -409,3 +463,18 @@ class FriendManagerAI(DistributedObjectGlobalAI):
avatar.d_friendsNotify(invite.inviterId, 2)
self.clearInvite(invite)
def requestSecretReply(self, result, secret, requesterId):
self.down_requestSecretResponse(requesterId, result, secret)
def down_requestSecretResponse(self, recipient, result, secret):
"""requestSecret(self, int8 result, string secret)
Sent by the AI to the client in response to requestSecret().
result is one of:
0 - Too many secrets outstanding. Try again later.
1 - Success. The new secret is supplied.
"""
self.sendUpdateToAvatarId(recipient, 'requestSecretResponse', [result, secret])

View File

@ -1,59 +1,67 @@
from panda3d.core import *
from panda3d.otp import *
from direct.gui.DirectGui import *
from direct.directnotify import DirectNotifyGlobal
from direct.fsm import StateData
from otp.otpbase import OTPLocalizer
from direct.gui.DirectGui import *
from panda3d.core import *
from panda3d.otp import NametagGlobals
from otp.otpbase import OTPGlobals
from otp.otpbase import OTPLocalizer
from otp.uberdog import RejectCode
globalFriendSecret = None
AccountSecret = 0
AvatarSecret = 1
BothSecrets = 2
def showFriendSecret(secretType = AvatarSecret):
def showFriendSecret(secretType=AvatarSecret):
"""
Added optional parameter to offer the choice between account and avatar friend tokens.
"""
# A module function to open the global secret panel.
global globalFriendSecret
if not base.cr.isPaid():
# bring up teaser panel
chatMgr = base.localAvatar.chatMgr
chatMgr.fsm.request('trueFriendTeaserPanel')
chatMgr.fsm.request("trueFriendTeaserPanel")
elif not base.cr.isParentPasswordSet():
# non-COPPA gamecard user: prompt to leave game and set parent password
chatMgr = base.localAvatar.chatMgr
if base.cr.productName in ['DisneyOnline-AP',
'DisneyOnline-UK',
'JP',
'DE',
'BR',
'FR']:
if base.cr.productName in ['DisneyOnline-AP', 'DisneyOnline-UK', 'JP', 'DE', 'BR', 'FR']:
chatMgr = base.localAvatar.chatMgr
if not base.cr.isPaid():
chatMgr.fsm.request('unpaidChatWarning')
chatMgr.fsm.request("unpaidChatWarning")
else:
chatMgr.paidNoParentPassword = 1
chatMgr.fsm.request('unpaidChatWarning')
chatMgr.fsm.request("unpaidChatWarning")
else:
chatMgr.paidNoParentPassword = 1
chatMgr.fsm.request('noSecretChatAtAll')
chatMgr.fsm.request("noSecretChatAtAll") # bring up dialog for true friends # open chat with true friends
elif not base.cr.allowSecretChat():
# If we're paid but have not yet activated secrets, pop up the
# dialog to do this.
chatMgr = base.localAvatar.chatMgr
if base.cr.productName in ['DisneyOnline-AP',
'DisneyOnline-UK',
'JP',
'DE',
'BR',
'FR']:
if base.cr.productName in ['DisneyOnline-AP', 'DisneyOnline-UK', 'JP', 'DE', 'BR', 'FR']:
chatMgr = base.localAvatar.chatMgr
if not base.cr.isPaid():
chatMgr.fsm.request('unpaidChatWarning')
chatMgr.fsm.request("unpaidChatWarning")
else:
chatMgr.paidNoParentPassword = 1
chatMgr.fsm.request('unpaidChatWarning')
chatMgr.fsm.request("unpaidChatWarning")
else:
chatMgr.fsm.request('noSecretChatAtAll')
# we no longer offer the ability to enable chat in game
# chatMgr.fsm.request("noSecretChatWarning")
chatMgr.fsm.request("noSecretChatAtAll")
elif base.cr.needParentPasswordForSecretChat():
# If we're paid but have the flag set to require the Parent Password to be
# entered to get or use a Secret Friends password, pop up the
# dialog to get the Parent Password.
unloadFriendSecret()
globalFriendSecret = FriendSecretNeedsParentLogin(secretType)
globalFriendSecret.enter()
else:
# Otherwise, actually open the secrets panel.
openFriendSecret(secretType)
@ -63,53 +71,60 @@ def openFriendSecret(secretType):
globalFriendSecret.unload()
globalFriendSecret = FriendSecret(secretType)
globalFriendSecret.enter()
return
def hideFriendSecret():
# A module function to close the global secret panel if it is open.
if globalFriendSecret != None:
globalFriendSecret.exit()
return
def unloadFriendSecret():
# A module function to completely unload the global secret panel.
global globalFriendSecret
if globalFriendSecret != None:
globalFriendSecret.unload()
globalFriendSecret = None
return
class FriendSecretNeedsParentLogin(StateData.StateData):
notify = DirectNotifyGlobal.directNotify.newCategory('FriendSecretNeedsParentLogin')
notify = DirectNotifyGlobal.directNotify.newCategory("FriendSecretNeedsParentLogin")
def __init__(self, secretType):
StateData.StateData.__init__(self, 'friend-secret-needs-parent-login-done')
StateData.StateData.__init__(self, "friend-secret-needs-parent-login-done")
self.dialog = None
self.secretType = secretType
return
def enter(self):
StateData.StateData.enter(self)
base.localAvatar.chatMgr.fsm.request('otherDialog')
base.localAvatar.chatMgr.fsm.request("otherDialog")
# Pop up a dialog indicating the parent account needs to login
# in order to get to the Secret Friends chat:
if self.dialog == None:
guiButton = loader.loadModel('phase_3/models/gui/quit_button')
guiButton = loader.loadModel("phase_3/models/gui/quit_button")
buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui')
nameBalloon = loader.loadModel('phase_3/models/props/chatbox_input')
optionsButtonImage = (guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR'))
okButtonImage = (buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr'))
cancelButtonImage = (buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr'))
nameBalloon = loader.loadModel("phase_3/models/props/chatbox_input")
optionsButtonImage = (
guiButton.find("**/QuitBtn_UP"), guiButton.find("**/QuitBtn_DN"), guiButton.find("**/QuitBtn_RLVR"))
okButtonImage = (
buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr'))
cancelButtonImage = (
buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr'))
# The Castillian (and all foreign) version relies on a seperate parent
# password system. Omit the the password entry field and cancel button.
withParentAccount = False
try:
withParentAccount = base.cr.withParentAccount
except:
self.notify.warning('withParentAccount not found in base.cr')
self.notify.warning("withParentAccount not found in base.cr")
pass
if withParentAccount:
okPos = (-0.22, 0.0, -0.5)
textPos = (0, 0.25)
okCommand = self.__handleOKWithParentAccount
elif base.cr.productName != 'Terra-DMC':
elif base.cr.productName != "Terra-DMC":
okPos = (-0.22, 0.0, -0.5)
textPos = (0, 0.25)
okCommand = self.__oldHandleOK
@ -118,24 +133,48 @@ class FriendSecretNeedsParentLogin(StateData.StateData):
okPos = (0, 0, -0.35)
textPos = (0, 0.125)
okCommand = self.__handleCancel
self.dialog = DirectFrame(parent=aspect2dp, pos=(0.0, 0.1, 0.2), relief=None, image=DGG.getDefaultDialogGeom(), image_color=OTPGlobals.GlobalDialogColor, image_scale=(1.4, 1.0, 1.25), image_pos=(0, 0, -0.1), text=OTPLocalizer.FriendSecretNeedsParentLoginWarning, text_wordwrap=21.5, text_scale=0.055, text_pos=textPos, textMayChange=1)
DirectButton(self.dialog, image=okButtonImage, relief=None, text=OTPLocalizer.FriendSecretNeedsPasswordWarningOK, text_scale=0.05, text_pos=(0.0, -0.1), textMayChange=0, pos=okPos, command=okCommand)
DirectLabel(parent=self.dialog, relief=None, pos=(0, 0, 0.35), text=OTPLocalizer.FriendSecretNeedsPasswordWarningTitle, textMayChange=0, text_scale=0.08)
if base.cr.productName != 'Terra-DMC':
self.usernameLabel = DirectLabel(parent=self.dialog, relief=None, pos=(-0.07, 0.0, -0.1), text=OTPLocalizer.ParentLogin, text_scale=0.06, text_align=TextNode.ARight, textMayChange=0)
self.usernameEntry = DirectEntry(parent=self.dialog, relief=None, image=nameBalloon, image1_color=(0.8, 0.8, 0.8, 1.0), scale=0.064, pos=(0.0, 0.0, -0.1), width=OTPGlobals.maxLoginWidth, numLines=1, focus=1, cursorKeys=1, obscured=1, command=self.__handleUsername)
self.passwordLabel = DirectLabel(parent=self.dialog, relief=None, pos=(-0.02, 0.0, -0.3), text=OTPLocalizer.ParentPassword, text_scale=0.06, text_align=TextNode.ARight, textMayChange=0)
self.passwordEntry = DirectEntry(parent=self.dialog, relief=None, image=nameBalloon, image1_color=(0.8, 0.8, 0.8, 1.0), scale=0.064, pos=(0.04, 0.0, -0.3), width=OTPGlobals.maxLoginWidth, numLines=1, focus=1, cursorKeys=1, obscured=1, command=okCommand)
DirectButton(self.dialog, image=cancelButtonImage, relief=None, text=OTPLocalizer.FriendSecretNeedsPasswordWarningCancel, text_scale=0.05, text_pos=(0.0, -0.1), textMayChange=1, pos=(0.2, 0.0, -0.5), command=self.__handleCancel)
# make the common gui elements
self.dialog = DirectFrame(parent=aspect2dp, pos=(0.0, 0.1, 0.2), relief=None,
image=DGG.getDefaultDialogGeom(), image_color=OTPGlobals.GlobalDialogColor,
image_scale=(1.4, 1.0, 1.25), image_pos=(0, 0, -0.1),
text=OTPLocalizer.FriendSecretNeedsParentLoginWarning, text_wordwrap=21.5, text_scale=0.055,
text_pos=textPos, textMayChange=1)
DirectButton(self.dialog, image=okButtonImage, relief=None,
text=OTPLocalizer.FriendSecretNeedsPasswordWarningOK, text_scale=0.05, text_pos=(0.0, -0.1),
textMayChange=0, pos=okPos, command=okCommand)
DirectLabel(parent=self.dialog, relief=None, pos=(0, 0, 0.35),
text=OTPLocalizer.FriendSecretNeedsPasswordWarningTitle, textMayChange=0, text_scale=0.08)
# if not foreign, make the domestic only password entry elements
if base.cr.productName != "Terra-DMC":
self.usernameLabel = DirectLabel(parent=self.dialog, relief=None, pos=(-0.07, 0.0, -0.1),
text=OTPLocalizer.ParentLogin, text_scale=0.06, text_align=TextNode.ARight, textMayChange=0)
self.usernameEntry = DirectEntry(parent=self.dialog, relief=None, image=nameBalloon,
image1_color=(0.8, 0.8, 0.8, 1.0), scale=0.064, pos=(0.0, 0.0, -0.1),
width=OTPGlobals.maxLoginWidth, numLines=1, focus=1, cursorKeys=1, obscured=1,
command=self.__handleUsername)
self.passwordLabel = DirectLabel(parent=self.dialog, relief=None, pos=(-0.02, 0.0, -0.3),
text=OTPLocalizer.ParentPassword, text_scale=0.06, text_align=TextNode.ARight, textMayChange=0)
self.passwordEntry = DirectEntry(parent=self.dialog, relief=None, image=nameBalloon,
image1_color=(0.8, 0.8, 0.8, 1.0), scale=0.064, pos=(0.04, 0.0, -0.3),
width=OTPGlobals.maxLoginWidth, numLines=1, focus=1, cursorKeys=1, obscured=1, command=okCommand)
DirectButton(self.dialog, image=cancelButtonImage, relief=None,
text=OTPLocalizer.FriendSecretNeedsPasswordWarningCancel, text_scale=0.05, text_pos=(0.0, -0.1),
textMayChange=1, pos=(0.2, 0.0, -0.5), command=self.__handleCancel)
# hide the parent login as it's not valid yet
if withParentAccount:
self.usernameEntry.enterText('')
self.usernameEntry['focus'] = 1
self.passwordEntry.enterText('')
else:
self.usernameEntry.hide()
self.usernameLabel.hide()
self.passwordEntry['focus'] = 1
self.passwordEntry.enterText('')
guiButton.removeNode()
buttons.removeNode()
nameBalloon.removeNode()
@ -147,8 +186,8 @@ class FriendSecretNeedsParentLogin(StateData.StateData):
elif self.passwordEntry:
self.passwordEntry['focus'] = 1
self.passwordEntry.enterText('')
self.dialog.show()
return
def exit(self):
self.ignoreAll()
@ -156,11 +195,11 @@ class FriendSecretNeedsParentLogin(StateData.StateData):
self.dialog.destroy()
self.dialog = None
if self.isEntered:
base.localAvatar.chatMgr.fsm.request('mainMenu')
base.localAvatar.chatMgr.fsm.request("mainMenu")
StateData.StateData.exit(self)
return
def __handleUsername(self, *args):
# activate password entry
if self.passwordEntry:
self.passwordEntry['focus'] = 1
self.passwordEntry.enterText('')
@ -168,17 +207,29 @@ class FriendSecretNeedsParentLogin(StateData.StateData):
def __handleOKWithParentAccount(self, *args):
username = self.usernameEntry.get()
password = self.passwordEntry.get()
# we need to store these in base.cr for __enterSecret
base.cr.parentUsername = username
base.cr.parentPassword = password
tt = base.cr.loginInterface
okflag, message = tt.authenticateParentUsernameAndPassword(localAvatar.DISLid, base.cr.password, username, password)
try:
DISLIdFromLogin = base.cr.DISLIdFromLogin
except:
DISLIdFromLogin = 0
if DISLIdFromLogin and (DISLIdFromLogin != localAvatar.DISLid):
# we only expect to have 1 DISLId per player, we're screwed if this happens
self.notify.error(
"Mismatched DISLIds, fromLogin=%s, localAvatar.dislId=%s" % (DISLIdFromLogin, localAvatar.DISLid))
okflag, message = tt.authenticateParentUsernameAndPassword(localAvatar.DISLid, base.cr.password, username,
password)
if okflag:
self.exit()
openFriendSecret(self.secretType)
elif message:
base.localAvatar.chatMgr.fsm.request('problemActivatingChat')
base.localAvatar.chatMgr.problemActivatingChat['text'] = OTPLocalizer.ProblemActivatingChat % message
# Error connecting.
base.localAvatar.chatMgr.fsm.request("problemActivatingChat")
base.localAvatar.chatMgr.problemActivatingChat['text'] = OTPLocalizer.ProblemActivatingChat % (message)
else:
# Wrong password.
self.dialog['text'] = OTPLocalizer.FriendSecretNeedsPasswordWarningWrongPassword
self.passwordEntry['focus'] = 1
self.passwordEntry.enterText('')
@ -186,6 +237,7 @@ class FriendSecretNeedsParentLogin(StateData.StateData):
def __oldHandleOK(self, *args):
username = self.usernameEntry.get()
password = self.passwordEntry.get()
# we need to store these in base.cr for __enterSecret
base.cr.parentUsername = username
base.cr.parentPassword = password
tt = base.cr.loginInterface
@ -194,59 +246,83 @@ class FriendSecretNeedsParentLogin(StateData.StateData):
self.exit()
openFriendSecret(self.secretType)
elif message:
base.localAvatar.chatMgr.fsm.request('problemActivatingChat')
base.localAvatar.chatMgr.problemActivatingChat['text'] = OTPLocalizer.ProblemActivatingChat % message
# Error connecting.
base.localAvatar.chatMgr.fsm.request("problemActivatingChat")
base.localAvatar.chatMgr.problemActivatingChat['text'] = OTPLocalizer.ProblemActivatingChat % (message)
else:
# Wrong password.
self.dialog['text'] = OTPLocalizer.FriendSecretNeedsPasswordWarningWrongPassword
self.passwordEntry['focus'] = 1
self.passwordEntry.enterText('')
def __handleOK(self, *args):
base.cr.parentUsername = self.usernameEntry.get()
base.cr.parentPassword = self.passwordEntry.get()
# we don't have a request for this yet, so pretend we are submitting a limited secret
base.cr.playerFriendsManager.sendRequestUseLimitedSecret('', base.cr.parentUsername, base.cr.parentPassword)
self.accept(OTPGlobals.PlayerFriendRejectUseSecretEvent, self.__handleParentLogin)
# we won't get an answer yet, so spoof a return code
# self.__handleParentLogin(0)
# that doesn't work, just immediately close the panel
self.exit()
def __handleParentLogin(self, reason):
# don't know reason codes yet, spoof something
if reason == 0:
self.exit()
openFriendSecret(self.secretType)
elif reason == 1:
# Wrong username
self.dialog['text'] = OTPLocalizer.FriendSecretNeedsPasswordWarningWrongUsername
self.usernameEntry['focus'] = 1
self.usernameEntry.enterText('')
elif reason == 2:
# Wrong password
self.dialog['text'] = OTPLocalizer.FriendSecretNeedsPasswordWarningWrongPassword
self.passwordEntry['focus'] = 1
self.passwordEntry.enterText('')
else:
base.localAvatar.chatMgr.fsm.request('problemActivatingChat')
base.localAvatar.chatMgr.problemActivatingChat['text'] = OTPLocalizer.ProblemActivatingChat % message
# Error connecting (fall through case)
base.localAvatar.chatMgr.fsm.request("problemActivatingChat")
base.localAvatar.chatMgr.problemActivatingChat['text'] = OTPLocalizer.ProblemActivatingChat % (message)
def __handleCancel(self):
self.exit()
class FriendSecret(DirectFrame, StateData.StateData):
notify = DirectNotifyGlobal.directNotify.newCategory('FriendSecret')
"""
This is a panel that allows the user to manage 'secrets' that is,
code words that identify people who are actually friends in real
life (and thus are entitled to use full chat with each other).
This panel is the place the user will come to either get a new
'secret' to give to someone else, or to enter the 'secret' they
got from someone.
"""
notify = DirectNotifyGlobal.directNotify.newCategory("FriendSecret")
def __init__(self, secretType):
DirectFrame.__init__(self, parent=aspect2dp, pos=(0, 0, 0.3), relief=None, image=DGG.getDefaultDialogGeom(), image_scale=(1.6, 1, 1.4), image_pos=(0, 0, -0.05), image_color=OTPGlobals.GlobalDialogColor, borderWidth=(0.01, 0.01))
StateData.StateData.__init__(self, 'friend-secret-done')
DirectFrame.__init__(self, parent=aspect2dp, pos=(0, 0, 0.30), relief=None, image=DGG.getDefaultDialogGeom(),
image_scale=(1.6, 1, 1.4), image_pos=(0, 0, -0.05),
image_color=OTPGlobals.GlobalDialogColor, borderWidth=(0.01, 0.01), )
StateData.StateData.__init__(self, "friend-secret-done")
self.initialiseoptions(FriendSecret)
self.prefix = OTPGlobals.getDefaultProductPrefix()
# what types of secret friends will we offer
self.secretType = secretType
self.notify.debug('### secretType = %s' % self.secretType)
self.notify.debug("### secretType = %s" % self.secretType)
# what type of secret friend has the user chosen
self.requestedSecretType = secretType
self.notify.debug('### requestedSecretType = %s' % self.requestedSecretType)
return
self.notify.debug("### requestedSecretType = %s" % self.requestedSecretType)
def unload(self):
if self.isLoaded == 0:
return None
self.isLoaded = 0
self.exit()
del self.introText
del self.getSecret
del self.enterSecretText
@ -259,34 +335,48 @@ class FriendSecret(DirectFrame, StateData.StateData):
del self.accountButton
DirectFrame.destroy(self)
self.ignore('clientCleanup')
return None
def load(self):
if self.isLoaded == 1:
return None
self.isLoaded = 1
self.introText = DirectLabel(parent=self, relief=None, pos=(0, 0, 0.4), scale=0.05, text=OTPLocalizer.FriendSecretIntro, text_fg=(0, 0, 0, 1), text_wordwrap=30)
self.introText = DirectLabel(parent=self, relief=None, pos=(0, 0, 0.4), scale=0.05,
text=OTPLocalizer.FriendSecretIntro, text_fg=(0, 0, 0, 1), text_wordwrap=30, )
self.introText.hide()
guiButton = loader.loadModel('phase_3/models/gui/quit_button')
self.getSecret = DirectButton(parent=self, relief=None, pos=(0, 0, -0.11), image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=OTPLocalizer.FSgetSecret, text=OTPLocalizer.FriendSecretGetSecret, text_scale=OTPLocalizer.FSgetSecretButton, text_pos=(0, -0.02), command=self.__determineSecret)
guiButton = loader.loadModel("phase_3/models/gui/quit_button")
self.getSecret = DirectButton(parent=self, relief=None, pos=(0, 0, -0.11), image=(
guiButton.find("**/QuitBtn_UP"), guiButton.find("**/QuitBtn_DN"), guiButton.find("**/QuitBtn_RLVR"),),
image_scale=OTPLocalizer.FSgetSecret, text=OTPLocalizer.FriendSecretGetSecret,
text_scale=OTPLocalizer.FSgetSecretButton, text_pos=(0, -0.02), command=self.__determineSecret, )
self.getSecret.hide()
self.enterSecretText = DirectLabel(parent=self, relief=None, pos=OTPLocalizer.FSenterSecretTextPos, scale=0.05, text=OTPLocalizer.FriendSecretEnterSecret, text_fg=(0, 0, 0, 1), text_wordwrap=30)
self.enterSecretText = DirectLabel(parent=self, relief=None, pos=OTPLocalizer.FSenterSecretTextPos, scale=0.05,
text=OTPLocalizer.FriendSecretEnterSecret, text_fg=(0, 0, 0, 1), text_wordwrap=30, )
self.enterSecretText.hide()
self.enterSecret = DirectEntry(parent=self, relief=DGG.SUNKEN, scale=0.06, pos=(-0.6, 0, -0.38), frameColor=(0.8, 0.8, 0.5, 1), borderWidth=(0.1, 0.1), numLines=1, width=20, frameSize=(-0.4,
20.4,
-0.4,
1.1), command=self.__enterSecret)
self.enterSecret = DirectEntry(parent=self, relief=DGG.SUNKEN, scale=0.06, pos=(-0.60, 0, -0.38),
frameColor=(0.8, 0.8, 0.5, 1), borderWidth=(0.1, 0.1), numLines=1, width=20,
frameSize=(-0.4, 20.4, -0.4, 1.1), command=self.__enterSecret)
# This fixes a little problem with the initial frame size.
self.enterSecret.resetFrameSize()
self.enterSecret.hide()
self.ok1 = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=OTPLocalizer.FSok1, text=OTPLocalizer.FriendSecretEnter, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.5), command=self.__ok1)
self.ok1 = DirectButton(parent=self, relief=None, image=(
guiButton.find("**/QuitBtn_UP"), guiButton.find("**/QuitBtn_DN"), guiButton.find("**/QuitBtn_RLVR"),),
image_scale=OTPLocalizer.FSok1, text=OTPLocalizer.FriendSecretEnter, text_scale=0.06, text_pos=(0, -0.02),
pos=(0, 0, -0.5), command=self.__ok1, )
self.ok1.hide()
if base.cr.productName in ['JP',
'DE',
'BR',
'FR']:
if base.cr.productName in ['JP', 'DE', 'BR', 'FR']:
# There should be no 'change secret friends options' button in
# the UK version.
# the only thing we do to self.changeOptions is show and hide it;
# avoid adding a bunch of 'if' statements
class ShowHide:
def show(self):
pass
@ -294,16 +384,32 @@ class FriendSecret(DirectFrame, StateData.StateData):
pass
self.changeOptions = ShowHide()
self.ok2 = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=OTPLocalizer.FSok2, text=OTPLocalizer.FriendSecretOK, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.57), command=self.__ok2)
self.ok2 = DirectButton(parent=self, relief=None, image=(
guiButton.find("**/QuitBtn_UP"), guiButton.find("**/QuitBtn_DN"), guiButton.find("**/QuitBtn_RLVR"),),
image_scale=OTPLocalizer.FSok2, text=OTPLocalizer.FriendSecretOK, text_scale=0.06, text_pos=(0, -0.02),
pos=(0, 0, -0.57), command=self.__ok2, )
self.ok2.hide()
self.cancel = DirectButton(parent=self, relief=None, text=OTPLocalizer.FriendSecretCancel, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=OTPLocalizer.FScancel, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.57), command=self.__cancel)
self.cancel = DirectButton(parent=self, relief=None, text=OTPLocalizer.FriendSecretCancel, image=(
guiButton.find("**/QuitBtn_UP"), guiButton.find("**/QuitBtn_DN"), guiButton.find("**/QuitBtn_RLVR"),),
image_scale=OTPLocalizer.FScancel, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.57),
command=self.__cancel, )
self.cancel.hide()
self.nextText = DirectLabel(parent=self, relief=None, pos=(0, 0, 0.3), scale=0.06, text='', text_scale=OTPLocalizer.FSnextText, text_fg=(0, 0, 0, 1), text_wordwrap=25.5)
self.nextText = DirectLabel(parent=self, relief=None, pos=(0, 0, 0.30), scale=0.06, text="",
text_scale=OTPLocalizer.FSnextText, text_fg=(0, 0, 0, 1), text_wordwrap=25.5, )
self.nextText.hide()
self.secretText = DirectLabel(parent=self, relief=None, pos=(0, 0, -0.42), scale=0.1, text='', text_fg=(0, 0, 0, 1), text_wordwrap=30)
self.secretText = DirectLabel(parent=self, relief=None, pos=(0, 0, -0.42), scale=0.1, text="",
text_fg=(0, 0, 0, 1), text_wordwrap=30, )
self.secretText.hide()
guiButton.removeNode()
# moved into it's own method to make overloading easier
self.makeFriendTypeButtons()
self.accept('clientCleanup', self.__handleCleanup)
self.accept('walkDone', self.__handleStop)
@ -314,59 +420,100 @@ class FriendSecret(DirectFrame, StateData.StateData):
self.unload()
def makeFriendTypeButtons(self):
# NOTE: this uses generic text, if you want game-specific text, please inherit and override
# (see $TOONTOWN/src/friends/ToontownFriendSecret.py for an example)
buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui')
self.avatarButton = DirectButton(self, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), relief=None, text=OTPLocalizer.FriendSecretDetermineSecretAvatar, text_scale=0.07, text_pos=(0.0, -0.1), pos=(-0.35, 0.0, -0.05), command=self.__handleAvatar)
avatarText = DirectLabel(parent=self, relief=None, pos=Vec3(0.35, 0, -0.3), text=OTPLocalizer.FriendSecretDetermineSecretAvatarRollover, text_fg=(0, 0, 0, 1), text_pos=(0, 0), text_scale=0.055, text_align=TextNode.ACenter)
# make an avatar friend
self.avatarButton = DirectButton(self, image=(
buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')),
relief=None, text=OTPLocalizer.FriendSecretDetermineSecretAvatar, text_scale=0.07, text_pos=(0.0, -0.1),
pos=(-0.35, 0.0, -0.05), command=self.__handleAvatar)
# make a label to show avatar friend desc on rollover
avatarText = DirectLabel(parent=self, relief=None, pos=Vec3(0.35, 0, -0.3),
text=OTPLocalizer.FriendSecretDetermineSecretAvatarRollover, text_fg=(0, 0, 0, 1), text_pos=(0, 0),
text_scale=0.055, text_align=TextNode.ACenter, )
avatarText.reparentTo(self.avatarButton.stateNodePath[2])
self.avatarButton.hide()
self.accountButton = DirectButton(self, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), relief=None, text=OTPLocalizer.FriendSecretDetermineSecretAccount, text_scale=0.07, text_pos=(0.0, -0.1), pos=(0.35, 0.0, -0.05), command=self.__handleAccount)
accountText = DirectLabel(parent=self, relief=None, pos=Vec3(-0.35, 0, -0.3), text=OTPLocalizer.FriendSecretDetermineSecretAccountRollover, text_fg=(0, 0, 0, 1), text_pos=(0, 0), text_scale=0.055, text_align=TextNode.ACenter)
# make an account friend
self.accountButton = DirectButton(self, image=(
buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')),
relief=None, text=OTPLocalizer.FriendSecretDetermineSecretAccount, text_scale=0.07, text_pos=(0.0, -0.1),
pos=(0.35, 0.0, -0.05), command=self.__handleAccount)
# make a label to show feature desc on rollover
accountText = DirectLabel(parent=self, relief=None, pos=Vec3(-0.35, 0, -0.3),
text=OTPLocalizer.FriendSecretDetermineSecretAccountRollover, text_fg=(0, 0, 0, 1), text_pos=(0, 0),
text_scale=0.055, text_align=TextNode.ACenter, )
accountText.reparentTo(self.accountButton.stateNodePath[2])
self.accountButton.hide()
buttons.removeNode()
return
def enter(self):
if self.isEntered == 1:
return
self.isEntered = 1
# Use isLoaded to avoid redundant loading
if self.isLoaded == 0:
self.load()
self.show()
# Set us up on the first page.
self.introText.show()
self.getSecret.show()
self.enterSecretText.show()
self.enterSecret.show()
self.ok1.show()
self.ok2.hide()
self.cancel.hide()
self.nextText.hide()
self.secretText.hide()
base.localAvatar.chatMgr.fsm.request('otherDialog')
# While the entry's on the screen, we have to turn off the
# background focus on the normal chat entry. Otherwise,
# keypresses would start chatting!
base.localAvatar.chatMgr.fsm.request("otherDialog")
# And now we can set the focus on our entry.
self.enterSecret['focus'] = 1
# The secret panel uses up a lot of space onscreen; in
# particular, it will hide most of the chat balloons. Force
# these to go to the margins.
NametagGlobals.setOnscreenChatForced(1)
def exit(self):
if self.isEntered == 0:
return
self.isEntered = 0
# Restore the normal chat behavior.
NametagGlobals.setOnscreenChatForced(0)
self.__cleanupFirstPage()
self.ignoreAll()
self.accept('clientCleanup', self.unload)
self.hide()
def __determineSecret(self):
# If we support both types of secrets...
if self.secretType == BothSecrets:
# ask the player what type they want
self.__cleanupFirstPage()
self.ok1.hide()
# NOTE: this uses generic text, if you want game-specific text, please inherit and override
# (see $TOONTOWN/src/friends/ToontownFriendSecret.py for an example)
self.nextText['text'] = OTPLocalizer.FriendSecretDetermineSecret
self.nextText.setPos(0, 0, 0.3)
self.nextText.setPos(0, 0, 0.30)
self.nextText.show()
self.avatarButton.show()
self.accountButton.show()
self.cancel.show()
else:
# or just get the secret
self.__getSecret()
def __handleAvatar(self):
@ -383,39 +530,36 @@ class FriendSecret(DirectFrame, StateData.StateData):
def __getSecret(self):
self.__cleanupFirstPage()
self.nextText['text'] = OTPLocalizer.FriendSecretGettingSecret
self.nextText.setPos(0, 0, 0.3)
self.nextText.setPos(0, 0, 0.30)
self.nextText.show()
self.avatarButton.hide()
self.accountButton.hide()
self.ok1.hide()
self.cancel.show()
if self.requestedSecretType == AvatarSecret:
if not base.cr.friendManager:
self.notify.warning('No FriendManager available.')
self.exit()
return
base.cr.friendManager.up_requestSecret()
self.accept('requestSecretResponse', self.__gotAvatarSecret)
else:
if base.cr.needParentPasswordForSecretChat():
self.notify.info('### requestLimitedSecret')
base.cr.playerFriendsManager.sendRequestLimitedSecret(base.cr.parentUsername, base.cr.parentPassword)
else:
base.cr.playerFriendsManager.sendRequestUnlimitedSecret()
self.notify.info('### requestUnlimitedSecret')
self.accept(OTPGlobals.PlayerFriendNewSecretEvent, self.__gotAccountSecret)
self.accept(OTPGlobals.PlayerFriendRejectNewSecretEvent, self.__rejectAccountSecret)
# If we don't have a FriendManager, something's badly wrong.
# Most likely we're running in a development environment
# without an AI client.
if not base.cr.friendManager:
self.notify.warning("No FriendManager available.")
self.exit()
return
base.cr.friendManager.up_requestSecret()
self.accept('requestSecretResponse',
self.__gotAvatarSecret) # else: # if base.cr.needParentPasswordForSecretChat(): # self.notify.info("### requestLimitedSecret") # base.cr.playerFriendsManager.sendRequestLimitedSecret(base.cr.parentUsername, base.cr.parentPassword) # else: # base.cr.playerFriendsManager.sendRequestUnlimitedSecret() # self.notify.info("### requestUnlimitedSecret") # self.accept(OTPGlobals.PlayerFriendNewSecretEvent, self.__gotAccountSecret) # self.accept(OTPGlobals.PlayerFriendRejectNewSecretEvent, self.__rejectAccountSecret)
def __gotAvatarSecret(self, result, secret):
self.ignore('requestSecretResponse')
if result == 1:
self.nextText['text'] = OTPLocalizer.FriendSecretGotSecret
self.nextText.setPos(*OTPLocalizer.FSgotSecretPos)
if self.prefix:
self.secretText['text'] = self.prefix + ' ' + secret
else:
self.secretText['text'] = secret
# always append the prefix
self.secretText['text'] = self.prefix + ' ' + secret
elif result == 2:
self.nextText['text'] = OTPLocalizer.FriendSecretTooManyFriends
else:
# Oops, too many secrets.
self.nextText['text'] = OTPLocalizer.FriendSecretTooMany
self.nextText.show()
self.secretText.show()
@ -423,133 +567,148 @@ class FriendSecret(DirectFrame, StateData.StateData):
self.ok1.hide()
self.ok2.show()
def __gotAccountSecret(self, secret):
self.ignore(OTPGlobals.PlayerFriendNewSecretEvent)
self.ignore(OTPGlobals.PlayerFriendRejectNewSecretEvent)
self.nextText['text'] = OTPLocalizer.FriendSecretGotSecret
self.nextText.setPos(0, 0, 0.47)
self.secretText['text'] = secret
self.nextText.show()
self.secretText.show()
self.cancel.hide()
self.ok1.hide()
self.ok2.show()
def __rejectAccountSecret(self, reason):
print('## rejectAccountSecret: reason = ', reason)
self.ignore(OTPGlobals.PlayerFriendNewSecretEvent)
self.ignore(OTPGlobals.PlayerFriendRejectNewSecretEvent)
self.nextText['text'] = OTPLocalizer.FriendSecretTooMany
self.nextText.show()
self.secretText.show()
self.cancel.hide()
self.ok1.hide()
self.ok2.show()
def __enterSecret(self, secret):
self.enterSecret.set('')
# Empty the entry for next time.
self.enterSecret.set("")
secret = secret.strip()
if not secret:
# If the secret is empty, it just means to close down
# the dialog.
self.exit()
return
# If we don't have a FriendManager, something's badly wrong.
# Most likely we're running in a development environment
# without an AI client.
if not base.cr.friendManager:
self.notify.warning('No FriendManager available.')
self.notify.warning("No FriendManager available.")
self.exit()
return
self.__cleanupFirstPage()
# The client can now prepend a product prefix to all secrets - strip this off if present
if self.prefix:
if secret[0:2] == self.prefix:
secret = secret[3:]
self.notify.info('### use TT secret')
self.notify.info("### use TT secret")
self.accept('submitSecretResponse', self.__enteredSecret)
base.cr.friendManager.up_submitSecret(secret)
else:
self.accept(OTPGlobals.PlayerFriendUpdateEvent, self.__useAccountSecret)
self.accept(OTPGlobals.PlayerFriendRejectUseSecretEvent, self.__rejectUseAccountSecret)
if base.cr.needParentPasswordForSecretChat():
self.notify.info('### useLimitedSecret')
base.cr.playerFriendsManager.sendRequestUseLimitedSecret(secret, base.cr.parentUsername, base.cr.parentPassword)
else:
self.notify.info('### useUnlimitedSecret')
base.cr.playerFriendsManager.sendRequestUseUnlimitedSecret(secret)
self.nextText['text'] = OTPLocalizer.FriendSecretTryingSecret
self.nextText.setPos(0, 0, 0.3)
self.nextText.setPos(0, 0, 0.30)
self.nextText.show()
self.ok1.hide()
self.cancel.show()
def __enteredSecret(self, result, avId):
self.ignore('submitSecretResponse')
if result == 1:
# We made it!
handle = base.cr.identifyAvatar(avId)
if handle != None:
self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretSuccess % handle.getName()
self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretSuccess % (handle.getName())
else:
# Shoot. We just made friends with someone, but we
# don't know who it is yet. We'll have to ask the
# server who this is, and wait for the response before
# we can continue.
self.accept('friendsMapComplete', self.__nowFriends, [avId])
ready = base.cr.fillUpFriendsMap()
if ready:
self.__nowFriends(avId)
return
elif result == 0:
# Unknown secret.
self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretUnknown
elif result == 2:
# Friends list full.
handle = base.cr.identifyAvatar(avId)
if handle != None:
self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretFull % handle.getName()
self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretFull % (handle.getName())
else:
self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretFullNoName
elif result == 3:
# Self match.
self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretSelf
elif result == 4:
self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretWrongProduct % self.prefix
# This doesn't look like our secret friend code - wrong prefix
self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretWrongProduct % (self.prefix)
self.nextText.show()
self.cancel.hide()
self.ok1.hide()
self.ok2.show()
return
def __useAccountSecret(self, avId, friendInfo):
self.ignore(OTPGlobals.PlayerFriendUpdateEvent)
self.ignore(OTPGlobals.PlayerFriendRejectUseSecretEvent)
# todo - pass an avId?
self.__enteredSecret(1, 0)
def __rejectUseAccountSecret(self, reason):
print('## rejectUseAccountSecret: reason = ', reason)
print("## rejectUseAccountSecret: reason = ", reason)
self.ignore(OTPGlobals.PlayerFriendUpdateEvent)
self.ignore(OTPGlobals.PlayerFriendRejectUseSecretEvent)
if reason == RejectCode.RejectCode.FRIENDS_LIST_FULL:
if (reason == RejectCode.RejectCode.FRIENDS_LIST_FULL):
self.__enteredSecret(2, 0)
elif reason == RejectCode.RejectCode.ALREADY_FRIENDS_WITH_SELF:
elif (reason == RejectCode.RejectCode.ALREADY_FRIENDS_WITH_SELF):
self.__enteredSecret(3, 0)
else:
# todo: this shouldn't be the fall thru
self.__enteredSecret(0, 0)
def __nowFriends(self, avId):
# This is called only from enteredSecret(), after the friend
# transaction has completed. This will be called only if the
# client didn't know the identity of the friend at the time,
# but it should know now.
self.ignore('friendsMapComplete')
handle = base.cr.identifyAvatar(avId)
if handle != None:
self.nextText['text'] = OTPLocalizer.FriendSecretNowFriends % handle.getName()
self.nextText['text'] = OTPLocalizer.FriendSecretNowFriends % (handle.getName())
else:
# This really shouldn't be possible.
self.nextText['text'] = OTPLocalizer.FriendSecretNowFriendsNoName
self.nextText.show()
self.cancel.hide()
self.ok1.hide()
self.ok2.show()
return
def __ok1(self):
# Clicking "ok" from the front screen is the same thing as
# pressing Enter in the entry.
secret = self.enterSecret.get()
self.__enterSecret(secret)
def __ok2(self):
# Clicking "ok" from a finished screen just makes the thing go
# away.
self.exit()
def __cancel(self):
# Clicking "cancel" makes the panel close too.
self.exit()
def __cleanupFirstPage(self):
# Removes all the widgets etc. that were created for the
# welcome page, except the introText.
self.introText.hide()
self.getSecret.hide()
self.enterSecretText.hide()
self.enterSecret.hide()
base.localAvatar.chatMgr.fsm.request('mainMenu')
# Restore the background focus on the chat entry.
base.localAvatar.chatMgr.fsm.request("mainMenu")

View File

@ -5,7 +5,17 @@ from datetime import datetime
from direct.directnotify import DirectNotifyGlobal
from direct.distributed.DistributedObjectGlobalUD import DistributedObjectGlobalUD
from direct.distributed.PyDatagram import *
from direct.distributed.PyDatagram import PyDatagram
from direct.distributed.MsgTypes import (
CLIENTAGENT_ADD_POST_REMOVE,
CLIENTAGENT_CLEAR_POST_REMOVES,
CLIENTAGENT_CLOSE_CHANNEL,
CLIENTAGENT_EJECT,
CLIENTAGENT_OPEN_CHANNEL,
CLIENTAGENT_REMOVE_SESSION_OBJECT,
CLIENTAGENT_SET_CLIENT_ID,
STATESERVER_OBJECT_DELETE_RAM
)
from otp.otpbase import OTPGlobals

View File

@ -37,12 +37,14 @@ from toontown.hood.TTHoodDataAI import TTHoodDataAI
from toontown.pets.PetManagerAI import PetManagerAI
from toontown.quest.QuestManagerAI import QuestManagerAI
from toontown.racing import RaceGlobals
from toontown.fishing.DistributedFishingPondAI import DistributedFishingPondAI
from toontown.racing.DistributedLeaderBoardAI import DistributedLeaderBoardAI
from toontown.racing.DistributedRacePadAI import DistributedRacePadAI
from toontown.racing.DistributedStartingBlockAI import DistributedStartingBlockAI
from toontown.racing.DistributedStartingBlockAI import DistributedViewingBlockAI
from toontown.racing.DistributedViewPadAI import DistributedViewPadAI
from toontown.racing.RaceManagerAI import RaceManagerAI
from toontown.uberdog.DistributedPartyManagerAI import DistributedPartyManagerAI
from toontown.safezone.SafeZoneManagerAI import SafeZoneManagerAI
from toontown.shtiker.CogPageManagerAI import CogPageManagerAI
from toontown.spellbook.ToontownMagicWordManagerAI import ToontownMagicWordManagerAI
@ -95,6 +97,7 @@ class ToontownAIRepository(ToontownInternalRepository):
self.friendManager = None
self.toontownFriendsManager = None
self.estateMgr = None
self.partyManager = None
self.zoneTable = {}
self.dnaStoreMap = {}
self.dnaDataMap = {}
@ -242,6 +245,10 @@ class ToontownAIRepository(ToontownInternalRepository):
self.tutorialManager = TutorialManagerAI(self)
self.tutorialManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
# Generate our party manager...
self.partyManager = DistributedPartyManagerAI(self)
self.partyManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
def generateHood(self, hoodConstructor, zoneId):
# Bossbot HQ doesn't use DNA, so we skip over that.
if zoneId != ToontownGlobals.BossbotHQ:
@ -391,7 +398,29 @@ class ToontownAIRepository(ToontownInternalRepository):
return loadDNAFileAI(dnaStore, dnaFileName)
def findFishingPonds(self, dnaData, zoneId, area):
return [], [] # TODO
fishingPonds, fishingPondGroups = [], []
if "fishing_pond" in dnaData.getName():
fishingPondGroups.append(dnaData)
pond = DistributedFishingPondAI(self)
pond.setArea(area)
pond.generateWithRequired(zoneId)
fishingPonds.append(pond)
else:
if isinstance(dnaData, DNAVisGroup):
name = dnaData.getName()
visId = int(name.split(":", 1)[0]) % 1000
zoneId = ZoneUtil.getHoodId(zoneId) + visId
for i in range(dnaData.getNumChildren()):
foundFishingPonds, foundFishingPondGroups = self.findFishingPonds(dnaData.at(i), zoneId, area)
fishingPonds.extend(foundFishingPonds)
fishingPondGroups.extend(foundFishingPondGroups)
return fishingPonds, fishingPondGroups
def findFishingSpots(self, dnaData, pond):
return [] # TODO
def findPartyHats(self, dnaData, zoneId):
return [] # TODO
@ -518,6 +547,19 @@ class ToontownAIRepository(ToontownInternalRepository):
if __astron__:
self.toontownFriendsManager.sendRequestSecret(requesterId)
def submitSecret(self, avId, secret):
"""
avId: the avatar id of the friend who requested the secret
secret: the secret that was requested
Submits a secret that was previously requested.
Will submit through the friends manager.
When the secret is submitted, a "submitSecretReply" message will
be thrown with two parameters: the result code (0 or 1,
indicating failure or success), and the requesterId again.
"""
if __astron__:
self.toontownFriendsManager.sendSubmitSecret(avId, secret)
def setupFiles(self):
if not os.path.exists(self.dataFolder):
os.mkdir(self.dataFolder)

View File

@ -74,7 +74,8 @@ class BattleCalculatorAI:
return (1, 95)
else:
return (0, 0)
if self.toonsAlwaysHit:
toon = self.battle.getToon(attackIndex)
if self.toonsAlwaysHit or toon.instantKillMode:
return (1, 95)
elif self.toonsAlwaysMiss:
return (0, 0)
@ -529,6 +530,9 @@ class BattleCalculatorAI:
if attackLevel == -1 and not atkTrack == FIRE:
result = LURE_SUCCEEDED
elif atkTrack != TRAP:
toon = self.battle.getToon(toonId)
if atkTrack != HEAL and toon.instantKillMode:
attackDamage = 32767
result = attackDamage
if atkTrack == HEAL:
if not self.__attackHasHit(attack, suit=0):
@ -747,11 +751,15 @@ class BattleCalculatorAI:
toonId = self.toonAtkOrder[attackIndex]
attack = self.battle.toonAttacks[toonId]
atkTrack = self.__getActualTrack(attack)
TTOStyle = simbase.config.GetBool('want-tto-style-knockback', False)
if atkTrack == HEAL or atkTrack == PETSOS:
return
tgts = self.__createToonTargetList(toonId)
for currTgt in tgts:
tgtPos = self.battle.suits.index(currTgt)
if not TTOStyle:
tgtPos = self.battle.activeSuits.index(currTgt)
else:
tgtPos = self.battle.suits.index(currTgt)
attackerId = self.toonAtkOrder[attackIndex]
attack = self.battle.toonAttacks[attackerId]
track = self.__getActualTrack(attack)

View File

@ -324,12 +324,12 @@ class PropPool:
lips.setPos(0, 0, -3.04)
lips.flattenMedium()
elif name == '5dollar':
tex = loader.loadTexture('phase_5/maps/dollar_5.jpg')
tex = loader.loadTexture('phase_5/maps/dollar_5.png')
tex.setMinfilter(Texture.FTLinearMipmapLinear)
tex.setMagfilter(Texture.FTLinear)
self.props[name].setTexture(tex, 1)
elif name == '10dollar':
tex = loader.loadTexture('phase_5/maps/dollar_10.jpg')
tex = loader.loadTexture('phase_5/maps/dollar_10.png')
tex.setMinfilter(Texture.FTLinearMipmapLinear)
tex.setMagfilter(Texture.FTLinear)
self.props[name].setTexture(tex, 1)

File diff suppressed because it is too large Load Diff

View File

@ -98,10 +98,10 @@ def __createFishingPoleMultiTrack(lure, dollar, dollarName):
suitTrack.append(Func(suit.loop, 'neutral'))
suitTrack.append(Wait(3.5))
suitName = suit.getStyleName()
retardPos, retardHpr = battle.getActorPosHpr(suit)
retardPos.setY(retardPos.getY() + MovieUtil.SUIT_EXTRA_REACH_DISTANCE)
luredPos, luredHpr = battle.getActorPosHpr(suit)
luredPos.setY(luredPos.getY() + MovieUtil.SUIT_EXTRA_REACH_DISTANCE)
if suitName in MovieUtil.largeSuits:
moveTrack = lerpSuit(suit, 0.0, reachAnimDuration / 2.5, retardPos, battle, trapProp)
moveTrack = lerpSuit(suit, 0.0, reachAnimDuration / 2.5, luredPos, battle, trapProp)
reachTrack = ActorInterval(suit, 'reach', duration=reachAnimDuration)
suitTrack.append(Parallel(moveTrack, reachTrack))
else:

View File

@ -1,48 +1,66 @@
from toontown.toonbase.ToonBaseGlobal import *
from panda3d.core import *
from direct.interval.IntervalGlobal import *
from direct.distributed.ClockDelta import *
from toontown.toonbase import ToontownGlobals
from direct.directnotify import DirectNotifyGlobal
from direct.fsm import ClassicFSM, State
from direct.distributed import DistributedObject
from toontown.hood import ZoneUtil
from toontown.suit import Suit
from toontown.distributed import DelayDelete
from . import FADoorCodes
from direct.task.Task import Task
from . import DoorTypes
from toontown.toontowngui import TTDialog
from toontown.toonbase import TTLocalizer
from toontown.toontowngui import TeaserPanel
from toontown.distributed.DelayDeletable import DelayDeletable
if (__debug__):
import pdb
from panda3d.core import NodePath, Point3, VBase3, Vec3
from panda3d.otp import Nametag, NametagGroup
class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.distributed.ClockDelta import globalClockDelta
from direct.distributed.DistributedObject import DistributedObject
from direct.fsm.ClassicFSM import ClassicFSM
from direct.fsm.State import State
from direct.interval.IntervalGlobal import (
ActorInterval,
Func,
HprInterval,
LerpHprInterval,
LerpPosHprInterval,
LerpPosInterval,
Parallel,
PosHprInterval,
Sequence,
SoundInterval,
Wait
)
from direct.showbase.MessengerGlobal import messenger
from direct.task.TaskManagerGlobal import taskMgr
from toontown.building import DoorTypes
from toontown.building import FADoorCodes
from toontown.distributed.DelayDeletable import DelayDeletable
from toontown.distributed.DelayDelete import DelayDelete, cleanupDelayDeletes
from toontown.hood import ZoneUtil
from toontown.suit.Suit import Suit
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import TTLocalizer
from toontown.toonbase.ToonBaseGlobal import base
from toontown.toontowngui import TTDialog
from toontown.toontowngui.TeaserPanel import TeaserPanel
class DistributedDoor(DistributedObject, DelayDeletable):
notify = directNotify.newCategory('DistributedDoor')
def __init__(self, cr):
DistributedObject.DistributedObject.__init__(self, cr)
DistributedObject.__init__(self, cr)
self.openSfx = base.loader.loadSfx('phase_3.5/audio/sfx/Door_Open_1.ogg')
self.closeSfx = base.loader.loadSfx('phase_3.5/audio/sfx/Door_Close_1.ogg')
self.nametag = None
self.fsm = ClassicFSM.ClassicFSM('DistributedDoor_right', [State.State('off', self.enterOff, self.exitOff, ['closing',
self.fsm = ClassicFSM('DistributedDoor_right', [State('off', self.enterOff, self.exitOff, ['closing',
'closed',
'opening',
'open']),
State.State('closing', self.enterClosing, self.exitClosing, ['closed', 'opening']),
State.State('closed', self.enterClosed, self.exitClosed, ['opening']),
State.State('opening', self.enterOpening, self.exitOpening, ['open']),
State.State('open', self.enterOpen, self.exitOpen, ['closing', 'open'])], 'off', 'off')
State('closing', self.enterClosing, self.exitClosing, ['closed', 'opening']),
State('closed', self.enterClosed, self.exitClosed, ['opening']),
State('opening', self.enterOpening, self.exitOpening, ['open']),
State('open', self.enterOpen, self.exitOpen, ['closing', 'open'])], 'off', 'off')
self.fsm.enterInitialState()
self.exitDoorFSM = ClassicFSM.ClassicFSM('DistributedDoor_left', [State.State('off', self.exitDoorEnterOff, self.exitDoorExitOff, ['closing',
self.exitDoorFSM = ClassicFSM('DistributedDoor_left', [State('off', self.exitDoorEnterOff, self.exitDoorExitOff, ['closing',
'closed',
'opening',
'open']),
State.State('closing', self.exitDoorEnterClosing, self.exitDoorExitClosing, ['closed', 'opening']),
State.State('closed', self.exitDoorEnterClosed, self.exitDoorExitClosed, ['opening']),
State.State('opening', self.exitDoorEnterOpening, self.exitDoorExitOpening, ['open']),
State.State('open', self.exitDoorEnterOpen, self.exitDoorExitOpen, ['closing', 'open'])], 'off', 'off')
State('closing', self.exitDoorEnterClosing, self.exitDoorExitClosing, ['closed', 'opening']),
State('closed', self.exitDoorEnterClosed, self.exitDoorExitClosed, ['opening']),
State('opening', self.exitDoorEnterOpening, self.exitDoorExitOpening, ['open']),
State('open', self.exitDoorEnterOpen, self.exitDoorExitOpen, ['closing', 'open'])], 'off', 'off')
self.exitDoorFSM.enterInitialState()
self.specialDoorTypes = {DoorTypes.EXT_HQ: 0,
DoorTypes.EXT_COGHQ: 0,
@ -50,17 +68,15 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
DoorTypes.EXT_KS: 0,
DoorTypes.INT_KS: 0}
self.doorX = 1.5
return
def generate(self):
DistributedObject.DistributedObject.generate(self)
DistributedObject.generate(self)
self.avatarTracks = []
self.avatarExitTracks = []
self.avatarIDList = []
self.avatarExitIDList = []
self.doorTrack = None
self.doorExitTrack = None
return
def disable(self):
self.clearNametag()
@ -72,20 +88,22 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
self.exitDoorFSM.request('off')
if 'building' in self.__dict__:
del self.building
self.finishAllTracks()
self.avatarIDList = []
self.avatarExitIDList = []
if hasattr(self, 'tempDoorNodePath'):
self.tempDoorNodePath.removeNode()
del self.tempDoorNodePath
DistributedObject.DistributedObject.disable(self)
DistributedObject.disable(self)
def delete(self):
del self.fsm
del self.exitDoorFSM
del self.openSfx
del self.closeSfx
DistributedObject.DistributedObject.delete(self)
DistributedObject.delete(self)
def wantsNametag(self):
return not ZoneUtil.isInterior(self.zoneId)
@ -93,11 +111,13 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def setupNametag(self):
if not self.wantsNametag():
return
if self.nametag == None:
self.nametag = NametagGroup()
self.nametag.setFont(ToontownGlobals.getBuildingNametagFont())
if TTLocalizer.BuildingNametagShadow:
self.nametag.setShadow(*TTLocalizer.BuildingNametagShadow)
self.nametag.setContents(Nametag.CName)
self.nametag.setColorCode(NametagGroup.CCToonBuilding)
self.nametag.setActive(0)
@ -106,14 +126,12 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
name = self.cr.playGame.dnaStore.getTitleFromBlockNumber(self.block)
self.nametag.setName(name)
self.nametag.manage(base.marginManager)
return
def clearNametag(self):
if self.nametag != None:
self.nametag.unmanage(base.marginManager)
self.nametag.setAvatar(NodePath())
self.nametag = None
return
def getTriggerName(self):
if self.doorType == DoorTypes.INT_HQ or self.doorType in self.specialDoorTypes:
@ -137,26 +155,25 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
self.hideIfHasFlat(self.findDoorNode('leftDoor'))
self.findDoorNode('doorFrameHoleRight').hide()
self.findDoorNode('doorFrameHoleLeft').hide()
else:
return
def setTriggerName(self):
if self.doorType in self.specialDoorTypes:
building = self.getBuilding()
doorTrigger = building.find('**/door_' + str(self.doorIndex) + '/**/door_trigger*')
doorTrigger.node().setName(self.getTriggerName())
else:
return
def setTriggerName_wip(self):
building = self.getBuilding()
doorTrigger = building.find('**/door_%d/**/door_trigger_%d' % (self.doorIndex, self.block))
if doorTrigger.isEmpty():
doorTrigger = building.find('**/door_trigger_%d' % (self.block,))
if doorTrigger.isEmpty():
doorTrigger = building.find('**/door_%d/**/door_trigger_*' % (self.doorIndex,))
if doorTrigger.isEmpty():
doorTrigger = building.find('**/door_trigger_*')
doorTrigger.node().setName(self.getTriggerName())
def setZoneIdAndBlock(self, zoneId, block):
@ -185,7 +202,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
self.exitDoorFSM.request(state, [globalClockDelta.localElapsedTime(timestamp)])
def announceGenerate(self):
DistributedObject.DistributedObject.announceGenerate(self)
DistributedObject.announceGenerate(self)
self.doPostAnnounceGenerate()
def doPostAnnounceGenerate(self):
@ -193,6 +210,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
self.bHasFlat = True
else:
self.bHasFlat = not self.findDoorNode('door*flat', True).isEmpty()
self.hideDoorParts()
self.setTriggerName()
self.accept(self.getEnterTriggerEvent(), self.doorTrigger)
@ -202,13 +220,13 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def getBuilding(self):
if 'building' not in self.__dict__:
if self.doorType == DoorTypes.INT_STANDARD:
door = render.find('**/leftDoor;+s')
door = base.render.find('**/leftDoor;+s')
self.building = door.getParent()
elif self.doorType == DoorTypes.INT_HQ:
door = render.find('**/door_0')
door = base.render.find('**/door_0')
self.building = door.getParent()
elif self.doorType == DoorTypes.INT_KS:
self.building = render.find('**/KartShop_Interior*')
self.building = base.render.find('**/KartShop_Interior*')
elif self.doorType == DoorTypes.EXT_STANDARD or self.doorType == DoorTypes.EXT_HQ or self.doorType == DoorTypes.EXT_KS:
self.building = self.cr.playGame.hood.loader.geom.find('**/??' + str(self.block) + ':*_landmark_*_DNARoot;+s')
if self.building.isEmpty():
@ -217,6 +235,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
self.building = self.cr.playGame.hood.loader.geom
else:
self.notify.error('No such door type as ' + str(self.doorType))
return self.building
def getBuilding_wip(self):
@ -226,6 +245,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
else:
self.building = self.cr.playGame.hood.loader.geom
print('---------------- door is interior -------')
return self.building
def readyToExit(self):
@ -238,33 +258,38 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
otherNP = self.getDoorNodePath()
if hasattr(avatar, 'stopSmooth'):
avatar.stopSmooth()
if avatar.doId == base.localAvatar.doId:
track.append(LerpPosHprInterval(nodePath=camera, other=avatar, duration=duration, pos=Point3(0, -8, avatar.getHeight()), hpr=VBase3(0, 0, 0), blendType='easeInOut'))
track.append(LerpPosHprInterval(nodePath=base.camera, other=avatar, duration=duration, pos=Point3(0, -8, avatar.getHeight()), hpr=VBase3(0, 0, 0), blendType='easeInOut'))
finalPos = avatar.getParent().getRelativePoint(otherNP, Point3(self.doorX, 2, ToontownGlobals.FloorOffset))
moveHere = Sequence(self.getAnimStateInterval(avatar, 'walk'), LerpPosInterval(nodePath=avatar, duration=duration, pos=finalPos, blendType='easeIn'))
track.append(moveHere)
if avatar.doId == base.localAvatar.doId:
track.append(Sequence(Wait(duration * 0.5), Func(base.transitions.irisOut, duration * 0.5), Wait(duration * 0.5), Func(avatar.b_setParent, ToontownGlobals.SPHidden)))
track.delayDelete = DelayDelete.DelayDelete(avatar, 'avatarEnterDoorTrack')
track.delayDelete = DelayDelete(avatar, 'avatarEnterDoorTrack')
return track
def avatarEnqueueTrack(self, avatar, duration):
if hasattr(avatar, 'stopSmooth'):
avatar.stopSmooth()
back = -5.0 - 2.0 * len(self.avatarIDList)
if back < -9.0:
back = -9.0
offset = Point3(self.doorX, back, ToontownGlobals.FloorOffset)
otherNP = self.getDoorNodePath()
walkLike = ActorInterval(avatar, 'walk', startTime=1, duration=duration, endTime=0.0001)
standHere = Sequence(LerpPosHprInterval(nodePath=avatar, other=otherNP, duration=duration, pos=offset, hpr=VBase3(0, 0, 0), blendType='easeInOut'), self.getAnimStateInterval(avatar, 'neutral'))
trackName = 'avatarEnqueueDoor-%d-%d' % (self.doId, avatar.doId)
track = Parallel(walkLike, standHere, name=trackName)
track.delayDelete = DelayDelete.DelayDelete(avatar, 'avatarEnqueueTrack')
track.delayDelete = DelayDelete(avatar, 'avatarEnqueueTrack')
return track
def getAnimStateInterval(self, avatar, animName):
isSuit = isinstance(avatar, Suit.Suit)
isSuit = isinstance(avatar, Suit)
if isSuit:
return Func(avatar.loop, animName, 0)
else:
@ -284,7 +309,8 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
place = base.cr.playGame.getPlace()
if place:
place.fsm.request('stopped')
self.dialog = TeaserPanel.TeaserPanel(pageName='otherHoods', doneFunc=self.handleOkTeaser)
self.dialog = TeaserPanel(pageName='otherHoods', doneFunc=self.handleOkTeaser)
def handleOkTeaser(self):
self.accept(self.getEnterTriggerEvent(), self.doorTrigger)
@ -301,6 +327,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
allowed = base.ttAccess.canAccess(zoneId)
else:
allowed = base.ttAccess.canAccess()
return allowed
def checkIsDoorHitTaskName(self):
@ -311,8 +338,9 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
self.ignore(self.checkIsDoorHitTaskName())
self.ignore(self.getExitTriggerEvent())
self.enterDoor()
return Task.done
return Task.cont
return task.done
return task.cont
def cancelCheckIsDoorHitTask(self, args):
taskMgr.remove(self.checkIsDoorHitTaskName())
@ -333,7 +361,6 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
else:
self.accept(self.getExitTriggerEvent(), self.cancelCheckIsDoorHitTask)
taskMgr.add(self.checkIsDoorHitTask, self.checkIsDoorHitTaskName())
return
def avatarEnter(self, avatarID):
avatar = self.cr.doId2do.get(avatarID, None)
@ -343,7 +370,6 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
track.start()
self.avatarTracks.append(track)
self.avatarIDList.append(avatarID)
return
def rejectEnter(self, reason):
message = FADoorCodes.reasonDict[reason]
@ -360,7 +386,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def __faRejectEnter(self, message):
self.rejectDialog = TTDialog.TTGlobalDialog(message=message, doneEvent='doorRejectAck', style=TTDialog.Acknowledge)
self.rejectDialog.show()
self.rejectDialog.delayDelete = DelayDelete.DelayDelete(self, '__faRejectEnter')
self.rejectDialog.delayDelete = DelayDelete(self, '__faRejectEnter')
event = 'clientCleanup'
self.acceptOnce(event, self.__handleClientCleanup)
base.cr.playGame.getPlace().setState('stopped')
@ -370,6 +396,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def __handleClientCleanup(self):
if hasattr(self, 'rejectDialog') and self.rejectDialog:
self.rejectDialog.doneStatus = 'ok'
self.__handleRejectAck()
def __handleFallAsleepDoor(self):
@ -383,6 +410,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
doneStatus = self.rejectDialog.doneStatus
if doneStatus != 'ok':
self.notify.error('Unrecognized doneStatus: ' + str(doneStatus))
self.__basicRejectEnter()
self.rejectDialog.delayDelete.destroy()
self.rejectDialog.cleanup()
@ -390,7 +418,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def getDoorNodePath(self):
if self.doorType == DoorTypes.INT_STANDARD:
otherNP = render.find('**/door_origin')
otherNP = base.render.find('**/door_origin')
elif self.doorType == DoorTypes.EXT_STANDARD:
if hasattr(self, 'tempDoorNodePath'):
return self.tempDoorNodePath
@ -404,14 +432,16 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
building = self.getBuilding()
otherNP = building.find('**/door_origin_' + str(self.doorIndex))
elif self.doorType == DoorTypes.INT_HQ:
otherNP = render.find('**/door_origin_' + str(self.doorIndex))
otherNP = base.render.find('**/door_origin_' + str(self.doorIndex))
else:
self.notify.error('No such door type as ' + str(self.doorType))
return otherNP
def avatarExitTrack(self, avatar, duration):
if hasattr(avatar, 'stopSmooth'):
avatar.stopSmooth()
otherNP = self.getDoorNodePath()
trackName = 'avatarExitDoor-%d-%d' % (self.doId, avatar.doId)
track = Sequence(name=trackName)
@ -419,18 +449,22 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
track.append(PosHprInterval(avatar, Point3(-self.doorX, 0, ToontownGlobals.FloorOffset), VBase3(179, 0, 0), other=otherNP))
track.append(Func(avatar.setParent, ToontownGlobals.SPRender))
if avatar.doId == base.localAvatar.doId:
track.append(PosHprInterval(camera, VBase3(-self.doorX, 5, avatar.getHeight()), VBase3(180, 0, 0), other=otherNP))
track.append(PosHprInterval(base.camera, VBase3(-self.doorX, 5, avatar.getHeight()), VBase3(180, 0, 0), other=otherNP))
if avatar.doId == base.localAvatar.doId:
finalPos = render.getRelativePoint(otherNP, Point3(-self.doorX, -6, ToontownGlobals.FloorOffset))
finalPos = base.render.getRelativePoint(otherNP, Point3(-self.doorX, -6, ToontownGlobals.FloorOffset))
else:
finalPos = render.getRelativePoint(otherNP, Point3(-self.doorX, -3, ToontownGlobals.FloorOffset))
finalPos = base.render.getRelativePoint(otherNP, Point3(-self.doorX, -3, ToontownGlobals.FloorOffset))
track.append(LerpPosInterval(nodePath=avatar, duration=duration, pos=finalPos, blendType='easeInOut'))
if avatar.doId == base.localAvatar.doId:
track.append(Func(self.exitCompleted))
track.append(Func(base.transitions.irisIn))
if hasattr(avatar, 'startSmooth'):
track.append(Func(avatar.startSmooth))
track.delayDelete = DelayDelete.DelayDelete(avatar, 'DistributedDoor.avatarExitTrack')
track.delayDelete = DelayDelete(avatar, 'DistributedDoor.avatarExitTrack')
return track
def exitCompleted(self):
@ -438,6 +472,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
place = self.cr.playGame.getPlace()
if place:
place.setState('walk')
base.localAvatar.d_setParent(ToontownGlobals.SPRender)
def avatarExit(self, avatarID):
@ -451,26 +486,26 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def finishDoorTrack(self):
if self.doorTrack:
self.doorTrack.finish()
self.doorTrack = None
return
def finishDoorExitTrack(self):
if self.doorExitTrack:
self.doorExitTrack.finish()
self.doorExitTrack = None
return
def finishAllTracks(self):
self.finishDoorTrack()
self.finishDoorExitTrack()
for t in self.avatarTracks:
t.finish()
DelayDelete.cleanupDelayDeletes(t)
cleanupDelayDeletes(t)
self.avatarTracks = []
for t in self.avatarExitTracks:
t.finish()
DelayDelete.cleanupDelayDeletes(t)
cleanupDelayDeletes(t)
self.avatarExitTracks = []
@ -498,16 +533,19 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
if doorFrameHoleRight.isEmpty():
self.notify.warning('enterClosing(): did not find doorFrameHoleRight')
return
rightDoor = self.findDoorNode('rightDoor')
if rightDoor.isEmpty():
self.notify.warning('enterClosing(): did not find rightDoor')
return
otherNP = self.getDoorNodePath()
trackName = 'doorClose-%d' % self.doId
if self.rightSwing:
h = 100
else:
h = -100
self.finishDoorTrack()
self.doorTrack = Sequence(LerpHprInterval(nodePath=rightDoor, duration=1.0, hpr=VBase3(0, 0, 0), startHpr=VBase3(h, 0, 0), other=otherNP, blendType='easeInOut'), Func(doorFrameHoleRight.hide), Func(self.hideIfHasFlat, rightDoor), SoundInterval(self.closeSfx, node=rightDoor), name=trackName)
self.doorTrack.start(ts)
@ -529,16 +567,19 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
if doorFrameHoleRight.isEmpty():
self.notify.warning('enterOpening(): did not find doorFrameHoleRight')
return
rightDoor = self.findDoorNode('rightDoor')
if rightDoor.isEmpty():
self.notify.warning('enterOpening(): did not find rightDoor')
return
otherNP = self.getDoorNodePath()
trackName = 'doorOpen-%d' % self.doId
if self.rightSwing:
h = 100
else:
h = -100
self.finishDoorTrack()
self.doorTrack = Parallel(SoundInterval(self.openSfx, node=rightDoor), Sequence(HprInterval(rightDoor, VBase3(0, 0, 0), other=otherNP), Wait(0.4), Func(rightDoor.show), Func(doorFrameHoleRight.show), LerpHprInterval(nodePath=rightDoor, duration=0.6, hpr=VBase3(h, 0, 0), startHpr=VBase3(0, 0, 0), other=otherNP, blendType='easeInOut')), name=trackName)
self.doorTrack.start(ts)
@ -553,6 +594,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
track = self.avatarEnterDoorTrack(avatar, 1.0)
track.start(ts)
self.avatarTracks.append(track)
if avatarID == base.localAvatar.doId:
self.done = 1
@ -561,7 +603,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def exitOpen(self):
for track in self.avatarTracks:
track.finish()
DelayDelete.cleanupDelayDeletes(track)
cleanupDelayDeletes(track)
self.avatarTracks = []
@ -576,10 +618,12 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
if doorFrameHoleLeft.isEmpty():
self.notify.warning('enterOpening(): did not find flatDoors')
return
if self.leftSwing:
h = -100
else:
h = 100
leftDoor = self.findDoorNode('leftDoor')
if not leftDoor.isEmpty():
otherNP = self.getDoorNodePath()
@ -602,11 +646,13 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
if doorFrameHoleLeft.isEmpty():
self.notify.warning('enterOpening(): did not find flatDoors')
return
leftDoor = self.findDoorNode('leftDoor')
if self.leftSwing:
h = -100
else:
h = 100
if not leftDoor.isEmpty():
otherNP = self.getDoorNodePath()
trackName = 'doorDoorExitTrack-%d' % self.doId
@ -632,7 +678,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def exitDoorExitOpen(self):
for track in self.avatarExitTracks:
track.finish()
DelayDelete.cleanupDelayDeletes(track)
cleanupDelayDeletes(track)
self.avatarExitTracks = []
@ -645,8 +691,10 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
foundNode = building.find('**/door_' + str(self.doorIndex) + '/**/' + string + '*;+s+i')
if foundNode.isEmpty():
foundNode = building.find('**/' + string + '*;+s+i')
if allowEmpty:
return foundNode
return foundNode
def hideIfHasFlat(self, node):

View File

@ -1,19 +1,24 @@
from toontown.toonbase.ToonBaseGlobal import *
from panda3d.core import *
from panda3d.toontown import *
from toontown.toonbase.ToontownGlobals import *
import random
from direct.task.Task import Task
from direct.distributed import DistributedObject
from direct.directnotify import DirectNotifyGlobal
from . import ToonInteriorColors
import pickle
from toontown.toonbase import TTLocalizer
from panda3d.core import ModelNode, NodePath, TextNode
from panda3d.toontown import DNADoor
class DistributedHQInterior(DistributedObject.DistributedObject):
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.distributed.DistributedObject import DistributedObject
from direct.task.TaskManagerGlobal import taskMgr
from toontown.building import ToonInteriorColors
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import TTLocalizer
from toontown.toonbase.ToonBaseGlobal import base
import pickle
from random import Random
class DistributedHQInterior(DistributedObject):
notify = directNotify.newCategory('DistributedHQInterior')
def __init__(self, cr):
DistributedObject.DistributedObject.__init__(self, cr)
DistributedObject.__init__(self, cr)
self.dnaStore = cr.playGame.dnaStore
self.leaderAvIds = []
self.leaderNames = []
@ -22,15 +27,15 @@ class DistributedHQInterior(DistributedObject.DistributedObject):
self.tutorial = 0
def generate(self):
DistributedObject.DistributedObject.generate(self)
self.interior = loader.loadModel('phase_3.5/models/modules/HQ_interior')
self.interior.reparentTo(render)
DistributedObject.generate(self)
self.interior = base.loader.loadModel('phase_3.5/models/modules/HQ_interior')
self.interior.reparentTo(base.render)
self.interior.find('**/cream').hide()
self.interior.find('**/crashed_piano').hide()
self.buildLeaderBoard()
def announceGenerate(self):
DistributedObject.DistributedObject.announceGenerate(self)
DistributedObject.announceGenerate(self)
self.setupDoors()
self.interior.flattenMedium()
emptyBoard = self.interior.find('**/empty_board')
@ -41,6 +46,7 @@ class DistributedHQInterior(DistributedObject.DistributedObject):
return
else:
self.tutorial = flag
if self.tutorial:
self.interior.find('**/periscope').hide()
self.interior.find('**/speakers').hide()
@ -53,7 +59,7 @@ class DistributedHQInterior(DistributedObject.DistributedObject):
self.block = block
def buildLeaderBoard(self):
self.leaderBoard = hidden.attachNewNode('leaderBoard')
self.leaderBoard = base.hidden.attachNewNode('leaderBoard')
self.leaderBoard.setPosHprScale(0.1, 0, 4.5, 90, 0, 0, 0.9, 0.9, 0.9)
z = 0
row = self.buildTitleRow()
@ -63,7 +69,7 @@ class DistributedHQInterior(DistributedObject.DistributedObject):
self.nameTextNodes = []
self.scoreTextNodes = []
self.trophyStars = []
for i in range(self.numLeaders):
for _ in range(self.numLeaders):
row, nameText, scoreText, trophyStar = self.buildLeaderRow()
self.nameTextNodes.append(nameText)
self.scoreTextNodes.append(scoreText)
@ -87,7 +93,7 @@ class DistributedHQInterior(DistributedObject.DistributedObject):
self.trophyStars[i].hide()
def buildTitleRow(self):
row = hidden.attachNewNode('leaderRow')
row = base.hidden.attachNewNode('leaderRow')
nameText = TextNode('titleRow')
nameText.setFont(ToontownGlobals.getSignFont())
nameText.setAlign(TextNode.ACenter)
@ -98,7 +104,7 @@ class DistributedHQInterior(DistributedObject.DistributedObject):
return row
def buildLeaderRow(self):
row = hidden.attachNewNode('leaderRow')
row = base.hidden.attachNewNode('leaderRow')
nameText = TextNode('nameText')
nameText.setFont(ToontownGlobals.getToonFont())
nameText.setAlign(TextNode.ALeft)
@ -135,15 +141,16 @@ class DistributedHQInterior(DistributedObject.DistributedObject):
doorModelName = doorModelName[:-1] + 'l'
else:
doorModelName = doorModelName[:-1] + 'r'
door = self.dnaStore.findNode(doorModelName)
return door
def setupDoors(self):
self.randomGenerator = random.Random()
self.randomGenerator = Random()
self.randomGenerator.seed(self.zoneId)
self.colors = ToonInteriorColors.colors[ToontownCentral]
self.colors = ToonInteriorColors.colors[ToontownGlobals.ToontownCentral]
door = self.chooseDoor()
doorOrigins = render.findAllMatches('**/door_origin*')
doorOrigins = base.render.findAllMatches('**/door_origin*')
numDoorOrigins = doorOrigins.getNumPaths()
for npIndex in range(numDoorOrigins):
doorOrigin = doorOrigins[npIndex]
@ -173,10 +180,10 @@ class DistributedHQInterior(DistributedObject.DistributedObject):
del self.scoreTextNodes
del self.trophyStars
taskMgr.remove(self.uniqueName('starSpinHQ'))
DistributedObject.DistributedObject.disable(self)
DistributedObject.disable(self)
def buildTrophyStar(self):
trophyStar = loader.loadModel('phase_3.5/models/gui/name_star')
trophyStar = base.loader.loadModel('phase_3.5/models/gui/name_star')
trophyStar.hide()
trophyStar.setPos(*TTLocalizer.DHQItrophyStarPos)
return trophyStar
@ -211,7 +218,7 @@ class DistributedHQInterior(DistributedObject.DistributedObject):
trophyStar.hide()
def __starSpin(self, task):
now = globalClock.getFrameTime()
now = base.clock.getFrameTime()
r = now * task.trophyStarSpeed % 360.0
task.trophyStar.setR(r)
return Task.cont
return task.cont

View File

@ -1,3 +1,4 @@
from panda3d.core import *
from panda3d.toontown import *
from toontown.toonbase.ToonBaseGlobal import *
from direct.interval.IntervalGlobal import *

View File

@ -1,31 +1,33 @@
from panda3d.core import *
from toontown.toonbase.ToonBaseGlobal import *
from direct.directnotify import DirectNotifyGlobal
from toontown.hood import Place
from toontown.hood import ZoneUtil
from direct.showbase import DirectObject
from direct.fsm import StateData
from direct.fsm import ClassicFSM, State
from direct.fsm import State
from direct.task import Task
from otp.distributed.TelemetryLimiter import RotationLimitToH, TLGatherAllAvs
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import TTLocalizer
from toontown.toon import NPCForceAcknowledge
from toontown.toon import HealthForceAcknowledge
from panda3d.core import ModelPool, TexturePool
from panda3d.otp import NametagGlobals
class ToonInterior(Place.Place):
notify = DirectNotifyGlobal.directNotify.newCategory('ToonInterior')
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.fsm.ClassicFSM import ClassicFSM
from direct.fsm.State import State
from direct.showbase.MessengerGlobal import messenger
from otp.distributed.TelemetryLimiter import RotationLimitToH, TLGatherAllAvs
from toontown.hood import ZoneUtil
from toontown.hood.Place import Place
from toontown.toon.HealthForceAcknowledge import HealthForceAcknowledge
from toontown.toon.NPCForceAcknowledge import NPCForceAcknowledge
from toontown.toonbase import ToontownGlobals
from toontown.toonbase.ToonBaseGlobal import base
class ToonInterior(Place):
notify = directNotify.newCategory('ToonInterior')
def __init__(self, loader, parentFSMState, doneEvent):
Place.Place.__init__(self, loader, doneEvent)
Place.__init__(self, loader, doneEvent)
self.dnaFile = 'phase_7/models/modules/toon_interior'
self.isInterior = 1
self.tfaDoneEvent = 'tfaDoneEvent'
self.hfaDoneEvent = 'hfaDoneEvent'
self.npcfaDoneEvent = 'npcfaDoneEvent'
self.fsm = ClassicFSM.ClassicFSM('ToonInterior', [State.State('start', self.enterStart, self.exitStart, ['doorIn', 'teleportIn', 'tutorial']),
State.State('walk', self.enterWalk, self.exitWalk, ['sit',
self.fsm = ClassicFSM('ToonInterior', [State('start', self.enterStart, self.exitStart, ['doorIn', 'teleportIn', 'tutorial']),
State('walk', self.enterWalk, self.exitWalk, ['sit',
'stickerBook',
'doorOut',
'DFA',
@ -36,8 +38,8 @@ class ToonInterior(Place.Place):
'phone',
'stopped',
'pet']),
State.State('sit', self.enterSit, self.exitSit, ['walk']),
State.State('stickerBook', self.enterStickerBook, self.exitStickerBook, ['walk',
State('sit', self.enterSit, self.exitSit, ['walk']),
State('stickerBook', self.enterStickerBook, self.exitStickerBook, ['walk',
'DFA',
'trialerFA',
'sit',
@ -48,37 +50,37 @@ class ToonInterior(Place.Place):
'phone',
'stopped',
'pet']),
State.State('trialerFA', self.enterTrialerFA, self.exitTrialerFA, ['trialerFAReject', 'DFA']),
State.State('trialerFAReject', self.enterTrialerFAReject, self.exitTrialerFAReject, ['walk']),
State.State('DFA', self.enterDFA, self.exitDFA, ['DFAReject',
State('trialerFA', self.enterTrialerFA, self.exitTrialerFA, ['trialerFAReject', 'DFA']),
State('trialerFAReject', self.enterTrialerFAReject, self.exitTrialerFAReject, ['walk']),
State('DFA', self.enterDFA, self.exitDFA, ['DFAReject',
'HFA',
'NPCFA',
'teleportOut',
'doorOut']),
State.State('DFAReject', self.enterDFAReject, self.exitDFAReject, ['walk']),
State.State('NPCFA', self.enterNPCFA, self.exitNPCFA, ['NPCFAReject', 'HFA', 'teleportOut']),
State.State('NPCFAReject', self.enterNPCFAReject, self.exitNPCFAReject, ['walk']),
State.State('HFA', self.enterHFA, self.exitHFA, ['HFAReject', 'teleportOut', 'tunnelOut']),
State.State('HFAReject', self.enterHFAReject, self.exitHFAReject, ['walk']),
State.State('doorIn', self.enterDoorIn, self.exitDoorIn, ['walk']),
State.State('doorOut', self.enterDoorOut, self.exitDoorOut, ['walk', 'stopped']),
State.State('teleportIn', self.enterTeleportIn, self.exitTeleportIn, ['walk']),
State.State('teleportOut', self.enterTeleportOut, self.exitTeleportOut, ['teleportIn']),
State.State('quest', self.enterQuest, self.exitQuest, ['walk', 'doorOut']),
State.State('tutorial', self.enterTutorial, self.exitTutorial, ['walk', 'quest']),
State.State('purchase', self.enterPurchase, self.exitPurchase, ['walk', 'doorOut']),
State.State('pet', self.enterPet, self.exitPet, ['walk']),
State.State('phone', self.enterPhone, self.exitPhone, ['walk', 'doorOut']),
State.State('stopped', self.enterStopped, self.exitStopped, ['walk', 'doorOut']),
State.State('final', self.enterFinal, self.exitFinal, ['start'])], 'start', 'final')
State('DFAReject', self.enterDFAReject, self.exitDFAReject, ['walk']),
State('NPCFA', self.enterNPCFA, self.exitNPCFA, ['NPCFAReject', 'HFA', 'teleportOut']),
State('NPCFAReject', self.enterNPCFAReject, self.exitNPCFAReject, ['walk']),
State('HFA', self.enterHFA, self.exitHFA, ['HFAReject', 'teleportOut', 'tunnelOut']),
State('HFAReject', self.enterHFAReject, self.exitHFAReject, ['walk']),
State('doorIn', self.enterDoorIn, self.exitDoorIn, ['walk']),
State('doorOut', self.enterDoorOut, self.exitDoorOut, ['walk', 'stopped']),
State('teleportIn', self.enterTeleportIn, self.exitTeleportIn, ['walk']),
State('teleportOut', self.enterTeleportOut, self.exitTeleportOut, ['teleportIn']),
State('quest', self.enterQuest, self.exitQuest, ['walk', 'doorOut']),
State('tutorial', self.enterTutorial, self.exitTutorial, ['walk', 'quest']),
State('purchase', self.enterPurchase, self.exitPurchase, ['walk', 'doorOut']),
State('pet', self.enterPet, self.exitPet, ['walk']),
State('phone', self.enterPhone, self.exitPhone, ['walk', 'doorOut']),
State('stopped', self.enterStopped, self.exitStopped, ['walk', 'doorOut']),
State('final', self.enterFinal, self.exitFinal, ['start'])], 'start', 'final')
self.parentFSMState = parentFSMState
def load(self):
Place.Place.load(self)
Place.load(self)
self.parentFSMState.addChild(self.fsm)
def unload(self):
Place.Place.unload(self)
Place.unload(self)
self.parentFSMState.removeChild(self.fsm)
del self.parentFSMState
del self.fsm
@ -111,7 +113,7 @@ class ToonInterior(Place.Place):
def enterTutorial(self, requestStatus):
self.fsm.request('walk')
base.localAvatar.b_setParent(ToontownGlobals.SPRender)
globalClock.tick()
base.clock.tick()
base.transitions.irisIn()
messenger.send('enterTutorialInterior')
@ -134,7 +136,7 @@ class ToonInterior(Place.Place):
def enterNPCFA(self, requestStatus):
self.acceptOnce(self.npcfaDoneEvent, self.enterNPCFACallback, [requestStatus])
self.npcfa = NPCForceAcknowledge.NPCForceAcknowledge(self.npcfaDoneEvent)
self.npcfa = NPCForceAcknowledge(self.npcfaDoneEvent)
self.npcfa.enter()
def exitNPCFA(self):
@ -161,7 +163,7 @@ class ToonInterior(Place.Place):
def enterHFA(self, requestStatus):
self.acceptOnce(self.hfaDoneEvent, self.enterHFACallback, [requestStatus])
self.hfa = HealthForceAcknowledge.HealthForceAcknowledge(self.hfaDoneEvent)
self.hfa = HealthForceAcknowledge(self.hfaDoneEvent)
self.hfa.enter(1)
def exitHFA(self):
@ -191,10 +193,11 @@ class ToonInterior(Place.Place):
base.localAvatar.setPosHpr(0, 0, ToontownGlobals.FloorOffset, 45.0, 0.0, 0.0)
else:
base.localAvatar.setPosHpr(2.5, 11.5, ToontownGlobals.FloorOffset, 45.0, 0.0, 0.0)
Place.Place.enterTeleportIn(self, requestStatus)
Place.enterTeleportIn(self, requestStatus)
def enterTeleportOut(self, requestStatus):
Place.Place.enterTeleportOut(self, requestStatus, self.__teleportOutDone)
Place.enterTeleportOut(self, requestStatus, self.__teleportOutDone)
def __teleportOutDone(self, requestStatus):
hoodId = requestStatus['hoodId']
@ -207,7 +210,6 @@ class ToonInterior(Place.Place):
else:
self.doneStatus = requestStatus
messenger.send(self.doneEvent)
return
def goHomeFailed(self, task):
self.notifyUserGoHomeFailed()
@ -215,7 +217,7 @@ class ToonInterior(Place.Place):
self.doneStatus['avId'] = -1
self.doneStatus['zoneId'] = self.getZoneId()
self.fsm.request('teleportIn', [self.doneStatus])
return Task.done
return task.done
def exitTeleportOut(self):
Place.Place.exitTeleportOut(self)
Place.exitTeleportOut(self)

View File

@ -2,30 +2,30 @@ from .CatalogSurfaceItem import *
FTTextureName = 0
FTColor = 1
FTBasePrice = 2
FlooringTypes = {1000: ('phase_5.5/maps/floor_wood_neutral.jpg', CTBasicWoodColorOnWhite, 150),
1010: ('phase_5.5/maps/flooring_carpetA_neutral.jpg', CTFlatColorDark, 150),
1020: ('phase_4/maps/flooring_tile_neutral.jpg', CTFlatColorDark, 150),
1030: ('phase_5.5/maps/flooring_tileB2.jpg', None, 150),
1040: ('phase_4/maps/grass.jpg', None, 150),
1050: ('phase_4/maps/floor_tile_brick_diagonal2.jpg', None, 150),
1060: ('phase_4/maps/floor_tile_brick_diagonal.jpg', None, 150),
1070: ('phase_4/maps/plazz_tile.jpg', None, 150),
1080: ('phase_4/maps/sidewalk.jpg', CTFlatColorDark, 150),
1090: ('phase_3.5/maps/boardwalk_floor.jpg', None, 150),
1100: ('phase_3.5/maps/dustroad.jpg', None, 150),
1110: ('phase_5.5/maps/floor_woodtile_neutral.jpg', CTBasicWoodColorOnWhite, 150),
1120: ('phase_5.5/maps/floor_tile_neutral.jpg', CTBasicWoodColorOnWhite + CTFlatColorDark, 150),
1130: ('phase_5.5/maps/floor_tile_honeycomb_neutral.jpg', CTBasicWoodColorOnWhite, 150),
1140: ('phase_5.5/maps/UWwaterFloor1.jpg', None, 150),
1150: ('phase_5.5/maps/UWtileFloor4.jpg', None, 150),
1160: ('phase_5.5/maps/UWtileFloor3.jpg', None, 150),
1170: ('phase_5.5/maps/UWtileFloor2.jpg', None, 150),
1180: ('phase_5.5/maps/UWtileFloor1.jpg', None, 150),
1190: ('phase_5.5/maps/UWsandyFloor1.jpg', None, 150),
10000: ('phase_5.5/maps/floor_icecube.jpg', CTWhite, 225),
10010: ('phase_5.5/maps/floor_snow.jpg', CTWhite, 225),
11000: ('phase_5.5/maps/StPatsFloor1.jpg', CTWhite, 225),
11010: ('phase_5.5/maps/StPatsFloor2.jpg', CTWhite, 225)}
FlooringTypes = {1000: ('phase_5.5/maps/floor_wood_neutral.png', CTBasicWoodColorOnWhite, 150),
1010: ('phase_5.5/maps/flooring_carpetA_neutral.png', CTFlatColorDark, 150),
1020: ('phase_4/maps/flooring_tile_neutral.png', CTFlatColorDark, 150),
1030: ('phase_5.5/maps/flooring_tileB2.png', None, 150),
1040: ('phase_4/maps/grass.png', None, 150),
1050: ('phase_4/maps/floor_tile_brick_diagonal2.png', None, 150),
1060: ('phase_4/maps/floor_tile_brick_diagonal.png', None, 150),
1070: ('phase_4/maps/plazz_tile.png', None, 150),
1080: ('phase_4/maps/sidewalk.png', CTFlatColorDark, 150),
1090: ('phase_3.5/maps/boardwalk_floor.png', None, 150),
1100: ('phase_3.5/maps/dustroad.png', None, 150),
1110: ('phase_5.5/maps/floor_woodtile_neutral.png', CTBasicWoodColorOnWhite, 150),
1120: ('phase_5.5/maps/floor_tile_neutral.png', CTBasicWoodColorOnWhite + CTFlatColorDark, 150),
1130: ('phase_5.5/maps/floor_tile_honeycomb_neutral.png', CTBasicWoodColorOnWhite, 150),
1140: ('phase_5.5/maps/UWwaterFloor1.png', None, 150),
1150: ('phase_5.5/maps/UWtileFloor4.png', None, 150),
1160: ('phase_5.5/maps/UWtileFloor3.png', None, 150),
1170: ('phase_5.5/maps/UWtileFloor2.png', None, 150),
1180: ('phase_5.5/maps/UWtileFloor1.png', None, 150),
1190: ('phase_5.5/maps/UWsandyFloor1.png', None, 150),
10000: ('phase_5.5/maps/floor_icecube.png', CTWhite, 225),
10010: ('phase_5.5/maps/floor_snow.png', CTWhite, 225),
11000: ('phase_5.5/maps/StPatsFloor1.png', CTWhite, 225),
11010: ('phase_5.5/maps/StPatsFloor2.png', CTWhite, 225)}
class CatalogFlooringItem(CatalogSurfaceItem):

View File

@ -2,20 +2,20 @@ from .CatalogSurfaceItem import *
MTTextureName = 0
MTColor = 1
MTBasePrice = 2
MouldingTypes = {1000: ('phase_3.5/maps/molding_wood1.jpg', CTBasicWoodColorOnWhite, 150),
1010: ('phase_5.5/maps/bd_grey_border1.jpg', CTFlatColorDark, 150),
1020: ('phase_5.5/maps/dental_Border_wood_neutral.jpg', CTFlatColorDark, 150),
1030: ('phase_5.5/maps/littleFlowers_border.jpg', CTWhite, 150),
1040: ('phase_5.5/maps/littleFlowers_border_neutral.jpg', CTFlatColorDark, 150),
1050: ('phase_5.5/maps/ladybugs2_Border.jpg', CTFlatColorDark, 150),
1060: ('phase_5.5/maps/bd_grey_border1.jpg', CTValentinesColors, 150),
1070: ('phase_5.5/maps/bd_grey_border1.jpg', CTUnderwaterColors, 150),
1080: ('phase_5.5/maps/tt_t_ara_int_border_winterLights1.jpg', CTWhite, 150),
1085: ('phase_5.5/maps/tt_t_ara_int_border_winterLights2.jpg', CTWhite, 150),
1090: ('phase_5.5/maps/tt_t_ara_int_border_winterLights3.jpg', CTWhite, 150),
1100: ('phase_5.5/maps/tt_t_ara_int_border_valentine_cupid.jpg', CTWhite, 150),
1110: ('phase_5.5/maps/tt_t_ara_int_border_valentine_heart1.jpg', CTWhite, 150),
1120: ('phase_5.5/maps/tt_t_ara_int_border_valentine_heart2.jpg', CTWhite, 150)}
MouldingTypes = {1000: ('phase_3.5/maps/molding_wood1.png', CTBasicWoodColorOnWhite, 150),
1010: ('phase_5.5/maps/bd_grey_border1.png', CTFlatColorDark, 150),
1020: ('phase_5.5/maps/dental_Border_wood_neutral.png', CTFlatColorDark, 150),
1030: ('phase_5.5/maps/littleFlowers_border.png', CTWhite, 150),
1040: ('phase_5.5/maps/littleFlowers_border_neutral.png', CTFlatColorDark, 150),
1050: ('phase_5.5/maps/ladybugs2_Border.png', CTFlatColorDark, 150),
1060: ('phase_5.5/maps/bd_grey_border1.png', CTValentinesColors, 150),
1070: ('phase_5.5/maps/bd_grey_border1.png', CTUnderwaterColors, 150),
1080: ('phase_5.5/maps/tt_t_ara_int_border_winterLights1.png', CTWhite, 150),
1085: ('phase_5.5/maps/tt_t_ara_int_border_winterLights2.png', CTWhite, 150),
1090: ('phase_5.5/maps/tt_t_ara_int_border_winterLights3.png', CTWhite, 150),
1100: ('phase_5.5/maps/tt_t_ara_int_border_valentine_cupid.png', CTWhite, 150),
1110: ('phase_5.5/maps/tt_t_ara_int_border_valentine_heart1.png', CTWhite, 150),
1120: ('phase_5.5/maps/tt_t_ara_int_border_valentine_heart2.png', CTWhite, 150)}
class CatalogMouldingItem(CatalogSurfaceItem):

View File

@ -2,11 +2,11 @@ from .CatalogSurfaceItem import *
WSTTextureName = 0
WSTColor = 1
WSTBasePrice = 2
WainscotingTypes = {1000: ('phase_3.5/maps/wall_paper_b3.jpg', CTFlatColorDark, 200),
1010: ('phase_5.5/maps/wall_paper_b4_greyscale.jpg', CTBasicWoodColorOnWhite, 200),
1020: ('phase_5.5/maps/wainscotings_neutral.jpg', CTBasicWoodColorOnWhite, 200),
1030: ('phase_3.5/maps/wall_paper_b3.jpg', CTValentinesColors, 200),
1040: ('phase_3.5/maps/wall_paper_b3.jpg', CTUnderwaterColors, 200)}
WainscotingTypes = {1000: ('phase_3.5/maps/wall_paper_b3.png', CTFlatColorDark, 200),
1010: ('phase_5.5/maps/wall_paper_b4_greyscale.png', CTBasicWoodColorOnWhite, 200),
1020: ('phase_5.5/maps/wainscotings_neutral.png', CTBasicWoodColorOnWhite, 200),
1030: ('phase_3.5/maps/wall_paper_b3.png', CTValentinesColors, 200),
1040: ('phase_3.5/maps/wall_paper_b3.png', CTUnderwaterColors, 200)}
class CatalogWainscotingItem(CatalogSurfaceItem):

View File

@ -13,242 +13,242 @@ All = (1000,
1050,
1060,
1070)
WallpaperTypes = {1000: ('phase_5.5/maps/flat_wallpaper1.jpg',
WallpaperTypes = {1000: ('phase_5.5/maps/flat_wallpaper1.png',
CTFlatColor,
(0, 1000),
180),
1100: ('phase_5.5/maps/big_stripes1.jpg',
1100: ('phase_5.5/maps/big_stripes1.png',
CTWhite,
(0, 1010),
180),
1110: ('phase_5.5/maps/big_stripes2.jpg',
1110: ('phase_5.5/maps/big_stripes2.png',
CTWhite,
(0, 1040),
180),
1120: ('phase_5.5/maps/big_stripes3.jpg',
1120: ('phase_5.5/maps/big_stripes3.png',
CTWhite,
(0, 1030),
180),
1130: ('phase_5.5/maps/big_stripes4.jpg',
1130: ('phase_5.5/maps/big_stripes4.png',
CTWhite,
(0, 1010),
180),
1140: ('phase_5.5/maps/big_stripes5.jpg',
1140: ('phase_5.5/maps/big_stripes5.png',
CTWhite,
(0, 1020),
180),
1150: ('phase_5.5/maps/big_stripes6.jpg',
1150: ('phase_5.5/maps/big_stripes6.png',
CTWhite,
(0, 1020),
180),
1200: ('phase_5.5/maps/stripeB1.jpg',
1200: ('phase_5.5/maps/stripeB1.png',
CTWhite,
(0, 1000),
180),
1210: ('phase_5.5/maps/stripeB2.jpg',
1210: ('phase_5.5/maps/stripeB2.png',
CTWhite,
(0, 1000),
180),
1220: ('phase_5.5/maps/stripeB3.jpg',
1220: ('phase_5.5/maps/stripeB3.png',
CTWhite,
(0, 1000),
180),
1230: ('phase_5.5/maps/stripeB4.jpg',
1230: ('phase_5.5/maps/stripeB4.png',
CTWhite,
(0, 1000),
180),
1240: ('phase_3.5/maps/stripeB5.jpg',
1240: ('phase_3.5/maps/stripeB5.png',
CTWhite,
(0, 1000),
180),
1250: ('phase_5.5/maps/stripeB6.jpg',
1250: ('phase_5.5/maps/stripeB6.png',
CTWhite,
(0, 1000),
180),
1260: ('phase_5.5/maps/stripeB7.jpg',
1260: ('phase_5.5/maps/stripeB7.png',
CTWhite,
(0, 1000),
180),
1300: ('phase_5.5/maps/squiggle1.jpg',
1300: ('phase_5.5/maps/squiggle1.png',
CTWhite,
(0,),
180),
1310: ('phase_5.5/maps/squiggle2.jpg',
1310: ('phase_5.5/maps/squiggle2.png',
CTWhite,
(0,),
180),
1320: ('phase_5.5/maps/squiggle3.jpg',
1320: ('phase_5.5/maps/squiggle3.png',
CTWhite,
(0,),
180),
1330: ('phase_5.5/maps/squiggle4.jpg',
1330: ('phase_5.5/maps/squiggle4.png',
CTWhite,
(0,),
180),
1340: ('phase_5.5/maps/squiggle5.jpg',
1340: ('phase_5.5/maps/squiggle5.png',
CTWhite,
(0,),
180),
1350: ('phase_5.5/maps/squiggle6.jpg',
1350: ('phase_5.5/maps/squiggle6.png',
CTWhite,
(0,),
180),
1400: ('phase_5.5/maps/stripes_cyan.jpg',
1400: ('phase_5.5/maps/stripes_cyan.png',
CTWhite,
(0, 1000),
180),
1410: ('phase_5.5/maps/stripes_green.jpg',
1410: ('phase_5.5/maps/stripes_green.png',
CTWhite,
(0, 1000),
180),
1420: ('phase_5.5/maps/stripes_magenta.jpg',
1420: ('phase_5.5/maps/stripes_magenta.png',
CTWhite,
(0, 1000),
180),
1430: ('phase_5.5/maps/two_stripes1.jpg',
1430: ('phase_5.5/maps/two_stripes1.png',
CTWhite,
(0, 1000),
180),
1440: ('phase_5.5/maps/two_stripes2.jpg',
1440: ('phase_5.5/maps/two_stripes2.png',
CTWhite,
(0, 1000),
180),
1450: ('phase_5.5/maps/two_stripes3.jpg',
1450: ('phase_5.5/maps/two_stripes3.png',
CTWhite,
(0, 1000),
180),
1500: ('phase_5.5/maps/leaves1.jpg',
1500: ('phase_5.5/maps/leaves1.png',
CTWhite,
(0,),
180),
1510: ('phase_5.5/maps/leaves2.jpg',
1510: ('phase_5.5/maps/leaves2.png',
CTWhite,
(0,),
180),
1520: ('phase_5.5/maps/leaves3.jpg',
1520: ('phase_5.5/maps/leaves3.png',
CTWhite,
(0,),
180),
1600: ('phase_5.5/maps/diamonds2_cherries.jpg',
1600: ('phase_5.5/maps/diamonds2_cherries.png',
CTWhite,
(0, 1000),
180),
1610: ('phase_5.5/maps/diamonds3_cherries.jpg',
1610: ('phase_5.5/maps/diamonds3_cherries.png',
CTWhite,
(0, 1000),
180),
1620: ('phase_5.5/maps/diamonds3_cherry.jpg',
1620: ('phase_5.5/maps/diamonds3_cherry.png',
CTWhite,
(0, 1000),
180),
1630: ('phase_5.5/maps/diamonds4_cherries.jpg',
1630: ('phase_5.5/maps/diamonds4_cherries.png',
CTWhite,
(0, 1000),
180),
1640: ('phase_5.5/maps/diamonds4_cherry.jpg',
1640: ('phase_5.5/maps/diamonds4_cherry.png',
CTWhite,
(0, 1000),
180),
1650: ('phase_5.5/maps/diamonds5_cherries.jpg',
1650: ('phase_5.5/maps/diamonds5_cherries.png',
CTWhite,
(0, 1000),
180),
1660: ('phase_5.5/maps/diamonds6_cherry.jpg',
1660: ('phase_5.5/maps/diamonds6_cherry.png',
CTWhite,
(0, 1000),
180),
1700: ('phase_5.5/maps/moon1.jpg',
1700: ('phase_5.5/maps/moon1.png',
CTWhite,
(0,),
180),
1710: ('phase_5.5/maps/moon2.jpg',
1710: ('phase_5.5/maps/moon2.png',
CTWhite,
(0,),
180),
1720: ('phase_5.5/maps/moon3.jpg',
1720: ('phase_5.5/maps/moon3.png',
CTWhite,
(0,),
180),
1730: ('phase_5.5/maps/moon4.jpg',
1730: ('phase_5.5/maps/moon4.png',
CTWhite,
(0,),
180),
1740: ('phase_5.5/maps/moon5.jpg',
1740: ('phase_5.5/maps/moon5.png',
CTWhite,
(0,),
180),
1750: ('phase_5.5/maps/moon6.jpg',
1750: ('phase_5.5/maps/moon6.png',
CTWhite,
(0,),
180),
1760: ('phase_5.5/maps/moon7.jpg',
1760: ('phase_5.5/maps/moon7.png',
CTWhite,
(0,),
180),
1800: ('phase_5.5/maps/stars1.jpg',
1800: ('phase_5.5/maps/stars1.png',
CTWhite,
(0,),
180),
1810: ('phase_5.5/maps/stars2.jpg',
1810: ('phase_5.5/maps/stars2.png',
(CT_BLUE2, CT_PINK2, CT_RED),
(0,),
180),
1820: ('phase_5.5/maps/stars3.jpg',
1820: ('phase_5.5/maps/stars3.png',
(CT_BLUE2,
CT_PINK2,
CT_RED,
CT_WHITE),
(0,),
180),
1830: ('phase_5.5/maps/stars4.jpg',
1830: ('phase_5.5/maps/stars4.png',
CTWhite,
(0,),
180),
1840: ('phase_5.5/maps/stars5.jpg',
1840: ('phase_5.5/maps/stars5.png',
CTWhite,
(0,),
180),
1850: ('phase_5.5/maps/stars6.jpg',
1850: ('phase_5.5/maps/stars6.png',
CTWhite,
(0,),
180),
1860: ('phase_5.5/maps/stars7.jpg',
1860: ('phase_5.5/maps/stars7.png',
(CT_BEIGE2, CT_WHITE),
(0,),
180),
1900: ('phase_5.5/maps/wall_paper_flower1.jpg',
1900: ('phase_5.5/maps/wall_paper_flower1.png',
CTWhite,
(0, 1000),
180),
1910: ('phase_5.5/maps/wall_paper_flower2.jpg',
1910: ('phase_5.5/maps/wall_paper_flower2.png',
CTWhite,
(0, 1000),
180),
1920: ('phase_5.5/maps/wall_paper_flower3.jpg',
1920: ('phase_5.5/maps/wall_paper_flower3.png',
CTWhite,
(0, 1000),
180),
1930: ('phase_5.5/maps/wall_paper_flower4.jpg',
1930: ('phase_5.5/maps/wall_paper_flower4.png',
CTWhite,
(0, 1000),
180),
1940: ('phase_5.5/maps/wall_paper_flower5.jpg',
1940: ('phase_5.5/maps/wall_paper_flower5.png',
CTWhite,
(0, 1000),
180),
1950: ('phase_5.5/maps/wall_paper_flower6.jpg',
1950: ('phase_5.5/maps/wall_paper_flower6.png',
CTWhite,
(0, 1000),
180),
2000: ('phase_5.5/maps/flat_wallpaper1.jpg',
2000: ('phase_5.5/maps/flat_wallpaper1.png',
(CT_BEIGE, CT_BEIGE2, CT_RED),
(1050,),
180),
2010: ('phase_5.5/maps/flat_wallpaper1.jpg',
2010: ('phase_5.5/maps/flat_wallpaper1.png',
(CT_BLUE2, CT_PINK2),
(1060,),
180),
2020: ('phase_5.5/maps/flat_wallpaper1.jpg',
2020: ('phase_5.5/maps/flat_wallpaper1.png',
(CT_BEIGE2,
CT_BLUE2,
CT_PINK2,
@ -256,207 +256,207 @@ WallpaperTypes = {1000: ('phase_5.5/maps/flat_wallpaper1.jpg',
CT_RED),
(1070,),
180),
2100: ('phase_5.5/maps/big_stripes1.jpg',
2100: ('phase_5.5/maps/big_stripes1.png',
CTWhite,
(1050,),
180),
2110: ('phase_5.5/maps/big_stripes2.jpg',
2110: ('phase_5.5/maps/big_stripes2.png',
CTWhite,
(1050,),
180),
2120: ('phase_5.5/maps/big_stripes3.jpg',
2120: ('phase_5.5/maps/big_stripes3.png',
CTWhite,
(1060,),
180),
2130: ('phase_5.5/maps/big_stripes3.jpg',
2130: ('phase_5.5/maps/big_stripes3.png',
CTWhite,
(1070,),
180),
2140: ('phase_5.5/maps/big_stripes6.jpg',
2140: ('phase_5.5/maps/big_stripes6.png',
CTWhite,
(1070,),
180),
2200: ('phase_5.5/maps/wall_paper_car.jpg',
2200: ('phase_5.5/maps/wall_paper_car.png',
CTWhite,
(0, 1000),
180),
2210: ('phase_5.5/maps/wall_paper_car_neutral.jpg',
2210: ('phase_5.5/maps/wall_paper_car_neutral.png',
CTFlatColor,
(0, 1000),
180),
2300: ('phase_5.5/maps/wall_paper_football_neutral.jpg',
2300: ('phase_5.5/maps/wall_paper_football_neutral.png',
CTFlatColor,
(0, 1080),
180),
2400: ('phase_5.5/maps/wall_paper_clouds.jpg',
2400: ('phase_5.5/maps/wall_paper_clouds.png',
CTWhite,
(0, 1000),
180),
2500: ('phase_5.5/maps/wall_paper_vine_neutral.jpg',
2500: ('phase_5.5/maps/wall_paper_vine_neutral.png',
CTFlatColorAll,
(0, 1090),
180),
2600: ('phase_5.5/maps/basket.jpg',
2600: ('phase_5.5/maps/basket.png',
CTWhite,
(0, 1000),
180),
2610: ('phase_5.5/maps/basket_neutral.jpg',
2610: ('phase_5.5/maps/basket_neutral.png',
CTFlatColor,
(0, 1000),
180),
2700: ('phase_5.5/maps/doll.jpg',
2700: ('phase_5.5/maps/doll.png',
CTWhite,
(0, 1000, 1110),
180),
2710: ('phase_5.5/maps/doll_neutral.jpg',
2710: ('phase_5.5/maps/doll_neutral.png',
CTFlatColor,
(0, 1100, 1110),
180),
2800: ('phase_5.5/maps/littleFlowers.jpg',
2800: ('phase_5.5/maps/littleFlowers.png',
CTWhite,
(0, 1000),
180),
2810: ('phase_5.5/maps/littleFlowers_neutral.jpg',
2810: ('phase_5.5/maps/littleFlowers_neutral.png',
CTFlatColor,
(0, 1000),
180),
2900: ('phase_5.5/maps/UWwallPaperAngelFish.jpg',
2900: ('phase_5.5/maps/UWwallPaperAngelFish.png',
CTWhite,
(0, 1120, 1160),
180),
2910: ('phase_5.5/maps/UWwallPaperAngelFishColor.jpg',
2910: ('phase_5.5/maps/UWwallPaperAngelFishColor.png',
CTWhite,
(0, 1120, 1160),
180),
2920: ('phase_5.5/maps/UWwallPaperBubbles.jpg',
2920: ('phase_5.5/maps/UWwallPaperBubbles.png',
CTWhite,
(0, 1120, 1160),
180),
2930: ('phase_5.5/maps/UWwallPaperBubbles2.jpg',
2930: ('phase_5.5/maps/UWwallPaperBubbles2.png',
CTWhite,
(0, 1120, 1160),
180),
2940: ('phase_5.5/maps/UWwallPaperGreenFish.jpg',
2940: ('phase_5.5/maps/UWwallPaperGreenFish.png',
CTWhite,
(0, 1120, 1160),
180),
2950: ('phase_5.5/maps/UWwallPaperRedFish.jpg',
2950: ('phase_5.5/maps/UWwallPaperRedFish.png',
CTWhite,
(0, 1120, 1160),
180),
2960: ('phase_5.5/maps/UWwallPaperSea_horse.jpg',
2960: ('phase_5.5/maps/UWwallPaperSea_horse.png',
CTWhite,
(0, 1120, 1160),
180),
2970: ('phase_5.5/maps/UWwallPaperShells.jpg',
2970: ('phase_5.5/maps/UWwallPaperShells.png',
CTWhite,
(0, 1140, 1150),
180),
2980: ('phase_5.5/maps/UWwaterFloor1.jpg',
2980: ('phase_5.5/maps/UWwaterFloor1.png',
(CT_WHITE, CT_PALE_GREEN, CT_LIGHT_BLUE),
(0,),
180),
3000: ('phase_5.5/maps/UWwallPaperBubbles.jpg',
3000: ('phase_5.5/maps/UWwallPaperBubbles.png',
CTWhite,
(0, 1120, 1160),
180),
3100: ('phase_5.5/maps/UWwallPaperBubbles2.jpg',
3100: ('phase_5.5/maps/UWwallPaperBubbles2.png',
CTWhite,
(0, 1120, 1160),
180),
3200: ('phase_5.5/maps/UWwallPaperGreenFish.jpg',
3200: ('phase_5.5/maps/UWwallPaperGreenFish.png',
CTWhite,
(0, 1120, 1160),
180),
3300: ('phase_5.5/maps/UWwallPaperRedFish.jpg',
3300: ('phase_5.5/maps/UWwallPaperRedFish.png',
CTWhite,
(0, 1120, 1160),
180),
3400: ('phase_5.5/maps/UWwallPaperSea_horse.jpg',
3400: ('phase_5.5/maps/UWwallPaperSea_horse.png',
CTWhite,
(0, 1120, 1160),
180),
3500: ('phase_5.5/maps/UWwallPaperShells.jpg',
3500: ('phase_5.5/maps/UWwallPaperShells.png',
(CT_WHITE, CT_SEA_GREEN, CT_LIGHT_BLUE),
(0, 1140, 1150),
180),
3600: ('phase_5.5/maps/UWwaterFloor1.jpg',
3600: ('phase_5.5/maps/UWwaterFloor1.png',
(CT_WHITE, CT_PALE_GREEN, CT_LIGHT_BLUE),
(0,),
180),
3700: ('phase_5.5/maps/WesternBootWallpaper1.jpg',
3700: ('phase_5.5/maps/WesternBootWallpaper1.png',
CTWhite,
(0, 1170, 1180),
180),
3800: ('phase_5.5/maps/WesternCactusWallpaper1.jpg',
3800: ('phase_5.5/maps/WesternCactusWallpaper1.png',
CTWhite,
(0, 1170, 1180),
180),
3900: ('phase_5.5/maps/WesternHatWallpaper1.jpg',
3900: ('phase_5.5/maps/WesternHatWallpaper1.png',
CTWhite,
(0, 1170, 1180),
180),
10100: ('phase_5.5/maps/cats1.jpg',
10100: ('phase_5.5/maps/cats1.png',
CTWhite,
(0, 10010, 10020),
400),
10200: ('phase_5.5/maps/bats2.jpg',
10200: ('phase_5.5/maps/bats2.png',
CTWhite,
(0, 10010, 10020),
400),
11000: ('phase_5.5/maps/wall_paper_snowflakes.jpg',
11000: ('phase_5.5/maps/wall_paper_snowflakes.png',
CTWhite,
(0, 11000, 11010),
400),
11100: ('phase_5.5/maps/wall_paper_hollyleaf.jpg',
11100: ('phase_5.5/maps/wall_paper_hollyleaf.png',
CTWhite,
(0, 11000, 11010),
400),
11200: ('phase_5.5/maps/wall_paper_snowman.jpg',
11200: ('phase_5.5/maps/wall_paper_snowman.png',
CTWhite,
(0, 11000, 11010),
400),
12000: ('phase_5.5/maps/VdayWall1.jpg',
12000: ('phase_5.5/maps/VdayWall1.png',
CTWhite,
(0,
12000,
12010,
12020),
400),
12100: ('phase_5.5/maps/VdayWall2.jpg',
12100: ('phase_5.5/maps/VdayWall2.png',
CTWhite,
(0,
12000,
12010,
12020),
400),
12200: ('phase_5.5/maps/VdayWall3.jpg',
12200: ('phase_5.5/maps/VdayWall3.png',
CTWhite,
(0,
12000,
12010,
12020),
400),
12300: ('phase_5.5/maps/VdayWall4.jpg',
12300: ('phase_5.5/maps/VdayWall4.png',
CTWhite,
(0,
12000,
12010,
12020),
400),
13000: ('phase_5.5/maps/StPatWallpaper1.jpg',
13000: ('phase_5.5/maps/StPatWallpaper1.png',
CTWhite,
(0, 13000),
400),
13100: ('phase_5.5/maps/StPatWallpaper2.jpg',
13100: ('phase_5.5/maps/StPatWallpaper2.png',
CTWhite,
(0, 13000),
400),
13200: ('phase_5.5/maps/StPatWallpaper3.jpg',
13200: ('phase_5.5/maps/StPatWallpaper3.png',
CTWhite,
(0, 13000),
400),
13300: ('phase_5.5/maps/StPatWallpaper4.jpg',
13300: ('phase_5.5/maps/StPatWallpaper4.png',
CTWhite,
(0, 13000),
400)}
@ -524,33 +524,33 @@ WallpaperGroups = {1100: (1100,
2700: (2700, 2710),
2800: (2800, 2810),
2900: (2900, 2910)}
BorderTypes = {1000: ('phase_5.5/maps/bd_grey_border1.jpg', CTFlatColorDark),
1010: ('phase_5.5/maps/diamonds_border2.jpg', CTWhite),
1020: ('phase_5.5/maps/diamonds_border2ch.jpg', CTWhite),
1030: ('phase_5.5/maps/diamonds_border3ch.jpg', CTWhite),
1040: ('phase_5.5/maps/diamonds_border4ch.jpg', CTWhite),
1050: ('phase_5.5/maps/flower_border2.jpg', CTWhite),
1060: ('phase_5.5/maps/flower_border5.jpg', CTWhite),
1070: ('phase_5.5/maps/flower_border6.jpg', CTWhite),
1080: ('phase_5.5/maps/football_border_neutral.jpg', CTFlatColorDark),
1090: ('phase_5.5/maps/vine_border1.jpg', CTFlatColorDark),
1100: ('phase_5.5/maps/doll_board.jpg', CTWhite),
1110: ('phase_5.5/maps/doll_board_neutral.jpg', CTFlatColorDark),
1120: ('phase_5.5/maps/UWwallPaperPlantBorder.jpg', CTWhite),
1130: ('phase_5.5/maps/UWwallPaperSea_horseBorder.jpg', CTWhite),
1140: ('phase_5.5/maps/UWwallPaperShellBorder1.jpg', CTWhite),
1150: ('phase_5.5/maps/UWwallPaperShellBorder2.jpg', CTWhite),
1160: ('phase_5.5/maps/UWwallPaperWaveBorder.jpg', CTWhite),
1170: ('phase_5.5/maps/WesternSkullBorder.jpg', CTWhite),
1180: ('phase_5.5/maps/WesternStarBorder.jpg', CTWhite),
10010: ('phase_5.5/maps/border_ScarryMoon1.jpg', CTWhite),
10020: ('phase_5.5/maps/border_candy1.jpg', CTWhite),
11000: ('phase_5.5/maps/flakes_border.jpg', CTWhite),
11010: ('phase_5.5/maps/hollyleaf_border.jpg', CTWhite),
12000: ('phase_5.5/maps/Vborder1a.jpg', CTWhite),
12010: ('phase_5.5/maps/Vborder1b.jpg', CTWhite),
12020: ('phase_5.5/maps/Vborder2b.jpg', CTWhite),
13000: ('phase_5.5/maps/StPatBorder1.jpg', CTWhite)}
BorderTypes = {1000: ('phase_5.5/maps/bd_grey_border1.png', CTFlatColorDark),
1010: ('phase_5.5/maps/diamonds_border2.png', CTWhite),
1020: ('phase_5.5/maps/diamonds_border2ch.png', CTWhite),
1030: ('phase_5.5/maps/diamonds_border3ch.png', CTWhite),
1040: ('phase_5.5/maps/diamonds_border4ch.png', CTWhite),
1050: ('phase_5.5/maps/flower_border2.png', CTWhite),
1060: ('phase_5.5/maps/flower_border5.png', CTWhite),
1070: ('phase_5.5/maps/flower_border6.png', CTWhite),
1080: ('phase_5.5/maps/football_border_neutral.png', CTFlatColorDark),
1090: ('phase_5.5/maps/vine_border1.png', CTFlatColorDark),
1100: ('phase_5.5/maps/doll_board.png', CTWhite),
1110: ('phase_5.5/maps/doll_board_neutral.png', CTFlatColorDark),
1120: ('phase_5.5/maps/UWwallPaperPlantBorder.png', CTWhite),
1130: ('phase_5.5/maps/UWwallPaperSea_horseBorder.png', CTWhite),
1140: ('phase_5.5/maps/UWwallPaperShellBorder1.png', CTWhite),
1150: ('phase_5.5/maps/UWwallPaperShellBorder2.png', CTWhite),
1160: ('phase_5.5/maps/UWwallPaperWaveBorder.png', CTWhite),
1170: ('phase_5.5/maps/WesternSkullBorder.png', CTWhite),
1180: ('phase_5.5/maps/WesternStarBorder.png', CTWhite),
10010: ('phase_5.5/maps/border_ScarryMoon1.png', CTWhite),
10020: ('phase_5.5/maps/border_candy1.png', CTWhite),
11000: ('phase_5.5/maps/flakes_border.png', CTWhite),
11010: ('phase_5.5/maps/hollyleaf_border.png', CTWhite),
12000: ('phase_5.5/maps/Vborder1a.png', CTWhite),
12010: ('phase_5.5/maps/Vborder1b.png', CTWhite),
12020: ('phase_5.5/maps/Vborder2b.png', CTWhite),
13000: ('phase_5.5/maps/StPatBorder1.png', CTWhite)}
class CatalogWallpaperItem(CatalogSurfaceItem):

View File

@ -252,8 +252,8 @@ class Char(Avatar.Avatar):
self.eyesOpen = None
self.eyesClosed = None
if self._name == 'mickey' or self._name == 'minnie':
self.eyesOpen = loader.loadTexture('phase_3/maps/eyes1.jpg', 'phase_3/maps/eyes1_a.rgb')
self.eyesClosed = loader.loadTexture('phase_3/maps/mickey_eyes_closed.jpg', 'phase_3/maps/mickey_eyes_closed_a.rgb')
self.eyesOpen = loader.loadTexture('phase_3/maps/eyes1.png')
self.eyesClosed = loader.loadTexture('phase_3/maps/mickey_eyes_closed.png')
self.eyes = self.find('**/1200/**/eyes')
self.eyes.setBin('transparent', 0)
self.lpupil = self.find('**/1200/**/joint_pupilL')
@ -285,8 +285,8 @@ class Char(Avatar.Avatar):
part.hide()
elif self._name == 'pluto':
self.eyesOpen = loader.loadTexture('phase_6/maps/plutoEyesOpen.jpg', 'phase_6/maps/plutoEyesOpen_a.rgb')
self.eyesClosed = loader.loadTexture('phase_6/maps/plutoEyesClosed.jpg', 'phase_6/maps/plutoEyesClosed_a.rgb')
self.eyesOpen = loader.loadTexture('phase_6/maps/plutoEyesOpen.png')
self.eyesClosed = loader.loadTexture('phase_6/maps/plutoEyesClosed.png')
self.eyes = self.find('**/1000/**/eyes')
self.lpupil = self.find('**/1000/**/joint_pupilL')
self.rpupil = self.find('**/1000/**/joint_pupilR')
@ -317,8 +317,8 @@ class Char(Avatar.Avatar):
self.rpupil = self.find('**/joint_pupilR')
self.drawInFront('joint_pupil?', 'eyes*', -3)
elif self._name == 'chip' or self._name == 'dale':
self.eyesOpen = loader.loadTexture('phase_6/maps/dale_eye1.jpg', 'phase_6/maps/dale_eye1_a.rgb')
self.eyesClosed = loader.loadTexture('phase_6/maps/chip_dale_eye1_blink.jpg', 'phase_6/maps/chip_dale_eye1_blink_a.rgb')
self.eyesOpen = loader.loadTexture('phase_6/maps/dale_eye1.png')
self.eyesClosed = loader.loadTexture('phase_6/maps/chip_dale_eye1_blink.png')
self.eyes = self.find('**/eyes')
self.lpupil = self.find('**/pupil_left')
self.rpupil = self.find('**/pupil_right')

View File

@ -1,6 +1,5 @@
from panda3d.core import NodePath, Point3, PlaneNode, TextNode
from panda3d.core import NodePath, Point3, Plane, PlaneNode, TextNode
from direct.interval.IntervalGlobal import *
from direct.showbase.ShowBase import Plane
from direct.directnotify import DirectNotifyGlobal
from direct.showbase.RandomNumGen import RandomNumGen
from direct.interval.MetaInterval import Sequence, Parallel

View File

@ -1,6 +1,5 @@
from panda3d.core import NodePath, Point3, PlaneNode, TextNode
from panda3d.core import NodePath, Point3, Plane, PlaneNode, TextNode
from direct.interval.IntervalGlobal import *
from direct.showbase.ShowBase import Plane
from direct.directnotify import DirectNotifyGlobal
from direct.showbase.RandomNumGen import RandomNumGen
from direct.interval.MetaInterval import Sequence, Parallel

View File

@ -1,5 +1,4 @@
from panda3d.core import Point3, PlaneNode
from direct.showbase.ShowBase import Plane
from panda3d.core import Point3, Plane, PlaneNode
from direct.showbase.RandomNumGen import RandomNumGen
from direct.interval.MetaInterval import Sequence, Parallel
from direct.interval.FunctionInterval import Func, Wait

View File

@ -1,5 +1,4 @@
from panda3d.core import NodePath, Point3, PlaneNode
from direct.showbase.ShowBase import Plane
from panda3d.core import NodePath, Point3, Plane, PlaneNode
from direct.showbase.RandomNumGen import RandomNumGen
from direct.interval.MetaInterval import Sequence, Parallel
from direct.interval.FunctionInterval import Func, Wait

View File

@ -34,8 +34,8 @@ class DistributedCogdoBarrel(DistributedObject.DistributedObject):
cogdoBarrelsNode = render.attachNewNode('CogdoBarrels')
cogdoBarrelsNode.stash()
self.model.reparentTo(cogdoBarrelsNode)
self.availableTex = loader.loadTexture('phase_5/maps/tt_t_ara_cbr_Barrel_notUsed.jpg')
self.usedTex = loader.loadTexture('phase_5/maps/tt_t_ara_cbr_Barrel_Used.jpg')
self.availableTex = loader.loadTexture('phase_5/maps/tt_t_ara_cbr_Barrel_notUsed.png')
self.usedTex = loader.loadTexture('phase_5/maps/tt_t_ara_cbr_Barrel_Used.png')
self.model.setTexture(self.availableTex, 100)
def __addCollision(self):

View File

@ -98,10 +98,10 @@ class DistributedToonStatuary(DistributedStatuary.DistributedStatuary):
for node in self.toon.findAllMatches('**/*'):
node.setState(RenderState.makeEmpty())
desatShirtTex = loader.loadTexture('phase_3/maps/desat_shirt_1.jpg')
desatSleeveTex = loader.loadTexture('phase_3/maps/desat_sleeve_1.jpg')
desatShortsTex = loader.loadTexture('phase_3/maps/desat_shorts_1.jpg')
desatSkirtTex = loader.loadTexture('phase_3/maps/desat_skirt_1.jpg')
desatShirtTex = loader.loadTexture('phase_3/maps/desat_shirt_1.png')
desatSleeveTex = loader.loadTexture('phase_3/maps/desat_sleeve_1.png')
desatShortsTex = loader.loadTexture('phase_3/maps/desat_shorts_1.png')
desatSkirtTex = loader.loadTexture('phase_3/maps/desat_skirt_1.png')
if self.toon.hasLOD():
for lodName in self.toon.getLODNames():
torso = self.toon.getPart('torso', lodName)
@ -123,7 +123,7 @@ class DistributedToonStatuary(DistributedStatuary.DistributedStatuary):
def setStoneTexture(self):
gray = VBase4(1.6, 1.6, 1.6, 1)
self.toon.setColor(gray, 10)
stoneTex = loader.loadTexture('phase_5.5/maps/smoothwall_1.jpg')
stoneTex = loader.loadTexture('phase_5.5/maps/smoothwall_1.png')
ts = TextureStage('ts')
ts.setPriority(1)
self.toon.setTexture(ts, stoneTex)

View File

@ -3,3 +3,13 @@ from direct.distributed.DistributedObjectAI import DistributedObjectAI
class DistributedFishingPondAI(DistributedObjectAI):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedFishingPondAI')
def __init__(self, air):
DistributedObjectAI.__init__(self, air)
self.area = None
def setArea(self, area):
self.area = area
def getArea(self):
return self.area

View File

@ -3,9 +3,13 @@ from direct.gui.DirectGui import *
from direct.directnotify import DirectNotifyGlobal
from otp.otpbase import OTPLocalizer
from toontown.toonbase import TTLocalizer
# This file overrides key methods in FriendSecret to add Toontown specific text to the OTP buttons
from otp.friends.FriendSecret import AccountSecret
from otp.friends.FriendSecret import AvatarSecret
from otp.friends.FriendSecret import BothSecrets
from otp.friends import FriendSecret
from otp.friends.FriendSecret import globalFriendSecret
from otp.friends.FriendSecret import showFriendSecret
@ -18,41 +22,94 @@ def openFriendSecret(secretType):
globalFriendSecret.unload()
globalFriendSecret = ToontownFriendSecret(secretType)
globalFriendSecret.enter()
return
# there is no way to overload module level methods, so hammer it in
FriendSecret.openFriendSecret = openFriendSecret
class ToontownFriendSecret(FriendSecret.FriendSecret):
notify = DirectNotifyGlobal.directNotify.newCategory('ToontownFriendSecret')
notify = DirectNotifyGlobal.directNotify.newCategory("ToontownFriendSecret")
def __init__(self, secretType):
#secretType is specefied in toon/ToonAvatarPanel.py-> __handleSecrets(self):
FriendSecret.FriendSecret.__init__(self, secretType)
self.initialiseoptions(ToontownFriendSecret)
def makeFriendTypeButtons(self):
assert self.notify.debugCall()
buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui')
self.avatarButton = DirectButton(parent=self, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), relief=None, text=TTLocalizer.FriendInviterToon, text_scale=0.07, text_pos=(0.0, -0.1), pos=(-0.35, 0.0, -0.05), command=self._FriendSecret__handleAvatar)
avatarText = DirectLabel(parent=self, relief=None, pos=Vec3(0.35, 0, -0.3), text=TTLocalizer.FriendInviterToonFriendInfo, text_fg=(0, 0, 0, 1), text_pos=(0, 0), text_scale=0.055, text_align=TextNode.ACenter)
# make an avatar friend
self.avatarButton = DirectButton(
parent = self,
image = (buttons.find('**/ChtBx_OKBtn_UP'),
buttons.find('**/ChtBx_OKBtn_DN'),
buttons.find('**/ChtBx_OKBtn_Rllvr')),
relief = None,
text = TTLocalizer.FriendInviterToon,
text_scale = 0.07,
text_pos = (0.0, -0.1),
pos = (-0.35, 0.0, -0.05),
command = self._FriendSecret__handleAvatar
)
# make a label to show avatar friend desc on rollover
avatarText = DirectLabel(
parent = self,
relief = None,
pos = Vec3(0.35, 0, -0.3),
text = TTLocalizer.FriendInviterToonFriendInfo,
text_fg = (0, 0, 0, 1),
text_pos = (0, 0),
text_scale = 0.055,
text_align = TextNode.ACenter,
)
avatarText.reparentTo(self.avatarButton.stateNodePath[2])
self.avatarButton.hide()
self.accountButton = DirectButton(parent=self, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), relief=None, text=TTLocalizer.FriendInviterPlayer, text_scale=0.07, text_pos=(0.0, -0.1), pos=(0.35, 0.0, -0.05), command=self._FriendSecret__handleAccount)
accountText = DirectLabel(parent=self, relief=None, pos=Vec3(-0.35, 0, -0.3), text=TTLocalizer.FriendInviterPlayerFriendInfo, text_fg=(0, 0, 0, 1), text_pos=(0, 0), text_scale=0.055, text_align=TextNode.ACenter)
# make an account friend
self.accountButton = DirectButton(
parent = self,
image = (buttons.find('**/ChtBx_OKBtn_UP'),
buttons.find('**/ChtBx_OKBtn_DN'),
buttons.find('**/ChtBx_OKBtn_Rllvr')),
relief = None,
text = TTLocalizer.FriendInviterPlayer,
text_scale = 0.07,
text_pos = (0.0, -0.1),
pos = (0.35, 0.0, -0.05),
command = self._FriendSecret__handleAccount
)
# make a label to show feature desc on rollover
accountText = DirectLabel(
parent = self,
relief = None,
pos = Vec3(-0.35, 0, -0.3),
text = TTLocalizer.FriendInviterPlayerFriendInfo,
text_fg = (0, 0, 0, 1),
text_pos = (0, 0),
text_scale = 0.055,
text_align = TextNode.ACenter,
)
accountText.reparentTo(self.accountButton.stateNodePath[2])
self.accountButton.hide()
buttons.removeNode()
return
def __determineSecret(self):
assert self.notify.debugCall()
# If we support both types of secrets...
if self.secretType == BothSecrets:
# ask the player what type they want
self._FriendSecret__cleanupFirstPage()
self.ok1.hide()
self.changeOptions.hide()
self.nextText['text'] = TTLocalizer.FriendInviterBegin
self.nextText.setPos(0, 0, 0.3)
self.nextText.setPos(0, 0, 0.30)
self.nextText.show()
self.avatarButton.show()
self.accountButton.show()
self.cancel.show()
else:
# or just get the secret
self._FriendSecret__getSecret()

View File

@ -22,5 +22,14 @@ class ToontownFriendsManagerAI(DistributedObjectGlobalAI):
messenger.send("makeFriendsReply", [result, context])
def requestSecretResponse(self, result, secret, avId):
messenger.send("requestSecretReply", [result, secret, avId])
def sendRequestSecret(self, requesterId):
self.sendUpdate('requestSecret', [requesterId])
def sendSubmitSecret(self, avId, secret):
self.sendUpdate('submitSecret', [avId, secret])
def submitSecretResponse(self, result, recipient, requesterId):
messenger.send("submitSecretReply", [result, recipient, requesterId])

View File

@ -1,28 +1,55 @@
from direct.directnotify import DirectNotifyGlobal
from direct.distributed.DistributedObjectGlobalUD import DistributedObjectGlobalUD
from direct.distributed.PyDatagram import *
from direct.distributed.MsgTypes import *
from otp.otpbase import OTPGlobals
import random
import string
import json
from panda3d.direct import DCPacker
class FriendsOperation:
"""
Base class for all friend-related operations.
"""
def __init__(self, friendsManager, sender):
"""
Initialize the FriendsOperation.
:param friendsManager: The friends manager instance.
:param sender: The sender's ID.
"""
self.friendsManager = friendsManager
self.sender = sender
def _handleDone(self):
# TODO
pass
"""
Handle the completion of the operation.
"""
self.friendsManager.operations.remove(self)
def _handleError(self, error):
# TODO
pass
"""
Handle an error during the operation.
:param error: The error message.
"""
self.friendsManager.notify.warning(error)
self.friendsManager.operations.remove(self)
class GetFriendsListOperation(FriendsOperation):
"""
Operation to retrieve the friends list of a sender.
"""
def __init__(self, friendsManager, sender):
"""
Initialize the GetFriendsListOperation.
:param friendsManager: The friends manager instance.
:param sender: The sender's ID.
"""
FriendsOperation.__init__(self, friendsManager, sender)
self.friendsList = None
self.tempFriendsList = None
@ -30,6 +57,9 @@ class GetFriendsListOperation(FriendsOperation):
self.currentFriendIdx = None
def start(self):
"""
Start the operation to retrieve the friends list.
"""
self.friendsList = []
self.tempFriendsList = []
self.onlineFriends = []
@ -38,6 +68,12 @@ class GetFriendsListOperation(FriendsOperation):
self.__handleSenderRetrieved)
def __handleSenderRetrieved(self, dclass, fields):
"""
Handle the retrieval of the sender's data.
:param dclass: The data class of the sender.
:param fields: The fields of the sender.
"""
if dclass != self.friendsManager.air.dclassesByName['DistributedToonUD']:
self._handleError('Retrieved sender is not a DistributedToonUD!')
return
@ -51,6 +87,12 @@ class GetFriendsListOperation(FriendsOperation):
self.__handleFriendRetrieved)
def __handleFriendRetrieved(self, dclass, fields):
"""
Handle the retrieval of a friend's data.
:param dclass: The data class of the friend.
:param fields: The fields of the friend.
"""
if dclass != self.friendsManager.air.dclassesByName['DistributedToonUD']:
self._handleError('Retrieved friend is not a DistributedToonUD!')
return
@ -67,11 +109,20 @@ class GetFriendsListOperation(FriendsOperation):
self.__handleFriendRetrieved)
def __checkFriendsOnline(self):
"""
Check which friends are currently online.
"""
self.currentFriendIdx = 0
for friendDetails in self.friendsList:
self.friendsManager.air.getActivated(friendDetails[0], self.__gotActivatedResp)
def __gotActivatedResp(self, avId, activated):
"""
Handle the response of checking if a friend is activated.
:param avId: The avatar ID.
:param activated: Whether the friend is activated.
"""
self.currentFriendIdx += 1
if activated:
self.onlineFriends.append(avId)
@ -80,34 +131,67 @@ class GetFriendsListOperation(FriendsOperation):
self._handleDone()
def __sendFriendsList(self, success):
"""
Send the friends list to the sender.
:param success: Whether the operation was successful.
"""
self.friendsManager.sendUpdateToAvatarId(self.sender, 'getFriendsListResponse', [success, self.friendsList if success else []])
for friendId in self.onlineFriends:
self.friendsManager.sendFriendOnline(self.sender, friendId, 0, 1)
def _handleDone(self):
"""
Handle the completion of the operation.
"""
self.__sendFriendsList(True)
FriendsOperation._handleDone(self)
def _handleError(self, error):
"""
Handle an error during the operation.
:param error: The error message.
"""
self.__sendFriendsList(False)
FriendsOperation._handleError(self, error)
class GetAvatarDetailsOperation(FriendsOperation):
"""
Operation to retrieve the details of an avatar.
"""
def __init__(self, friendsManager, sender):
"""
Initialize the GetAvatarDetailsOperation.
:param friendsManager: The friends manager instance.
:param sender: The sender's ID.
"""
FriendsOperation.__init__(self, friendsManager, sender)
self.avId = None
self.dclass = None
self.fields = None
def start(self, avId):
"""
Start the operation to retrieve the avatar details.
:param avId: The avatar ID.
"""
self.avId = avId
self.fields = {}
self.friendsManager.air.dbInterface.queryObject(self.friendsManager.air.dbId, avId,
self.__handleAvatarRetrieved)
def __handleAvatarRetrieved(self, dclass, fields):
"""
Handle the retrieval of the avatar's data.
:param dclass: The data class of the avatar.
:param fields: The fields of the avatar.
"""
if dclass not in (self.friendsManager.air.dclassesByName['DistributedToonUD'],
self.friendsManager.air.dclassesByName['DistributedPetAI']):
self._handleError('Retrieved avatar is not a DistributedToonUD or DistributedPetAI!')
@ -119,6 +203,13 @@ class GetAvatarDetailsOperation(FriendsOperation):
self._handleDone()
def __packAvatarDetails(self, dclass, fields):
"""
Pack the avatar details into a byte array.
:param dclass: The data class of the avatar.
:param fields: The fields of the avatar.
:return: The packed avatar details.
"""
# Pack required fields.
fieldPacker = DCPacker()
for i in range(dclass.getNumInheritedFields()):
@ -140,6 +231,11 @@ class GetAvatarDetailsOperation(FriendsOperation):
return fieldPacker.getBytes()
def __sendAvatarDetails(self, success):
"""
Send the avatar details to the sender.
:param success: Whether the operation was successful.
"""
datagram = PyDatagram()
datagram.addUint32(self.fields['avId']) # avId
datagram.addUint8(0 if success else 1) # returnCode
@ -150,17 +246,33 @@ class GetAvatarDetailsOperation(FriendsOperation):
self.friendsManager.sendUpdateToAvatarId(self.sender, 'getAvatarDetailsResponse', [datagram.getMessage()])
def _handleDone(self):
"""
Handle the completion of the operation.
"""
self.__sendAvatarDetails(True)
FriendsOperation._handleDone(self)
def _handleError(self, error):
"""
Handle an error during the operation.
:param error: The error message.
"""
self.__sendAvatarDetails(False)
FriendsOperation._handleError(self, error)
class MakeFriendsOperation(FriendsOperation):
"""
Operation to make two avatars friends.
"""
def __init__(self, friendsManager):
"""
Initialize the MakeFriendsOperation.
:param friendsManager: The friends manager instance.
"""
FriendsOperation.__init__(self, friendsManager, None)
self.avatarAId = None
self.avatarBId = None
@ -172,6 +284,14 @@ class MakeFriendsOperation(FriendsOperation):
self.avatarBFriendsList = None
def start(self, avatarAId, avatarBId, flags, context):
"""
Start the operation to make two avatars friends.
:param avatarAId: The first avatar's ID.
:param avatarBId: The second avatar's ID.
:param flags: The friendship flags.
:param context: The context of the operation.
"""
self.avatarAId = avatarAId
self.avatarBId = avatarBId
self.flags = flags
@ -181,14 +301,34 @@ class MakeFriendsOperation(FriendsOperation):
self.friendsManager.air.getActivated(self.avatarAId, self.__gotActivatedAvatarA)
def __handleActivatedResp(self, avId, activated):
"""
Handle the response of checking if an avatar is activated.
:param avId: The avatar ID.
:param activated: Whether the avatar is activated.
"""
if activated:
self.onlineToons.append(avId)
def __gotActivatedAvatarA(self, avId, activated):
"""
Handle the response of checking if the first avatar is activated.
:param avId: The avatar ID.
:param activated: Whether the avatar is activated.
"""
self.__handleActivatedResp(avId, activated)
self.friendsManager.air.getActivated(self.avatarBId, self.__gotActivatedAvatarB)
def __handleMakeFriends(self, dclass, fields, friendId):
"""
Handle the process of making friends.
:param dclass: The data class of the avatar.
:param fields: The fields of the avatar.
:param friendId: The friend's ID.
:return: A tuple indicating success and the updated friends list.
"""
if dclass != self.friendsManager.air.dclassesByName['DistributedToonUD']:
self._handleError('Retrieved avatar is not a DistributedToonUD!')
return False, []
@ -207,6 +347,12 @@ class MakeFriendsOperation(FriendsOperation):
return True, friendsList
def __handleAvatarARetrieved(self, dclass, fields):
"""
Handle the retrieval of the first avatar's data.
:param dclass: The data class of the avatar.
:param fields: The fields of the avatar.
"""
success, avatarAFriendsList = self.__handleMakeFriends(dclass, fields, self.avatarBId)
if success:
self.avatarAFriendsList = avatarAFriendsList
@ -214,17 +360,35 @@ class MakeFriendsOperation(FriendsOperation):
self.__handleAvatarBRetrieved)
def __gotActivatedAvatarB(self, avId, activated):
"""
Handle the response of checking if the second avatar is activated.
:param avId: The avatar ID.
:param activated: Whether the avatar is activated.
"""
self.__handleActivatedResp(avId, activated)
self.friendsManager.air.dbInterface.queryObject(self.friendsManager.air.dbId, self.avatarAId,
self.__handleAvatarARetrieved)
def __handleAvatarBRetrieved(self, dclass, fields):
"""
Handle the retrieval of the second avatar's data.
:param dclass: The data class of the avatar.
:param fields: The fields of the avatar.
"""
success, avatarBFriendsList = self.__handleMakeFriends(dclass, fields, self.avatarAId)
if success:
self.avatarBFriendsList = avatarBFriendsList
self._handleDone()
def __handleSetFriendsList(self, avId, friendsList):
"""
Handle setting the friends list for an avatar.
:param avId: The avatar ID.
:param friendsList: The updated friends list.
"""
if avId in self.onlineToons:
self.friendsManager.sendUpdateToAvatar(avId, 'setFriendsList', [friendsList])
else:
@ -234,6 +398,9 @@ class MakeFriendsOperation(FriendsOperation):
{'setFriendsList': [friendsList]})
def _handleDone(self):
"""
Handle the completion of the operation.
"""
self.resultCode = 1
if self.avatarAFriendsList is not None and self.avatarBFriendsList is not None:
self.__handleSetFriendsList(self.avatarAId, self.avatarAFriendsList)
@ -247,14 +414,28 @@ class MakeFriendsOperation(FriendsOperation):
FriendsOperation._handleDone(self)
def _handleError(self, error):
"""
Handle an error during the operation.
:param error: The error message.
"""
self.resultCode = 0
self.friendsManager.sendMakeFriendsResponse(self.avatarAId, self.avatarBId, self.resultCode, self.context)
FriendsOperation._handleError(self, error)
class RemoveFriendOperation(FriendsOperation):
"""
Operation to remove a friend from the sender's friends list.
"""
def __init__(self, friendsManager, sender):
"""
Initialize the RemoveFriendOperation.
:param friendsManager: The friends manager instance.
:param sender: The sender's ID.
"""
FriendsOperation.__init__(self, friendsManager, sender)
self.friendId = None
self.onlineToons = None
@ -262,24 +443,55 @@ class RemoveFriendOperation(FriendsOperation):
self.friendFriendsList = None
def start(self, friendId):
"""
Start the operation to remove a friend.
:param friendId: The friend's ID.
"""
self.friendId = friendId
self.onlineToons = []
self.friendsManager.air.getActivated(self.sender, self.__gotSenderActivated)
def __handleActivatedResp(self, avId, activated):
"""
Handle the response of checking if an avatar is activated.
:param avId: The avatar ID.
:param activated: Whether the avatar is activated.
"""
if activated:
self.onlineToons.append(avId)
def __gotSenderActivated(self, avId, activated):
"""
Handle the response of checking if the sender is activated.
:param avId: The avatar ID.
:param activated: Whether the avatar is activated.
"""
self.__handleActivatedResp(avId, activated)
self.friendsManager.air.getActivated(self.friendId, self.__gotFriendActivated)
def __gotFriendActivated(self, avId, activated):
"""
Handle the response of checking if the friend is activated.
:param avId: The avatar ID.
:param activated: Whether the avatar is activated.
"""
self.__handleActivatedResp(avId, activated)
self.friendsManager.air.dbInterface.queryObject(self.friendsManager.air.dbId, self.sender,
self.__handleSenderRetrieved)
def __handleRemoveFriend(self, dclass, fields, friendId):
"""
Handle the process of removing a friend.
:param dclass: The data class of the avatar.
:param fields: The fields of the avatar.
:param friendId: The friend's ID.
:return: A tuple indicating success and the updated friends list.
"""
if dclass != self.friendsManager.air.dclassesByName['DistributedToonUD']:
self._handleError('Retrieved sender is not a DistributedToonUD!')
return False, []
@ -299,6 +511,12 @@ class RemoveFriendOperation(FriendsOperation):
return False, []
def __handleSenderRetrieved(self, dclass, fields):
"""
Handle the retrieval of the sender's data.
:param dclass: The data class of the sender.
:param fields: The fields of the sender.
"""
success, senderFriendsList = self.__handleRemoveFriend(dclass, fields, self.friendId)
if success:
self.senderFriendsList = senderFriendsList
@ -306,12 +524,24 @@ class RemoveFriendOperation(FriendsOperation):
self.__handleFriendRetrieved)
def __handleFriendRetrieved(self, dclass, fields):
"""
Handle the retrieval of the friend's data.
:param dclass: The data class of the friend.
:param fields: The fields of the friend.
"""
success, friendFriendsList = self.__handleRemoveFriend(dclass, fields, self.sender)
if success:
self.friendFriendsList = friendFriendsList
self._handleDone()
def __handleSetFriendsList(self, avId, friendsList):
"""
Handle setting the friends list for an avatar.
:param avId: The avatar ID.
:param friendsList: The updated friends list.
"""
if avId in self.onlineToons:
self.friendsManager.sendUpdateToAvatar(avId, 'setFriendsList', [friendsList])
else:
@ -321,6 +551,9 @@ class RemoveFriendOperation(FriendsOperation):
{'setFriendsList': [friendsList]})
def _handleDone(self):
"""
Handle the completion of the operation.
"""
if self.senderFriendsList is not None and self.friendFriendsList is not None:
self.__handleSetFriendsList(self.sender, self.senderFriendsList)
self.__handleSetFriendsList(self.friendId, self.friendFriendsList)
@ -336,24 +569,47 @@ class RemoveFriendOperation(FriendsOperation):
class ComingOnlineOperation(FriendsOperation):
"""
Operation to handle an avatar coming online.
"""
def __init__(self, friendsManager):
"""
Initialize the ComingOnlineOperation.
:param friendsManager: The friends manager instance.
"""
FriendsOperation.__init__(self, friendsManager, None)
self.avId = None
self.friendsList = None
self.currentFriendIdx = None
def start(self, avId, friendsList):
"""
Start the operation to handle an avatar coming online.
:param avId: The avatar ID.
:param friendsList: The friends list of the avatar.
"""
self.avId = avId
self.friendsList = friendsList
self.__checkFriendsOnline()
def __checkFriendsOnline(self):
"""
Check which friends are currently online.
"""
self.currentFriendIdx = 0
for friendId in self.friendsList:
self.friendsManager.air.getActivated(friendId, self.__gotFriendActivated)
def __gotFriendActivated(self, avId, activated):
"""
Handle the response of checking if a friend is activated.
:param avId: The avatar ID.
:param activated: Whether the friend is activated.
"""
self.currentFriendIdx += 1
if activated:
self.friendsManager.declareObject(avId, self.avId)
@ -365,8 +621,16 @@ class ComingOnlineOperation(FriendsOperation):
class GoingOfflineOperation(FriendsOperation):
"""
Operation to handle an avatar going offline.
"""
def __init__(self, friendsManager):
"""
Initialize the GoingOfflineOperation.
:param friendsManager: The friends manager instance.
"""
FriendsOperation.__init__(self, friendsManager, None)
self.avId = None
self.friendsList = None
@ -374,12 +638,23 @@ class GoingOfflineOperation(FriendsOperation):
self.currentFriendIdx = None
def start(self, avId):
"""
Start the operation to handle an avatar going offline.
:param avId: The avatar ID.
"""
self.avId = avId
self.friendsList = []
self.accId = 0
self.friendsManager.air.dbInterface.queryObject(self.friendsManager.air.dbId, self.avId, self.__handleAvatarRetrieved)
def __handleAvatarRetrieved(self, dclass, fields):
"""
Handle the retrieval of the avatar's data.
:param dclass: The data class of the avatar.
:param fields: The fields of the avatar.
"""
if dclass != self.friendsManager.air.dclassesByName['DistributedToonUD']:
self._handleError('Retrieved avatar is not a DistributedToonUD!')
return
@ -389,11 +664,20 @@ class GoingOfflineOperation(FriendsOperation):
self.__checkFriendsOnline()
def __checkFriendsOnline(self):
"""
Check which friends are currently online.
"""
self.currentFriendIdx = 0
for friendId, _ in self.friendsList:
self.friendsManager.air.getActivated(friendId, self.__gotFriendActivated)
def __gotFriendActivated(self, avId, activated):
"""
Handle the response of checking if a friend is activated.
:param avId: The avatar ID.
:param activated: Whether the friend is activated.
"""
self.currentFriendIdx += 1
if activated:
self.friendsManager.undeclareObject(avId, self.avId)
@ -403,19 +687,97 @@ class GoingOfflineOperation(FriendsOperation):
if self.currentFriendIdx >= len(self.friendsList):
self._handleDone()
class GenerateSecretOperation(FriendsOperation):
"""
Operation to generate a secret.
"""
def __init__(self, friendsManager):
"""
Initialize the GenerateSecretOperation.
:param friendsManager: The friends manager instance.
:param requesterId: The requester's ID.
"""
FriendsOperation.__init__(self, friendsManager, None)
self.secret = None
self.requesterId = None
def start(self, requesterId):
"""
Start the operation to generate a secret.
Format of secret:
TT 3 random letters/numbers 3 random letters/numbers
"""
self.requesterId = requesterId
self.friendsManager.loadSecretsDB()
# check if too many secrets
# TODO
self.secret = ''
for i in range(3):
self.secret += random.choice(string.ascii_letters + string.digits)
self.secret += ' '
for i in range(3):
self.secret += random.choice(string.ascii_letters + string.digits)
self.friendsManager.secrets[self.secret] = requesterId
self._handleDone()
def _handleDone(self):
"""
Handle the completion of the operation.
"""
FriendsOperation._handleDone(self)
self.friendsManager.updateSecretsDB()
# send the response to the requester that it was a success, the result and the secret
self.friendsManager.sendRequestSecretResponse(self.requesterId, 1, self.secret)
def _handleError(self, error):
"""
Handle an error during the operation.
:param error: The error message.
"""
FriendsOperation._handleError(self, error)
# send the response to the requester that it was a failure, the result and the secret
self.friendsManager.sendRequestSecretResponse(self.requesterId, 0, '')
class ToontownFriendsManagerUD(DistributedObjectGlobalUD):
"""
The main friends manager class for Toontown.
"""
notify = DirectNotifyGlobal.directNotify.newCategory('ToontownFriendsManagerUD')
def __init__(self, air):
"""
Initialize the ToontownFriendsManagerUD.
:param air: The AI repository instance.
"""
DistributedObjectGlobalUD.__init__(self, air)
self.secret = None
self.operations = []
self.secrets = []
self.secrets = {}
def sendMakeFriendsResponse(self, avatarAId, avatarBId, result, context):
"""
Send the response for making friends.
:param avatarAId: The first avatar's ID.
:param avatarBId: The second avatar's ID.
:param result: The result of the operation.
:param context: The context of the operation.
"""
self.sendUpdate('makeFriendsResponse', [avatarAId, avatarBId, result, context])
def declareObject(self, doId, objId):
"""
Declare an object to the client.
:param doId: The distributed object ID.
:param objId: The object ID.
"""
datagram = PyDatagram()
datagram.addServerHeader(self.GetPuppetConnectionChannel(doId), self.air.ourChannel, CLIENTAGENT_DECLARE_OBJECT)
datagram.addUint32(objId)
@ -423,6 +785,13 @@ class ToontownFriendsManagerUD(DistributedObjectGlobalUD):
self.air.send(datagram)
def undeclareObject(self, doId, objId, isAccount=False):
"""
Undeclare an object to the client.
:param doId: The distributed object ID.
:param objId: The object ID.
:param isAccount: Whether the object is an account.
"""
datagram = PyDatagram()
if isAccount:
datagram.addServerHeader(self.GetAccountConnectionChannel(doId), self.air.ourChannel,
@ -435,12 +804,33 @@ class ToontownFriendsManagerUD(DistributedObjectGlobalUD):
self.air.send(datagram)
def sendFriendOnline(self, avId, friendId, commonChatFlags, whitelistChatFlags):
"""
Notify that a friend has come online.
:param avId: The avatar ID.
:param friendId: The friend's ID.
:param commonChatFlags: The common chat flags.
:param whitelistChatFlags: The whitelist chat flags.
"""
self.sendUpdateToAvatarId(avId, 'friendOnline', [friendId, commonChatFlags, whitelistChatFlags])
def sendFriendOffline(self, avId, friendId):
"""
Notify that a friend has gone offline.
:param avId: The avatar ID.
:param friendId: The friend's ID.
"""
self.sendUpdateToAvatarId(avId, 'friendOffline', [friendId])
def sendUpdateToAvatar(self, avId, fieldName, args=[]):
"""
Send an update to an avatar.
:param avId: The avatar ID.
:param fieldName: The field name to update.
:param args: The arguments for the update.
"""
dclass = self.air.dclassesByName['DistributedToonUD']
if not dclass:
return
@ -453,6 +843,12 @@ class ToontownFriendsManagerUD(DistributedObjectGlobalUD):
self.air.send(datagram)
def runSenderOperation(self, operationType, *args):
"""
Run an operation initiated by the sender.
:param operationType: The type of operation.
:param args: The arguments for the operation.
"""
sender = self.air.getAvatarIdFromSender()
if not sender:
return
@ -462,27 +858,120 @@ class ToontownFriendsManagerUD(DistributedObjectGlobalUD):
newOperation.start(*args)
def runServerOperation(self, operationType, *args):
"""
Run an operation initiated by the server.
:param operationType: The type of operation.
:param args: The arguments for the operation.
"""
newOperation = operationType(self)
self.operations.append(newOperation)
newOperation.start(*args)
def getFriendsListRequest(self):
"""
Handle a request to get the friends list.
"""
self.runSenderOperation(GetFriendsListOperation)
def getAvatarDetailsRequest(self, avId):
"""
Handle a request to get avatar details.
:param avId: The avatar ID.
"""
self.runSenderOperation(GetAvatarDetailsOperation, avId)
def makeFriends(self, avatarAId, avatarBId, flags, context):
"""
Handle a request to make two avatars friends.
:param avatarAId: The first avatar's ID.
:param avatarBId: The second avatar's ID.
:param flags: The friendship flags.
:param context: The context of the operation.
"""
self.runServerOperation(MakeFriendsOperation, avatarAId, avatarBId, flags, context)
def removeFriend(self, friendId):
"""
Handle a request to remove a friend.
:param friendId: The friend's ID.
"""
self.runSenderOperation(RemoveFriendOperation, friendId)
def requestSecret(self, requesterId):
"""
Handle a request to generate a secret.
"""
self.runServerOperation(GenerateSecretOperation, requesterId)
def submitSecret(self, avId, secret):
"""
Handle a request to submit a secret.
:param avId: The avatar ID.
:param secret: The secret.
"""
self.loadSecretsDB()
recipient = self.secrets.get(secret, None)
if recipient:
self.runServerOperation(MakeFriendsOperation, avId, recipient, 0, 0)
self.sendSubmitSecretResponse(avId, 1, recipient)
else:
self.sendSubmitSecretResponse(avId, 0, recipient)
def sendSubmitSecretResponse(self, requesterId, success, recipient):
"""
Send a response to a secret submission.
:param requesterId: The requester's ID.
:param success: Whether the operation was successful.
:param secret: The secret.
:param recipient: The recipient's ID.
"""
self.sendUpdate('submitSecretResponse', [success, recipient, requesterId])
def comingOnline(self, avId, friendsList):
"""
Handle a request for an avatar coming online.
:param avId: The avatar ID.
:param friendsList: The friends list of the avatar.
"""
self.runServerOperation(ComingOnlineOperation, avId, friendsList)
def goingOffline(self, avId):
"""
Handle a request for an avatar going offline.
:param avId: The avatar ID.
"""
self.runServerOperation(GoingOfflineOperation, avId)
def requestSecret(self, requesterId):
print('requestSecret')
def sendRequestSecretResponse(self, requesterId, success, secret):
"""
Send a response to a secret request.
:param requesterId: The requester's ID.
:param success: Whether the operation was successful.
:param secret: The generated secret.
"""
self.sendUpdate('requestSecretResponse', [success, secret, requesterId])
def updateSecretsDB(self):
with open('astron/databases/secrets.json', 'w') as f:
json.dump(self.secrets, f)
self.notify.debug('Updated secrets database')
def loadSecretsDB(self):
try:
with open('astron/databases/secrets.json', 'r') as f:
self.secrets = json.load(f)
self.notify.debug('Loaded secrets database')
except:
self.notify.warning('Failed to load secrets database')

View File

@ -2,6 +2,7 @@ from direct.distributed import DistributedObjectAI
from direct.directnotify import DirectNotifyGlobal
from toontown.toonbase import ToontownGlobals
from panda3d.core import *
from panda3d.ode import OdeTriMeshData, OdeTriMeshGeom, OdeBody, OdeRayGeom
from . import DistributedPhysicsWorldAI
from direct.fsm.FSM import FSM
from toontown.ai.ToonBarrier import *

View File

@ -1,5 +1,6 @@
from panda3d.core import *
from toontown.toonbase.ToonBaseGlobal import *
from direct.gui.DirectGui import *
from toontown.toonbase import TTLocalizer, ToontownGlobals
from direct.interval.IntervalGlobal import *
from direct.task import Task
from direct.directnotify import DirectNotifyGlobal

View File

@ -1,6 +1,7 @@
from panda3d.core import *
from toontown.toonbase.ToonBaseGlobal import *
from toontown.toonbase import TTLocalizer, ToontownGlobals
from direct.directnotify import DirectNotifyGlobal
from direct.gui.DirectGui import *
from direct.interval.IntervalGlobal import *
from direct.task import Task
from math import *

View File

@ -2,6 +2,7 @@ from direct.distributed import DistributedObject
from direct.directnotify import DirectNotifyGlobal
from toontown.toonbase import ToontownGlobals
from panda3d.core import *
from panda3d.ode import OdeWorld, OdeSimpleSpace, OdeJointGroup, OdePlaneGeom, OdeBody, OdeMass, OdeSphereGeom, OdeBoxGeom, OdeSliderJoint, OdeTriMeshData, OdeTriMeshGeom, OdeHingeJoint
from math import *
import math
from direct.fsm.FSM import FSM

View File

@ -1,24 +1,33 @@
from panda3d.core import *
from toontown.toonbase.ToonBaseGlobal import *
from toontown.toonbase.ToontownGlobals import *
from toontown.distributed.ToontownMsgTypes import *
from direct.directnotify import DirectNotifyGlobal
from direct.fsm import StateData
from direct.task.Task import Task
from toontown.minigame import Purchase
from direct.gui import OnscreenText
from toontown.building import SuitInterior
from . import QuietZoneState
from . import ZoneUtil
from toontown.toonbase import TTLocalizer
from toontown.toon.Toon import teleportDebug
from direct.interval.IntervalGlobal import *
from panda3d.core import (
CompassEffect,
ModelPool,
NodePath,
TexturePool,
TransparencyAttrib,
Vec4
)
class Hood(StateData.StateData):
notify = DirectNotifyGlobal.directNotify.newCategory('Hood')
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.fsm.StateData import StateData
from direct.gui.OnscreenText import OnscreenText
from direct.interval.IntervalGlobal import Sequence, Wait, Func
from direct.showbase.MessengerGlobal import messenger
from direct.showbase.PythonUtil import uniqueName
from direct.task.TaskManagerGlobal import taskMgr
from toontown.hood import ZoneUtil
from toontown.hood.QuietZoneState import QuietZoneState
from toontown.toon.Toon import teleportDebug
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import TTLocalizer
from toontown.toonbase.ToonBaseGlobal import base
class Hood(StateData):
notify = directNotify.newCategory('Hood')
def __init__(self, parentFSM, doneEvent, dnaStore, hoodId):
StateData.StateData.__init__(self, doneEvent)
StateData.__init__(self, doneEvent)
self.loader = 'not initialized'
self.parentFSM = parentFSM
self.dnaStore = dnaStore
@ -31,21 +40,20 @@ class Hood(StateData.StateData):
self.holidayStorageDNADict = {}
self.spookySkyFile = None
self.halloweenLights = []
return
def enter(self, requestStatus):
hoodId = requestStatus['hoodId']
zoneId = requestStatus['zoneId']
hoodText = self.getHoodText(zoneId)
self.titleText = OnscreenText.OnscreenText(hoodText, fg=self.titleColor, font=getSignFont(), pos=(0, -0.5), scale=TTLocalizer.HtitleText, drawOrder=0, mayChange=1)
self.titleText = OnscreenText(hoodText, fg=self.titleColor, font=ToontownGlobals.getSignFont(), pos=(0, -0.5), scale=TTLocalizer.HtitleText, drawOrder=0, mayChange=1)
self.fsm.request(requestStatus['loader'], [requestStatus])
def getHoodText(self, zoneId):
hoodText = base.cr.hoodMgr.getFullnameFromId(self.id)
if self.id != Tutorial:
streetName = StreetNames.get(ZoneUtil.getCanonicalBranchZone(zoneId))
if self.id != ToontownGlobals.Tutorial:
streetName = ToontownGlobals.StreetNames.get(ZoneUtil.getCanonicalBranchZone(zoneId))
if streetName:
hoodText = hoodText + '\n' + streetName[-1]
return hoodText
def spawnTitleText(self, zoneId):
@ -69,32 +77,35 @@ class Hood(StateData.StateData):
if self.titleTextSeq:
self.titleTextSeq.finish()
self.titleTextSeq = None
if self.titleText:
self.titleText.cleanup()
self.titleText = None
base.localAvatar.stopChat()
return
def load(self):
if self.storageDNAFile:
loader.loadDNAFile(self.dnaStore, self.storageDNAFile)
base.loader.loadDNAFile(self.dnaStore, self.storageDNAFile)
newsManager = base.cr.newsManager
if newsManager:
holidayIds = base.cr.newsManager.getDecorationHolidayId()
for holiday in holidayIds:
for storageFile in self.holidayStorageDNADict.get(holiday, []):
loader.loadDNAFile(self.dnaStore, storageFile)
base.loader.loadDNAFile(self.dnaStore, storageFile)
if ToontownGlobals.HALLOWEEN_COSTUMES not in holidayIds and ToontownGlobals.SPOOKY_COSTUMES not in holidayIds or not self.spookySkyFile:
self.sky = loader.loadModel(self.skyFile)
self.sky = base.loader.loadModel(self.skyFile)
self.sky.setTag('sky', 'Regular')
self.sky.setScale(1.0)
self.sky.setFogOff()
else:
self.sky = loader.loadModel(self.spookySkyFile)
self.sky = base.loader.loadModel(self.spookySkyFile)
self.sky.setTag('sky', 'Halloween')
if not newsManager:
self.sky = loader.loadModel(self.skyFile)
self.sky = base.loader.loadModel(self.skyFile)
self.sky.setTag('sky', 'Regular')
self.sky.setScale(1.0)
self.sky.setFogOff()
@ -105,6 +116,7 @@ class Hood(StateData.StateData):
self.loader.exit()
self.loader.unload()
del self.loader
del self.fsm
del self.parentFSM
self.dnaStore.resetHood()
@ -134,12 +146,13 @@ class Hood(StateData.StateData):
teleportDebug(requestStatus, 'Hood.enterQuietZone: status=%s' % requestStatus)
self._quietZoneDoneEvent = uniqueName('quietZoneDone')
self.acceptOnce(self._quietZoneDoneEvent, self.handleQuietZoneDone)
self.quietZoneStateData = QuietZoneState.QuietZoneState(self._quietZoneDoneEvent)
self.quietZoneStateData = QuietZoneState(self._quietZoneDoneEvent)
self._enterWaitForSetZoneResponseMsg = self.quietZoneStateData.getEnterWaitForSetZoneResponseMsg()
self.acceptOnce(self._enterWaitForSetZoneResponseMsg, self.handleWaitForSetZoneResponse)
self._quietZoneLeftEvent = self.quietZoneStateData.getQuietZoneLeftEvent()
if base.placeBeforeObjects:
self.acceptOnce(self._quietZoneLeftEvent, self.handleLeftQuietZone)
self.quietZoneStateData.load()
self.quietZoneStateData.enter(requestStatus)
@ -151,7 +164,6 @@ class Hood(StateData.StateData):
self.quietZoneStateData.exit()
self.quietZoneStateData.unload()
self.quietZoneStateData = None
return
def loadLoader(self, requestStatus):
pass
@ -159,19 +171,21 @@ class Hood(StateData.StateData):
def handleWaitForSetZoneResponse(self, requestStatus):
loaderName = requestStatus['loader']
if loaderName == 'safeZoneLoader':
if not loader.inBulkBlock:
loader.beginBulkLoad('hood', TTLocalizer.HeadingToPlayground, safeZoneCountMap[self.id], 1, TTLocalizer.TIP_GENERAL)
if not base.loader.inBulkBlock:
base.loader.beginBulkLoad('hood', TTLocalizer.HeadingToPlayground, ToontownGlobals.safeZoneCountMap[self.id], 1, TTLocalizer.TIP_GENERAL)
self.loadLoader(requestStatus)
loader.endBulkLoad('hood')
base.loader.endBulkLoad('hood')
elif loaderName == 'townLoader':
if not loader.inBulkBlock:
if not base.loader.inBulkBlock:
zoneId = requestStatus['zoneId']
toPhrase = StreetNames[ZoneUtil.getCanonicalBranchZone(zoneId)][0]
streetName = StreetNames[ZoneUtil.getCanonicalBranchZone(zoneId)][-1]
loader.beginBulkLoad('hood', TTLocalizer.HeadingToStreet % {'to': toPhrase,
'street': streetName}, townCountMap[self.id], 1, TTLocalizer.TIP_STREET)
toPhrase = ToontownGlobals.StreetNames[ZoneUtil.getCanonicalBranchZone(zoneId)][0]
streetName = ToontownGlobals.StreetNames[ZoneUtil.getCanonicalBranchZone(zoneId)][-1]
base.loader.beginBulkLoad('hood', TTLocalizer.HeadingToStreet % {'to': toPhrase,
'street': streetName}, ToontownGlobals.townCountMap[self.id], 1, TTLocalizer.TIP_STREET)
self.loadLoader(requestStatus)
loader.endBulkLoad('hood')
base.loader.endBulkLoad('hood')
elif loaderName == 'minigame':
pass
elif loaderName == 'cogHQLoader':
@ -197,6 +211,7 @@ class Hood(StateData.StateData):
if self.titleTextSeq:
self.titleTextSeq.finish()
self.titleTextSeq = None
self.hideTitleText()
self.ignore(self.loaderDoneEvent)
self.loader.exit()
@ -215,7 +230,7 @@ class Hood(StateData.StateData):
messenger.send(self.doneEvent)
def startSky(self):
self.sky.reparentTo(camera)
self.sky.reparentTo(base.camera)
self.sky.setZ(0.0)
self.sky.setHpr(0.0, 0.0, 0.0)
ce = CompassEffect.make(NodePath(), CompassEffect.PRot | CompassEffect.PZ)
@ -223,17 +238,19 @@ class Hood(StateData.StateData):
def stopSky(self):
taskMgr.remove('skyTrack')
self.sky.reparentTo(hidden)
self.sky.reparentTo(base.hidden)
def startSpookySky(self):
if not self.spookySkyFile:
return
if hasattr(self, 'sky') and self.sky:
self.stopSky()
self.sky = loader.loadModel(self.spookySkyFile)
self.sky = base.loader.loadModel(self.spookySkyFile)
self.sky.setTag('sky', 'Halloween')
self.sky.setColor(0.5, 0.5, 0.5, 1)
self.sky.reparentTo(camera)
self.sky.reparentTo(base.camera)
self.sky.setTransparency(TransparencyAttrib.MDual, 1)
fadeIn = self.sky.colorScaleInterval(1.5, Vec4(1, 1, 1, 1), startColorScale=Vec4(1, 1, 1, 0.25), blendType='easeInOut')
fadeIn.start()
@ -244,9 +261,10 @@ class Hood(StateData.StateData):
def endSpookySky(self):
if hasattr(self, 'sky') and self.sky:
self.sky.reparentTo(hidden)
self.sky.reparentTo(base.hidden)
if hasattr(self, 'sky'):
self.sky = loader.loadModel(self.skyFile)
self.sky = base.loader.loadModel(self.skyFile)
self.sky.setTag('sky', 'Regular')
self.sky.setScale(1.0)
self.startSky()

View File

@ -1,30 +1,36 @@
from panda3d.core import *
from toontown.toonbase.ToonBaseGlobal import *
from direct.directnotify import DirectNotifyGlobal
from direct.fsm import StateData
from direct.showbase.PythonUtil import PriorityCallbacks
from toontown.safezone import PublicWalk
from toontown.launcher import DownloadForceAcknowledge
from . import TrialerForceAcknowledge
from . import ZoneUtil
from toontown.friends import FriendsListManager
from toontown.toonbase import ToontownGlobals
from toontown.toon.Toon import teleportDebug
from toontown.estate import HouseGlobals
from toontown.toonbase import TTLocalizer
from otp.otpbase import OTPLocalizer
from otp.avatar import Emote
from otp.avatar.Avatar import teleportNotify
from direct.task import Task
from . import QuietZoneState
from toontown.distributed import ToontownDistrictStats
from panda3d.core import NodePath
from panda3d.otp import NametagGlobals
class Place(StateData.StateData, FriendsListManager.FriendsListManager):
notify = DirectNotifyGlobal.directNotify.newCategory('Place')
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.fsm.StateData import StateData
from direct.showbase.MessengerGlobal import messenger
from direct.showbase.PythonUtil import Functor, PriorityCallbacks, SubframeCall, uniqueName
from direct.task.TaskManagerGlobal import taskMgr
from otp.avatar.Avatar import teleportNotify
from otp.avatar.Emote import globalEmote
from otp.otpbase import OTPLocalizer
from toontown.distributed import ToontownDistrictStats
from toontown.estate import HouseGlobals
from toontown.friends.FriendsListManager import FriendsListManager
from toontown.hood import ZoneUtil
from toontown.hood.QuietZoneState import QuietZoneState
from toontown.hood.TrialerForceAcknowledge import TrialerForceAcknowledge
from toontown.launcher.DownloadForceAcknowledge import DownloadForceAcknowledge
from toontown.safezone.PublicWalk import PublicWalk
from toontown.toon.Toon import teleportDebug
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import TTLocalizer
from toontown.toonbase.ToonBaseGlobal import base
class Place(StateData, FriendsListManager):
notify = directNotify.newCategory('Place')
def __init__(self, loader, doneEvent):
StateData.StateData.__init__(self, doneEvent)
FriendsListManager.FriendsListManager.__init__(self)
StateData.__init__(self, doneEvent)
FriendsListManager.__init__(self)
self.loader = loader
self.dfaDoneEvent = 'dfaDoneEvent'
self.trialerFADoneEvent = 'trialerFADoneEvent'
@ -35,26 +41,27 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self._leftQuietZoneSubframeCall = None
self._setZoneCompleteLocalCallbacks = PriorityCallbacks()
self._setZoneCompleteSubframeCall = None
return
def load(self):
StateData.StateData.load(self)
FriendsListManager.FriendsListManager.load(self)
StateData.load(self)
FriendsListManager.load(self)
self.walkDoneEvent = 'walkDone'
self.walkStateData = PublicWalk.PublicWalk(self.fsm, self.walkDoneEvent)
self.walkStateData = PublicWalk(self.fsm, self.walkDoneEvent)
self.walkStateData.load()
self._tempFSM = self.fsm
def unload(self):
StateData.StateData.unload(self)
FriendsListManager.FriendsListManager.unload(self)
StateData.unload(self)
FriendsListManager.unload(self)
self.notify.info('Unloading Place (%s). Fsm in %s' % (self.zoneId, self._tempFSM.getCurrentState().getName()))
if self._leftQuietZoneSubframeCall:
self._leftQuietZoneSubframeCall.cleanup()
self._leftQuietZoneSubframeCall = None
if self._setZoneCompleteSubframeCall:
self._setZoneCompleteSubframeCall.cleanup()
self._setZoneCompleteSubframeCall = None
self._leftQuietZoneLocalCallbacks = None
self._setZoneCompleteLocalCallbacks = None
del self._tempFSM
@ -66,12 +73,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
if self.trialerFA:
self.trialerFA.exit()
del self.trialerFA
return
def _getQZState(self):
if hasattr(base, 'cr') and hasattr(base.cr, 'playGame'):
if hasattr(base.cr.playGame, 'quietZoneStateData') and base.cr.playGame.quietZoneStateData:
return base.cr.playGame.quietZoneStateData
return None
def addLeftQuietZoneCallback(self, callback, priority = None):
@ -82,22 +89,22 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
token = self._leftQuietZoneLocalCallbacks.add(callback, priority=priority)
if not self._leftQuietZoneSubframeCall:
self._leftQuietZoneSubframeCall = SubframeCall(self._doLeftQuietZoneCallbacks, taskMgr.getCurrentTask().getPriority() - 1)
return token
def removeLeftQuietZoneCallback(self, token):
if token is not None:
if token in self._leftQuietZoneLocalCallbacks:
self._leftQuietZoneLocalCallbacks.remove(token)
qzsd = self._getQZState()
if qzsd:
qzsd.removeLeftQuietZoneCallback(token)
return
def _doLeftQuietZoneCallbacks(self):
self._leftQuietZoneLocalCallbacks()
self._leftQuietZoneLocalCallbacks.clear()
self._leftQuietZoneSubframeCall = None
return
def addSetZoneCompleteCallback(self, callback, priority = None):
qzsd = self._getQZState()
@ -107,29 +114,30 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
token = self._setZoneCompleteLocalCallbacks.add(callback, priority=priority)
if not self._setZoneCompleteSubframeCall:
self._setZoneCompleteSubframeCall = SubframeCall(self._doSetZoneCompleteLocalCallbacks, taskMgr.getCurrentTask().getPriority() - 1)
return token
def removeSetZoneCompleteCallback(self, token):
if token is not None:
if any(token == x[1] for x in self._setZoneCompleteLocalCallbacks._callbacks):
self._setZoneCompleteLocalCallbacks.remove(token)
qzsd = self._getQZState()
if qzsd:
qzsd.removeSetZoneCompleteCallback(token)
return
def _doSetZoneCompleteLocalCallbacks(self):
self._setZoneCompleteSubframeCall = None
localCallbacks = self._setZoneCompleteLocalCallbacks
self._setZoneCompleteLocalCallbacks()
localCallbacks.clear()
return
def setState(self, state):
if hasattr(self, 'fsm'):
curState = self.fsm.getName()
if state == 'pet' or curState == 'pet':
self.preserveFriendsList()
self.fsm.request(state)
def getState(self):
@ -148,10 +156,10 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def handleTeleportQuery(self, fromAvatar, toAvatar):
if base.config.GetBool('want-tptrack', False):
if toAvatar == localAvatar:
if toAvatar == base.localAvatar:
toAvatar.doTeleportResponse(fromAvatar, toAvatar, toAvatar.doId, 1, toAvatar.defaultShard, base.cr.playGame.getPlaceId(), self.getZoneId(), fromAvatar.doId)
else:
self.notify.warning('handleTeleportQuery toAvatar.doId != localAvatar.doId' % (toAvatar.doId, localAvatar.doId))
self.notify.warning('handleTeleportQuery toAvatar.doId != localAvatar.doId' % (toAvatar.doId, base.localAvatar.doId))
else:
fromAvatar.d_teleportResponse(toAvatar.doId, 1, toAvatar.defaultShard, base.cr.playGame.getPlaceId(), self.getZoneId())
@ -159,6 +167,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
if self.isPeriodTimerEffective():
if base.cr.periodTimerExpired:
taskMgr.doMethodLater(5, self.redoPeriodTimer, 'redoPeriodTimer')
self.accept('periodTimerExpired', self.periodTimerExpired)
def disablePeriodTimer(self):
@ -167,7 +176,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def redoPeriodTimer(self, task):
messenger.send('periodTimerExpired')
return Task.done
return task.done
def periodTimerExpired(self):
self.fsm.request('final')
@ -209,10 +218,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.walkStateData.enter()
if teleportIn == 0:
self.walkStateData.fsm.request('walking')
self.acceptOnce(self.walkDoneEvent, self.handleWalkDone)
if base.cr.productName in ['DisneyOnline-US', 'ES'] and not base.cr.isPaid() and base.localAvatar.tutorialAck:
base.localAvatar.chatMgr.obscure(0, 0)
base.localAvatar.chatMgr.normalButton.show()
self.accept('teleportQuery', self.handleTeleportQuery)
base.localAvatar.setTeleportAvailable(1)
base.localAvatar.questPage.acceptOnscreenHooks()
@ -225,6 +236,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.exitFLM()
if base.cr.productName in ['DisneyOnline-US', 'ES'] and not base.cr.isPaid() and base.localAvatar.tutorialAck and not base.cr.whiteListChatEnabled:
base.localAvatar.chatMgr.obscure(1, 0)
self.disablePeriodTimer()
messenger.send('wakeup')
self.walkStateData.exit()
@ -233,13 +245,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.ignore('teleportQuery')
if base.cr.playGame.hood != None:
base.cr.playGame.hood.hideTitleText()
base.localAvatar.questPage.hideQuestsOnscreen()
base.localAvatar.questPage.ignoreOnscreenHooks()
base.localAvatar.invPage.ignoreOnscreenHooks()
base.localAvatar.invPage.hideInventoryOnscreen()
base.localAvatar.questMap.hide()
base.localAvatar.questMap.ignoreOnscreenHooks()
return
def handleWalkDone(self, doneStatus):
mode = doneStatus['mode']
@ -308,10 +320,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
target = base.cr.doFind('DistributedTarget')
if target:
target.hideGui()
self.accept('teleportQuery', self.handleTeleportQuery)
base.localAvatar.setTeleportAvailable(1)
if page:
base.localAvatar.book.setPage(page)
base.localAvatar.b_setAnimState('OpenBook', 1, self.enterStickerBookGUI)
base.localAvatar.obscureMoveFurnitureButton(1)
@ -328,11 +342,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def __handleFallingAsleep(self, task):
base.localAvatar.book.exit()
base.localAvatar.b_setAnimState('CloseBook', 1, callback=self.__handleFallingAsleepBookClose)
return Task.done
return task.done
def __handleFallingAsleepBookClose(self):
if hasattr(self, 'fsm'):
self.fsm.request('walk')
base.localAvatar.forceGotoSleep()
def exitStickerBook(self):
@ -377,10 +392,11 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
base.localAvatar.b_setAnimState('CloseBook', 1, callback=self.startPartyNow, extraArgs=[firstStart, hostId])
def handleBookCloseTeleport(self, hoodId, zoneId):
if localAvatar.hasActiveBoardingGroup():
if base.localAvatar.hasActiveBoardingGroup():
rejectText = TTLocalizer.BoardingCannotLeaveZone
localAvatar.elevatorNotifier.showMe(rejectText)
base.localAvatar.elevatorNotifier.showMe(rejectText)
return
self.requestLeave({'loader': ZoneUtil.getBranchLoaderName(zoneId),
'where': ZoneUtil.getToonWhereName(zoneId),
'how': 'teleportIn',
@ -388,7 +404,6 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
'zoneId': zoneId,
'shardId': None,
'avId': -1})
return
def __handleBookCloseExit(self):
base.localAvatar.b_setAnimState('TeleportOut', 1, self.__handleBookExitTeleport, [0])
@ -396,14 +411,16 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def __handleBookExitTeleport(self, requestStatus):
if base.cr.timeManager:
base.cr.timeManager.setDisconnectReason(ToontownGlobals.DisconnectBookExit)
base.transitions.fadeScreen(1.0)
base.cr.gameFSM.request(self.exitTo)
def goHomeNow(self, curZoneId):
if localAvatar.hasActiveBoardingGroup():
if base.localAvatar.hasActiveBoardingGroup():
rejectText = TTLocalizer.BoardingCannotLeaveZone
localAvatar.elevatorNotifier.showMe(rejectText)
base.localAvatar.elevatorNotifier.showMe(rejectText)
return
hoodId = ToontownGlobals.MyEstate
self.requestLeave({'loader': 'safeZoneLoader',
'where': 'estate',
@ -412,13 +429,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
'zoneId': -1,
'shardId': None,
'avId': -1})
return
def startPartyNow(self, firstStart, hostId):
if localAvatar.hasActiveBoardingGroup():
if base.localAvatar.hasActiveBoardingGroup():
rejectText = TTLocalizer.BoardingCannotLeaveZone
localAvatar.elevatorNotifier.showMe(rejectText)
base.localAvatar.elevatorNotifier.showMe(rejectText)
return
base.localAvatar.creatingNewPartyWithMagicWord = False
base.localAvatar.aboutToPlanParty = False
hoodId = ToontownGlobals.PartyHood
@ -436,6 +453,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
if shardId == base.localAvatar.defaultShard:
shardId = None
base.cr.playGame.getPlace().requestLeave({'loader': 'safeZoneLoader',
'where': 'party',
'how': 'teleportIn',
@ -446,13 +464,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
else:
if hostId is None:
hostId = base.localAvatar.doId
base.cr.partyManager.sendAvatarToParty(hostId)
return
return
def handleBookClose(self):
if hasattr(self, 'fsm'):
self.fsm.request('walk')
if hasattr(self, 'toonSubmerged') and self.toonSubmerged == 1:
if hasattr(self, 'walkStateData'):
self.walkStateData.fsm.request('swimming', [self.loader.swimSound])
@ -469,26 +487,27 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def enterDFA(self, requestStatus):
teleportDebug(requestStatus, 'enterDFA(%s)' % (requestStatus,))
self.acceptOnce(self.dfaDoneEvent, self.enterDFACallback, [requestStatus])
self.dfa = DownloadForceAcknowledge.DownloadForceAcknowledge(self.dfaDoneEvent)
self.dfa = DownloadForceAcknowledge(self.dfaDoneEvent)
self.dfa.enter(base.cr.hoodMgr.getPhaseFromHood(requestStatus['hoodId']))
def exitDFA(self):
self.ignore(self.dfaDoneEvent)
def handleEnterTunnel(self, requestStatus, collEntry):
if localAvatar.hasActiveBoardingGroup():
if base.localAvatar.hasActiveBoardingGroup():
rejectText = TTLocalizer.BoardingCannotLeaveZone
localAvatar.elevatorNotifier.showMe(rejectText)
base.localAvatar.elevatorNotifier.showMe(rejectText)
dummyNP = NodePath('dummyNP')
dummyNP.reparentTo(render)
dummyNP.reparentTo(base.render)
tunnelOrigin = requestStatus['tunnelOrigin']
dummyNP.setPos(localAvatar.getPos())
dummyNP.setPos(base.localAvatar.getPos())
dummyNP.setH(tunnelOrigin.getH())
dummyNP.setPos(dummyNP, 0, 4, 0)
localAvatar.setPos(dummyNP.getPos())
base.localAvatar.setPos(dummyNP.getPos())
dummyNP.removeNode()
del dummyNP
return
self.requestLeave(requestStatus)
def enterDFACallback(self, requestStatus, doneStatus):
@ -504,6 +523,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
out = {'teleportIn': 'teleportOut',
'tunnelIn': 'tunnelOut',
'doorIn': 'doorOut'}
teleportDebug(requestStatus, 'requesting %s, requestStatus=%s' % (out[requestStatus['how']], requestStatus))
self.fsm.request(out[requestStatus['how']], [requestStatus])
elif doneStatus['mode'] == 'incomplete':
@ -520,7 +540,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def enterTrialerFA(self, requestStatus):
teleportDebug(requestStatus, 'enterTrialerFA(%s)' % requestStatus)
self.acceptOnce(self.trialerFADoneEvent, self.trialerFACallback, [requestStatus])
self.trialerFA = TrialerForceAcknowledge.TrialerForceAcknowledge(self.trialerFADoneEvent)
self.trialerFA = TrialerForceAcknowledge(self.trialerFADoneEvent)
self.trialerFA.enter(requestStatus['hoodId'])
def exitTrialerFA(self):
@ -589,6 +609,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
tunnelName = requestStatus.get('tunnelName')
if tunnelName == None:
tunnelName = base.cr.hoodMgr.makeLinkTunnelName(self.loader.hood.id, fromZoneId)
self.doneStatus = {'loader': ZoneUtil.getLoaderName(zoneId),
'where': ZoneUtil.getToonWhereName(zoneId),
'how': how,
@ -599,7 +620,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')
@ -621,11 +641,11 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def enterDied(self, requestStatus, callback = None):
if callback == None:
callback = self.__diedDone
base.localAvatar.laffMeter.start()
camera.wrtReparentTo(render)
base.camera.wrtReparentTo(base.render)
base.localAvatar.b_setAnimState('Died', 1, callback, [requestStatus])
base.localAvatar.obscureMoveFurnitureButton(1)
return
def __diedDone(self, requestStatus):
self.doneStatus = requestStatus
@ -643,6 +663,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
base.cr.estateMgr.getLocalEstateZone(avId)
else:
base.cr.estateMgr.getLocalEstateZone(base.localAvatar.getDoId())
if HouseGlobals.WANT_TELEPORT_TIMEOUT:
taskMgr.doMethodLater(HouseGlobals.TELEPORT_TIMEOUT, self.goHomeFailed, 'goHomeFailed')
@ -653,6 +674,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.doneStatus['failed'] = 1
self.goHomeFailed(None)
return
if ownerId == 0 and zoneId == 0:
if self.doneStatus['shardId'] is None or self.doneStatus['shardId'] is base.localAvatar.defaultShard:
self.doneStatus['failed'] = 1
@ -666,14 +688,15 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.doneStatus['how'] = 'teleportIn'
messenger.send(self.doneEvent)
return
if self.doneStatus['zoneId'] == -1:
self.doneStatus['zoneId'] = zoneId
elif self.doneStatus['zoneId'] != zoneId:
self.doneStatus['where'] = 'house'
self.doneStatus['ownerId'] = ownerId
messenger.send(self.doneEvent)
messenger.send('localToonLeft')
return
def goHomeFailed(self, task):
self.notify.debug('goHomeFailed')
@ -682,7 +705,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.doneStatus['hood'] = base.localAvatar.lastHood
self.doneStatus['zone'] = base.localAvatar.lastHood
self.fsm.request('teleportIn', [self.doneStatus])
return Task.done
return task.done
def notifyUserGoHomeFailed(self):
self.notify.debug('notifyUserGoHomeFailed')
@ -692,12 +715,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
avatar = base.cr.identifyAvatar(failedToVisitAvId)
if avatar:
avName = avatar.getName()
if avName:
message = TTLocalizer.EstateTeleportFailedNotFriends % avName
else:
message = TTLocalizer.EstateTeleportFailed
base.localAvatar.setSystemMessage(0, message)
return
def enterTeleportIn(self, requestStatus):
self._tiToken = self.addSetZoneCompleteCallback(Functor(self._placeTeleportInPostZoneComplete, requestStatus), 100)
@ -723,16 +747,16 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
teleportDebug(requestStatus, 'friend not here, giving up')
base.localAvatar.setSystemMessage(avId, OTPLocalizer.WhisperTargetLeftVisit % (friend.getName(),))
friend.d_teleportGiveup(base.localAvatar.doId)
base.transitions.irisIn()
self.nextState = requestStatus.get('nextState', 'walk')
base.localAvatar.attachCamera()
base.localAvatar.startUpdateSmartCamera()
base.localAvatar.startPosHprBroadcast()
globalClock.tick()
base.clock.tick()
base.localAvatar.b_setAnimState('TeleportIn', 1, callback=self.teleportInDone)
base.localAvatar.d_broadcastPositionNow()
base.localAvatar.b_setParent(ToontownGlobals.SPRender)
return
def teleportInDone(self):
if hasattr(self, 'fsm'):
@ -748,7 +772,6 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
base.localAvatar.stopUpdateSmartCamera()
base.localAvatar.detachCamera()
base.localAvatar.stopPosHprBroadcast()
return
def requestTeleport(self, hoodId, zoneId, shardId, avId):
if avId > 0:
@ -756,20 +779,25 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
zoneId,
shardId,
avId),))
if localAvatar.hasActiveBoardingGroup():
if base.localAvatar.hasActiveBoardingGroup():
if avId > 0:
teleportNotify.debug('requestTeleport: has active boarding group')
rejectText = TTLocalizer.BoardingCannotLeaveZone
localAvatar.elevatorNotifier.showMe(rejectText)
base.localAvatar.elevatorNotifier.showMe(rejectText)
return
loaderId = ZoneUtil.getBranchLoaderName(zoneId)
whereId = ZoneUtil.getToonWhereName(zoneId)
if hoodId == ToontownGlobals.MyEstate:
loaderId = 'safeZoneLoader'
whereId = 'estate'
if hoodId == ToontownGlobals.PartyHood:
loaderId = 'safeZoneLoader'
whereId = 'party'
self.requestLeave({'loader': loaderId,
'where': whereId,
'how': 'teleportIn',
@ -828,6 +856,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
if hasattr(self, 'fsm'):
messenger.send('bankAsleep')
self.fsm.request('walk')
base.localAvatar.forceGotoSleep()
def exitBanking(self):
@ -850,6 +879,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def __handleFallingAsleepPhone(self, arg):
if hasattr(self, 'fsm'):
self.fsm.request('walk')
messenger.send('phoneAsleep')
base.localAvatar.forceGotoSleep()
@ -863,12 +893,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def enterStopped(self):
base.localAvatar.b_setAnimState('neutral', 1)
Emote.globalEmote.disableBody(base.localAvatar, 'enterStopped')
globalEmote.disableBody(base.localAvatar, 'enterStopped')
self.accept('teleportQuery', self.handleTeleportQuery)
if base.localAvatar.isDisguised:
base.localAvatar.setTeleportAvailable(0)
else:
base.localAvatar.setTeleportAvailable(1)
base.localAvatar.laffMeter.start()
base.localAvatar.obscureMoveFurnitureButton(1)
base.localAvatar.startSleepWatch(self.__handleFallingAsleepStopped)
@ -877,11 +908,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def __handleFallingAsleepStopped(self, arg):
if hasattr(self, 'fsm'):
self.fsm.request('walk')
base.localAvatar.forceGotoSleep()
messenger.send('stoppedAsleep')
def exitStopped(self):
Emote.globalEmote.releaseBody(base.localAvatar, 'exitStopped')
globalEmote.releaseBody(base.localAvatar, 'exitStopped')
base.localAvatar.setTeleportAvailable(0)
self.ignore('teleportQuery')
base.localAvatar.laffMeter.stop()
@ -892,7 +924,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def enterPet(self):
base.localAvatar.b_setAnimState('neutral', 1)
Emote.globalEmote.disableBody(base.localAvatar, 'enterPet')
globalEmote.disableBody(base.localAvatar, 'enterPet')
self.accept('teleportQuery', self.handleTeleportQuery)
base.localAvatar.setTeleportAvailable(1)
base.localAvatar.setTeleportAllowed(0)
@ -902,7 +934,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def exitPet(self):
base.localAvatar.setTeleportAvailable(0)
base.localAvatar.setTeleportAllowed(1)
Emote.globalEmote.releaseBody(base.localAvatar, 'exitPet')
globalEmote.releaseBody(base.localAvatar, 'exitPet')
self.ignore('teleportQuery')
base.localAvatar.laffMeter.stop()
self.exitFLM()
@ -910,7 +942,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def enterQuietZone(self, requestStatus):
self.quietZoneDoneEvent = uniqueName('quietZoneDone')
self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone)
self.quietZoneStateData = QuietZoneState.QuietZoneState(self.quietZoneDoneEvent)
self.quietZoneStateData = QuietZoneState(self.quietZoneDoneEvent)
self.quietZoneStateData.load()
self.quietZoneStateData.enter(requestStatus)
@ -920,7 +952,6 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.quietZoneStateData.exit()
self.quietZoneStateData.unload()
self.quietZoneStateData = None
return
def handleQuietZoneDone(self):
how = base.cr.handlerArgs['how']

View File

@ -5,7 +5,7 @@ from direct.distributed import DistributedObject
class StreetSign(DistributedObject.DistributedObject):
RedownloadTaskName = 'RedownloadStreetSign'
StreetSignFileName = config.GetString('street-sign-filename', 'texture.jpg')
StreetSignFileName = config.GetString('street-sign-filename', 'texture.png')
StreetSignBaseDir = config.GetString('street-sign-base-dir', 'sign')
StreetSignUrl = base.config.GetString('street-sign-url', 'http://cdn.toontown.disney.go.com/toontown/en/street-signs/img/')
notify = DirectNotifyGlobal.directNotify.newCategory('StreetSign')

View File

@ -1,23 +1,28 @@
from direct.directnotify import DirectNotifyGlobal
from panda3d.core import *
from toontown.toonbase.ToonBaseGlobal import *
from .DistributedMinigame import *
from direct.distributed.ClockDelta import *
from direct.interval.IntervalGlobal import *
from direct.fsm import ClassicFSM, State
from direct.fsm import State
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import ToontownTimer
from panda3d.core import Point3, Quat, rad2Deg, Vec3
from panda3d.otp import Nametag, NametagFloat3d
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.fsm.ClassicFSM import ClassicFSM
from direct.fsm.State import State
from direct.gui.DirectGui import DGG, DirectButton, DirectFrame, DirectLabel
from direct.interval.IntervalGlobal import Parallel, Sequence, SoundInterval, Wait
from direct.task.Task import Task
from . import Trajectory
import math
from toontown.toon import ToonHead
from toontown.effects import Splash
from toontown.effects import DustCloud
from . import CannonGameGlobals
from direct.gui.DirectGui import *
from panda3d.core import *
from direct.task.TaskManagerGlobal import taskMgr
from toontown.effects.DustCloud import DustCloud
from toontown.effects.Splash import Splash
from toontown.minigame import CannonGameGlobals
from toontown.minigame import MinigameGlobals
from toontown.minigame.DistributedMinigame import DistributedMinigame
from toontown.minigame.Trajectory import Trajectory
from toontown.toon.ToonHead import ToonHead
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import TTLocalizer
from toontown.toonbase.ToonBaseGlobal import base
from toontown.toonbase.ToontownTimer import ToontownTimer
import math
LAND_TIME = 2
WORLD_SCALE = 2.0
GROUND_SCALE = 1.4 * WORLD_SCALE
@ -40,8 +45,9 @@ TOWER_X_RANGE = int(TOWER_Y_RANGE / 2.0)
INITIAL_VELOCITY = 94.0
WHISTLE_SPEED = INITIAL_VELOCITY * 0.55
class DistributedCannonGame(DistributedMinigame):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedMinigame')
notify = directNotify.newCategory('DistributedCannonGame')
font = ToontownGlobals.getToonFont()
LOCAL_CANNON_MOVE_TASK = 'localCannonMoveTask'
REWARD_COUNTDOWN_TASK = 'cannonGameRewardCountdown'
@ -58,11 +64,11 @@ class DistributedCannonGame(DistributedMinigame):
def __init__(self, cr):
DistributedMinigame.__init__(self, cr)
self.gameFSM = ClassicFSM.ClassicFSM('DistributedCannonGame', [State.State('off', self.enterOff, self.exitOff, ['aim']),
State.State('aim', self.enterAim, self.exitAim, ['shoot', 'waitForToonsToLand', 'cleanup']),
State.State('shoot', self.enterShoot, self.exitShoot, ['aim', 'waitForToonsToLand', 'cleanup']),
State.State('waitForToonsToLand', self.enterWaitForToonsToLand, self.exitWaitForToonsToLand, ['cleanup']),
State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup')
self.gameFSM = ClassicFSM('DistributedCannonGame', [State('off', self.enterOff, self.exitOff, ['aim']),
State('aim', self.enterAim, self.exitAim, ['shoot', 'waitForToonsToLand', 'cleanup']),
State('shoot', self.enterShoot, self.exitShoot, ['aim', 'waitForToonsToLand', 'cleanup']),
State('waitForToonsToLand', self.enterWaitForToonsToLand, self.exitWaitForToonsToLand, ['cleanup']),
State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup')
self.addChildGameFSM(self.gameFSM)
self.cannonLocationDict = {}
self.cannonPositionDict = {}
@ -92,12 +98,12 @@ class DistributedCannonGame(DistributedMinigame):
def load(self):
self.notify.debug('load')
DistributedMinigame.load(self)
self.sky = loader.loadModel('phase_3.5/models/props/TT_sky')
self.ground = loader.loadModel('phase_4/models/minigames/toon_cannon_gameground')
self.tower = loader.loadModel('phase_4/models/minigames/toon_cannon_water_tower')
self.cannon = loader.loadModel('phase_4/models/minigames/toon_cannon')
self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow')
self.hill = loader.loadModel('phase_4/models/minigames/cannon_hill')
self.sky = base.loader.loadModel('phase_3.5/models/props/TT_sky')
self.ground = base.loader.loadModel('phase_4/models/minigames/toon_cannon_gameground')
self.tower = base.loader.loadModel('phase_4/models/minigames/toon_cannon_water_tower')
self.cannon = base.loader.loadModel('phase_4/models/minigames/toon_cannon')
self.dropShadow = base.loader.loadModel('phase_3/models/props/drop_shadow')
self.hill = base.loader.loadModel('phase_4/models/minigames/cannon_hill')
self.sky.setScale(WORLD_SCALE)
self.ground.setScale(GROUND_SCALE)
self.cannon.setScale(CANNON_SCALE)
@ -105,12 +111,12 @@ class DistributedCannonGame(DistributedMinigame):
self.ground.setColor(0.85, 0.85, 0.85, 1.0)
self.hill.setScale(1, 1, CANNON_Z / 20.0)
self.dropShadow.setBin('fixed', 0, 1)
self.splash = Splash.Splash(render)
self.dustCloud = DustCloud.DustCloud(render)
purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui')
self.splash = Splash(base.render)
self.dustCloud = DustCloud(base.render)
purchaseModels = base.loader.loadModel('phase_4/models/gui/purchase_gui')
self.jarImage = purchaseModels.find('**/Jar')
self.jarImage.reparentTo(hidden)
self.rewardPanel = DirectLabel(parent=hidden, relief=None, pos=(1.16, 0.0, 0.45), scale=0.65, text='', text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -.13), text_font=ToontownGlobals.getSignFont(), image=self.jarImage)
self.jarImage.reparentTo(base.hidden)
self.rewardPanel = DirectLabel(parent=base.hidden, relief=None, pos=(1.16, 0.0, 0.45), scale=0.65, text='', text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -.13), text_font=ToontownGlobals.getSignFont(), image=self.jarImage)
self.rewardPanelTitle = DirectLabel(parent=self.rewardPanel, relief=None, pos=(0, 0, 0.06), scale=0.08, text=TTLocalizer.CannonGameReward, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1))
self.music = base.loader.loadMusic('phase_4/audio/bgm/MG_cannon_game.ogg')
self.sndCannonMove = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_adjust.ogg')
@ -122,7 +128,7 @@ class DistributedCannonGame(DistributedMinigame):
self.sndWin = base.loader.loadSfx('phase_4/audio/sfx/MG_win.ogg')
self.sndRewardTick = base.loader.loadSfx('phase_3.5/audio/sfx/tick_counter.ogg')
guiModel = 'phase_4/models/gui/cannon_game_gui'
cannonGui = loader.loadModel(guiModel)
cannonGui = base.loader.loadModel(guiModel)
self.aimPad = DirectFrame(image=cannonGui.find('**/CannonFire_PAD'), relief=None, pos=(0.7, 0, -0.553333), scale=0.8)
cannonGui.removeNode()
self.aimPad.hide()
@ -141,14 +147,13 @@ class DistributedCannonGame(DistributedMinigame):
bindButton(self.downButton, self.__downPressed, self.__downReleased)
bindButton(self.leftButton, self.__leftPressed, self.__leftReleased)
bindButton(self.rightButton, self.__rightPressed, self.__rightReleased)
self.timer = ToontownTimer.ToontownTimer()
self.timer = ToontownTimer()
self.timer.posInTopRightCorner()
self.timer.hide()
self.DEBUG_TOWER_RANGE = 0
self.DEBUG_CANNON_FAR_LEFT = 0
self.DEBUG_TOWER_NEAR = 1
self.DEBUG_TOWER_FAR_LEFT = 1
return
def unload(self):
self.notify.debug('unload')
@ -199,6 +204,7 @@ class DistributedCannonGame(DistributedMinigame):
av.loop('neutral')
av.setPlayRate(1.0, 'run')
av.nametag.removeNametag(head.tag)
head.delete()
del self.toonHeadDict
@ -227,19 +233,19 @@ class DistributedCannonGame(DistributedMinigame):
DistributedMinigame.onstage(self)
self.__createCannons()
for avId in self.avIdList:
self.cannonDict[avId][0].reparentTo(render)
self.cannonDict[avId][0].reparentTo(base.render)
self.towerPos = self.getTowerPosition()
self.tower.setPos(self.towerPos)
self.tower.reparentTo(render)
self.sky.reparentTo(render)
self.ground.reparentTo(render)
self.tower.reparentTo(base.render)
self.sky.reparentTo(base.render)
self.ground.reparentTo(base.render)
self.hill.setPosHpr(0, CANNON_Y + 2.33, 0, 0, 0, 0)
self.hill.reparentTo(render)
self.splash.reparentTo(render)
self.dustCloud.reparentTo(render)
self.hill.reparentTo(base.render)
self.splash.reparentTo(base.render)
self.dustCloud.reparentTo(base.render)
self.__createToonModels(self.localAvId)
camera.reparentTo(render)
base.camera.reparentTo(base.render)
self.__oldCamFar = base.camLens.getFar()
base.camLens.setFar(FAR_PLANE_DIST)
self.__startIntro()
@ -248,27 +254,28 @@ class DistributedCannonGame(DistributedMinigame):
def offstage(self):
self.notify.debug('offstage')
self.sky.reparentTo(hidden)
self.ground.reparentTo(hidden)
self.hill.reparentTo(hidden)
self.tower.reparentTo(hidden)
self.sky.reparentTo(base.hidden)
self.ground.reparentTo(base.hidden)
self.hill.reparentTo(base.hidden)
self.tower.reparentTo(base.hidden)
for avId in self.avIdList:
self.cannonDict[avId][0].reparentTo(hidden)
self.cannonDict[avId][0].reparentTo(base.hidden)
if avId in self.dropShadowDict:
self.dropShadowDict[avId].reparentTo(hidden)
self.dropShadowDict[avId].reparentTo(base.hidden)
av = self.getAvatar(avId)
if av:
av.dropShadow.show()
av.resetLOD()
self.splash.reparentTo(hidden)
self.splash.reparentTo(base.hidden)
self.splash.stop()
self.dustCloud.reparentTo(hidden)
self.dustCloud.reparentTo(base.hidden)
self.dustCloud.stop()
self.__stopIntro()
base.camLens.setFar(self.__oldCamFar)
self.timer.reparentTo(hidden)
self.rewardPanel.reparentTo(hidden)
self.timer.reparentTo(base.hidden)
self.rewardPanel.reparentTo(base.hidden)
DistributedMinigame.offstage(self)
def getTowerPosition(self):
@ -282,6 +289,7 @@ class DistributedCannonGame(DistributedMinigame):
y = yMax
else:
y = self.randomNumGen.randint(yMin, yMax)
xRange = TOWER_X_RANGE
if self.DEBUG_TOWER_RANGE:
if self.DEBUG_TOWER_FAR_LEFT:
@ -290,6 +298,7 @@ class DistributedCannonGame(DistributedMinigame):
x = xRange
else:
x = self.randomNumGen.randint(0, xRange)
x = x - int(xRange / 2.0)
if base.wantMinigameDifficulty:
diff = self.getDifficulty()
@ -297,6 +306,7 @@ class DistributedCannonGame(DistributedMinigame):
x *= scale
yCenter = (yMin + yMax) / 2.0
y = (y - yCenter) * scale + yCenter
x = float(x) * (float(y) / float(yRange))
y = y - int(yRange / 2.0)
self.notify.debug('getTowerPosition: ' + str(x) + ', ' + str(y))
@ -304,7 +314,7 @@ class DistributedCannonGame(DistributedMinigame):
def __createCannons(self):
for avId in self.avIdList:
cannon = self.cannon.copyTo(hidden)
cannon = self.cannon.copyTo(base.hidden)
barrel = cannon.find('**/cannon')
self.cannonDict[avId] = [cannon, barrel]
@ -317,6 +327,7 @@ class DistributedCannonGame(DistributedMinigame):
self.cannonLocationDict[avId] = Point3(0 * CANNON_X_SPACING - (4 - 1) * CANNON_X_SPACING / 2, CANNON_Y, CANNON_Z)
else:
self.cannonLocationDict[avId] = Point3(3 * CANNON_X_SPACING - (4 - 1) * CANNON_X_SPACING / 2, CANNON_Y, CANNON_Z)
self.cannonPositionDict[avId] = [0, CannonGameGlobals.CANNON_ANGLE_MIN]
self.cannonDict[avId][0].setPos(self.cannonLocationDict[avId])
self.__updateCannonPosition(avId)
@ -324,9 +335,11 @@ class DistributedCannonGame(DistributedMinigame):
def setGameReady(self):
if not self.hasLocalToon:
return
self.notify.debug('setGameReady')
if DistributedMinigame.setGameReady(self):
return
for avId in self.avIdList:
if avId != self.localAvId:
self.__createToonModels(avId)
@ -335,13 +348,13 @@ class DistributedCannonGame(DistributedMinigame):
toon = self.getAvatar(avId)
self.toonScaleDict[avId] = toon.getScale()
toon.useLOD(1000)
toonParent = render.attachNewNode('toonOriginChange')
toonParent = base.render.attachNewNode('toonOriginChange')
toon.reparentTo(toonParent)
toon.setPosHpr(0, 0, -(toon.getHeight() / 2.0), 0, 0, 0)
self.toonModelDict[avId] = toonParent
head = ToonHead.ToonHead()
head = ToonHead()
head.setupHead(self.getAvatar(avId).style)
head.reparentTo(hidden)
head.reparentTo(base.hidden)
self.toonHeadDict[avId] = head
toon = self.getAvatar(avId)
tag = NametagFloat3d()
@ -354,11 +367,12 @@ class DistributedCannonGame(DistributedMinigame):
head.tag = tag
self.__loadToonInCannon(avId)
self.getAvatar(avId).dropShadow.hide()
self.dropShadowDict[avId] = self.dropShadow.copyTo(hidden)
self.dropShadowDict[avId] = self.dropShadow.copyTo(base.hidden)
def setGameStart(self, timestamp):
if not self.hasLocalToon:
return
self.notify.debug('setGameStart')
DistributedMinigame.setGameStart(self, timestamp)
self.__stopIntro()
@ -366,13 +380,13 @@ class DistributedCannonGame(DistributedMinigame):
if not base.config.GetBool('endless-cannon-game', 0):
self.timer.show()
self.timer.countdown(CannonGameGlobals.GameTime, self.__gameTimerExpired)
self.rewardPanel.reparentTo(aspect2d)
self.rewardPanel.reparentTo(base.aspect2d)
self.scoreMult = MinigameGlobals.getScoreMult(self.cr.playGame.hood.id)
self.__startRewardCountdown()
self.airborneToons = 0
self.clockStopTime = None
self.gameFSM.request('aim')
return
def __gameTimerExpired(self):
self.notify.debug('game timer expired')
@ -384,8 +398,10 @@ class DistributedCannonGame(DistributedMinigame):
def updateCannonPosition(self, avId, zRot, angle):
if not self.hasLocalToon:
return
if not self.__playing():
return
if avId != self.localAvId:
self.cannonPositionDict[avId] = [zRot, angle]
self.__updateCannonPosition(avId)
@ -393,8 +409,10 @@ class DistributedCannonGame(DistributedMinigame):
def setCannonWillFire(self, avId, fireTime, zRot, angle):
if not self.hasLocalToon:
return
if not self.__playing():
return
self.notify.debug('setCannonWillFire: ' + str(avId) + ': zRot=' + str(zRot) + ', angle=' + str(angle) + ', time=' + str(fireTime))
self.cannonPositionDict[avId][0] = zRot
self.cannonPositionDict[avId][1] = angle
@ -407,6 +425,7 @@ class DistributedCannonGame(DistributedMinigame):
fireTask = Task.sequence(Task.pause(timeToWait), task)
else:
fireTask = task
fireTask = task
taskMgr.add(fireTask, 'fireCannon' + str(avId))
self.airborneToons += 1
@ -414,10 +433,10 @@ class DistributedCannonGame(DistributedMinigame):
def announceToonWillLandInWater(self, avId, landTime):
if not self.hasLocalToon:
return
self.notify.debug('announceToonWillLandInWater: ' + str(avId) + ': time=' + str(landTime))
if self.clockStopTime == None:
self.clockStopTime = landTime
return
def enterOff(self):
self.notify.debug('enterOff')
@ -444,6 +463,7 @@ class DistributedCannonGame(DistributedMinigame):
def __somebodyWon(self, avId):
if avId == self.localAvId:
base.playSfx(self.sndWin)
self.__killRewardCountdown()
self.timer.stop()
self.gameFSM.request('waitForToonsToLand')
@ -463,6 +483,7 @@ class DistributedCannonGame(DistributedMinigame):
if hasattr(self, 'jarIval'):
self.jarIval.finish()
del self.jarIval
for avId in self.avIdList:
taskMgr.remove('fireCannon' + str(avId))
taskMgr.remove('flyingToon' + str(avId))
@ -607,27 +628,34 @@ class DistributedCannonGame(DistributedMinigame):
rotVel = 0
if self.leftPressed:
rotVel += CannonGameGlobals.CANNON_ROTATION_VEL
if self.rightPressed:
rotVel -= CannonGameGlobals.CANNON_ROTATION_VEL
pos[0] += rotVel * globalClock.getDt()
pos[0] += rotVel * base.clock.getDt()
if pos[0] < CannonGameGlobals.CANNON_ROTATION_MIN:
pos[0] = CannonGameGlobals.CANNON_ROTATION_MIN
elif pos[0] > CannonGameGlobals.CANNON_ROTATION_MAX:
pos[0] = CannonGameGlobals.CANNON_ROTATION_MAX
angVel = 0
if self.upPressed:
angVel += CannonGameGlobals.CANNON_ANGLE_VEL
if self.downPressed:
angVel -= CannonGameGlobals.CANNON_ANGLE_VEL
pos[1] += angVel * globalClock.getDt()
pos[1] += angVel * base.clock.getDt()
if pos[1] < CannonGameGlobals.CANNON_ANGLE_MIN:
pos[1] = CannonGameGlobals.CANNON_ANGLE_MIN
elif pos[1] > CannonGameGlobals.CANNON_ANGLE_MAX:
pos[1] = CannonGameGlobals.CANNON_ANGLE_MAX
if oldRot != pos[0] or oldAng != pos[1]:
if self.cannonMoving == 0:
self.cannonMoving = 1
base.playSfx(self.sndCannonMove, looping=1)
self.__updateCannonPosition(self.localAvId)
if task.time - task.lastPositionBroadcastTime > CANNON_MOVE_UPDATE_FREQ:
task.lastPositionBroadcastTime = task.time
@ -636,7 +664,8 @@ class DistributedCannonGame(DistributedMinigame):
self.cannonMoving = 0
self.sndCannonMove.stop()
self.__broadcastLocalCannonPosition()
return Task.cont
return task.cont
def __broadcastLocalCannonPosition(self):
self.sendUpdate('setCannonPosition', [self.cannonPositionDict[self.localAvId][0], self.cannonPositionDict[self.localAvId][1]])
@ -649,8 +678,8 @@ class DistributedCannonGame(DistributedMinigame):
return Point3(self.cannonLocationDict[self.localAvId][0], CANNON_Y - 25.0, CANNON_Z + 7)
def __putCameraBehindCannon(self):
camera.setPos(self.__getCameraPositionBehindCannon())
camera.setHpr(0, 0, 0)
base.camera.setPos(self.__getCameraPositionBehindCannon())
base.camera.setHpr(0, 0, 0)
def __loadToonInCannon(self, avId):
self.toonModelDict[avId].detachNode()
@ -660,7 +689,7 @@ class DistributedCannonGame(DistributedMinigame):
head.reparentTo(self.cannonDict[avId][1])
head.setPosHpr(0, 6, 0, 0, -45, 0)
sc = self.toonScaleDict[avId]
head.setScale(render, sc[0], sc[1], sc[2])
head.setScale(base.render, sc[0], sc[1], sc[2])
def __toRadians(self, angle):
return angle * 2.0 * math.pi / 360.0
@ -670,10 +699,10 @@ class DistributedCannonGame(DistributedMinigame):
def __calcFlightResults(self, avId, launchTime):
head = self.toonHeadDict[avId]
startPos = head.getPos(render)
startHpr = head.getHpr(render)
hpr = self.cannonDict[avId][1].getHpr(render)
towerPos = self.tower.getPos(render)
startPos = head.getPos(base.render)
startHpr = head.getHpr(base.render)
hpr = self.cannonDict[avId][1].getHpr(base.render)
towerPos = self.tower.getPos(base.render)
rotation = self.__toRadians(hpr[0])
angle = self.__toRadians(hpr[1])
horizVel = INITIAL_VELOCITY * math.cos(angle)
@ -681,7 +710,7 @@ class DistributedCannonGame(DistributedMinigame):
yVel = horizVel * math.cos(rotation)
zVel = INITIAL_VELOCITY * math.sin(angle)
startVel = Vec3(xVel, yVel, zVel)
trajectory = Trajectory.Trajectory(launchTime, startPos, startVel)
trajectory = Trajectory(launchTime, startPos, startVel)
towerList = [towerPos + Point3(0, 0, BUCKET_HEIGHT), TOWER_RADIUS, TOWER_HEIGHT - BUCKET_HEIGHT]
self.notify.debug('calcFlightResults(%s): rotation(%s), angle(%s), horizVel(%s), xVel(%s), yVel(%s), zVel(%s), startVel(%s), trajectory(%s), towerList(%s)' % (avId,
rotation,
@ -701,7 +730,6 @@ class DistributedCannonGame(DistributedMinigame):
avId = task.avId
self.notify.debug('FIRING CANNON FOR AVATAR ' + str(avId))
startPos, startHpr, startVel, trajectory, timeOfImpact, hitWhat = self.__calcFlightResults(avId, launchTime)
self.notify.debug('start position: ' + str(startPos))
self.notify.debug('start velocity: ' + str(startVel))
self.notify.debug('time of launch: ' + str(launchTime))
@ -713,12 +741,13 @@ class DistributedCannonGame(DistributedMinigame):
self.notify.debug('toon will hit the tower')
else:
self.notify.debug('toon will hit the ground')
head = self.toonHeadDict[avId]
head.stopBlink()
head.stopLookAroundNow()
head.reparentTo(hidden)
head.reparentTo(base.hidden)
av = self.toonModelDict[avId]
av.reparentTo(render)
av.reparentTo(base.render)
av.setPos(startPos)
av.setHpr(startHpr)
avatar = self.getAvatar(avId)
@ -737,7 +766,7 @@ class DistributedCannonGame(DistributedMinigame):
info['hRot'] = self.cannonPositionDict[avId][0]
info['haveWhistled'] = 0
info['maxCamPullback'] = CAMERA_PULLBACK_MIN
info['timeEnterTowerXY'], info['timeExitTowerXY'] = trajectory.calcEnterAndLeaveCylinderXY(self.tower.getPos(render), TOWER_RADIUS)
info['timeEnterTowerXY'], info['timeExitTowerXY'] = trajectory.calcEnterAndLeaveCylinderXY(self.tower.getPos(base.render), TOWER_RADIUS)
shootTask.info = info
flyTask.info = info
seqDoneTask.info = info
@ -746,7 +775,8 @@ class DistributedCannonGame(DistributedMinigame):
if avId == self.localAvId:
if info['hitWhat'] == self.HIT_WATER:
self.sendUpdate('setToonWillLandInWater', [info['timeOfImpact']])
return Task.done
return task.done
def __calcToonImpact(self, trajectory, waterTower):
self.notify.debug('trajectory: %s' % trajectory)
@ -757,10 +787,12 @@ class DistributedCannonGame(DistributedMinigame):
self.notify.debug('t_waterImpact: %s' % t_waterImpact)
if t_waterImpact > 0:
return (t_waterImpact, self.HIT_WATER)
t_towerImpact = trajectory.checkCollisionWithCylinderSides(waterTower[0], waterTower[1], waterTower[2])
self.notify.debug('t_towerImpact: %s' % t_towerImpact)
if t_towerImpact > 0:
return (t_towerImpact, self.HIT_TOWER)
t_groundImpact = trajectory.checkCollisionWithGround()
self.notify.debug('t_groundImpact: %s' % t_groundImpact)
if t_groundImpact >= trajectory.getStartTime():
@ -771,8 +803,8 @@ class DistributedCannonGame(DistributedMinigame):
def __shootTask(self, task):
base.playSfx(self.sndCannonFire)
self.dropShadowDict[task.info['avId']].reparentTo(render)
return Task.done
self.dropShadowDict[task.info['avId']].reparentTo(base.render)
return task.done
def __flyTask(self, task):
curTime = task.time + task.info['launchTime']
@ -780,10 +812,11 @@ class DistributedCannonGame(DistributedMinigame):
pos = task.info['trajectory'].getPos(t)
task.info['toon'].setPos(pos)
shadowPos = Point3(pos)
if t >= task.info['timeEnterTowerXY'] and t <= task.info['timeExitTowerXY'] and pos[2] >= self.tower.getPos(render)[2] + TOWER_HEIGHT:
shadowPos.setZ(self.tower.getPos(render)[2] + TOWER_HEIGHT + SHADOW_Z_OFFSET)
if t >= task.info['timeEnterTowerXY'] and t <= task.info['timeExitTowerXY'] and pos[2] >= self.tower.getPos(base.render)[2] + TOWER_HEIGHT:
shadowPos.setZ(self.tower.getPos(base.render)[2] + TOWER_HEIGHT + SHADOW_Z_OFFSET)
else:
shadowPos.setZ(SHADOW_Z_OFFSET)
self.dropShadowDict[task.info['avId']].setPos(shadowPos)
vel = task.info['trajectory'].getVel(t)
run = math.sqrt(vel[0] * vel[0] + vel[1] * vel[1])
@ -791,7 +824,7 @@ class DistributedCannonGame(DistributedMinigame):
theta = self.__toDegrees(math.atan(rise / run))
task.info['toon'].setHpr(task.info['hRot'], -90 + theta, 0)
if task.info['avId'] == self.localAvId:
lookAt = self.tower.getPos(render)
lookAt = self.tower.getPos(base.render)
lookAt.setZ(lookAt.getZ() - TOWER_HEIGHT / 2.0)
towerPos = Point3(self.towerPos)
towerPos.setZ(TOWER_HEIGHT)
@ -804,26 +837,31 @@ class DistributedCannonGame(DistributedMinigame):
perp.normalize()
if ttVec.dot(perp) > 0.0:
perp = Vec3(-perp[0], -perp[1], -perp[2])
a = 1.0 - toonTowerDist / TOON_TOWER_THRESHOLD
a_2 = a * a
multiplier = -2.0 * a_2 * a + 3 * a_2
lookAt = lookAt + perp * (multiplier * MAX_LOOKAT_OFFSET)
foo = Vec3(pos - lookAt)
foo.normalize()
task.info['maxCamPullback'] = max(task.info['maxCamPullback'], CAMERA_PULLBACK_MIN + multiplier * (CAMERA_PULLBACK_MAX - CAMERA_PULLBACK_MIN))
foo = foo * task.info['maxCamPullback']
camPos = pos + Point3(foo)
camera.setPos(camPos)
camera.lookAt(pos)
base.camera.setPos(camPos)
base.camera.lookAt(pos)
if task.info['haveWhistled'] == 0:
if -vel[2] > WHISTLE_SPEED:
if t < task.info['timeOfImpact'] - 0.5:
task.info['haveWhistled'] = 1
base.playSfx(self.sndWhizz)
if t == task.info['timeOfImpact']:
if task.info['haveWhistled']:
self.sndWhizz.stop()
self.dropShadowDict[task.info['avId']].reparentTo(hidden)
self.dropShadowDict[task.info['avId']].reparentTo(base.hidden)
avatar = self.getAvatar(task.info['avId'])
if task.info['hitWhat'] == self.HIT_WATER:
avatar.loop('neutral')
@ -853,15 +891,17 @@ class DistributedCannonGame(DistributedMinigame):
avatar.pose('slip-forward', 25)
base.playSfx(self.sndHitTower)
elif task.info['hitWhat'] == self.HIT_GROUND:
task.info['toon'].setP(render, -150.0)
task.info['toon'].setP(base.render, -150.0)
self.dustCloud.setPos(task.info['toon'], 0, 0, -2.5)
self.dustCloud.setScale(0.35)
self.dustCloud.play()
base.playSfx(self.sndHitGround)
avatar.setPlayRate(2.0, 'run')
avatar.loop('run')
return Task.done
return Task.cont
return task.done
return task.cont
def __flySequenceDoneTask(self, task):
self.airborneToons -= 1
@ -872,7 +912,8 @@ class DistributedCannonGame(DistributedMinigame):
self.__loadToonInCannon(task.info['avId'])
if task.info['avId'] == self.localAvId:
self.gameFSM.request('aim')
return Task.done
return task.done
def __startRewardCountdown(self):
taskMgr.remove(self.REWARD_COUNTDOWN_TASK)
@ -883,24 +924,29 @@ class DistributedCannonGame(DistributedMinigame):
def __updateRewardCountdown(self, task):
if not hasattr(self, 'rewardPanel'):
return Task.cont
return task.cont
curTime = self.getCurrentGameTime()
if self.clockStopTime is not None:
if self.clockStopTime < curTime:
self.__killRewardCountdown()
curTime = self.clockStopTime
score = int(self.scoreMult * CannonGameGlobals.calcScore(curTime) + 0.5)
if not hasattr(task, 'curScore'):
task.curScore = score
self.rewardPanel['text'] = str(score)
if task.curScore != score:
if hasattr(self, 'jarIval'):
self.jarIval.finish()
s = self.rewardPanel.getScale()
self.jarIval = Parallel(Sequence(self.rewardPanel.scaleInterval(0.15, s * 3.0 / 4.0, blendType='easeOut'), self.rewardPanel.scaleInterval(0.15, s, blendType='easeIn')), SoundInterval(self.sndRewardTick), name='cannonGameRewardJarThrob')
self.jarIval.start()
task.curScore = score
return Task.cont
return task.cont
def __startIntro(self):
self.T_WATER = 1
@ -926,18 +972,19 @@ class DistributedCannonGame(DistributedMinigame):
if self.introCameraSeq:
self.introCameraSeq.finish()
self.introCameraSeq = None
camera.wrtReparentTo(render)
base.camera.wrtReparentTo(base.render)
def __spawnCameraLookAtLerp(self, targetPos, targetLookAt, duration):
oldPos = camera.getPos()
oldHpr = camera.getHpr()
camera.setPos(targetPos)
camera.lookAt(targetLookAt)
oldPos = base.camera.getPos()
oldHpr = base.camera.getHpr()
base.camera.setPos(targetPos)
base.camera.lookAt(targetLookAt)
targetQuat = Quat()
targetQuat.setHpr(camera.getHpr())
camera.setPos(oldPos)
camera.setHpr(oldHpr)
self.introCameraSeq = camera.posQuatInterval(duration, Point3(targetPos), targetQuat, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP)
targetQuat.setHpr(base.camera.getHpr())
base.camera.setPos(oldPos)
base.camera.setHpr(oldHpr)
self.introCameraSeq = base.camera.posQuatInterval(duration, Point3(targetPos), targetQuat, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP)
self.introCameraSeq.start()
def __taskLookInWater(self, task):
@ -949,40 +996,40 @@ class DistributedCannonGame(DistributedMinigame):
vecAwayFromCannons.normalize()
camLoc = Point3(vecAwayFromCannons * 20) + Point3(0, 0, 20)
camLoc = camLoc + task.data['towerWaterCenter']
camera.setPos(camLoc)
camera.lookAt(task.data['towerWaterCenter'])
base.camera.setPos(camLoc)
base.camera.lookAt(task.data['towerWaterCenter'])
task.data['vecAwayFromCannons'] = vecAwayFromCannons
return Task.done
return task.done
def __taskPullBackFromWater(self, task):
camLoc = Point3(task.data['vecAwayFromCannons'] * 40) + Point3(0, 0, 20)
camLoc = camLoc + task.data['towerWaterCenter']
lookAt = task.data['cannonCenter']
self.__spawnCameraLookAtLerp(camLoc, lookAt, self.T_WATER2LONGVIEW)
return Task.done
return task.done
def __flyUpToToon(self, task):
headPos = self.toonHeadDict[self.localAvId].getPos(render)
headPos = self.toonHeadDict[self.localAvId].getPos(base.render)
camLoc = headPos + Point3(0, 5, 0)
lookAt = Point3(headPos)
self.__spawnCameraLookAtLerp(camLoc, lookAt, self.T_LONGVIEW2TOONHEAD)
return Task.done
return task.done
def __flyToBackOfCannon(self, task):
lerpNode = hidden.attachNewNode('CannonGameCameraLerpNode')
lerpNode.reparentTo(render)
lerpNode = base.hidden.attachNewNode('CannonGameCameraLerpNode')
lerpNode.reparentTo(base.render)
lerpNode.setPos(self.cannonLocationDict[self.localAvId] + Point3(0, 1, 0))
relCamPos = camera.getPos(lerpNode)
relCamHpr = camera.getHpr(lerpNode)
relCamPos = base.camera.getPos(lerpNode)
relCamHpr = base.camera.getHpr(lerpNode)
startRotation = lerpNode.getHpr()
endRotation = Point3(-180, 0, 0)
lerpNode.setHpr(endRotation)
camera.setPos(self.__getCameraPositionBehindCannon())
endPos = camera.getPos(lerpNode)
base.camera.setPos(self.__getCameraPositionBehindCannon())
endPos = base.camera.getPos(lerpNode)
lerpNode.setHpr(startRotation)
camera.reparentTo(lerpNode)
camera.setPos(relCamPos)
camera.setHpr(relCamHpr)
self.introCameraSeq = Parallel(lerpNode.hprInterval(self.T_TOONHEAD2CANNONBACK, endRotation, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP), camera.posInterval(self.T_TOONHEAD2CANNONBACK, endPos, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP))
base.camera.reparentTo(lerpNode)
base.camera.setPos(relCamPos)
base.camera.setHpr(relCamHpr)
self.introCameraSeq = Parallel(lerpNode.hprInterval(self.T_TOONHEAD2CANNONBACK, endRotation, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP), base.camera.posInterval(self.T_TOONHEAD2CANNONBACK, endPos, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP))
self.introCameraSeq.start()
return Task.done
return task.done

View File

@ -11,7 +11,7 @@ from toontown.minigame import PlayingCardDeck
from toontown.minigame import PairingGameGlobals
from .OrthoWalk import OrthoWalk
from .OrthoDrive import OrthoDrive
from direct.interval.IntervalGlobal import Sequence, Parallel, Func, LerpColorScaleInterval, LerpScaleInterval, LerpFunctionInterval, Wait, SoundInterval
from direct.interval.IntervalGlobal import Sequence, Parallel, Func, LerpColorScaleInterval, LerpScaleInterval, LerpFunctionInterval, Wait, SoundInterval, WaitInterval
from toontown.toonbase.ToontownGlobals import GlobalDialogColor
class DistributedPairingGame(DistributedMinigame):

View File

@ -1,22 +1,36 @@
from panda3d.core import *
from toontown.toonbase.ToonBaseGlobal import *
from direct.interval.IntervalGlobal import *
from .DistributedMinigame import *
from direct.gui.DirectGui import *
from panda3d.core import *
from direct.fsm import ClassicFSM, State
from direct.fsm import State
from toontown.toonbase import ToontownTimer
from . import PatternGameGlobals
from toontown.toon import ToonHead
from toontown.char import CharDNA
from toontown.char import Char
from . import ArrowKeys
import random
from panda3d.core import Point3, VBase4, Vec3
from panda3d.otp import CFSpeech, NametagGlobals
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.fsm.ClassicFSM import ClassicFSM
from direct.fsm.State import State
from direct.gui.DirectGui import DirectLabel
from direct.interval.IntervalGlobal import (
ActorInterval,
Func,
LerpColorInterval,
LerpHprInterval,
LerpPosInterval,
Parallel,
Sequence,
Wait
)
from toontown.char.Char import Char
from toontown.char.CharDNA import CharDNA
from toontown.minigame import PatternGameGlobals
from toontown.minigame.ArrowKeys import ArrowKeys
from toontown.minigame.DistributedMinigame import DistributedMinigame
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import TTLocalizer
from toontown.toonbase.ToonBaseGlobal import base
from toontown.toonbase.ToontownTimer import ToontownTimer
from random import choice
class DistributedPatternGame(DistributedMinigame):
notify = directNotify.newCategory('DistributedPatternGame')
phase4snd = 'phase_4/audio/sfx/'
ButtonSoundNames = (phase4snd + 'm_match_trumpet.ogg',
phase4snd + 'm_match_guitar.ogg',
@ -46,14 +60,14 @@ class DistributedPatternGame(DistributedMinigame):
def __init__(self, cr):
DistributedMinigame.__init__(self, cr)
self.gameFSM = ClassicFSM.ClassicFSM('DistributedPatternGame', [State.State('off', self.enterOff, self.exitOff, ['waitForServerPattern']),
State.State('waitForServerPattern', self.enterWaitForServerPattern, self.exitWaitForServerPattern, ['showServerPattern', 'cleanup']),
State.State('showServerPattern', self.enterShowServerPattern, self.exitShowServerPattern, ['getUserInput', 'playBackPatterns', 'cleanup']),
State.State('getUserInput', self.enterGetUserInput, self.exitGetUserInput, ['waitForPlayerPatterns', 'playBackPatterns', 'cleanup']),
State.State('waitForPlayerPatterns', self.enterWaitForPlayerPatterns, self.exitWaitForPlayerPatterns, ['playBackPatterns', 'cleanup', 'checkGameOver']),
State.State('playBackPatterns', self.enterPlayBackPatterns, self.exitPlayBackPatterns, ['checkGameOver', 'cleanup']),
State.State('checkGameOver', self.enterCheckGameOver, self.exitCheckGameOver, ['waitForServerPattern', 'cleanup']),
State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup')
self.gameFSM = ClassicFSM('DistributedPatternGame', [State('off', self.enterOff, self.exitOff, ['waitForServerPattern']),
State('waitForServerPattern', self.enterWaitForServerPattern, self.exitWaitForServerPattern, ['showServerPattern', 'cleanup']),
State('showServerPattern', self.enterShowServerPattern, self.exitShowServerPattern, ['getUserInput', 'playBackPatterns', 'cleanup']),
State('getUserInput', self.enterGetUserInput, self.exitGetUserInput, ['waitForPlayerPatterns', 'playBackPatterns', 'cleanup']),
State('waitForPlayerPatterns', self.enterWaitForPlayerPatterns, self.exitWaitForPlayerPatterns, ['playBackPatterns', 'cleanup', 'checkGameOver']),
State('playBackPatterns', self.enterPlayBackPatterns, self.exitPlayBackPatterns, ['checkGameOver', 'cleanup']),
State('checkGameOver', self.enterCheckGameOver, self.exitCheckGameOver, ['waitForServerPattern', 'cleanup']),
State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup')
self.addChildGameFSM(self.gameFSM)
self.arrowColor = VBase4(1, 0, 0, 1)
self.xColor = VBase4(1, 0, 0, 1)
@ -63,7 +77,6 @@ class DistributedPatternGame(DistributedMinigame):
self.opaq = VBase4(1, 0, 0, 1)
self.normalTextColor = VBase4(0.537, 0.84, 0.33, 1.0)
self.__otherToonIndex = {}
return
def getTitle(self):
return TTLocalizer.PatternGameTitle
@ -78,10 +91,10 @@ class DistributedPatternGame(DistributedMinigame):
def load(self):
self.notify.debug('load')
DistributedMinigame.load(self)
self.timer = ToontownTimer.ToontownTimer()
self.timer = ToontownTimer()
self.timer.posInTopRightCorner()
self.timer.hide()
self.room = loader.loadModel('phase_4/models/minigames/matching_room')
self.room = base.loader.loadModel('phase_4/models/minigames/matching_room')
self.buttonSounds = []
for soundName in self.ButtonSoundNames:
self.buttonSounds.append(base.loader.loadSfx(soundName))
@ -95,18 +108,18 @@ class DistributedPatternGame(DistributedMinigame):
self.roundText = DirectLabel(text=self.strRound % 1, text_fg=self.normalTextColor, frameColor=(1, 1, 1, 0), text_font=ToontownGlobals.getSignFont(), pos=(0.014, 0, -.84), scale=0.12)
self.roundText.hide()
self.waitingText.hide()
matchingGameGui = loader.loadModel('phase_3.5/models/gui/matching_game_gui')
matchingGameGui = base.loader.loadModel('phase_3.5/models/gui/matching_game_gui')
minnieArrow = matchingGameGui.find('**/minnieArrow')
minnieX = matchingGameGui.find('**/minnieX')
minnieCircle = matchingGameGui.find('**/minnieCircle')
self.arrows = [None] * 5
for x in range(0, 5):
self.arrows[x] = minnieArrow.copyTo(hidden)
self.arrows[x] = minnieArrow.copyTo(base.hidden)
self.arrows[x].hide()
self.xs = [None] * 5
for x in range(0, 5):
self.xs[x] = minnieX.copyTo(hidden)
self.xs[x] = minnieX.copyTo(base.hidden)
self.xs[x].hide()
self.statusBalls = []
@ -116,20 +129,20 @@ class DistributedPatternGame(DistributedMinigame):
for x in range(0, 4):
for y in range(0, self.totalMoves):
self.statusBalls[x][y] = minnieCircle.copyTo(hidden)
self.statusBalls[x][y] = minnieCircle.copyTo(base.hidden)
self.statusBalls[x][y].hide()
minnieArrow.removeNode()
minnieX.removeNode()
minnieCircle.removeNode()
matchingGameGui.removeNode()
self.minnie = Char.Char()
self.minnie = Char()
m = self.minnie
dna = CharDNA.CharDNA()
dna = CharDNA()
dna.newChar('mn')
m.setDNA(dna)
m.setName(TTLocalizer.Minnie)
m.reparentTo(hidden)
m.reparentTo(base.hidden)
self.backRowHome = Point3(3, 11, 0)
self.backRowXSpacing = 1.8
self.frontRowHome = Point3(0, 18, 0)
@ -140,12 +153,10 @@ class DistributedPatternGame(DistributedMinigame):
self.animPlayRates = []
animPlayRate = 1.4
animPlayRateMult = 1.06
for i in range(PatternGameGlobals.NUM_ROUNDS):
for _ in range(PatternGameGlobals.NUM_ROUNDS):
self.animPlayRates.append(animPlayRate)
animPlayRate *= animPlayRateMult
return
def unload(self):
self.notify.debug('unload')
DistributedMinigame.unload(self)
@ -201,12 +212,12 @@ class DistributedPatternGame(DistributedMinigame):
DistributedMinigame.onstage(self)
self.arrowDict = {}
self.lt = base.localAvatar
camera.reparentTo(render)
camera.setPosHpr(0.0, -14.59, 10.56, 0.0, -16.39, 0.0)
base.camera.reparentTo(base.render)
base.camera.setPosHpr(0.0, -14.59, 10.56, 0.0, -16.39, 0.0)
base.camLens.setFov(24.66)
NametagGlobals.setGlobalNametagScale(0.6)
self.arrowKeys = ArrowKeys.ArrowKeys()
self.room.reparentTo(render)
self.arrowKeys = ArrowKeys()
self.room.reparentTo(base.render)
self.room.setPosHpr(0.0, 18.39, -ToontownGlobals.FloorOffset, 0.0, 0.0, 0.0)
self.room.setScale(1)
for anim in self.minnieAnimNames:
@ -226,7 +237,7 @@ class DistributedPatternGame(DistributedMinigame):
self.toonAnimSpeedMult[anim] = float(self.__numPingPongFrames(numFrames)) / float(self.stdNumDanceStepPingPongFrames)
lt = self.lt
lt.reparentTo(render)
lt.reparentTo(base.render)
lt.useLOD(1000)
lt.setPos(-3.5, 11, 0.0)
lt.setScale(1)
@ -246,11 +257,12 @@ class DistributedPatternGame(DistributedMinigame):
else:
self.arrowDict['lt'][k].setScale(4, 4, 4)
self.arrowDict['lt'][k].setColor(self.xColor)
self.arrowDict['lt'][k].setPos(0, 0, 1)
self.formatStatusBalls(self.arrowDict['lt'][2], jj)
m = self.minnie
m.reparentTo(render)
m.reparentTo(base.render)
m.setPos(-1.6, 20, 0)
m.setScale(1)
self.makeToonLookatCamera(m)
@ -280,13 +292,13 @@ class DistributedPatternGame(DistributedMinigame):
NametagGlobals.setGlobalNametagScale(1.0)
self.arrowKeys.destroy()
del self.arrowKeys
self.room.reparentTo(hidden)
self.room.reparentTo(base.hidden)
self.roundText.hide()
self.minnie.nametag.unmanage(base.marginManager)
self.minnie.stopEarTask()
self.minnie.stop()
self.minnie.stopBlink()
self.minnie.reparentTo(hidden)
self.minnie.reparentTo(base.hidden)
self.lt.setScale(1)
for avId in self.remoteAvIdList:
toon = self.getAvatar(avId)
@ -303,9 +315,11 @@ class DistributedPatternGame(DistributedMinigame):
def setGameReady(self):
if not self.hasLocalToon:
return
self.notify.debug('setGameReady')
if DistributedMinigame.setGameReady(self):
return
for avId in self.remoteAvIdList:
toon = self.getAvatar(avId)
if toon:
@ -321,10 +335,11 @@ class DistributedPatternGame(DistributedMinigame):
else:
self.arrowDict[avId][k].setScale(4, 4, 4)
self.arrowDict[avId][k].setColor(self.xColor)
self.arrowDict[avId][k].setPos(0, 0, 1)
self.formatStatusBalls(self.arrowDict[avId][2], jj)
toon.reparentTo(render)
toon.reparentTo(base.render)
toon.useLOD(1000)
toon.setPos(self.getBackRowPos(avId))
toon.setScale(0.9)
@ -338,16 +353,17 @@ class DistributedPatternGame(DistributedMinigame):
self.waitingText['text'] = self.strPleaseWait
else:
self.waitingText['text'] = self.strWaitingOtherPlayers
self.animTracks = {}
for avId in self.avIdList:
self.animTracks[avId] = None
self.__initGameVars()
return
def setGameStart(self, timestamp):
if not self.hasLocalToon:
return
self.notify.debug('setGameStart')
DistributedMinigame.setGameStart(self, timestamp)
self.gameFSM.request('waitForServerPattern')
@ -360,7 +376,7 @@ class DistributedPatternGame(DistributedMinigame):
return numFrames * 2 - 1
def makeToonLookatCamera(self, toon):
toon.headsUp(camera)
toon.headsUp(base.camera)
def setText(self, t, newtext):
t['text'] = newtext
@ -376,6 +392,7 @@ class DistributedPatternGame(DistributedMinigame):
if startPos:
toon.setPos(startPos)
track.append(Func(toon.setPos, startPos))
for endPos in posList:
toon.headsUp(Point3(endPos))
track.append(Func(toon.setHpr, Point3(toon.getH(), 0, 0)))
@ -387,14 +404,16 @@ class DistributedPatternGame(DistributedMinigame):
if lookAtCam:
saveHpr = toon.getHpr()
toon.headsUp(camera)
toon.headsUp(base.camera)
endHeading = toon.getHpr()[0]
toon.setHpr(saveHpr)
curHeading = toon.getH()
if endHeading - curHeading > 180.0:
endHeading -= 360
elif endHeading - curHeading < -180.0:
endHeading += 360
endHpr = Point3(endHeading, 0, 0)
duration = abs(endHeading - curHeading) / 180.0 * 0.3
track.extend([Func(toon.loop, 'walk'), LerpHprInterval(toon, duration, endHpr), Func(toon.loop, 'neutral')])
@ -456,6 +475,7 @@ class DistributedPatternGame(DistributedMinigame):
ri.append(ActorInterval(actor=self.lt, animName='victory', duration=5.5))
else:
ri.append(Func(self.lt.loop, 'neutral'))
for avId in self.remoteAvIdList:
toon = self.getAvatar(avId)
if toon:
@ -503,18 +523,21 @@ class DistributedPatternGame(DistributedMinigame):
track = Sequence(Func(self.changeArrow, toonID, index), Wait(wait))
else:
track = Sequence(Func(self.changeArrow, toonID, index), Wait(wait), LerpColorInterval(self.arrowDict[toonID][0], d, self.trans, self.opaq))
return track
def getDanceSequenceAnimTrack(self, toon, pattern):
getDanceStepTrack = self.__getToonDanceStepAnimTrack
if toon == self.minnie:
getDanceStepTrack = self.__getMinnieDanceStepAnimTrack
tracks = Sequence()
for direction in pattern:
tracks.append(getDanceStepTrack(toon, direction))
if len(pattern):
tracks.append(Func(toon.loop, 'neutral'))
return tracks
def getDanceSequenceButtonSoundTrack(self, pattern):
@ -558,6 +581,7 @@ class DistributedPatternGame(DistributedMinigame):
def setPattern(self, pattern):
if not self.hasLocalToon:
return
self.notify.debug('setPattern: ' + str(pattern))
self.__serverPattern = pattern
self.gameFSM.request('showServerPattern')
@ -591,6 +615,7 @@ class DistributedPatternGame(DistributedMinigame):
def exitShowServerPattern(self):
if self.showTrack.isPlaying():
self.showTrack.pause()
del self.showTrack
def enterGetUserInput(self):
@ -599,7 +624,7 @@ class DistributedPatternGame(DistributedMinigame):
self.proceedTrack = None
def startTimer(self = self):
self.currentStartTime = globalClock.getFrameTime()
self.currentStartTime = base.clock.getFrameTime()
self.timer.show()
self.timer.countdown(PatternGameGlobals.InputTime, self.__handleInputTimeout)
@ -629,7 +654,6 @@ class DistributedPatternGame(DistributedMinigame):
self.setupTrack = Sequence(Func(self.__setMinnieChat, self.strGo, 0), Func(self.setText, self.roundText, TTLocalizer.PatternGameGo), Func(self.roundText.setScale, 0.3), Func(enableKeys), Func(startTimer), Wait(0.8), Func(self.__clearMinnieChat), Func(self.setText, self.roundText, ' '), Func(self.roundText.setScale, 0.12), Func(self.setTextFG, self.roundText, self.normalTextColor))
self.setupTrack.start()
return
def __handleInputTimeout(self):
self.__doneGettingInput(self.__localPattern)
@ -643,15 +667,18 @@ class DistributedPatternGame(DistributedMinigame):
def remoteButtonPressed(self, avId, index, wrong):
if not self.hasLocalToon:
return
if self.gameFSM.getCurrentState().getName() not in ['getUserInput', 'waitForPlayerPatterns']:
return
if avId != self.localAvId:
if self.animTracks[avId]:
self.animTracks[avId].finish()
av = self.getAvatar(avId)
if wrong:
acts = ['slip-forward', 'slip-backward']
ag = random.choice(acts)
ag = choice(acts)
self.arrowDict[avId][0].hide()
self.animTracks[avId] = Sequence(Func(self.showX, avId), Func(self.colorStatusBall, avId, self.__otherToonIndex[avId], 0), ActorInterval(actor=av, animName=ag, duration=2.35), Func(av.loop, 'neutral'), Func(self.hideX, avId))
else:
@ -659,6 +686,7 @@ class DistributedPatternGame(DistributedMinigame):
arrowTrack = self.getDanceArrowAnimTrack(avId, [index], 1)
potTrack = self.getDanceSequenceAnimTrack(av, [index])
self.animTracks[avId] = Parallel(potTrack, arrowTrack)
self.__otherToonIndex[avId] += 1
self.animTracks[avId].start()
@ -668,13 +696,15 @@ class DistributedPatternGame(DistributedMinigame):
def __buttonPressed(self, index):
if len(self.__localPattern) >= len(self.__serverPattern):
return
if self.animTracks[self.localAvId]:
self.animTracks[self.localAvId].finish()
badd = 0
if index != self.__serverPattern[len(self.__localPattern)]:
badd = 1
acts = ['slip-forward', 'slip-backward']
ag = random.choice(acts)
ag = choice(acts)
self.animTracks[self.localAvId] = Sequence(Func(self.showX, 'lt'), Func(self.colorStatusBall, 'lt', len(self.__localPattern), 0), ActorInterval(actor=self.lt, animName=ag, duration=2.35), Func(self.lt.loop, 'neutral'), Func(self.hideX, 'lt'))
self.arrowDict['lt'][0].hide()
base.playSfx(self.fallSound)
@ -684,6 +714,7 @@ class DistributedPatternGame(DistributedMinigame):
arrowTrack = self.getDanceArrowAnimTrack('lt', [index], 1)
potTrack = self.getDanceSequenceAnimTrack(self.lt, [index])
self.animTracks[self.localAvId] = Parallel(potTrack, arrowTrack)
self.sendUpdate('reportButtonPress', [index, badd])
self.animTracks[self.localAvId].start()
self.__localPattern.append(index)
@ -692,7 +723,7 @@ class DistributedPatternGame(DistributedMinigame):
def __doneGettingInput(self, pattern):
self.arrowKeys.setPressHandlers(self.arrowKeys.NULL_HANDLERS)
self.currentTotalTime = globalClock.getFrameTime() - self.currentStartTime
self.currentTotalTime = base.clock.getFrameTime() - self.currentStartTime
self.proceedTrack = Sequence(Wait(self.getDanceStepDuration()), Func(self.sendUpdate, 'reportPlayerPattern', [pattern, self.currentTotalTime]), Func(self.gameFSM.request, 'waitForPlayerPatterns'))
self.proceedTrack.start()
@ -703,8 +734,10 @@ class DistributedPatternGame(DistributedMinigame):
self.arrowKeys.setReleaseHandlers(self.arrowKeys.NULL_HANDLERS)
if self.setupTrack and self.setupTrack.isPlaying():
self.setupTrack.pause()
if self.proceedTrack and self.proceedTrack.isPlaying():
self.proceedTrack.pause()
del self.setupTrack
del self.proceedTrack
self.__clearMinnieChat()
@ -715,6 +748,7 @@ class DistributedPatternGame(DistributedMinigame):
def setPlayerPatterns(self, pattern1, pattern2, pattern3, pattern4, fastestAvId):
if not self.hasLocalToon:
return
self.fastestAvId = fastestAvId
self.notify.debug('setPlayerPatterns:' + ' pattern1:' + str(pattern1) + ' pattern2:' + str(pattern2) + ' pattern3:' + str(pattern3) + ' pattern4:' + str(pattern4))
self.playerPatterns = {}
@ -738,6 +772,7 @@ class DistributedPatternGame(DistributedMinigame):
self.roundText['text'] = TTLocalizer.PatternGameFastest
else:
self.roundText['text'] = TTLocalizer.PatternGameFaster
jumpTrack = Sequence(ActorInterval(actor=self.lt, animName='jump', duration=1.7), Func(self.lt.loop, 'neutral'))
elif self.fastestAvId == 0:
if self.round == PatternGameGlobals.NUM_ROUNDS:
@ -745,6 +780,7 @@ class DistributedPatternGame(DistributedMinigame):
else:
self.roundText.setScale(0.1)
self.roundText['text'] = TTLocalizer.PatternGameYouCanDoIt
jumpTrack = Sequence(Wait(0.5), Wait(0.5))
elif self.fastestAvId == 1:
self.roundText.setScale(0.1)
@ -758,7 +794,9 @@ class DistributedPatternGame(DistributedMinigame):
rewardStr = TTLocalizer.PatternGameOtherFastest
else:
rewardStr = TTLocalizer.PatternGameOtherFaster
self.roundText['text'] = av.getName() + rewardStr
success = self.playerPatterns[self.localAvId] == self.__serverPattern
self.hideStatusBalls('lt')
for avId in self.remoteAvIdList:
@ -771,6 +809,7 @@ class DistributedPatternGame(DistributedMinigame):
self.perfectGame = 0
sound = self.incorrectSound
text = self.strWrong
soundTrack = Sequence(Func(base.playSfx, sound), Wait(1.6))
textTrack = Sequence(Wait(0.2), Func(self.__setMinnieChat, text, 0), Wait(1.3), Func(self.__clearMinnieChat))
self.playBackPatternsTrack = Sequence(Parallel(soundTrack, textTrack, jumpTrack), Func(self.gameFSM.request, 'checkGameOver'))
@ -779,6 +818,7 @@ class DistributedPatternGame(DistributedMinigame):
def exitPlayBackPatterns(self):
if self.playBackPatternsTrack.isPlaying():
self.playBackPatternsTrack.pause()
del self.playBackPatternsTrack
def enterCheckGameOver(self):
@ -794,17 +834,19 @@ class DistributedPatternGame(DistributedMinigame):
text = self.strPerfect
sound = self.perfectSound
delay = 2.2
if self.celebrate:
text = TTLocalizer.PatternGameImprov
self.__winTrack = Sequence(Func(self.__setMinnieChat, text, 1), Func(base.playSfx, self.perfectSound), Sequence(self.returnCelebrationIntervals(1)), Sequence(self.returnCelebrationIntervals(0)), Func(self.__clearMinnieChat), Func(self.gameOver))
else:
self.__winTrack = Sequence(Func(self.__setMinnieChat, text, 1), Func(base.playSfx, sound), Wait(delay), Func(self.__clearMinnieChat), Func(self.gameOver))
self.__winTrack.start()
return
def exitCheckGameOver(self):
if self.__winTrack and self.__winTrack.isPlaying():
self.__winTrack.pause()
del self.__winTrack
def enterCleanup(self):

View File

@ -28,6 +28,8 @@ from toontown.makeatoon import NameGenerator
from otp.otpbase import OTPGlobals
from toontown.battle import BattleParticles
from toontown.minigame import PhotoGameBase
from panda3d.otp import *
WORLD_SCALE = 2.0
FAR_PLANE_DIST = 600 * WORLD_SCALE
STAGE_Z_OFFSET = 7.0
@ -243,6 +245,11 @@ class DistributedPhotoGame(DistributedMinigame, PhotoGameBase.PhotoGameBase):
self.removeChildGameFSM(self.gameFSM)
del self.gameFSM
self.ignoreAll()
for rayEntry in self.rayArray:
rayEntry[3].remove_node()
del self.rayArray
return
def onstage(self):

View File

@ -137,10 +137,10 @@ class DistributedTargetGame(DistributedMinigame):
UPDATE_RUBBER_BAND_PRIORITY = 2
COLLISION_DETECTION_PRIORITY = 5
UPDATE_SHADOWS_PRIORITY = 47
UMBRELLA_TEXTURE_LIST = ['phase_4/maps/mg_slingshot_umbrella_blue.jpg',
'phase_4/maps/mg_slingshot_umbrella_purple.jpg',
'phase_4/maps/mg_slingshot_umbrella_red.jpg',
'phase_4/maps/mg_slingshot_umbrella_yellow.jpg']
UMBRELLA_TEXTURE_LIST = ['phase_4/maps/mg_slingshot_umbrella_blue.png',
'phase_4/maps/mg_slingshot_umbrella_purple.png',
'phase_4/maps/mg_slingshot_umbrella_red.png',
'phase_4/maps/mg_slingshot_umbrella_yellow.png']
RT_UNKNOWN = 0
RT_SUCCESS = 1
RT_GROUPSUCCESS = 2

View File

@ -1,30 +1,42 @@
from panda3d.core import *
from toontown.toonbase.ToonBaseGlobal import *
from direct.interval.IntervalGlobal import *
from .DistributedMinigame import *
from direct.gui.DirectGui import *
from panda3d.core import *
from direct.fsm import ClassicFSM, State
from direct.fsm import State
from toontown.toonbase import ToontownTimer
from toontown.toon import ToonHead
from toontown.suit import SuitDNA
from toontown.suit import Suit
from toontown.char import Char
from . import ArrowKeys
import random
from panda3d.core import RopeNode, VBase3
from panda3d.otp import NametagGlobals
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.fsm.ClassicFSM import ClassicFSM
from direct.fsm.State import State
from direct.gui.DirectGui import DGG, DirectLabel
from direct.interval.IntervalGlobal import (
ActorInterval,
Func,
LerpHprInterval,
LerpPosInterval,
LerpPosHprInterval,
Parallel,
Sequence,
Wait
)
from direct.showutil.Rope import Rope
from direct.task.TaskManagerGlobal import taskMgr
from toontown.effects.Ripples import Ripples
from toontown.effects.Splash import Splash
from toontown.minigame import TugOfWarGameGlobals
from toontown.minigame.ArrowKeys import ArrowKeys
from toontown.minigame.DistributedMinigame import DistributedMinigame
from toontown.minigame.MinigamePowerMeter import MinigamePowerMeter
from toontown.suit.Suit import Suit
from toontown.suit.SuitDNA import SuitDNA
from toontown.toonbase import ToontownGlobals
import string
from toontown.toonbase import TTLocalizer
from . import TugOfWarGameGlobals
from direct.showutil import Rope
from toontown.effects import Splash
from toontown.effects import Ripples
from toontown.toonbase import TTLocalizer
from . import MinigamePowerMeter
from direct.task.Task import Task
from toontown.toonbase.ToonBaseGlobal import base
from toontown.toonbase.ToontownTimer import ToontownTimer
import math
class DistributedTugOfWarGame(DistributedMinigame):
notify = directNotify.newCategory('DistributedTugOfWarGame')
bgm = 'phase_4/audio/bgm/MG_tug_o_war.ogg'
toonAnimNames = ['neutral',
'tug-o-war',
@ -46,11 +58,11 @@ class DistributedTugOfWarGame(DistributedMinigame):
def __init__(self, cr):
DistributedMinigame.__init__(self, cr)
self.gameFSM = ClassicFSM.ClassicFSM('DistributedTugOfWarGame', [State.State('off', self.enterOff, self.exitOff, ['waitForGoSignal']),
State.State('waitForGoSignal', self.enterWaitForGoSignal, self.exitWaitForGoSignal, ['tug', 'cleanup']),
State.State('tug', self.enterTug, self.exitTug, ['gameDone', 'cleanup']),
State.State('gameDone', self.enterGameDone, self.exitGameDone, ['cleanup']),
State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup')
self.gameFSM = ClassicFSM('DistributedTugOfWarGame', [State('off', self.enterOff, self.exitOff, ['waitForGoSignal']),
State('waitForGoSignal', self.enterWaitForGoSignal, self.exitWaitForGoSignal, ['tug', 'cleanup']),
State('tug', self.enterTug, self.exitTug, ['gameDone', 'cleanup']),
State('gameDone', self.enterGameDone, self.exitGameDone, ['cleanup']),
State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup')
self.addChildGameFSM(self.gameFSM)
self.gameType = TugOfWarGameGlobals.TOON_VS_TOON
self.suit = None
@ -92,13 +104,11 @@ class DistributedTugOfWarGame(DistributedMinigame):
for k in range(4):
self.drinkPositions.append(VBase3(-.2 + 0.2 * k, 16 + 2 * k, 0.0))
self.rng = RandomNumGen.RandomNumGen(1000)
self.introTrack = None
self.showTrack = None
self.setupTrack = None
self.animTracks = {}
self.randomNumGen = None
return
def getTitle(self):
return TTLocalizer.TugOfWarGameTitle
@ -112,40 +122,39 @@ class DistributedTugOfWarGame(DistributedMinigame):
def load(self):
self.notify.debug('load')
DistributedMinigame.load(self)
self.timer = ToontownTimer.ToontownTimer()
self.timer = ToontownTimer()
self.timer.posInTopRightCorner()
self.timer.hide()
self.room = loader.loadModel('phase_4/models/minigames/tug_of_war_dock')
self.room.reparentTo(hidden)
ropeModel = loader.loadModel('phase_4/models/minigames/tug_of_war_rope')
self.room = base.loader.loadModel('phase_4/models/minigames/tug_of_war_dock')
self.room.reparentTo(base.hidden)
ropeModel = base.loader.loadModel('phase_4/models/minigames/tug_of_war_rope')
self.ropeTexture = ropeModel.findTexture('*')
ropeModel.removeNode()
self.sky = loader.loadModel('phase_3.5/models/props/TT_sky')
self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow')
self.sky = base.loader.loadModel('phase_3.5/models/props/TT_sky')
self.dropShadow = base.loader.loadModel('phase_3/models/props/drop_shadow')
self.correctSound = base.loader.loadSfx('phase_4/audio/sfx/MG_pos_buzzer.ogg')
self.sndHitWater = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_splash.ogg')
self.whistleSound = base.loader.loadSfx('phase_4/audio/sfx/AA_sound_whistle.ogg')
self.music = base.loader.loadMusic(self.bgm)
self.roundText = DirectLabel(text=' ', text_fg=(0, 1, 0, 1), frameColor=(1, 1, 1, 0), text_font=ToontownGlobals.getSignFont(), pos=(0.014, 0, -.84), scale=0.2)
self.powerMeter = MinigamePowerMeter.MinigamePowerMeter(17)
self.powerMeter.reparentTo(aspect2d)
self.powerMeter = MinigamePowerMeter(17)
self.powerMeter.reparentTo(base.aspect2d)
self.powerMeter.setPos(0, 0, 0.4)
self.powerMeter.setPower(8)
self.powerMeter.setTarget(8)
self.arrows = [None] * 2
for x in range(len(self.arrows)):
self.arrows[x] = loader.loadModel('phase_3/models/props/arrow')
self.arrows[x] = base.loader.loadModel('phase_3/models/props/arrow')
self.arrows[x].reparentTo(self.powerMeter)
self.arrows[x].hide()
self.arrows[x].setScale(0.2 - 0.4 * x, 0.2, 0.2)
self.arrows[x].setPos(0.12 - 0.24 * x, 0, -.26)
self.disableArrow(self.arrows[x])
self.splash = Splash.Splash(render)
self.suitSplash = Splash.Splash(render)
self.ripples = Ripples.Ripples(render)
self.suitRipples = Ripples.Ripples(render)
return
self.splash = Splash(base.render)
self.suitSplash = Splash(base.render)
self.ripples = Ripples(base.render)
self.suitRipples = Ripples(base.render)
def toggleMouseMode(self, param):
self.mouseMode = not self.mouseMode
@ -155,6 +164,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.hilightArrow(self.arrows[1])
else:
self.hilightArrow(self.arrows[0])
self.__spawnMouseSpeedTask()
else:
self.__releaseHandler(0)
@ -183,6 +193,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
if self.powerMeter:
self.powerMeter.destroy()
del self.powerMeter
for x in self.arrows:
if x:
x.removeNode()
@ -197,10 +208,12 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.ripples.stop()
self.ripples.detachNode()
del self.ripples
if self.suitRipples != None:
self.suitRipples.stop()
self.suitRipples.detachNode()
del self.suitRipples
for x in self.avList:
del x
@ -208,6 +221,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
for x in self.tugRopes:
if x != None:
x.detachNode()
del x
del self.tugRopes
@ -235,6 +249,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
if self.suit:
self.suit.delete()
del self.suit
del self.sides
del self.buttons
del self.pullingDict
@ -245,26 +260,24 @@ class DistributedTugOfWarGame(DistributedMinigame):
del self.drinkPositions
del self.offsetDict
del self.keyTTL
del self.rng
return
def onstage(self):
self.notify.debug('onstage')
DistributedMinigame.onstage(self)
self.lt = base.localAvatar
NametagGlobals.setGlobalNametagScale(1)
self.arrowKeys = ArrowKeys.ArrowKeys()
self.room.reparentTo(render)
self.arrowKeys = ArrowKeys()
self.room.reparentTo(base.render)
self.room.setPosHpr(0.0, 18.39, -ToontownGlobals.FloorOffset, 0.0, 0.0, 0.0)
self.room.setScale(0.4)
self.sky.setZ(-5)
self.sky.reparentTo(render)
self.sky.reparentTo(base.render)
self.dropShadow.setColor(0, 0, 0, 0.5)
camera.reparentTo(render)
camera.setPosHpr(-11.4427, 9.03559, 2.80094, -49.104, -0.89, 0)
base.camera.reparentTo(base.render)
base.camera.setPosHpr(-11.4427, 9.03559, 2.80094, -49.104, -0.89, 0)
self.dropShadow.setBin('fixed', 0, 1)
self.splash.reparentTo(render)
self.suitSplash.reparentTo(render)
self.splash.reparentTo(base.render)
self.suitSplash.reparentTo(base.render)
base.playMusic(self.music, looping=1, volume=1)
for x in range(len(self.arrows)):
self.arrows[x].show()
@ -280,20 +293,24 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.introTrack.finish()
del self.introTrack
self.introTrack = None
for track in list(self.animTracks.values()):
if track:
track.finish()
del track
self.animTracks = {}
if self.showTrack:
self.showTrack.finish()
del self.showTrack
self.showTrack = None
if self.setupTrack:
self.setupTrack.finish()
del self.setupTrack
self.setupTrack = None
base.camLens.setFov(ToontownGlobals.DefaultCameraFov)
base.camLens.setNearFar(ToontownGlobals.DefaultCameraNear, ToontownGlobals.DefaultCameraFar)
NametagGlobals.setGlobalNametagScale(1.0)
@ -303,13 +320,14 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.arrowKeys.destroy()
del self.arrowKeys
self.arrowKeys = None
self.room.reparentTo(hidden)
self.sky.reparentTo(hidden)
self.splash.reparentTo(hidden)
self.room.reparentTo(base.hidden)
self.sky.reparentTo(base.hidden)
self.splash.reparentTo(base.hidden)
self.splash.stop()
self.suitSplash.reparentTo(hidden)
self.suitSplash.reparentTo(base.hidden)
self.suitSplash.stop()
self.ripples.reparentTo(hidden)
self.ripples.reparentTo(base.hidden)
self.ripples.stop()
self.hideControls()
self.roundText.hide()
@ -322,42 +340,36 @@ class DistributedTugOfWarGame(DistributedMinigame):
for x in self.tugRopes:
if x != None:
x.reparentTo(hidden)
x.reparentTo(base.hidden)
if self.suit:
self.suit.reparentTo(hidden)
self.suit.reparentTo(base.hidden)
for avId in self.avIdList:
if avId in self.dropShadowDict:
self.dropShadowDict[avId].reparentTo(hidden)
self.dropShadowDict[avId].reparentTo(base.hidden)
if self.suitId in self.dropShadowDict:
self.dropShadowDict[self.suitId].reparentTo(hidden)
return
self.dropShadowDict[self.suitId].reparentTo(base.hidden)
def initCamera(self):
birdseyePosHpr = [1.95461,
18.4891,
38.4646,
1.18185,
-87.5308,
0]
introPosHpr = [None] * 2
introPosHpr[0] = [VBase3(-11.4427, 9.03559, 2.80094), VBase3(-49.104, -0.732374, 0)]
introPosHpr[1] = [VBase3(16.9291, 13.9302, 2.64282), VBase3(66.9685, -6.195, 0)]
gameCamHpr = VBase3(-1.13, 1.042, 0)
gameCamPos = VBase3(0, 1.0838, 2.745)
camera.reparentTo(render)
camera.setPosHpr(introPosHpr[self.sides[self.localAvId]][0], introPosHpr[self.sides[self.localAvId]][1])
base.camera.reparentTo(base.render)
base.camera.setPosHpr(introPosHpr[self.sides[self.localAvId]][0], introPosHpr[self.sides[self.localAvId]][1])
lerpDur = 8
self.introTrack = LerpPosHprInterval(camera, lerpDur, pos=gameCamPos, hpr=gameCamHpr, blendType='easeInOut', name=self.uniqueName('introLerpCameraPos'))
self.introTrack = LerpPosHprInterval(base.camera, lerpDur, pos=gameCamPos, hpr=gameCamHpr, blendType='easeInOut', name=self.uniqueName('introLerpCameraPos'))
self.introTrack.start()
base.camLens.setFov(60 + 2 * self.numPlayers)
base.camLens.setFar(450.0)
return
def sendGameType(self, index, suit):
if not self.hasLocalToon:
return
self.gameType = index
self.suitLevel = suit
if suit == 1:
@ -372,9 +384,11 @@ class DistributedTugOfWarGame(DistributedMinigame):
def setGameReady(self):
if not self.hasLocalToon:
return
self.notify.debug('setGameReady')
if DistributedMinigame.setGameReady(self):
return
self.initToons()
self.createSuits()
self.calculatePositions()
@ -389,7 +403,6 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.showTrack = None
self.setupTrack = None
self.__initGameVars()
return
def hideControls(self):
for x in range(len(self.arrows)):
@ -397,40 +410,39 @@ class DistributedTugOfWarGame(DistributedMinigame):
for rope in self.tugRopes:
if rope != None:
rope.reparentTo(hidden)
rope.reparentTo(base.hidden)
for tex in self.ropeTex:
if tex != None:
for texi in tex:
if texi:
texi.reparentTo(hidden)
texi.reparentTo(base.hidden)
if self.powerMeter != None:
self.powerMeter.unbind(DGG.B1PRESS)
self.powerMeter.unbind(DGG.B1RELEASE)
self.powerMeter.hide()
return
def setUpRopes(self, notTaut):
if self.numPlayers == 1:
suitRightHand = self.suit.getRightHand()
toonRightHand = self.rightHandDict[self.avIdList[0]]
if notTaut:
self.tugRopes[0].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0,
self.tugRopes[0].setup(3, ((toonRightHand, (0, 0, 0)), (base.render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0,
0,
0,
1,
1,
1])
else:
midPt = (suitRightHand.getPos() - toonRightHand.getPos()) / 2.0
self.tugRopes[0].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0,
0,
0,
1,
1,
1])
self.tugRopes[0].reparentTo(render)
self.tugRopes[0].reparentTo(base.render)
elif self.numPlayers == 2:
if self.gameType == TugOfWarGameGlobals.TOON_VS_COG:
self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0,
@ -442,25 +454,25 @@ class DistributedTugOfWarGame(DistributedMinigame):
suitRightHand = self.suit.getRightHand()
toonRightHand = self.rightHandDict[self.avIdList[1]]
if notTaut:
self.tugRopes[1].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0,
self.tugRopes[1].setup(3, ((toonRightHand, (0, 0, 0)), (base.render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0,
0,
0,
1,
1,
1])
else:
midPt = (suitRightHand.getPos() - toonRightHand.getPos()) / 2.0
self.tugRopes[1].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0,
0,
0,
1,
1,
1])
self.tugRopes[0].reparentTo(render)
self.tugRopes[1].reparentTo(render)
self.tugRopes[0].reparentTo(base.render)
self.tugRopes[1].reparentTo(base.render)
else:
if notTaut:
self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (render, (0, 18, -1)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0,
self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (base.render, (0, 18, -1)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0,
0,
0,
1,
@ -473,7 +485,8 @@ class DistributedTugOfWarGame(DistributedMinigame):
1,
1,
1])
self.tugRopes[0].reparentTo(render)
self.tugRopes[0].reparentTo(base.render)
elif self.numPlayers == 3:
if self.gameType == TugOfWarGameGlobals.TOON_VS_COG:
self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0,
@ -491,26 +504,26 @@ class DistributedTugOfWarGame(DistributedMinigame):
suitRightHand = self.suit.getRightHand()
toonRightHand = self.rightHandDict[self.avIdList[2]]
if notTaut:
self.tugRopes[2].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0,
self.tugRopes[2].setup(3, ((toonRightHand, (0, 0, 0)), (base.render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0,
0,
0,
1,
1,
1])
else:
midPt = (suitRightHand.getPos() - toonRightHand.getPos()) / 2.0
self.tugRopes[2].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0,
0,
0,
1,
1,
1])
self.tugRopes[0].reparentTo(render)
self.tugRopes[1].reparentTo(render)
self.tugRopes[2].reparentTo(render)
self.tugRopes[0].reparentTo(base.render)
self.tugRopes[1].reparentTo(base.render)
self.tugRopes[2].reparentTo(base.render)
else:
if notTaut:
self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (render, (0, 18, -1)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0,
self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (base.render, (0, 18, -1)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0,
0,
0,
1,
@ -523,14 +536,15 @@ class DistributedTugOfWarGame(DistributedMinigame):
1,
1,
1])
self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0,
0,
0,
1,
1,
1])
self.tugRopes[0].reparentTo(render)
self.tugRopes[1].reparentTo(render)
self.tugRopes[0].reparentTo(base.render)
self.tugRopes[1].reparentTo(base.render)
elif self.numPlayers == 4:
if self.gameType == TugOfWarGameGlobals.TOON_VS_COG:
self.tugRopes[2].setup(3, ((self.rightHandDict[self.avIdList[2]], (0, 0, 0)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0)), (self.rightHandDict[self.avIdList[3]], (0, 0, 0))), [0,
@ -554,24 +568,24 @@ class DistributedTugOfWarGame(DistributedMinigame):
suitRightHand = self.suit.getRightHand()
toonRightHand = self.rightHandDict[self.avIdList[3]]
if notTaut:
self.tugRopes[3].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0,
self.tugRopes[3].setup(3, ((toonRightHand, (0, 0, 0)), (base.render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0,
0,
0,
1,
1,
1])
else:
midPt = (suitRightHand.getPos() - toonRightHand.getPos()) / 2.0
self.tugRopes[3].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0,
0,
0,
1,
1,
1])
self.tugRopes[0].reparentTo(render)
self.tugRopes[1].reparentTo(render)
self.tugRopes[2].reparentTo(render)
self.tugRopes[3].reparentTo(render)
self.tugRopes[0].reparentTo(base.render)
self.tugRopes[1].reparentTo(base.render)
self.tugRopes[2].reparentTo(base.render)
self.tugRopes[3].reparentTo(base.render)
else:
self.tugRopes[2].setup(3, ((self.rightHandDict[self.avIdList[2]], (0, 0, 0)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0)), (self.rightHandDict[self.avIdList[3]], (0, 0, 0))), [0,
0,
@ -586,7 +600,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
1,
1])
if notTaut:
self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (render, (0, 18, -1)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0,
self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (base.render, (0, 18, -1)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0,
0,
0,
1,
@ -599,15 +613,16 @@ class DistributedTugOfWarGame(DistributedMinigame):
1,
1,
1])
self.tugRopes[0].reparentTo(render)
self.tugRopes[1].reparentTo(render)
self.tugRopes[2].reparentTo(render)
self.tugRopes[0].reparentTo(base.render)
self.tugRopes[1].reparentTo(base.render)
self.tugRopes[2].reparentTo(base.render)
def initToons(self):
for avId in self.avIdList:
toon = self.getAvatar(avId)
if toon:
toon.reparentTo(render)
toon.reparentTo(base.render)
toon.useLOD(1000)
toon.startBlink()
toon.startLookAround()
@ -618,7 +633,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.rightHandDict[avId] = toon.getRightHands()[0]
toon.loop('neutral')
toon.dropShadow.hide()
self.dropShadowDict[avId] = self.dropShadow.copyTo(hidden)
self.dropShadowDict[avId] = self.dropShadow.copyTo(base.hidden)
self.dropShadowDict[avId].reparentTo(toon)
self.dropShadowDict[avId].setScale(0.35)
@ -696,6 +711,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.hprDict[self.avIdList[1]] = hprPositions[0]
self.hprDict[self.avIdList[2]] = hprPositions[1]
self.hprDict[self.avIdList[3]] = hprPositions[1]
for x in self.avIdList:
self.offsetDict[x] = 0
if self.posDict[x][0] < 0:
@ -741,9 +757,11 @@ class DistributedTugOfWarGame(DistributedMinigame):
def setGameStart(self, timestamp):
if not self.hasLocalToon:
return
self.notify.debug('setGameStart')
if not self.__playing():
return
DistributedMinigame.setGameStart(self, timestamp)
self.gameFSM.request('waitForGoSignal')
@ -751,7 +769,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
pass
def makeToonLookatCamera(self, toon):
toon.headsUp(camera)
toon.headsUp(base.camera)
def setText(self, t, newtext):
t['text'] = newtext
@ -788,6 +806,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.notify.debug('exitTug')
if self.suit:
self.suit.loop('neutral')
self.timer.stop()
self.timer.hide()
taskMgr.remove(self.taskName('tug-timeout'))
@ -828,7 +847,8 @@ class DistributedTugOfWarGame(DistributedMinigame):
def __updateKeyPressRateTask(self, task):
if self.gameFSM.getCurrentState().getName() != 'tug':
return Task.done
return task.done
for i in range(len(self.keyTTL)):
self.keyTTL[i] -= 0.1
@ -844,18 +864,20 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.rateMatchAward += 0.3
else:
self.rateMatchAward = 0
self.__spawnUpdateKeyPressRateTask()
return Task.done
return task.done
def __updateTimerTask(self, task):
if self.gameFSM.getCurrentState().getName() != 'tug':
return Task.done
return task.done
self.currentForce = self.computeForce(self.keyRate)
self.sendUpdate('reportCurrentKeyRate', [self.keyRate, self.currentForce])
self.setSpeedGauge()
self.setAnimState(self.localAvId, self.keyRate)
self.__spawnUpdateTimerTask()
return Task.done
return task.done
def __spawnUpdateTimerTask(self):
taskMgr.remove(self.taskName(self.UPDATE_TIMER_TASK))
@ -881,10 +903,12 @@ class DistributedTugOfWarGame(DistributedMinigame):
if self.nextRateIndex < len(self.targetRateList):
if self.nextRateIndex == len(self.targetRateList) - 1:
self.allOutMode = 1
self.idealRate = self.targetRateList[self.nextRateIndex][1]
self.idealForce = self.advantage * (4 + 0.4 * self.idealRate)
taskMgr.doMethodLater(self.targetRateList[self.nextRateIndex][0], self.__updateIdealRateTask, self.taskName('targetRateTimer'))
return Task.done
return task.done
def __killUpdateIdealRateTask(self):
taskMgr.remove(self.taskName('targetRateTimer'))
@ -892,14 +916,14 @@ class DistributedTugOfWarGame(DistributedMinigame):
def sendGoSignal(self, index):
if not self.hasLocalToon:
return
self.notify.debug('sendGoSignal')
self.buttons = index
self.setupTrack = None
self.showTrack = None
def startTimer(self = self):
self.currentStartTime = int(globalClock.getFrameTime() * 1000)
time = 10
self.currentStartTime = int(base.clock.getFrameTime() * 1000)
self.timer.show()
self.timer.setTime(TugOfWarGameGlobals.GAME_DURATION)
self.timer.countdown(TugOfWarGameGlobals.GAME_DURATION, self.__gameTimerExpired)
@ -926,13 +950,14 @@ class DistributedTugOfWarGame(DistributedMinigame):
if self.introTrack != None:
self.introTrack.finish()
self.introTrack = None
self.setupTrack = Sequence(Func(self.setText, self.roundText, TTLocalizer.TugOfWarGameReady), Wait(1.5), Func(base.playSfx, self.whistleSound), Func(self.setText, self.roundText, TTLocalizer.TugOfWarGameGo), Func(self.roundText.setScale, 0.3), Wait(1.5), Func(startTimer), Func(enableKeys), Func(self.gameFSM.request, 'tug'), Func(self.setText, self.roundText, ' '), Func(self.roundText.setScale, 0.2))
self.setupTrack.start()
return
def sendStopSignal(self, winners, losers, tieers):
if not self.hasLocalToon:
return
self.notify.debug('sendStopSignal')
self.gameFSM.request('gameDone')
self.hideControls()
@ -941,6 +966,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
suitSlipTime = 0
if self.gameFSM.getCurrentState().getName() == 'cleanup' or not self.randomNumGen:
return
if self.suit:
if self.suitId in winners:
newPos = VBase3(2.65, 18, 0.1)
@ -959,6 +985,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
destHpr = startHpr + VBase3(0, 0, -30)
oopsTrack = Sequence(Parallel(Func(self.suit.play, 'flail', None, 26, 38), LerpHprInterval(self.suit, 0.5, destHpr, startHpr=startHpr)), Parallel(Func(self.suit.play, 'slip-forward'), LerpPosInterval(self.suit, duration=1, pos=waterPos), Sequence(Wait(0.55), Func(base.playSfx, self.sndHitWater), Func(self.suitSplash.play), Func(self.ripples.play))))
reactSeq.append(Sequence(Func(self.suit.loop, 'victory'), Wait(2.6), LerpPosInterval(self.suit, duration=2, pos=newPos), oopsTrack, Func(self.suit.loop, 'neutral')))
for avId in self.avIdList:
toon = self.getAvatar(avId)
toon.loop('neutral')
@ -978,6 +1005,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
else:
exitSeq.append(Func(self.setText, self.roundText, TTLocalizer.TugOfWarGameTie))
exitSeq.append(Wait(2.5))
exitSeq.append(Func(self.gameOver))
self.showTrack = Parallel(reactSeq, exitSeq)
for x in list(self.animTracks.values()):
@ -988,27 +1016,31 @@ class DistributedTugOfWarGame(DistributedMinigame):
if self.arrowKeys:
self.arrowKeys.setPressHandlers(self.arrowKeys.NULL_HANDLERS)
self.arrowKeys.setReleaseHandlers(self.arrowKeys.NULL_HANDLERS)
return
def remoteKeyRateUpdate(self, avId, keyRate):
if not self.hasLocalToon:
return
if avId != self.localAvId:
self.setAnimState(avId, keyRate)
def sendSuitPosition(self, suitOffset):
if not self.hasLocalToon:
return
if self.gameFSM.getCurrentState().getName() != 'tug':
return
self.suitOffset = suitOffset
self.moveSuits()
def sendCurrentPosition(self, avIdList, offsetList):
if not self.hasLocalToon:
return
if self.gameFSM.getCurrentState().getName() != 'tug':
return
for i in range(len(avIdList)):
self.offsetDict[avIdList[i]] = offsetList[i]
@ -1017,20 +1049,20 @@ class DistributedTugOfWarGame(DistributedMinigame):
def createSuits(self):
if self.gameType == TugOfWarGameGlobals.TOON_VS_COG:
self.suit = Suit.Suit()
self.suit = Suit()
self.origSuitPosHpr = [VBase3(6.0, 18, 0.1), VBase3(120, 0, 0)]
self.suitOffset = 0
d = SuitDNA.SuitDNA()
d = SuitDNA()
d.newSuit(self.suitType)
self.suit.setDNA(d)
self.suit.reparentTo(render)
self.suit.reparentTo(base.render)
self.suit.setPos(self.origSuitPosHpr[0])
self.suit.setHpr(self.origSuitPosHpr[1])
for anim in self.suitAnimNames:
self.suit.pose(anim, 0)
self.suit.pose('tug-o-war', 0)
self.dropShadowDict[self.suitId] = self.dropShadow.copyTo(hidden)
self.dropShadowDict[self.suitId] = self.dropShadow.copyTo(base.hidden)
self.dropShadowDict[self.suitId].reparentTo(self.suit)
self.dropShadowDict[self.suitId].setScale(0.45)
@ -1040,11 +1072,13 @@ class DistributedTugOfWarGame(DistributedMinigame):
toon = self.getAvatar(self.avList[0][0])
if self.avList[0][0] == self.localAvId:
self.advantage = 2.0
toon.applyCheesyEffect(ToontownGlobals.CEBigHead)
elif len(self.avList[1]) == 1:
toon = self.getAvatar(self.avList[1][0])
if self.avList[1][0] == self.localAvId:
self.advantage = 2.0
toon.applyCheesyEffect(ToontownGlobals.CEBigHead)
def setSpeedGauge(self):
@ -1052,12 +1086,14 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.powerMeter.setTarget(self.idealRate)
if not self.allOutMode:
self.powerMeter.updateTooSlowTooFast()
if not self.allOutMode:
index = float(self.currentForce) / self.idealForce
bonus = 0.0
if index > 1:
bonus = max(1, index - 1)
index = 1
color = (0,
0.75 * index + 0.25 * bonus,
0.75 * (1 - index),
@ -1069,10 +1105,12 @@ class DistributedTugOfWarGame(DistributedMinigame):
def setAnimState(self, avId, keyRate):
if self.gameFSM.getCurrentState().getName() != 'tug':
return
toon = self.getAvatar(avId)
if keyRate > 0 and self.pullingDict[avId] == 0:
toon.loop('tug-o-war')
self.pullingDict[avId] = 1
if keyRate <= 0 and self.pullingDict[avId] == 1:
toon.pose('tug-o-war', 3)
toon.startLookAround()
@ -1081,6 +1119,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
def moveSuits(self):
if self.gameType != TugOfWarGameGlobals.TOON_VS_COG:
return
origPos = self.origSuitPosHpr[0]
curPos = self.suit.getPos()
newPos = VBase3(origPos[0] + self.suitOffset, curPos[1], curPos[2])
@ -1088,10 +1127,10 @@ class DistributedTugOfWarGame(DistributedMinigame):
if self.animTracks[self.suitId].isPlaying():
self.animTracks[self.suitId].finish()
self.checkIfFallen()
if self.suitId not in self.fallenList:
self.animTracks[self.suitId] = Sequence(LerpPosInterval(self.suit, duration=TugOfWarGameGlobals.SEND_UPDATE, pos=newPos), Func(self.checkIfFallen))
self.animTracks[self.suitId].start()
return
def moveToons(self):
for avId in self.avIdList:
@ -1105,12 +1144,11 @@ class DistributedTugOfWarGame(DistributedMinigame):
if self.animTracks[avId].isPlaying():
self.animTracks[avId].finish()
self.checkIfFallen(avId)
if avId not in self.fallenList:
self.animTracks[avId] = Sequence(LerpPosInterval(toon, duration=TugOfWarGameGlobals.SEND_UPDATE, pos=newPos), Func(self.checkIfFallen, avId))
self.animTracks[avId].start()
return
def checkIfFallen(self, avId = None):
if avId == None:
if self.suitId not in self.fallenList:
@ -1132,7 +1170,6 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.throwInWater(avId)
self.sendUpdate('reportEndOfContest', [losingSide])
return
def throwInWater(self, avId = None):
if avId == None:
@ -1140,7 +1177,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
waterPos = self.drinkPositions.pop()
newPos = VBase3(waterPos[0], waterPos[1], waterPos[2] - self.suit.getHeight() / 1.5)
self.suit.loop('neutral')
self.dropShadowDict[self.suitId].reparentTo(hidden)
self.dropShadowDict[self.suitId].reparentTo(base.hidden)
loser = self.suit
animId = self.suitId
else:
@ -1149,19 +1186,20 @@ class DistributedTugOfWarGame(DistributedMinigame):
waterPos = self.drinkPositions.pop()
newPos = VBase3(waterPos[0], waterPos[1], waterPos[2] - toon.getHeight())
toon.loop('neutral')
self.dropShadowDict[avId].reparentTo(hidden)
self.dropShadowDict[avId].reparentTo(base.hidden)
loser = toon
animId = avId
if self.animTracks[animId] != None:
if self.animTracks[animId].isPlaying():
self.animTracks[animId].finish()
self.splash.setPos(newPos[0], newPos[1], -1.8)
self.splash.setScale(2.5, 2.5, 1)
self.ripples.setPos(newPos[0], newPos[1], -1.7)
self.ripples.setScale(1, 1, 1)
self.animTracks[animId] = Sequence(Parallel(ActorInterval(actor=loser, animName='slip-forward', duration=2.0), LerpPosInterval(loser, duration=2.0, pos=newPos), Sequence(Wait(1.0), Parallel(Func(base.playSfx, self.sndHitWater), Func(self.splash.play), Func(self.ripples.play)))), Func(loser.loop, 'neutral'))
self.animTracks[animId].start()
return
def computeForce(self, keyRate):
F = 0
@ -1170,6 +1208,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
else:
stdDev = 0.25 * self.idealRate
F = self.advantage * (self.rateMatchAward + 4 + 0.4 * self.idealRate) * math.pow(math.e, -math.pow(keyRate - self.idealRate, 2) / (2.0 * math.pow(stdDev, 2)))
return F
def initRopes(self):
@ -1177,8 +1216,9 @@ class DistributedTugOfWarGame(DistributedMinigame):
numRopes = self.numPlayers
else:
numRopes = self.numPlayers - 1
for x in range(0, numRopes):
rope = Rope.Rope(self.uniqueName('TugRope' + str(x)))
rope = Rope(self.uniqueName('TugRope' + str(x)))
if rope.showRope:
rope.ropeNode.setRenderMode(RopeNode.RMBillboard)
rope.ropeNode.setThickness(0.2)
@ -1187,6 +1227,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
rope.ropeNode.setUvDirection(1)
rope.setTransparency(1)
rope.setColor(0.89, 0.89, 0.6, 1)
self.tugRopes.append(rope)
self.setUpRopes(1)
@ -1203,18 +1244,18 @@ class DistributedTugOfWarGame(DistributedMinigame):
for j in range(len(self.ropePts[i])):
self.ropeTex[i][j].setPos(self.ropePts[i][j])
return Task.cont
return task.cont
def __killUpdateRopeTask(self):
taskMgr.remove(self.taskName(self.UPDATE_ROPE_TASK))
def tugTimeoutTask(self, task):
self.gameOver()
return Task.done
return task.done
def waitForGoTimeoutTask(self, task):
self.gameOver()
return Task.done
return task.done
def __spawnMouseSpeedTask(self):
taskMgr.remove(self.taskName('mouseSpeed'))
@ -1227,7 +1268,6 @@ class DistributedTugOfWarGame(DistributedMinigame):
dx = 0.1
if self.mouseMode:
mx = base.mouseWatcherNode.getMouseX()
my = base.mouseWatcherNode.getMouseY()
if self.mouseSide == 0:
if mx > dx:
self.mouseSide = 1
@ -1242,4 +1282,5 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.__pressHandler(1)
elif mx < dx:
self.__releaseHandler(0)
return Task.cont
return task.cont

View File

@ -1,11 +1,18 @@
from direct.interval.IntervalGlobal import *
from direct.task.Task import Task
from panda3d.core import Point3, Vec3
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.interval.IntervalGlobal import LerpHprInterval
from direct.showbase.PythonUtil import fitSrcAngle2Dest
from direct.task.TaskManagerGlobal import taskMgr
from otp.otpbase import OTPGlobals
from toontown.toonbase.ToonBaseGlobal import *
from . import ArrowKeys
from toontown.minigame.ArrowKeys import ArrowKeys
from toontown.toonbase.ToonBaseGlobal import base
class OrthoDrive:
notify = DirectNotifyGlobal.directNotify.newCategory('OrthoDrive')
notify = directNotify.newCategory('OrthoDrive')
TASK_NAME = 'OrthoDriveTask'
SET_ATREST_HEADING_TASK = 'setAtRestHeadingTask'
@ -17,7 +24,7 @@ class OrthoDrive:
self.priority = priority
self.setHeading = setHeading
self.upHeading = upHeading
self.arrowKeys = ArrowKeys.ArrowKeys()
self.arrowKeys = ArrowKeys()
self.lt = base.localAvatar
self.instantTurn = instantTurn
@ -31,18 +38,17 @@ class OrthoDrive:
self.__placeToonHOG(self.lt.getPos())
taskMgr.add(self.__update, OrthoDrive.TASK_NAME, priority=self.priority)
self.lastAction = None
return
def __placeToonHOG(self, pos, h = None):
if h == None:
h = self.lt.getH()
self.lt.setPos(pos)
self.lt.setH(h)
self.lastPos = pos
self.atRestHeading = h
self.lastXVel = 0
self.lastYVel = 0
return
def stop(self):
self.notify.debug('stop')
@ -52,7 +58,9 @@ class OrthoDrive:
if hasattr(self, 'turnLocalToonIval'):
if self.turnLocalToonIval.isPlaying():
self.turnLocalToonIval.pause()
del self.turnLocalToonIval
base.localAvatar.setSpeed(0, 0)
def __update(self, task):
@ -61,12 +69,16 @@ class OrthoDrive:
yVel = 0
if self.arrowKeys.upPressed():
yVel += 1
if self.arrowKeys.downPressed():
yVel -= 1
if self.arrowKeys.leftPressed():
xVel -= 1
if self.arrowKeys.rightPressed():
xVel += 1
vel.setX(xVel)
vel.setY(yVel)
vel.normalize()
@ -82,10 +94,12 @@ class OrthoDrive:
self.lt.runSound()
else:
self.lt.stopSound()
if self.setHeading:
self.__handleHeading(xVel, yVel)
toonPos = self.lt.getPos()
dt = globalClock.getDt()
dt = base.clock.getDt()
posOffset = vel * dt
posOffset += toonPos - self.lastPos
toonPos = self.lastPos
@ -94,13 +108,15 @@ class OrthoDrive:
if posOffsetLen > self.maxFrameMove:
posOffset *= self.maxFrameMove
posOffset /= posOffsetLen
if self.customCollisionCallback:
toonPos = self.customCollisionCallback(toonPos, toonPos + posOffset)
else:
toonPos = toonPos + posOffset
self.lt.setPos(toonPos)
self.lastPos = toonPos
return Task.cont
return task.cont
def __handleHeading(self, xVel, yVel):
def getHeading(xVel, yVel):
@ -126,11 +142,13 @@ class OrthoDrive:
if ((self.lastXVel and self.lastYVel) and not (xVel and yVel)):
def setAtRestHeading(task, self = self, angle = curHeading):
self.atRestHeading = angle
return Task.done
return task.done
taskMgr.doMethodLater(0.05, setAtRestHeading, OrthoDrive.SET_ATREST_HEADING_TASK)
else:
self.atRestHeading = curHeading
orientToon(curHeading)
self.lastXVel = xVel
self.lastYVel = yVel

View File

@ -51,15 +51,15 @@ class Purchase(PurchaseBase):
self.bg = loader.loadModel('phase_%s/models/modules/toon_interior' % interiorPhase)
self.bg.setPos(0.0, 5.0, -1.0)
self.wt = self.bg.find('**/random_tc1_TI_wallpaper')
wallTex = loader.loadTexture('phase_%s/maps/wall_paper_a5.jpg' % interiorPhase)
wallTex = loader.loadTexture('phase_%s/maps/wall_paper_a5.png' % interiorPhase)
self.wt.setTexture(wallTex, 100)
self.wt.setColorScale(0.8, 0.67, 0.549, 1.0)
self.bt = self.bg.find('**/random_tc1_TI_wallpaper_border')
wallTex = loader.loadTexture('phase_%s/maps/wall_paper_a5.jpg' % interiorPhase)
wallTex = loader.loadTexture('phase_%s/maps/wall_paper_a5.png' % interiorPhase)
self.bt.setTexture(wallTex, 100)
self.bt.setColorScale(0.8, 0.67, 0.549, 1.0)
self.wb = self.bg.find('**/random_tc1_TI_wainscotting')
wainTex = loader.loadTexture('phase_%s/maps/wall_paper_b4.jpg' % interiorPhase)
wainTex = loader.loadTexture('phase_%s/maps/wall_paper_b4.png' % interiorPhase)
self.wb.setTexture(wainTex, 100)
self.wb.setColorScale(0.473, 0.675, 0.488, 1.0)
self.playAgain = DirectButton(parent=self.frame, relief=None, scale=1.04, pos=(0.72, 0, -0.24), image=(purchaseModels.find('**/PurchScrn_BTN_UP'),

View File

@ -112,7 +112,7 @@ class SwingVine(NodePath):
self.link1 = self.links[-2][0]
self.rope = self.makeSpline()
self.rope.reparentTo(self.root)
myTexture = loader.loadTexture('phase_4/maps/swinging_vine.jpg')
myTexture = loader.loadTexture('phase_4/maps/swinging_vine.png')
gameAssets = loader.loadModel('phase_4/models/minigames/vine_game')
vine = gameAssets.find('**/vine1')
self.cableTex = vine.findTexture('*')

View File

@ -1,12 +1,15 @@
from panda3d.core import *
from panda3d.core import CardMaker, CollisionNode, CollisionPlane, NodePath, Plane, Point3, Vec3
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.showbase.DirectObject import DirectObject
from toontown.toonbase.ToonBaseGlobal import *
from direct.directnotify import DirectNotifyGlobal
from toontown.minigame import ToonBlitzGlobals, TwoDBlock
from panda3d.core import CardMaker
from toontown.minigame import ToonBlitzGlobals
from toontown.toonbase import ToontownGlobals
from toontown.toonbase.ToonBaseGlobal import base
class ToonBlitzAssetMgr(DirectObject):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedToonBlitzAssets')
notify = directNotify.newCategory('DistributedToonBlitzAssets')
def __init__(self, game):
self.__defineConstants()
@ -18,47 +21,47 @@ class ToonBlitzAssetMgr(DirectObject):
def load(self):
self.world = NodePath('ToonBlitzWorld')
self.background = loader.loadModel('phase_4/models/minigames/toonblitz_game')
self.background = base.loader.loadModel('phase_4/models/minigames/toonblitz_game')
self.background.reparentTo(self.world)
self.startingWall = loader.loadModel('phase_4/models/minigames/toonblitz_game_wall')
self.startingPipe = loader.loadModel('phase_4/models/minigames/toonblitz_game_start')
self.exitElevator = loader.loadModel('phase_4/models/minigames/toonblitz_game_elevator')
self.arrow = loader.loadModel('phase_4/models/minigames/toonblitz_game_arrow')
self.sprayProp = loader.loadModel('phase_4/models/minigames/prop_waterspray')
self.startingWall = base.loader.loadModel('phase_4/models/minigames/toonblitz_game_wall')
self.startingPipe = base.loader.loadModel('phase_4/models/minigames/toonblitz_game_start')
self.exitElevator = base.loader.loadModel('phase_4/models/minigames/toonblitz_game_elevator')
self.arrow = base.loader.loadModel('phase_4/models/minigames/toonblitz_game_arrow')
self.sprayProp = base.loader.loadModel('phase_4/models/minigames/prop_waterspray')
self.treasureModelList = []
salesIcon = loader.loadModel('phase_4/models/minigames/salesIcon')
salesIcon = base.loader.loadModel('phase_4/models/minigames/salesIcon')
self.treasureModelList.append(salesIcon)
moneyIcon = loader.loadModel('phase_4/models/minigames/moneyIcon')
moneyIcon = base.loader.loadModel('phase_4/models/minigames/moneyIcon')
self.treasureModelList.append(moneyIcon)
legalIcon = loader.loadModel('phase_4/models/minigames/legalIcon')
legalIcon = base.loader.loadModel('phase_4/models/minigames/legalIcon')
self.treasureModelList.append(legalIcon)
corpIcon = loader.loadModel('phase_4/models/minigames/corpIcon')
corpIcon = base.loader.loadModel('phase_4/models/minigames/corpIcon')
self.treasureModelList.append(corpIcon)
self.particleGlow = loader.loadModel('phase_4/models/minigames/particleGlow')
self.particleGlow = base.loader.loadModel('phase_4/models/minigames/particleGlow')
self.blockTypes = []
for i in range(4):
blockType = loader.loadModel('phase_4/models/minigames/toonblitz_game_block0' + str(i))
blockType = base.loader.loadModel('phase_4/models/minigames/toonblitz_game_block0' + str(i))
self.blockTypes.append(blockType)
self.stomper = loader.loadModel('phase_4/models/minigames/toonblitz_game_stomper')
self.stomper = base.loader.loadModel('phase_4/models/minigames/toonblitz_game_stomper')
plane = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, -50)))
dropPlane = CollisionNode('dropPlane')
dropPlane.addSolid(plane)
dropPlane.setCollideMask(ToontownGlobals.FloorBitmask)
self.world.attachNewNode(dropPlane)
self.gameMusic = base.loader.loadMusic('phase_4/audio/bgm/MG_TwoDGame.ogg')
self.treasureGrabSound = loader.loadSfx('phase_4/audio/sfx/SZ_DD_treasure.ogg')
self.treasureGrabSound = base.loader.loadSfx('phase_4/audio/sfx/SZ_DD_treasure.ogg')
self.sndOof = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_hit_dirt.ogg')
self.soundJump = base.loader.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_jump.ogg')
self.fallSound = base.loader.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_fall.ogg')
self.watergunSound = base.loader.loadSfx('phase_4/audio/sfx/AA_squirt_seltzer_miss.ogg')
self.splashSound = base.loader.loadSfx('phase_4/audio/sfx/Seltzer_squirt_2dgame_hit.ogg')
self.threeSparkles = loader.loadSfx('phase_4/audio/sfx/threeSparkles.ogg')
self.sparkleSound = loader.loadSfx('phase_4/audio/sfx/sparkly.ogg')
self.headCollideSound = loader.loadSfx('phase_3.5/audio/sfx/AV_collision.ogg')
self.threeSparkles = base.loader.loadSfx('phase_4/audio/sfx/threeSparkles.ogg')
self.sparkleSound = base.loader.loadSfx('phase_4/audio/sfx/sparkly.ogg')
self.headCollideSound = base.loader.loadSfx('phase_3.5/audio/sfx/AV_collision.ogg')
self.faceStartPos = Vec3(-0.8, 0, -0.87)
self.faceEndPos = Vec3(0.8, 0, -0.87)
self.aspect2dRoot = aspect2d.attachNewNode('TwoDGuiAspect2dRoot')
self.aspect2dRoot = base.aspect2d.attachNewNode('TwoDGuiAspect2dRoot')
self.aspect2dRoot.setDepthWrite(1)
self.cardMaker = CardMaker('card')
self.cardMaker.reset()
@ -114,10 +117,9 @@ class ToonBlitzAssetMgr(DirectObject):
del self.sparkleSound
del self.headCollideSound
self.game = None
return
def onstage(self):
self.world.reparentTo(render)
self.world.reparentTo(base.render)
base.playMusic(self.gameMusic, looping=1, volume=0.9)
def offstage(self):

View File

@ -1,14 +1,29 @@
from panda3d.core import *
from panda3d.core import CollisionHandlerEvent, CollisionNode, CollisionSphere, Point3, Point4, VBase3, Vec3
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.interval.IntervalGlobal import (
ActorInterval,
Func,
LerpPosInterval,
LerpScaleInterval,
Parallel,
Sequence,
Wait
)
from direct.showbase.DirectObject import DirectObject
from toontown.toonbase.ToonBaseGlobal import *
from direct.directnotify import DirectNotifyGlobal
from direct.interval.IntervalGlobal import *
from toontown.battle.BattleProps import *
from direct.showbase.MessengerGlobal import messenger
from toontown.battle import MovieUtil
import math
from toontown.battle.BattleProps import globalPropPool
from toontown.toonbase import ToontownGlobals
from toontown.toonbase.ToonBaseGlobal import base
from math import sin
class TwoDBattleMgr(DirectObject):
notify = DirectNotifyGlobal.directNotify.newCategory('TwoDBattleMgr')
notify = directNotify.newCategory('TwoDBattleMgr')
def __init__(self, game, toon):
self.game = game
@ -26,7 +41,6 @@ class TwoDBattleMgr(DirectObject):
self.setupPistol()
if self.toon == base.localAvatar:
self.createShootCollision()
return
def destroy(self):
if self.toon == base.localAvatar:
@ -34,18 +48,20 @@ class TwoDBattleMgr(DirectObject):
self.waterBulletIval.finish()
del self.waterBulletIval
self.waterBulletIval = None
self.ignore('enter' + self.collSphereName)
base.localAvatar.controlManager.currentControls.cTrav.removeCollider(self.waterBullet)
self.waterBullet.removeNode()
del self.waterBullet
self.hand_jointpath0.removeNode()
MovieUtil.removeProp(self.pistol)
if self.shootTrack != None:
self.shootTrack.finish()
self.shootTrack = None
self.game = None
self.toon = None
return
def start(self):
pass
@ -67,6 +83,7 @@ class TwoDBattleMgr(DirectObject):
if self.toon == base.localAvatar:
self.shootTrack.append(Func(self.game.assetMgr.playWatergunSound))
self.shootTrack.append(self.getWaterBulletIval())
self.shootTrack.start()
return
elif self.shootTrack.isStopped():
@ -74,6 +91,7 @@ class TwoDBattleMgr(DirectObject):
if self.toon == base.localAvatar:
self.shootTrack.append(Func(self.game.assetMgr.playWatergunSound))
self.shootTrack.append(self.getWaterBulletIval())
self.shootTrack.start()
def createShootCollision(self):
@ -90,6 +108,7 @@ class TwoDBattleMgr(DirectObject):
self.waterBullet.hide()
if self.showCollSpheres:
self.waterBullet.show()
bulletEvent = CollisionHandlerEvent()
bulletEvent.addInPattern('enter%fn')
bulletEvent.addOutPattern('exit%fn')
@ -108,22 +127,23 @@ class TwoDBattleMgr(DirectObject):
else:
toon.loop('neutral')
torso = self.toon.getPart('torso', '1000')
toonTrack = Sequence(ActorInterval(self.toon, 'water-gun', startFrame=48, endFrame=58, partName='torso'), ActorInterval(self.toon, 'water-gun', startFrame=107, endFrame=126, playRate=2, partName='torso'), Func(returnToLastAnim, self.toon))
return toonTrack
def calcSprayStartPos(self):
if self.toon:
self.toon.update(0)
joint = self.pistol.find('**/joint_nozzle')
p = joint.getPos(render)
p = joint.getPos(base.render)
self.origin = p
def calcSprayEndPos(self):
if self.toon:
xDirection = -math.sin(self.toon.getH())
xDirection = -sin(self.toon.getH())
else:
xDirection = -math.sin(-90)
xDirection = -sin(-90)
endPos = Point3(self.origin.getX() + self.SHOOT_DISTANCE * xDirection, self.origin.getY(), self.origin.getZ())
self.target = endPos
@ -131,7 +151,7 @@ class TwoDBattleMgr(DirectObject):
dSprayScale = 0.15
dSprayHold = 0.035
color = self.WATER_SPRAY_COLOR
parent = render
parent = base.render
horizScale = 1.0
vertScale = 1.0
@ -161,12 +181,13 @@ class TwoDBattleMgr(DirectObject):
sprayScale.removeNode()
sprayProp = self.sprayProp
sprayScale = hidden.attachNewNode('spray-parent')
sprayRot = hidden.attachNewNode('spray-rotate')
sprayScale = base.hidden.attachNewNode('spray-parent')
sprayRot = base.hidden.attachNewNode('spray-rotate')
spray = sprayRot
spray.setColor(color)
if color[3] < 1.0:
spray.setTransparency(1)
track = Sequence(Wait(0.1), Func(self.calcSprayStartPos), Func(self.calcSprayEndPos), Func(showSpray, sprayScale, sprayRot, sprayProp, parent), LerpScaleInterval(sprayScale, dSprayScale, calcTargetScale, startScale=MovieUtil.PNT3_NEARZERO), Wait(dSprayHold), Func(prepareToShrinkSpray, spray, sprayProp), LerpScaleInterval(sprayScale, dSprayScale, MovieUtil.PNT3_NEARZERO), Func(hideSpray, spray, sprayScale, sprayRot, sprayProp, globalPropPool))
return track
@ -180,8 +201,8 @@ class TwoDBattleMgr(DirectObject):
if self.waterBulletIval:
self.waterBulletIval.finish()
del self.waterBulletIval
self.waterBulletIval = None
return
def getWaterBulletIval(self):
if not self.waterBulletIval.isPlaying():

View File

@ -1,11 +1,19 @@
from toontown.toonbase.ToonBaseGlobal import *
from panda3d.core import Point3, Vec3
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.interval.IntervalGlobal import LerpHprInterval
from direct.showbase.MessengerGlobal import messenger
from direct.showbase.PythonUtil import fitSrcAngle2Dest
from direct.task.TaskManagerGlobal import taskMgr
from otp.otpbase import OTPGlobals
from direct.interval.IntervalGlobal import *
from . import ArrowKeys
from direct.task.Task import Task
from toontown.minigame.ArrowKeys import ArrowKeys
from toontown.toonbase.ToonBaseGlobal import base
class TwoDDrive:
notify = DirectNotifyGlobal.directNotify.newCategory('TwoDDrive')
notify = directNotify.newCategory('TwoDDrive')
TASK_NAME = 'TwoDDriveTask'
SET_ATREST_HEADING_TASK = 'setAtRestHeadingTask'
@ -17,7 +25,7 @@ class TwoDDrive:
self.priority = priority
self.setHeading = setHeading
self.upHeading = upHeading
self.arrowKeys = ArrowKeys.ArrowKeys()
self.arrowKeys = ArrowKeys()
self.wasUpReleased = True
self.lt = base.localAvatar
base.localAvatar.useTwoDControls()
@ -25,7 +33,6 @@ class TwoDDrive:
self.ONE_JUMP_PER_UP_PRESSED = True
self.lastAction = None
self.isMovingX = False
return
def destroy(self):
self.game = None
@ -35,7 +42,6 @@ class TwoDDrive:
del self.arrowKeys
del self.customCollisionCallback
self.lastAction = None
return
def start(self):
self.notify.debug('start')
@ -47,6 +53,7 @@ class TwoDDrive:
def __placeToonHOG(self, pos, h = None):
if h == None:
h = self.lt.getH()
self.lt.setPos(pos)
self.lt.setH(h)
self.lastPos = pos
@ -54,7 +61,6 @@ class TwoDDrive:
self.oldAtRestHeading = h
self.lastXVel = 0
self.lastYVel = 0
return
def stop(self):
self.notify.debug('stop')
@ -64,7 +70,9 @@ class TwoDDrive:
if hasattr(self, 'turnLocalToonIval'):
if self.turnLocalToonIval.isPlaying():
self.turnLocalToonIval.pause()
del self.turnLocalToonIval
base.localAvatar.setSpeed(0, 0)
base.localAvatar.stopSound()
@ -78,16 +86,19 @@ class TwoDDrive:
elif self.arrowKeys.upPressed() and self.wasUpReleased:
self.wasUpReleased = False
if not self.game.isHeadInFloor:
if localAvatar.controlManager.currentControls == localAvatar.controlManager.get('twoD'):
if base.localAvatar.controlManager.currentControls == base.localAvatar.controlManager.get('twoD'):
base.localAvatar.controlManager.currentControls.jumpPressed()
elif self.arrowKeys.upPressed():
if not self.game.isHeadInFloor:
if localAvatar.controlManager.currentControls == localAvatar.controlManager.get('twoD'):
if base.localAvatar.controlManager.currentControls == base.localAvatar.controlManager.get('twoD'):
base.localAvatar.controlManager.currentControls.jumpPressed()
if self.arrowKeys.leftPressed():
xVel -= 1
if self.arrowKeys.rightPressed():
xVel += 1
vel.setX(xVel)
vel.setY(yVel)
vel.normalize()
@ -99,6 +110,7 @@ class TwoDDrive:
elif self.isMovingX:
self.isMovingX = False
messenger.send('avatarStoppedX')
speed = vel.length()
action = self.lt.setSpeed(speed, 0)
if action != self.lastAction:
@ -107,18 +119,21 @@ class TwoDDrive:
base.localAvatar.runSound()
else:
base.localAvatar.stopSound()
if self.setHeading:
self.__handleHeading(xVel, yVel)
toonPos = self.lt.getPos()
dt = globalClock.getDt()
dt = base.clock.getDt()
posOffset = vel * dt
if self.customCollisionCallback:
toonPos = self.customCollisionCallback(toonPos, toonPos + posOffset)
else:
toonPos += posOffset
self.lt.setPos(toonPos)
self.lastPos = toonPos
return Task.cont
return task.cont
def __handleHeading(self, xVel, yVel):
def getHeading(xVel, yVel):
@ -144,11 +159,13 @@ class TwoDDrive:
if ((self.lastXVel and self.lastYVel) and not (xVel and yVel)):
def setAtRestHeading(task, self = self, angle = curHeading):
self.atRestHeading = angle
return Task.done
return task.done
taskMgr.doMethodLater(0.05, setAtRestHeading, TwoDDrive.SET_ATREST_HEADING_TASK)
else:
self.atRestHeading = curHeading
orientToon(curHeading)
self.lastXVel = xVel
self.lastYVel = yVel

View File

@ -9,7 +9,7 @@ class DistributedPartyJukebox40Activity(DistributedPartyJukeboxActivityBase):
def load(self):
DistributedPartyJukeboxActivityBase.load(self)
newTexture = loader.loadTexture('phase_13/maps/tt_t_ara_pty_jukeboxBlue.jpg', 'phase_13/maps/tt_t_ara_pty_jukeboxBlue_a.rgb')
newTexture = loader.loadTexture('phase_13/maps/tt_t_ara_pty_jukeboxBlue.png')
case = self.jukebox.find('**/jukeboxGlass')
if not case.isEmpty():
case.setTexture(newTexture, 1)

View File

@ -9,7 +9,7 @@ class DistributedPartyValentineJukebox40Activity(DistributedPartyJukeboxActivity
def load(self):
DistributedPartyJukeboxActivityBase.load(self)
newTexture = loader.loadTexture('phase_13/maps/tt_t_ara_pty_jukeboxValentineB.jpg', 'phase_13/maps/tt_t_ara_pty_jukeboxValentineB_a.rgb')
newTexture = loader.loadTexture('phase_13/maps/tt_t_ara_pty_jukeboxValentineB.png')
case = self.jukebox.find('**/jukeboxGlass')
if not case.isEmpty():
case.setTexture(newTexture, 1)

View File

@ -9,7 +9,7 @@ class DistributedPartyValentineJukeboxActivity(DistributedPartyJukeboxActivityBa
def load(self):
DistributedPartyJukeboxActivityBase.load(self)
newTexture = loader.loadTexture('phase_13/maps/tt_t_ara_pty_jukeboxValentineA.jpg', 'phase_13/maps/tt_t_ara_pty_jukeboxValentineA_a.rgb')
newTexture = loader.loadTexture('phase_13/maps/tt_t_ara_pty_jukeboxValentineA.png')
case = self.jukebox.find('**/jukeboxGlass')
if not case.isEmpty():
case.setTexture(newTexture, 1)

View File

@ -3,4 +3,4 @@ from toontown.parties.DistributedPartyTrampolineActivity import DistributedParty
class DistributedPartyValentineTrampolineActivity(DistributedPartyTrampolineActivity):
def __init__(self, cr, doJellyBeans = True, doTricks = False, texture = None):
DistributedPartyTrampolineActivity.__init__(self, cr, doJellyBeans, doTricks, 'phase_13/maps/tt_t_ara_pty_trampolineValentine.jpg')
DistributedPartyTrampolineActivity.__init__(self, cr, doJellyBeans, doTricks, 'phase_13/maps/tt_t_ara_pty_trampolineValentine.png')

View File

@ -3,4 +3,4 @@ from toontown.parties.DistributedPartyTrampolineActivity import DistributedParty
class DistributedPartyVictoryTrampolineActivity(DistributedPartyTrampolineActivity):
def __init__(self, cr, doJellyBeans = True, doTricks = False, texture = None):
DistributedPartyTrampolineActivity.__init__(self, cr, doJellyBeans, doTricks, 'phase_13/maps/tt_t_ara_pty_trampolineVictory.jpg')
DistributedPartyTrampolineActivity.__init__(self, cr, doJellyBeans, doTricks, 'phase_13/maps/tt_t_ara_pty_trampolineVictory.png')

View File

@ -3,4 +3,4 @@ from toontown.parties.DistributedPartyTrampolineActivity import DistributedParty
class DistributedPartyWinterTrampolineActivity(DistributedPartyTrampolineActivity):
def __init__(self, cr, doJellyBeans = True, doTricks = False, texture = None):
DistributedPartyTrampolineActivity.__init__(self, cr, doJellyBeans, doTricks, 'phase_13/maps/tt_t_ara_pty_trampolineWinter.jpg')
DistributedPartyTrampolineActivity.__init__(self, cr, doJellyBeans, doTricks, 'phase_13/maps/tt_t_ara_pty_trampolineWinter.png')

View File

@ -97,8 +97,7 @@ class PartyCogActivity(DirectObject):
signLocator = self.arena.find('**/eventSign_locator')
self.activity.sign.setPos(signLocator.getPos(self.root))
if self.texture:
textureAlpha = self.texture[:-4] + '_a.rgb'
reskinTexture = loader.loadTexture(self.texture, textureAlpha)
reskinTexture = loader.loadTexture(self.texture)
self.arena.find('**/center_grp').setTexture(reskinTexture, 100)
self.arena.find('**/leftSide_grp').setTexture(reskinTexture, 100)
self.arena.find('**/rightSide_grp').setTexture(reskinTexture, 100)

View File

@ -247,11 +247,11 @@ class Pet(Avatar.Avatar):
self.rightHighlight.hide()
self.leftHighlight.hide()
if self.style[8]:
self.eyesOpenTexture = loader.loadTexture('phase_4/maps/BeanEyeBoys2.jpg', 'phase_4/maps/BeanEyeBoys2_a.rgb')
self.eyesClosedTexture = loader.loadTexture('phase_4/maps/BeanEyeBoysBlink.jpg', 'phase_4/maps/BeanEyeBoysBlink_a.rgb')
self.eyesOpenTexture = loader.loadTexture('phase_4/maps/BeanEyeBoys2.png')
self.eyesClosedTexture = loader.loadTexture('phase_4/maps/BeanEyeBoysBlink.png')
else:
self.eyesOpenTexture = loader.loadTexture('phase_4/maps/BeanEyeGirlsNew.jpg', 'phase_4/maps/BeanEyeGirlsNew_a.rgb')
self.eyesClosedTexture = loader.loadTexture('phase_4/maps/BeanEyeGirlsBlinkNew.jpg', 'phase_4/maps/BeanEyeGirlsBlinkNew_a.rgb')
self.eyesOpenTexture = loader.loadTexture('phase_4/maps/BeanEyeGirlsNew.png')
self.eyesClosedTexture = loader.loadTexture('phase_4/maps/BeanEyeGirlsBlinkNew.png')
self.eyesOpenTexture.setMinfilter(Texture.FTLinear)
self.eyesOpenTexture.setMagfilter(Texture.FTLinear)
self.eyesClosedTexture.setMinfilter(Texture.FTLinear)

View File

@ -21,13 +21,13 @@ EarParts = ['horns',
EarTextures = {'horns': None,
'antennae': None,
'dogEars': None,
'catEars': 'phase_4/maps/BeanCatEar6.jpg',
'rabbitEars': 'phase_4/maps/BeanBunnyEar6.jpg'}
'catEars': 'phase_4/maps/BeanCatEar6.png',
'rabbitEars': 'phase_4/maps/BeanBunnyEar6.png'}
ExoticEarTextures = {'horns': None,
'antennae': None,
'dogEars': None,
'catEars': 'phase_4/maps/BeanCatEar3Yellow.jpg',
'rabbitEars': 'phase_4/maps/BeanBunnyEar6.jpg'}
'catEars': 'phase_4/maps/BeanCatEar3Yellow.png',
'rabbitEars': 'phase_4/maps/BeanBunnyEar6.png'}
NoseParts = ['clownNose',
'dogNose',
'ovalNose',
@ -36,12 +36,12 @@ TailParts = ['catTail',
'longTail',
'birdTail',
'bunnyTail']
TailTextures = {'catTail': 'phase_4/maps/beanCatTail6.jpg',
'longTail': 'phase_4/maps/BeanLongTail6.jpg',
TailTextures = {'catTail': 'phase_4/maps/beanCatTail6.png',
'longTail': 'phase_4/maps/BeanLongTail6.png',
'birdTail': None,
'bunnyTail': None}
GiraffeTail = 'phase_4/maps/BeanLongTailGiraffe.jpg'
LeopardTail = 'phase_4/maps/BeanLongTailLepord.jpg'
GiraffeTail = 'phase_4/maps/BeanLongTailGiraffe.png'
LeopardTail = 'phase_4/maps/BeanLongTailLepord.png'
GenericBodies = ['dots',
'threeStripe',
'tigerStripe',
@ -85,17 +85,17 @@ PetRarities = {'body': {ToontownGlobals.ToontownCentral: {'threeStripe': 50,
'turtle': 25,
'giraffe': 20,
'leopard': 10}}}
BodyTextures = {'dots': 'phase_4/maps/BeanbodyDots6.jpg',
'threeStripe': 'phase_4/maps/Beanbody3stripes6.jpg',
'tigerStripe': 'phase_4/maps/BeanbodyZebraStripes6.jpg',
'turtle': 'phase_4/maps/BeanbodyTurtle.jpg',
'giraffe': 'phase_4/maps/BeanbodyGiraffe1.jpg',
'leopard': 'phase_4/maps/BeanbodyLepord2.jpg',
'tummy': 'phase_4/maps/BeanbodyTummy6.jpg'}
FeetTextures = {'normal': 'phase_4/maps/BeanFoot6.jpg',
'turtle': 'phase_4/maps/BeanFootTurttle.jpg',
'giraffe': 'phase_4/maps/BeanFootYellow3.jpg',
'leopard': 'phase_4/maps/BeanFootYellow3.jpg'}
BodyTextures = {'dots': 'phase_4/maps/BeanbodyDots6.png',
'threeStripe': 'phase_4/maps/Beanbody3stripes6.png',
'tigerStripe': 'phase_4/maps/BeanbodyZebraStripes6.png',
'turtle': 'phase_4/maps/BeanbodyTurtle.png',
'giraffe': 'phase_4/maps/BeanbodyGiraffe1.png',
'leopard': 'phase_4/maps/BeanbodyLepord2.png',
'tummy': 'phase_4/maps/BeanbodyTummy6.png'}
FeetTextures = {'normal': 'phase_4/maps/BeanFoot6.png',
'turtle': 'phase_4/maps/BeanFootTurttle.png',
'giraffe': 'phase_4/maps/BeanFootYellow3.png',
'leopard': 'phase_4/maps/BeanFootYellow3.png'}
AllPetColors = (VBase4(1.0, 1.0, 1.0, 1.0),
VBase4(0.96875, 0.691406, 0.699219, 1.0),
VBase4(0.933594, 0.265625, 0.28125, 1.0),

View File

@ -1,39 +1,39 @@
from direct.distributed import DistributedObject
from direct.directnotify import DirectNotifyGlobal
from otp.otpbase import OTPTimer
from panda3d.core import NodePath, TextNode
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.distributed.DistributedObject import DistributedObject
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import TTLocalizer
from toontown.racing import KartShopGlobals
from toontown.toonbase.ToonBaseGlobal import *
from panda3d.core import *
from toontown.toonbase.ToontownGlobals import *
import random
from toontown.toonbase.ToonBaseGlobal import base
import pickle
class DistributedLeaderBoard(DistributedObject.DistributedObject):
notify = DirectNotifyGlobal.directNotify.newCategory('DisributedLeaderBoard')
class DistributedLeaderBoard(DistributedObject):
notify = directNotify.newCategory('DisributedLeaderBoard')
def __init__(self, cr):
self.notify.debug('__init__: initialization of local leaderboard')
DistributedObject.DistributedObject.__init__(self, cr)
DistributedObject.__init__(self, cr)
self.corner = 0
self.length = 0
self.width = 0
self.updateCount = 0
self.board = None
self.surface = None
return
def generateInit(self):
DistributedObject.DistributedObject.generateInit(self)
DistributedObject.generateInit(self)
self.board = NodePath(self.uniqueName('LeaderBoard'))
def generate(self):
DistributedObject.DistributedObject.generate(self)
DistributedObject.generate(self)
self.buildListParts()
def announceGenerate(self):
DistributedObject.DistributedObject.announceGenerate(self)
self.board.reparentTo(render)
DistributedObject.announceGenerate(self)
self.board.reparentTo(base.render)
self.accept('decorator-holiday-%d-ending' % ToontownGlobals.CRASHED_LEADERBOARD, self.showLists)
self.accept('decorator-holiday-%d-starting' % ToontownGlobals.CRASHED_LEADERBOARD, self.hideLists)
newsManager = base.cr.newsManager
@ -72,7 +72,7 @@ class DistributedLeaderBoard(DistributedObject.DistributedObject):
z = zListTop
self.nameTextNodes = []
self.timeTextNodes = []
for i in range(10):
for _ in range(10):
row, nameText, timeText, placeText = self.buildLeaderRow()
self.nameTextNodes.append(nameText)
placeText.setText(str(len(self.nameTextNodes)) + '.')
@ -81,6 +81,7 @@ class DistributedLeaderBoard(DistributedObject.DistributedObject):
if len(self.nameTextNodes) == 6:
z = zListTop
x = 0.35
row.setX(x)
row.setZ(z)
row.setY(1.6)
@ -105,7 +106,7 @@ class DistributedLeaderBoard(DistributedObject.DistributedObject):
self.timeTextNodes[i].setText('%02d:%02d:%02d' % (min, sec, hundredths * 100))
def buildTitleRow(self):
row = hidden.attachNewNode('TitleRow')
row = base.hidden.attachNewNode('TitleRow')
nameText = TextNode('titleRow')
nameText.setFont(ToontownGlobals.getSignFont())
nameText.setAlign(TextNode.ACenter)
@ -117,7 +118,7 @@ class DistributedLeaderBoard(DistributedObject.DistributedObject):
return (row, nameText)
def buildTrackRow(self):
row = hidden.attachNewNode('trackRow')
row = base.hidden.attachNewNode('trackRow')
nameText = TextNode('trackRow')
nameText.setFont(ToontownGlobals.getSignFont())
nameText.setAlign(TextNode.ACenter)
@ -129,7 +130,7 @@ class DistributedLeaderBoard(DistributedObject.DistributedObject):
return (row, nameText)
def buildLeaderRow(self):
row = hidden.attachNewNode('leaderRow')
row = base.hidden.attachNewNode('leaderRow')
nameText = TextNode('nameText')
nameText.setFont(ToontownGlobals.getToonFont())
nameText.setAlign(TextNode.ALeft)
@ -166,4 +167,4 @@ class DistributedLeaderBoard(DistributedObject.DistributedObject):
self.notify.debug('delete: deleting local leaderboard')
self.ignoreAll()
self.board.removeNode()
DistributedObject.DistributedObject.delete(self)
DistributedObject.delete(self)

View File

@ -41,7 +41,7 @@ class DistributedRace(DistributedObject.DistributedObject):
def __init__(self, cr):
self.qbox = loader.loadModel('phase_6/models/karting/qbox')
self.boostArrowTexture = loader.loadTexture('phase_6/maps/boost_arrow.jpg', 'phase_6/maps/boost_arrow_a.rgb')
self.boostArrowTexture = loader.loadTexture('phase_6/maps/boost_arrow.png')
self.boostArrowTexture.setMinfilter(Texture.FTLinear)
DistributedObject.DistributedObject.__init__(self, cr)
self.kartMap = {}

View File

@ -1,7 +1,7 @@
from direct.directnotify import DirectNotifyGlobal
from panda3d.core import *
from panda3d.physics import *
from direct.gui.DirectGui import *
from panda3d.core import *
from direct.interval.IntervalGlobal import *
from otp.avatar import ShadowCaster
from toontown.racing.KartDNA import *
@ -315,7 +315,7 @@ class Kart(NodePath, ShadowCaster.ShadowCaster):
rimTexPath = getAccessory(getDefaultRim())
else:
rimTexPath = getAccessory(self.kartDNA[KartDNA.rimsType])
rimTex = loader.loadTexture('%s.jpg' % rimTexPath, '%s_a.rgb' % rimTexPath)
rimTex = loader.loadTexture('%s.png' % rimTexPath)
for kart in self.geom:
leftFrontWheelRim = self.geom[kart].find('**/leftFrontWheelRim')
rightFrontWheelRim = self.geom[kart].find('**/rightFrontWheelRim')
@ -397,8 +397,8 @@ class Kart(NodePath, ShadowCaster.ShadowCaster):
if self.kartDNA[KartDNA.decalType] != InvalidEntry:
decalId = getAccessory(self.kartDNA[KartDNA.decalType])
kartDecal = getDecalId(self.kartDNA[KartDNA.bodyType])
hoodDecalTex = loader.loadTexture('phase_6/maps/%s_HoodDecal_%s.jpg' % (kartDecal, decalId), 'phase_6/maps/%s_HoodDecal_%s_a.rgb' % (kartDecal, decalId))
sideDecalTex = loader.loadTexture('phase_6/maps/%s_SideDecal_%s.jpg' % (kartDecal, decalId), 'phase_6/maps/%s_SideDecal_%s_a.rgb' % (kartDecal, decalId))
hoodDecalTex = loader.loadTexture('phase_6/maps/%s_HoodDecal_%s.png' % (kartDecal, decalId))
sideDecalTex = loader.loadTexture('phase_6/maps/%s_SideDecal_%s.png' % (kartDecal, decalId))
hoodDecalTex.setMinfilter(Texture.FTLinearMipmapLinear)
sideDecalTex.setMinfilter(Texture.FTLinearMipmapLinear)
for kart in self.geom:

View File

@ -688,15 +688,15 @@ class KartShopGuiMgr(DirectObject.DirectObject, object):
KartDNA.fwwType,
KartDNA.bwwType]:
texNodePath = getTexCardNode(accID)
tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath, 'phase_6/maps/%s_a.rgb' % texNodePath)
tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath)
elif accType == KartDNA.rimsType:
if accID == InvalidEntry:
texNodePath = getTexCardNode(getDefaultRim())
else:
texNodePath = getTexCardNode(accID)
tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath, 'phase_6/maps/%s_a.rgb' % texNodePath)
tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath)
elif accType in [KartDNA.bodyColor, KartDNA.accColor]:
tex = loader.loadTexture('phase_6/maps/Kartmenu_paintbucket.jpg', 'phase_6/maps/Kartmenu_paintbucket_a.rgb')
tex = loader.loadTexture('phase_6/maps/Kartmenu_paintbucket.png')
if accID == InvalidEntry:
self.kartView.component('geom0').setColorScale(getDefaultColor())
else:
@ -704,9 +704,9 @@ class KartShopGuiMgr(DirectObject.DirectObject, object):
elif accType == KartDNA.decalType:
kartDecal = getDecalId(base.localAvatar.getKartBodyType())
texNodePath = getTexCardNode(accID)
tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath % kartDecal, 'phase_6/maps/%s_a.rgb' % texNodePath % kartDecal)
tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath % kartDecal)
else:
tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.jpg', 'phase_6/maps/NoAccessoryIcon3_a.rgb')
tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.png')
tex.setMinfilter(Texture.FTLinearMipmapLinear)
self.kartView.component('geom0').setTexture(tex, 1)
self.initialize = True
@ -748,15 +748,15 @@ class KartShopGuiMgr(DirectObject.DirectObject, object):
KartDNA.fwwType,
KartDNA.bwwType]:
texNodePath = getTexCardNode(accID)
tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath, 'phase_6/maps/%s_a.rgb' % texNodePath)
tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath)
elif accType == KartDNA.rimsType:
if accID == InvalidEntry:
texNodePath = getTexCardNode(getDefaultRim())
else:
texNodePath = getTexCardNode(accID)
tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath, 'phase_6/maps/%s_a.rgb' % texNodePath)
tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath)
elif accType in [KartDNA.bodyColor, KartDNA.accColor]:
tex = loader.loadTexture('phase_6/maps/Kartmenu_paintbucket.jpg', 'phase_6/maps/Kartmenu_paintbucket_a.rgb')
tex = loader.loadTexture('phase_6/maps/Kartmenu_paintbucket.png')
if accID == InvalidEntry:
self.kartView.component('geom0').setColorScale(getDefaultColor())
else:
@ -764,9 +764,9 @@ class KartShopGuiMgr(DirectObject.DirectObject, object):
elif accType == KartDNA.decalType:
kartDecal = getDecalId(base.localAvatar.getKartBodyType())
texNodePath = getTexCardNode(accID)
tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath % kartDecal, 'phase_6/maps/%s_a.rgb' % texNodePath % kartDecal)
tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath % kartDecal)
else:
tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.jpg', 'phase_6/maps/NoAccessoryIcon3_a.rgb')
tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.png')
tex.setMinfilter(Texture.FTLinearMipmapLinear)
self.kartView.component('geom0').setTexture(tex, 1)
self.initialize = True

View File

@ -1,41 +1,45 @@
from direct.interval.IntervalGlobal import *
from panda3d.core import *
from toontown.toonbase.ToonBaseGlobal import *
from direct.directnotify import DirectNotifyGlobal
from toontown.hood import Place
from direct.showbase import DirectObject
from direct.fsm import StateData
from direct.fsm import ClassicFSM, State
from direct.fsm import State
from direct.task import Task
from toontown.toon import DeathForceAcknowledge
from toontown.toon import HealthForceAcknowledge
from toontown.tutorial import TutorialForceAcknowledge
from toontown.toon import NPCForceAcknowledge
from toontown.trolley import Trolley
from toontown.toontowngui import TTDialog
from toontown.toonbase import ToontownGlobals
from toontown.toon.Toon import teleportDebug
from toontown.toonbase import TTLocalizer
from direct.gui import DirectLabel
from otp.distributed.TelemetryLimiter import RotationLimitToH, TLGatherAllAvs
from toontown.quest import Quests
from panda3d.core import LineSegs, NodePath, TextNode, Vec4
from panda3d.otp import NametagGlobals
class Playground(Place.Place):
notify = DirectNotifyGlobal.directNotify.newCategory('Playground')
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.fsm.ClassicFSM import ClassicFSM
from direct.fsm.State import State
from direct.gui.DirectLabel import DirectLabel
from direct.interval.IntervalGlobal import Func, LerpColorScaleInterval, Sequence
from direct.showbase.MessengerGlobal import messenger
from otp.distributed.TelemetryLimiter import RotationLimitToH, TLGatherAllAvs
from toontown.classicchars import CCharPaths
from toontown.hood.Place import Place
from toontown.quest import Quests
from toontown.toon.DeathForceAcknowledge import DeathForceAcknowledge
from toontown.toon.HealthForceAcknowledge import HealthForceAcknowledge
from toontown.toon.NPCForceAcknowledge import NPCForceAcknowledge
from toontown.toon.Toon import teleportDebug
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import TTLocalizer
from toontown.toonbase.ToonBaseGlobal import base
from toontown.toontowngui import TTDialog
from toontown.trolley.Trolley import Trolley
from toontown.tutorial.TutorialForceAcknowledge import TutorialForceAcknowledge
class Playground(Place):
notify = directNotify.newCategory('Playground')
def __init__(self, loader, parentFSM, doneEvent):
Place.Place.__init__(self, loader, doneEvent)
Place.__init__(self, loader, doneEvent)
self.tfaDoneEvent = 'tfaDoneEvent'
self.fsm = ClassicFSM.ClassicFSM('Playground', [
State.State('start',
self.fsm = ClassicFSM('Playground', [
State('start',
self.enterStart,
self.exitStart, [
'walk',
'deathAck',
'doorIn',
'tunnelIn']),
State.State('walk',
State('walk',
self.enterWalk,
self.exitWalk, [
'drive',
@ -52,7 +56,7 @@ class Playground(Place.Place):
'purchase',
'stopped',
'fishing']),
State.State('stickerBook',
State('stickerBook',
self.enterStickerBook,
self.exitStickerBook, [
'walk',
@ -66,124 +70,124 @@ class Playground(Place.Place):
'stopped',
'fishing',
'trialerFA']),
State.State('sit',
State('sit',
self.enterSit,
self.exitSit, [
'walk',
'DFA',
'trialerFA']),
State.State('drive',
State('drive',
self.enterDrive,
self.exitDrive, [
'walk',
'DFA',
'trialerFA']),
State.State('trolley',
State('trolley',
self.enterTrolley,
self.exitTrolley, [
'walk']),
State.State('doorIn',
State('doorIn',
self.enterDoorIn,
self.exitDoorIn, [
'walk']),
State.State('doorOut',
State('doorOut',
self.enterDoorOut,
self.exitDoorOut, [
'walk']),
State.State('TFA',
State('TFA',
self.enterTFA,
self.exitTFA, [
'TFAReject',
'DFA']),
State.State('TFAReject',
State('TFAReject',
self.enterTFAReject,
self.exitTFAReject, [
'walk']),
State.State('trialerFA',
State('trialerFA',
self.enterTrialerFA,
self.exitTrialerFA, [
'trialerFAReject',
'DFA']),
State.State('trialerFAReject',
State('trialerFAReject',
self.enterTrialerFAReject,
self.exitTrialerFAReject, [
'walk']),
State.State('DFA',
State('DFA',
self.enterDFA,
self.exitDFA, [
'DFAReject',
'NPCFA',
'HFA']),
State.State('DFAReject',
State('DFAReject',
self.enterDFAReject,
self.exitDFAReject, [
'walk']),
State.State('NPCFA',
State('NPCFA',
self.enterNPCFA,
self.exitNPCFA, [
'NPCFAReject',
'HFA']),
State.State('NPCFAReject',
State('NPCFAReject',
self.enterNPCFAReject,
self.exitNPCFAReject, [
'walk']),
State.State('HFA',
State('HFA',
self.enterHFA,
self.exitHFA, [
'HFAReject',
'teleportOut',
'tunnelOut']),
State.State('HFAReject',
State('HFAReject',
self.enterHFAReject,
self.exitHFAReject, [
'walk']),
State.State('deathAck',
State('deathAck',
self.enterDeathAck,
self.exitDeathAck, [
'teleportIn']),
State.State('teleportIn',
State('teleportIn',
self.enterTeleportIn,
self.exitTeleportIn, [
'walk',
'popup']),
State.State('popup',
State('popup',
self.enterPopup,
self.exitPopup, [
'walk']),
State.State('teleportOut',
State('teleportOut',
self.enterTeleportOut,
self.exitTeleportOut, [
'deathAck',
'teleportIn']),
State.State('died',
State('died',
self.enterDied,
self.exitDied, [
'final']),
State.State('tunnelIn',
State('tunnelIn',
self.enterTunnelIn,
self.exitTunnelIn, [
'walk']),
State.State('tunnelOut',
State('tunnelOut',
self.enterTunnelOut,
self.exitTunnelOut, [
'final']),
State.State('quest',
State('quest',
self.enterQuest,
self.exitQuest, [
'walk']),
State.State('purchase',
State('purchase',
self.enterPurchase,
self.exitPurchase, [
'walk']),
State.State('stopped',
State('stopped',
self.enterStopped,
self.exitStopped, [
'walk']),
State.State('fishing',
State('fishing',
self.enterFishing,
self.exitFishing, [
'walk']),
State.State('final',
State('final',
self.enterFinal,
self.exitFinal, [
'start'])],
@ -195,7 +199,6 @@ class Playground(Place.Place):
self.npcfaDoneEvent = 'npcfaDoneEvent'
self.dialog = None
self.deathAckBox = None
return
def enter(self, requestStatus):
self.fsm.enterInitialState()
@ -203,7 +206,7 @@ class Playground(Place.Place):
self.accept('doorDoneEvent', self.handleDoorDoneEvent)
self.accept('DistributedDoor_doorTrigger', self.handleDoorTrigger)
base.playMusic(self.loader.music, looping=1, volume=0.8)
self.loader.geom.reparentTo(render)
self.loader.geom.reparentTo(base.render)
for i in self.loader.nodeList:
self.loader.enterAnimatedProps(i)
@ -231,12 +234,14 @@ class Playground(Place.Place):
self.loader.hood.startSky()
lightsOn = LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, 0.1, Vec4(1, 1, 1, 1))
lightsOn.start()
NametagGlobals.setMasterArrowsOn(1)
self.zoneId = requestStatus['zoneId']
self.tunnelOriginList = base.cr.hoodMgr.addLinkTunnelHooks(self, self.loader.nodeList, self.zoneId)
how = requestStatus['how']
if how == 'teleportIn':
how = 'deathAck'
self.fsm.request(how, [requestStatus])
def exit(self):
@ -248,13 +253,12 @@ class Playground(Place.Place):
node.removeNode()
del self.tunnelOriginList
self.loader.geom.reparentTo(hidden)
self.loader.geom.reparentTo(base.hidden)
def __lightDecorationOff__():
for light in self.loader.hood.halloweenLights:
light.reparentTo(hidden)
light.reparentTo(base.hidden)
newsManager = base.cr.newsManager
NametagGlobals.setMasterArrowsOn(0)
for i in self.loader.nodeList:
self.loader.exitAnimatedProps(i)
@ -263,7 +267,7 @@ class Playground(Place.Place):
self.loader.music.stop()
def load(self):
Place.Place.load(self)
Place.load(self)
self.parentFSM.getStateNamed('playground').addChild(self.fsm)
def unload(self):
@ -273,13 +277,14 @@ class Playground(Place.Place):
if self.dialog:
self.dialog.cleanup()
self.dialog = None
if self.deathAckBox:
self.deathAckBox.cleanup()
self.deathAckBox = None
TTDialog.cleanupDialog('globalDialog')
self.ignoreAll()
Place.Place.unload(self)
return
Place.unload(self)
def showTreasurePoints(self, points):
self.hideDebugPointText()
@ -303,7 +308,6 @@ class Playground(Place.Place):
self.hideDebugPointText()
lines = LineSegs()
lines.setColor(1, 0, 0, 1)
from toontown.classicchars import CCharPaths
for name, pointDef in list(paths.items()):
self.showDebugPointText(name, pointDef[0])
for connectTo in pointDef[1]:
@ -333,6 +337,7 @@ class Playground(Place.Place):
self.debugTextNode.setTextColor(1, 0, 0, 1)
self.debugTextNode.setAlign(TextNode.ACenter)
self.debugTextNode.setFont(ToontownGlobals.getSignFont())
self.debugTextNode.setText(text)
np = self.debugText.attachNewNode(self.debugTextNode.generate())
np.setPos(point[0], point[1], point[2])
@ -344,7 +349,7 @@ class Playground(Place.Place):
base.localAvatar.b_setAnimState('off', 1)
base.localAvatar.cantLeaveGame = 1
self.accept(self.trolleyDoneEvent, self.handleTrolleyDone)
self.trolley = Trolley.Trolley(self, self.fsm, self.trolleyDoneEvent)
self.trolley = Trolley(self, self.fsm, self.trolleyDoneEvent)
self.trolley.load()
self.trolley.enter()
@ -376,7 +381,6 @@ class Playground(Place.Place):
messenger.send(self.doneEvent)
else:
self.notify.error('Unknown mode: ' + mode + ' in handleTrolleyDone')
return
def debugStartMinigame(self, zoneId, minigameId):
self.doneStatus = {'loader': 'minigame',
@ -386,7 +390,6 @@ class Playground(Place.Place):
'shardId': None,
'minigameId': minigameId}
messenger.send(self.doneEvent)
return
def enterTFACallback(self, requestStatus, doneStatus):
self.tfa.exit()
@ -412,7 +415,7 @@ class Playground(Place.Place):
def enterHFA(self, requestStatus):
self.acceptOnce(self.hfaDoneEvent, self.enterHFACallback, [requestStatus])
self.hfa = HealthForceAcknowledge.HealthForceAcknowledge(self.hfaDoneEvent)
self.hfa = HealthForceAcknowledge(self.hfaDoneEvent)
self.hfa.enter(1)
def exitHFA(self):
@ -428,6 +431,7 @@ class Playground(Place.Place):
outHow = {'teleportIn': 'teleportOut',
'tunnelIn': 'tunnelOut',
'doorIn': 'doorOut'}
self.fsm.request(outHow[requestStatus['how']], [requestStatus])
elif doneStatus['mode'] == 'incomplete':
self.fsm.request('HFAReject')
@ -442,7 +446,7 @@ class Playground(Place.Place):
def enterNPCFA(self, requestStatus):
self.acceptOnce(self.npcfaDoneEvent, self.enterNPCFACallback, [requestStatus])
self.npcfa = NPCForceAcknowledge.NPCForceAcknowledge(self.npcfaDoneEvent)
self.npcfa = NPCForceAcknowledge(self.npcfaDoneEvent)
self.npcfa.enter()
def exitNPCFA(self):
@ -469,20 +473,18 @@ class Playground(Place.Place):
self.ignore('deathAck')
self.deathAckBox.cleanup()
self.deathAckBox = None
Place.Place.enterWalk(self, teleportIn)
return
Place.enterWalk(self, teleportIn)
def enterDeathAck(self, requestStatus):
self.deathAckBox = None
self.fsm.request('teleportIn', [requestStatus])
return
def exitDeathAck(self):
if self.deathAckBox:
self.ignore('deathAck')
self.deathAckBox.cleanup()
self.deathAckBox = None
return
def enterTeleportIn(self, requestStatus):
imgScale = 0.25
@ -492,10 +494,10 @@ class Playground(Place.Place):
requestStatus['nextState'] = 'popup'
x, y, z, h, p, r = base.cr.hoodMgr.getPlaygroundCenterFromId(self.loader.hood.id)
self.accept('deathAck', self.__handleDeathAck, extraArgs=[requestStatus])
self.deathAckBox = DeathForceAcknowledge.DeathForceAcknowledge(doneEvent='deathAck')
self.deathAckBox = DeathForceAcknowledge(doneEvent='deathAck')
elif base.localAvatar.hp > 0 and (Quests.avatarHasTrolleyQuest(base.localAvatar) or Quests.avatarHasFirstCogQuest(base.localAvatar) or Quests.avatarHasFriendQuest(base.localAvatar) or Quests.avatarHasPhoneQuest(base.localAvatar) and Quests.avatarHasCompletedPhoneQuest(base.localAvatar)) and self.loader.hood.id == ToontownGlobals.ToontownCentral:
requestStatus['nextState'] = 'popup'
imageModel = loader.loadModel('phase_4/models/gui/tfa_images')
imageModel = base.loader.loadModel('phase_4/models/gui/tfa_images')
if base.localAvatar.quests[0][0] == Quests.TROLLEY_QUEST_ID:
if not Quests.avatarHasCompletedTrolleyQuest(base.localAvatar):
x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(base.cr.hoodMgr.ToontownCentralInitialDropPoints)
@ -526,7 +528,7 @@ class Playground(Place.Place):
if not Quests.avatarHasCompletedFriendQuest(base.localAvatar):
x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(base.cr.hoodMgr.ToontownCentralInitialDropPoints)
msg = TTLocalizer.NPCForceAcknowledgeMessage7
gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui')
gui = base.loader.loadModel('phase_3.5/models/gui/friendslist_gui')
imgNodePath = gui.find('**/FriendsBox_Closed')
imgPos = (0, 0, 0.04)
imgScale = 1.0
@ -544,38 +546,40 @@ class Playground(Place.Place):
imgNodePath = imageModel.find('**/hq-dialog-image')
imgPos = (0, 0, 0.05)
imgScale = 0.5
self.dialog = TTDialog.TTDialog(text=msg, command=self.__cleanupDialog, style=TTDialog.Acknowledge)
imgLabel = DirectLabel.DirectLabel(parent=self.dialog, relief=None, pos=imgPos, scale=TTLocalizer.PimgLabel, image=imgNodePath, image_scale=imgScale)
imgLabel = DirectLabel(parent=self.dialog, relief=None, pos=imgPos, scale=TTLocalizer.PimgLabel, image=imgNodePath, image_scale=imgScale)
imageModel.removeNode()
else:
requestStatus['nextState'] = 'walk'
x, y, z, h, p, r = base.cr.hoodMgr.getPlaygroundCenterFromId(self.loader.hood.id)
base.localAvatar.detachNode()
base.localAvatar.setPosHpr(render, x, y, z, h, p, r)
Place.Place.enterTeleportIn(self, requestStatus)
return
base.localAvatar.setPosHpr(base.render, x, y, z, h, p, r)
Place.enterTeleportIn(self, requestStatus)
def __cleanupDialog(self, value):
if self.dialog:
self.dialog.cleanup()
self.dialog = None
if hasattr(self, 'fsm'):
self.fsm.request('walk', [1])
return
def __handleDeathAck(self, requestStatus):
if self.deathAckBox:
self.ignore('deathAck')
self.deathAckBox.cleanup()
self.deathAckBox = None
self.fsm.request('walk', [1])
return
def enterPopup(self, teleportIn = 0):
if base.localAvatar.hp < 1:
base.localAvatar.b_setAnimState('Sad', 1)
else:
base.localAvatar.b_setAnimState('neutral', 1.0)
self.accept('teleportQuery', self.handleTeleportQuery)
base.localAvatar.setTeleportAvailable(1)
base.localAvatar.startSleepWatch(self.__handleFallingAsleepPopup)
@ -589,18 +593,19 @@ class Playground(Place.Place):
if hasattr(self, 'fsm'):
self.fsm.request('walk')
base.localAvatar.forceGotoSleep()
return Task.done
return task.done
def enterTeleportOut(self, requestStatus):
Place.Place.enterTeleportOut(self, requestStatus, self.__teleportOutDone)
Place.enterTeleportOut(self, requestStatus, self.__teleportOutDone)
def __teleportOutDone(self, requestStatus):
teleportDebug(requestStatus, 'Playground.__teleportOutDone(%s)' % (requestStatus,))
if hasattr(self, 'activityFsm'):
self.activityFsm.requestFinalState()
hoodId = requestStatus['hoodId']
zoneId = requestStatus['zoneId']
avId = requestStatus['avId']
shardId = requestStatus['shardId']
if hoodId == self.loader.hood.hoodId and zoneId == self.loader.hood.hoodId and shardId == None:
teleportDebug(requestStatus, 'same playground')
@ -612,19 +617,19 @@ class Playground(Place.Place):
teleportDebug(requestStatus, 'different hood/zone')
self.doneStatus = requestStatus
messenger.send(self.doneEvent)
return
def exitTeleportOut(self):
Place.Place.exitTeleportOut(self)
Place.exitTeleportOut(self)
def createPlayground(self, dnaFile):
loader.loadDNAFile(self.loader.dnaStore, self.safeZoneStorageDNAFile)
node = loader.loadDNAFile(self.loader.dnaStore, dnaFile)
base.loader.loadDNAFile(self.loader.dnaStore, self.safeZoneStorageDNAFile)
node = base.loader.loadDNAFile(self.loader.dnaStore, dnaFile)
if node.getNumParents() == 1:
self.geom = NodePath(node.getParent(0))
self.geom.reparentTo(hidden)
self.geom.reparentTo(base.hidden)
else:
self.geom = hidden.attachNewNode(node)
self.geom = base.hidden.attachNewNode(node)
self.makeDictionaries(self.loader.dnaStore)
self.tunnelOriginList = base.cr.hoodMgr.addLinkTunnelHooks(self, self.nodeList, self.zoneId)
self.geom.flattenMedium()
@ -636,10 +641,10 @@ class Playground(Place.Place):
self.nodeList = []
for i in range(dnaStore.getNumDNAVisGroups()):
groupFullName = dnaStore.getDNAVisGroupName(i)
groupName = base.cr.hoodMgr.extractGroupName(groupFullName)
groupNode = self.geom.find('**/' + groupFullName)
if groupNode.isEmpty():
self.notify.error('Could not find visgroup')
self.nodeList.append(groupNode)
self.removeLandmarkBlockNodes()
@ -655,7 +660,7 @@ class Playground(Place.Place):
def enterTFA(self, requestStatus):
self.acceptOnce(self.tfaDoneEvent, self.enterTFACallback, [requestStatus])
self.tfa = TutorialForceAcknowledge.TutorialForceAcknowledge(self.tfaDoneEvent)
self.tfa = TutorialForceAcknowledge(self.tfaDoneEvent)
self.tfa.enter()
def exitTFA(self):

View File

@ -34,6 +34,6 @@ class InGameNewsFrame(HtmlView.HtmlView):
filename = filename.replace('.', '-')
pngfilename = filename + '.png'
self.writeTex(pngfilename)
jpgfilename = filename + '.jpg'
jpgfilename = filename + '.png'
self.writeTex(jpgfilename)
return jpgfilename

View File

@ -23,7 +23,7 @@ class IssueFrame(DirectFrame):
-0.751666665077,
0.751666665077)
notify = DirectNotifyGlobal.directNotify.newCategory('IssueFrame')
ContentPattern = 'tt_i_art_%s_%s%d.jpg'
ContentPattern = 'tt_i_art_%s_%s%d.png'
SectionIdents = ['hom',
'new',
'evt',

View File

@ -366,7 +366,7 @@ class ItemSelector(DirectFrame):
self.locator2 = self.attachNewNode('locator2')
self.locator1.setPos(0, 0, 0.035)
self.locator2.setPos(0.0, 0.0, 0.0)
tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.jpg', 'phase_6/maps/NoAccessoryIcon3_a.rgb')
tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.png')
self.uiImagePlane.component('geom0').setTexture(tex, self.texCount)
self.texCount += 1
self.uiTextBox = DirectFrame(parent=self, relief=None, scale=1.0, text='', text_font=ToontownGlobals.getInterfaceFont(), text_fg=(0.5, 0, 0, 1), text_shadow=(0, 0, 0, 1), text_scale=0.0715, text_pos=(0.0, -0.23, 0.0))
@ -526,15 +526,15 @@ class ItemSelector(DirectFrame):
KartDNA.fwwType,
KartDNA.bwwType]:
texNodePath = getTexCardNode(self.currItem)
tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath, 'phase_6/maps/%s_a.rgb' % texNodePath)
tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath)
elif self.currAccessoryType == KartDNA.rimsType:
if self.currItem == InvalidEntry:
texNodePath = getTexCardNode(getDefaultRim())
else:
texNodePath = getTexCardNode(self.currItem)
tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath, 'phase_6/maps/%s_a.rgb' % texNodePath)
tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath)
elif self.currAccessoryType in [KartDNA.bodyColor, KartDNA.accColor]:
tex = loader.loadTexture('phase_6/maps/Kartmenu_paintbucket.jpg', 'phase_6/maps/Kartmenu_paintbucket_a.rgb')
tex = loader.loadTexture('phase_6/maps/Kartmenu_paintbucket.png')
if self.currItem == InvalidEntry:
self.uiImagePlane.component('geom0').setColorScale(getDefaultColor())
else:
@ -543,9 +543,9 @@ class ItemSelector(DirectFrame):
kart = self._parent._parent.getKartViewer().getKart()
kartDecal = getDecalId(kart.kartDNA[KartDNA.bodyType])
texNodePath = getTexCardNode(self.currItem)
tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath % kartDecal, 'phase_6/maps/%s_a.rgb' % texNodePath % kartDecal)
tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath % kartDecal)
else:
tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.jpg', 'phase_6/maps/NoAccessoryIcon3_a.rgb')
tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.png')
colorTypeList = [KartDNA.bodyColor, KartDNA.accColor]
if self.currItem == InvalidEntry:
if self.currAccessoryType == KartDNA.rimsType:
@ -561,7 +561,7 @@ class ItemSelector(DirectFrame):
def __handleHideItem(self):
self.uiImagePlane.component('geom0').setColorScale(1.0, 1.0, 1.0, 1.0)
self.uiImagePlane.component('geom0').setTexture(loader.loadTexture('phase_6/maps/NoAccessoryIcon3.jpg', 'phase_6/maps/NoAccessoryIcon3_a.rgb'), self.texCount)
self.uiImagePlane.component('geom0').setTexture(loader.loadTexture('phase_6/maps/NoAccessoryIcon3.png'), self.texCount)
self.texCount += 1
def __handleItemDeleteConfirm(self):

View File

@ -182,7 +182,7 @@ class PhotoAlbumPage(ShtikerPage.ShtikerPage):
files = os.listdir('.')
photos = []
for fileName in files:
if fileName[0:10] == 'screenshot' and fileName[-4:] == '.jpg':
if fileName[0:10] == 'screenshot' and fileName[-4:] == '.png':
photos.append(fileName)
return photos

View File

@ -176,7 +176,6 @@ class MagicWord(DirectObject):
def handleWord(self, invoker, avId, toon, *args):
raise NotImplementedError
class SetHP(MagicWord):
aliases = ["hp", "setlaff", "laff"]
desc = "Sets the target's current laff."
@ -200,7 +199,6 @@ class SetHP(MagicWord):
toon.b_setHp(hp)
return "{}'s laff has been set to {}.".format(toon.getName(), hp)
class SetMaxHP(MagicWord):
aliases = ["maxhp", "setmaxlaff", "maxlaff"]
desc = "Sets the target's max laff."
@ -219,7 +217,6 @@ class SetMaxHP(MagicWord):
toon.toonUp(maxhp)
return "{}'s max laff has been set to {}.".format(toon.getName(), maxhp)
class ToggleOobe(MagicWord):
aliases = ["oobe"]
desc = "Toggles the out of body experience mode, which lets you move the camera freely."
@ -232,7 +229,6 @@ class ToggleOobe(MagicWord):
base.oobe()
return "Oobe mode has been toggled."
class ToggleRun(MagicWord):
aliases = ["run"]
desc = "Toggles run mode, which gives you a faster running speed."
@ -286,7 +282,40 @@ class MaxToon(MagicWord):
toon.b_setCogLevels([ToontownGlobals.MaxCogSuitLevel] * 4)
return f"Successfully maxed {toon.getName()}!"
class Inventory(MagicWord):
# by default restock the inventory
aliases = ['gags', 'inv']
desc = 'This allows you to modify your inventory in various ways.'
execLocation = MagicWordConfig.EXEC_LOC_SERVER
arguments = [("command", str, False, ''), ("track", str, False, ""), ("level", int, False, 0), ("amount", int, False, 0)]
def handleWord(self, invoker, avId, toon, *args):
command = args[0]
# the list of words that can be used to restock the inventory
restockInvWords = ['restock', 'max', 'all', '', 'fill']
# the list of words that can be used to empty the inventory
emptyInvWords = ['empty', 'zero', 'null', 'clear', 'none', 'reset']
if command in restockInvWords:
toon.inventory.maxOutInv()
toon.d_setInventory(toon.inventory.makeNetString())
return ("Maxing out inventory for " + toon.getName() + ".")
if command in emptyInvWords:
toon.inventory.zeroInv()
toon.d_setInventory(toon.inventory.makeNetString())
return ("Zeroing inventory for " + toon.getName() + ".")
class SetPinkSlips(MagicWord):
# this command gives the target toon the specified amount of pink slips
# default is 255
aliases = ["pinkslips", "fires", 'setfires']
desc = "Gives the target toon the specified amount of pink slips."
execLocation = MagicWordConfig.EXEC_LOC_SERVER
arguments = [("amount", int, False, 255)]
def handleWord(self, invoker, avId, toon, *args):
toon.b_setPinkSlips(args[0])
return f"Gave {toon.getName()} {args[0]} pink slips!"
class AbortMinigame(MagicWord):
aliases = ["exitgame", "exitminigame", "quitgame", "quitminigame", "skipgame", "skipminigame"]
desc = "Aborts an ongoing minigame."
@ -295,7 +324,52 @@ class AbortMinigame(MagicWord):
def handleWord(self, invoker, avId, toon, *args):
messenger.send("minigameAbort")
return "Requested minigame abort."
return "Requested minigame abort."
class SkipMiniGolfHole(MagicWord):
aliases = ["skipgolfhole", "skipgolf", "skiphole"]
desc = "Skips the current golf hole."
execLocation = MagicWordConfig.EXEC_LOC_SERVER
arguments = []
def handleWord(self, invoker, avId, toon, *args):
from toontown.golf.DistributedGolfCourseAI import DistributedGolfCourseAI
course = None
for do in simbase.air.doId2do.values(): # For all doids, check whether it's a golf course, then check if our target is part of it.
if isinstance(do, DistributedGolfCourseAI):
if invoker.doId in do.avIdList:
course = do
break
if not course:
return "You aren't in a golf course!"
if course.isPlayingLastHole(): # If the Toon is on the final hole, calling holeOver() will softlock, so instead we move onto the reward screen.
course.demand('WaitReward')
else:
course.holeOver()
return "Skipped the current hole."
class AbortGolfCourse(MagicWord):
aliases = ["abortminigolf", "abortgolf", "abortcourse", "leavegolf", "leavecourse"]
desc = "Aborts the current golf course."
execLocation = MagicWordConfig.EXEC_LOC_SERVER
arguments = []
def handleWord(self, invoker, avId, toon, *args):
from toontown.golf.DistributedGolfCourseAI import DistributedGolfCourseAI
course = None
for do in simbase.air.doId2do.values(): # For all doids, check whether it's a golf course, then check if our target is part of it.
if isinstance(do, DistributedGolfCourseAI):
if invoker.doId in do.avIdList:
course = do
break
if not course:
return "You aren't in a golf course!"
course.setCourseAbort()
return "Aborted golf course."
class Minigame(MagicWord):
aliases = ["mg"]
@ -350,8 +424,10 @@ class Minigame(MagicWord):
mgId = ToontownGlobals.MinigameNames.get(minigame)
if any((isTeleport, isRequest)):
if isTeleport and (ZoneUtil.isDynamicZone(toon.zoneId) or not toon.zoneId == mgSzId):
return "Target needs to be in a playground to teleport to a minigame."
if isTeleport:
if ZoneUtil.isDynamicZone(toon.zoneId) or not toon.zoneId == mgSzId:
return "Target needs to be in a playground to teleport to a minigame."
mgSzId = ToontownGlobals.ToontownCentral if ZoneUtil.isWelcomeValley(mgSzId) else mgSzId
MinigameCreatorAI.RequestMinigame[avId] = (mgId, mgKeep, mgDiff, mgSzId)
if isTeleport:
try:
@ -479,7 +555,7 @@ class BossBattle(MagicWord):
if not start:
respText += " in Frolic state"
return respText + ", teleporting...", ["cogHQLoader", "cogHQBossBattle", "movie" if start else "teleportIn", boss.getHoodId(), boss.zoneId, 0]
return respText + ", teleporting...", toon.doId, ["cogHQLoader", "cogHQBossBattle", "movie" if start else "teleportIn", boss.getHoodId(), boss.zoneId, 0]
elif command == "list":
# List all the ongoing boss battles.
@ -521,7 +597,7 @@ class BossBattle(MagicWord):
return "Index out of range!"
boss = AllBossCogs[index]
return "Teleporting to boss battle...", ["cogHQLoader", "cogHQBossBattle", "", boss.getHoodId(), boss.zoneId, 0]
return "Teleporting to boss battle...", toon.doId, ["cogHQLoader", "cogHQBossBattle", "", boss.getHoodId(), boss.zoneId, 0]
# The following commands needs the invoker to be in a boss battle.
@ -560,13 +636,129 @@ class BossBattle(MagicWord):
# The create command is already described when the invoker is not in a battle. These are the commands
# they can use INSIDE the battle.
return respText + f"Unknown command: \"{command}\". Valid commands: \"start\", \"stop\", \"skip\", \"final\", \"kill\"."
return f"Unknown command: \"{command}\". Valid commands: \"start\", \"stop\", \"skip\", \"final\", \"kill\"."
def __destroyBoss(self, boss):
bossZone = boss.zoneId
boss.requestDelete()
self.air.deallocateZone(bossZone)
class GlobalTeleport(MagicWord):
aliases = ["globaltp", "tpaccess"]
desc = "Enables teleport access to all zones."
execLocation = MagicWordConfig.EXEC_LOC_SERVER
def handleWord(self, invoker, avId, toon, *args):
from toontown.toonbase import ToontownGlobals
toon.b_setHoodsVisited(ToontownGlobals.HoodsForTeleportAll)
toon.b_setTeleportAccess(ToontownGlobals.HoodsForTeleportAll)
return f"Enabled teleport access to all zones for {toon.getName()}."
class Teleport(MagicWord):
aliases = ["tp", "goto"]
desc = "Teleport to a specified zone."
execLocation = MagicWordConfig.EXEC_LOC_SERVER
arguments = [("zoneName", str, False, '')]
def handleWord(self, invoker, avId, toon, *args):
from toontown.hood import ZoneUtil
from toontown.toonbase import ToontownGlobals
zoneName = args[0]
# Can add stuff like streets to this too if you wanted, but if you do you'll want it to be a valid zone on that street. eg: 2100 is invalid, but any value 2101 to 2156 is fine.
# so if you wanted to add a silly street key, theroetically you could do something like this: 'sillystreet': ToontownGlobals.SillyStreet +1,
zoneName2Id = {'ttc': ToontownGlobals.ToontownCentral,
'dd': ToontownGlobals.DonaldsDock,
'dg': ToontownGlobals.DaisyGardens,
'mml': ToontownGlobals.MinniesMelodyland,
'tb': ToontownGlobals.TheBrrrgh,
'ddl': ToontownGlobals.DonaldsDreamland,
'gs': ToontownGlobals.GoofySpeedway,
'oz': ToontownGlobals.OutdoorZone,
'aa': ToontownGlobals.OutdoorZone,
'gz': ToontownGlobals.GolfZone,
'sbhq': ToontownGlobals.SellbotHQ,
'factory': ToontownGlobals.SellbotFactoryExt,
'cbhq': ToontownGlobals.CashbotHQ,
'lbhq': ToontownGlobals.LawbotHQ,
'bbhq': ToontownGlobals.BossbotHQ}
try:
zone = zoneName2Id[zoneName]
except KeyError:
return "Unknown zone name!"
return f"Requested to teleport {toon.getName()} to zone {zone}.", toon.doId, [ZoneUtil.getBranchLoaderName(zone), ZoneUtil.getToonWhereName(zone), "", ZoneUtil.getHoodId(zone), zone, 0]
class ToggleSleep(MagicWord):
aliases = ["sleep", "nosleep", "neversleep", "togglesleeping", "insomnia"]
desc = "Toggles sleeping for the target."
execLocation = MagicWordConfig.EXEC_LOC_SERVER
def handleWord(self, invoker, avId, toon, *args):
toon.d_toggleSleep()
return f"Toggled sleeping for {toon.getName()}."
class ToggleImmortal(MagicWord):
aliases = ["immortal", "invincible", "invulnerable"]
desc = "Toggle immortal mode. This makes the Toon immune to damage."
execLocation = MagicWordConfig.EXEC_LOC_SERVER
def handleWord(self, invoker, avId, toon, *args):
toon.setImmortalMode(not toon.immortalMode)
return f"Toggled immortal mode for {toon.getName()}"
class ToggleGhost(MagicWord):
aliases = ["ghost", "invisible", "spy"]
desc = "Toggle ghost mode."
execLocation = MagicWordConfig.EXEC_LOC_SERVER
def handleWord(self, invoker, avId, toon, *args):
# 1 is for the attic, 2 enables you to see yourself other ghost toons. 0 is off.
toon.b_setGhostMode(2 if not toon.ghostMode else 0) # As it's primarily for moderation purposes, we set it to 2 here, or 0 if it's already on.
return f"Toggled ghost mode for {toon.getName()}"
class SetGM(MagicWord):
aliases = ["icon", "seticon", "gm", "gmicon", "setgmicon"]
desc = "Sets the GM icon on the target."
execLocation = MagicWordConfig.EXEC_LOC_SERVER
arguments = [("iconRequest", int, False, 0),]
def handleWord(self, invoker, avId, toon, *args):
from toontown.toonbase import TTLocalizer
iconRequest = args[0]
if iconRequest > len(TTLocalizer.GM_NAMES) or iconRequest < 0:
return "Invalid GM icon ID!"
toon.b_setGM(0) # Reset it first, otherwise the Toon keeps the old icon, but the name still changes.
toon.b_setGM(iconRequest)
return f"GM icon set to {iconRequest} for {toon.getName()}"
class SetMaxCarry(MagicWord):
aliases = ["gagpouch", "pouch", "gagcapacity"]
desc = "Set a Toon's gag pouch size."
execLocation = MagicWordConfig.EXEC_LOC_SERVER
arguments = [("pouchSize", int, True)]
def handleWord(self, invoker, avId, toon, *args):
pouchSize = args[0]
if pouchSize > 255 or pouchSize < 0:
return "Specified pouch size must be between 1 and 255."
toon.b_setMaxCarry(pouchSize)
return f"Set gag pouch size to {pouchSize} for {toon.getName()}"
class ToggleInstantKill(MagicWord):
aliases = ["instantkill", "instakill"]
desc = "Toggle the ability to instantly kill a Cog with any gag."
execLocation = MagicWordConfig.EXEC_LOC_SERVER
def handleWord(self, invoker, avId, toon, *args):
toon.setInstantKillMode(not toon.instantKillMode)
return f"Toggled instant-kill mode for {toon.getName()}"
class Fireworks(MagicWord):
aliases = ["firework"]
desc = "Starts a firework show."

View File

@ -275,11 +275,14 @@ class ToontownMagicWordManager(DistributedObject.DistributedObject):
hoodId = place.loader.hood.id
if avId == 0:
avId = -1
place.fsm.forceTransition('teleportOut',
[{"loader": loaderId,
"where": whereId,
"how": how,
"hoodId": hoodId,
"zoneId": zoneId,
"shardId": None,
"avId": avId}])
try:
place.fsm.forceTransition('teleportOut',
[{"loader": loaderId,
"where": whereId,
"how": how,
"hoodId": hoodId,
"zoneId": zoneId,
"shardId": None,
"avId": avId}])
except Exception: # Most likely cause is the place the avatar is in has no teleportOut state, for example, boss lobbies.
place.fsm.request('DFAReject') # We have to do this, or the avatar will be stuck.

View File

@ -19,6 +19,7 @@ from toontown.distributed import DelayDelete
from toontown.chat import ResistanceChat
from toontown.coghq import CogDisguiseGlobals
from panda3d.core import *
from panda3d.direct import ShowInterval
from panda3d.physics import *
from panda3d.otp import *
import random

View File

@ -442,7 +442,7 @@ class Suit(Avatar.Avatar):
self.scale = 6.75 / cSize
self.handColor = VBase4(0.85, 0.55, 0.55, 1.0)
self.generateBody()
self.headTexture = 'corporate-raider.jpg'
self.headTexture = 'corporate-raider.png'
self.generateHead('flunky')
self.setHeight(8.23)
elif dna.name == 'tbc':
@ -455,21 +455,21 @@ class Suit(Avatar.Avatar):
self.scale = 4.0 / cSize
self.handColor = SuitDNA.legalPolyColor
self.generateBody()
self.headTexture = 'bottom-feeder.jpg'
self.headTexture = 'bottom-feeder.png'
self.generateHead('tightwad')
self.setHeight(4.81)
elif dna.name == 'b':
self.scale = 4.375 / bSize
self.handColor = VBase4(0.95, 0.95, 1.0, 1.0)
self.generateBody()
self.headTexture = 'blood-sucker.jpg'
self.headTexture = 'blood-sucker.png'
self.generateHead('movershaker')
self.setHeight(6.17)
elif dna.name == 'dt':
self.scale = 4.25 / aSize
self.handColor = SuitDNA.legalPolyColor
self.generateBody()
self.headTexture = 'double-talker.jpg'
self.headTexture = 'double-talker.png'
self.generateHead('twoface')
self.setHeight(5.63)
elif dna.name == 'ac':
@ -488,7 +488,7 @@ class Suit(Avatar.Avatar):
self.scale = 5.65 / bSize
self.handColor = VBase4(0.5, 0.8, 0.75, 1.0)
self.generateBody()
self.headTexture = 'spin-doctor.jpg'
self.headTexture = 'spin-doctor.png'
self.generateHead('telemarketer')
self.setHeight(7.9)
elif dna.name == 'le':
@ -549,7 +549,7 @@ class Suit(Avatar.Avatar):
self.scale = 7.0 / aSize
self.handColor = SuitDNA.moneyPolyColor
self.generateBody()
self.headTexture = 'robber-baron.jpg'
self.headTexture = 'robber-baron.png'
self.generateHead('yesman')
self.setHeight(8.95)
elif dna.name == 'cc':
@ -569,7 +569,7 @@ class Suit(Avatar.Avatar):
self.scale = 4.35 / aSize
self.handColor = SuitDNA.salesPolyColor
self.generateBody()
self.headTexture = 'name-dropper.jpg'
self.headTexture = 'name-dropper.png'
self.generateHead('numbercruncher')
self.setHeight(5.98)
elif dna.name == 'gh':
@ -594,7 +594,7 @@ class Suit(Avatar.Avatar):
self.scale = 5.75 / aSize
self.handColor = SuitDNA.salesPolyColor
self.generateBody()
self.headTexture = 'mingler.jpg'
self.headTexture = 'mingler.png'
self.generateHead('twoface')
self.setHeight(7.61)
elif dna.name == 'mh':
@ -677,13 +677,13 @@ class Suit(Avatar.Avatar):
phase = 3.5
def __doItTheOldWay__():
torsoTex = loader.loadTexture('phase_%s/maps/%s_blazer.jpg' % (phase, dept))
torsoTex = loader.loadTexture('phase_%s/maps/%s_blazer.png' % (phase, dept))
torsoTex.setMinfilter(Texture.FTLinearMipmapLinear)
torsoTex.setMagfilter(Texture.FTLinear)
legTex = loader.loadTexture('phase_%s/maps/%s_leg.jpg' % (phase, dept))
legTex = loader.loadTexture('phase_%s/maps/%s_leg.png' % (phase, dept))
legTex.setMinfilter(Texture.FTLinearMipmapLinear)
legTex.setMagfilter(Texture.FTLinear)
armTex = loader.loadTexture('phase_%s/maps/%s_sleeve.jpg' % (phase, dept))
armTex = loader.loadTexture('phase_%s/maps/%s_sleeve.png' % (phase, dept))
armTex.setMinfilter(Texture.FTLinearMipmapLinear)
armTex.setMagfilter(Texture.FTLinear)
modelRoot.find('**/torso').setTexture(torsoTex, 1)
@ -707,8 +707,8 @@ class Suit(Avatar.Avatar):
if self.find('**/body').isEmpty():
__doItTheOldWay__()
else:
filepath = 'phase_3.5/maps/tt_t_ene_' + texType + '.jpg'
if cogExists('/maps/tt_t_ene_' + texType + '.jpg'):
filepath = 'phase_3.5/maps/tt_t_ene_' + texType + '.png'
if cogExists('/maps/tt_t_ene_' + texType + '.png'):
bodyTex = loader.loadTexture(filepath)
self.find('**/body').setTexture(bodyTex, 1)
self.leftHand = self.find('**/def_joint_left_hold')
@ -722,13 +722,13 @@ class Suit(Avatar.Avatar):
if not modelRoot:
modelRoot = self
self.isWaiter = 1
torsoTex = loader.loadTexture('phase_3.5/maps/waiter_m_blazer.jpg')
torsoTex = loader.loadTexture('phase_3.5/maps/waiter_m_blazer.png')
torsoTex.setMinfilter(Texture.FTLinearMipmapLinear)
torsoTex.setMagfilter(Texture.FTLinear)
legTex = loader.loadTexture('phase_3.5/maps/waiter_m_leg.jpg')
legTex = loader.loadTexture('phase_3.5/maps/waiter_m_leg.png')
legTex.setMinfilter(Texture.FTLinearMipmapLinear)
legTex.setMagfilter(Texture.FTLinear)
armTex = loader.loadTexture('phase_3.5/maps/waiter_m_sleeve.jpg')
armTex = loader.loadTexture('phase_3.5/maps/waiter_m_sleeve.png')
armTex.setMinfilter(Texture.FTLinearMipmapLinear)
armTex.setMagfilter(Texture.FTLinear)
modelRoot.find('**/torso').setTexture(torsoTex, 1)
@ -739,10 +739,10 @@ class Suit(Avatar.Avatar):
if not modelRoot:
modelRoot = self.getGeomNode()
if suitType == 's':
torsoTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_blazer.jpg')
legTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_leg.jpg')
armTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_sleeve.jpg')
handTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_hand.jpg')
torsoTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_blazer.png')
legTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_leg.png')
armTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_sleeve.png')
handTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_hand.png')
else:
self.notify.warning('No rental suit for cog type %s' % suitType)
return
@ -786,13 +786,13 @@ class Suit(Avatar.Avatar):
self.notify.warning('skelecog has no tie model!!!')
return
if dept == 'c':
tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_boss.jpg')
tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_boss.png')
elif dept == 's':
tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_sales.jpg')
tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_sales.png')
elif dept == 'l':
tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_legal.jpg')
tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_legal.png')
elif dept == 'm':
tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_money.jpg')
tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_money.png')
tieTex.setMinfilter(Texture.FTLinearMipmapLinear)
tieTex.setMagfilter(Texture.FTLinear)
tie.setTexture(tieTex, 1)

View File

@ -2528,7 +2528,7 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute
self._handleGMName()
def _handleGMName(self):
name = self.name
name = self._name
self.setDisplayName(name)
if self._isGM:
self.setNametagStyle(5)
@ -2589,3 +2589,6 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute
def getTransitioning(self):
return self.transitioning
def toggleSleep(self):
base.localAvatar.noSleep = not base.localAvatar.noSleep

View File

@ -155,6 +155,7 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo
self.savedCheesyExpireTime = 0
self.ghostMode = 0
self.immortalMode = 0
self.instantKillMode = 0
self.numPies = 0
self.pieType = 0
self._isGM = False
@ -2375,6 +2376,9 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo
def setImmortalMode(self, flag):
self.immortalMode = flag
def setInstantKillMode(self, flag):
self.instantKillMode = flag
def b_setSpeedChatStyleIndex(self, index):
self.setSpeedChatStyleIndex(index)
self.d_setSpeedChatStyleIndex(index)
@ -4129,6 +4133,9 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo
zoneId])
self.air.send(dg)
def d_toggleSleep(self):
self.sendUpdate('toggleSleep', [])
@staticmethod
def staticGetLogicalZoneChangeAllEvent():
return 'DOLogicalChangeZone-all'

View File

@ -860,6 +860,9 @@ class Toon(Avatar.Avatar, ToonHead):
self.resetHeight()
self.setupToonNodes()
self.generateBackpack()
hands = self.getRightHands()
for bookActor, hand in zip(self.__bookActors, hands):
bookActor.reparentTo(hand)
def generateToonHead(self, copy = 1):
headHeight = ToonHead.generateToonHead(self, copy, self.style, ('1000', '500', '250'))
@ -1165,7 +1168,7 @@ class Toon(Avatar.Avatar, ToonHead):
for geom in geoms:
texName = ToonDNA.ShoesTextures[shoes[1]]
if self.style.legs == 'l' and shoes[0] == 3:
texName = texName[:-4] + 'LL.jpg'
texName = texName[:-4] + 'LL.png'
tex = loader.loadTexture(texName, okMissing=True)
if tex is None:
self.sendLogSuspiciousEvent('failed to load texture %s' % texName)
@ -1995,7 +1998,7 @@ class Toon(Avatar.Avatar, ToonHead):
def exitSitStart(self):
self.playingAnim = 'neutral'
if self.track != None:
self.track.finish()
self.track.pause()
DelayDelete.cleanupDelayDeletes(self.track)
self.track = None
Emote.globalEmote.releaseBody(self)

File diff suppressed because it is too large Load Diff

View File

@ -49,31 +49,31 @@ DogMuzzleDict = {'dls': '/models/char/dogMM_Shorts-headMuzzles-',
class ToonHead(Actor.Actor):
notify = DirectNotifyGlobal.directNotify.newCategory('ToonHead')
EyesOpen = loader.loadTexture('phase_3/maps/eyes.jpg', 'phase_3/maps/eyes_a.rgb')
EyesOpen = loader.loadTexture('phase_3/maps/eyes.png')
EyesOpen.setMinfilter(Texture.FTLinear)
EyesOpen.setMagfilter(Texture.FTLinear)
EyesClosed = loader.loadTexture('phase_3/maps/eyesClosed.jpg', 'phase_3/maps/eyesClosed_a.rgb')
EyesClosed = loader.loadTexture('phase_3/maps/eyesClosed.png')
EyesClosed.setMinfilter(Texture.FTLinear)
EyesClosed.setMagfilter(Texture.FTLinear)
EyesSadOpen = loader.loadTexture('phase_3/maps/eyesSad.jpg', 'phase_3/maps/eyesSad_a.rgb')
EyesSadOpen = loader.loadTexture('phase_3/maps/eyesSad.png')
EyesSadOpen.setMinfilter(Texture.FTLinear)
EyesSadOpen.setMagfilter(Texture.FTLinear)
EyesSadClosed = loader.loadTexture('phase_3/maps/eyesSadClosed.jpg', 'phase_3/maps/eyesSadClosed_a.rgb')
EyesSadClosed = loader.loadTexture('phase_3/maps/eyesSadClosed.png')
EyesSadClosed.setMinfilter(Texture.FTLinear)
EyesSadClosed.setMagfilter(Texture.FTLinear)
EyesAngryOpen = loader.loadTexture('phase_3/maps/eyesAngry.jpg', 'phase_3/maps/eyesAngry_a.rgb')
EyesAngryOpen = loader.loadTexture('phase_3/maps/eyesAngry.png')
EyesAngryOpen.setMinfilter(Texture.FTLinear)
EyesAngryOpen.setMagfilter(Texture.FTLinear)
EyesAngryClosed = loader.loadTexture('phase_3/maps/eyesAngryClosed.jpg', 'phase_3/maps/eyesAngryClosed_a.rgb')
EyesAngryClosed = loader.loadTexture('phase_3/maps/eyesAngryClosed.png')
EyesAngryClosed.setMinfilter(Texture.FTLinear)
EyesAngryClosed.setMagfilter(Texture.FTLinear)
EyesSurprised = loader.loadTexture('phase_3/maps/eyesSurprised.jpg', 'phase_3/maps/eyesSurprised_a.rgb')
EyesSurprised = loader.loadTexture('phase_3/maps/eyesSurprised.png')
EyesSurprised.setMinfilter(Texture.FTLinear)
EyesSurprised.setMagfilter(Texture.FTLinear)
Muzzle = loader.loadTexture('phase_3/maps/muzzleShrtGeneric.jpg')
Muzzle = loader.loadTexture('phase_3/maps/muzzleShrtGeneric.png')
Muzzle.setMinfilter(Texture.FTLinear)
Muzzle.setMagfilter(Texture.FTLinear)
MuzzleSurprised = loader.loadTexture('phase_3/maps/muzzleShortSurprised.jpg')
MuzzleSurprised = loader.loadTexture('phase_3/maps/muzzleShortSurprised.png')
MuzzleSurprised.setMinfilter(Texture.FTLinear)
MuzzleSurprised.setMagfilter(Texture.FTLinear)
LeftA = Point3(0.06, 0.0, 0.14)

View File

@ -10,22 +10,24 @@ InterfaceFont = 'phase_3/models/fonts/ImpressBT.ttf'
ToonFont = 'phase_3/models/fonts/ImpressBT.ttf'
SuitFont = 'phase_3/models/fonts/vtRemingtonPortable.ttf'
SignFont = 'phase_3/models/fonts/MickeyFont'
MinnieFont = 'phase_3/models/fonts/MinnieFont'
FancyFont = 'phase_3/models/fonts/Comedy'
NametagFonts = ('phase_3/models/fonts/AnimGothic',
'phase_3/models/fonts/Aftershock',
'phase_3/models/fonts/JiggeryPokery',
'phase_3/models/fonts/Ironwork',
'phase_3/models/fonts/HastyPudding',
'phase_3/models/fonts/Comedy',
'phase_3/models/fonts/Humanist',
'phase_3/models/fonts/Portago',
'phase_3/models/fonts/Musicals',
'phase_3/models/fonts/Scurlock',
'phase_3/models/fonts/Danger',
'phase_3/models/fonts/Alie',
'phase_3/models/fonts/OysterBar',
'phase_3/models/fonts/RedDogSaloon')
MinnieFont = 'phase_3/models/fonts/MinnieFont.ttf'
FancyFont = 'phase_3/models/fonts/Comedy.ttf'
NametagFonts = (
'phase_3/models/fonts/AnimGothic.ttf',
'phase_3/models/fonts/Aftershock.ttf',
'phase_3/models/fonts/JiggeryPokery.ttf',
'phase_3/models/fonts/Ironwork.ttf',
'phase_3/models/fonts/HastyPudding.ttf',
'phase_3/models/fonts/Comedy.ttf',
'phase_3/models/fonts/Humanist.ttf',
'phase_3/models/fonts/Portago.ttf',
'phase_3/models/fonts/Musicals.ttf',
'phase_3/models/fonts/Scurlock.ttf',
'phase_3/models/fonts/Danger.ttf',
'phase_3/models/fonts/Alie.ttf',
'phase_3/models/fonts/OysterBar.ttf',
'phase_3/models/fonts/RedDogSaloon.ttf'
)
NametagFontNames = ('Member',
'Shivering',
'Wonky',

View File

@ -1 +1,5 @@
from .ToonBase import *
__all__ = ['base']
from .ToonBase import ToonBase
base = ToonBase()

View File

@ -6,7 +6,20 @@ class game:
builtins.game = game()
from panda3d.core import *
from panda3d.core import (
ConfigVariableBool,
ConfigVariableDouble,
ConfigVariableString,
Filename,
HTTPClient,
Loader,
loadPrcFile,
TextNode,
Thread,
VBase3,
Vec4
)
import time
import sys
try:
@ -31,6 +44,7 @@ if launcher.isDummy():
http = HTTPClient()
else:
http = launcher.http
tempLoader = Loader()
backgroundNode = tempLoader.loadSync(Filename('phase_3/models/gui/loading-background'))
from direct.gui import DirectGuiGlobals
@ -38,11 +52,11 @@ print('ToontownStart: setting default font')
from . import ToontownGlobals
DirectGuiGlobals.setDefaultFontFunc(ToontownGlobals.getInterfaceFont)
launcher.setPandaErrorCode(7)
from . import ToonBase
ToonBase.ToonBase()
from .ToonBaseGlobal import base
if base.win == None:
print('Unable to open window; aborting.')
sys.exit()
launcher.setPandaErrorCode(0)
launcher.setPandaWindowOpen()
ConfigVariableDouble('decompressor-step-time').setValue(0.01)
@ -65,31 +79,32 @@ if base.musicManagerIsValid:
music.setLoop(1)
music.setVolume(0.9)
music.play()
print('ToontownStart: Loading default gui sounds')
DirectGuiGlobals.setDefaultRolloverSound(base.loader.loadSfx('phase_3/audio/sfx/GUI_rollover.ogg'))
DirectGuiGlobals.setDefaultClickSound(base.loader.loadSfx('phase_3/audio/sfx/GUI_create_toon_fwd.ogg'))
else:
music = None
from direct.gui.DirectGui import *
from direct.gui.DirectGui import OnscreenText
serverVersion = ConfigVariableString('server-version', 'no_version_set').value
print('ToontownStart: serverVersion: ', serverVersion)
version = OnscreenText(serverVersion, pos=(-1.3, -0.975), scale=0.06, fg=Vec4(0, 0, 1, 0.6), align=TextNode.ALeft)
loader.beginBulkLoad('init', TTLocalizer.LoaderLabel, 138, 0, TTLocalizer.TIP_NONE)
from .ToonBaseGlobal import *
from direct.showbase.MessengerGlobal import *
from toontown.distributed import ToontownClientRepository
cr = ToontownClientRepository.ToontownClientRepository(serverVersion, launcher)
from toontown.distributed.ToontownClientRepository import ToontownClientRepository
cr = ToontownClientRepository(serverVersion, launcher)
cr.music = music
del music
base.initNametagGlobals()
base.cr = cr
loader.endBulkLoad('init')
from otp.distributed.OtpDoGlobals import *
from otp.distributed.OtpDoGlobals import OTP_DO_ID_FRIEND_MANAGER
cr.generateGlobalObject(OTP_DO_ID_FRIEND_MANAGER, 'FriendManager')
if not launcher.isDummy():
base.startShow(cr, launcher.getGameServer())
else:
base.startShow(cr)
backgroundNodePath.reparentTo(hidden)
backgroundNodePath.removeNode()
del backgroundNodePath
@ -97,7 +112,6 @@ del backgroundNode
del tempLoader
version.cleanup()
del version
base.loader = base.loader
builtins.loader = base.loader
autoRun = ConfigVariableBool('toontown-auto-run', 1)
if autoRun and launcher.isDummy() and (not Thread.isTrueThreads() or __name__ == '__main__'):

View File

@ -381,13 +381,11 @@ class Street(BattlePlace.BattlePlace):
streetSign = base.cr.streetSign
signTexturePath = streetSign.StreetSignBaseDir + '/' + streetSign.StreetSignFileName
loaderTexturePath = Filename(str(signTexturePath))
alphaPath = 'phase_4/maps/tt_t_ara_gen_tunnelAheadSign_a.rgb'
inDreamland = False
if place.zoneId and ZoneUtil.getCanonicalHoodId(place.zoneId) == ToontownGlobals.DonaldsDreamland:
inDreamland = True
alphaPath = 'phase_4/maps/tt_t_ara_gen_tunnelAheadSign_a.rgb'
if Filename(signTexturePath).exists():
signTexture = loader.loadTexture(loaderTexturePath, alphaPath)
signTexture = loader.loadTexture(loaderTexturePath)
for sign in signs:
if Filename(signTexturePath).exists():
sign.setTexture(signTexture, 1)

View File

@ -3,3 +3,6 @@ from direct.distributed.DistributedObjectAI import DistributedObjectAI
class DistributedPartyManagerAI(DistributedObjectAI):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPartyManagerAI')
def canBuyParties(self):
return False # TODO