Poodletooth-iLand/toontown/toonbase/ToonBase.py

458 lines
20 KiB
Python
Raw Normal View History

2015-03-03 16:10:12 -06:00
import atexit
from direct.directnotify import DirectNotifyGlobal
from direct.filter.CommonFilters import CommonFilters
from direct.gui import DirectGuiGlobals
from direct.gui.DirectGui import *
from direct.showbase.PythonUtil import *
from direct.showbase.Transitions import Transitions
from direct.task import *
import math
import os
from panda3d.core import *
2015-03-03 16:10:12 -06:00
import random
import shutil
from sys import platform
import sys
import tempfile
import time
import ToontownGlobals
import ToontownLoader
from otp.otpbase import OTPBase
from otp.otpbase import OTPGlobals
2015-06-24 11:32:30 -05:00
from otp.nametag.ChatBalloon import ChatBalloon
from otp.nametag import NametagGlobals
from otp.margins.MarginManager import MarginManager
2015-03-03 16:10:12 -06:00
from toontown.toonbase import TTLocalizer
from toontown.toonbase import ToontownBattleGlobals
from toontown.toontowngui import TTDialog
class ToonBase(OTPBase.OTPBase):
notify = DirectNotifyGlobal.directNotify.newCategory('ToonBase')
def __init__(self):
OTPBase.OTPBase.__init__(self)
self.disableShowbaseMouse()
self.addCullBins()
self.debugRunningMultiplier /= OTPGlobals.ToonSpeedFactor
self.baseXpMultiplier = self.config.GetFloat('base-xp-multiplier', 1.0)
self.toonChatSounds = self.config.GetBool('toon-chat-sounds', 1)
self.placeBeforeObjects = self.config.GetBool('place-before-objects', 1)
self.endlessQuietZone = False
self.wantDynamicShadows = 0
self.exitErrorCode = 0
camera.setPosHpr(0, 0, 0, 0, 0, 0)
self.camLens.setMinFov(settings['fov']/(4./3.))
2015-03-03 16:10:12 -06:00
self.camLens.setNearFar(ToontownGlobals.DefaultCameraNear, ToontownGlobals.DefaultCameraFar)
self.musicManager.setVolume(0.65)
self.setBackgroundColor(ToontownGlobals.DefaultBackgroundColor)
tpm = TextPropertiesManager.getGlobalPtr()
candidateActive = TextProperties()
candidateActive.setTextColor(0, 0, 1, 1)
tpm.setProperties('candidate_active', candidateActive)
candidateInactive = TextProperties()
candidateInactive.setTextColor(0.3, 0.3, 0.7, 1)
tpm.setProperties('candidate_inactive', candidateInactive)
self.transitions.IrisModelName = 'phase_3/models/misc/iris'
self.transitions.FadeModelName = 'phase_3/models/misc/fade'
self.exitFunc = self.userExit
globalClock.setMaxDt(0.2)
if self.config.GetBool('want-particles', 1) == 1:
self.notify.debug('Enabling particles')
self.enableParticles()
self.accept(ToontownGlobals.ScreenshotHotkey, self.takeScreenShot)
# OS X Specific Actions
if platform == "darwin":
self.acceptOnce(ToontownGlobals.QuitGameHotKeyOSX, self.exitOSX)
self.accept(ToontownGlobals.QuitGameHotKeyRepeatOSX, self.exitOSX)
self.acceptOnce(ToontownGlobals.HideGameHotKeyOSX, self.hideGame)
self.accept(ToontownGlobals.HideGameHotKeyRepeatOSX, self.hideGame)
self.acceptOnce(ToontownGlobals.MinimizeGameHotKeyOSX, self.minimizeGame)
self.accept(ToontownGlobals.MinimizeGameHotKeyRepeatOSX, self.minimizeGame)
self.accept('f3', self.toggleGui)
self.accept('f4', self.oobe)
2015-03-03 16:10:12 -06:00
self.accept('panda3d-render-error', self.panda3dRenderError)
oldLoader = self.loader
self.loader = ToontownLoader.ToontownLoader(self)
__builtins__['loader'] = self.loader
oldLoader.destroy()
self.accept('PandaPaused', self.disableAllAudio)
self.accept('PandaRestarted', self.enableAllAudio)
self.wantPets = self.config.GetBool('want-pets', 1)
self.wantBingo = self.config.GetBool('want-fish-bingo', 1)
self.wantKarts = self.config.GetBool('want-karts', 1)
self.inactivityTimeout = self.config.GetFloat('inactivity-timeout', ToontownGlobals.KeyboardTimeout)
if self.inactivityTimeout:
self.notify.debug('Enabling Panda timeout: %s' % self.inactivityTimeout)
self.mouseWatcherNode.setInactivityTimeout(self.inactivityTimeout)
self.mouseWatcherNode.setEnterPattern('mouse-enter-%r')
self.mouseWatcherNode.setLeavePattern('mouse-leave-%r')
self.mouseWatcherNode.setButtonDownPattern('button-down-%r')
self.mouseWatcherNode.setButtonUpPattern('button-up-%r')
self.randomMinigameAbort = self.config.GetBool('random-minigame-abort', 0)
self.randomMinigameDisconnect = self.config.GetBool('random-minigame-disconnect', 0)
self.randomMinigameNetworkPlugPull = self.config.GetBool('random-minigame-netplugpull', 0)
self.autoPlayAgain = self.config.GetBool('auto-play-again', 0)
self.skipMinigameReward = self.config.GetBool('skip-minigame-reward', 0)
self.wantMinigameDifficulty = self.config.GetBool('want-minigame-difficulty', 0)
self.minigameDifficulty = self.config.GetFloat('minigame-difficulty', -1.0)
if self.minigameDifficulty == -1.0:
del self.minigameDifficulty
self.minigameSafezoneId = self.config.GetInt('minigame-safezone-id', -1)
if self.minigameSafezoneId == -1:
del self.minigameSafezoneId
cogdoGameSafezoneId = self.config.GetInt('cogdo-game-safezone-id', -1)
cogdoGameDifficulty = self.config.GetFloat('cogdo-game-difficulty', -1)
if cogdoGameDifficulty != -1:
self.cogdoGameDifficulty = cogdoGameDifficulty
if cogdoGameSafezoneId != -1:
self.cogdoGameSafezoneId = cogdoGameSafezoneId
ToontownBattleGlobals.SkipMovie = self.config.GetBool('skip-battle-movies', 0)
self.housingEnabled = self.config.GetBool('want-housing', 1)
self.cannonsEnabled = self.config.GetBool('estate-cannons', 0)
self.fireworksEnabled = self.config.GetBool('estate-fireworks', 0)
self.dayNightEnabled = self.config.GetBool('estate-day-night', 0)
self.cloudPlatformsEnabled = self.config.GetBool('estate-clouds', 0)
self.greySpacing = self.config.GetBool('allow-greyspacing', 0)
self.slowQuietZone = self.config.GetBool('slow-quiet-zone', 0)
self.slowQuietZoneDelay = self.config.GetFloat('slow-quiet-zone-delay', 5)
self.killInterestResponse = self.config.GetBool('kill-interest-response', 0)
tpMgr = TextPropertiesManager.getGlobalPtr()
WLDisplay = TextProperties()
WLDisplay.setSlant(0.3)
tpMgr.setProperties('WLDisplay', WLDisplay)
2015-06-09 15:24:18 -05:00
WLRed = tpMgr.getProperties('red')
WLRed.setTextColor(1.0, 0.0, 0.0, 1)
tpMgr.setProperties('WLRed', WLRed)
2015-03-03 16:10:12 -06:00
del tpMgr
self.lastScreenShotTime = globalClock.getRealTime()
self.accept('InputState-forward', self.__walking)
self.canScreenShot = 1
self.glitchCount = 0
self.walking = 0
self.oldX = max(1, base.win.getXSize())
self.oldY = max(1, base.win.getYSize())
self.aspectRatio = float(self.oldX) / self.oldY
self.localAvatarStyle = None
self.filters = CommonFilters(self.win, self.cam)
self.wantCogInterface = settings.get('cogInterface', True)
2015-03-03 16:10:12 -06:00
def openMainWindow(self, *args, **kw):
result = OTPBase.OTPBase.openMainWindow(self, *args, **kw)
self.setCursorAndIcon()
return result
def windowEvent(self, win):
OTPBase.OTPBase.windowEvent(self, win)
def setCursorAndIcon(self):
tempdir = tempfile.mkdtemp()
atexit.register(shutil.rmtree, tempdir)
vfs = VirtualFileSystem.getGlobalPtr()
searchPath = DSearchPath()
if __debug__:
searchPath.appendDirectory(Filename('resources/phase_3/etc'))
searchPath.appendDirectory(Filename('/phase_3/etc'))
for filename in ['toonmono.cur', 'icon.ico']:
p3filename = Filename(filename)
found = vfs.resolveFilename(p3filename, searchPath)
if not found:
return # Can't do anything past this point.
with open(os.path.join(tempdir, filename), 'wb') as f:
f.write(vfs.readFile(p3filename, False))
wp = WindowProperties()
wp.setCursorFilename(Filename.fromOsSpecific(os.path.join(tempdir, 'toonmono.cur')))
wp.setIconFilename(Filename.fromOsSpecific(os.path.join(tempdir, 'icon.ico')))
self.win.requestProperties(wp)
def addCullBins(self):
cbm = CullBinManager.getGlobalPtr()
cbm.addBin('ground', CullBinManager.BTUnsorted, 18)
cbm.addBin('shadow', CullBinManager.BTBackToFront, 19)
cbm.addBin('gui-popup', CullBinManager.BTUnsorted, 60)
def disableShowbaseMouse(self):
self.useDrive()
self.disableMouse()
if self.mouseInterface: self.mouseInterface.detachNode()
if self.mouse2cam: self.mouse2cam.detachNode()
def __walking(self, pressed):
self.walking = pressed
def toggleGui(self):
if aspect2d.isHidden():
aspect2d.show()
else:
aspect2d.hide()
def takeScreenShot(self):
if not os.path.exists(TTLocalizer.ScreenshotPath):
os.mkdir(TTLocalizer.ScreenshotPath)
self.notify.info('Made new directory to save screenshots.')
namePrefix = TTLocalizer.ScreenshotPath + launcher.logPrefix + 'screenshot'
timedif = globalClock.getRealTime() - self.lastScreenShotTime
if self.glitchCount > 10 and self.walking:
return
if timedif < 1.0 and self.walking:
self.glitchCount += 1
return
if not hasattr(self, 'localAvatar'):
self.screenshot(namePrefix=namePrefix)
self.lastScreenShotTime = globalClock.getRealTime()
return
coordOnScreen = self.config.GetBool('screenshot-coords', 0)
self.localAvatar.stopThisFrame = 1
ctext = self.localAvatar.getAvPosStr()
self.screenshotStr = ''
messenger.send('takingScreenshot')
if coordOnScreen:
coordTextLabel = DirectLabel(pos=(-0.81, 0.001, -0.87), text=ctext, text_scale=0.05, text_fg=VBase4(1.0, 1.0, 1.0, 1.0), text_bg=(0, 0, 0, 0), text_shadow=(0, 0, 0, 1), relief=None)
coordTextLabel.setBin('gui-popup', 0)
strTextLabel = None
if len(self.screenshotStr):
strTextLabel = DirectLabel(pos=(0.0, 0.001, 0.9), text=self.screenshotStr, text_scale=0.05, text_fg=VBase4(1.0, 1.0, 1.0, 1.0), text_bg=(0, 0, 0, 0), text_shadow=(0, 0, 0, 1), relief=None)
strTextLabel.setBin('gui-popup', 0)
self.graphicsEngine.renderFrame()
self.screenshot(namePrefix=namePrefix, imageComment=ctext + ' ' + self.screenshotStr)
self.lastScreenShotTime = globalClock.getRealTime()
self.snapshotSfx = base.loadSfx('phase_4/audio/sfx/Photo_shutter.ogg')
base.playSfx(self.snapshotSfx)
if coordOnScreen:
if strTextLabel is not None:
strTextLabel.destroy()
coordTextLabel.destroy()
return
def addScreenshotString(self, str):
if len(self.screenshotStr):
self.screenshotStr += '\n'
self.screenshotStr += str
def initNametagGlobals(self):
2015-06-24 11:32:30 -05:00
arrow = loader.loadModel('phase_3/models/props/arrow')
card = loader.loadModel('phase_3/models/props/panel')
speech3d = ChatBalloon(loader.loadModel('phase_3/models/props/chatbox'))
thought3d = ChatBalloon(loader.loadModel('phase_3/models/props/chatbox_thought_cutout'))
speech2d = ChatBalloon(loader.loadModel('phase_3/models/props/chatbox_noarrow'))
chatButtonGui = loader.loadModel('phase_3/models/gui/chat_button_gui')
NametagGlobals.setCamera(self.cam)
NametagGlobals.setArrowModel(arrow)
NametagGlobals.setNametagCard(card, VBase4(-0.5, 0.5, -0.5, 0.5))
if self.mouseWatcherNode:
NametagGlobals.setMouseWatcher(self.mouseWatcherNode)
NametagGlobals.setSpeechBalloon3d(speech3d)
NametagGlobals.setThoughtBalloon3d(thought3d)
NametagGlobals.setSpeechBalloon2d(speech2d)
NametagGlobals.setThoughtBalloon2d(thought3d)
NametagGlobals.setPageButton(PGButton.SReady, chatButtonGui.find('**/Horiz_Arrow_UP'))
NametagGlobals.setPageButton(PGButton.SDepressed, chatButtonGui.find('**/Horiz_Arrow_DN'))
NametagGlobals.setPageButton(PGButton.SRollover, chatButtonGui.find('**/Horiz_Arrow_Rllvr'))
NametagGlobals.setQuitButton(PGButton.SReady, chatButtonGui.find('**/CloseBtn_UP'))
NametagGlobals.setQuitButton(PGButton.SDepressed, chatButtonGui.find('**/CloseBtn_DN'))
NametagGlobals.setQuitButton(PGButton.SRollover, chatButtonGui.find('**/CloseBtn_Rllvr'))
2015-03-03 16:10:12 -06:00
rolloverSound = DirectGuiGlobals.getDefaultRolloverSound()
2015-06-24 11:32:30 -05:00
if rolloverSound:
2015-03-03 16:10:12 -06:00
NametagGlobals.setRolloverSound(rolloverSound)
clickSound = DirectGuiGlobals.getDefaultClickSound()
2015-06-24 11:32:30 -05:00
if clickSound:
2015-03-03 16:10:12 -06:00
NametagGlobals.setClickSound(clickSound)
2015-06-24 11:32:30 -05:00
NametagGlobals.setToon(self.cam)
2015-03-03 16:10:12 -06:00
self.marginManager = MarginManager()
2015-06-24 11:32:30 -05:00
self.margins = self.aspect2d.attachNewNode(self.marginManager, DirectGuiGlobals.MIDGROUND_SORT_INDEX + 1)
mm = self.marginManager
# TODO: Dynamicaly add more and reposition cells
padding = 0.0225
# Order: Top to bottom
2015-03-03 16:10:12 -06:00
self.leftCells = [
2015-06-24 11:32:30 -05:00
mm.addGridCell(0.2 + padding, -0.45, base.a2dTopLeft), # Above boarding groups
mm.addGridCell(0.2 + padding, -0.9, base.a2dTopLeft), # 1
mm.addGridCell(0.2 + padding, -1.35, base.a2dTopLeft) # Below Boarding Groups
2015-03-03 16:10:12 -06:00
]
2015-06-24 11:32:30 -05:00
# Order: Left to right
2015-03-03 16:10:12 -06:00
self.bottomCells = [
2015-06-24 11:32:30 -05:00
mm.addGridCell(-0.87, 0.2 + padding, base.a2dBottomCenter), # To the right of the laff meter
mm.addGridCell(-0.43, 0.2 + padding, base.a2dBottomCenter), # 1
mm.addGridCell(0.01, 0.2 + padding, base.a2dBottomCenter), # 2
mm.addGridCell(0.45, 0.2 + padding, base.a2dBottomCenter), # 3
mm.addGridCell(0.89, 0.2 + padding, base.a2dBottomCenter) # To the left of the shtiker book
2015-03-03 16:10:12 -06:00
]
2015-06-24 11:32:30 -05:00
# Order: Bottom to top
2015-03-03 16:10:12 -06:00
self.rightCells = [
2015-06-24 11:32:30 -05:00
mm.addGridCell(-0.2 - padding, -1.35, base.a2dTopRight), # Above the street map
mm.addGridCell(-0.2 - padding, -0.9, base.a2dTopRight), # Below the friends list
mm.addGridCell(-0.2 - padding, -0.45, base.a2dTopRight) # Behind the friends list
2015-03-03 16:10:12 -06:00
]
2015-06-24 11:32:30 -05:00
def hideFriendMargins(self):
middleCell = self.rightCells[1]
topCell = self.rightCells[2]
self.setCellsAvailable([middleCell, topCell], False)
def showFriendMargins(self):
middleCell = self.rightCells[1]
topCell = self.rightCells[2]
self.setCellsAvailable([middleCell, topCell], True)
def setCellsAvailable(self, cell_list, available):
for cell in cell_list:
self.marginManager.setCellAvailable(cell, available)
2015-03-03 16:10:12 -06:00
def startShow(self, cr):
2015-03-03 16:10:12 -06:00
self.cr = cr
base.graphicsEngine.renderFrame()
# Get the base port.
serverPort = base.config.GetInt('server-port', 7199)
# Get the number of client-agents.
clientagents = base.config.GetInt('client-agents', 1) - 1
# Get a new port.
serverPort += (random.randint(0, clientagents) * 100)
serverList = []
for name in launcher.getGameServer().split(';'):
2015-03-03 16:10:12 -06:00
url = URLSpec(name, 1)
if base.config.GetBool('server-force-ssl', False):
url.setScheme('s')
if not url.hasPort():
url.setPort(serverPort)
serverList.append(url)
if len(serverList) == 1:
failover = base.config.GetString('server-failover', '')
serverURL = serverList[0]
for arg in failover.split():
try:
port = int(arg)
url = URLSpec(serverURL)
url.setPort(port)
except:
url = URLSpec(arg, 1)
if url != serverURL:
serverList.append(url)
cr.loginFSM.request('connect', [serverList])
# Start detecting speed hacks:
self.lastSpeedHackCheck = time.time()
self.lastTrueClockTime = TrueClock.getGlobalPtr().getLongTime()
taskMgr.add(self.__speedHackCheckTick, 'speedHackCheck-tick')
def __speedHackCheckTick(self, task):
elapsed = time.time() - self.lastSpeedHackCheck
tcElapsed = TrueClock.getGlobalPtr().getLongTime() - self.lastTrueClockTime
if tcElapsed > (elapsed + 0.05):
# The TrueClock is running faster than it should. This means the
# player may have sped up the process. Disconnect them:
self.cr.stopReaderPollTask()
self.cr.lostConnection()
return task.done
self.lastSpeedHackCheck = time.time()
self.lastTrueClockTime = TrueClock.getGlobalPtr().getLongTime()
return task.cont
def removeGlitchMessage(self):
self.ignore('InputState-forward')
def exitShow(self, errorCode = None):
self.notify.info('Exiting Toontown: errorCode = %s' % errorCode)
sys.exit()
def setExitErrorCode(self, code):
self.exitErrorCode = code
def getExitErrorCode(self):
return self.exitErrorCode
def userExit(self):
try:
self.localAvatar.d_setAnimState('TeleportOut', 1)
except:
pass
if self.cr.timeManager:
self.cr.timeManager.setDisconnectReason(ToontownGlobals.DisconnectCloseWindow)
base.cr._userLoggingOut = False
try:
localAvatar
except:
pass
else:
messenger.send('clientLogout')
self.cr.dumpAllSubShardObjects()
self.cr.loginFSM.request('shutdown')
self.notify.warning('Could not request shutdown; exiting anyway.')
self.ignore(ToontownGlobals.QuitGameHotKeyOSX)
self.ignore(ToontownGlobals.QuitGameHotKeyRepeatOSX)
self.ignore(ToontownGlobals.HideGameHotKeyOSX)
self.ignore(ToontownGlobals.HideGameHotKeyRepeatOSX)
self.ignore(ToontownGlobals.MinimizeGameHotKeyOSX)
self.ignore(ToontownGlobals.MinimizeGameHotKeyRepeatOSX)
self.exitShow()
def panda3dRenderError(self):
if self.cr.timeManager:
self.cr.timeManager.setDisconnectReason(ToontownGlobals.DisconnectGraphicsError)
self.cr.sendDisconnect()
sys.exit()
def getShardPopLimits(self):
return (
config.GetInt('shard-low-pop', ToontownGlobals.LOW_POP),
config.GetInt('shard-mid-pop', ToontownGlobals.MID_POP),
config.GetInt('shard-high-pop', ToontownGlobals.HIGH_POP)
)
def playMusic(self, music, looping = 0, interrupt = 1, volume = None, time = 0.0):
OTPBase.OTPBase.playMusic(self, music, looping, interrupt, volume, time)
# OS X Specific Actions
def exitOSX(self):
self.confirm = TTDialog.TTGlobalDialog(doneEvent='confirmDone', message=TTLocalizer.OptionsPageExitConfirm, style=TTDialog.TwoChoice)
self.confirm.show()
self.accept('confirmDone', self.handleConfirm)
def handleConfirm(self):
status = self.confirm.doneStatus
self.ignore('confirmDone')
self.confirm.cleanup()
del self.confirm
if status == 'ok':
self.userExit()
def hideGame(self):
# Hacky, I know, but it works
hideCommand = """osascript -e 'tell application "System Events"
set frontProcess to first process whose frontmost is true
set visible of frontProcess to false
end tell'"""
os.system(hideCommand)
def minimizeGame(self):
wp = WindowProperties()
wp.setMinimized(True)
base.win.requestProperties(wp)