toontown-just-works/toontown/building/DistributedBoardingParty.py
2024-07-07 18:08:39 -05:00

567 lines
24 KiB
Python

from direct.directnotify import DirectNotifyGlobal
from direct.distributed import DistributedObject
from direct.gui.DirectGui import *
from direct.interval.IntervalGlobal import *
from panda3d.core import *
import BoardingGroupShow
from toontown.building import BoardingPartyBase
from otp.nametag.NametagConstants import *
from otp.margins.WhisperPopup import *
from toontown.hood import ZoneUtil
from toontown.toon import BoardingGroupInviterPanels
from toontown.toon import GroupInvitee
from toontown.toon import GroupPanel
from toontown.toonbase import TTLocalizer
from toontown.toonbase import ToontownGlobals
from toontown.toontowngui import TTDialog
class DistributedBoardingParty(DistributedObject.DistributedObject, BoardingPartyBase.BoardingPartyBase):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedBoardingParty')
InvitationFailedTimeout = 60.0
def __init__(self, cr):
DistributedObject.DistributedObject.__init__(self, cr)
BoardingPartyBase.BoardingPartyBase.__init__(self)
self.groupInviteePanel = None
self.groupPanel = None
self.inviterPanels = BoardingGroupInviterPanels.BoardingGroupInviterPanels()
self.lastInvitationFailedMessage = {}
self.goToPreShowTrack = None
self.goToShowTrack = None
return
def generate(self):
self.load()
DistributedObject.DistributedObject.generate(self)
localAvatar.boardingParty = self
def announceGenerate(self):
canonicalZoneId = ZoneUtil.getCanonicalZoneId(self.zoneId)
self.notify.debug('canonicalZoneId = %s' % canonicalZoneId)
localAvatar.chatMgr.chatInputSpeedChat.addBoardingGroupMenu(canonicalZoneId)
def delete(self):
DistributedObject.DistributedObject.delete(self)
def disable(self):
self.finishGoToPreShowTrack()
self.finishGoToShowTrack()
self.forceCleanupInviteePanel()
self.forceCleanupInviterPanels()
self.inviterPanels = None
if self.groupPanel:
self.groupPanel.cleanup()
self.groupPanel = None
DistributedObject.DistributedObject.disable(self)
BoardingPartyBase.BoardingPartyBase.cleanup(self)
localAvatar.boardingParty = None
localAvatar.chatMgr.chatInputSpeedChat.removeBoardingGroupMenu()
self.lastInvitationFailedMessage = {}
return
def getElevatorIdList(self):
return self.elevatorIdList
def setElevatorIdList(self, elevatorIdList):
self.notify.debug('setElevatorIdList')
self.elevatorIdList = elevatorIdList
def load(self):
pass
# this is a pretty brute force group check that will see if a toon
# (in the same zone) is already in a group. This might introduce
# lag in a very crowded district with hundreds of active groups
# (if we should be so lucky)
def isInGroup(self, avId):
if avId in self.groupListDict:
return True
for leader in self.groupListDict:
group = self.groupListDict.get(leader)
for member in group[0]:
if member == avId:
return True
return False
def countInGroup(self, avId):
if avId in self.groupListDict:
group = self.groupListDict.get(avId)
return len(group[0])
for leader in self.groupListDict:
group = self.groupListDict.get(leader)
for member in group[0]:
if member == avId:
return len(group[0])
return 0
def postGroupInfo(self, leaderId, memberList, inviteeList, kickedList):
self.notify.debug('postgroupInfo')
isMyGroup = 0
removedMemberIdList = []
if leaderId in self.groupListDict:
oldGroupEntry = self.groupListDict[leaderId]
else:
oldGroupEntry = [[], [], []]
oldMemberList = oldGroupEntry[0]
newGroupEntry = [memberList, inviteeList, kickedList]
self.groupListDict[leaderId] = newGroupEntry
if not len(oldMemberList) == len(memberList):
for oldMember in oldMemberList:
if oldMember not in memberList:
if oldMember in self.avIdDict:
if self.avIdDict[oldMember] == leaderId:
self.avIdDict.pop(oldMember)
removedMemberIdList.append(oldMember)
self.avIdDict[leaderId] = leaderId
if leaderId == localAvatar.doId:
isMyGroup = 1
for memberId in memberList:
self.avIdDict[memberId] = leaderId
if memberId == localAvatar.doId:
isMyGroup = 1
if newGroupEntry[0] == [0] or not newGroupEntry[0]:
dgroup = self.groupListDict.pop(leaderId)
for memberId in dgroup[0]:
if memberId in self.avIdDict:
self.avIdDict.pop(memberId)
if isMyGroup:
self.notify.debug('new info posted on my group')
# update the leaderId in case it has changed (group merge)
if self.groupPanel and self.groupPanel.leaderId == localAvatar.doId and leaderId != localAvatar.doId:
self.groupPanel.cleanup()
self.groupPanel = None
if not self.groupPanel:
self.groupPanel = GroupPanel.GroupPanel(self)
messenger.send('updateGroupStatus')
for removedMemberId in removedMemberIdList:
removedMember = base.cr.doId2do.get(removedMemberId)
if not removedMember:
removedMember = base.cr.identifyFriend(removedMemberId)
if removedMember:
removedMemberName = removedMember.name
messageText = TTLocalizer.BoardingMessageLeftGroup % removedMemberName
localAvatar.setSystemMessage(removedMemberId, messageText, WTToontownBoardingGroup)
elif localAvatar.doId in oldMemberList and localAvatar.doId not in memberList:
messenger.send('updateGroupStatus')
if self.groupPanel:
self.groupPanel.cleanup()
self.groupPanel = None
else:
self.notify.debug('new info posted on some other group')
return
def postInvite(self, leaderId, inviterId, merger):
self.notify.debug('post Invite')
if not base.localAvatar.isIgnored(inviterId):
inviter = base.cr.doId2do.get(inviterId)
if inviter:
if self.inviterPanels.isInvitingPanelUp() or self.inviterPanels.isInvitationRejectedPanelUp():
self.inviterPanels.forceCleanup()
self.groupInviteePanel = GroupInvitee.GroupInvitee()
self.groupInviteePanel.make(self, inviter, leaderId, merger)
if base.config.GetBool('reject-boarding-group-invites', 0):
self.groupInviteePanel.forceCleanup()
self.groupInviteePanel = None
return
def postKick(self, leaderId):
self.notify.debug('%s was kicked out of the Boarding Group by %s' % (localAvatar.doId, leaderId))
localAvatar.setSystemMessage(leaderId, TTLocalizer.BoardingMessageKickedOut, WTToontownBoardingGroup)
def postSizeReject(self, leaderId, inviterId, inviteeId):
self.notify.debug('%s was not invited because the group is full' % inviteeId)
def postKickReject(self, leaderId, inviterId, inviteeId):
self.notify.debug('%s was not invited because %s has kicked them from the group' % (inviteeId, leaderId))
def postInviteDelcined(self, inviteeId):
self.notify.debug("%s delinced %s's Boarding Group invitation." % (inviteeId, localAvatar.doId))
invitee = base.cr.doId2do.get(inviteeId)
if invitee:
self.inviterPanels.createInvitationRejectedPanel(self, inviteeId)
def postInviteAccepted(self, inviteeId):
self.notify.debug("%s accepted %s's Boarding Group invitation." % (inviteeId, localAvatar.doId))
if self.inviterPanels.isInvitingPanelIdCorrect(inviteeId):
self.inviterPanels.destroyInvitingPanel()
def postInviteCanceled(self):
self.notify.debug('The invitation to the Boarding Group was cancelled')
if self.isInviteePanelUp():
self.groupInviteePanel.cleanup()
self.groupInviteePanel = None
return
def postInviteNotQualify(self, avId, reason):
messenger.send('updateGroupStatus')
rejectText = ''
if avId == localAvatar.doId:
if reason == BoardingPartyBase.BOARDCODE_PROMOTION:
rejectText = TTLocalizer.BoardingInvitePromotionInviter
else:
avatar = base.cr.doId2do.get(avId)
if avatar:
avatarNameText = avatar.name
else:
avatarNameText = ''
if reason == BoardingPartyBase.BOARDCODE_PROMOTION:
rejectText = TTLocalizer.BoardingInvitePromotionInvitee % avatarNameText
if reason == BoardingPartyBase.BOARDCODE_BATTLE:
rejectText = TTLocalizer.TeleportPanelNotAvailable % avatarNameText
if reason == BoardingPartyBase.BOARDCODE_DIFF_GROUP:
rejectText = TTLocalizer.BoardingInviteeInDiffGroup % avatarNameText
if reason == BoardingPartyBase.BOARDCODE_PENDING_INVITE:
rejectText = TTLocalizer.BoardingInviteePendingIvite % avatarNameText
if reason == BoardingPartyBase.BOARDCODE_IN_ELEVATOR:
rejectText = TTLocalizer.BoardingInviteeInElevator % avatarNameText
if reason == BoardingPartyBase.BOARDCODE_GROUPS_TOO_LARGE: # JBS
rejectText = TTLocalizer.BoardingGroupsTooLarge % avatarNameText
if self.inviterPanels.isInvitingPanelIdCorrect(avId) or avId == localAvatar.doId:
self.inviterPanels.destroyInvitingPanel()
self.showMe(rejectText)
def postAlreadyInGroup(self):
self.showMe(TTLocalizer.BoardingAlreadyInGroup)
def postGroupAlreadyFull(self):
self.showMe(TTLocalizer.BoardingGroupAlreadyFull)
def postSomethingMissing(self):
self.showMe(TTLocalizer.BoardcodeMissing)
def postRejectBoard(self, elevatorId, reason, avatarsFailingRequirements, avatarsInBattle):
self.showRejectMessage(elevatorId, reason, avatarsFailingRequirements, avatarsInBattle)
self.enableGoButton()
def postRejectGoto(self, elevatorId, reason, avatarsFailingRequirements, avatarsInBattle):
self.showRejectMessage(elevatorId, reason, avatarsFailingRequirements, avatarsInBattle)
def postMessageInvited(self, inviteeId, inviterId):
inviterName = ''
inviteeName = ''
inviter = base.cr.doId2do.get(inviterId)
if inviter:
inviterName = inviter.name
invitee = base.cr.doId2do.get(inviteeId)
if invitee:
inviteeName = invitee.name
messageText = TTLocalizer.BoardingMessageInvited % (inviterName, inviteeName)
localAvatar.setSystemMessage(inviteeId, messageText, WTToontownBoardingGroup)
def postMessageInvitationFailed(self, inviterId):
inviterName = ''
inviter = base.cr.doId2do.get(inviterId)
if inviter:
inviterName = inviter.name
if self.invitationFailedMessageOk(inviterId):
messageText = TTLocalizer.BoardingMessageInvitationFailed % inviterName
localAvatar.setSystemMessage(inviterId, messageText, WTToontownBoardingGroup)
def postMessageAcceptanceFailed(self, inviteeId, reason):
inviteeName = ''
messageText = ''
invitee = base.cr.doId2do.get(inviteeId)
if invitee:
inviteeName = invitee.name
if reason == BoardingPartyBase.INVITE_ACCEPT_FAIL_GROUP_FULL:
messageText = TTLocalizer.BoardingMessageGroupFull % inviteeName
localAvatar.setSystemMessage(inviteeId, messageText, WTToontownBoardingGroup)
if self.inviterPanels.isInvitingPanelIdCorrect(inviteeId):
self.inviterPanels.destroyInvitingPanel()
def invitationFailedMessageOk(self, inviterId):
now = globalClock.getFrameTime()
lastTime = self.lastInvitationFailedMessage.get(inviterId, None)
if lastTime:
elapsedTime = now - lastTime
if elapsedTime < self.InvitationFailedTimeout:
return False
self.lastInvitationFailedMessage[inviterId] = now
return True
def showRejectMessage(self, elevatorId, reason, avatarsFailingRequirements, avatarsInBattle):
leaderId = localAvatar.doId
rejectText = ''
def getAvatarText(avIdList):
avatarText = ''
nameList = []
for avId in avIdList:
avatar = base.cr.doId2do.get(avId)
if avatar:
nameList.append(avatar.name)
if len(nameList) > 0:
lastName = nameList.pop()
avatarText = lastName
if len(nameList) > 0:
secondLastName = nameList.pop()
for name in nameList:
avatarText = name + ', '
avatarText += secondLastName + ' ' + TTLocalizer.And + ' ' + lastName
return avatarText
if reason == BoardingPartyBase.BOARDCODE_PROMOTION:
self.notify.debug("%s 's group cannot board because it does not have enough promotion merits." % leaderId)
if leaderId in avatarsFailingRequirements:
rejectText = TTLocalizer.BoardcodePromotionLeader
else:
avatarNameText = getAvatarText(avatarsFailingRequirements)
if len(avatarsFailingRequirements) == 1:
rejectText = TTLocalizer.BoardcodePromotionNonLeaderSingular % avatarNameText
else:
rejectText = TTLocalizer.BoardcodePromotionNonLeaderPlural % avatarNameText
elif reason == BoardingPartyBase.BOARDCODE_BATTLE:
self.notify.debug("%s 's group cannot board because it is in a battle" % leaderId)
if leaderId in avatarsInBattle:
rejectText = TTLocalizer.BoardcodeBattleLeader
else:
avatarNameText = getAvatarText(avatarsInBattle)
if len(avatarsInBattle) == 1:
rejectText = TTLocalizer.BoardcodeBattleNonLeaderSingular % avatarNameText
else:
rejectText = TTLocalizer.BoardcodeBattleNonLeaderPlural % avatarNameText
elif reason == BoardingPartyBase.BOARDCODE_SPACE:
self.notify.debug("%s 's group cannot board there was not enough room" % leaderId)
rejectText = TTLocalizer.BoardcodeSpace
elif reason == BoardingPartyBase.BOARDCODE_MISSING:
self.notify.debug("%s 's group cannot board because something was missing" % leaderId)
rejectText = TTLocalizer.BoardcodeMissing
base.localAvatar.elevatorNotifier.showMe(rejectText)
def postGroupDissolve(self, quitterId, leaderId, memberList, kick):
self.notify.debug('%s group has dissolved' % leaderId)
isMyGroup = 0
if localAvatar.doId == quitterId or localAvatar.doId == leaderId:
isMyGroup = 1
if leaderId in self.groupListDict:
if leaderId == localAvatar.doId:
isMyGroup = 1
if leaderId in self.avIdDict:
self.avIdDict.pop(leaderId)
dgroup = self.groupListDict.pop(leaderId)
for memberId in memberList:
if memberId == localAvatar.doId:
isMyGroup = 1
if memberId in self.avIdDict:
self.avIdDict.pop(memberId)
if isMyGroup:
self.notify.debug('new info posted on my group')
messenger.send('updateGroupStatus')
groupFormed = False
if self.groupPanel:
groupFormed = True
self.groupPanel.cleanup()
self.groupPanel = None
if groupFormed:
if leaderId == quitterId:
if not localAvatar.doId == leaderId:
localAvatar.setSystemMessage(leaderId, TTLocalizer.BoardingMessageGroupDissolved, WTToontownBoardingGroup)
elif not kick:
if not localAvatar.doId == quitterId:
quitter = base.cr.doId2do.get(quitterId)
if quitter:
quitterName = quitter.name
messageText = TTLocalizer.BoardingMessageLeftGroup % quitterName
localAvatar.setSystemMessage(quitterId, messageText, WTToontownBoardingGroup)
else:
messageText = TTLocalizer.BoardingMessageGroupDisbandedGeneric
localAvatar.setSystemMessage(quitterId, messageText, WTToontownBoardingGroup)
return
def requestInvite(self, inviteeId):
self.notify.debug('requestInvite %s' % inviteeId)
elevator = base.cr.doId2do.get(self.getElevatorIdList()[0])
if elevator:
if inviteeId in self.getGroupKickList(localAvatar.doId):
if not self.isGroupLeader(localAvatar.doId):
avatar = base.cr.doId2do.get(inviteeId)
if avatar:
avatarNameText = avatar.name
else:
avatarNameText = ''
rejectText = TTLocalizer.BoardingInviteeInKickOutList % avatarNameText
self.showMe(rejectText)
return
if self.inviterPanels.isInvitingPanelUp():
self.showMe(TTLocalizer.BoardingPendingInvite, pos=(0, 0, 0))
elif len(self.getGroupMemberList(localAvatar.doId)) >= self.maxSize:
self.showMe(TTLocalizer.BoardingInviteGroupFull)
else:
invitee = base.cr.doId2do.get(inviteeId)
if invitee:
self.inviterPanels.createInvitingPanel(self, inviteeId)
self.sendUpdate('requestInvite', [inviteeId])
def requestCancelInvite(self, inviteeId):
self.sendUpdate('requestCancelInvite', [inviteeId])
def requestAcceptInvite(self, leaderId, inviterId):
self.notify.debug('requestAcceptInvite %s %s' % (leaderId, inviterId))
self.sendUpdate('requestAcceptInvite', [leaderId, inviterId])
def requestRejectInvite(self, leaderId, inviterId):
self.sendUpdate('requestRejectInvite', [leaderId, inviterId])
def requestKick(self, kickId):
self.sendUpdate('requestKick', [kickId])
def requestLeave(self):
if self.goToShowTrack and self.goToShowTrack.isPlaying():
return
place = base.cr.playGame.getPlace()
if place:
if not place.getState() == 'elevator':
if localAvatar.doId in self.avIdDict:
leaderId = self.avIdDict[localAvatar.doId]
self.sendUpdate('requestLeave', [leaderId])
def handleEnterElevator(self, elevator):
if self.getGroupLeader(localAvatar.doId) == localAvatar.doId:
if base.localAvatar.hp > 0:
self.cr.playGame.getPlace().detectedElevatorCollision(elevator)
self.sendUpdate('requestBoard', [elevator.doId])
elevatorId = elevator.doId
if elevatorId in self.elevatorIdList:
offset = self.elevatorIdList.index(elevatorId)
if self.groupPanel:
self.groupPanel.scrollToDestination(offset)
self.informDestChange(offset)
self.disableGoButton()
def informDestChange(self, offset):
self.sendUpdate('informDestinationInfo', [offset])
def postDestinationInfo(self, offset):
if self.groupPanel:
self.groupPanel.changeDestination(offset)
def enableGoButton(self):
if self.groupPanel:
self.groupPanel.enableGoButton()
self.groupPanel.enableDestinationScrolledList()
def disableGoButton(self):
if self.groupPanel:
self.groupPanel.disableGoButton()
self.groupPanel.disableDestinationScrolledList()
def isInviteePanelUp(self):
if self.groupInviteePanel:
if not self.groupInviteePanel.isEmpty():
return True
self.groupInviteePanel = None
return False
def requestGoToFirstTime(self, elevatorId):
self.waitingForFirstResponse = True
self.firstRequestAccepted = False
self.sendUpdate('requestGoToFirstTime', [elevatorId])
self.startGoToPreShow(elevatorId)
def acceptGoToFirstTime(self, elevatorId):
self.waitingForFirstResponse = False
self.firstRequestAccepted = True
def requestGoToSecondTime(self, elevatorId):
if not self.waitingForFirstResponse:
if self.firstRequestAccepted:
self.firstRequestAccepted = False
self.disableGoButton()
self.sendUpdate('requestGoToSecondTime', [elevatorId])
else:
self.postRejectGoto(elevatorId, BoardingPartyBase.BOARDCODE_MISSING, [], [])
self.cancelGoToElvatorDest()
def acceptGoToSecondTime(self, elevatorId):
self.startGoToShow(elevatorId)
def rejectGoToRequest(self, elevatorId, reason, avatarsFailingRequirements, avatarsInBattle):
self.firstRequestAccepted = False
self.waitingForFirstResponse = False
self.cancelGoToElvatorDest()
self.postRejectGoto(elevatorId, reason, avatarsFailingRequirements, avatarsInBattle)
def startGoToPreShow(self, elevatorId):
self.notify.debug('Starting Go Pre Show.')
place = base.cr.playGame.getPlace()
if place:
place.setState('stopped')
goButtonPreShow = BoardingGroupShow.BoardingGroupShow(localAvatar)
goButtonPreShowTrack = goButtonPreShow.getGoButtonPreShow()
if self.groupPanel:
self.groupPanel.changeGoToCancel()
self.groupPanel.disableQuitButton()
self.groupPanel.disableDestinationScrolledList()
self.finishGoToPreShowTrack()
self.goToPreShowTrack = Sequence()
self.goToPreShowTrack.append(goButtonPreShowTrack)
self.goToPreShowTrack.append(Func(self.requestGoToSecondTime, elevatorId))
self.goToPreShowTrack.start()
def finishGoToPreShowTrack(self):
if self.goToPreShowTrack:
self.goToPreShowTrack.finish()
self.goToPreShowTrack = None
return
def startGoToShow(self, elevatorId):
self.notify.debug('Starting Go Show.')
localAvatar.boardingParty.forceCleanupInviterPanels()
elevatorName = self.__getDestName(elevatorId)
if self.groupPanel:
self.groupPanel.disableQuitButton()
goButtonShow = BoardingGroupShow.BoardingGroupShow(localAvatar)
place = base.cr.playGame.getPlace()
if place:
place.setState('stopped')
self.goToShowTrack = goButtonShow.getGoButtonShow(elevatorName)
self.goToShowTrack.start()
def finishGoToShowTrack(self):
if self.goToShowTrack:
self.goToShowTrack.finish()
self.goToShowTrack = None
return
def cancelGoToElvatorDest(self):
self.notify.debug('%s cancelled the GoTo Button.' % localAvatar.doId)
self.firstRequestAccepted = False
self.waitingForFirstResponse = False
self.finishGoToPreShowTrack()
place = base.cr.playGame.getPlace()
if place:
place.setState('walk')
if self.groupPanel:
self.groupPanel.changeCancelToGo()
self.groupPanel.enableGoButton()
self.groupPanel.enableQuitButton()
self.groupPanel.enableDestinationScrolledList()
def __getDestName(self, elevatorId):
elevator = base.cr.doId2do.get(elevatorId)
destName = ''
if elevator:
destName = elevator.getDestName()
return destName
def showMe(self, message, pos = None):
base.localAvatar.elevatorNotifier.showMeWithoutStopping(message, pos)
def forceCleanupInviteePanel(self):
if self.isInviteePanelUp():
self.groupInviteePanel.forceCleanup()
self.groupInviteePanel = None
return
def forceCleanupInviterPanels(self):
if self.inviterPanels:
self.inviterPanels.forceCleanup()