oldschool-toontown/toontown/parties/DistributedParty.py

581 lines
18 KiB
Python
Raw Normal View History

2019-11-02 17:27:54 -05:00
import random
import time
import datetime
2022-01-18 15:12:05 -06:00
from panda3d.core import Vec4, TextNode, CardMaker, NodePath
2019-11-02 17:27:54 -05:00
from direct.distributed import DistributedObject
from direct.gui.DirectGui import DirectLabel
from direct.gui import OnscreenText
2022-01-18 15:12:05 -06:00
from direct.interval.IntervalGlobal import *
2019-11-02 17:27:54 -05:00
from toontown.toonbase import ToontownGlobals
from toontown.parties.PartyInfo import PartyInfo
from toontown.toonbase import TTLocalizer
from toontown.toon import Toon
from toontown.parties import PartyGlobals
from toontown.parties.Decoration import Decoration
from . import PartyUtils
2019-11-02 17:27:54 -05:00
class DistributedParty(DistributedObject.DistributedObject):
notify = directNotify.newCategory('DistributedParty')
generatedEvent = 'distributedPartyGenerated'
def __init__(self, cr):
DistributedObject.DistributedObject.__init__(self, cr)
self.partyDoneEvent = 'partyDone'
self.load()
self.avIdsAtParty = []
base.distributedParty = self
self.titleText = ''
self.isPartyEnding = False
def setPartyState(self, partyState):
self.isPartyEnding = partyState
messenger.send('partyStateChanged', [partyState])
def getPartyState(self):
return self.isPartyEnding
def setPartyClockInfo(self, x, y, h):
x = PartyUtils.convertDistanceFromPartyGrid(x, 0)
y = PartyUtils.convertDistanceFromPartyGrid(y, 1)
h = PartyUtils.convertDegreesFromPartyGrid(h)
self.partyClockInfo = (x, y, h)
self.loadPartyCountdownTimer()
def setInviteeIds(self, inviteeIds):
self.inviteeIds = inviteeIds
def setPartyInfoTuple(self, partyInfoTuple):
self.partyInfo = PartyInfo(*partyInfoTuple)
self.loadDecorations()
allActIds = [ x.activityId for x in self.partyInfo.activityList ]
base.partyHasJukebox = PartyGlobals.ActivityIds.PartyJukebox in allActIds or PartyGlobals.ActivityIds.PartyJukebox40 in allActIds
self.grid = [[False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False],
[False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False],
[False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False],
[False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False],
[False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
False],
[False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True],
[False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True],
[False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False,
False],
[False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False],
[False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False],
[False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False]]
def fillGrid(x, y, size):
2022-01-18 15:12:05 -06:00
for i in range(-size[1] // 2 + 1, size[1] // 2 + 1):
for j in range(-size[0] // 2 + 1, size[0] // 2 + 1):
2019-11-02 17:27:54 -05:00
self.grid[i + y][j + x] = False
for activityBase in self.partyInfo.activityList:
fillGrid(activityBase.x, activityBase.y, PartyGlobals.ActivityInformationDict[activityBase.activityId]['gridsize'])
for decorBase in self.partyInfo.decors:
fillGrid(decorBase.x, decorBase.y, PartyGlobals.DecorationInformationDict[decorBase.decorId]['gridsize'])
self.loadGrass()
def setPartyStartedTime(self, startedTime):
stime = time.strptime(startedTime, '%Y-%m-%d %H:%M:%S')
self.partyStartedTime = datetime.datetime(year=stime.tm_year, month=stime.tm_mon, day=stime.tm_mday, hour=stime.tm_hour, minute=stime.tm_min, second=stime.tm_sec, tzinfo=base.cr.toontownTimeManager.getCurServerDateTime().tzinfo)
def disable(self):
self.notify.debug('disable')
DistributedObject.DistributedObject.disable(self)
base.localAvatar.chatMgr.chatInputSpeedChat.removeInsidePartiesMenu()
def delete(self):
self.notify.debug('delete')
self.unload()
if hasattr(base, 'distributedParty'):
del base.distributedParty
DistributedObject.DistributedObject.delete(self)
def load(self):
Toon.loadMinigameAnims()
self.defaultSignModel = loader.loadModel('phase_13/models/parties/eventSign')
self.activityIconsModel = loader.loadModel('phase_4/models/parties/eventSignIcons')
model = loader.loadModel('phase_4/models/parties/partyStickerbook')
self.partyHat = model.find('**/Stickerbook_PartyIcon')
self.partyHat.setPos(0.0, 0.1, 2.5)
self.partyHat.setHpr(0.0, 0.0, -50.0)
self.partyHat.setScale(4.0)
self.partyHat.setBillboardAxis()
self.partyHat.reparentTo(hidden)
model.removeNode()
self.defaultLeverModel = loader.loadModel('phase_13/models/parties/partyLeverBase')
self.defaultStickModel = loader.loadModel('phase_13/models/parties/partyLeverStick')
def loadGrass(self):
self.grassRoot = NodePath('GrassRoot')
self.grassRoot.reparentTo(base.cr.playGame.hood.loader.geom)
grass = loader.loadModel('phase_13/models/parties/grass')
clearPositions = self.getClearSquarePositions()
numTufts = min(len(clearPositions) * 3, PartyGlobals.TuftsOfGrass)
for i in range(numTufts):
g = grass.copyTo(self.grassRoot)
pos = random.choice(clearPositions)
g.setPos(pos[0] + random.randint(-8, 8), pos[1] + random.randint(-8, 8), 0.0)
def loadDecorations(self):
self.decorationsList = []
for decorBase in self.partyInfo.decors:
self.decorationsList.append(Decoration(PartyGlobals.DecorationIds.getString(decorBase.decorId), PartyUtils.convertDistanceFromPartyGrid(decorBase.x, 0), PartyUtils.convertDistanceFromPartyGrid(decorBase.y, 1), PartyUtils.convertDegreesFromPartyGrid(decorBase.h)))
def unload(self):
if hasattr(self, 'decorationsList') and self.decorationsList:
for decor in self.decorationsList:
decor.unload()
del self.decorationsList
self.stopPartyClock()
self.grassRoot.removeNode()
del self.grassRoot
if hasattr(self, 'testGrid'):
self.testGrid.removeNode()
del self.testGrid
self.ignoreAll()
Toon.unloadMinigameAnims()
self.partyHat.removeNode()
del self.partyHat
if hasattr(base, 'partyHasJukebox'):
del base.partyHasJukebox
def announceGenerate(self):
DistributedObject.DistributedObject.announceGenerate(self)
self.sendUpdate('avIdEnteredParty', [base.localAvatar.doId])
globalClock.syncFrameTime()
self.startPartyClock()
base.localAvatar.chatMgr.chatInputSpeedChat.addInsidePartiesMenu()
self.spawnTitleText()
messenger.send(self.generatedEvent)
if config.GetBool('show-debug-party-grid', 0):
self.testGrid = NodePath('test_grid')
self.testGrid.reparentTo(base.cr.playGame.hood.loader.geom)
for i in range(len(self.grid)):
for j in range(len(self.grid[i])):
cm = CardMaker('gridsquare')
np = NodePath(cm.generate())
np.setScale(12)
np.setP(-90.0)
np.setPos(PartyUtils.convertDistanceFromPartyGrid(j, 0) - 6.0, PartyUtils.convertDistanceFromPartyGrid(i, 1) - 6.0, 0.1)
np.reparentTo(self.testGrid)
if self.grid[i][j]:
np.setColorScale(0.0, 1.0, 0.0, 1.0)
else:
np.setColorScale(1.0, 0.0, 0.0, 1.0)
def getClearSquarePos(self):
clearPositions = self.getClearSquarePositions()
if len(clearPositions) == 0:
raise Exception('Party %s has no empty grid squares.' % self.doId)
2019-11-02 17:27:54 -05:00
return random.choice(clearPositions)
def getClearSquarePositions(self):
clearPositions = []
for y in range(len(self.grid)):
for x in range(len(self.grid[0])):
if self.grid[y][x]:
pos = (PartyUtils.convertDistanceFromPartyGrid(x, 0), PartyUtils.convertDistanceFromPartyGrid(y, 1), 0.1)
clearPositions.append(pos)
return clearPositions
def startPartyClock(self):
self.partyClockModel.reparentTo(base.cr.playGame.hood.loader.geom)
curServerTime = base.cr.toontownTimeManager.getCurServerDateTime()
timePartyWillEnd = self.partyStartedTime + datetime.timedelta(hours=PartyGlobals.DefaultPartyDuration)
timeLeftInParty = timePartyWillEnd - curServerTime
if curServerTime < timePartyWillEnd:
self.secondsLeftInParty = timeLeftInParty.seconds
else:
self.secondsLeftInParty = 0
taskMgr.doMethodLater(0.5, self.partyClockTask, 'UpdatePartyClock')
self.partyClockSignFront = self.partyClockModel.find('**/signFrontText_locator')
self.partyClockSignBack = self.partyClockModel.find('**/signBackText_locator')
self.attachHostNameToSign(self.partyClockSignFront)
self.attachHostNameToSign(self.partyClockSignBack)
def attachHostNameToSign(self, locator):
if self.hostName == '':
return
nameText = TextNode('nameText')
nameText.setCardAsMargin(0.1, 0.1, 0.1, 0.1)
nameText.setCardDecal(True)
nameText.setCardColor(1.0, 1.0, 1.0, 0.0)
r = 232.0 / 255.0
g = 169.0 / 255.0
b = 23.0 / 255.0
nameText.setTextColor(r, g, b, 1)
nameText.setAlign(nameText.ACenter)
nameText.setFont(ToontownGlobals.getBuildingNametagFont())
nameText.setShadowColor(0, 0, 0, 1)
nameText.setBin('fixed')
if TTLocalizer.BuildingNametagShadow:
nameText.setShadow(*TTLocalizer.BuildingNametagShadow)
nameWordWrap = 11.0
nameText.setWordwrap(nameWordWrap)
scaleMult = 0.48
houseName = self.hostName
nameText.setText(houseName)
textWidth = nameText.getWidth()
xScale = 1.0 * scaleMult
if textWidth > nameWordWrap:
xScale = nameWordWrap / textWidth * scaleMult
sign_origin = locator
namePlate = sign_origin.attachNewNode(nameText)
namePlate.setDepthWrite(0)
namePlate.setPos(0, 0, 0)
namePlate.setScale(xScale)
def stopPartyClock(self):
self.partyClockModel.removeNode()
taskMgr.remove('UpdatePartyClock')
def partyClockTask(self, task):
self.secondsLeftInParty -= 0.5
if self.secondsLeftInParty < 0:
self.frontTimer['minute']['text'] = '--'
self.backTimer['minute']['text'] = '--'
self.frontTimer['second']['text'] = '--'
self.backTimer['second']['text'] = '--'
return
if self.frontTimer['colon'].isStashed():
self.frontTimer['colon'].unstash()
self.backTimer['colon'].unstash()
else:
self.frontTimer['colon'].stash()
self.backTimer['colon'].stash()
minutesLeft = int(int(self.secondsLeftInParty / 60) % 60)
if minutesLeft < 10:
minutesLeft = '0%d' % minutesLeft
else:
minutesLeft = '%d' % minutesLeft
secondsLeft = int(self.secondsLeftInParty % 60)
if secondsLeft < 10:
secondsLeft = '0%d' % secondsLeft
else:
secondsLeft = '%d' % secondsLeft
self.frontTimer['minute']['text'] = minutesLeft
self.backTimer['minute']['text'] = minutesLeft
self.frontTimer['second']['text'] = secondsLeft
self.backTimer['second']['text'] = secondsLeft
taskMgr.doMethodLater(0.5, self.partyClockTask, 'UpdatePartyClock')
if self.secondsLeftInParty != int(self.secondsLeftInParty):
self.partyClockModel.find('**/middleRotateFront_grp').setR(-6.0 * (self.secondsLeftInParty % 60))
self.partyClockModel.find('**/middleRotateBack_grp').setR(6.0 * (self.secondsLeftInParty % 60))
def getAvIdsAtParty(self):
return self.avIdsAtParty
def setAvIdsAtParty(self, avIdsAtParty):
self.avIdsAtParty = avIdsAtParty
def loadPartyCountdownTimer(self):
self.partyClockModel = loader.loadModel('phase_13/models/parties/partyClock')
self.partyClockModel.setPos(self.partyClockInfo[0], self.partyClockInfo[1], 0.0)
self.partyClockModel.setH(self.partyClockInfo[2])
self.partyClockModel.reparentTo(base.cr.playGame.hood.loader.geom)
self.partyClockModel.find('**/frontText_locator').setY(-1.1)
self.partyClockModel.find('**/backText_locator').setY(0.633)
self.frontTimer = self.getTimer(self.partyClockModel.find('**/frontText_locator'))
base.frontTimerLoc = self.partyClockModel.find('**/frontText_locator')
base.backTimerLoc = self.partyClockModel.find('**/backText_locator')
self.backTimer = self.getTimer(self.partyClockModel.find('**/backText_locator'))
self.partyClockModel.stash()
def getTimer(self, parent):
timeFont = ToontownGlobals.getMinnieFont()
timer = {}
timer['minute'] = DirectLabel(parent=parent, pos=TTLocalizer.DPtimerMinutePos, relief=None, text='59', text_align=TextNode.ACenter, text_font=timeFont, text_fg=(0.7, 0.3, 0.3, 1.0), scale=TTLocalizer.DPtimerMinute)
timer['colon'] = DirectLabel(parent=parent, pos=TTLocalizer.DPtimerColonPos, relief=None, text=':', text_align=TextNode.ACenter, text_font=timeFont, text_fg=(0.7, 0.3, 0.3, 1.0), scale=TTLocalizer.DPtimerColon)
timer['second'] = DirectLabel(parent=parent, relief=None, pos=TTLocalizer.DPtimerSecondPos, text='14', text_align=TextNode.ACenter, text_font=timeFont, text_fg=(0.7, 0.3, 0.3, 1.0), scale=TTLocalizer.DPtimerSecond)
timer['textLabel'] = DirectLabel(parent=parent, relief=None, pos=(0.0, 0.0, 1.15), text=TTLocalizer.PartyCountdownClockText, text_font=timeFont, text_fg=(0.7, 0.3, 0.3, 1.0), scale=TTLocalizer.DPtimerTextLabel)
return timer
def setHostName(self, hostName):
self.hostName = hostName
if hasattr(self, 'partyClockSignFront'):
self.attachHostNameToSign(self.partyClockSignFront)
if hasattr(self, 'partyClockSignBack'):
self.attachHostNameToSign(self.partyClockSignBack)
def spawnTitleText(self):
if not self.hostName:
return
partyText = TTLocalizer.PartyTitleText % TTLocalizer.GetPossesive(self.hostName)
self.doSpawnTitleText(partyText)
def doSpawnTitleText(self, text):
self.titleColor = (1.0, 0.5, 0.4, 1.0)
self.titleText = OnscreenText.OnscreenText(text, fg=self.titleColor, font=ToontownGlobals.getSignFont(), pos=(0, -0.5), scale=0.16, drawOrder=0, mayChange=1, wordwrap=16)
self.titleText.setText(text)
self.titleText.show()
self.titleText.setColor(Vec4(*self.titleColor))
self.titleText.clearColorScale()
self.titleText.setFg(self.titleColor)
2022-01-18 15:12:05 -06:00
seq = Sequence(Wait(0.1), Wait(6.0), self.titleText.colorScaleInterval(0.5, Vec4(1.0, 1.0, 1.0, 0.0)), Func(self.hideTitleText))
seq.start()
2019-11-02 17:27:54 -05:00
def hideTitleText(self):
if self.titleText:
self.titleText.hide()