class Result(): def __init__(self): self.txtresult = DirectLabel( scale = 0.25, frameColor = (0, 0, 0, 0), text = "", #text_align = TextNode.ACenter, text_fg = (0,0,0,1)) self.txtresult.setTransparency(1) def setTeam(self, team): self.txtresult["text"] = "Team %s win" % team if team == "Yellow": self.txtresult["text_fg"] = (1,1,0,1) else: self.txtresult["text_fg"] = (0,0,1,1) def show(self): self.txtresult.show() def hide(self): self.txtresult.hide()
class DoubleFrameQuestPoster(QuestPoster): notify = directNotify.newCategory('DoubleFrameQuestPoster') def __init__(self, quest, parent=aspect2d, **kw): QuestPoster.__init__(self, quest, parent, **kw) # This text is in between the two frames and it usually says # either "from:" or "to:" self.fromToMiddleText = DirectLabel( parent=self, relief=None, text=QuestGlobals.FROM, text_font=CIGlobals.getToonFont(), text_scale=QuestGlobals.QPauxText, text_fg=QuestGlobals.TEXT_COLOR, text_align=TextNode.ACenter, textMayChange=1, pos=QuestGlobals.DEFAULT_MIDDLE_POS) self.fromToMiddleText.hide() ########################################################################## # THE FOLLOWING ELEMENTS BELOW ARE GROUPED TOGETHER # ########################################################################## # We need this again for certain geometry. circleGui = loader.loadModel( 'phase_4/models/gui/CircleIconBackgroundGui.bam') # The background frame where the objective image is displayed. # This is the colored background frame. self.goalFrame = DirectFrame( parent=self, relief=None, image=circleGui.find('**/circle_display_interior'), image_scale=0.18, text='', text_pos=(0, -0.11), text_fg=QuestGlobals.TEXT_COLOR, text_scale=QuestGlobals.QPtextScale, text_align=TextNode.ACenter, text_wordwrap=11.0, pos=QuestGlobals.DEFAULT_RIGHT_PICTURE_POS) self.goalFrame.hide() # The icon that goes on top of the goal frame. self.goalIcon = DirectFrame(parent=self.goalFrame, relief=None, text=' ', text_font=CIGlobals.getSuitFont(), text_pos=(0, -0.03), text_fg=QuestGlobals.TEXT_COLOR, text_scale=0.13, text_align=TextNode.ACenter, text_wordwrap=13.0, textMayChange=1) self.goalIcon.setColorOff(-1) self.goalIcon.hide() self.goalOutline = DirectLabel( parent=self.goalFrame, relief=None, image=circleGui.find('**/circle_display_outline'), image_scale=0.18) self.goalOutline.hide() # Information displayed about the additional goal. self.goalInfo = DirectLabel(parent=self, relief=None, text='', text_font=CIGlobals.getToonFont(), text_fg=QuestGlobals.TEXT_COLOR, text_scale=0.04, text_align=TextNode.ACenter, text_wordwrap=QuestGlobals.QPtextWordwrap, textMayChange=1, pos=(QuestGlobals.DEFAULT_INFO2_POS)) self.goalInfo.hide() circleGui.removeNode() return ########################################################################## def setup(self): QuestPoster.setup(self) objective = self.viewObjective # Let's reset our icon. self.goalIcon.setScale(1, 1, 1) self.goalIcon.setPos(0, 0, 0) self.goalIcon.setHpr(0, 0, 0) if objective.__class__ in DoubleFrameObjectives: if objective.__class__ == DeliverItemObjective: # It's kind of hard to return delivered stuff to somebody. # We're not handling complete objectives from here. self.handleDeliverItemObjective() elif objective.__class__ == RecoverItemObjective: self.handleRecoverItemObjective() if len(self.quest.accessibleObjectives) > 1: self.prevObjArrow.setPos(QuestGlobals.SECONDARY_LEFT_ARROW_POS) self.nextObjArrow.setPos( QuestGlobals.SECONDARY_RIGHT_ARROW_POS) self.goalFrame.show() self.goalIcon.show() self.goalOutline.show() self.goalInfo.show() self.fromToMiddleText.show() else: self.goalFrame.hide() self.goalIcon.hide() self.goalOutline.hide() self.goalInfo.hide() self.fromToMiddleText.hide() self.goalIcon.initialiseoptions(DirectFrame) self.initialiseoptions(DoubleFrameQuestPoster) def handleRecoverItemObjective(self): objective = self.viewObjective # Let's make sure we have a current objective that is # an instance of the RecoverItemObjective class and this poster isn't destroyed. if not objective or not hasattr(self, 'titleLabel') or not isinstance( objective, RecoverItemObjective): return # Let's make the left icon use the item icon we chose. self.handleSimpleIcon(objective.itemIcon, 0.12, self.auxIcon) # Handle the objective information. infoText = '%d %s' % (objective.goal, CIGlobals.makePlural(objective.itemName)) if objective.goal == 1: infoText = objective.itemName # Update the positions and information regarding the left side. self.auxFrame.setPos(QuestGlobals.RECOVER_LEFT_PICTURE_POS) self.auxFrame['image_color'] = QuestGlobals.GREEN self.objectiveInfo.setPos(QuestGlobals.RECOVER_INFO_POS) self.objectiveInfo['text'] = infoText self.fromToMiddleText[ 'text'] = QuestGlobals.FROM if not objective.isComplete( ) else QuestGlobals.TO if not objective.isComplete(): self.handleCogObjective(self.goalIcon, auxText=QuestGlobals.RECOVER, frameColor=QuestGlobals.GREEN) # Let's set the progress bar text pgBarText = '%d of %d %s' % (objective.progress, objective.goal, CIGlobals.makePastTense( QuestGlobals.RECOVER)) self.progressBar['text'] = pgBarText self.progressBar['value'] = objective.progress & pow(2, 16) - 1 else: self.handleNPCObjective(self.goalIcon, auxText=QuestGlobals.RETURN, frameColor=QuestGlobals.BLUE) def handleDeliverItemObjective(self): objective = self.viewObjective # Let's make sure we have a current objective that is # an instance of the DeliverItemObjective class and this poster isn't destroyed. if not objective or not hasattr(self, 'titleLabel') or not isinstance( objective, DeliverItemObjective): return # Correct the scaling if we need to and set the icon. scale = 0.12 if objective.itemIcon.getName() == 'package' else 0.85 self.handleSimpleIcon(objective.itemIcon, scale, self.auxIcon) self.auxFrame.setPos(QuestGlobals.RECOVER_LEFT_PICTURE_POS) self.auxFrame['image_color'] = QuestGlobals.RED infoText = '%d %s' % (objective.goal, CIGlobals.makePlural(objective.itemName)) if objective.goal == 1: infoText = objective.itemName self.objectiveInfo.setPos(QuestGlobals.RECOVER_INFO_POS) self.objectiveInfo['text'] = infoText self.fromToMiddleText['text'] = QuestGlobals.TO # Let's set the progress bar text pgBarText = '%d of %d %s' % (objective.progress, objective.goal, CIGlobals.makePastTense( QuestGlobals.DELIVER)) self.progressBar['text'] = pgBarText self.progressBar['value'] = objective.progress & pow(2, 16) - 1 self.handleNPCObjective(self.goalIcon, auxText=QuestGlobals.DELIVER, frameColor=QuestGlobals.RED) def destroy(self): self.fromToMiddleText.destroy() self.goalFrame.destroy() self.goalIcon.destroy() self.goalOutline.destroy() self.goalInfo.destroy() del self.fromToMiddleText del self.goalFrame del self.goalIcon del self.goalOutline del self.goalInfo QuestPoster.destroy(self)
class ShopWindow(DirectFrame): def __init__(self, shop, image): DirectFrame.__init__(self) self.shop = shop self.bgImage = image self.title = None self.okBtn = None self.clBtn = None self.infoLbl = None self.nPage = -1 self.nPages = 0 self.nextPage = 0 self.prevPage = -1 self.pages = [] self.isSetup = False return def setup(self, title = 'CHOOSE WHAT YOU WANT TO BUY'): font = CIGlobals.getMickeyFont() txtFg = (0, 0, 0, 1) txtScale = 0.05 txtPos = (0, -0.1) buttons = loader.loadModel('phase_3.5/models/gui/QT_buttons.bam') self.window = OnscreenImage(image=self.bgImage, scale=(0.9, 1, 0.7), parent=self) self.title = DirectLabel(text=title, relief=None, pos=(0, 0, 0.5), text_wordwrap=10, text_font=font, text_fg=(1, 1, 0, 1), scale=0.1, parent=self) self.infoLbl = DirectLabel(text='Welcome!', relief=None, text_scale=0.075, text_fg=txtFg, text_shadow=(0, 0, 0, 0), pos=(0, 0, 0.215)) self.okBtn = DirectButton(geom=CIGlobals.getOkayBtnGeom(), relief=None, text='OK', text_fg=txtFg, text_scale=txtScale, text_pos=txtPos, pos=(-0.1, 0, -0.5), parent=self) self.clBtn = DirectButton(geom=CIGlobals.getCancelBtnGeom(), relief=None, text='Cancel', text_fg=txtFg, text_scale=txtScale, text_pos=txtPos, pos=(0.1, 0, -0.5), parent=self) buttonGeom = (buttons.find('**/QT_back'), buttons.find('**/QT_back'), buttons.find('**/QT_back'), buttons.find('**/QT_back')) self.backBtn = DirectButton(geom=buttonGeom, relief=None, scale=0.05, pos=(-0.3, 0, -0.25), parent=self, command=self.changePage, extraArgs=[0]) self.nextBtn = DirectButton(geom=buttonGeom, relief=None, scale=0.05, pos=(0.3, 0, -0.25), hpr=(0, 0, 180), command=self.changePage, extraArgs=[1], parent=self) self.hideInfo() return def changePage(self, direction): var = self.prevPage if direction == 1: var = self.nextPage self.setPage(var) def __makeGagEntry(self, pos, item, values, page): itemImage = values.get('image') button = DirectButton(geom=itemImage, scale=1.3, pos=pos, relief=None, parent=page, command=self.shop.purchaseItem, extraArgs=[item]) supply = base.localAvatar.getBackpack().getSupply(item().getName()) maxSupply = base.localAvatar.getBackpack().getMaxSupply(item().getName()) buttonLabel = DirectLabel(text='%s/%s\n%s JBS' % (str(supply), str(maxSupply), str(values.get('price'))), relief=None, parent=button, text_scale=0.05, pos=(0, 0, -0.11)) self.addEntryToPage(page, item, values, button, buttonLabel) return def __makeUpgradeEntry(self, pos, item, values, page): itemImage = values.get('image') button = DirectButton(image=itemImage, scale=0.15, pos=pos, relief=None, parent=page, command=self.shop.purchaseItem, extraArgs=[item]) button.setTransparency(TransparencyAttrib.MAlpha) upgradeID = values.get('upgradeID') supply = base.localAvatar.getPUInventory()[0] if supply < 0: supply = 0 maxSupply = values.get('maxUpgrades') if upgradeID == 0 and base.localAvatar.getMyBattle().getTurretManager().myTurret: supply = 1 buttonLabel = DirectLabel(text='%s\n%s/%s\n%s JBS' % (item, str(supply), str(maxSupply), str(values.get('price'))), relief=None, parent=button, text_scale=0.3, pos=(0, 0, -1.2)) self.addEntryToPage(page, item, values, button, buttonLabel) return def __makeHealEntry(self, pos, item, values, page): label = '%s' % item itemImage = values.get('image') if 'showTitle' in values: label = '%s\n%s JBS' % (item, values.get('price')) button = DirectButton(image=itemImage, scale=0.105, pos=pos, relief=None, parent=page, command=self.shop.purchaseItem, extraArgs=[item]) button.setTransparency(TransparencyAttrib.MAlpha) buttonLabel = DirectLabel(text=label, relief=None, parent=button, text_scale=0.55, pos=(0, 0, -1.6)) self.addEntryToPage(page, item, values, button, buttonLabel) return def addEntryToPage(self, page, item, values, button, buttonLabel): page.addItemEntry(item, [button, buttonLabel]) page.addItem({item: values}) def makePages(self, items): newItems = dict(items) loadout = [] for slot in base.localAvatar.getBackpack().gagGUI.getSlots(): loadout.append(slot.getGag().getID()) for item, values in newItems.items(): if values.get('type') == ItemType.GAG: gag = item() if gag.getID() not in loadout or not base.localAvatar.getBackpack().isInBackpack(gag.getName()): del newItems[item] self.nPages = int(len(newItems) / 4) if self.nPages % 4 != 0 and len(newItems) > 4: self.nPages += 1 elif self.nPages == 0: self.nPages = 1 itemPos = [(-0.45, 0, 0), (-0.15, 0, 0), (0.15, 0, 0), (0.45, 0, 0)] pageIndex = 0 itemIndex = 0 index = 1 for _ in range(self.nPages): page = Page(self.shop, self) self.pages.append(page) for item, values in newItems.iteritems(): pos = itemPos[itemIndex] page = self.pages[pageIndex] itemType = values.get('type') if itemType == ItemType.GAG: self.__makeGagEntry(pos, item, values, page) elif itemType == ItemType.UPGRADE: self.__makeUpgradeEntry(pos, item, values, page) elif itemType == ItemType.HEAL: self.__makeHealEntry(pos, item, values, page) if index % 4 == 0: index = 1 pageIndex += 1 itemIndex = 0 else: itemIndex = itemIndex + 1 index += 1 if self.nPages == 1: self.backBtn.hide() self.nextBtn.hide() for page in self.pages: page.hide() page.update() self.isSetup = True def updatePages(self): for page in self.pages: page.update() def setPage(self, page): if self.nPage > -1: self.pages[self.nPage].hide() self.setBackBtn(True) self.setNextBtn(True) if page - 1 < 0: self.setBackBtn(False) elif page + 1 == self.nPages: self.setNextBtn(False) if page < 0 or page > self.nPages: return self.prevPage = page - 1 self.nextPage = page + 1 self.nPage = page self.pages[page].show() def setBackBtn(self, enabled): if self.backBtn: if enabled == False: self.backBtn.setColorScale(GRAYED_OUT_COLOR) self.backBtn['state'] = DGG.DISABLED else: self.backBtn.setColorScale(NORMAL_COLOR) self.backBtn['state'] = DGG.NORMAL def setNextBtn(self, enabled): if self.nextBtn: if enabled == False: self.nextBtn.setColorScale(GRAYED_OUT_COLOR) self.nextBtn['state'] = DGG.DISABLED else: self.nextBtn.setColorScale(NORMAL_COLOR) self.nextBtn['state'] = DGG.NORMAL def setOKCommand(self, command): if self.okBtn: self.okBtn['command'] = command def setCancelCommand(self, command): if self.clBtn: self.clBtn['command'] = command def showInfo(self, text, negative = 0, duration = -1): self.infoLbl.show() if negative: self.infoLbl['text_fg'] = (0.9, 0, 0, 1) self.infoLbl['text_shadow'] = (0, 0, 0, 1) else: self.infoLbl['text_fg'] = (0, 0, 0, 1) self.infoLbl['text_shadow'] = (0, 0, 0, 0) self.infoLbl['text'] = text if duration > -1: Sequence(Wait(duration), Func(self.hideInfo)).start() def hideInfo(self): if self.infoLbl: self.infoLbl.hide() def delete(self): elements = [self.title, self.okBtn, self.clBtn, self.infoLbl, self.backBtn, self.nextBtn] for element in elements: element.destroy() del elements for page in self.pages: page.destroy() self.pages.remove(page) self.title = None self.okBtn = None self.clBtn = None self.infoLbl = None self.backBtn = None self.nextBtn = None self.bgImage = None if self.window: self.window.destroy() self.window = None self.destroy() return
class VoteResultsPanel(DirectFrame): notify = DirectNotifyGlobal.directNotify.newCategory('VoteResultsPanel') def __init__(self, numPlayers, avIdList, votes, directions, namesList, disconnectedList, directionToGo, directionReason, directionTotals, *args, **kwargs): opts = {'relief': None, 'geom': DGG.getDefaultDialogGeom(), 'geom_color': ToontownGlobals.GlobalDialogColor[:3] + (0.8,), 'geom_scale': (1.75, 1, 0.75), 'pos': (0, 0, 0.525)} opts.update(kwargs) DirectFrame.__init__(self, *args, **opts) self.initialiseoptions(VoteResultsPanel) listMultiplier = 1 if TravelGameGlobals.SpoofFour: listMultiplier = 4 self.avIdList = avIdList * listMultiplier self.numPlayers = numPlayers * listMultiplier self.votes = votes * listMultiplier self.directions = directions * listMultiplier self.namesList = namesList * listMultiplier self.disconnectedList = disconnectedList * listMultiplier self.directionToGo = directionToGo self.directionReason = directionReason self.directionTotals = directionTotals self.entryList = [] self.rowFrame = [] self.upDownFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(-1)) self.upLabel = DirectLabel(parent=self.upDownFrame, relief=None, pos=(1.2, 0, 0.0), text=TTLocalizer.TravelGameDirections[0], text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.downLabel = DirectLabel(parent=self.upDownFrame, relief=None, pos=(1.43, 0, 0.0), text=TTLocalizer.TravelGameDirections[1], text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(self.numPlayers)) self.totalText = DirectLabel(parent=self.totalFrame, relief=None, pos=(1.0, 0, 0.0), text='Total', text_fg=(0.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalVotesUpLabel = DirectLabel(parent=self.totalFrame, relief=None, pos=(1.2, 0, 0.0), text='', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalVotesDownLabel = DirectLabel(parent=self.totalFrame, relief=None, pos=(1.43, 0, 0.0), text='', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalVotesLabels = [self.totalVotesUpLabel, self.totalVotesDownLabel] self.resultFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(5)) self.resultLabel = DirectLabel(parent=self.resultFrame, text='', text_scale=0.06, pos=(0.7, 0, 0.0), text_align=TextNode.ACenter) self.setupResultLabel() for index in range(self.numPlayers): frame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(index)) self.rowFrame.append(frame) nameLabel = DirectFrame(parent=frame, relief=None, pos=(0.46, 0.0, 0.0), text=self.namesList[index], text_fg=(0.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ACenter, text_font=DGG.getDefaultFont()) votesUpLabel = DirectLabel(parent=frame, relief=None, pos=(1.2, 0.0, 0.0), text='', text_fg=(0, 0, 1, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont()) votesDownLabel = DirectLabel(parent=frame, relief=None, pos=(1.43, 0.0, 0.0), text='', text_fg=(1, 0, 0, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont()) nameLabel.hide() self.entryList.append((nameLabel, votesUpLabel, votesDownLabel)) return def getRowPos(self, place): return Point3(-0.72, -0.01, 0.2 - place * 0.1) def setupResultLabel(self): reasonStr = '' if self.directionReason == TravelGameGlobals.ReasonVote: reasonStr = TTLocalizer.TravelGameReasonVotes % {'dir': TTLocalizer.TravelGameDirections[self.directionToGo], 'numVotes': self.directionTotals[self.directionToGo]} elif self.directionReason == TravelGameGlobals.ReasonRandom: reasonStr = TTLocalizer.TravelGameReasonRandom % {'dir': TTLocalizer.TravelGameDirections[self.directionToGo], 'numVotes': self.directionTotals[self.directionToGo]} elif self.directionReason == TravelGameGlobals.ReasonPlaceDecider: reasonStr = TravelGameReasonPlace % {'name': 'TODO NAME', 'dir': TTLocalizer.TravelGameDirections[self.directionToGo]} self.resultLabel['text'] = reasonStr self.resultLabel.hide() def createOnePlayerSequence(self, index, duration): numVotes = self.votes[index] direction = self.directions[index] def ticketTicker(t, label = self.entryList[index][direction + 1], startVotes = 0, endVotes = numVotes): label['text'] = str(int(t * endVotes + startVotes)) track = Parallel() track.append(Func(self.entryList[index][0].show, name='showName %d' % index)) track.append(LerpFunc(ticketTicker, duration=duration, name='countVotes %d' % index)) startVotes = 0 for prev in range(index): if self.directions[prev] == direction: startVotes += self.votes[prev] def totalTicker(t, label = self.totalVotesLabels[direction], startVotes = startVotes, additionalVotes = numVotes): label['text'] = str(int(t * additionalVotes + startVotes)) track.append(LerpFunc(totalTicker, duration=duration, name='countTotal %d' % index)) return track def startMovie(self): self.movie = Sequence() for index in range(self.numPlayers): track = self.createOnePlayerSequence(index, 1.25) self.movie.append(track) self.movie.append(Wait(0.75)) self.movie.append(Func(self.resultLabel.show)) self.movie.append(Wait(2.0)) self.movie.start() def destroy(self): self.movie.finish() DirectFrame.destroy(self)
def __init__(self, numPlayers, avIdList, votes, directions, namesList, disconnectedList, directionToGo, directionReason, directionTotals, *args, **kwargs): opts = {'relief': None, 'geom': DGG.getDefaultDialogGeom(), 'geom_color': ToontownGlobals.GlobalDialogColor[:3] + (0.8,), 'geom_scale': (1.75, 1, 0.25), 'pos': (0, 0, 0.825)} opts.update(kwargs) DirectFrame.__init__(self, *args, **opts) self.initialiseoptions(VoteResultsTrolleyPanel) listMultiplier = 1 if TravelGameGlobals.SpoofFour: listMultiplier = 4 self.avIdList = avIdList * listMultiplier self.numPlayers = numPlayers * listMultiplier self.votes = votes * listMultiplier self.directions = directions * listMultiplier self.namesList = namesList * listMultiplier self.disconnectedList = disconnectedList * listMultiplier self.directionToGo = directionToGo self.directionReason = directionReason self.directionTotals = directionTotals self.entryList = [] self.rowFrame = [] self.upDownFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(-1)) self.upLabel = DirectLabel(parent=self, relief=None, pos=(-0.5, 0, 0.06), text=TTLocalizer.TravelGameDirections[0] + ':', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.downLabel = DirectLabel(parent=self, relief=None, pos=(0.5, 0, 0.06), text=TTLocalizer.TravelGameDirections[1] + ':', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalVotesUpLabel = DirectLabel(parent=self.upLabel, relief=None, pos=(0.2, 0, 0.0), text='0', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalVotesDownLabel = DirectLabel(parent=self.downLabel, relief=None, pos=(0.2, 0, 0.0), text='0', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(self.numPlayers)) self.totalVotesLabels = [self.totalVotesUpLabel, self.totalVotesDownLabel] self.resultFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(0.5)) self.resultLabel = DirectLabel(parent=self.resultFrame, text='', text_scale=0.06, pos=(0.7, 0, 0.0), text_align=TextNode.ACenter) self.setupResultLabel() for index in range(self.numPlayers): frame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(index)) self.rowFrame.append(frame) nameLabel = DirectFrame(parent=frame, relief=None, pos=(0.46, 0.0, 0.0), text=self.namesList[index], text_fg=(0.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ACenter, text_font=DGG.getDefaultFont()) votesUpLabel = DirectLabel(parent=frame, relief=None, pos=(1.2, 0.0, 0.0), text='', text_fg=(0, 0, 1, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont()) votesDownLabel = DirectLabel(parent=frame, relief=None, pos=(1.43, 0.0, 0.0), text='', text_fg=(1, 0, 0, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont()) nameLabel.hide() self.entryList.append((nameLabel, votesUpLabel, votesDownLabel)) self.avVotesLabel = {} self.avArrows = {} matchingGameGui = loader.loadModel('phase_3.5/models/gui/matching_game_gui') minnieArrow = matchingGameGui.find('**/minnieArrow') from toontown.minigame.DistributedTravelGame import map3dToAspect2d for index in range(self.numPlayers): avId = self.avIdList[index] av = base.cr.doId2do.get(avId) if av: height = av.getHeight() avPos = av.getPos(render) avPos.setZ(av.getZ() + 5) labelPos = map3dToAspect2d(render, avPos) if not labelPos: continue labelPos.setZ(labelPos.getZ() + 0.3) arrow = None if self.votes[index] > 0: arrow = aspect2d.attachNewNode('avArrow') minnieArrow.copyTo(arrow) arrow.setScale(1.1, 1, 1.15) arrow.setPos(labelPos) if self.directions[index] == 0: arrow.setR(-90) arrow.setColorScale(0, 0, 1, 1) else: arrow.setR(90) arrow.setColorScale(1, 0, 0, 1) arrow.wrtReparentTo(self.resultFrame) arrow.hide() self.avArrows[index] = arrow fgColor = Vec4(0, 0, 0, 1) if self.votes[index] > 0: if self.directions[index] == 0: fgColor = Vec4(0, 0, 1, 1) else: fgColor = Vec4(1, 0, 0, 1) if self.votes[index] > 0: newLabel = DirectLabel(parent=aspect2d, relief=None, pos=labelPos, text='test', text_fg=(1, 1, 1, 1), text_scale=0.1, text_align=TextNode.ACenter, text_font=ToontownGlobals.getSignFont(), text_pos=(0, -0.01, 0)) else: newLabel = DirectLabel(parent=aspect2d, geom=DGG.getDefaultDialogGeom(), geom_scale=(0.2, 1, 0.2), relief=None, pos=labelPos, text='test', text_fg=(0.5, 0.5, 0.5, 1), text_scale=0.1, text_align=TextNode.ACenter, text_font=ToontownGlobals.getSignFont(), text_pos=(0, -0.035, 0)) newLabel.wrtReparentTo(self.resultFrame) newLabel.hide() self.avVotesLabel[index] = newLabel matchingGameGui.removeNode() self.curArrowSfxIndex = 0 self.upArrowSfx = [] self.downArrowSfx = [] for i in range(5): self.upArrowSfx.append(base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.mp3')) self.downArrowSfx.append(base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_red_arrow.mp3')) self.winVoteSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_win_vote.mp3') self.noVoteSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_square_no_vote_1.mp3') self.loseVoteSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_lose_vote.mp3') self.localAvatarWon = False self.localAvatarLost = False localIndex = self.avIdList.index(base.localAvatar.doId) localDirection = self.directions[localIndex] localVotes = self.votes[localIndex] if localVotes: if localDirection == self.directionToGo: if not TravelGameGlobals.ReverseWin: self.localAvatarWon = True else: self.localAvatarLost = True elif not TravelGameGlobals.ReverseWin: self.localAvatarLost = True else: self.localAvatarWon = True return
class InventoryGui(DirectObject): directNotify = DirectNotify().newCategory('InventoryGui') def __init__(self): DirectObject.__init__(self) self.backpack = None self.threeSlotsPos = [(0, 0, 0.5), (0, 0, 0), (0, 0, -0.5)] self.fourSlotPos = [(0, 0, 0.45), (0, 0, 0.15), (0, 0, -0.15), (0, 0, -0.45)] self.availableSlot = 0 self.slots = [] self.activeSlot = None self.defaultSlots = 3 self.prevSlot = None self.ammoLabel = None self.inventoryFrame = None self.switchSound = True self.switchSoundSfx = base.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.mp3') return def setWeapon(self, slot, playSound = True): if isinstance(slot, str): for iSlot in self.slots: if iSlot.getGag(): if iSlot.getGag().getName() == slot: slot = iSlot if self.activeSlot: self.activeSlot.setOutlineImage('idle') self.prevSlot = self.activeSlot if self.backpack.getSupply(slot.getGag().getName()) > 0: if self.activeSlot != slot: base.localAvatar.b_equip(GagGlobals.getIDByName(slot.getGag().getName())) slot.setOutlineImage('selected') self.activeSlot = slot elif self.activeSlot == slot and slot.getGag().getState() == GagState.LOADED: base.localAvatar.b_unEquip() self.activeSlot = None self.update() if self.switchSound and playSound: SoundInterval(self.switchSoundSfx).start() else: return return def createGui(self): self.deleteGui() phase = 'phase_3.5/maps/' posGroup = self.threeSlotsPos self.inventoryFrame = DirectFrame(parent=base.a2dRightCenter, pos=(-0.2, 0, 0)) if self.defaultSlots == 4: posGroup = self.fourSlotPos for slot in range(len(posGroup) + 1): if slot == 3: posGroup = self.fourSlotPos slotIdle = loader.loadTexture(phase + 'slot_%s_idle.png' % str(slot + 1)) slotObj = Slot(slot + 1, posGroup[slot], self.inventoryFrame) slotOutline = OnscreenImage(image=slotIdle, color=(1, 1, 1, 0.5), parent=slotObj) slotOutline.setTransparency(TransparencyAttrib.MAlpha) slotObj.setOutline(slotOutline) self.slots.append(slotObj) if slot == 3: slotObj.hide() self.ammoLabel = DirectLabel(text='Ammo: 0', text_fg=(1, 1, 1, 1), relief=None, text_shadow=(0, 0, 0, 1), text_scale=0.08, pos=(0.2, 0, 0.35), parent=base.a2dBottomLeft) self.ammoLabel.hide() self.enableWeaponSwitch() self.resetScroll() self.update() return def deleteGui(self): self.disableWeaponSwitch() for slot in self.slots: self.slots.remove(slot) slot.destroy() if self.ammoLabel: self.ammoLabel.destroy() self.ammoLabel = None if self.inventoryFrame: self.inventoryFrame.destroy() self.inventoryFrame = None return def resetScroll(self): nextGag = 0 prevGag = -1 curGag = -1 if self.prevSlot: prevGag = self.slots.index(self.prevSlot) if self.activeSlot: curGag = self.slots.index(self.activeSlot) if curGag == len(self.slots) - 1: nextGag = 0 prevGag = curGag - 1 elif curGag == 0: nextGag = 1 prevGag = len(self.slots) - 1 elif curGag == -1: prevGag = len(self.slots) - 1 else: nextGag = curGag + 1 prevGag = curGag - 1 self.accept('wheel_down', self.setWeapon, extraArgs=[self.slots[prevGag]]) self.accept('wheel_up', self.setWeapon, extraArgs=[self.slots[nextGag]]) def update(self): if not self.backpack: return else: for element in [self.ammoLabel, self.inventoryFrame]: if not element: return for slot in self.slots: gag = slot.getGag() if not gag: continue supply = self.backpack.getSupply(gag.getName()) index = self.slots.index(slot) if not gag and len(self.backpack.getGags()) - 1 >= index: gag = self.backpack.getGagByIndex(index) slot.setGag(gag) if self.backpack.getSupply(gag.getName()) > 0: slot.setOutlineImage('idle') else: slot.setOutlineImage('no_ammo') elif slot == self.activeSlot: if supply > 0: slot.setOutlineImage('selected') self.ammoLabel['text_fg'] = (1, 1, 1, 1) else: slot.setOutlineImage('no_ammo') self.ammoLabel['text_fg'] = (0.9, 0, 0, 1) self.activeSlot = None self.ammoLabel.show() self.ammoLabel['text'] = 'Ammo: %s' % self.backpack.getSupply(slot.getGag().getName()) elif self.backpack.getSupply(slot.getGag().getName()) > 0: slot.setOutlineImage('idle') else: slot.setOutlineImage('no_ammo') if self.activeSlot == None: self.ammoLabel.hide() self.ammoLabel['text'] = 'Ammo: 0' self.resetScroll() return def setBackpack(self, backpack): self.backpack = backpack def updateLoadout(self): if self.backpack: loadout = self.backpack.getLoadout() if len(loadout) <= 3: self.reseatSlots() elif len(loadout) == 4: self.reseatSlots(slots=4) for i in range(len(self.slots)): slot = self.slots[i] if i < len(loadout): slot.setGag(loadout[i]) else: slot.setGag(None) self.update() return def reseatSlots(self, slots = 3): for slot in range(len(self.slots) - 1): if slots == 4: self.slots[slot].setPos(self.fourSlotPos[slot]) else: self.slots[slot].setPos(self.threeSlotsPos[slot]) def enableWeaponSwitch(self): for index in range(len(self.slots)): self.accept(str(index + 1), self.setWeapon, extraArgs=[self.slots[index]]) def disableWeaponSwitch(self): for key in ['1', '2', '3', '4', 'wheel_down', 'wheel_up']: self.ignore(key) def getSlots(self): return self.slots
class DistributedIceGame(DistributedMinigame.DistributedMinigame, DistributedIceWorld.DistributedIceWorld): notify = directNotify.newCategory('DistributedIceGame') MaxLocalForce = 100 MaxPhysicsForce = 25000 def __init__(self, cr): DistributedMinigame.DistributedMinigame.__init__(self, cr) DistributedIceWorld.DistributedIceWorld.__init__(self, cr) self.gameFSM = ClassicFSM.ClassicFSM('DistributedIceGame', [ State.State('off', self.enterOff, self.exitOff, ['inputChoice']), State.State( 'inputChoice', self.enterInputChoice, self.exitInputChoice, ['waitServerChoices', 'moveTires', 'displayVotes', 'cleanup']), State.State('waitServerChoices', self.enterWaitServerChoices, self.exitWaitServerChoices, ['moveTires', 'cleanup']), State.State('moveTires', self.enterMoveTires, self.exitMoveTires, ['synch', 'cleanup']), State.State('synch', self.enterSynch, self.exitSynch, ['inputChoice', 'scoring', 'cleanup']), State.State('scoring', self.enterScoring, self.exitScoring, ['cleanup', 'finalResults', 'inputChoice']), State.State('finalResults', self.enterFinalResults, self.exitFinalResults, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, []) ], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) self.cameraThreeQuarterView = (0, -22, 45, 0, -62.89, 0) self.tireDict = {} self.forceArrowDict = {} self.canDrive = False self.timer = None self.timerStartTime = None self.curForce = 0 self.curHeading = 0 self.headingMomentum = 0.0 self.forceMomentum = 0.0 self.allTireInputs = None self.curRound = 0 self.curMatch = 0 self.controlKeyWarningLabel = DirectLabel( text=TTLocalizer.IceGameControlKeyWarning, text_fg=VBase4(1, 0, 0, 1), relief=None, pos=(0.0, 0, 0), scale=0.15) self.controlKeyWarningLabel.hide() self.waitingMoveLabel = DirectLabel( text=TTLocalizer.IceGameWaitingForPlayersToFinishMove, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075) self.waitingMoveLabel.hide() self.waitingSyncLabel = DirectLabel( text=TTLocalizer.IceGameWaitingForAISync, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075) self.waitingSyncLabel.hide() self.infoLabel = DirectLabel(text='', text_fg=VBase4(0, 0, 0, 1), relief=None, pos=(0.0, 0, 0.7), scale=0.075) self.updateInfoLabel() self.lastForceArrowUpdateTime = 0 self.sendForceArrowUpdateAsap = False self.treasures = [] self.penalties = [] self.obstacles = [] self.controlKeyPressed = False self.controlKeyWarningIval = None return def delete(self): DistributedIceWorld.DistributedIceWorld.delete(self) DistributedMinigame.DistributedMinigame.delete(self) if self.controlKeyWarningIval: self.controlKeyWarningIval.finish() self.controlKeyWarningIval = None self.controlKeyWarningLabel.destroy() del self.controlKeyWarningLabel self.waitingMoveLabel.destroy() del self.waitingMoveLabel self.waitingSyncLabel.destroy() del self.waitingSyncLabel self.infoLabel.destroy() del self.infoLabel for treasure in self.treasures: treasure.destroy() del self.treasures for penalty in self.penalties: penalty.destroy() del self.penalties for obstacle in self.obstacles: obstacle.removeNode() del self.obstacles del self.gameFSM return def announceGenerate(self): DistributedMinigame.DistributedMinigame.announceGenerate(self) DistributedIceWorld.DistributedIceWorld.announceGenerate(self) self.debugTaskName = self.uniqueName('debugTask') def getTitle(self): return TTLocalizer.IceGameTitle def getInstructions(self): szId = self.getSafezoneId() numPenalties = IceGameGlobals.NumPenalties[szId] result = TTLocalizer.IceGameInstructions if numPenalties == 0: result = TTLocalizer.IceGameInstructionsNoTnt return result def getMaxDuration(self): return 0 def load(self): self.notify.debug('load') DistributedMinigame.DistributedMinigame.load(self) self.music = base.loadMusic('phase_4/audio/bgm/MG_IceGame.ogg') self.gameBoard = loader.loadModel( 'phase_4/models/minigames/ice_game_icerink') background = loader.loadModel('phase_4/models/minigames/ice_game_2d') backgroundWide = loader.loadModel( 'phase_4/models/minigames/iceslide_ground') background.reparentTo(self.gameBoard) backgroundWide.reparentTo(self.gameBoard) backgroundWide.setPos(0, -0.3, -0.5) self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0) self.gameBoard.setScale(1.0) self.setupSimulation() index = 0 for avId in self.avIdList: self.setupTire(avId, index) self.setupForceArrow(avId) index += 1 for index in xrange(len(self.avIdList), 4): self.setupTire(-index, index) self.setupForceArrow(-index) self.showForceArrows(realPlayersOnly=True) self.westWallModel = NodePath() if not self.westWallModel.isEmpty(): self.westWallModel.reparentTo(self.gameBoard) self.westWallModel.setPos(IceGameGlobals.MinWall[0], IceGameGlobals.MinWall[1], 0) self.westWallModel.setScale(4) self.eastWallModel = NodePath() if not self.eastWallModel.isEmpty(): self.eastWallModel.reparentTo(self.gameBoard) self.eastWallModel.setPos(IceGameGlobals.MaxWall[0], IceGameGlobals.MaxWall[1], 0) self.eastWallModel.setScale(4) self.eastWallModel.setH(180) self.arrowKeys = ArrowKeys.ArrowKeys() self.target = loader.loadModel('phase_3/models/misc/sphere') self.target.setScale(0.01) self.target.reparentTo(self.gameBoard) self.target.setPos(0, 0, 0) self.scoreCircle = loader.loadModel( 'phase_4/models/minigames/ice_game_score_circle') self.scoreCircle.setScale(0.01) self.scoreCircle.reparentTo(self.gameBoard) self.scoreCircle.setZ(IceGameGlobals.TireRadius / 2.0) self.scoreCircle.setAlphaScale(0.5) self.scoreCircle.setTransparency(1) self.scoreCircle.hide() self.treasureModel = loader.loadModel( 'phase_4/models/minigames/ice_game_barrel') self.penaltyModel = loader.loadModel( 'phase_4/models/minigames/ice_game_tnt2') self.penaltyModel.setScale(0.75, 0.75, 0.7) szId = self.getSafezoneId() obstacles = IceGameGlobals.Obstacles[szId] index = 0 cubicObstacle = IceGameGlobals.ObstacleShapes[szId] for pos in obstacles: newPos = Point3(pos[0], pos[1], IceGameGlobals.TireRadius) newObstacle = self.createObstacle(newPos, index, cubicObstacle) self.obstacles.append(newObstacle) index += 1 self.countSound = loader.loadSfx( 'phase_3.5/audio/sfx/tick_counter.ogg') self.treasureGrabSound = loader.loadSfx( 'phase_4/audio/sfx/MG_sfx_vine_game_bananas.ogg') self.penaltyGrabSound = loader.loadSfx( 'phase_4/audio/sfx/MG_cannon_fire_alt.ogg') self.tireSounds = [] for tireIndex in xrange(4): tireHit = loader.loadSfx( 'phase_4/audio/sfx/Golf_Hit_Barrier_1.ogg') wallHit = loader.loadSfx('phase_4/audio/sfx/MG_maze_pickup.ogg') obstacleHit = loader.loadSfx( 'phase_4/audio/sfx/Golf_Hit_Barrier_2.ogg') self.tireSounds.append({ 'tireHit': tireHit, 'wallHit': wallHit, 'obstacleHit': obstacleHit }) self.arrowRotateSound = loader.loadSfx( 'phase_4/audio/sfx/MG_sfx_ice_force_rotate.ogg') self.arrowUpSound = loader.loadSfx( 'phase_4/audio/sfx/MG_sfx_ice_force_increase_3sec.ogg') self.arrowDownSound = loader.loadSfx( 'phase_4/audio/sfx/MG_sfx_ice_force_decrease_3sec.ogg') self.scoreCircleSound = loader.loadSfx( 'phase_4/audio/sfx/MG_sfx_ice_scoring_1.ogg') def unload(self): self.notify.debug('unload') DistributedMinigame.DistributedMinigame.unload(self) del self.music self.gameBoard.removeNode() del self.gameBoard for forceArrow in self.forceArrowDict.values(): forceArrow.removeNode() del self.forceArrowDict self.scoreCircle.removeNode() del self.scoreCircle del self.countSound def onstage(self): self.notify.debug('onstage') DistributedMinigame.DistributedMinigame.onstage(self) self.gameBoard.reparentTo(render) self.__placeToon(self.localAvId) self.moveCameraToTop() self.scorePanels = [] base.playMusic(self.music, looping=1, volume=0.8) def offstage(self): self.notify.debug('offstage') self.music.stop() self.gameBoard.hide() self.infoLabel.hide() for avId in self.tireDict: self.tireDict[avId]['tireNodePath'].hide() for panel in self.scorePanels: panel.cleanup() del self.scorePanels for obstacle in self.obstacles: obstacle.hide() for treasure in self.treasures: treasure.nodePath.hide() for penalty in self.penalties: penalty.nodePath.hide() for avId in self.avIdList: av = self.getAvatar(avId) if av: av.dropShadow.show() av.resetLOD() taskMgr.remove(self.uniqueName('aimtask')) self.arrowKeys.destroy() del self.arrowKeys DistributedMinigame.DistributedMinigame.offstage(self) def handleDisabledAvatar(self, avId): self.notify.debug('handleDisabledAvatar') self.notify.debug('avatar ' + str(avId) + ' disabled') DistributedMinigame.DistributedMinigame.handleDisabledAvatar( self, avId) def setGameReady(self): if not self.hasLocalToon: return self.notify.debug('setGameReady') if DistributedMinigame.DistributedMinigame.setGameReady(self): return for index in xrange(self.numPlayers): avId = self.avIdList[index] toon = self.getAvatar(avId) if toon: toon.reparentTo(render) self.__placeToon(avId) toon.forwardSpeed = 0 toon.rotateSpeed = False toon.dropShadow.hide() toon.setAnimState('Sit') if avId in self.tireDict: tireNp = self.tireDict[avId]['tireNodePath'] toon.reparentTo(tireNp) toon.setY(1.0) toon.setZ(-3) toon.startLookAround() def setGameStart(self, timestamp): if not self.hasLocalToon: return self.notify.debug('setGameStart') DistributedMinigame.DistributedMinigame.setGameStart(self, timestamp) for avId in self.remoteAvIdList: toon = self.getAvatar(avId) if toon: toon.stopLookAround() self.scores = [0] * self.numPlayers spacing = 0.4 for i in xrange(self.numPlayers): avId = self.avIdList[i] avName = self.getAvatarName(avId) scorePanel = MinigameAvatarScorePanel.MinigameAvatarScorePanel( avId, avName) scorePanel.setScale(0.9) scorePanel.setPos(-0.583 - spacing * (self.numPlayers - 1 - i), 0.0, -0.15) scorePanel.reparentTo(base.a2dTopRight) scorePanel.makeTransparent(0.75) self.scorePanels.append(scorePanel) self.arrowKeys.setPressHandlers([ self.__upArrowPressed, self.__downArrowPressed, self.__leftArrowPressed, self.__rightArrowPressed, self.__controlPressed ]) def isInPlayState(self): if not self.gameFSM.getCurrentState(): return False if not self.gameFSM.getCurrentState().getName() == 'play': return False return True def enterOff(self): self.notify.debug('enterOff') def exitOff(self): pass def enterInputChoice(self): self.notify.debug('enterInputChoice') self.forceLocalToonToTire() self.controlKeyPressed = False if self.curRound == 0: self.setupStartOfMatch() else: self.notify.debug('self.curRound = %s' % self.curRound) self.timer = ToontownTimer.ToontownTimer() self.timer.hide() if self.timerStartTime != None: self.startTimer() self.showForceArrows(realPlayersOnly=True) self.localForceArrow().setPosHpr(0, 0, -1.0, 0, 0, 0) self.localForceArrow().reparentTo(self.localTireNp()) self.localForceArrow().setY(IceGameGlobals.TireRadius) self.localTireNp().headsUp(self.target) self.notify.debug('self.localForceArrow() heading = %s' % self.localForceArrow().getH()) self.curHeading = self.localTireNp().getH() self.curForce = 25 self.updateLocalForceArrow() for avId in self.forceArrowDict: forceArrow = self.forceArrowDict[avId] forceArrow.setPosHpr(0, 0, -1.0, 0, 0, 0) tireNp = self.tireDict[avId]['tireNodePath'] forceArrow.reparentTo(tireNp) forceArrow.setY(IceGameGlobals.TireRadius) tireNp.headsUp(self.target) self.updateForceArrow(avId, tireNp.getH(), 25) taskMgr.add(self.__aimTask, self.uniqueName('aimtask')) if base.localAvatar.laffMeter: base.localAvatar.laffMeter.stop() self.sendForceArrowUpdateAsap = False return def exitInputChoice(self): if not self.controlKeyPressed: if self.controlKeyWarningIval: self.controlKeyWarningIval.finish() self.controlKeyWarningIval = None self.controlKeyWarningIval = Sequence( Func(self.controlKeyWarningLabel.show), self.controlKeyWarningLabel.colorScaleInterval( 10, VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1)), Func(self.controlKeyWarningLabel.hide)) self.controlKeyWarningIval.start() if self.timer != None: self.timer.destroy() self.timer = None self.timerStartTime = None self.hideForceArrows() self.arrowRotateSound.stop() self.arrowUpSound.stop() self.arrowDownSound.stop() taskMgr.remove(self.uniqueName('aimtask')) return def enterWaitServerChoices(self): self.waitingMoveLabel.show() self.showForceArrows(True) def exitWaitServerChoices(self): self.waitingMoveLabel.hide() self.hideForceArrows() def enterMoveTires(self): for key in self.tireDict: body = self.tireDict[key]['tireBody'] body.setAngularVel(0, 0, 0) body.setLinearVel(0, 0, 0) for index in xrange(len(self.allTireInputs)): input = self.allTireInputs[index] avId = self.avIdList[index] body = self.getTireBody(avId) degs = input[1] + 90 tireNp = self.getTireNp(avId) tireH = tireNp.getH() self.notify.debug('tireH = %s' % tireH) radAngle = deg2Rad(degs) foo = NodePath('foo') dirVector = Vec3(math.cos(radAngle), math.sin(radAngle), 0) self.notify.debug('dirVector is now=%s' % dirVector) inputForce = input[0] inputForce /= self.MaxLocalForce inputForce *= self.MaxPhysicsForce force = dirVector * inputForce self.notify.debug('adding force %s to %d' % (force, avId)) body.addForce(force) self.enableAllTireBodies() self.totalPhysicsSteps = 0 self.startSim() taskMgr.add(self.__moveTiresTask, self.uniqueName('moveTiresTtask')) def exitMoveTires(self): self.forceLocalToonToTire() self.disableAllTireBodies() self.stopSim() self.notify.debug('total Physics steps = %d' % self.totalPhysicsSteps) taskMgr.remove(self.uniqueName('moveTiresTtask')) def enterSynch(self): self.waitingSyncLabel.show() def exitSynch(self): self.waitingSyncLabel.hide() def enterScoring(self): sortedByDistance = [] for avId in self.avIdList: np = self.getTireNp(avId) pos = np.getPos() pos.setZ(0) sortedByDistance.append((avId, pos.length())) def compareDistance(x, y): if x[1] - y[1] > 0: return 1 elif x[1] - y[1] < 0: return -1 else: return 0 sortedByDistance.sort(cmp=compareDistance) self.scoreMovie = Sequence() curScale = 0.01 curTime = 0 self.scoreCircle.setScale(0.01) self.scoreCircle.show() self.notify.debug('newScores = %s' % self.newScores) circleStartTime = 0 for index in xrange(len(sortedByDistance)): distance = sortedByDistance[index][1] avId = sortedByDistance[index][0] scorePanelIndex = self.avIdList.index(avId) time = (distance - curScale) / IceGameGlobals.ExpandFeetPerSec if time < 0: time = 0.01 scaleXY = distance + IceGameGlobals.TireRadius self.notify.debug('circleStartTime = %s' % circleStartTime) self.scoreMovie.append( Parallel( LerpScaleInterval(self.scoreCircle, time, Point3(scaleXY, scaleXY, 1.0)), SoundInterval(self.scoreCircleSound, duration=time, startTime=circleStartTime))) circleStartTime += time startScore = self.scorePanels[scorePanelIndex].getScore() destScore = self.newScores[scorePanelIndex] self.notify.debug('for avId %d, startScore=%d, newScores=%d' % (avId, startScore, destScore)) def increaseScores(t, scorePanelIndex=scorePanelIndex, startScore=startScore, destScore=destScore): oldScore = self.scorePanels[scorePanelIndex].getScore() diff = destScore - startScore newScore = int(startScore + diff * t) if newScore > oldScore: base.playSfx(self.countSound) self.scorePanels[scorePanelIndex].setScore(newScore) self.scores[scorePanelIndex] = newScore duration = (destScore - startScore) * IceGameGlobals.ScoreCountUpRate tireNp = self.tireDict[avId]['tireNodePath'] self.scoreMovie.append( Parallel( LerpFunctionInterval(increaseScores, duration), Sequence( LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1))))) curScale += distance self.scoreMovie.append( Func(self.sendUpdate, 'reportScoringMovieDone', [])) self.scoreMovie.start() def exitScoring(self): self.scoreMovie.finish() self.scoreMovie = None self.scoreCircle.hide() return def enterFinalResults(self): lerpTrack = Parallel() lerpDur = 0.5 tY = 0.6 bY = -0.05 lX = -0.5 cX = 0 rX = 0.5 scorePanelLocs = (((cX, bY), ), ((lX, bY), (rX, bY)), ((cX, tY), (lX, bY), (rX, bY)), ((lX, tY), (rX, tY), (lX, bY), (rX, bY))) scorePanelLocs = scorePanelLocs[self.numPlayers - 1] for i in xrange(self.numPlayers): panel = self.scorePanels[i] pos = scorePanelLocs[i] panel.wrtReparentTo(aspect2d) lerpTrack.append( Parallel( LerpPosInterval(panel, lerpDur, Point3(pos[0], 0, pos[1]), blendType='easeInOut'), LerpScaleInterval(panel, lerpDur, Vec3(panel.getScale()) * 2.0, blendType='easeInOut'))) self.showScoreTrack = Parallel( lerpTrack, Sequence(Wait(IceGameGlobals.ShowScoresDuration), Func(self.gameOver))) self.showScoreTrack.start() def exitFinalResults(self): self.showScoreTrack.pause() del self.showScoreTrack def enterCleanup(self): self.notify.debug('enterCleanup') if base.localAvatar.laffMeter: base.localAvatar.laffMeter.start() def exitCleanup(self): pass def __placeToon(self, avId): toon = self.getAvatar(avId) if toon: toon.setPos(0, 0, 0) toon.setHpr(0, 0, 0) def moveCameraToTop(self): camera.reparentTo(render) p = self.cameraThreeQuarterView camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5]) def setupTire(self, avId, index): tireNp, tireBody, tireOdeGeom = self.createTire(index) self.tireDict[avId] = { 'tireNodePath': tireNp, 'tireBody': tireBody, 'tireOdeGeom': tireOdeGeom } if avId <= 0: tireBlocker = tireNp.find('**/tireblockermesh') if not tireBlocker.isEmpty(): tireBlocker.hide() if avId == self.localAvId: tireNp = self.tireDict[avId]['tireNodePath'] self.treasureSphereName = 'treasureCollider' self.treasureCollSphere = CollisionSphere( 0, 0, 0, IceGameGlobals.TireRadius) self.treasureCollSphere.setTangible(0) self.treasureCollNode = CollisionNode(self.treasureSphereName) self.treasureCollNode.setFromCollideMask( ToontownGlobals.PieBitmask) self.treasureCollNode.addSolid(self.treasureCollSphere) self.treasureCollNodePath = tireNp.attachNewNode( self.treasureCollNode) self.treasureHandler = CollisionHandlerEvent() self.treasureHandler.addInPattern('%fn-intoTreasure') base.cTrav.addCollider(self.treasureCollNodePath, self.treasureHandler) eventName = '%s-intoTreasure' % self.treasureCollNodePath.getName() self.notify.debug('eventName = %s' % eventName) self.accept(eventName, self.toonHitSomething) def setupForceArrow(self, avId): arrow = loader.loadModel('phase_4/models/minigames/ice_game_arrow') priority = 0 if avId < 0: priority = -avId else: priority = self.avIdList.index(avId) if avId == self.localAvId: priority = 10 self.forceArrowDict[avId] = arrow def hideForceArrows(self): for forceArrow in self.forceArrowDict.values(): forceArrow.hide() def showForceArrows(self, realPlayersOnly=True): for avId in self.forceArrowDict: if realPlayersOnly: if avId > 0: self.forceArrowDict[avId].show() else: self.forceArrowDict[avId].hide() else: self.forceArrowDict[avId].show() def localForceArrow(self): if self.localAvId in self.forceArrowDict: return self.forceArrowDict[self.localAvId] else: return None return None def setChoices(self, input0, input1, input2, input3): pass def startDebugTask(self): taskMgr.add(self.debugTask, self.debugTaskName) def stopDebugTask(self): taskMgr.remove(self.debugTaskName) def debugTask(self, task): if self.canDrive and self.tireDict.has_key(localAvatar.doId): dt = globalClock.getDt() forceMove = 25000 forceMoveDt = forceMove tireBody = self.tireDict[localAvatar.doId]['tireBody'] if self.arrowKeys.upPressed() and not tireBody.isEnabled(): x = 0 y = 1 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.downPressed() and not tireBody.isEnabled(): x = 0 y = -1 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.leftPressed() and not tireBody.isEnabled(): x = -1 y = 0 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.rightPressed() and not tireBody.isEnabled(): x = 1 y = 0 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) return task.cont def __upArrowPressed(self): pass def __downArrowPressed(self): pass def __leftArrowPressed(self): pass def __rightArrowPressed(self): pass def __controlPressed(self): if self.gameFSM.getCurrentState().getName() == 'inputChoice': self.sendForceArrowUpdateAsap = True self.updateLocalForceArrow() self.controlKeyPressed = True self.sendUpdate('setAvatarChoice', [self.curForce, self.curHeading]) self.gameFSM.request('waitServerChoices') def startTimer(self): now = globalClock.getFrameTime() elapsed = now - self.timerStartTime self.timer.posInTopRightCorner() self.timer.setTime(IceGameGlobals.InputTimeout) self.timer.countdown(IceGameGlobals.InputTimeout - elapsed, self.handleChoiceTimeout) self.timer.show() def setTimerStartTime(self, timestamp): if not self.hasLocalToon: return else: self.timerStartTime = globalClockDelta.networkToLocalTime( timestamp) if self.timer != None: self.startTimer() return def handleChoiceTimeout(self): self.sendUpdate('setAvatarChoice', [0, 0]) self.gameFSM.request('waitServerChoices') def localTireNp(self): ret = None if self.localAvId in self.tireDict: ret = self.tireDict[self.localAvId]['tireNodePath'] return ret def localTireBody(self): ret = None if self.localAvId in self.tireDict: ret = self.tireDict[self.localAvId]['tireBody'] return ret def getTireBody(self, avId): ret = None if avId in self.tireDict: ret = self.tireDict[avId]['tireBody'] return ret def getTireNp(self, avId): ret = None if avId in self.tireDict: ret = self.tireDict[avId]['tireNodePath'] return ret def updateForceArrow(self, avId, curHeading, curForce): forceArrow = self.forceArrowDict[avId] tireNp = self.tireDict[avId]['tireNodePath'] tireNp.setH(curHeading) tireBody = self.tireDict[avId]['tireBody'] tireBody.setQuaternion(tireNp.getQuat()) self.notify.debug('curHeading = %s' % curHeading) yScale = curForce / 100.0 yScale *= 1 headY = yScale * 15 xScale = (yScale - 1) / 2.0 + 1.0 shaft = forceArrow.find('**/arrow_shaft') head = forceArrow.find('**/arrow_head') shaft.setScale(xScale, yScale, 1) head.setPos(0, headY, 0) head.setScale(xScale, xScale, 1) def updateLocalForceArrow(self): avId = self.localAvId self.b_setForceArrowInfo(avId, self.curHeading, self.curForce) def __aimTask(self, task): if not hasattr(self, 'arrowKeys'): return task.done dt = globalClock.getDt() headingMomentumChange = dt * 60.0 forceMomentumChange = dt * 160.0 arrowUpdate = False arrowRotating = False arrowUp = False arrowDown = False if self.arrowKeys.upPressed() and not self.arrowKeys.downPressed(): self.forceMomentum += forceMomentumChange if self.forceMomentum < 0: self.forceMomentum = 0 if self.forceMomentum > 50: self.forceMomentum = 50 oldForce = self.curForce self.curForce += self.forceMomentum * dt arrowUpdate = True if oldForce < self.MaxLocalForce: arrowUp = True elif self.arrowKeys.downPressed() and not self.arrowKeys.upPressed(): self.forceMomentum += forceMomentumChange if self.forceMomentum < 0: self.forceMomentum = 0 if self.forceMomentum > 50: self.forceMomentum = 50 oldForce = self.curForce self.curForce -= self.forceMomentum * dt arrowUpdate = True if oldForce > 0.01: arrowDown = True else: self.forceMomentum = 0 if self.arrowKeys.leftPressed() and not self.arrowKeys.rightPressed(): self.headingMomentum += headingMomentumChange if self.headingMomentum < 0: self.headingMomentum = 0 if self.headingMomentum > 50: self.headingMomentum = 50 self.curHeading += self.headingMomentum * dt arrowUpdate = True arrowRotating = True elif self.arrowKeys.rightPressed( ) and not self.arrowKeys.leftPressed(): self.headingMomentum += headingMomentumChange if self.headingMomentum < 0: self.headingMomentum = 0 if self.headingMomentum > 50: self.headingMomentum = 50 self.curHeading -= self.headingMomentum * dt arrowUpdate = True arrowRotating = True else: self.headingMomentum = 0 if arrowUpdate: self.normalizeHeadingAndForce() self.updateLocalForceArrow() if arrowRotating: if not self.arrowRotateSound.status( ) == self.arrowRotateSound.PLAYING: base.playSfx(self.arrowRotateSound, looping=True) else: self.arrowRotateSound.stop() if arrowUp: if not self.arrowUpSound.status() == self.arrowUpSound.PLAYING: base.playSfx(self.arrowUpSound, looping=False) else: self.arrowUpSound.stop() if arrowDown: if not self.arrowDownSound.status() == self.arrowDownSound.PLAYING: base.playSfx(self.arrowDownSound, looping=False) else: self.arrowDownSound.stop() return task.cont def normalizeHeadingAndForce(self): if self.curForce > self.MaxLocalForce: self.curForce = self.MaxLocalForce if self.curForce < 0.01: self.curForce = 0.01 def setTireInputs(self, tireInputs): if not self.hasLocalToon: return self.allTireInputs = tireInputs self.gameFSM.request('moveTires') def enableAllTireBodies(self): for avId in self.tireDict.keys(): self.tireDict[avId]['tireBody'].enable() def disableAllTireBodies(self): for avId in self.tireDict.keys(): self.tireDict[avId]['tireBody'].disable() def areAllTiresDisabled(self): for avId in self.tireDict.keys(): if self.tireDict[avId]['tireBody'].isEnabled(): return False return True def __moveTiresTask(self, task): if self.areAllTiresDisabled(): self.sendTirePositions() self.gameFSM.request('synch') return task.done return task.cont def sendTirePositions(self): tirePositions = [] for index in xrange(len(self.avIdList)): avId = self.avIdList[index] tire = self.getTireBody(avId) pos = Point3(tire.getPosition()) tirePositions.append([pos[0], pos[1], pos[2]]) for index in xrange(len(self.avIdList), 4): avId = -index tire = self.getTireBody(avId) pos = Point3(tire.getPosition()) tirePositions.append([pos[0], pos[1], pos[2]]) self.sendUpdate('endingPositions', [tirePositions]) def setFinalPositions(self, finalPos): if not self.hasLocalToon: return for index in xrange(len(self.avIdList)): avId = self.avIdList[index] tire = self.getTireBody(avId) np = self.getTireNp(avId) pos = finalPos[index] tire.setPosition(pos[0], pos[1], pos[2]) np.setPos(pos[0], pos[1], pos[2]) for index in xrange(len(self.avIdList), 4): avId = -index tire = self.getTireBody(avId) np = self.getTireNp(avId) pos = finalPos[index] tire.setPosition(pos[0], pos[1], pos[2]) np.setPos(pos[0], pos[1], pos[2]) def updateInfoLabel(self): self.infoLabel['text'] = TTLocalizer.IceGameInfo % { 'curMatch': self.curMatch + 1, 'numMatch': IceGameGlobals.NumMatches, 'curRound': self.curRound + 1, 'numRound': IceGameGlobals.NumRounds } def setMatchAndRound(self, match, round): if not self.hasLocalToon: return self.curMatch = match self.curRound = round self.updateInfoLabel() def setScores(self, match, round, scores): if not self.hasLocalToon: return self.newMatch = match self.newRound = round self.newScores = scores def setNewState(self, state): if not self.hasLocalToon: return self.notify.debug('setNewState gameFSM=%s newState=%s' % (self.gameFSM, state)) self.gameFSM.request(state) def putAllTiresInStartingPositions(self): for index in xrange(len(self.avIdList)): avId = self.avIdList[index] np = self.tireDict[avId]['tireNodePath'] np.setPos(IceGameGlobals.StartingPositions[index]) self.notify.debug('avId=%s newPos=%s' % (avId, np.getPos)) np.setHpr(0, 0, 0) quat = np.getQuat() body = self.tireDict[avId]['tireBody'] body.setPosition(IceGameGlobals.StartingPositions[index]) body.setQuaternion(quat) for index in xrange(len(self.avIdList), 4): avId = -index np = self.tireDict[avId]['tireNodePath'] np.setPos(IceGameGlobals.StartingPositions[index]) self.notify.debug('avId=%s newPos=%s' % (avId, np.getPos)) np.setHpr(0, 0, 0) quat = np.getQuat() body = self.tireDict[avId]['tireBody'] body.setPosition(IceGameGlobals.StartingPositions[index]) body.setQuaternion(quat) def b_setForceArrowInfo(self, avId, force, heading): self.setForceArrowInfo(avId, force, heading) self.d_setForceArrowInfo(avId, force, heading) def d_setForceArrowInfo(self, avId, force, heading): sendIt = False curTime = self.getCurrentGameTime() if self.sendForceArrowUpdateAsap: sendIt = True elif curTime - self.lastForceArrowUpdateTime > 0.2: sendIt = True if sendIt: self.sendUpdate('setForceArrowInfo', [avId, force, heading]) self.sendForceArrowUpdateAsap = False self.lastForceArrowUpdateTime = self.getCurrentGameTime() def setForceArrowInfo(self, avId, force, heading): if not self.hasLocalToon: return self.updateForceArrow(avId, force, heading) def setupStartOfMatch(self): self.putAllTiresInStartingPositions() szId = self.getSafezoneId() self.numTreasures = IceGameGlobals.NumTreasures[szId] if self.treasures: for treasure in self.treasures: treasure.destroy() self.treasures = [] index = 0 treasureMargin = IceGameGlobals.TireRadius + 1.0 while len(self.treasures) < self.numTreasures: xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5, IceGameGlobals.MaxWall[0] - 5) yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5, IceGameGlobals.MaxWall[1] - 5) self.notify.debug('yPos=%s' % yPos) pos = Point3(xPos, yPos, IceGameGlobals.TireRadius) newTreasure = IceTreasure.IceTreasure(self.treasureModel, pos, index, self.doId, penalty=False) goodSpot = True for obstacle in self.obstacles: if newTreasure.nodePath.getDistance(obstacle) < treasureMargin: goodSpot = False break if goodSpot: for treasure in self.treasures: if newTreasure.nodePath.getDistance( treasure.nodePath) < treasureMargin: goodSpot = False break if goodSpot: self.treasures.append(newTreasure) index += 1 else: newTreasure.destroy() self.numPenalties = IceGameGlobals.NumPenalties[szId] if self.penalties: for penalty in self.penalties: penalty.destroy() self.penalties = [] index = 0 while len(self.penalties) < self.numPenalties: xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5, IceGameGlobals.MaxWall[0] - 5) yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5, IceGameGlobals.MaxWall[1] - 5) self.notify.debug('yPos=%s' % yPos) pos = Point3(xPos, yPos, IceGameGlobals.TireRadius) newPenalty = IceTreasure.IceTreasure(self.penaltyModel, pos, index, self.doId, penalty=True) goodSpot = True for obstacle in self.obstacles: if newPenalty.nodePath.getDistance(obstacle) < treasureMargin: goodSpot = False break if goodSpot: for treasure in self.treasures: if newPenalty.nodePath.getDistance( treasure.nodePath) < treasureMargin: goodSpot = False break if goodSpot: for penalty in self.penalties: if newPenalty.nodePath.getDistance( penalty.nodePath) < treasureMargin: goodSpot = False break if goodSpot: self.penalties.append(newPenalty) index += 1 else: newPenalty.destroy() def toonHitSomething(self, entry): self.notify.debug('---- treasure Enter ---- ') self.notify.debug('%s' % entry) name = entry.getIntoNodePath().getName() parts = name.split('-') if len(parts) < 3: self.notify.debug('collided with %s, but returning' % name) return if not int(parts[1]) == self.doId: self.notify.debug("collided with %s, but doId doesn't match" % name) return treasureNum = int(parts[2]) if 'penalty' in parts[0]: self.__penaltyGrabbed(treasureNum) else: self.__treasureGrabbed(treasureNum) def __treasureGrabbed(self, treasureNum): self.treasures[treasureNum].showGrab() self.treasureGrabSound.play() self.sendUpdate('claimTreasure', [treasureNum]) def setTreasureGrabbed(self, avId, treasureNum): if not self.hasLocalToon: return self.notify.debug('treasure %s grabbed by %s' % (treasureNum, avId)) if avId != self.localAvId: self.treasures[treasureNum].showGrab() i = self.avIdList.index(avId) self.scores[i] += 1 self.scorePanels[i].setScore(self.scores[i]) def __penaltyGrabbed(self, penaltyNum): self.penalties[penaltyNum].showGrab() self.sendUpdate('claimPenalty', [penaltyNum]) def setPenaltyGrabbed(self, avId, penaltyNum): if not self.hasLocalToon: return self.notify.debug('penalty %s grabbed by %s' % (penaltyNum, avId)) if avId != self.localAvId: self.penalties[penaltyNum].showGrab() i = self.avIdList.index(avId) self.scores[i] -= 1 self.scorePanels[i].setScore(self.scores[i]) def postStep(self): DistributedIceWorld.DistributedIceWorld.postStep(self) if self.colCount: for count in range(self.colCount): c0, c1 = self.getOrderedContacts(count) if c1 in self.tireCollideIds: tireIndex = self.tireCollideIds.index(c1) if c0 in self.tireCollideIds: self.tireSounds[tireIndex]['tireHit'].play() elif c0 == self.wallCollideId: self.tireSounds[tireIndex]['wallHit'].play() elif c0 == self.obstacleCollideId: self.tireSounds[tireIndex]['obstacleHit'].play() def forceLocalToonToTire(self): toon = localAvatar if toon and self.localAvId in self.tireDict: tireNp = self.tireDict[self.localAvId]['tireNodePath'] toon.reparentTo(tireNp) toon.setPosHpr(0, 0, 0, 0, 0, 0) toon.setY(1.0) toon.setZ(-3)
class SimpleInteractive(DirectObject): def __init__(self, object, name, proximityText): DirectObject.__init__(self) self.object = object self.proximityText = proximityText self.proximityEvent = name self.enterProximityEvent = 'enter' + name self.exitProximityEvent = 'exit' + name self.useLabel = None self.fader = None self.size = 6 self.disk = None proximitySphere = CollisionSphere(0, 0, 0, self.size) proximitySphere.setTangible(0) proximityNode = CollisionNode(self.proximityEvent) proximityNode.setIntoCollideMask(PiratesGlobals.WallBitmask) proximityNode.addSolid(proximitySphere) self.proximityNodePath = self.object.attachNewNode(proximityNode) self.accept(self.enterProximityEvent, self.approach) self.accept(self.exitProximityEvent, self.leave) def createInteractionDisk(self): self.disk = loader.loadModel('models/effects/selectionCursor') self.disk.setScale(self.size) self.disk.setColorScale(0, 1, 0, 1) self.disk.setP(-90) self.disk.setZ(0.025000000000000001) self.disk.setBillboardAxis(6) self.disk.reparentTo(self.object) self.disk.setBin('shadow', 0) self.disk.setTransparency(TransparencyAttrib.MAlpha) self.disk.setDepthWrite(0) self.disk.setDepthTest(0) def loadUseLabel(self, text): self.useLabel = DirectLabel(parent = aspect2d, frameColor = (0.10000000000000001, 0.10000000000000001, 0.25, 0.20000000000000001), text = text, text_align = TextNode.ACenter, text_scale = 0.059999999999999998, text_pos = (0.02, 0.02), text_fg = (1, 1, 1, 1), text_shadow = (0, 0, 0, 1), textMayChange = 1, text_font = PiratesGlobals.getPirateOutlineFont()) self.useLabel.setPos(0, 0, -0.69999999999999996) self.useLabel.setAlphaScale(0) self.useLabel.hide() def fadeInText(self): if self.fader: self.fader.pause() def interactionAllowed(self, avId): return True def approach(self, collEntry): if not self.interactionAllowed(localAvatar.doId): return None if not self.disk: self.createInteractionDisk() if self.proximityText: if not self.useLabel: self.loadUseLabel(self.proximityText) if self.fader: self.fader.pause() fadeIn = LerpFunctionInterval(self.useLabel.setAlphaScale, fromData = 0, toData = 1, duration = 0.5) self.fader = Sequence(Func(self.useLabel.show), fadeIn) self.fader.start() self.disk.show() self.accept(USE_KEY_EVENT, self.handleUseKey) def requestInteraction(self, avId): pass def handleUseKey(self): self.requestInteraction(localAvatar.doId) def leave(self, collEntry): if self.disk: self.disk.hide() if self.proximityText: if self.fader: self.fader.pause() self.fader = None if self.useLabel: self.useLabel.hide() self.ignore(USE_KEY_EVENT)
class GroupTrackerPage(ShtikerPage.ShtikerPage): notify = directNotify.newCategory('GroupTrackerPage') def __init__(self): ShtikerPage.ShtikerPage.__init__(self) self.groupWidgets = [] self.playerWidgets = [] self.images = [] # image nodes: Possible images to apply on groups self.scrollList = None # DirectScrolledList: Holds the GroupTrackerGroup widgets self.scrollTitle = None # DirectLabel: Title of the list that holds the groups self.playerList = None # DirectScrolledList: Holds players when showing a specific group details self.playerListTitle = None # DirectLabel: Title of the playerList self.groupInfoTitle = None # DirectLabel: holds the group detail title to show on the right self.groupInfoDistrict = None # DirectLabel: shows group detail district on the right self.statusMessage = None # DirectLabel: Shows important messages like Loading... or "No boarding groups available" self.groupIcon = None # DirectButton: Icon to associate with the group ex. sellbot icon or cashbot icon depending on group info self.wantGroupToggle = None # DirectButton: Allows the toon to toggle his listing def load(self): self.listXorigin = -0.02 self.listFrameSizeX = 0.67 self.listZorigin = -0.96 self.listFrameSizeZ = 1.04 self.arrowButtonScale = 1.3 self.itemFrameXorigin = -0.237 self.itemFrameZorigin = 0.365 self.buttonXstart = self.itemFrameXorigin + 0.293 self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui') guiButton = loader.loadModel('phase_3/models/gui/quit_button') self.scrollList = DirectScrolledList(parent=self, relief=None, pos=(-0.5, 0, 0), incButton_image=(self.gui.find('**/FndsLst_ScrollUp'), self.gui.find('**/FndsLst_ScrollDN'), self.gui.find('**/FndsLst_ScrollUp_Rllvr'), self.gui.find('**/FndsLst_ScrollUp') ), incButton_relief=None, incButton_scale=(self.arrowButtonScale, self.arrowButtonScale, -self.arrowButtonScale), incButton_pos=(self.buttonXstart, 0, self.itemFrameZorigin - 0.999), incButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_image=(self.gui.find('**/FndsLst_ScrollUp'), self.gui.find('**/FndsLst_ScrollDN'), self.gui.find('**/FndsLst_ScrollUp_Rllvr'), self.gui.find('**/FndsLst_ScrollUp') ), decButton_relief=None, decButton_scale=(self.arrowButtonScale, self.arrowButtonScale, self.arrowButtonScale), decButton_pos=(self.buttonXstart, 0, self.itemFrameZorigin + 0.227), decButton_image3_color=Vec4(1, 1, 1, 0.2), itemFrame_pos=(self.itemFrameXorigin, 0, self.itemFrameZorigin), itemFrame_scale=1.0, itemFrame_relief=DGG.SUNKEN, itemFrame_frameSize=(self.listXorigin, self.listXorigin + self.listFrameSizeX, self.listZorigin, self.listZorigin + self.listFrameSizeZ ), itemFrame_frameColor=(0.85, 0.95, 1, 1), itemFrame_borderWidth=(0.01, 0.01), numItemsVisible=15, forceHeight=0.065, items=self.groupWidgets ) self.scrollTitle = DirectFrame(parent=self.scrollList, text=TTLocalizer.GroupTrackerListTitle, text_scale=0.06, text_align=TextNode.ACenter, relief=None, pos=(self.buttonXstart, 0, self.itemFrameZorigin + 0.127) ) self.playerList = DirectScrolledList(parent=self, relief=None, pos=(0.45, 0, 0.1), incButton_image=(self.gui.find('**/FndsLst_ScrollUp'), self.gui.find('**/FndsLst_ScrollDN'), self.gui.find('**/FndsLst_ScrollUp_Rllvr'), self.gui.find('**/FndsLst_ScrollUp') ), incButton_relief=None, incButton_scale=(1.0, 1.0, -1.0), incButton_pos=(0, 0, -0.28), incButton_image3_color=Vec4(1, 1, 1, 0.05), decButton_image=(self.gui.find('**/FndsLst_ScrollUp'), self.gui.find('**/FndsLst_ScrollDN'), self.gui.find('**/FndsLst_ScrollUp_Rllvr'), self.gui.find('**/FndsLst_ScrollUp') ), decButton_relief=None, decButton_scale=(1.0, 1.0, 1.0), decButton_pos=(0.0, 0, 0.04), decButton_image3_color=Vec4(1, 1, 1, 0.25), itemFrame_pos=(0, 0, -0.05), itemFrame_scale=1.0, itemFrame_relief=DGG.SUNKEN, itemFrame_frameSize=(-0.3, 0.3, #x -0.2, 0.06), #z itemFrame_frameColor=(0.85, 0.95, 1, 1), itemFrame_borderWidth=(0.01, 0.01), numItemsVisible=4, forceHeight=0.05, items=self.playerWidgets ) self.playerListTitle = DirectFrame(parent=self.playerList, text='', text_scale=0.05, text_align=TextNode.ACenter, relief=None, pos=(0, 0, 0.08) ) self.groupInfoTitle = DirectLabel(parent=self, text='', text_scale=0.080, text_align=TextNode.ACenter, text_wordwrap=15, relief=None, pos=(0.45, 0, 0.5)) self.groupInfoDistrict = DirectLabel(parent=self, text='', text_scale=0.050, text_align=TextNode.ACenter, text_wordwrap=15, relief=None, pos=(0.45, 0, 0.4) ) self.statusMessage = DirectLabel(parent=self, text='', text_scale=0.060, text_align=TextNode.ACenter, text_wordwrap=5, relief=None, pos=(0.45,0,0.1)) # Group Image: self.groupIcon = DirectButton(parent=self, relief=None, state=DGG.DISABLED, image=None, image_scale=(0.35, 1, 0.35), image_color=Vec4(1.0, 1.0, 1.0, 0.75), pos=(0.45, 10, -0.45), command=self.doNothing) # Group Toggle: self.wantGroupToggle = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=(0.7, 1, 1), text='', text_scale=0.052, text_pos=(0, -0.02), pos=(0.2, 0, -0.65), command=self.toggleWantGroup) self.updateWantGroupButton() # Loading possible group icons suitIcons = loader.loadModel('phase_3/models/gui/cog_icons') bossbotIcon = suitIcons.find('**/CorpIcon') bossbotIcon.setColor(SUIT_ICON_COLORS[0]) self.images.append(bossbotIcon) lawbotIcon = suitIcons.find('**/LegalIcon') lawbotIcon.setColor(SUIT_ICON_COLORS[1]) self.images.append(lawbotIcon) cashbotIcon = suitIcons.find('**/MoneyIcon') cashbotIcon.setColor(SUIT_ICON_COLORS[2]) self.images.append(cashbotIcon) sellbotIcon = suitIcons.find('**/SalesIcon') sellbotIcon.setColor(SUIT_ICON_COLORS[3]) self.images.append(sellbotIcon) # Clean up self.clearGroupInfo() self.statusMessage.hide() suitIcons.removeNode() self.gui.removeNode() guiButton.removeNode() self.accept('GroupTrackerResponse', self.updatePage) def unload(self): self.scrollList.destroy() self.groupInfoDistrict.destroy() self.playerList.destroy() self.groupInfoTitle.destroy() self.groupIcon.destroy() self.wantGroupToggle.destroy() for widget in self.playerWidgets: widget.destroy() for widget in self.groupWidgets: widget.destroy() self.playerWidgets = [] del self.scrollList del self.groupInfoDistrict del self.playerList del self.groupInfoTitle del self.groupIcon del self.wantGroupToggle ShtikerPage.ShtikerPage.unload(self) def enter(self): ShtikerPage.ShtikerPage.enter(self) self.setGroups([]) # CLEAR IT ALL self.setPlayers() # CLEAR IT ALL if(self.scrollList['items'] == []): self.statusMessage['text'] = TTLocalizer.GroupTrackerLoading self.statusMessage.show() base.cr.globalGroupTracker.requestGroups() taskMgr.doMethodLater(3, self.displayNoGroupsTaskHandler, self.uniqueName('timeout')) def displayNoGroups(self): self.statusMessage['text'] = TTLocalizer.GroupTrackerEmpty self.statusMessage.show() self.clearGroupInfo() def displayNoGroupsTaskHandler(self, task): self.displayNoGroups() return task.done def updatePage(self): taskMgr.remove(self.uniqueName('timeout')) groups = base.cr.globalGroupTracker.getGroupInfo() self.setGroups(groups) def exit(self): self.clearGroupInfo() ShtikerPage.ShtikerPage.exit(self) base.cr.globalGroupTracker.doneRequesting() def updateGroupInfoEventHandle(self, groupWidget, mouseEvent): self.updateGroupInfo(groupWidget) def updateGroupInfo(self, groupWidget): ''' Updates the Right Page of the Group Tracker Page with new Info ''' self.statusMessage.hide() # Update the Player List self.setPlayers(groupWidget) self.playerList.show() # Update the Player List Title self.playerListTitle['text'] = ('Players ' + str(groupWidget.getCurrentPlayers()) + '/' + str(groupWidget.getMaxPlayers()) + ':') self.playerListTitle.show() # Update the District self.groupInfoDistrict['text'] = TTLocalizer.BoardingGroupDistrictInformation % { 'district' : groupWidget.getDistrict() } self.groupInfoDistrict.show() # Update the Title self.groupInfoTitle['text'] = groupWidget.getTitle() self.groupInfoTitle.show() # Update the Image self.groupIcon['image'] = self.images[GroupTrackerGlobals.CATEGORY_TO_IMAGE_ID[groupWidget.getCategory()]] self.groupIcon['image_scale'] = (0.35, 1, 0.35) self.groupIcon.show() def clearGroupInfo(self): self.playerList.hide() self.playerListTitle.hide() self.groupInfoDistrict.hide() self.groupInfoTitle.hide() self.groupIcon.hide() def setPlayers(self, groupWidget=None): ''' Calls updatePlayerList ''' # Clear the Widgets that were held in the listings for playerWidget in self.playerWidgets: playerWidget.destroy() self.playerWidgets = [] # Make a player widget for each player # TODO: Edit this stuff when avIds come from players if groupWidget: leaderId = groupWidget.getLeaderId() playerNames = groupWidget.getMemberNames() playerIds = groupWidget.getMemberIds() for playerName in playerNames: playerId = playerIds[playerNames.index(playerName)] isLeader = playerId == leaderId self.playerWidgets.append(GroupTrackerPlayer(parent=self, avId=playerId, name=playerName, isLeader=isLeader)) self.updatePlayerList() def reconsiderGroupInfo(self, groupWidget): ''' If someone is viewing this info and it was updated, we also want to update the info being viewed ''' if self.playerWidgets is None or self.playerList['items'] == []: return # No Info is being viewed at the moment since you cant have an empty group # We have to update if this group's leader is the leader in the playerlist being viewed right now leaderId = groupWidget.getLeaderId() # Check all the players in the playerList being viewed for the same leader for playerWidget in self.playerWidgets: if playerWidget.getLeader(): if leaderId == playerWidget.getId(): self.updateGroupInfo(groupWidget) return False return True def setGroups(self, groups): ''' Calls updateGroupList ''' # Clear our Group Widgets for group in self.groupWidgets: group.destroy() self.groupWidgets = [] wantReconsiderInfo = True # Create a new group widget for each group for group in groups: if not group[GroupTrackerGlobals.SHOW] or len(group[GroupTrackerGlobals.MEMBER_IDS]) == 0: continue # We are using this to see if this group is dead or if someone doesnt want it up leaderId = 0 for i, g in base.cr.globalGroupTracker.leader2Group.items(): if g == group: leaderId = i if not leaderId: continue leaderName = group[GroupTrackerGlobals.LEADER_NAME] shardName = group[GroupTrackerGlobals.SHARD_NAME] category = group[GroupTrackerGlobals.CATEGORY] memberIds = group[GroupTrackerGlobals.MEMBER_IDS] memberNames = group[GroupTrackerGlobals.MEMBER_NAMES] groupWidget = GroupTrackerGroup(parent=self, leaderId=leaderId, leaderName=leaderName, shardName=shardName, category=category, memberIds=memberIds, memberNames=memberNames) groupWidget.bind(DGG.WITHIN, self.updateGroupInfoEventHandle, extraArgs=[groupWidget]) self.groupWidgets.append(groupWidget) if wantReconsiderInfo: wantReconsiderInfo = self.reconsiderGroupInfo(groupWidget) # Edge case where a group that was removed, info might remain on the screen if it didn't exist any more if wantReconsiderInfo: self.clearGroupInfo() # There are no groups, hide the information if len(self.groupWidgets) == 0: self.displayNoGroups() self.updateGroupList() def updateGroupList(self): self.statusMessage.hide() if self.scrollList is None: return # Clear the Group Listing for item in self.scrollList['items']: if item: self.scrollList.removeItem(item, refresh=True) self.scrollList['items'] = [] # Re-populate the Group Listing for groupWidget in self.groupWidgets: self.scrollList.addItem(groupWidget, refresh=True) if len(self.groupWidgets) == 0: self.displayNoGroups() def updatePlayerList(self): if self.playerList is None: return # Clear the Player Listing for item in self.playerList['items']: if item: self.playerList.removeItem(item) self.playerList['items'] = [] # Re-Populate the List for playerWidget in self.playerWidgets: self.playerList.addItem(playerWidget) def toggleWantGroup(self): if settings.get('grouptracker', False): settings['grouptracker'] = False base.cr.globalGroupTracker.showMe(False) else: settings['grouptracker'] = True base.cr.globalGroupTracker.showMe(True) base.localAvatar.wantGroupTracker() base.localAvatar.wantGroupTracker() # Updates the ai toon so the boarding group AI could know what he wants self.updateWantGroupButton() def updateWantGroupButton(self): if settings.get('grouptracker', False): self.wantGroupToggle['text'] = 'Hide Me' else: self.wantGroupToggle['text'] = 'Show Me' def doNothing(self): pass
class IsisAgent(kinematicCharacterController, DirectObject): @classmethod def setPhysics(cls, physics): """ This method is set in src.loader when the generators are loaded into the namespace. This frees the environment definitions (in scenario files) from having to pass around the physics parameter that is required for all IsisObjects """ cls.physics = physics def __init__(self, name, queueSize=100): # load the model and the different animations for the model into an Actor object. self.actor = Actor("media/models/boxman", { "walk": "media/models/boxman-walk", "idle": "media/models/boxman-idle" }) self.actor.setScale(1.0) self.actor.setH(0) #self.actor.setLODAnimation(10,5,2) # slows animation framerate when actor is far from camera, if you can figure out reasonable params self.actor.setColorScale(random.random(), random.random(), random.random(), 1.0) self.actorNodePath = NodePath('agent-%s' % name) self.activeModel = self.actorNodePath self.actorNodePath.reparentTo(render) self.actor.reparentTo(self.actorNodePath) self.name = name self.isMoving = False # initialize ODE controller kinematicCharacterController.__init__(self, IsisAgent.physics, self.actorNodePath) self.setGeomPos(self.actorNodePath.getPos(render)) """ Additional Direct Object that I use for convenience. """ self.specialDirectObject = DirectObject() """ How high above the center of the capsule you want the camera to be when walking and when crouching. It's related to the values in KCC. """ self.walkCamH = 0.7 self.crouchCamH = 0.2 self.camH = self.walkCamH """ This tells the Player Controller what we're aiming at. """ self.aimed = None self.isSitting = False self.isDisabled = False """ The special direct object is used for trigger messages and the like. """ #self.specialDirectObject.accept("ladder_trigger_enter", self.setFly, [True]) #self.specialDirectObject.accept("ladder_trigger_exit", self.setFly, [False]) self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"]) # Expose agent's right hand joint to attach objects to self.player_right_hand = self.actor.exposeJoint( None, 'modelRoot', 'Hand.R') self.player_left_hand = self.actor.exposeJoint(None, 'modelRoot', 'Hand.L') self.right_hand_holding_object = None self.left_hand_holding_object = None # don't change the color of things you pick up self.player_right_hand.setColorScaleOff() self.player_left_hand.setColorScaleOff() self.player_head = self.actor.exposeJoint(None, 'modelRoot', 'Head') self.neck = self.actor.controlJoint(None, 'modelRoot', 'Head') self.controlMap = { "turn_left": 0, "turn_right": 0, "move_forward": 0, "move_backward": 0, "move_right": 0, "move_left": 0, "look_up": 0, "look_down": 0, "look_left": 0, "look_right": 0, "jump": 0 } # see update method for uses, indices are [turn left, turn right, move_forward, move_back, move_right, move_left, look_up, look_down, look_right, look_left] # turns are in degrees per second, moves are in units per second self.speeds = [270, 270, 5, 5, 5, 5, 60, 60, 60, 60] self.originalPos = self.actor.getPos() bubble = loader.loadTexture("media/textures/thought_bubble.png") #bubble.setTransparency(TransparencyAttrib.MAlpha) self.speech_bubble = DirectLabel(parent=self.actor, text="", text_wordwrap=10, pad=(3, 3), relief=None, text_scale=(.3, .3), pos=(0, 0, 3.6), frameColor=(.6, .2, .1, .5), textMayChange=1, text_frame=(0, 0, 0, 1), text_bg=(1, 1, 1, 1)) #self.myImage= self.speech_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.speech_bubble.setColorScaleOff() self.speech_bubble.component('text0').textNode.setCardDecal(1) self.speech_bubble.setBillboardAxis() # hide the speech bubble from IsisAgent's own camera self.speech_bubble.hide(BitMask32.bit(1)) self.thought_bubble = DirectLabel(parent=self.actor, text="", text_wordwrap=9, text_frame=(1, 0, -2, 1), text_pos=(0, .5), text_bg=(1, 1, 1, 0), relief=None, frameSize=(0, 1.5, -2, 3), text_scale=(.18, .18), pos=(0, 0.2, 3.6), textMayChange=1, image=bubble, image_pos=(0, 0.1, 0), sortOrder=5) self.thought_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.thought_bubble.setColorScaleOff() self.thought_bubble.component('text0').textNode.setFrameColor( 1, 1, 1, 0) self.thought_bubble.component('text0').textNode.setFrameAsMargin( 0.1, 0.1, 0.1, 0.1) self.thought_bubble.component('text0').textNode.setCardDecal(1) self.thought_bubble.setBillboardAxis() # hide the thought bubble from IsisAgent's own camera self.thought_bubble.hide(BitMask32.bit(1)) # disable by default self.thought_bubble.hide() self.thought_filter = {} # only show thoughts whose values are in here self.last_spoke = 0 # timers to keep track of last thought/speech and self.last_thought = 0 # hide visualizations # put a camera on ralph self.fov = NodePath(Camera('RaphViz')) self.fov.node().setCameraMask(BitMask32.bit(1)) # position the camera to be infront of Boxman's face. self.fov.reparentTo(self.player_head) # x,y,z are not in standard orientation when parented to player-Head self.fov.setPos(0, 0.2, 0) # if P=0, canrea is looking directly up. 90 is back of head. -90 is on face. self.fov.setHpr(0, -90, 0) lens = self.fov.node().getLens() lens.setFov(60) # degree field of view (expanded from 40) lens.setNear(0.2) #self.fov.node().showFrustum() # displays a box around his head #self.fov.place() self.prevtime = 0 self.current_frame_count = 0 self.isSitting = False self.isDisabled = False self.msg = None self.actorNodePath.setPythonTag("agent", self) # Initialize the action queue, with a maximum length of queueSize self.queue = [] self.queueSize = queueSize self.lastSense = 0 def setLayout(self, layout): """ Dummy method called by spatial methods for use with objects. Doesn't make sense for an agent that can move around.""" pass def setPos(self, pos): """ Wrapper to set the position of the ODE geometry, which in turn sets the visual model's geometry the next time the update() method is called. """ self.setGeomPos(pos) def setPosition(self, pos): self.setPos(pos) def reparentTo(self, parent): self.actorNodePath.reparentTo(parent) def setControl(self, control, value): """Set the state of one of the character's movement controls. """ self.controlMap[control] = value def get_objects_in_field_of_vision(self, exclude=['isisobject']): """ This works in an x-ray style. Fast. Works best if you listen to http://en.wikipedia.org/wiki/Rock_Art_and_the_X-Ray_Style while you use it. needs to exclude isisobjects since they cannot be serialized """ objects = {} for obj in base.render.findAllMatches("**/IsisObject*"): if not obj.hasPythonTag("isisobj"): continue o = obj.getPythonTag("isisobj") bounds = o.activeModel.getBounds() bounds.xform(o.activeModel.getMat(self.fov)) if self.fov.node().isInView(o.activeModel.getPos(self.fov)): pos = o.activeModel.getPos(render) pos = (pos[0], pos[1], pos[2] + o.getHeight() / 2) p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) object_dict = {} if 'x_pos' not in exclude: object_dict['x_pos'] = p3[0] if 'y_pos' not in exclude: object_dict['y_pos'] = p3[2] if 'distance' not in exclude: object_dict['distance'] = o.activeModel.getDistance( self.fov) if 'orientation' not in exclude: object_dict['orientation'] = o.activeModel.getH(self.fov) if 'actions' not in exclude: object_dict['actions'] = o.list_actions() if 'isisobject' not in exclude: object_dict['isisobject'] = o # add item to dinctionary objects[o] = object_dict return objects def get_agents_in_field_of_vision(self): """ This works in an x-ray vision style as well""" agents = {} for agent in base.render.findAllMatches("**/agent-*"): if not agent.hasPythonTag("agent"): continue a = agent.getPythonTag("agent") bounds = a.actorNodePath.getBounds() bounds.xform(a.actorNodePath.getMat(self.fov)) pos = a.actorNodePath.getPos(self.fov) if self.fov.node().isInView(pos): p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) agentDict = {'x_pos': p3[0],\ 'y_pos': p3[2],\ 'distance':a.actorNodePath.getDistance(self.fov),\ 'orientation': a.actorNodePath.getH(self.fov)} agents[a] = agentDict return agents def in_view(self, isisobj): """ Returns true iff a particular isisobject is in view """ return len( filter(lambda x: x['isisobject'] == isisobj, self.get_objects_in_field_of_vision(exclude=[]).values())) def get_objects_in_view(self): """ Gets objects through ray tracing. Slow""" return self.picker.get_objects_in_view() def control__turn_left__start(self, speed=None): self.setControl("turn_left", 1) self.setControl("turn_right", 0) if speed: self.speeds[0] = speed return "success" def control__turn_left__stop(self): self.setControl("turn_left", 0) return "success" def control__turn_right__start(self, speed=None): self.setControl("turn_left", 0) self.setControl("turn_right", 1) if speed: self.speeds[1] = speed return "success" def control__turn_right__stop(self): self.setControl("turn_right", 0) return "success" def control__move_forward__start(self, speed=None): self.setControl("move_forward", 1) self.setControl("move_backward", 0) if speed: self.speeds[2] = speed return "success" def control__move_forward__stop(self): self.setControl("move_forward", 0) return "success" def control__move_backward__start(self, speed=None): self.setControl("move_forward", 0) self.setControl("move_backward", 1) if speed: self.speeds[3] = speed return "success" def control__move_backward__stop(self): self.setControl("move_backward", 0) return "success" def control__move_left__start(self, speed=None): self.setControl("move_left", 1) self.setControl("move_right", 0) if speed: self.speeds[4] = speed return "success" def control__move_left__stop(self): self.setControl("move_left", 0) return "success" def control__move_right__start(self, speed=None): self.setControl("move_right", 1) self.setControl("move_left", 0) if speed: self.speeds[5] = speed return "success" def control__move_right__stop(self): self.setControl("move_right", 0) return "success" def control__look_left__start(self, speed=None): self.setControl("look_left", 1) self.setControl("look_right", 0) if speed: self.speeds[9] = speed return "success" def control__look_left__stop(self): self.setControl("look_left", 0) return "success" def control__look_right__start(self, speed=None): self.setControl("look_right", 1) self.setControl("look_left", 0) if speed: self.speeds[8] = speed return "success" def control__look_right__stop(self): self.setControl("look_right", 0) return "success" def control__look_up__start(self, speed=None): self.setControl("look_up", 1) self.setControl("look_down", 0) if speed: self.speeds[6] = speed return "success" def control__look_up__stop(self): self.setControl("look_up", 0) return "success" def control__look_down__start(self, speed=None): self.setControl("look_down", 1) self.setControl("look_up", 0) if speed: self.speeds[7] = speed return "success" def control__look_down__stop(self): self.setControl("look_down", 0) return "success" def control__jump(self): self.setControl("jump", 1) return "success" def control__view_objects(self): """ calls a raytrace to to all objects in view """ objects = self.get_objects_in_field_of_vision() self.control__say( "If I were wearing x-ray glasses, I could see %i items" % len(objects)) print "Objects in view:", objects return objects def control__sense(self): """ perceives the world, returns percepts dict """ percepts = dict() # eyes: visual matricies #percepts['vision'] = self.sense__get_vision() # objects in purview (cheating object recognition) percepts['objects'] = self.sense__get_objects() # global position in environment - our robots can have GPS :) percepts['position'] = self.sense__get_position() # language: get last utterances that were typed percepts['language'] = self.sense__get_utterances() # agents: returns a map of agents to a list of actions that have been sensed percepts['agents'] = self.sense__get_agents() print percepts return percepts def control__think(self, message, layer=0): """ Changes the contents of an agent's thought bubble""" # only say things that are checked in the controller if self.thought_filter.has_key(layer): self.thought_bubble.show() self.thought_bubble['text'] = message #self.thought_bubble.component('text0').textNode.setShadow(0.05, 0.05) #self.thought_bubble.component('text0').textNode.setShadowColor(self.thought_filter[layer]) self.last_thought = 0 return "success" def control__say(self, message="Hello!"): self.speech_bubble['text'] = message self.last_spoke = 0 return "success" """ Methods explicitly for IsisScenario files """ def put_in_front_of(self, isisobj): # find open direction pos = isisobj.getGeomPos() direction = render.getRelativeVector(isisobj, Vec3(0, 1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], [isisobj.geom]) print "CLOSEST", closestEntry, closestObject if closestObject == None: self.setPosition(pos + Vec3(0, 2, 0)) else: print "CANNOT PLACE IN FRONT OF %s BECAUSE %s IS THERE" % ( isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(0, -1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], [isisobj.geom]) if closestEntry == None: self.setPosition(pos + Vec3(0, -2, 0)) else: print "CANNOT PLACE BEHIND %s BECAUSE %s IS THERE" % ( isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(1, 0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], [isisobj.geom]) if closestEntry == None: self.setPosition(pos + Vec3(2, 0, 0)) else: print "CANNOT PLACE TO LEFT OF %s BECAUSE %s IS THERE" % ( isisobj, closestObject) # there's only one option left, do it anyway self.setPosition(pos + Vec3(-2, 0, 0)) # rotate agent to look at it self.actorNodePath.setPos(self.getGeomPos()) self.actorNodePath.lookAt(pos) self.setH(self.actorNodePath.getH()) def put_in_right_hand(self, target): return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) def put_in_left_hand(self, target): return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) def __get_object_in_center_of_view(self): direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.fov.getPos(render) exclude = [ ] #[base.render.find("**/kitchenNode*").getPythonTag("isisobj").geom] closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], exclude) return closestObject def pick_object_up_with(self, target, hand_slot, hand_joint): """ Attaches an IsisObject, target, to the hand joint. Does not check anything first, other than the fact that the hand joint is not currently holding something else.""" if hand_slot != None: print 'already holding ' + hand_slot.getName() + '.' return None else: if target.layout: target.layout.remove(target) target.layout = None # store original position target.originalHpr = target.getHpr(render) target.disable() #turn off physics if target.body: target.body.setGravityMode(0) target.reparentTo(hand_joint) target.setPosition(hand_joint.getPos(render)) target.setTag('heldBy', self.name) if hand_joint == self.player_right_hand: self.right_hand_holding_object = target elif hand_joint == self.player_left_hand: self.left_hand_holding_object = target hand_slot = target return target def control__pick_up_with_right_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return "error: no target in reach" else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with right hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) else: print 'object (' + target.name + ') is not graspable (i.e. in view and close enough).' return 'error: object not graspable' def control__pick_up_with_left_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with left hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) else: print 'object (' + target.name + ') is not graspable (i.e. in view and close enough).' return 'error: object not graspable' def control__drop_from_right_hand(self): print "attempting to drop object from right hand.\n" if self.right_hand_holding_object is None: print 'right hand is not holding an object.' return False if self.right_hand_holding_object.getNetTag('heldBy') == self.name: self.right_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_right_hand.getPos(render) heldPos = self.right_hand_holding_object.geom.getPosition() self.right_hand_holding_object.setPosition(pos) self.right_hand_holding_object.synchPosQuatToNode() self.right_hand_holding_object.setTag('heldBy', '') self.right_hand_holding_object.setRotation( self.right_hand_holding_object.originalHpr) self.right_hand_holding_object.enable() if self.right_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.right_hand_holding_object.body.setGravityMode(1) self.right_hand_holding_object.getBody().setForce( quat.xform(Vec3(0, force, 0))) self.right_hand_holding_object = None return 'success' else: return "Error: not being held by agent %s" % (self.name) def control__drop_from_left_hand(self): print "attempting to drop object from left hand.\n" if self.left_hand_holding_object is None: return 'left hand is not holding an object.' if self.left_hand_holding_object.getNetTag('heldBy') == self.name: self.left_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_left_hand.getPos(render) heldPos = self.left_hand_holding_object.geom.getPosition() self.left_hand_holding_object.setPosition(pos) self.left_hand_holding_object.synchPosQuatToNode() self.left_hand_holding_object.setTag('heldBy', '') self.left_hand_holding_object.setRotation( self.left_hand_holding_object.originalHpr) self.left_hand_holding_object.enable() if self.left_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.left_hand_holding_object.body.setGravityMode(1) self.left_hand_holding_object.getBody().setForce( quat.xform(Vec3(0, force, 0))) self.left_hand_holding_object = None return 'success' else: return "Error: not being held by agent %s" % (self.name) def control__use_right_hand(self, target=None, action=None): # TODO, rename this to use object with if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag('isisobj') print "Trying to use object", target if self.can_grasp(target): if (target.call(self, action, self.right_hand_holding_object) or (self.right_hand_holding_object and self.right_hand_holding_object.call(self, action, target))): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def control__use_left_hand(self, target=None, action=None): if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag('isisobj') if self.can_grasp(target): if (target.call(self, action, self.left_hand_holding_object) or (self.left_hand_holding_object and self.left_hand_holding_object.call(self, action, target))): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def can_grasp(self, isisobject): distance = isisobject.activeModel.getDistance(self.fov) print "distance = ", distance return distance < 5.0 def is_holding(self, object_name): return ((self.left_hand_holding_object and (self.left_hand_holding_object.getPythonTag('isisobj').name == object_name)) \ or (self.right_hand_holding_object and (self.right_hand_holding_object.getPythonTag('isisobj').name == object_name))) def empty_hand(self): if (self.left_hand_holding_object is None): return self.player_left_hand elif (self.right_hand_holding_object is None): return self.player_right_hand return False def has_empty_hand(self): return (self.empty_hand() is not False) def control__use_aimed(self): """ Try to use the object that we aim at, by calling its callback method. """ target = self.__get_object_in_center_of_view() if target.selectionCallback: target.selectionCallback(self, dir) return "success" def sense__get_position(self): x, y, z = self.actorNodePath.getPos() h, p, r = self.actorNodePath.getHpr() #FIXME # neck is not positioned in Blockman nh,np,nr = self.agents[agent_id].actor_neck.getHpr() left_hand_obj = "" right_hand_obj = "" if self.left_hand_holding_object: left_hand_obj = self.left_hand_holding_object.getName() if self.right_hand_holding_object: right_hand_obj = self.right_hand_holding_object.getName() return {'body_x': x, 'body_y': y, 'body_z': z,'body_h':h,\ 'body_p': p, 'body_r': r, 'in_left_hand': left_hand_obj, 'in_right_hand':right_hand_obj} def sense__get_vision(self): self.fov.node().saveScreenshot("temp.jpg") image = Image.open("temp.jpg") os.remove("temp.jpg") return image def sense__get_objects(self): return dict([x.getName(), y] for (x, y) in self.get_objects_in_field_of_vision().items()) def sense__get_agents(self): curSense = time() agents = {} for k, v in self.get_agents_in_field_of_vision().items(): v['actions'] = k.get_other_agents_actions(self.lastSense, curSense) agents[k.name] = v self.lastSense = curSense return agents def sense__get_utterances(self): """ Clear out the buffer of things that the teacher has typed, FIXME: this doesn't work right now """ return [] utterances = self.teacher_utterances self.teacher_utterances = [] return utterances def debug__print_objects(self): text = "Objects in FOV: " + ", ".join(self.sense__get_objects().keys()) print text def add_action_to_history(self, action, args, result=0): self.queue.append((time(), action, args, result)) if len(self.queue) > self.queueSize: self.queue.pop(0) def get_other_agents_actions(self, start=0, end=None): if not end: end = time() actions = [] for act in self.queue: if act[0] >= start: if act[0] < end: actions.append(act) else: break return actions def update(self, stepSize=0.1): self.speed = [0.0, 0.0] self.actorNodePath.setPos(self.geom.getPosition() + Vec3(0, 0, -0.70)) self.actorNodePath.setQuat(self.getQuat()) # the values in self.speeds are used as coefficientes for turns and movements if (self.controlMap["turn_left"] != 0): self.addToH(stepSize * self.speeds[0]) if (self.controlMap["turn_right"] != 0): self.addToH(-stepSize * self.speeds[1]) if self.verticalState == 'ground': # these actions require contact with the ground if (self.controlMap["move_forward"] != 0): self.speed[1] = self.speeds[2] if (self.controlMap["move_backward"] != 0): self.speed[1] = -self.speeds[3] if (self.controlMap["move_left"] != 0): self.speed[0] = -self.speeds[4] if (self.controlMap["move_right"] != 0): self.speed[0] = self.speeds[5] if (self.controlMap["jump"] != 0): kinematicCharacterController.jump(self) # one jump at a time! self.controlMap["jump"] = 0 if (self.controlMap["look_left"] != 0): self.neck.setR(bound(self.neck.getR(), -60, 60) + stepSize * 80) if (self.controlMap["look_right"] != 0): self.neck.setR(bound(self.neck.getR(), -60, 60) - stepSize * 80) if (self.controlMap["look_up"] != 0): self.neck.setP(bound(self.neck.getP(), -60, 80) + stepSize * 80) if (self.controlMap["look_down"] != 0): self.neck.setP(bound(self.neck.getP(), -60, 80) - stepSize * 80) kinematicCharacterController.update(self, stepSize) """ Update the held object position to be in the hands """ if self.right_hand_holding_object != None: self.right_hand_holding_object.setPosition( self.player_right_hand.getPos(render)) if self.left_hand_holding_object != None: self.left_hand_holding_object.setPosition( self.player_left_hand.getPos(render)) #Update the dialog box and thought windows #This allows dialogue window to gradually decay (changing transparancy) and then disappear self.last_spoke += stepSize / 2 self.last_thought += stepSize / 2 self.speech_bubble['text_bg'] = (1, 1, 1, 1 / (self.last_spoke + 0.01)) self.speech_bubble['frameColor'] = (.6, .2, .1, .5 / (self.last_spoke + 0.01)) if self.last_spoke > 2: self.speech_bubble['text'] = "" if self.last_thought > 1: self.thought_bubble.hide() # If the character is moving, loop the run animation. # If he is standing still, stop the animation. if (self.controlMap["move_forward"] != 0) or (self.controlMap["move_backward"] != 0) or (self.controlMap["move_left"] != 0) or (self.controlMap["move_right"] != 0): if self.isMoving is False: self.isMoving = True else: if self.isMoving: self.current_frame_count = 5.0 self.isMoving = False total_frame_num = self.actor.getNumFrames('walk') if self.isMoving: self.current_frame_count = self.current_frame_count + (stepSize * 250.0) if self.current_frame_count > total_frame_num: self.current_frame_count = self.current_frame_count % total_frame_num self.actor.pose('walk', self.current_frame_count) elif self.current_frame_count != 0: self.current_frame_count = 0 self.actor.pose('idle', 0) return Task.cont def destroy(self): self.disable() self.specialDirectObject.ignoreAll() self.actorNodePath.removeNode() del self.specialDirectObject kinematicCharacterController.destroy(self) def disable(self): self.isDisabled = True self.geom.disable() self.footRay.disable() def enable(self): self.footRay.enable() self.geom.enable() self.isDisabled = False """ Set camera to correct height above the center of the capsule when crouching and when standing up. """ def crouch(self): kinematicCharacterController.crouch(self) self.camH = self.crouchCamH def crouchStop(self): """ Only change the camera's placement when the KCC allows standing up. See the KCC to find out why it might not allow it. """ if kinematicCharacterController.crouchStop(self): self.camH = self.walkCamH
class Menu(DirectObject): def __init__(self): """Default constructor""" # load the default fonts #self.defaultFont = loader.loadFont("gui/fonts/UbuntuBold") #self.defaultFontRegular = loader.loadFont("gui/fonts/UbuntuRegular") # load the default button image map self.defaultBtnMaps = base.loader.loadModel( "gui/buttons/mainMenu/button_maps") # this button can be created with the createBackButton function self.btnBack = None self.frameMain = DirectFrame( # size of the frame frameSize = (base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), # position of the frame pos = (0, 0, 0), # tramsparent bg color frameColor = (0, 0, 0, 0)) self.title = DirectLabel( scale = 0.25, pos = (0, 0, -0.25), frameColor = (0, 0, 0, 0), text = "Missing Title", text_align = TextNode.ACenter, text_fg = (1,1,1,1), #text_font = self.defaultFont ) self.title.reparentTo(base.a2dTopCenter) self.clock = DirectLabel( scale = 0.1, pos = (-.1,0,.1), frameColor = (0, 0, 0, 0), text = "00:00", text_align = TextNode.ARight, text_fg = (1,1,1,1)) self.clock.reparentTo(base.a2dBottomRight) self.hide() def showBase(self): """Show all GUI controls of the base menu""" self.accept("RatioChanged", self.recalcAspectRatio) self.frameMain.show() self.clock.show() self.title.show() if self.btnBack: self.btnBack.show() if not taskMgr.hasTaskNamed("clock"): taskMgr.add(self.clockTask, "clock") def hideBase(self): """Hide all GUI controls of the base menu""" self.ignore("RatioChanged") self.frameMain.hide() self.clock.hide() self.title.hide() if self.btnBack: self.btnBack.hide() if taskMgr.hasTaskNamed("clock"): taskMgr.remove("clock") def createBackButton(self, func): """Create the back button on the bottom left edge of the window""" self.btnBack = DirectButton( # size of the button scale = (0.25, 0.25, 0.25), # size of the text text_scale = (0.5*1.33, 0.5, 0.5), # the text on the button text = "ABC", # set the alignment to right text_align = TextNode.ARight, # put the text on the left side of the button text_pos = (4.1, -0.15), # set the text color to white text_fg = (1,1,1,1), # set the font of the text #text_font = self.defaultFont, # set the buttons images geom = (self.defaultBtnMaps.find("**/button_ready"), self.defaultBtnMaps.find("**/button_click"), self.defaultBtnMaps.find("**/button_rollover"), self.defaultBtnMaps.find("**/button_disabled")), # set no relief relief = 1, # make it transparent frameColor = (0,0,0,0), # No sink in when press pressEffect = False, # position on the window pos = (0.0, 0, 0.2), # the event which is thrown on clickSound command = func, # sounds that should be played rolloverSound = None, clickSound = None) self.btnBack.reparentTo(base.a2dBottomLeft) def clockTask(self, task): self.clock["text"] = time.strftime("%H:%M") return task.cont def recalcAspectRatio(self): """get the new aspect ratio to resize the mainframe""" self.frameMain["frameSize"] = ( base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom)
class ShopWindow(DirectFrame): def __init__(self, shop, image, wantTurretCount): DirectFrame.__init__(self, sortOrder=1) self.shop = shop self.wantTurretCount = wantTurretCount self.bgImage = image self.title = None self.okBtn = None self.clBtn = None self.infoLbl = None self.turretLabel = None self.turretImg = None self.isSetup = False self.turretCount = 0 # New variables for optimized shop. self.firstItemIndex = -1 self.btnPositions = [(-0.45, 0, 0), (-0.15, 0, 0), (0.15, 0, 0), (0.45, 0, 0)] self.page = Page(self.shop, self) self.itemButtons = [] self.itemButtons.append(ItemButton(self.page, self.btnPositions[0])) self.itemButtons.append(ItemButton(self.page, self.btnPositions[1])) self.itemButtons.append(ItemButton(self.page, self.btnPositions[2])) self.itemButtons.append(ItemButton(self.page, self.btnPositions[3])) self.newItems = None def setup(self, title='CHOOSE WHAT YOU WANT TO BUY'): font = CIGlobals.getMickeyFont() txtFg = (0, 0, 0, 1) txtScale = 0.05 txtPos = (0, -0.1) buttons = loader.loadModel('phase_3.5/models/gui/QT_buttons.bam') self.window = OnscreenImage(image=self.bgImage, scale=(0.9, 1, 0.7), parent=self) self.title = DirectLabel(text=title, relief=None, pos=(0, 0, 0.5), text_wordwrap=10, text_font=font, text_fg=(1, 1, 0, 1), scale=0.1, parent=self) # Let's update the turret count. self.updateTurretCount() self.infoLbl = DirectLabel(text='Welcome!', relief=None, text_scale=0.075, text_fg=txtFg, text_shadow=(0, 0, 0, 0), pos=(0, 0, 0.215)) self.okBtn = DirectButton(geom=CIGlobals.getOkayBtnGeom(), relief=None, text='OK', text_fg=txtFg, text_scale=txtScale, text_pos=txtPos, pos=(-0.1, 0, -0.5), parent=self) self.clBtn = DirectButton(geom=CIGlobals.getCancelBtnGeom(), relief=None, text='Cancel', text_fg=txtFg, text_scale=txtScale, text_pos=txtPos, pos=(0.1, 0, -0.5), parent=self) buttonGeom = (buttons.find('**/QT_back'), buttons.find('**/QT_back'), buttons.find('**/QT_back'), buttons.find('**/QT_back')) self.backBtn = DirectButton(geom=buttonGeom, relief=None, scale=0.05, pos=(-0.3, 0, -0.25), parent=self, command=self.changePage, extraArgs=[0]) self.nextBtn = DirectButton(geom=buttonGeom, relief=None, scale=0.05, pos=(0.3, 0, -0.25), hpr=(0, 0, 180), command=self.changePage, extraArgs=[1], parent=self) self.hideInfo() def setTurrets(self, amount): if self.shop.upgradesPurchased: amount += 1 self.turretCount = amount self.updatePage() def updateTurretCount(self): if self.turretLabel: self.turretLabel.destroy() if self.wantTurretCount: maxTurrets = CogBattleGlobals.MAX_TURRETS if not self.turretImg: self.turretImg = OnscreenImage( image="phase_3.5/maps/cannon-icon.png", scale=(0.05, 1, 0.05), pos=(-0.22, 0, 0.275)) self.turretImg.setTransparency(TransparencyAttrib.MAlpha) self.turretLabel = DirectLabel( text='Turrets: %s/%s' % (str(self.turretCount), str(maxTurrets)), relief=None, text_scale=0.07, text_fg=(0, 0, 0, 1), text_shadow=(0, 0, 0, 0), pos=(0, 0, 0.265)) def changePage(self, direction): var = (self.firstItemIndex - 4) if direction == 1: var = (self.firstItemIndex + 4) self.setBackBtn(True) self.setNextBtn(True) if (var - 4) < 0: self.setBackBtn(False) elif (var + 4) >= len(self.newItems): self.setNextBtn(False) self.firstItemIndex = var self.setupItems(begin=self.firstItemIndex) def initializeShop(self, items): newItems = dict(items) loadout = base.localAvatar.backpack.loadout # Let's show the loadout gags first in a full shop. if self.shop.wantFullShop: crcGags = OrderedDict(newItems) for item, values in newItems.items(): if values and values.get('type') == ItemType.GAG: gagId = base.cr.attackMgr.getAttackIDByName(item) hasGag = base.localAvatar.getBackpack().hasGag(gagId) if gagId not in loadout or not hasGag: del crcGags[item] if not hasGag: del newItems[item] else: del newItems[item] # Let's add back the other gags. crcGags.update(newItems) newItems = crcGags else: for item, values in newItems.items(): if values and values.get('type') == ItemType.GAG: gagId = base.localAvatar.getBackpack().hasGag(gagId) if gagId not in loadout or not base.localAvatar.getBackpack( ).hasGag(gagId): del newItems[item] self.newItems = newItems self.firstItemIndex = 0 self.setupItems() if len(newItems.keys()) <= 4: self.backBtn.hide() self.nextBtn.hide() self.setBackBtn(False) self.isSetup = True def setupItems(self, begin=0): for button in self.itemButtons: button.hide() button.label.hide() for i in xrange(4): item = self.newItems.keys()[begin + i] if (begin + i) < len( self.newItems.keys()) else None values = self.newItems.get(item) if item else None if item: button = self.itemButtons[i] button.setItem(item, values) button.update() def updatePage(self): battle = base.localAvatar.getBattleZone() if battle and self.wantTurretCount: self.shop.distShop.sendUpdate('requestTurretCount', []) self.updateTurretCount() for button in self.itemButtons: button.update() def setBackBtn(self, enabled): if self.backBtn: if enabled == False: self.backBtn.setColorScale(GRAYED_OUT_COLOR) self.backBtn['state'] = DGG.DISABLED else: self.backBtn.setColorScale(NORMAL_COLOR) self.backBtn['state'] = DGG.NORMAL def setNextBtn(self, enabled): if self.nextBtn: if enabled == False: self.nextBtn.setColorScale(GRAYED_OUT_COLOR) self.nextBtn['state'] = DGG.DISABLED else: self.nextBtn.setColorScale(NORMAL_COLOR) self.nextBtn['state'] = DGG.NORMAL def setOKCommand(self, command): if self.okBtn: self.okBtn['command'] = command def setCancelCommand(self, command): if self.clBtn: self.clBtn['command'] = command def showInfo(self, text, negative=0, duration=-1): self.infoLbl.show() if negative: self.infoLbl['text_fg'] = (0.9, 0, 0, 1) self.infoLbl['text_shadow'] = (0, 0, 0, 1) else: self.infoLbl['text_fg'] = (0, 0, 0, 1) self.infoLbl['text_shadow'] = (0, 0, 0, 0) self.infoLbl['text'] = text if duration > -1: Sequence(Wait(duration), Func(self.hideInfo)).start() def hideInfo(self): if self.infoLbl: self.infoLbl.hide() def delete(self): elements = [ self.title, self.okBtn, self.clBtn, self.infoLbl, self.backBtn, self.nextBtn, self.turretLabel, self.turretImg, self.page ] for element in elements: if element: element.destroy() del elements del self.page for button in self.itemButtons: button.destroy() self.itemButtons = None del self.itemButtons self.title = None self.okBtn = None self.clBtn = None self.infoLbl = None self.backBtn = None self.nextBtn = None self.bgImage = None self.turretLabel = None self.turretCount = None if self.window: self.window.destroy() self.window = None self.destroy()
class ItemButton(DirectButton): def __init__(self, page, pos): DirectButton.__init__(self, parent=page, relief=None, command=self.handleClick, pos=pos) self.window = page self.item = None self.values = None self.label = DirectLabel(text='', relief=None, parent=self, text_scale=0.05) self.label.initialiseoptions(DirectLabel) self.label.hide() self.hide() def setItem(self, item, values): if values: image = values.get('image') price = values.get('price') text = '' self.item = item self.values = values self['geom'] = image if values.get('type') == ItemType.GAG: gagId = base.cr.attackMgr.getAttackIDByName(item) supply = base.localAvatar.getBackpack().getSupply(gagId) maxSupply = base.localAvatar.getBackpack().getMaxSupply(gagId) self.setScale(1.3) self.label['text_scale'] = 0.05 self.label.setPos(0, 0, -0.11) self.setTransparency(TransparencyAttrib.MNone) elif values.get('type') == ItemType.UPGRADE: upgradeID = values.get('upgradeID') avID = base.localAvatar.getPUInventory()[1] supply = 0 maxSupply = values.get('maxUpgrades') battle = base.localAvatar.getBattleZone() if battle and battle.getTurretManager(): turret = battle.getTurretManager().getTurret() if turret and turret.getGagID() == upgradeID: supply = 1 if avID == upgradeID: dataSupply = base.localAvatar.getPUInventory()[0] if dataSupply > 0: supply = dataSupply self.setScale(0.15) self.label['text_scale'] = 0.3 self.label.setPos(0, 0, -1.2) self.setTransparency(TransparencyAttrib.MNone) elif values.get('type') == ItemType.HEAL: text = '%s\n%s JBS' % ( item, price) if 'showTitle' in values else item self.setTransparency(TransparencyAttrib.MAlpha) self.setScale(0.105) self.label['text_scale'] = 0.55 self.label.setPos(0, 0, -1.6) text = text if text else '%s/%s\n%s JBS' % ( str(supply), str(maxSupply), str(price)) self.label['text'] = text self.label.initialiseoptions(DirectLabel) self.initialiseoptions(ItemButton) self.label.show() self.show() def update(self): money = base.localAvatar.getMoney() if self.values: itemType = self.values.get('type') price = self.values.get('price') self.setColorScale(NORMAL_COLOR) if price > money: self.setColorScale(GRAYED_OUT_COLOR) if itemType == ItemType.GAG: backpack = base.localAvatar.getBackpack() gagId = base.cr.attackMgr.getAttackIDByName(self.item) supply = backpack.getSupply(gagId) maxSupply = backpack.getMaxSupply(gagId) inBackpack = backpack.hasGag(gagId) if not inBackpack or inBackpack and supply >= maxSupply: self.setColorScale(GRAYED_OUT_COLOR) self.label['text'] = '%s/%s\n%s JBS' % ( str(supply), str(maxSupply), str(price)) elif itemType == ItemType.UPGRADE: maxSupply = self.values.get('maxUpgrades') upgradeID = self.values.get('upgradeID') avID = base.localAvatar.getPUInventory()[1] supply = 0 turretCount = 0 hasTurret = False battle = base.localAvatar.getBattleZone() if battle and battle.getTurretManager(): turretCount = battle.getTurretCount() turret = battle.getTurretManager().getTurret() if turret: hasTurret = True if turret.getGagID() == upgradeID: supply = 1 if avID == upgradeID: dataSupply = base.localAvatar.getPUInventory()[0] if dataSupply > 0: supply = dataSupply if supply > 0 or base.localAvatar.getPUInventory( )[0] > 0 or hasTurret or turretCount == CogBattleGlobals.MAX_TURRETS: self.setColorScale(GRAYED_OUT_COLOR) self.label['text'] = '%s\n%s/%s\n%s JBS' % ( self.item, str(supply), str(maxSupply), str(price)) elif itemType == ItemType.HEAL: if base.localAvatar.getHealth( ) == base.localAvatar.getMaxHealth() or self.shop.hasCooldown( self.item): self.setColorScale(GRAYED_OUT_COLOR) def handleClick(self): if self.item: self.window.shop.purchaseItem(self.item) def destroy(self): DirectFrame.destroy(self)
class OutingsGUI: """Outing dialogs GUI.""" def __init__(self): self.is_shown = False self._char_chooser = None self._outing_widgets = [] self._assignees = [] self._char_buttons = {} self._blink_step = 0 self._outing_snd = loader.loadSfx( "sounds/outing_event.ogg") # noqa: F821 self._upcome_ico = DirectFrame( frameSize=(-0.1, 0.1, -0.1, 0.1), pos=(0, 0, 0.8), frameTexture="gui/tex/looting.png", ) self._upcome_ico.setTransparency(TransparencyAttrib.MAlpha) self._upcome_ico.hide() self._upcome_text = DirectLabel( text="", text_font=base.main_font, # noqa: F821 frameSize=(0.4, 0.4, 0.4, 0.4), text_scale=0.04, text_fg=SILVER_COL, text_bg=(0, 0, 0, 0.5), pos=(0, 0, 0.65), ) self._upcome_text.hide() self._list = DirectFrame( frameSize=(-0.73, 0.73, -0.9, 0.9), frameTexture="gui/tex/paper1.png", state=DGG.NORMAL, ) self._list.setDepthTest(False) self._list.setTransparency(TransparencyAttrib.MAlpha) self._list.hide() self._name = DirectLabel( parent=self._list, text="", text_font=base.main_font, # noqa: F821 frameSize=(0.4, 0.4, 0.4, 0.4), text_scale=0.047, pos=(-0.4, 0, 0.7), ) self._type = DirectLabel( parent=self._list, text="", text_font=base.main_font, # noqa: F821 frameSize=(0.4, 0.4, 0.4, 0.4), text_scale=0.032, pos=(-0.13, 0, 0.699), ) self._desc = DirectLabel( parent=self._list, text="", text_font=base.main_font, # noqa: F821 frameSize=(0.6, 0.6, 0.6, 0.6), text_scale=0.037, pos=(0, 0, 0.55), ) def _assign_for_outing(self, to_send_wid, assignees): """Assign the chosen character for the outing. Args: to_send_wid (direct.gui.DirectLabel.DirectLabel): Widget with number of assigned characters. assignees (int): Assignees limit. """ char = base.common_ctrl.chosen_char # noqa: F821 if char is None or char in self._assignees or len( self._assignees) == assignees: return self._assignees.append(char) self._char_buttons[char.id].setX(0.35) to_send_wid["text"] = base.labels.OUTINGS_GUI[0].format( # noqa: F821 cur_as=str(len(self._assignees)), max_as=str(assignees)) def _unassign_for_outing(self, to_send_wid, assignees): """Exclude the chosen character from the outing. Args: to_send_wid (direct.gui.DirectLabel.DirectLabel): Widget with number of assigned characters. assignees (int): Assignees limit. """ char = base.common_ctrl.chosen_char # noqa: F821 if char not in self._assignees: return self._assignees.remove(char) self._char_buttons[char.id].setX(-0.35) to_send_wid["text"] = base.labels.OUTINGS_GUI[0].format( # noqa: F821 cur_as=str(len(self._assignees)), max_as=str(assignees)) def _blink_upcome_icon(self, task): """Blink upcoming outing icon to attract attention.""" self._blink_step += 1 if self._blink_step in (2, 4, 6): self._upcome_ico.show() if self._blink_step == 6: self._blink_step = 0 return task.done return task.again self._upcome_ico.hide() return task.again def _animate_bars(self, bars, score, selected_effect, recruit_effect, cohesion_inc, task): """Animate filling the bars. Args: bars (list): Widget to fill. score (int): Total outing score. selected_effect (dict): Effect which requires to choose a target. recruit_effect (int): Cost of a possible recruit cohesion_inc (float): Cohesion increase value. """ all_filled = True for bar in bars: bar_wid = bar[0] if bar_wid["value"] >= bar[1]: continue bar_wid["value"] = bar_wid["value"] + bar_wid["range"] / 100 all_filled = False if all_filled: shift = -0.07 for num in range(4): self._outing_widgets.append( DirectLabel( parent=self._list, text=str(bars[num][1]) + "/" + str(bars[num][2]), frameSize=(0.6, 0.6, 0.6, 0.6), text_scale=0.035, pos=(0.168, 0, shift), )) shift -= 0.12 self._outing_widgets.append( DirectLabel( # Total outing score: parent=self._list, text=base.labels.OUTINGS_GUI[1] + str(score) + "/100", # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.6, 0.6, 0.6, 0.6), text_scale=0.042, pos=(0, 0, -0.57), )) if round(cohesion_inc, 2) > 0.05: self._outing_widgets.append( DirectLabel( # Cohesion increased: parent=self._list, text=base.labels.OUTINGS_GUI[15].format( # noqa: F821 value=round(cohesion_inc, 2)), text_font=base.main_font, # noqa: F821 frameSize=(0.6, 0.6, 0.6, 0.6), text_scale=0.035, pos=(0, 0, -0.69), )) self._outing_widgets.append( DirectButton( # Done pos=(0, 0, -0.77), text=base.labels.DISTINGUISHED[6], # noqa: F821 text_font=base.main_font, # noqa: F821 text_fg=RUST_COL, text_shadow=(0, 0, 0, 1), frameColor=(0, 0, 0, 0), command=self._finish_outing, extraArgs=[selected_effect, recruit_effect], scale=(0.05, 0, 0.05), clickSound=base.main_menu.click_snd, # noqa: F821 )) return task.done return task.again def _dont_hire_unit(self): """Finish an outing without recruiting.""" self.hide_outing() base.common_ctrl.deselect() # noqa: F821 def _hire_unit(self, char, cost): """Hire unit from the outing. Args: char (units.crew.character.Character): Character to recruit. cost (int): Cost of the recruitement. """ if not base.res_gui.check_enough_money(cost): # noqa: F821 return if not base.res_gui.check_has_cell(): # noqa: F821 return base.dollars -= cost # noqa: F821 base.world.city_gui.write_snd.play() # noqa: F821 base.team.chars[char.id] = char # noqa: F821 char.prepare() base.train.place_recruit(char) # noqa: F821 base.res_gui.update_chars() # noqa: F821 self.hide_outing() base.common_ctrl.deselect() # noqa: F821 def _finish_outing(self, selected_effect, recruit_effect): """Show effect selector if needed and finish the outing. Args: selected_effect (dict): Effect which requires to choose a target. recruit_effect (int): Cost of a possible recruit. """ clear_wids(self._outing_widgets) if not (selected_effect or recruit_effect): self.hide_outing() return if recruit_effect: char = base.team.generate_recruit() # noqa: F821 base.char_gui.show_char_info(char) # noqa: F821 self._outing_widgets.append( DirectLabel( # You can recruit <name> for <cost>$ parent=self._list, pos=(0, 0, 0), text=base.labels.OUTINGS_GUI[12].format( # noqa: F821 name=char.name, cost=recruit_effect), text_font=base.main_font, # noqa: F821 frameSize=(0.6, 0.6, 0.6, 0.6), text_scale=0.045, )) self._outing_widgets.append( DirectButton( # Recruit pos=(-0.2, 0, -0.75), text=base.labels.OUTINGS_GUI[10], # noqa: F821 text_font=base.main_font, # noqa: F821 text_fg=RUST_COL, text_shadow=(0, 0, 0, 1), frameColor=(0, 0, 0, 0), command=self._hire_unit, extraArgs=[char, recruit_effect], scale=(0.05, 0, 0.05), clickSound=base.main_menu.click_snd, # noqa: F821 )) self._outing_widgets.append( DirectButton( # Don't recruit pos=(0.2, 0, -0.75), text=base.labels.OUTINGS_GUI[11], # noqa: F821 text_font=base.main_font, # noqa: F821 text_fg=RUST_COL, text_shadow=(0, 0, 0, 1), frameColor=(0, 0, 0, 0), command=self._dont_hire_unit, scale=(0.05, 0, 0.05), clickSound=base.main_menu.click_snd, # noqa: F821 )) return # there are effects to select a target for effect_str = "" for key, value in selected_effect.items(): if key == "add_trait": ind1, ind2 = value value = base.labels.TRAITS[ind1][ind2] # noqa: F821 effect_str = base.labels.OUTINGS_GUI[13].format( # noqa: F821 trait=value, desc=base.labels.TRAIT_DESC[value] # noqa: F821 ) else: effect_str += (key + " " + ("+" if value > 0 else "-") + str(value) + "\n") self._outing_widgets.append( DirectLabel( # Select one character as a target for the effect: parent=self._list, text=base.labels.OUTINGS_GUI[14] # noqa: F821 + "\n{effect}".format(effect=effect_str), text_font=base.main_font, # noqa: F821 frameSize=(0.6, 0.6, 0.6, 0.6), text_scale=0.045, )) self._char_chooser = CharacterChooser(is_shadowed=True) self._char_chooser.prepare( self._list, (0, 0, -0.15), base.team.chars # noqa: F821 ) self._outing_widgets.append( DirectButton( # Done pos=(0, 0, -0.75), text=base.labels.DISTINGUISHED[6], # noqa: F821 text_font=base.main_font, # noqa: F821 text_fg=RUST_COL, text_shadow=(0, 0, 0, 1), frameColor=(0, 0, 0, 0), command=self._do_effect_and_finish, # noqa: F821 extraArgs=[selected_effect], scale=(0.05, 0, 0.05), clickSound=base.main_menu.click_snd, # noqa: F821 )) def _do_effect_and_finish(self, effect): """ Do effects for the selected character and finish the outing. Args: effect (dict): The effect to do. """ self._char_chooser.chosen_item.do_effects(effect) self._char_chooser.destroy() self.hide_outing() def show_upcoming(self, text, icon): """Show the upcoming event notification. Args: text (str): Event text. icon (str): Event icon. """ self._upcome_text["text"] = text self._upcome_ico["frameTexture"] = icon self._upcome_text.show() self._upcome_ico.show() taskMgr.doMethodLater( # noqa: F821 0.3, self._blink_upcome_icon, "blink_outing_icon") def show_place_of_interest(self): """Show icon for a place of interest.""" self.show_upcoming( base.labels.NOTIFIERS[0], OUTINGS_ICONS["Place Of Interest"], # noqa: F821 ) def show_upcoming_outing(self, type_orig, type_): """Show upcoming outing notification. Args: type_orig (str): Original outing type. type_ (str): Translated outing type. """ self._outing_snd.play() self.show_upcoming( base.labels.NOTIFIERS[1].format(type_.capitalize()), # noqa: F821 OUTINGS_ICONS[type_orig], ) def show_city(self): """Show upcoming city notification.""" self.show_upcoming(base.labels.TIPS[2], "gui/tex/city.png") # noqa: F821 def show_upcoming_closer(self): """Show that 1 mile left until available outing.""" self._upcome_text["text"] = self._upcome_text["text"].replace( base.labels.NOTIFIERS[2], # noqa: F821 base.labels.NOTIFIERS[3], # noqa: F821 ) def show_can_start(self): """Show that outing can be started.""" self._upcome_text["text"] = base.labels.NOTIFIERS[4] # noqa: F821 def hide_outing(self): """Hide all the outings gui.""" self._upcome_text.hide() self._upcome_ico.hide() if self.is_shown: self._assignees.clear() self._list.hide() self.is_shown = False clear_wids(self._outing_widgets) def start(self, outing): """Start the outing scenario. Draw an interface with outing description. Args: outing (dict): Outing description. """ self.hide_outing() base.traits_gui.hide() # noqa: F821 self.is_shown = True self._list.show() out_labels = base.labels.OUTINGS[outing["index"]] # noqa: F821 self._name["text"] = out_labels["name"] self._type["text"] = base.labels.OUTING_TYPES[ outing["type"]] # noqa: F821 self._desc["text"] = out_labels["desc"] self._outing_widgets.append( DirectLabel( # Crew: parent=self._list, text=base.labels.OUTINGS_GUI[9], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.6, 0.6, 0.6, 0.6), text_scale=0.035, pos=(-0.35, 0, 0), )) shift = -0.07 for id_, char in base.team.chars.items(): # noqa: F821 but = DirectButton( pos=(-0.35, 0, shift), text=char.name, text_fg=SILVER_COL, frameColor=(0, 0, 0, 0.3), command=base.common_ctrl.choose_char, # noqa: F821 extraArgs=[char.id], scale=(0.04, 0, 0.03), ) self._char_buttons[id_] = but self._outing_widgets.append(but) shift -= 0.04 to_send = DirectLabel( # People to send parent=self._list, text=base.labels.OUTINGS_GUI[0].format( # noqa: F821 cur_as="0", max_as=outing["assignees"]), text_scale=0.035, text_font=base.main_font, # noqa: F821 frameSize=(0.6, 0.6, 0.6, 0.6), pos=(0.35, 0, 0), ) self._outing_widgets.append(to_send) self._outing_widgets.append( DirectButton( pos=(0, 0, -0.15), text=">", text_fg=SILVER_COL, frameColor=(0, 0, 0, 0.3), command=self._assign_for_outing, extraArgs=[to_send, outing["assignees"]], scale=(0.075, 0, 0.075), )) self._outing_widgets.append( DirectButton( pos=(0, 0, -0.21), text="<", text_fg=SILVER_COL, frameColor=(0, 0, 0, 0.3), command=self._unassign_for_outing, extraArgs=[to_send, outing["assignees"]], scale=(0.075, 0, 0.075), )) self._outing_widgets.append( DirectButton( # Don't send pos=(-0.15, 0, -0.75), text=base.labels.OUTINGS_GUI[2], # noqa: F821 text_font=base.main_font, # noqa: F821 text_fg=RUST_COL, text_shadow=(0, 0, 0, 1), frameColor=(0, 0, 0, 0), command=self.hide_outing, scale=(0.05, 0, 0.05), clickSound=base.main_menu.click_snd, # noqa: F821 )) self._outing_widgets.append( DirectButton( # Send pos=(0.15, 0, -0.75), text=base.labels.OUTINGS_GUI[3], # noqa: F821 text_font=base.main_font, # noqa: F821 text_fg=RUST_COL, text_shadow=(0, 0, 0, 1), frameColor=(0, 0, 0, 0), command=base.world.outings_mgr.go_for_outing, # noqa: F821 extraArgs=[outing, self._assignees], clickSound=base.main_menu.click_snd, # noqa: F821 scale=(0.05, 0, 0.05), )) def show_result( self, desc, score, cond_score, class_score, cohesion_score, day_part_score, selected_effect, recruit_effect, cohesion_inc, ): """Show outing results GUI. Args: desc (str): Result description. score (int): Total outing score. cond_score (float): Score from characters condition. class_score (int): Score from characters classes. cohesion_score (float): Characters cohesion score. day_part_score (int): Day part bonus and special skills score. selected_effect (dict): Effect which requires to choose a target. recruit_effect (int): Cost of a possible recruit. cohesion_inc (float): Cohesion increase value. """ clear_wids(self._outing_widgets) self._desc["text"] = desc self._outing_widgets.append( DirectLabel( # Outing score: parent=self._list, text=base.labels.OUTINGS_GUI[4], # noqa: F821 text_font=base.main_font, # noqa: F821 frameSize=(0.6, 0.6, 0.6, 0.6), text_scale=0.042, )) bars = [] shift = -0.07 for name, maximum, col, value in ( ( # Character classes fit: base.labels.OUTINGS_GUI[5], # noqa: F821 40, (0.36, 0.6, 0.42, 1), class_score, ), ( # Characters condition: base.labels.OUTINGS_GUI[6], # noqa: F821 25, (0.65, 0.2, 0.2, 1), cond_score, ), ( # Characters cohesion: base.labels.OUTINGS_GUI[7], # noqa: F821 25, SILVER_COL, cohesion_score, ), ( # Day part: base.labels.OUTINGS_GUI[8], # noqa: F821 10, (0.42, 0.42, 0.8, 1), day_part_score, ), ): self._outing_widgets.append( DirectLabel( parent=self._list, text=name, text_font=base.main_font, # noqa: F821 frameSize=(0.6, 0.6, 0.6, 0.6), text_scale=0.035, pos=(-0.08, 0, shift), )) shift -= 0.04 bar = DirectWaitBar( parent=self._list, frameSize=(-0.17, 0.17, -0.005, 0.005), frameColor=(0.3, 0.3, 0.3, 0.5), value=0, range=maximum, barColor=col, pos=(0, 0, shift), ) bars.append((bar, value, maximum)) self._outing_widgets.append(bar) shift -= 0.08 taskMgr.doMethodLater( # noqa: F821 0.035, self._animate_bars, "animate_outing_bars", extraArgs=[ bars, score, selected_effect, recruit_effect, cohesion_inc ], appendTask=True, )
def __init__(self, numPlayers, avIdList, votes, directions, namesList, disconnectedList, directionToGo, directionReason, directionTotals, *args, **kwargs): opts = { 'relief': None, 'geom': DGG.getDefaultDialogGeom(), 'geom_color': ToontownGlobals.GlobalDialogColor[:3] + (0.8, ), 'geom_scale': (1.75, 1, 0.25), 'pos': (0, 0, 0.825) } opts.update(kwargs) DirectFrame.__init__(self, *args, **opts) self.initialiseoptions(VoteResultsTrolleyPanel) listMultiplier = 1 if TravelGameGlobals.SpoofFour: listMultiplier = 4 self.avIdList = avIdList * listMultiplier self.numPlayers = numPlayers * listMultiplier self.votes = votes * listMultiplier self.directions = directions * listMultiplier self.namesList = namesList * listMultiplier self.disconnectedList = disconnectedList * listMultiplier self.directionToGo = directionToGo self.directionReason = directionReason self.directionTotals = directionTotals self.entryList = [] self.rowFrame = [] self.upDownFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(-1)) self.upLabel = DirectLabel(parent=self, relief=None, pos=(-0.5, 0, 0.06), text=TTLocalizer.TravelGameDirections[0] + ':', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.downLabel = DirectLabel(parent=self, relief=None, pos=(0.5, 0, 0.06), text=TTLocalizer.TravelGameDirections[1] + ':', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalVotesUpLabel = DirectLabel(parent=self.upLabel, relief=None, pos=(0.2, 0, 0.0), text='0', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalVotesDownLabel = DirectLabel(parent=self.downLabel, relief=None, pos=(0.2, 0, 0.0), text='0', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(self.numPlayers)) self.totalVotesLabels = [ self.totalVotesUpLabel, self.totalVotesDownLabel ] self.resultFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(0.5)) self.resultLabel = DirectLabel(parent=self.resultFrame, text='', text_scale=0.06, pos=(0.7, 0, 0.0), text_align=TextNode.ACenter) self.setupResultLabel() for index in xrange(self.numPlayers): frame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(index)) self.rowFrame.append(frame) nameLabel = DirectFrame(parent=frame, relief=None, pos=(0.46, 0.0, 0.0), text=self.namesList[index], text_fg=(0.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ACenter, text_font=DGG.getDefaultFont()) votesUpLabel = DirectLabel(parent=frame, relief=None, pos=(1.2, 0.0, 0.0), text='', text_fg=(0, 0, 1, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont()) votesDownLabel = DirectLabel(parent=frame, relief=None, pos=(1.43, 0.0, 0.0), text='', text_fg=(1, 0, 0, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont()) nameLabel.hide() self.entryList.append((nameLabel, votesUpLabel, votesDownLabel)) self.avVotesLabel = {} self.avArrows = {} matchingGameGui = loader.loadModel( 'phase_3.5/models/gui/matching_game_gui') minnieArrow = matchingGameGui.find('**/minnieArrow') from toontown.minigame.DistributedTravelGame import map3dToAspect2d for index in xrange(self.numPlayers): avId = self.avIdList[index] av = base.cr.doId2do.get(avId) if av: height = av.getHeight() avPos = av.getPos(render) avPos.setZ(av.getZ() + 5) labelPos = map3dToAspect2d(render, avPos) if not labelPos: continue labelPos.setZ(labelPos.getZ() + 0.3) arrow = None if self.votes[index] > 0: arrow = aspect2d.attachNewNode('avArrow') minnieArrow.copyTo(arrow) arrow.setScale(1.1, 1, 1.15) arrow.setPos(labelPos) if self.directions[index] == 0: arrow.setR(-90) arrow.setColorScale(0, 0, 1, 1) else: arrow.setR(90) arrow.setColorScale(1, 0, 0, 1) arrow.wrtReparentTo(self.resultFrame) arrow.hide() self.avArrows[index] = arrow fgColor = Vec4(0, 0, 0, 1) if self.votes[index] > 0: if self.directions[index] == 0: fgColor = Vec4(0, 0, 1, 1) else: fgColor = Vec4(1, 0, 0, 1) if self.votes[index] > 0: newLabel = DirectLabel( parent=aspect2d, relief=None, pos=labelPos, text='test', text_fg=(1, 1, 1, 1), text_scale=0.1, text_align=TextNode.ACenter, text_font=ToontownGlobals.getSignFont(), text_pos=(0, -0.01, 0)) else: newLabel = DirectLabel( parent=aspect2d, geom=DGG.getDefaultDialogGeom(), geom_scale=(0.2, 1, 0.2), relief=None, pos=labelPos, text='test', text_fg=(0.5, 0.5, 0.5, 1), text_scale=0.1, text_align=TextNode.ACenter, text_font=ToontownGlobals.getSignFont(), text_pos=(0, -0.035, 0)) newLabel.wrtReparentTo(self.resultFrame) newLabel.hide() self.avVotesLabel[index] = newLabel matchingGameGui.removeNode() self.curArrowSfxIndex = 0 self.upArrowSfx = [] self.downArrowSfx = [] for i in xrange(5): self.upArrowSfx.append( base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.ogg')) self.downArrowSfx.append( base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_red_arrow.ogg')) self.winVoteSfx = base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_win_vote.ogg') self.noVoteSfx = base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_square_no_vote_1.ogg') self.loseVoteSfx = base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_lose_vote.ogg') self.localAvatarWon = False self.localAvatarLost = False localIndex = self.avIdList.index(base.localAvatar.doId) localDirection = self.directions[localIndex] localVotes = self.votes[localIndex] if localVotes: if localDirection == self.directionToGo: if not TravelGameGlobals.ReverseWin: self.localAvatarWon = True else: self.localAvatarLost = True elif not TravelGameGlobals.ReverseWin: self.localAvatarLost = True else: self.localAvatarWon = True return
class QuestPoster(DirectFrame): notify = directNotify.newCategory('QuestPoster') # We need to declare and initialize these variables here # because some methods use them as default arguments. auxIcon = None # Requires one parameter, quest, this must be a Quest instance. # The next argument, parent, is where to reparent the DirectFrame to. # The next arguments are simply additional options when setting up the DirectFrame. def __init__(self, quest, parent=aspect2d, **kw): # The quest this poster is representing. self.quest = quest # Let's define our options for the DirectFrame. bookModel = loader.loadModel( 'phase_3.5/models/gui/stickerbook_gui.bam') optiondefs = (('relief', None, None), ('image', bookModel.find('**/questCard'), None), ('image_scale', (0.8, 1.0, 0.58), None), ('state', DGG.NORMAL, None)) self.defineoptions(kw, optiondefs) # Finally, initialize the DirectFrame. DirectFrame.__init__(self, relief=None) self.initialiseoptions(QuestPoster) # Let's declare and initialize our barebone GUI element variables. self.titleLabel = DirectLabel(parent=self, relief=None, text=self.quest.getName(), text_font=CIGlobals.getMinnieFont(), text_fg=QuestGlobals.TEXT_COLOR, text_scale=0.05, text_align=TextNode.ACenter, text_wordwrap=25.0, textMayChange=1, pos=(0, 0, 0.23)) ########################################################################## # THE FOLLOWING ELEMENTS BELOW ARE GROUPED TOGETHER # ########################################################################## # The background frame where the objective image is displayed. # This is the colored background frame. self.auxFrame = DirectFrame( parent=self, relief=None, image=bookModel.find('**/questPictureFrame'), image_scale=QuestGlobals.IMAGE_SCALE_SMALL, text='', text_pos=(0, -0.11), text_fg=QuestGlobals.TEXT_COLOR, text_scale=QuestGlobals.QPtextScale, text_align=TextNode.ACenter, text_wordwrap=11.0, pos=QuestGlobals.DEFAULT_LEFT_PICTURE_POS) # The icon that goes on top of the aux frame. self.auxIcon = DirectFrame(parent=self.auxFrame, relief=None, text=' ', text_font=CIGlobals.getSuitFont(), text_pos=(0, -0.03), text_fg=QuestGlobals.TEXT_COLOR, text_scale=0.13, text_align=TextNode.ACenter, text_wordwrap=13.0, textMayChange=1) self.auxIcon.setColorOff(-1) # The aux text saying: DEFEAT, RECOVER, etc. self.auxText = DirectLabel(parent=self, relief=None, text=QuestGlobals.RECOVER, text_font=CIGlobals.getToonFont(), text_scale=QuestGlobals.QPauxText, text_fg=QuestGlobals.TEXT_COLOR, text_align=TextNode.ACenter, textMayChange=1, pos=QuestGlobals.DEFAULT_AUX_POS) self.auxText.hide() ########################################################################## # Information displayed about the objective. self.objectiveInfo = DirectLabel( parent=self, relief=None, text='', text_font=CIGlobals.getToonFont(), text_fg=QuestGlobals.TEXT_COLOR, text_scale=0.04, text_align=TextNode.ACenter, text_wordwrap=QuestGlobals.QPtextWordwrap, textMayChange=1, pos=(QuestGlobals.DEFAULT_INFO_POS)) self.objectiveInfo.hide() # Information displayed showing the location. self.locationInfo = DirectLabel( parent=self, relief=None, text='N/A', text_font=CIGlobals.getToonFont(), text_fg=QuestGlobals.TEXT_COLOR, text_scale=QuestGlobals.QPtextScale, text_align=TextNode.ACenter, text_wordwrap=QuestGlobals.QPtextWordwrap, textMayChange=1, pos=(0, 0, -0.115)) self.locationInfo.hide() # The progress bar showing the objective's progress self.progressBar = DirectWaitBar(parent=self, relief=DGG.SUNKEN, frameSize=(-0.95, 0.95, -0.1, 0.12), borderWidth=(0.025, 0.025), scale=0.2, frameColor=(0.945, 0.875, 0.706, 1.0), barColor=(0.5, 0.7, 0.5, 1), text='0/0', text_font=CIGlobals.getToonFont(), text_scale=0.19, text_fg=(0.05, 0.14, 0.4, 1), text_align=TextNode.ACenter, text_pos=(0, -0.05), pos=(0, 0, -0.2425)) self.progressBar.hide() # The wood panel at the bottom where rewards are displayed. rewardFrameGeom = loader.loadModel( 'phase_4/models/gui/gag_shop_purchase_gui.bam') self.rewardFrame = DirectFrame( parent=self, relief=None, geom=rewardFrameGeom.find('**/Goofys_Sign'), geom_scale=(0.615, 0, 0.4), pos=(-0.01, 0, -0.25)) # The text displayed on the right side of the frame with additional information, if necessary. self.sideInfo = DirectLabel(parent=self, relief=None, text=QuestGlobals.JUST_FOR_FUN, text_fg=(0.0, 0.439, 1.0, 1.0), text_shadow=(0, 0, 0, 1), pos=(-0.2825, 0, 0.2), scale=0.03) self.sideInfo.setR(-30) # This side information is usually not needed, let's hide it. self.sideInfo.hide() # Remove the nodes of the loaded models we no longer need. bookModel.removeNode() rewardFrameGeom.removeNode() # Let's hide this until it is needed. self.hide() return def setup(self): objective = self.quest.currentObjective objective.updateInfo() self.objectiveInfo.show() self.auxFrame.show() self.locationInfo['text'] = QuestGlobals.getLocationText( objective.location) self.locationInfo['text_pos'] = (0, 0 if not QuestGlobals.isShopLocation( objective.location) else 0.025) self.locationInfo.show() # Let's setup the quest progress bar progress = objective.amount if hasattr(objective, 'amount') else None if progress and objective.neededAmount > 0: self.progressBar['range'] = objective.getNeededAmount() self.progressBar['value'] = progress & pow(2, 16) - 1 if objective.__class__ in [ DeliverItemObjective, CogObjective, RecoverItemObjective ]: self.progressBar.show() self.auxText.show() # Let's handle the objectives. if objective.__class__ == CogObjective: self.handleCogObjective() elif objective.__class__ == VisitNPCObjective: self.handleNPCObjective() self.titleLabel.initialiseoptions(DirectLabel) self.auxIcon.initialiseoptions(DirectFrame) self.auxText.initialiseoptions(DirectLabel) self.objectiveInfo.initialiseoptions(DirectLabel) self.locationInfo.initialiseoptions(DirectLabel) self.rewardFrame.initialiseoptions(DirectFrame) self.sideInfo.initialiseoptions(DirectLabel) # Changes geometry and scale of an icon. def handleSimpleIcon(self, geom, scale, icon): icon['geom'] = geom icon['geom_scale'] = scale def handleComplexIcon(self, geom, icon, scale=QuestGlobals.IMAGE_SCALE_SMALL): isHead = True if type(geom) == ToonHead else geom.getName() == ( '%sHead' % CIGlobals.Suit) if isHead: geom.setDepthWrite(1) geom.setDepthTest(1) self.fitGeometry(geom, fFlip=1) self.handleSimpleIcon(geom, scale, icon) # We have to rotate the head and set the scale of the icon. if CIGlobals.Suit in geom.getName(): cogName = geom.getPythonTag('Settings') data = QuestGlobals.Suit2PosterZNDScale.get(cogName) zOffset = data[0] headScale = data[1] icon.setScale(headScale) icon.setZ(icon.getZ() + zOffset) geom.setH(180) else: raise ValueError( 'Tried to use #handleComplexIcon() on a non-complex icon. Use this method for 3D geometry.' ) def handleCogObjective(self, iconElement=auxIcon, auxText=QuestGlobals.DEFEAT, frameColor=QuestGlobals.BLUE): objective = self.quest.currentObjective infoText = objective.getTaskInfo(speech=False) if objective.__class__ == RecoverItemObjective: infoText = QuestGlobals.makePlural(objective.name) print 'Yep' if not iconElement: iconElement = self.auxIcon # Let's make sure we have a current objective that is # an instance of the CogObjective class and this poster isn't destroyed. if not objective or not hasattr(self, 'titleLabel') or not isinstance( objective, CogObjective): return if objective.dept: icons = loader.loadModel('phase_3/models/gui/cog_icons.bam') deptIcon = None if objective.dept == Dept.BOSS: deptIcon = icons.find('**/CorpIcon') else: deptIcon = icons.find('**/%sIcon' % objective.dept.getTie().title()) # Correct the medallion color. deptIcon.setColor(SuitGlobals.medallionColors[objective.dept]) # Setup the icon and remove the icons node. self.handleSimpleIcon(deptIcon, 0.13, iconElement) icons.removeNode() elif not objective.name: # We aren't fighting a Cog in particular. cogIcon = QuestGlobals.getCogIcon() self.handleSimpleIcon(cogIcon, cogIcon.getScale(), iconElement) # We're fighting a Cog in particular. if objective.name: cogHeadInstance = SuitBank.getSuitByName(objective.name).getHead() cogHead = cogHeadInstance.generate() cogHead.setName('%sHead' % CIGlobals.Suit) cogHead.setPythonTag('Settings', cogHeadInstance.head) cogHeadInstance.setScale(2) self.handleComplexIcon(cogHead, iconElement) if not iconElement is self.auxIcon: if hasattr(self, 'goalInfo'): # We're working with the second frame, on the right. # Let's update the information pertaining to this side. self.goalInfo['text'] = infoText self.goalInfo.setPos(QuestGlobals.RECOVER_INFO2_POS) self.auxText.setPos(QuestGlobals.RECOVER_AUX_POS) else: raise AttributeError( 'Attempted to setup DoubleFrame information for poster using default style.' ) else: self.objectiveInfo['text'] = infoText self.auxText['text'] = auxText # Let's set the progress bar text pgBarText = '%d of %d %s' % (objective.amount, objective.neededAmount, QuestGlobals.makePastTense(auxText)) self.progressBar['text'] = pgBarText # Let's set the color of the poster. frame = self.auxFrame if iconElement is self.auxIcon else self.goalFrame frame['image_color'] = Vec4(*frameColor) def handleNPCObjective(self, iconElement=auxIcon, auxText=QuestGlobals.VISIT, frameColor=QuestGlobals.BROWN): objective = self.quest.currentObjective infoText = CIGlobals.NPCToonNames[objective.npcId] if not iconElement: iconElement = self.auxIcon # Let's make sure we have a current objective that is # an instance of the CogObjective class and this poster isn't destroyed. if not objective or not hasattr(self, 'titleLabel') or not isinstance( objective, VisitNPCObjective): return # Let's generate the head. dna = ToonDNA() dna.setDNAStrand(CIGlobals.NPCToonDict.get(objective.npcId)[2]) head = ToonHead(base.cr) head.generateHead(dna.getGender(), dna.getAnimal(), dna.getHead(), forGui=1) head.setHeadColor(dna.getHeadColor()) self.handleComplexIcon(head, iconElement) self.auxText['text'] = auxText if not iconElement is self.auxIcon: if hasattr(self, 'goalInfo'): # We're working with the second frame, on the right. # Let's update the information pertaining to this side. self.goalInfo['text'] = infoText self.goalInfo.setPos(QuestGlobals.RECOVER_INFO2_POS) self.auxText.setPos(QuestGlobals.RECOVER_AUX_POS) self.goalFrame['image_color'] = frameColor else: raise AttributeError( 'Attempted to setup DoubleFrame information for poster using default style.' ) else: self.objectiveInfo['text'] = infoText self.auxFrame['image_color'] = frameColor def fitGeometry(self, geom, fFlip=0, dimension=0.8): p1 = Point3() p2 = Point3() geom.calcTightBounds(p1, p2) if fFlip: t = p1[0] p1.setX(-p2[0]) p2.setX(-t) d = p2 - p1 biggest = max(d[0], d[2]) s = dimension / biggest mid = (p1 + d / 2.0) * s geomXform = hidden.attachNewNode('geomXform') for child in geom.getChildren(): child.reparentTo(geomXform) geomXform.setPosHprScale(-mid[0], -mid[1] + 1, -mid[2], 180, 0, 0, s, s, s) geomXform.reparentTo(geom) def destroy(self): if hasattr(self, 'titleLabel'): self.titleLabel.destroy() self.auxFrame.destroy() self.auxIcon.destroy() self.auxText.destroy() self.objectiveInfo.destroy() self.locationInfo.destroy() self.progressBar.destroy() self.rewardFrame.destroy() self.sideInfo.destroy() del self.titleLabel del self.auxFrame del self.auxIcon del self.auxText del self.objectiveInfo del self.locationInfo del self.progressBar del self.rewardFrame del self.sideInfo DirectFrame.destroy(self) self.notify.debug('Destroyed all elements.')
class SimpleInteractive(DirectObject): __module__ = __name__ def __init__(self, object, name, proximityText): DirectObject.__init__(self) self.object = object self.proximityText = proximityText self.proximityEvent = name self.enterProximityEvent = 'enter' + name self.exitProximityEvent = 'exit' + name self.useLabel = None self.fader = None self.size = 6 self.disk = None proximitySphere = CollisionSphere(0, 0, 0, self.size) proximitySphere.setTangible(0) proximityNode = CollisionNode(self.proximityEvent) proximityNode.setIntoCollideMask(PiratesGlobals.WallBitmask) proximityNode.addSolid(proximitySphere) self.proximityNodePath = self.object.attachNewNode(proximityNode) self.accept(self.enterProximityEvent, self.approach) self.accept(self.exitProximityEvent, self.leave) return def createInteractionDisk(self): self.disk = loader.loadModel('models/effects/selectionCursor') self.disk.setScale(self.size) self.disk.setColorScale(0, 1, 0, 1) self.disk.setP(-90) self.disk.setZ(0.025) self.disk.setBillboardAxis(6) self.disk.reparentTo(self.object) self.disk.setBin('shadow', 0) self.disk.setTransparency(TransparencyAttrib.MAlpha) self.disk.setDepthWrite(0) self.disk.setDepthTest(0) def loadUseLabel(self, text): self.useLabel = DirectLabel( parent=aspect2d, frameColor=(0.1, 0.1, 0.25, 0.2), text=text, text_align=TextNode.ACenter, text_scale=0.06, text_pos=(0.02, 0.02), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), textMayChange=1, text_font=PiratesGlobals.getPirateOutlineFont()) self.useLabel.setPos(0, 0, -0.7) self.useLabel.setAlphaScale(0) self.useLabel.hide() def fadeInText(self): if self.fader: self.fader.pause() def interactionAllowed(self, avId): return True def approach(self, collEntry): if not self.interactionAllowed(localAvatar.doId): return if not self.disk: self.createInteractionDisk() if self.proximityText: if not self.useLabel: self.loadUseLabel(self.proximityText) if self.fader: self.fader.pause() fadeIn = LerpFunctionInterval(self.useLabel.setAlphaScale, fromData=0, toData=1, duration=0.5) self.fader = Sequence(Func(self.useLabel.show), fadeIn) self.fader.start() self.disk.show() self.accept(USE_KEY_EVENT, self.handleUseKey) def requestInteraction(self, avId): pass def handleUseKey(self): self.requestInteraction(localAvatar.doId) def leave(self, collEntry): if self.disk: self.disk.hide() if self.proximityText: if self.fader: self.fader.pause() self.fader = None if self.useLabel: self.useLabel.hide() self.ignore(USE_KEY_EVENT) return
class DistCogdoGame(DistributedObject): notify = directNotify.newCategory("DistCogdoGame") def __init__(self, cr): DistributedObject.__init__(self, cr) self._waitingStartLabel = DirectLabel( text=TTL.MinigameWaitingForOtherPlayers, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075) self._waitingStartLabel.hide() self.loadFSM = ClassicFSM.ClassicFSM( 'DistCogdoGame.loaded', [ State.State('NotLoaded', self.enterNotLoaded, self.exitNotLoaded, ['Loaded']), State.State('Loaded', self.enterLoaded, self.exitLoaded, ['NotLoaded']) ], # Initial state 'NotLoaded', # Final state 'NotLoaded') self.fsm = ClassicFSM.ClassicFSM( 'DistCogdoGame', [ State.State('Intro', self.enterIntro, self.exitIntro, ['WaitServerStart']), State.State('WaitServerStart', self.enterWaitServerStart, self.exitWaitServerStart, ['Game']), State.State('Game', self.enterGame, self.exitGame, ['Finish']), State.State('Finish', self.enterFinish, self.exitFinish, ['Off']), State.State('Off', self.enterOff, self.exitOff, ['Intro']) ], # Initial state 'Off', # Final state 'Off') self.fsm.enterInitialState() def getTitle(self): pass # override and return title def getInstructions(self): pass # override and return instructions def setInteriorId(self, interiorId): self._interiorId = interiorId def getInterior(self): return self.cr.getDo(self._interiorId) def getToonIds(self): toonIds = [] interior = self.getInterior() for toonId in interior.getToons()[0]: if toonId: toonIds.append(toonId) return toonIds def getNumPlayers(self): return len(self.getToonIds()) def announceGenerate(self): DistributedObject.announceGenerate(self) self.loadFSM.request('Loaded') def disable(self): self.fsm.requestFinalState() self.loadFSM.requestFinalState() self.fsm = None self.loadFSM = None DistributedObject.disable(self) def delete(self): self._waitingStartLabel.destroy() self._waitingStartLabel = None DistributedObject.delete(self) def enterNotLoaded(self): pass def exitNotLoaded(self): pass def enterLoaded(self): pass def exitLoaded(self): pass def enterOff(self): pass def exitOff(self): pass def setIntroStart(self): self.fsm.request('Intro') def enterIntro(self): assert self.notify.debugCall() base.cr.playGame.getPlace().fsm.request('Game') self._rulesDoneEvent = uniqueName('cogdoGameRulesDone') self.accept(self._rulesDoneEvent, self._handleRulesDone) self._rulesPanel = MinigameRulesPanel("MinigameRulesPanel", self.getTitle(), self.getInstructions(), self._rulesDoneEvent) self._rulesPanel.load() self._rulesPanel.enter() def exitIntro(self): self.ignore(self._rulesDoneEvent) if self._rulesPanel: self._rulesPanel.exit() self._rulesPanel.unload() self._rulesPanel = None def _handleRulesDone(self): self.ignore(self._rulesDoneEvent) self._rulesPanel.exit() self._rulesPanel.unload() self._rulesPanel = None self.sendUpdate('setAvatarReady', []) self.fsm.request('WaitServerStart') def enterWaitServerStart(self): numToons = 1 interior = self.getInterior() if interior: numToons = len(interior.getToonIds()) if numToons > 1: msg = TTL.MinigameWaitingForOtherPlayers else: msg = TTL.MinigamePleaseWait self._waitingStartLabel['text'] = msg self._waitingStartLabel.show() def exitWaitServerStart(self): self._waitingStartLabel.hide() def setGameStart(self, timestamp): self._startTime = globalClockDelta.networkToLocalTime(timestamp) self.fsm.request('Game') def getStartTime(self): return self._startTime def enterGame(self): assert self.notify.debugCall() def exitGame(self): pass def setGameFinish(self, timestamp): self._finishTime = globalClockDelta.networkToLocalTime(timestamp) self.fsm.request('Finish') def getFinishTime(self): return self._finishTime def enterFinish(self): assert self.notify.debugCall() def exitFinish(self): pass
class JellybeanRewardGui(DirectFrame): notify = directNotify.newCategory('JellybeanRewardGui') PreCountdownDelay = 1.0 CountDownRate = 0.2 JarLabelTextColor = (0.95, 0.95, 0.0, 1.0) JarLabelMaxedTextColor = (1.0, 0.0, 0.0, 1.0) def __init__(self, doneEvent): self.doneEvent = doneEvent DirectFrame.__init__(self) self.reparentTo(aspect2d) self.setPos(0.0, 0.0, 0.16) self.stash() publicPartyGui = loader.loadModel( 'phase_4/models/parties/publicPartyGUI') self.frame = DirectFrame( parent=self, geom=publicPartyGui.find('**/activities_background'), geom_pos=(-0.8, 0.0, 0.2), geom_scale=2.0, relief=None) self.earnedLabel = DirectLabel( parent=self, relief=None, text=str(0), text_align=TextNode.ACenter, text_pos=(0.0, -0.07), text_scale=0.2, text_fg=(0.95, 0.95, 0.0, 1.0), text_font=ToontownGlobals.getSignFont(), textMayChange=True, image=DirectGuiGlobals.getDefaultDialogGeom(), image_scale=(0.33, 1.0, 0.33), pos=(-0.3, 0.0, 0.2), scale=0.9) purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui') jarImage = purchaseModels.find('**/Jar') self.jarLabel = DirectLabel( parent=self, relief=None, text=str(0), text_align=TextNode.ACenter, text_pos=(0.0, -0.07), text_scale=0.2, text_fg=JellybeanRewardGui.JarLabelTextColor, text_font=ToontownGlobals.getSignFont(), textMayChange=True, image=jarImage, scale=0.7, pos=(0.3, 0.0, 0.17)) purchaseModels.removeNode() del purchaseModels jarImage.removeNode() del jarImage self.messageLabel = DirectLabel(parent=self, relief=None, text='', text_align=TextNode.ALeft, text_wordwrap=16.0, text_scale=0.07, pos=(-0.52, 0.0, -0.1), textMayChange=True) self.doubledJellybeanLabel = DirectLabel( parent=self, relief=None, text=TTLocalizer.PartyRewardDoubledJellybean, text_align=TextNode.ACenter, text_wordwrap=12.0, text_scale=0.09, text_fg=(1.0, 0.125, 0.125, 1.0), pos=(0.0, 0.0, -0.465), textMayChange=False) self.doubledJellybeanLabel.hide() self.closeButton = DirectButton( parent=self, relief=None, text=TTLocalizer.PartyJellybeanRewardOK, text_align=TextNode.ACenter, text_scale=0.065, text_pos=(0.0, -0.625), geom=(publicPartyGui.find('**/startButton_up'), publicPartyGui.find('**/startButton_down'), publicPartyGui.find('**/startButton_rollover'), publicPartyGui.find('**/startButton_inactive')), geom_pos=(-0.39, 0.0, 0.125), command=self._close) publicPartyGui.removeNode() del publicPartyGui self.countSound = base.loadSfx( 'phase_13/audio/sfx/tick_counter_short.ogg') self.overMaxSound = base.loadSfx( 'phase_13/audio/sfx/tick_counter_overflow.ogg') return def showReward(self, earnedAmount, jarAmount, message): JellybeanRewardGui.notify.debug( 'showReward( earnedAmount=%d, jarAmount=%d, ...)' % (earnedAmount, jarAmount)) self.earnedCount = earnedAmount self.earnedLabel['text'] = str(self.earnedCount) self.jarCount = jarAmount self.jarMax = base.localAvatar.getMaxMoney() self.jarLabel['text'] = str(self.jarCount) self.jarLabel['text_fg'] = JellybeanRewardGui.JarLabelTextColor self.messageLabel['text'] = message if base.cr.newsManager.isHolidayRunning( ToontownGlobals.JELLYBEAN_DAY ) or base.cr.newsManager.isHolidayRunning( ToontownGlobals.JELLYBEAN_PARTIES_HOLIDAY ) or base.cr.newsManager.isHolidayRunning( ToontownGlobals.JELLYBEAN_PARTIES_HOLIDAY_MONTH): self.doubledJellybeanLabel.show() else: self.doubledJellybeanLabel.hide() self.unstash() taskMgr.doMethodLater(JellybeanRewardGui.PreCountdownDelay, self.transferOneJellybean, 'JellybeanRewardGuiTransferOneJellybean', extraArgs=[]) def transferOneJellybean(self): if self.earnedCount == 0: return self.earnedCount -= 1 self.earnedLabel['text'] = str(self.earnedCount) self.jarCount += 1 if self.jarCount <= self.jarMax: self.jarLabel['text'] = str(self.jarCount) elif self.jarCount > self.jarMax: self.jarLabel[ 'text_fg'] = JellybeanRewardGui.JarLabelMaxedTextColor if self.jarCount <= self.jarMax: base.playSfx(self.countSound) else: base.playSfx(self.overMaxSound) taskMgr.doMethodLater(JellybeanRewardGui.CountDownRate, self.transferOneJellybean, 'JellybeanRewardGuiTransferOneJellybean', extraArgs=[]) def _close(self): taskMgr.remove('JellybeanRewardGuiTransferOneJellybean') self.stash() messenger.send(self.doneEvent) def destroy(self): taskMgr.remove('JellybeanRewardGuiTransferOneJellybean') del self.countSound del self.overMaxSound self.frame.destroy() self.earnedLabel.destroy() self.jarLabel.destroy() self.messageLabel.destroy() self.closeButton.destroy() DirectFrame.destroy(self)
class IsisAgent(kinematicCharacterController, DirectObject): @classmethod def setPhysics(cls, physics): """ This method is set in src.loader when the generators are loaded into the namespace. This frees the environment definitions (in scenario files) from having to pass around the physics parameter that is required for all IsisObjects """ cls.physics = physics def __init__(self, name, queueSize=100): # load the model and the different animations for the model into an Actor object. self.actor = Actor( "media/models/boxman", {"walk": "media/models/boxman-walk", "idle": "media/models/boxman-idle"} ) self.actor.setScale(1.0) self.actor.setH(0) # self.actor.setLODAnimation(10,5,2) # slows animation framerate when actor is far from camera, if you can figure out reasonable params self.actor.setColorScale(random.random(), random.random(), random.random(), 1.0) self.actorNodePath = NodePath("agent-%s" % name) self.activeModel = self.actorNodePath self.actorNodePath.reparentTo(render) self.actor.reparentTo(self.actorNodePath) self.name = name self.isMoving = False # initialize ODE controller kinematicCharacterController.__init__(self, IsisAgent.physics, self.actorNodePath) self.setGeomPos(self.actorNodePath.getPos(render)) """ Additional Direct Object that I use for convenience. """ self.specialDirectObject = DirectObject() """ How high above the center of the capsule you want the camera to be when walking and when crouching. It's related to the values in KCC. """ self.walkCamH = 0.7 self.crouchCamH = 0.2 self.camH = self.walkCamH """ This tells the Player Controller what we're aiming at. """ self.aimed = None self.isSitting = False self.isDisabled = False """ The special direct object is used for trigger messages and the like. """ # self.specialDirectObject.accept("ladder_trigger_enter", self.setFly, [True]) # self.specialDirectObject.accept("ladder_trigger_exit", self.setFly, [False]) self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"]) # Expose agent's right hand joint to attach objects to self.player_right_hand = self.actor.exposeJoint(None, "modelRoot", "Hand.R") self.player_left_hand = self.actor.exposeJoint(None, "modelRoot", "Hand.L") self.right_hand_holding_object = None self.left_hand_holding_object = None # don't change the color of things you pick up self.player_right_hand.setColorScaleOff() self.player_left_hand.setColorScaleOff() self.player_head = self.actor.exposeJoint(None, "modelRoot", "Head") self.neck = self.actor.controlJoint(None, "modelRoot", "Head") self.controlMap = { "turn_left": 0, "turn_right": 0, "move_forward": 0, "move_backward": 0, "move_right": 0, "move_left": 0, "look_up": 0, "look_down": 0, "look_left": 0, "look_right": 0, "jump": 0, } # see update method for uses, indices are [turn left, turn right, move_forward, move_back, move_right, move_left, look_up, look_down, look_right, look_left] # turns are in degrees per second, moves are in units per second self.speeds = [270, 270, 5, 5, 5, 5, 60, 60, 60, 60] self.originalPos = self.actor.getPos() bubble = loader.loadTexture("media/textures/thought_bubble.png") # bubble.setTransparency(TransparencyAttrib.MAlpha) self.speech_bubble = DirectLabel( parent=self.actor, text="", text_wordwrap=10, pad=(3, 3), relief=None, text_scale=(0.3, 0.3), pos=(0, 0, 3.6), frameColor=(0.6, 0.2, 0.1, 0.5), textMayChange=1, text_frame=(0, 0, 0, 1), text_bg=(1, 1, 1, 1), ) # self.myImage= self.speech_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.speech_bubble.setColorScaleOff() self.speech_bubble.component("text0").textNode.setCardDecal(1) self.speech_bubble.setBillboardAxis() # hide the speech bubble from IsisAgent's own camera self.speech_bubble.hide(BitMask32.bit(1)) self.thought_bubble = DirectLabel( parent=self.actor, text="", text_wordwrap=9, text_frame=(1, 0, -2, 1), text_pos=(0, 0.5), text_bg=(1, 1, 1, 0), relief=None, frameSize=(0, 1.5, -2, 3), text_scale=(0.18, 0.18), pos=(0, 0.2, 3.6), textMayChange=1, image=bubble, image_pos=(0, 0.1, 0), sortOrder=5, ) self.thought_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.thought_bubble.setColorScaleOff() self.thought_bubble.component("text0").textNode.setFrameColor(1, 1, 1, 0) self.thought_bubble.component("text0").textNode.setFrameAsMargin(0.1, 0.1, 0.1, 0.1) self.thought_bubble.component("text0").textNode.setCardDecal(1) self.thought_bubble.setBillboardAxis() # hide the thought bubble from IsisAgent's own camera self.thought_bubble.hide(BitMask32.bit(1)) # disable by default self.thought_bubble.hide() self.thought_filter = {} # only show thoughts whose values are in here self.last_spoke = 0 # timers to keep track of last thought/speech and self.last_thought = 0 # hide visualizations # put a camera on ralph self.fov = NodePath(Camera("RaphViz")) self.fov.node().setCameraMask(BitMask32.bit(1)) # position the camera to be infront of Boxman's face. self.fov.reparentTo(self.player_head) # x,y,z are not in standard orientation when parented to player-Head self.fov.setPos(0, 0.2, 0) # if P=0, canrea is looking directly up. 90 is back of head. -90 is on face. self.fov.setHpr(0, -90, 0) lens = self.fov.node().getLens() lens.setFov(60) # degree field of view (expanded from 40) lens.setNear(0.2) # self.fov.node().showFrustum() # displays a box around his head # self.fov.place() self.prevtime = 0 self.current_frame_count = 0 self.isSitting = False self.isDisabled = False self.msg = None self.actorNodePath.setPythonTag("agent", self) # Initialize the action queue, with a maximum length of queueSize self.queue = [] self.queueSize = queueSize self.lastSense = 0 def setLayout(self, layout): """ Dummy method called by spatial methods for use with objects. Doesn't make sense for an agent that can move around.""" pass def setPos(self, pos): """ Wrapper to set the position of the ODE geometry, which in turn sets the visual model's geometry the next time the update() method is called. """ self.setGeomPos(pos) def setPosition(self, pos): self.setPos(pos) def reparentTo(self, parent): self.actorNodePath.reparentTo(parent) def setControl(self, control, value): """Set the state of one of the character's movement controls. """ self.controlMap[control] = value def get_objects_in_field_of_vision(self, exclude=["isisobject"]): """ This works in an x-ray style. Fast. Works best if you listen to http://en.wikipedia.org/wiki/Rock_Art_and_the_X-Ray_Style while you use it. needs to exclude isisobjects since they cannot be serialized """ objects = {} for obj in base.render.findAllMatches("**/IsisObject*"): if not obj.hasPythonTag("isisobj"): continue o = obj.getPythonTag("isisobj") bounds = o.activeModel.getBounds() bounds.xform(o.activeModel.getMat(self.fov)) if self.fov.node().isInView(o.activeModel.getPos(self.fov)): pos = o.activeModel.getPos(render) pos = (pos[0], pos[1], pos[2] + o.getHeight() / 2) p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) object_dict = {} if "x_pos" not in exclude: object_dict["x_pos"] = p3[0] if "y_pos" not in exclude: object_dict["y_pos"] = p3[2] if "distance" not in exclude: object_dict["distance"] = o.activeModel.getDistance(self.fov) if "orientation" not in exclude: object_dict["orientation"] = o.activeModel.getH(self.fov) if "actions" not in exclude: object_dict["actions"] = o.list_actions() if "isisobject" not in exclude: object_dict["isisobject"] = o # add item to dinctionary objects[o] = object_dict return objects def get_agents_in_field_of_vision(self): """ This works in an x-ray vision style as well""" agents = {} for agent in base.render.findAllMatches("**/agent-*"): if not agent.hasPythonTag("agent"): continue a = agent.getPythonTag("agent") bounds = a.actorNodePath.getBounds() bounds.xform(a.actorNodePath.getMat(self.fov)) pos = a.actorNodePath.getPos(self.fov) if self.fov.node().isInView(pos): p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) agentDict = { "x_pos": p3[0], "y_pos": p3[2], "distance": a.actorNodePath.getDistance(self.fov), "orientation": a.actorNodePath.getH(self.fov), } agents[a] = agentDict return agents def in_view(self, isisobj): """ Returns true iff a particular isisobject is in view """ return len( filter(lambda x: x["isisobject"] == isisobj, self.get_objects_in_field_of_vision(exclude=[]).values()) ) def get_objects_in_view(self): """ Gets objects through ray tracing. Slow""" return self.picker.get_objects_in_view() def control__turn_left__start(self, speed=None): self.setControl("turn_left", 1) self.setControl("turn_right", 0) if speed: self.speeds[0] = speed return "success" def control__turn_left__stop(self): self.setControl("turn_left", 0) return "success" def control__turn_right__start(self, speed=None): self.setControl("turn_left", 0) self.setControl("turn_right", 1) if speed: self.speeds[1] = speed return "success" def control__turn_right__stop(self): self.setControl("turn_right", 0) return "success" def control__move_forward__start(self, speed=None): self.setControl("move_forward", 1) self.setControl("move_backward", 0) if speed: self.speeds[2] = speed return "success" def control__move_forward__stop(self): self.setControl("move_forward", 0) return "success" def control__move_backward__start(self, speed=None): self.setControl("move_forward", 0) self.setControl("move_backward", 1) if speed: self.speeds[3] = speed return "success" def control__move_backward__stop(self): self.setControl("move_backward", 0) return "success" def control__move_left__start(self, speed=None): self.setControl("move_left", 1) self.setControl("move_right", 0) if speed: self.speeds[4] = speed return "success" def control__move_left__stop(self): self.setControl("move_left", 0) return "success" def control__move_right__start(self, speed=None): self.setControl("move_right", 1) self.setControl("move_left", 0) if speed: self.speeds[5] = speed return "success" def control__move_right__stop(self): self.setControl("move_right", 0) return "success" def control__look_left__start(self, speed=None): self.setControl("look_left", 1) self.setControl("look_right", 0) if speed: self.speeds[9] = speed return "success" def control__look_left__stop(self): self.setControl("look_left", 0) return "success" def control__look_right__start(self, speed=None): self.setControl("look_right", 1) self.setControl("look_left", 0) if speed: self.speeds[8] = speed return "success" def control__look_right__stop(self): self.setControl("look_right", 0) return "success" def control__look_up__start(self, speed=None): self.setControl("look_up", 1) self.setControl("look_down", 0) if speed: self.speeds[6] = speed return "success" def control__look_up__stop(self): self.setControl("look_up", 0) return "success" def control__look_down__start(self, speed=None): self.setControl("look_down", 1) self.setControl("look_up", 0) if speed: self.speeds[7] = speed return "success" def control__look_down__stop(self): self.setControl("look_down", 0) return "success" def control__jump(self): self.setControl("jump", 1) return "success" def control__view_objects(self): """ calls a raytrace to to all objects in view """ objects = self.get_objects_in_field_of_vision() self.control__say("If I were wearing x-ray glasses, I could see %i items" % len(objects)) print "Objects in view:", objects return objects def control__sense(self): """ perceives the world, returns percepts dict """ percepts = dict() # eyes: visual matricies # percepts['vision'] = self.sense__get_vision() # objects in purview (cheating object recognition) percepts["objects"] = self.sense__get_objects() # global position in environment - our robots can have GPS :) percepts["position"] = self.sense__get_position() # language: get last utterances that were typed percepts["language"] = self.sense__get_utterances() # agents: returns a map of agents to a list of actions that have been sensed percepts["agents"] = self.sense__get_agents() print percepts return percepts def control__think(self, message, layer=0): """ Changes the contents of an agent's thought bubble""" # only say things that are checked in the controller if self.thought_filter.has_key(layer): self.thought_bubble.show() self.thought_bubble["text"] = message # self.thought_bubble.component('text0').textNode.setShadow(0.05, 0.05) # self.thought_bubble.component('text0').textNode.setShadowColor(self.thought_filter[layer]) self.last_thought = 0 return "success" def control__say(self, message="Hello!"): self.speech_bubble["text"] = message self.last_spoke = 0 return "success" """ Methods explicitly for IsisScenario files """ def put_in_front_of(self, isisobj): # find open direction pos = isisobj.getGeomPos() direction = render.getRelativeVector(isisobj, Vec3(0, 1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], [isisobj.geom]) print "CLOSEST", closestEntry, closestObject if closestObject == None: self.setPosition(pos + Vec3(0, 2, 0)) else: print "CANNOT PLACE IN FRONT OF %s BECAUSE %s IS THERE" % (isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(0, -1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], [isisobj.geom]) if closestEntry == None: self.setPosition(pos + Vec3(0, -2, 0)) else: print "CANNOT PLACE BEHIND %s BECAUSE %s IS THERE" % (isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(1, 0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( "aimRay", 5, [pos, direction], [isisobj.geom] ) if closestEntry == None: self.setPosition(pos + Vec3(2, 0, 0)) else: print "CANNOT PLACE TO LEFT OF %s BECAUSE %s IS THERE" % (isisobj, closestObject) # there's only one option left, do it anyway self.setPosition(pos + Vec3(-2, 0, 0)) # rotate agent to look at it self.actorNodePath.setPos(self.getGeomPos()) self.actorNodePath.lookAt(pos) self.setH(self.actorNodePath.getH()) def put_in_right_hand(self, target): return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) def put_in_left_hand(self, target): return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) def __get_object_in_center_of_view(self): direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.fov.getPos(render) exclude = [] # [base.render.find("**/kitchenNode*").getPythonTag("isisobj").geom] closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], exclude) return closestObject def pick_object_up_with(self, target, hand_slot, hand_joint): """ Attaches an IsisObject, target, to the hand joint. Does not check anything first, other than the fact that the hand joint is not currently holding something else.""" if hand_slot != None: print "already holding " + hand_slot.getName() + "." return None else: if target.layout: target.layout.remove(target) target.layout = None # store original position target.originalHpr = target.getHpr(render) target.disable() # turn off physics if target.body: target.body.setGravityMode(0) target.reparentTo(hand_joint) target.setPosition(hand_joint.getPos(render)) target.setTag("heldBy", self.name) if hand_joint == self.player_right_hand: self.right_hand_holding_object = target elif hand_joint == self.player_left_hand: self.left_hand_holding_object = target hand_slot = target return target def control__pick_up_with_right_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return "error: no target in reach" else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with right hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) else: print "object (" + target.name + ") is not graspable (i.e. in view and close enough)." return "error: object not graspable" def control__pick_up_with_left_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with left hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) else: print "object (" + target.name + ") is not graspable (i.e. in view and close enough)." return "error: object not graspable" def control__drop_from_right_hand(self): print "attempting to drop object from right hand.\n" if self.right_hand_holding_object is None: print "right hand is not holding an object." return False if self.right_hand_holding_object.getNetTag("heldBy") == self.name: self.right_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_right_hand.getPos(render) heldPos = self.right_hand_holding_object.geom.getPosition() self.right_hand_holding_object.setPosition(pos) self.right_hand_holding_object.synchPosQuatToNode() self.right_hand_holding_object.setTag("heldBy", "") self.right_hand_holding_object.setRotation(self.right_hand_holding_object.originalHpr) self.right_hand_holding_object.enable() if self.right_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.right_hand_holding_object.body.setGravityMode(1) self.right_hand_holding_object.getBody().setForce(quat.xform(Vec3(0, force, 0))) self.right_hand_holding_object = None return "success" else: return "Error: not being held by agent %s" % (self.name) def control__drop_from_left_hand(self): print "attempting to drop object from left hand.\n" if self.left_hand_holding_object is None: return "left hand is not holding an object." if self.left_hand_holding_object.getNetTag("heldBy") == self.name: self.left_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_left_hand.getPos(render) heldPos = self.left_hand_holding_object.geom.getPosition() self.left_hand_holding_object.setPosition(pos) self.left_hand_holding_object.synchPosQuatToNode() self.left_hand_holding_object.setTag("heldBy", "") self.left_hand_holding_object.setRotation(self.left_hand_holding_object.originalHpr) self.left_hand_holding_object.enable() if self.left_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.left_hand_holding_object.body.setGravityMode(1) self.left_hand_holding_object.getBody().setForce(quat.xform(Vec3(0, force, 0))) self.left_hand_holding_object = None return "success" else: return "Error: not being held by agent %s" % (self.name) def control__use_right_hand(self, target=None, action=None): # TODO, rename this to use object with if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "Trying to use object", target if self.can_grasp(target): if target.call(self, action, self.right_hand_holding_object) or ( self.right_hand_holding_object and self.right_hand_holding_object.call(self, action, target) ): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def control__use_left_hand(self, target=None, action=None): if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") if self.can_grasp(target): if target.call(self, action, self.left_hand_holding_object) or ( self.left_hand_holding_object and self.left_hand_holding_object.call(self, action, target) ): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def can_grasp(self, isisobject): distance = isisobject.activeModel.getDistance(self.fov) print "distance = ", distance return distance < 5.0 def is_holding(self, object_name): return ( self.left_hand_holding_object and (self.left_hand_holding_object.getPythonTag("isisobj").name == object_name) ) or ( self.right_hand_holding_object and (self.right_hand_holding_object.getPythonTag("isisobj").name == object_name) ) def empty_hand(self): if self.left_hand_holding_object is None: return self.player_left_hand elif self.right_hand_holding_object is None: return self.player_right_hand return False def has_empty_hand(self): return self.empty_hand() is not False def control__use_aimed(self): """ Try to use the object that we aim at, by calling its callback method. """ target = self.__get_object_in_center_of_view() if target.selectionCallback: target.selectionCallback(self, dir) return "success" def sense__get_position(self): x, y, z = self.actorNodePath.getPos() h, p, r = self.actorNodePath.getHpr() # FIXME # neck is not positioned in Blockman nh,np,nr = self.agents[agent_id].actor_neck.getHpr() left_hand_obj = "" right_hand_obj = "" if self.left_hand_holding_object: left_hand_obj = self.left_hand_holding_object.getName() if self.right_hand_holding_object: right_hand_obj = self.right_hand_holding_object.getName() return { "body_x": x, "body_y": y, "body_z": z, "body_h": h, "body_p": p, "body_r": r, "in_left_hand": left_hand_obj, "in_right_hand": right_hand_obj, } def sense__get_vision(self): self.fov.node().saveScreenshot("temp.jpg") image = Image.open("temp.jpg") os.remove("temp.jpg") return image def sense__get_objects(self): return dict([x.getName(), y] for (x, y) in self.get_objects_in_field_of_vision().items()) def sense__get_agents(self): curSense = time() agents = {} for k, v in self.get_agents_in_field_of_vision().items(): v["actions"] = k.get_other_agents_actions(self.lastSense, curSense) agents[k.name] = v self.lastSense = curSense return agents def sense__get_utterances(self): """ Clear out the buffer of things that the teacher has typed, FIXME: this doesn't work right now """ return [] utterances = self.teacher_utterances self.teacher_utterances = [] return utterances def debug__print_objects(self): text = "Objects in FOV: " + ", ".join(self.sense__get_objects().keys()) print text def add_action_to_history(self, action, args, result=0): self.queue.append((time(), action, args, result)) if len(self.queue) > self.queueSize: self.queue.pop(0) def get_other_agents_actions(self, start=0, end=None): if not end: end = time() actions = [] for act in self.queue: if act[0] >= start: if act[0] < end: actions.append(act) else: break return actions def update(self, stepSize=0.1): self.speed = [0.0, 0.0] self.actorNodePath.setPos(self.geom.getPosition() + Vec3(0, 0, -0.70)) self.actorNodePath.setQuat(self.getQuat()) # the values in self.speeds are used as coefficientes for turns and movements if self.controlMap["turn_left"] != 0: self.addToH(stepSize * self.speeds[0]) if self.controlMap["turn_right"] != 0: self.addToH(-stepSize * self.speeds[1]) if self.verticalState == "ground": # these actions require contact with the ground if self.controlMap["move_forward"] != 0: self.speed[1] = self.speeds[2] if self.controlMap["move_backward"] != 0: self.speed[1] = -self.speeds[3] if self.controlMap["move_left"] != 0: self.speed[0] = -self.speeds[4] if self.controlMap["move_right"] != 0: self.speed[0] = self.speeds[5] if self.controlMap["jump"] != 0: kinematicCharacterController.jump(self) # one jump at a time! self.controlMap["jump"] = 0 if self.controlMap["look_left"] != 0: self.neck.setR(bound(self.neck.getR(), -60, 60) + stepSize * 80) if self.controlMap["look_right"] != 0: self.neck.setR(bound(self.neck.getR(), -60, 60) - stepSize * 80) if self.controlMap["look_up"] != 0: self.neck.setP(bound(self.neck.getP(), -60, 80) + stepSize * 80) if self.controlMap["look_down"] != 0: self.neck.setP(bound(self.neck.getP(), -60, 80) - stepSize * 80) kinematicCharacterController.update(self, stepSize) """ Update the held object position to be in the hands """ if self.right_hand_holding_object != None: self.right_hand_holding_object.setPosition(self.player_right_hand.getPos(render)) if self.left_hand_holding_object != None: self.left_hand_holding_object.setPosition(self.player_left_hand.getPos(render)) # Update the dialog box and thought windows # This allows dialogue window to gradually decay (changing transparancy) and then disappear self.last_spoke += stepSize / 2 self.last_thought += stepSize / 2 self.speech_bubble["text_bg"] = (1, 1, 1, 1 / (self.last_spoke + 0.01)) self.speech_bubble["frameColor"] = (0.6, 0.2, 0.1, 0.5 / (self.last_spoke + 0.01)) if self.last_spoke > 2: self.speech_bubble["text"] = "" if self.last_thought > 1: self.thought_bubble.hide() # If the character is moving, loop the run animation. # If he is standing still, stop the animation. if ( (self.controlMap["move_forward"] != 0) or (self.controlMap["move_backward"] != 0) or (self.controlMap["move_left"] != 0) or (self.controlMap["move_right"] != 0) ): if self.isMoving is False: self.isMoving = True else: if self.isMoving: self.current_frame_count = 5.0 self.isMoving = False total_frame_num = self.actor.getNumFrames("walk") if self.isMoving: self.current_frame_count = self.current_frame_count + (stepSize * 250.0) if self.current_frame_count > total_frame_num: self.current_frame_count = self.current_frame_count % total_frame_num self.actor.pose("walk", self.current_frame_count) elif self.current_frame_count != 0: self.current_frame_count = 0 self.actor.pose("idle", 0) return Task.cont def destroy(self): self.disable() self.specialDirectObject.ignoreAll() self.actorNodePath.removeNode() del self.specialDirectObject kinematicCharacterController.destroy(self) def disable(self): self.isDisabled = True self.geom.disable() self.footRay.disable() def enable(self): self.footRay.enable() self.geom.enable() self.isDisabled = False """ Set camera to correct height above the center of the capsule when crouching and when standing up. """ def crouch(self): kinematicCharacterController.crouch(self) self.camH = self.crouchCamH def crouchStop(self): """ Only change the camera's placement when the KCC allows standing up. See the KCC to find out why it might not allow it. """ if kinematicCharacterController.crouchStop(self): self.camH = self.walkCamH
class JellybeanRewardGui(DirectFrame): notify = directNotify.newCategory('JellybeanRewardGui') PreCountdownDelay = 1.0 CountDownRate = 0.2 JarLabelTextColor = (0.95, 0.95, 0.0, 1.0) JarLabelMaxedTextColor = (1.0, 0.0, 0.0, 1.0) def __init__(self, doneEvent): self.doneEvent = doneEvent DirectFrame.__init__(self) self.reparentTo(aspect2d) self.setPos(0.0, 0.0, 0.16) self.stash() publicPartyGui = loader.loadModel('phase_4/models/parties/publicPartyGUI') self.frame = DirectFrame(parent=self, geom=publicPartyGui.find('**/activities_background'), geom_pos=(-0.8, 0.0, 0.2), geom_scale=2.0, relief=None) self.earnedLabel = DirectLabel(parent=self, relief=None, text=str(0), text_align=TextNode.ACenter, text_pos=(0.0, -0.07), text_scale=0.2, text_fg=(0.95, 0.95, 0.0, 1.0), text_font=ToontownGlobals.getSignFont(), textMayChange=True, image=DirectGuiGlobals.getDefaultDialogGeom(), image_scale=(0.33, 1.0, 0.33), pos=(-0.3, 0.0, 0.2), scale=0.9) purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui') jarImage = purchaseModels.find('**/Jar') self.jarLabel = DirectLabel(parent=self, relief=None, text=str(0), text_align=TextNode.ACenter, text_pos=(0.0, -0.07), text_scale=0.2, text_fg=JellybeanRewardGui.JarLabelTextColor, text_font=ToontownGlobals.getSignFont(), textMayChange=True, image=jarImage, scale=0.7, pos=(0.3, 0.0, 0.17)) purchaseModels.removeNode() del purchaseModels jarImage.removeNode() del jarImage self.messageLabel = DirectLabel(parent=self, relief=None, text='', text_align=TextNode.ALeft, text_wordwrap=16.0, text_scale=0.07, pos=(-0.52, 0.0, -0.1), textMayChange=True) self.doubledJellybeanLabel = DirectLabel(parent=self, relief=None, text=TTLocalizer.PartyRewardDoubledJellybean, text_align=TextNode.ACenter, text_wordwrap=12.0, text_scale=0.09, text_fg=(1.0, 0.125, 0.125, 1.0), pos=(0.0, 0.0, -0.465), textMayChange=False) self.doubledJellybeanLabel.hide() self.closeButton = DirectButton(parent=self, relief=None, text=TTLocalizer.PartyJellybeanRewardOK, text_align=TextNode.ACenter, text_scale=0.065, text_pos=(0.0, -0.625), geom=(publicPartyGui.find('**/startButton_up'), publicPartyGui.find('**/startButton_down'), publicPartyGui.find('**/startButton_rollover'), publicPartyGui.find('**/startButton_inactive')), geom_pos=(-0.39, 0.0, 0.125), command=self._close) publicPartyGui.removeNode() del publicPartyGui self.countSound = base.loadSfx('phase_13/audio/sfx/tick_counter_short.mp3') self.overMaxSound = base.loadSfx('phase_13/audio/sfx/tick_counter_overflow.mp3') return def showReward(self, earnedAmount, jarAmount, message): JellybeanRewardGui.notify.debug('showReward( earnedAmount=%d, jarAmount=%d, ...)' % (earnedAmount, jarAmount)) self.earnedCount = earnedAmount self.earnedLabel['text'] = str(self.earnedCount) self.jarCount = jarAmount self.jarMax = base.localAvatar.getMaxMoney() self.jarLabel['text'] = str(self.jarCount) self.jarLabel['text_fg'] = JellybeanRewardGui.JarLabelTextColor self.messageLabel['text'] = message if base.cr.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_DAY) or base.cr.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_PARTIES_HOLIDAY) or base.cr.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_PARTIES_HOLIDAY_MONTH): self.doubledJellybeanLabel.show() else: self.doubledJellybeanLabel.hide() self.unstash() taskMgr.doMethodLater(JellybeanRewardGui.PreCountdownDelay, self.transferOneJellybean, 'JellybeanRewardGuiTransferOneJellybean', extraArgs=[]) def transferOneJellybean(self): if self.earnedCount == 0: return self.earnedCount -= 1 self.earnedLabel['text'] = str(self.earnedCount) self.jarCount += 1 if self.jarCount <= self.jarMax: self.jarLabel['text'] = str(self.jarCount) elif self.jarCount > self.jarMax: self.jarLabel['text_fg'] = JellybeanRewardGui.JarLabelMaxedTextColor if self.jarCount <= self.jarMax: base.playSfx(self.countSound) else: base.playSfx(self.overMaxSound) taskMgr.doMethodLater(JellybeanRewardGui.CountDownRate, self.transferOneJellybean, 'JellybeanRewardGuiTransferOneJellybean', extraArgs=[]) def _close(self): taskMgr.remove('JellybeanRewardGuiTransferOneJellybean') self.stash() messenger.send(self.doneEvent) def destroy(self): taskMgr.remove('JellybeanRewardGuiTransferOneJellybean') del self.countSound del self.overMaxSound self.frame.destroy() self.earnedLabel.destroy() self.jarLabel.destroy() self.messageLabel.destroy() self.closeButton.destroy() DirectFrame.destroy(self)
class DistributedCannonDefenseShip(DistributedNPCSimpleShip): specialHitSfx = {} coldShotHitSfx = None sharkChompSfx = {} def __init__(self, cr): DistributedNPCSimpleShip.__init__(self, cr) self.goldStolenlbl = None self.hasGoldlbl = None self.hasBNote = None self.textureCard = None self.goldIcon = None self.flameEffects = [] self.isSinkingWhileOnFire = False self.healthModifier = 0 self.modifierSet = False self.shipStatsSet = False self.shipStatIndex = None self.initHealthBar() self.initIndicatorIcons() self.sinkTimeScale = CannonDefenseGlobals.SHIP_SINK_DURATION_SCALE self.sharkActor = Actor( 'models/char/pir_r_gam_fsh_lgComTshark.bam', {'attack': 'models/char/pir_a_gam_fsh_lgComTshark_attack.bam'}) self.sharkParallel = None self.fader = None if not self.coldShotHitSfx: DistributedCannonDefenseShip.specialHitSfx = { InventoryType.DefenseCannonMineInWater: loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_MINE_HIT), InventoryType.DefenseCannonBomb: loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_BOMB_HIT), InventoryType.DefenseCannonHotShot: loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_HOTSHOT_HIT), InventoryType.DefenseCannonFireStorm: loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_FIRESTORM_HIT), InventoryType.DefenseCannonChumShot: loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_SHARK) } DistributedCannonDefenseShip.coldShotHitSfx = loadSfx( SoundGlobals.SFX_MINIGAME_CANNON_ICE_HIT) DistributedCannonDefenseShip.sharkChompSfxs = [ loadSfx(SoundGlobals.SFX_MONSTER_SMASH_01), loadSfx(SoundGlobals.SFX_MONSTER_SMASH_02), loadSfx(SoundGlobals.SFX_MONSTER_SMASH_03) ] def buildShip(self): DistributedNPCSimpleShip.buildShip(self) self.model.sfxAlternativeStyle = True def setupLocalStats(self): DistributedNPCSimpleShip.setupLocalStats(self) def setShipStatIndex(self, statIndex): self.shipStatsSet = True self.shipStatIndex = statIndex self.maxHp = CannonDefenseGlobals.shipStats[ self.shipStatIndex]['shipHp'] self.maxMastHealth = CannonDefenseGlobals.shipStats[ self.shipStatIndex]['mastHp'] self.healthBar.setPos( 0.0, 0.0, CannonDefenseGlobals.shipStats[self.shipStatIndex] ['healthBarHeight']) if self.modifierSet: self.calcModifiedHealth() def setHealthModifier(self, modifier): self.modifierSet = True self.healthModifier = modifier if self.shipStatsSet: self.calcModifiedHealth() def calcModifiedHealth(self): if self.healthModifier == 0: return None self.maxHp += self.healthModifier * self.maxHp * CannonDefenseGlobals.ENEMY_DIFFICULTY_INCREASE mastList = CannonDefenseGlobals.shipStats[self.shipStatIndex]['mastHp'] mastFinalHp = [] for mastHealth in mastList: hp = mastHealth hp += self.healthModifier * mastHealth * CannonDefenseGlobals.ENEMY_DIFFICULTY_INCREASE mastFinalHp.append(hp) self.maxMastHealth = mastFinalHp def setLogo(self, logo): self.logo = logo def setStyle(self, style): self.style = style def announceGenerate(self): DistributedNPCSimpleShip.announceGenerate(self) rad = (self.model.dimensions / 2.0).length() cn = NodePath(CollisionNode('c')) cs = CollisionSphere(0, 0, 0, rad) cn.node().addSolid(cs) cn.reparentTo(self.model.modelCollisions) cn.setTransform(self.model.center.getTransform(self)) cn.node().setIntoCollideMask(PiratesGlobals.GenericShipBitmask) self.model.defendSphere = cn self.model.modelRoot.setScale(CannonDefenseGlobals.SHIP_SCALE) self.fadeIn(CannonDefenseGlobals.SHIP_FADEIN) self.smoother.setExpectedBroadcastPeriod(0.29999999999999999) self.smoother.setDelay(2) self.healthBar.reparentTo(self.model.modelRoot) def initHealthBar(self): self.healthBar = DirectWaitBar( frameSize=(-0.34999999999999998, 0.34999999999999998, -0.040000000000000001, 0.040000000000000001), relief=DGG.FLAT, frameColor=(0.0, 0.0, 0.0, 0.0), borderWidth=(0.0, 0.0), barColor=(0.0, 1.0, 0.0, 1.0), scale=100) self.healthBar.setBillboardPointEye() self.healthBar['value'] = 100 self.healthBar.hide(OTPRender.ReflectionCameraBitmask) self.healthBar.setLightOff() def initIndicatorIcons(self): self.textureCard = loader.loadModel( 'models/textureCards/pir_m_gam_can_ship_icons') if self.textureCard: self.goldIcon = self.textureCard.find('**/pir_t_shp_can_gold*') self.goldStolenlbl = DirectLabel( parent=self.healthBar, relief=None, pos=(0, 0, 0.20000000000000001), text_align=TextNode.ACenter, text_scale=0.5, textMayChange=0, text='!', text_fg=PiratesGuiGlobals.TextFG23, text_shadow=PiratesGuiGlobals.TextShadow, text_font=PiratesGlobals.getPirateBoldOutlineFont(), sortOrder=2) self.goldStolenlbl.setTransparency(1) self.goldStolenlbl.hide() self.hasGoldlbl = DirectLabel(parent=self.healthBar, relief=None, pos=(0, 0, 0.34999999999999998), image=self.goldIcon, image_scale=0.5, image_pos=(0, 0, 0), sortOrder=2) self.hasGoldlbl.setTransparency(1) self.hasGoldlbl.hide() self.hasBNote = self.healthBar.attachNewNode('noteIndicator') self.bnoteBack = loader.loadModel( 'models/textureCards/skillIcons').find( '**/pir_t_gui_can_moneyIcon').copyTo(self.hasBNote) self.hasBNote.setZ(0.34999999999999998) self.hasBNote.setScale(0.59999999999999998) self.hasBNote.hide() def getHealthBarColor(self, health): return CannonDefenseGlobals.SHIP_HEALTH_COLORS[int( (health / 100.0) * (len(CannonDefenseGlobals.SHIP_HEALTH_COLORS) - 1))] def setHealthState(self, health): DistributedNPCSimpleShip.setHealthState(self, health) self.healthBar['value'] = health self.healthBar['barColor'] = self.getHealthBarColor(health) def setCurrentState(self, state): if state == CannonDefenseGlobals.SHIP_STATE_STEALING: self.goldStolenlbl.show() elif state == CannonDefenseGlobals.SHIP_STATE_HASTREASURE: self.hasGoldlbl.show() self.goldStolenlbl.hide() elif state == CannonDefenseGlobals.SHIP_STATE_HASBNOTES: self.hasBNote.show() self.goldStolenlbl.hide() else: self.hasGoldlbl.hide() self.hasBNote.hide() self.goldStolenlbl.hide() rad = (self.model.dimensions / 2.0).length() cn = NodePath(CollisionNode('c')) cs = CollisionSphere(0, 0, 0, rad) cn.node().addSolid(cs) cn.reparentTo(self.model.modelCollisions) cn.setTransform(self.model.center.getTransform(self)) cn.node().setIntoCollideMask(PiratesGlobals.GenericShipBitmask) self.model.defendSphere = cn self.model.modelRoot.setScale(CannonDefenseGlobals.SHIP_SCALE) self.fadeIn(CannonDefenseGlobals.SHIP_FADEIN) self.smoother.setExpectedBroadcastPeriod(0.29999999999999999) self.smoother.setDelay(2) self.healthBar.reparentTo(self.model.modelRoot) def initHealthBar(self): self.healthBar = DirectWaitBar( frameSize=(-0.34999999999999998, 0.34999999999999998, -0.040000000000000001, 0.040000000000000001), relief=DGG.FLAT, frameColor=(0.0, 0.0, 0.0, 0.0), borderWidth=(0.0, 0.0), barColor=(0.0, 1.0, 0.0, 1.0), scale=100) self.healthBar.setBillboardPointEye() self.healthBar['value'] = 100 self.healthBar.hide(OTPRender.ReflectionCameraBitmask) self.healthBar.setLightOff() def initIndicatorIcons(self): self.textureCard = loader.loadModel( 'models/textureCards/pir_m_gam_can_ship_icons') if self.textureCard: self.goldIcon = self.textureCard.find('**/pir_t_shp_can_gold*') self.goldStolenlbl = DirectLabel( parent=self.healthBar, relief=None, pos=(0, 0, 0.20000000000000001), text_align=TextNode.ACenter, text_scale=0.5, textMayChange=0, text='!', text_fg=PiratesGuiGlobals.TextFG23, text_shadow=PiratesGuiGlobals.TextShadow, text_font=PiratesGlobals.getPirateBoldOutlineFont(), sortOrder=2) self.goldStolenlbl.setTransparency(1) self.goldStolenlbl.hide() self.hasGoldlbl = DirectLabel(parent=self.healthBar, relief=None, pos=(0, 0, 0.34999999999999998), image=self.goldIcon, image_scale=0.5, image_pos=(0, 0, 0), sortOrder=2) self.hasGoldlbl.setTransparency(1) self.hasGoldlbl.hide() self.hasBNote = self.healthBar.attachNewNode('noteIndicator') self.bnoteBack = loader.loadModel( 'models/textureCards/skillIcons').find( '**/pir_t_gui_can_moneyIcon').copyTo(self.hasBNote) self.hasBNote.setZ(0.34999999999999998) self.hasBNote.setScale(0.59999999999999998) self.hasBNote.hide() def getHealthBarColor(self, health): return CannonDefenseGlobals.SHIP_HEALTH_COLORS[int( (health / 100.0) * (len(CannonDefenseGlobals.SHIP_HEALTH_COLORS) - 1))] def setHealthState(self, health): DistributedNPCSimpleShip.setHealthState(self, health) self.healthBar['value'] = health self.healthBar['barColor'] = self.getHealthBarColor(health) def setCurrentState(self, state): if state == CannonDefenseGlobals.SHIP_STATE_STEALING: self.goldStolenlbl.show() elif state == CannonDefenseGlobals.SHIP_STATE_HASTREASURE: self.hasGoldlbl.show() self.goldStolenlbl.hide() elif state == CannonDefenseGlobals.SHIP_STATE_HASBNOTES: self.hasBNote.show() self.goldStolenlbl.hide() else: self.hasGoldlbl.hide() self.hasBNote.hide() self.goldStolenlbl.hide() def calculateLook(self): pass def playProjectileHitSfx(self, ammoSkillId, hitSail): if ammoSkillId in [ InventoryType.DefenseCannonColdShotInWater, InventoryType.DefenseCannonSmokePowder ]: return None if ammoSkillId in self.specialHitSfx: sfx = self.specialHitSfx[ammoSkillId] base.playSfx(sfx, node=self, cutoff=2000) return None DistributedNPCSimpleShip.playProjectileHitSfx(self, ammoSkillId, hitSail) def projectileWeaponHit(self, skillId, ammoSkillId, skillResult, targetEffects, pos, normal, codes, attacker, itemEffects=[]): DistributedNPCSimpleShip.projectileWeaponHit(self, skillId, ammoSkillId, skillResult, targetEffects, pos, normal, codes, attacker, itemEffects) def sinkingBegin(self): self.healthBar.reparentTo(hidden) if len(self.flameEffects) > 0: self.isSinkingWhileOnFire = True DistributedNPCSimpleShip.sinkingBegin(self) def sinkingEnd(self): while len(self.flameEffects) > 0: effect = self.flameEffects.pop() effect.stopLoop() DistributedNPCSimpleShip.sinkingEnd(self) def addStatusEffect(self, effectId, attackerId, duration=0, timeLeft=0, timestamp=0, buffData=[0]): if effectId == WeaponGlobals.C_CANNON_DEFENSE_FIRE: self.addFireEffect(self.getModelRoot().getPos()) if effectId == WeaponGlobals.C_CANNON_DEFENSE_ICE: base.playSfx(self.coldShotHitSfx, node=self, cutoff=2000) DistributedNPCSimpleShip.addStatusEffect(self, effectId, attackerId, duration, timeLeft, timestamp, buffData) def removeStatusEffect(self, effectId, attackerId): DistributedNPCSimpleShip.removeStatusEffect(self, effectId, attackerId) if effectId == WeaponGlobals.C_CANNON_DEFENSE_FIRE: if not self.isSinkingWhileOnFire: while len(self.flameEffects) > 0: effect = self.flameEffects.pop() effect.stopLoop() def addFireEffect(self, pos): fireEffect = ShipFire.getEffect() if fireEffect: fireEffect.reparentTo(self.getModelRoot()) fireEffect.setPos(pos) fireEffect.setHpr(90, -15, 0) fireEffect.startLoop() fireEffect.setEffectScale(20.0) self.flameEffects.append(fireEffect) def playSharkAttack(self, pos): if self.sharkActor.getCurrentAnim() == None: self.sharkActor.wrtReparentTo(self.getModelRoot()) self.sharkActor.setPos(self, pos) self.sharkActor.setScale(20) self.sharkActor.play('attack') sharkAttackEffect = None if base.options.getSpecialEffectsSetting( ) >= base.options.SpecialEffectsLow: effect = CannonSplash.getEffect() if effect: effect.reparentTo(base.effectsRoot) effect.setPos(self, pos) effect.setZ(1) effect.play() sharkAttackEffect = Func(self.playAttackEffect, pos) hprIvalShip = LerpHprInterval(self.getModelRoot(), duration=3, hpr=(0, 0, -180)) s1 = Sequence(Wait(0.75), hprIvalShip, Func(self.getModelRoot().stash)) s2 = Sequence(Wait(0.75), sharkAttackEffect, Wait(0.5), sharkAttackEffect) self.sharkParallel = Parallel(s1, s2) self.sharkParallel.start() taskMgr.doMethodLater(self.sharkActor.getDuration('attack'), self.detachShark, self.uniqueName('playSharkAttack'), extraArgs=[]) def playAttackEffect(self, pos): effect = BulletEffect.getEffect() if effect: effect.reparentTo(base.effectsRoot) effect.setPos(self, pos) effect.loadObjects(6) effect.play() sfx = random.choice(self.sharkChompSfxs) base.playSfx(sfx, node=self.getModelRoot(), cutoff=2000) def detachShark(self): self.sharkActor.detachNode() def delete(self): if self.fader: self.fader.pause() self.fader = None DistributedNPCSimpleShip.delete(self) def destroy(self): if self.goldStolenlbl: self.goldStolenlbl.destroy() self.goldStolenlbl = None if self.hasGoldlbl: self.hasGoldlbl.destroy() self.hasGoldlbl = None if self.textureCard: self.textureCard.removeNode() self.textureCard = None self.goldIcon = None if self.healthBar: self.healthBar.destroy() if self.sharkActor: self.sharkActor.cleanUp() self.sharkActor.removeNode() if self.sharkParallel: self.sharkParallel.pause() self.sharkParallel = None DistributedNPCSimpleShip.destroy(self) def fadeIn(self, length): if self.fader: self.fader.finish() self.fader = None self.setTransparency(1) self.fader = Sequence( self.colorScaleInterval(length, Vec4(1, 1, 1, 1), Vec4(1, 1, 1, 0)), Func(self.clearTransparency)) self.fader.start() def fadeOut(self, length): if self.fader: self.fader.finish() self.fader = None self.setTransparency(1) self.fader = Sequence( self.colorScaleInterval(length, Vec4(1, 1, 1, 0), Vec4(1, 1, 1, 1)), Func(self.hide), Func(self.clearTransparency)) self.fader.start()
class VoteResultsTrolleyPanel(DirectFrame): __module__ = __name__ notify = DirectNotifyGlobal.directNotify.newCategory('VoteResultsTrolleyPanel') def __init__(self, numPlayers, avIdList, votes, directions, namesList, disconnectedList, directionToGo, directionReason, directionTotals, *args, **kwargs): opts = {'relief': None, 'geom': DGG.getDefaultDialogGeom(), 'geom_color': ToontownGlobals.GlobalDialogColor[:3] + (0.8,), 'geom_scale': (1.75, 1, 0.25), 'pos': (0, 0, 0.825)} opts.update(kwargs) DirectFrame.__init__(self, *args, **opts) self.initialiseoptions(VoteResultsTrolleyPanel) listMultiplier = 1 if TravelGameGlobals.SpoofFour: listMultiplier = 4 self.avIdList = avIdList * listMultiplier self.numPlayers = numPlayers * listMultiplier self.votes = votes * listMultiplier self.directions = directions * listMultiplier self.namesList = namesList * listMultiplier self.disconnectedList = disconnectedList * listMultiplier self.directionToGo = directionToGo self.directionReason = directionReason self.directionTotals = directionTotals self.entryList = [] self.rowFrame = [] self.upDownFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(-1)) self.upLabel = DirectLabel(parent=self, relief=None, pos=(-0.5, 0, 0.06), text=TTLocalizer.TravelGameDirections[0] + ':', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.downLabel = DirectLabel(parent=self, relief=None, pos=(0.5, 0, 0.06), text=TTLocalizer.TravelGameDirections[1] + ':', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalVotesUpLabel = DirectLabel(parent=self.upLabel, relief=None, pos=(0.2, 0, 0.0), text='0', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalVotesDownLabel = DirectLabel(parent=self.downLabel, relief=None, pos=(0.2, 0, 0.0), text='0', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(self.numPlayers)) self.totalVotesLabels = [self.totalVotesUpLabel, self.totalVotesDownLabel] self.resultFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(0.5)) self.resultLabel = DirectLabel(parent=self.resultFrame, text='', text_scale=0.06, pos=(0.7, 0, 0.0), text_align=TextNode.ACenter) self.setupResultLabel() for index in range(self.numPlayers): frame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(index)) self.rowFrame.append(frame) nameLabel = DirectFrame(parent=frame, relief=None, pos=(0.46, 0.0, 0.0), text=self.namesList[index], text_fg=(0.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ACenter, text_font=DGG.getDefaultFont()) votesUpLabel = DirectLabel(parent=frame, relief=None, pos=(1.2, 0.0, 0.0), text='', text_fg=(0, 0, 1, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont()) votesDownLabel = DirectLabel(parent=frame, relief=None, pos=(1.43, 0.0, 0.0), text='', text_fg=(1, 0, 0, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont()) nameLabel.hide() self.entryList.append((nameLabel, votesUpLabel, votesDownLabel)) self.avVotesLabel = {} self.avArrows = {} matchingGameGui = loader.loadModel('phase_3.5/models/gui/matching_game_gui') minnieArrow = matchingGameGui.find('**/minnieArrow') from toontown.minigame.DistributedTravelGame import map3dToAspect2d for index in range(self.numPlayers): avId = self.avIdList[index] av = base.cr.doId2do.get(avId) if av: height = av.getHeight() avPos = av.getPos(render) avPos.setZ(av.getZ() + 5) labelPos = map3dToAspect2d(render, avPos) if not labelPos: continue labelPos.setZ(labelPos.getZ() + 0.3) arrow = None if self.votes[index] > 0: arrow = aspect2d.attachNewNode('avArrow') minnieArrow.copyTo(arrow) arrow.setScale(1.1, 1, 1.15) arrow.setPos(labelPos) if self.directions[index] == 0: arrow.setR(-90) arrow.setColorScale(0, 0, 1, 1) else: arrow.setR(90) arrow.setColorScale(1, 0, 0, 1) arrow.wrtReparentTo(self.resultFrame) arrow.hide() self.avArrows[index] = arrow fgColor = Vec4(0, 0, 0, 1) if self.votes[index] > 0: if self.directions[index] == 0: fgColor = Vec4(0, 0, 1, 1) else: fgColor = Vec4(1, 0, 0, 1) if self.votes[index] > 0: newLabel = DirectLabel(parent=aspect2d, relief=None, pos=labelPos, text='test', text_fg=(1, 1, 1, 1), text_scale=0.1, text_align=TextNode.ACenter, text_font=ToontownGlobals.getSignFont(), text_pos=(0, -0.01, 0)) else: newLabel = DirectLabel(parent=aspect2d, geom=DGG.getDefaultDialogGeom(), geom_scale=(0.2, 1, 0.2), relief=None, pos=labelPos, text='test', text_fg=(0.5, 0.5, 0.5, 1), text_scale=0.1, text_align=TextNode.ACenter, text_font=ToontownGlobals.getSignFont(), text_pos=(0, -0.035, 0)) newLabel.wrtReparentTo(self.resultFrame) newLabel.hide() self.avVotesLabel[index] = newLabel matchingGameGui.removeNode() self.curArrowSfxIndex = 0 self.upArrowSfx = [] self.downArrowSfx = [] for i in range(5): self.upArrowSfx.append(base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.mp3')) self.downArrowSfx.append(base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_red_arrow.mp3')) self.winVoteSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_win_vote.mp3') self.noVoteSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_square_no_vote_1.mp3') self.loseVoteSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_lose_vote.mp3') self.localAvatarWon = False self.localAvatarLost = False localIndex = self.avIdList.index(base.localAvatar.doId) localDirection = self.directions[localIndex] localVotes = self.votes[localIndex] if localVotes: if localDirection == self.directionToGo: if not TravelGameGlobals.ReverseWin: self.localAvatarWon = True else: self.localAvatarLost = True elif not TravelGameGlobals.ReverseWin: self.localAvatarLost = True else: self.localAvatarWon = True return def getRowPos(self, place): return Point3(-0.72, -0.01, 0.0 - place * 0.1) def setupResultLabel(self): reasonStr = '' if self.directionReason == TravelGameGlobals.ReasonVote: if self.directionToGo == 0: losingDirection = 1 else: losingDirection = 0 diffVotes = self.directionTotals[self.directionToGo] - self.directionTotals[losingDirection] if diffVotes > 1: reasonStr = TTLocalizer.TravelGameReasonVotesPlural % {'dir': TTLocalizer.TravelGameDirections[self.directionToGo], 'numVotes': diffVotes} else: reasonStr = TTLocalizer.TravelGameReasonVotesSingular % {'dir': TTLocalizer.TravelGameDirections[self.directionToGo], 'numVotes': diffVotes} elif self.directionReason == TravelGameGlobals.ReasonRandom: reasonStr = TTLocalizer.TravelGameReasonRandom % {'dir': TTLocalizer.TravelGameDirections[self.directionToGo], 'numVotes': self.directionTotals[self.directionToGo]} elif self.directionReason == TravelGameGlobals.ReasonPlaceDecider: reasonStr = TravelGameReasonPlace % {'name': 'TODO NAME', 'dir': TTLocalizer.TravelGameDirections[self.directionToGo]} self.resultLabel['text'] = reasonStr self.resultLabel.hide() def createOnePlayerSequence(self, index, duration): numVotes = self.votes[index] direction = self.directions[index] def ticketTicker(t, label = self.entryList[index][direction + 1], startVotes = 0, endVotes = numVotes): label['text'] = str(int(t * endVotes + startVotes)) track = Parallel() startVotes = 0 for prev in range(index): if self.directions[prev] == direction: startVotes += self.votes[prev] def totalTicker(t, label = self.totalVotesLabels[direction], startVotes = startVotes, additionalVotes = numVotes): label['text'] = str(int(t * additionalVotes + startVotes)) track.append(LerpFunc(totalTicker, duration=duration, name='countTotal %d' % index)) if self.avVotesLabel.has_key(index): def avVotesTicker(t, label = self.avVotesLabel[index], startVotes = 0, endVotes = numVotes, direction = direction): oldValue = label['text'] newValue = int(t * endVotes + startVotes) label['text'] = str(newValue) if not oldValue == label['text']: if newValue: if direction == 0: self.upArrowSfx[self.curArrowSfxIndex].play() else: self.downArrowSfx[self.curArrowSfxIndex].play() self.curArrowSfxIndex += 1 if self.curArrowSfxIndex >= len(self.upArrowSfx): self.curArrowSfxIndex = 0 label = self.avVotesLabel[index] track.append(Func(self.avVotesLabel[index].show, name='showName %d' % index)) if self.avArrows.has_key(index): track.append(Func(self.avArrows[index].show, name='showArrow %d' % index)) if direction == 0 and numVotes: pass elif direction == 1 and numVotes: pass else: track.append(SoundInterval(self.noVoteSfx)) track.append(LerpFunc(avVotesTicker, duration=duration, name='countAvVotes %d' % index)) return track def startMovie(self): self.movie = Sequence() for index in range(self.numPlayers): track = self.createOnePlayerSequence(index, 1.25) self.movie.append(track) self.movie.append(Wait(0.75)) self.movie.append(Func(self.resultLabel.show)) soundAndWait = Parallel() soundAndWait.append(Wait(2.0)) if self.localAvatarWon: soundAndWait.append(SoundInterval(self.winVoteSfx)) elif self.localAvatarLost: soundAndWait.append(SoundInterval(self.loseVoteSfx, duration=0.43)) self.movie.append(soundAndWait) self.movie.start() def destroy(self): self.movie.finish() del self.movie del self.winVoteSfx del self.noVoteSfx del self.upArrowSfx del self.loseVoteSfx del self.downArrowSfx DirectFrame.destroy(self)
class DistCogdoGame(DistCogdoGameBase, DistributedObject): notify = directNotify.newCategory('DistCogdoGame') def __init__(self, cr): DistributedObject.__init__(self, cr) base.cogdoGame = self cr.cogdoGame = self self._waitingStartLabel = DirectLabel( text=TTL.MinigameWaitingForOtherPlayers, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075) self._waitingStartLabel.hide() self.loadFSM = ClassicFSM.ClassicFSM('DistCogdoGame.loaded', [ State.State('NotLoaded', self.enterNotLoaded, self.exitNotLoaded, ['Loaded']), State.State('Loaded', self.enterLoaded, self.exitLoaded, ['NotLoaded']) ], 'NotLoaded', 'NotLoaded') self.loadFSM.enterInitialState() self.fsm = ClassicFSM.ClassicFSM('DistCogdoGame', [ State.State('Visible', self.enterVisible, self.exitVisible, ['Intro']), State.State('Intro', self.enterIntro, self.exitIntro, ['WaitServerStart']), State.State('WaitServerStart', self.enterWaitServerStart, self.exitWaitServerStart, ['Game']), State.State('Game', self.enterGame, self.exitGame, ['Finish']), State.State('Finish', self.enterFinish, self.exitFinish, ['Off']), State.State('Off', self.enterOff, self.exitOff, ['Visible']) ], 'Off', 'Off') self.fsm.enterInitialState() self.difficultyOverride = None self.exteriorZoneOverride = None self._gotInterior = StateVar(False) self._toonsInEntranceElev = StateVar(False) self._wantStashElevator = StateVar(False) self._stashElevatorFC = FunctionCall(self._doStashElevator, self._toonsInEntranceElev, self._gotInterior, self._wantStashElevator) def getTitle(self): pass def getInstructions(self): pass def setInteriorId(self, interiorId): self._interiorId = interiorId def setExteriorZone(self, exteriorZone): self.exteriorZone = exteriorZone def setDifficultyOverrides(self, difficultyOverride, exteriorZoneOverride): if difficultyOverride != CogdoGameConsts.NoDifficultyOverride: self.difficultyOverride = difficultyOverride / float( CogdoGameConsts.DifficultyOverrideMult) if exteriorZoneOverride != CogdoGameConsts.NoExteriorZoneOverride: self.exteriorZoneOverride = exteriorZoneOverride def getInterior(self): return self.cr.getDo(self._interiorId) def getEntranceElevator(self, callback): return self.getInterior().getEntranceElevator(callback) def getToonIds(self): interior = self.getInterior() if interior is not None: return interior.getToonIds() return [] def getToon(self, toonId): if toonId in self.cr.doId2do: return self.cr.doId2do[toonId] return None def getNumPlayers(self): return len(self.getToonIds()) def isSinglePlayer(self): if self.getNumPlayers() == 1: return 1 return 0 def announceGenerate(self): DistributedObject.announceGenerate(self) self.loadFSM.request('Loaded') self._requestInterior() self.notify.info('difficulty: %s, safezoneId: %s' % (self.getDifficulty(), self.getSafezoneId())) def _requestInterior(self): self.cr.relatedObjectMgr.requestObjects( [self._interiorId], allCallback=self._handleGotInterior) def _handleGotInterior(self, objs): self._gotInterior.set(True) self.getEntranceElevator(self.placeEntranceElev) def stashEntranceElevator(self): self._wantStashElevator.set(True) def placeEntranceElev(self, elev): pass def _doStashElevator(self, toonsInEntranceElev, gotInterior, wantStashElevator): if gotInterior: interior = self.getInterior() if interior: if not toonsInEntranceElev and wantStashElevator: interior.stashElevatorIn() else: interior.stashElevatorIn(False) def disable(self): base.cogdoGame = None self.cr.cogdoGame = None self.fsm.requestFinalState() self.loadFSM.requestFinalState() self.fsm = None self.loadFSM = None DistributedObject.disable(self) def delete(self): self._stashElevatorFC.destroy() self._wantStashElevator.destroy() self._toonsInEntranceElev.destroy() self._gotInterior.destroy() self._waitingStartLabel.destroy() self._waitingStartLabel = None DistributedObject.delete(self) def getDifficulty(self): if self.difficultyOverride is not None: return self.difficultyOverride if hasattr(base, 'cogdoGameDifficulty'): return float(base.cogdoGameDifficulty) return CogdoGameConsts.getDifficulty(self.getSafezoneId()) def getSafezoneId(self): if self.exteriorZoneOverride is not None: return self.exteriorZoneOverride if hasattr(base, 'cogdoGameSafezoneId'): return CogdoGameConsts.getSafezoneId(base.cogdoGameSafezoneId) return CogdoGameConsts.getSafezoneId(self.exteriorZone) def enterNotLoaded(self): pass def exitNotLoaded(self): pass def enterLoaded(self): pass def exitLoaded(self): pass def enterOff(self): pass def exitOff(self): pass def setVisible(self): self.fsm.request('Visible') def setIntroStart(self): self.fsm.request('Intro') def enterVisible(self): self._toonsInEntranceElev.set(True) def exitVisible(self): pass def enterIntro(self, duration=MinigameGlobals.rulesDuration): base.cr.playGame.getPlace().fsm.request('Game') self._rulesDoneEvent = self.uniqueName('cogdoGameRulesDone') self.accept(self._rulesDoneEvent, self._handleRulesDone) self._rulesPanel = CogdoGameRulesPanel('CogdoGameRulesPanel', self.getTitle(), '', self._rulesDoneEvent, timeout=duration) self._rulesPanel.load() self._rulesPanel.enter() def exitIntro(self): self._toonsInEntranceElev.set(False) self.ignore(self._rulesDoneEvent) if self._rulesPanel: self._rulesPanel.exit() self._rulesPanel.unload() self._rulesPanel = None def _handleRulesDone(self): self.ignore(self._rulesDoneEvent) self._rulesPanel.exit() self._rulesPanel.unload() self._rulesPanel = None self.fsm.request('WaitServerStart') self.d_setAvatarReady() def d_setAvatarReady(self): self.sendUpdate('setAvatarReady', []) def enterWaitServerStart(self): numToons = 1 interior = self.getInterior() if interior: numToons = len(interior.getToonIds()) if numToons > 1: msg = TTL.MinigameWaitingForOtherPlayers else: msg = TTL.MinigamePleaseWait self._waitingStartLabel['text'] = msg self._waitingStartLabel.show() def exitWaitServerStart(self): self._waitingStartLabel.hide() def setGameStart(self, timestamp): self._startTime = globalClockDelta.networkToLocalTime(timestamp) self.fsm.request('Game') def getStartTime(self): return self._startTime def enterGame(self): pass def exitGame(self): pass def setGameFinish(self, timestamp): self._finishTime = globalClockDelta.networkToLocalTime(timestamp) self.fsm.request('Finish') def getFinishTime(self): return self._finishTime def enterFinish(self): pass def exitFinish(self): pass def setToonSad(self, toonId): pass def setToonDisconnect(self, toonId): pass
class GameOverScreen(): def __init__(self): # a fill panel so the player doesn't see how everything # gets loaded in the background self.frameMain = DirectFrame( # size of the frame frameSize = (base.a2dLeft, base.a2dRight, base.a2dTop, base.a2dBottom), image = "Logo.png", image_scale = (0.612/2.0, 1, 0.495/2.0), image_pos = (0, 0, 0.7), # tramsparent bg color frameColor = (0, 0, 0, 1)) self.frameMain.setTransparency(1) self.lblWin = DirectLabel( scale = 0.25, pos = (0, 0, 0.25), frameColor = (0, 0, 0, 0), text = _("You Succeeded"), text_align = TextNode.ACenter, text_fg = (1,1,1,1)) self.lblWin.reparentTo(self.frameMain) self.lblTime = DirectLabel( scale = 0.07, pos = (0, 0, 0.00), frameColor = (0, 0, 0, 0), text = "your time", text_align = TextNode.ACenter, text_fg = (1,1,1,1)) self.lblTime.reparentTo(self.frameMain) self.lblResult = DirectLabel( scale = 0.40, pos = (0, 0, -0.25), frameColor = (0, 0, 0, 0), text = "00:00", text_align = TextNode.ACenter, text_fg = (1,1,1,1)) self.lblResult.reparentTo(self.frameMain) self.btnContinue = DirectButton( scale = (0.25, 0.25, 0.25), # some temp text text = _("Continue..."), text_scale = (0.5, 0.5, 0.5), # set the alignment to right text_align = TextNode.ACenter, # put the text on the right side of the button text_pos = (0, 0), # set the text color to black text_fg = (1,1,1,1), text_shadow = (0.3, 0.3, 0.1, 1), text_shadowOffset = (0.05, 0.05), relief = 1, frameColor = (0,0,0,0), pressEffect = False, pos = (0, 0, -0.65), command = lambda: base.messenger.send("Exit"), rolloverSound = None, clickSound = None) self.btnContinue.setTransparency(1) self.btnContinue.reparentTo(self.frameMain) self.hide() def show(self, winLoose, resulttime): if winLoose == "win": timestring = "%d:%02d" % (resulttime/60, resulttime%60) self.lblResult["text"] = timestring self.lblTime.show() self.lblResult.show() else: self.lblWin["text"] = _("You Loose") self.lblTime.hide() self.lblResult.hide() self.frameMain.show() def hide(self): self.frameMain.hide()
class VoteResultsPanel(DirectFrame): notify = DirectNotifyGlobal.directNotify.newCategory('VoteResultsPanel') def __init__(self, numPlayers, avIdList, votes, directions, namesList, disconnectedList, directionToGo, directionReason, directionTotals, *args, **kwargs): opts = { 'relief': None, 'geom': DGG.getDefaultDialogGeom(), 'geom_color': ToontownGlobals.GlobalDialogColor[:3] + (0.8, ), 'geom_scale': (1.75, 1, 0.75), 'pos': (0, 0, 0.525) } opts.update(kwargs) DirectFrame.__init__(self, *args, **opts) self.initialiseoptions(VoteResultsPanel) listMultiplier = 1 if TravelGameGlobals.SpoofFour: listMultiplier = 4 self.avIdList = avIdList * listMultiplier self.numPlayers = numPlayers * listMultiplier self.votes = votes * listMultiplier self.directions = directions * listMultiplier self.namesList = namesList * listMultiplier self.disconnectedList = disconnectedList * listMultiplier self.directionToGo = directionToGo self.directionReason = directionReason self.directionTotals = directionTotals self.entryList = [] self.rowFrame = [] self.upDownFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(-1)) self.upLabel = DirectLabel(parent=self.upDownFrame, relief=None, pos=(1.2, 0, 0.0), text=TTLocalizer.TravelGameDirections[0], text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.downLabel = DirectLabel(parent=self.upDownFrame, relief=None, pos=(1.43, 0, 0.0), text=TTLocalizer.TravelGameDirections[1], text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(self.numPlayers)) self.totalText = DirectLabel(parent=self.totalFrame, relief=None, pos=(1.0, 0, 0.0), text='Total', text_fg=(0.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalVotesUpLabel = DirectLabel(parent=self.totalFrame, relief=None, pos=(1.2, 0, 0.0), text='', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalVotesDownLabel = DirectLabel(parent=self.totalFrame, relief=None, pos=(1.43, 0, 0.0), text='', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalVotesLabels = [ self.totalVotesUpLabel, self.totalVotesDownLabel ] self.resultFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(5)) self.resultLabel = DirectLabel(parent=self.resultFrame, text='', text_scale=0.06, pos=(0.7, 0, 0.0), text_align=TextNode.ACenter) self.setupResultLabel() for index in xrange(self.numPlayers): frame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(index)) self.rowFrame.append(frame) nameLabel = DirectFrame(parent=frame, relief=None, pos=(0.46, 0.0, 0.0), text=self.namesList[index], text_fg=(0.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ACenter, text_font=DGG.getDefaultFont()) votesUpLabel = DirectLabel(parent=frame, relief=None, pos=(1.2, 0.0, 0.0), text='', text_fg=(0, 0, 1, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont()) votesDownLabel = DirectLabel(parent=frame, relief=None, pos=(1.43, 0.0, 0.0), text='', text_fg=(1, 0, 0, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont()) nameLabel.hide() self.entryList.append((nameLabel, votesUpLabel, votesDownLabel)) return def getRowPos(self, place): return Point3(-0.72, -0.01, 0.2 - place * 0.1) def setupResultLabel(self): reasonStr = '' if self.directionReason == TravelGameGlobals.ReasonVote: reasonStr = TTLocalizer.TravelGameReasonVotes % { 'dir': TTLocalizer.TravelGameDirections[self.directionToGo], 'numVotes': self.directionTotals[self.directionToGo] } elif self.directionReason == TravelGameGlobals.ReasonRandom: reasonStr = TTLocalizer.TravelGameReasonRandom % { 'dir': TTLocalizer.TravelGameDirections[self.directionToGo], 'numVotes': self.directionTotals[self.directionToGo] } elif self.directionReason == TravelGameGlobals.ReasonPlaceDecider: reasonStr = TravelGameReasonPlace % { 'name': 'TODO NAME', 'dir': TTLocalizer.TravelGameDirections[self.directionToGo] } self.resultLabel['text'] = reasonStr self.resultLabel.hide() def createOnePlayerSequence(self, index, duration): numVotes = self.votes[index] direction = self.directions[index] def ticketTicker(t, label=self.entryList[index][(direction + 1)], startVotes=0, endVotes=numVotes): label['text'] = str(int(t * endVotes + startVotes)) track = Parallel() track.append( Func(self.entryList[index][0].show, name='showName %d' % index)) track.append( LerpFunc(ticketTicker, duration=duration, name='countVotes %d' % index)) startVotes = 0 for prev in xrange(index): if self.directions[prev] == direction: startVotes += self.votes[prev] def totalTicker(t, label=self.totalVotesLabels[direction], startVotes=startVotes, additionalVotes=numVotes): label['text'] = str(int(t * additionalVotes + startVotes)) track.append( LerpFunc(totalTicker, duration=duration, name='countTotal %d' % index)) return track def startMovie(self): self.movie = Sequence() for index in xrange(self.numPlayers): track = self.createOnePlayerSequence(index, 1.25) self.movie.append(track) self.movie.append(Wait(0.75)) self.movie.append(Func(self.resultLabel.show)) self.movie.append(Wait(2.0)) self.movie.start() def destroy(self): self.movie.finish() DirectFrame.destroy(self)
class DistributedIceGame(DistributedMinigame.DistributedMinigame, DistributedIceWorld.DistributedIceWorld): notify = directNotify.newCategory("DistributedIceGame") MaxLocalForce = 100 MaxPhysicsForce = 25000 def __init__(self, cr): DistributedMinigame.DistributedMinigame.__init__(self, cr) DistributedIceWorld.DistributedIceWorld.__init__(self, cr) self.gameFSM = ClassicFSM.ClassicFSM( "DistributedIceGame", [ State.State("off", self.enterOff, self.exitOff, ["inputChoice"]), State.State( "inputChoice", self.enterInputChoice, self.exitInputChoice, ["waitServerChoices", "moveTires", "displayVotes", "cleanup"], ), State.State( "waitServerChoices", self.enterWaitServerChoices, self.exitWaitServerChoices, ["moveTires", "cleanup"], ), State.State("moveTires", self.enterMoveTires, self.exitMoveTires, ["synch", "cleanup"]), State.State("synch", self.enterSynch, self.exitSynch, ["inputChoice", "scoring", "cleanup"]), State.State("scoring", self.enterScoring, self.exitScoring, ["cleanup", "finalResults", "inputChoice"]), State.State("finalResults", self.enterFinalResults, self.exitFinalResults, ["cleanup"]), State.State("cleanup", self.enterCleanup, self.exitCleanup, []), ], "off", "cleanup", ) self.addChildGameFSM(self.gameFSM) self.cameraThreeQuarterView = (0, -22, 45, 0, -62.89, 0) self.tireDict = {} self.forceArrowDict = {} self.canDrive = False self.timer = None self.timerStartTime = None self.curForce = 0 self.curHeading = 0 self.headingMomentum = 0.0 self.forceMomentum = 0.0 self.allTireInputs = None self.curRound = 0 self.curMatch = 0 self.controlKeyWarningLabel = DirectLabel( text=TTLocalizer.IceGameControlKeyWarning, text_fg=VBase4(1, 0, 0, 1), relief=None, pos=(0.0, 0, 0), scale=0.15, ) self.controlKeyWarningLabel.hide() self.waitingMoveLabel = DirectLabel( text=TTLocalizer.IceGameWaitingForPlayersToFinishMove, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075, ) self.waitingMoveLabel.hide() self.waitingSyncLabel = DirectLabel( text=TTLocalizer.IceGameWaitingForAISync, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075, ) self.waitingSyncLabel.hide() self.infoLabel = DirectLabel(text="", text_fg=VBase4(0, 0, 0, 1), relief=None, pos=(0.0, 0, 0.7), scale=0.075) self.updateInfoLabel() self.lastForceArrowUpdateTime = 0 self.sendForceArrowUpdateAsap = False self.treasures = [] self.penalties = [] self.obstacles = [] self.controlKeyPressed = False self.controlKeyWarningIval = None return def delete(self): DistributedIceWorld.DistributedIceWorld.delete(self) DistributedMinigame.DistributedMinigame.delete(self) if self.controlKeyWarningIval: self.controlKeyWarningIval.finish() self.controlKeyWarningIval = None self.controlKeyWarningLabel.destroy() del self.controlKeyWarningLabel self.waitingMoveLabel.destroy() del self.waitingMoveLabel self.waitingSyncLabel.destroy() del self.waitingSyncLabel self.infoLabel.destroy() del self.infoLabel for treasure in self.treasures: treasure.destroy() del self.treasures for penalty in self.penalties: penalty.destroy() del self.penalties for obstacle in self.obstacles: obstacle.removeNode() del self.obstacles del self.gameFSM return def announceGenerate(self): DistributedMinigame.DistributedMinigame.announceGenerate(self) DistributedIceWorld.DistributedIceWorld.announceGenerate(self) self.debugTaskName = self.uniqueName("debugTask") def getTitle(self): return TTLocalizer.IceGameTitle def getInstructions(self): szId = self.getSafezoneId() numPenalties = IceGameGlobals.NumPenalties[szId] result = TTLocalizer.IceGameInstructions if numPenalties == 0: result = TTLocalizer.IceGameInstructionsNoTnt return result def getMaxDuration(self): return 0 def load(self): self.notify.debug("load") DistributedMinigame.DistributedMinigame.load(self) self.music = base.loadMusic("phase_4/audio/bgm/MG_IceGame.ogg") self.gameBoard = loader.loadModel("phase_4/models/minigames/ice_game_icerink") background = loader.loadModel("phase_4/models/minigames/ice_game_2d") backgroundWide = loader.loadModel("phase_4/models/minigames/iceslide_ground") background.reparentTo(self.gameBoard) backgroundWide.reparentTo(self.gameBoard) backgroundWide.setPos(0, -0.3, -0.5) self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0) self.gameBoard.setScale(1.0) self.setupSimulation() index = 0 for avId in self.avIdList: self.setupTire(avId, index) self.setupForceArrow(avId) index += 1 for index in xrange(len(self.avIdList), 4): self.setupTire(-index, index) self.setupForceArrow(-index) self.showForceArrows(realPlayersOnly=True) self.westWallModel = NodePath() if not self.westWallModel.isEmpty(): self.westWallModel.reparentTo(self.gameBoard) self.westWallModel.setPos(IceGameGlobals.MinWall[0], IceGameGlobals.MinWall[1], 0) self.westWallModel.setScale(4) self.eastWallModel = NodePath() if not self.eastWallModel.isEmpty(): self.eastWallModel.reparentTo(self.gameBoard) self.eastWallModel.setPos(IceGameGlobals.MaxWall[0], IceGameGlobals.MaxWall[1], 0) self.eastWallModel.setScale(4) self.eastWallModel.setH(180) self.arrowKeys = ArrowKeys.ArrowKeys() self.target = loader.loadModel("phase_3/models/misc/sphere") self.target.setScale(0.01) self.target.reparentTo(self.gameBoard) self.target.setPos(0, 0, 0) self.scoreCircle = loader.loadModel("phase_4/models/minigames/ice_game_score_circle") self.scoreCircle.setScale(0.01) self.scoreCircle.reparentTo(self.gameBoard) self.scoreCircle.setZ(IceGameGlobals.TireRadius / 2.0) self.scoreCircle.setAlphaScale(0.5) self.scoreCircle.setTransparency(1) self.scoreCircle.hide() self.treasureModel = loader.loadModel("phase_4/models/minigames/ice_game_barrel") self.penaltyModel = loader.loadModel("phase_4/models/minigames/ice_game_tnt2") self.penaltyModel.setScale(0.75, 0.75, 0.7) szId = self.getSafezoneId() obstacles = IceGameGlobals.Obstacles[szId] index = 0 cubicObstacle = IceGameGlobals.ObstacleShapes[szId] for pos in obstacles: newPos = Point3(pos[0], pos[1], IceGameGlobals.TireRadius) newObstacle = self.createObstacle(newPos, index, cubicObstacle) self.obstacles.append(newObstacle) index += 1 self.countSound = loader.loadSfx("phase_3.5/audio/sfx/tick_counter.ogg") self.treasureGrabSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_vine_game_bananas.ogg") self.penaltyGrabSound = loader.loadSfx("phase_4/audio/sfx/MG_cannon_fire_alt.ogg") self.tireSounds = [] for tireIndex in xrange(4): tireHit = loader.loadSfx("phase_4/audio/sfx/Golf_Hit_Barrier_1.ogg") wallHit = loader.loadSfx("phase_4/audio/sfx/MG_maze_pickup.ogg") obstacleHit = loader.loadSfx("phase_4/audio/sfx/Golf_Hit_Barrier_2.ogg") self.tireSounds.append({"tireHit": tireHit, "wallHit": wallHit, "obstacleHit": obstacleHit}) self.arrowRotateSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_ice_force_rotate.ogg") self.arrowUpSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_ice_force_increase_3sec.ogg") self.arrowDownSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_ice_force_decrease_3sec.ogg") self.scoreCircleSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_ice_scoring_1.ogg") def unload(self): self.notify.debug("unload") DistributedMinigame.DistributedMinigame.unload(self) del self.music self.gameBoard.removeNode() del self.gameBoard for forceArrow in self.forceArrowDict.values(): forceArrow.removeNode() del self.forceArrowDict self.scoreCircle.removeNode() del self.scoreCircle del self.countSound def onstage(self): self.notify.debug("onstage") DistributedMinigame.DistributedMinigame.onstage(self) self.gameBoard.reparentTo(render) self.__placeToon(self.localAvId) self.moveCameraToTop() self.scorePanels = [] base.playMusic(self.music, looping=1, volume=0.8) def offstage(self): self.notify.debug("offstage") self.music.stop() self.gameBoard.hide() self.infoLabel.hide() for avId in self.tireDict: self.tireDict[avId]["tireNodePath"].hide() for panel in self.scorePanels: panel.cleanup() del self.scorePanels for obstacle in self.obstacles: obstacle.hide() for treasure in self.treasures: treasure.nodePath.hide() for penalty in self.penalties: penalty.nodePath.hide() for avId in self.avIdList: av = self.getAvatar(avId) if av: av.dropShadow.show() av.resetLOD() taskMgr.remove(self.uniqueName("aimtask")) self.arrowKeys.destroy() del self.arrowKeys DistributedMinigame.DistributedMinigame.offstage(self) def handleDisabledAvatar(self, avId): self.notify.debug("handleDisabledAvatar") self.notify.debug("avatar " + str(avId) + " disabled") DistributedMinigame.DistributedMinigame.handleDisabledAvatar(self, avId) def setGameReady(self): if not self.hasLocalToon: return self.notify.debug("setGameReady") if DistributedMinigame.DistributedMinigame.setGameReady(self): return for index in xrange(self.numPlayers): avId = self.avIdList[index] toon = self.getAvatar(avId) if toon: toon.reparentTo(render) self.__placeToon(avId) toon.forwardSpeed = 0 toon.rotateSpeed = False toon.dropShadow.hide() toon.setAnimState("Sit") if avId in self.tireDict: tireNp = self.tireDict[avId]["tireNodePath"] toon.reparentTo(tireNp) toon.setY(1.0) toon.setZ(-3) toon.startLookAround() def setGameStart(self, timestamp): if not self.hasLocalToon: return self.notify.debug("setGameStart") DistributedMinigame.DistributedMinigame.setGameStart(self, timestamp) for avId in self.remoteAvIdList: toon = self.getAvatar(avId) if toon: toon.stopLookAround() self.scores = [0] * self.numPlayers spacing = 0.4 for i in xrange(self.numPlayers): avId = self.avIdList[i] avName = self.getAvatarName(avId) scorePanel = MinigameAvatarScorePanel.MinigameAvatarScorePanel(avId, avName) scorePanel.setScale(0.9) scorePanel.setPos(-0.583 - spacing * (self.numPlayers - 1 - i), 0.0, -0.15) scorePanel.reparentTo(base.a2dTopRight) scorePanel.makeTransparent(0.75) self.scorePanels.append(scorePanel) self.arrowKeys.setPressHandlers( [ self.__upArrowPressed, self.__downArrowPressed, self.__leftArrowPressed, self.__rightArrowPressed, self.__controlPressed, ] ) def isInPlayState(self): if not self.gameFSM.getCurrentState(): return False if not self.gameFSM.getCurrentState().getName() == "play": return False return True def enterOff(self): self.notify.debug("enterOff") def exitOff(self): pass def enterInputChoice(self): self.notify.debug("enterInputChoice") self.forceLocalToonToTire() self.controlKeyPressed = False if self.curRound == 0: self.setupStartOfMatch() else: self.notify.debug("self.curRound = %s" % self.curRound) self.timer = ToontownTimer.ToontownTimer() self.timer.hide() if self.timerStartTime != None: self.startTimer() self.showForceArrows(realPlayersOnly=True) self.localForceArrow().setPosHpr(0, 0, -1.0, 0, 0, 0) self.localForceArrow().reparentTo(self.localTireNp()) self.localForceArrow().setY(IceGameGlobals.TireRadius) self.localTireNp().headsUp(self.target) self.notify.debug("self.localForceArrow() heading = %s" % self.localForceArrow().getH()) self.curHeading = self.localTireNp().getH() self.curForce = 25 self.updateLocalForceArrow() for avId in self.forceArrowDict: forceArrow = self.forceArrowDict[avId] forceArrow.setPosHpr(0, 0, -1.0, 0, 0, 0) tireNp = self.tireDict[avId]["tireNodePath"] forceArrow.reparentTo(tireNp) forceArrow.setY(IceGameGlobals.TireRadius) tireNp.headsUp(self.target) self.updateForceArrow(avId, tireNp.getH(), 25) taskMgr.add(self.__aimTask, self.uniqueName("aimtask")) if base.localAvatar.laffMeter: base.localAvatar.laffMeter.stop() self.sendForceArrowUpdateAsap = False return def exitInputChoice(self): if not self.controlKeyPressed: if self.controlKeyWarningIval: self.controlKeyWarningIval.finish() self.controlKeyWarningIval = None self.controlKeyWarningIval = Sequence( Func(self.controlKeyWarningLabel.show), self.controlKeyWarningLabel.colorScaleInterval( 10, VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1) ), Func(self.controlKeyWarningLabel.hide), ) self.controlKeyWarningIval.start() if self.timer != None: self.timer.destroy() self.timer = None self.timerStartTime = None self.hideForceArrows() self.arrowRotateSound.stop() self.arrowUpSound.stop() self.arrowDownSound.stop() taskMgr.remove(self.uniqueName("aimtask")) return def enterWaitServerChoices(self): self.waitingMoveLabel.show() self.showForceArrows(True) def exitWaitServerChoices(self): self.waitingMoveLabel.hide() self.hideForceArrows() def enterMoveTires(self): for key in self.tireDict: body = self.tireDict[key]["tireBody"] body.setAngularVel(0, 0, 0) body.setLinearVel(0, 0, 0) for index in xrange(len(self.allTireInputs)): input = self.allTireInputs[index] avId = self.avIdList[index] body = self.getTireBody(avId) degs = input[1] + 90 tireNp = self.getTireNp(avId) tireH = tireNp.getH() self.notify.debug("tireH = %s" % tireH) radAngle = deg2Rad(degs) foo = NodePath("foo") dirVector = Vec3(math.cos(radAngle), math.sin(radAngle), 0) self.notify.debug("dirVector is now=%s" % dirVector) inputForce = input[0] inputForce /= self.MaxLocalForce inputForce *= self.MaxPhysicsForce force = dirVector * inputForce self.notify.debug("adding force %s to %d" % (force, avId)) body.addForce(force) self.enableAllTireBodies() self.totalPhysicsSteps = 0 self.startSim() taskMgr.add(self.__moveTiresTask, self.uniqueName("moveTiresTtask")) def exitMoveTires(self): self.forceLocalToonToTire() self.disableAllTireBodies() self.stopSim() self.notify.debug("total Physics steps = %d" % self.totalPhysicsSteps) taskMgr.remove(self.uniqueName("moveTiresTtask")) def enterSynch(self): self.waitingSyncLabel.show() def exitSynch(self): self.waitingSyncLabel.hide() def enterScoring(self): sortedByDistance = [] for avId in self.avIdList: np = self.getTireNp(avId) pos = np.getPos() pos.setZ(0) sortedByDistance.append((avId, pos.length())) def compareDistance(x, y): if x[1] - y[1] > 0: return 1 elif x[1] - y[1] < 0: return -1 else: return 0 sortedByDistance.sort(cmp=compareDistance) self.scoreMovie = Sequence() curScale = 0.01 curTime = 0 self.scoreCircle.setScale(0.01) self.scoreCircle.show() self.notify.debug("newScores = %s" % self.newScores) circleStartTime = 0 for index in xrange(len(sortedByDistance)): distance = sortedByDistance[index][1] avId = sortedByDistance[index][0] scorePanelIndex = self.avIdList.index(avId) time = (distance - curScale) / IceGameGlobals.ExpandFeetPerSec if time < 0: time = 0.01 scaleXY = distance + IceGameGlobals.TireRadius self.notify.debug("circleStartTime = %s" % circleStartTime) self.scoreMovie.append( Parallel( LerpScaleInterval(self.scoreCircle, time, Point3(scaleXY, scaleXY, 1.0)), SoundInterval(self.scoreCircleSound, duration=time, startTime=circleStartTime), ) ) circleStartTime += time startScore = self.scorePanels[scorePanelIndex].getScore() destScore = self.newScores[scorePanelIndex] self.notify.debug("for avId %d, startScore=%d, newScores=%d" % (avId, startScore, destScore)) def increaseScores(t, scorePanelIndex=scorePanelIndex, startScore=startScore, destScore=destScore): oldScore = self.scorePanels[scorePanelIndex].getScore() diff = destScore - startScore newScore = int(startScore + diff * t) if newScore > oldScore: base.playSfx(self.countSound) self.scorePanels[scorePanelIndex].setScore(newScore) self.scores[scorePanelIndex] = newScore duration = (destScore - startScore) * IceGameGlobals.ScoreCountUpRate tireNp = self.tireDict[avId]["tireNodePath"] self.scoreMovie.append( Parallel( LerpFunctionInterval(increaseScores, duration), Sequence( LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), ), ) ) curScale += distance self.scoreMovie.append(Func(self.sendUpdate, "reportScoringMovieDone", [])) self.scoreMovie.start() def exitScoring(self): self.scoreMovie.finish() self.scoreMovie = None self.scoreCircle.hide() return def enterFinalResults(self): lerpTrack = Parallel() lerpDur = 0.5 tY = 0.6 bY = -0.05 lX = -0.5 cX = 0 rX = 0.5 scorePanelLocs = ( ((cX, bY),), ((lX, bY), (rX, bY)), ((cX, tY), (lX, bY), (rX, bY)), ((lX, tY), (rX, tY), (lX, bY), (rX, bY)), ) scorePanelLocs = scorePanelLocs[self.numPlayers - 1] for i in xrange(self.numPlayers): panel = self.scorePanels[i] pos = scorePanelLocs[i] panel.wrtReparentTo(aspect2d) lerpTrack.append( Parallel( LerpPosInterval(panel, lerpDur, Point3(pos[0], 0, pos[1]), blendType="easeInOut"), LerpScaleInterval(panel, lerpDur, Vec3(panel.getScale()) * 2.0, blendType="easeInOut"), ) ) self.showScoreTrack = Parallel( lerpTrack, Sequence(Wait(IceGameGlobals.ShowScoresDuration), Func(self.gameOver)) ) self.showScoreTrack.start() def exitFinalResults(self): self.showScoreTrack.pause() del self.showScoreTrack def enterCleanup(self): self.notify.debug("enterCleanup") if base.localAvatar.laffMeter: base.localAvatar.laffMeter.start() def exitCleanup(self): pass def __placeToon(self, avId): toon = self.getAvatar(avId) if toon: toon.setPos(0, 0, 0) toon.setHpr(0, 0, 0) def moveCameraToTop(self): camera.reparentTo(render) p = self.cameraThreeQuarterView camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5]) def setupTire(self, avId, index): tireNp, tireBody, tireOdeGeom = self.createTire(index) self.tireDict[avId] = {"tireNodePath": tireNp, "tireBody": tireBody, "tireOdeGeom": tireOdeGeom} if avId <= 0: tireBlocker = tireNp.find("**/tireblockermesh") if not tireBlocker.isEmpty(): tireBlocker.hide() if avId == self.localAvId: tireNp = self.tireDict[avId]["tireNodePath"] self.treasureSphereName = "treasureCollider" self.treasureCollSphere = CollisionSphere(0, 0, 0, IceGameGlobals.TireRadius) self.treasureCollSphere.setTangible(0) self.treasureCollNode = CollisionNode(self.treasureSphereName) self.treasureCollNode.setFromCollideMask(ToontownGlobals.PieBitmask) self.treasureCollNode.addSolid(self.treasureCollSphere) self.treasureCollNodePath = tireNp.attachNewNode(self.treasureCollNode) self.treasureHandler = CollisionHandlerEvent() self.treasureHandler.addInPattern("%fn-intoTreasure") base.cTrav.addCollider(self.treasureCollNodePath, self.treasureHandler) eventName = "%s-intoTreasure" % self.treasureCollNodePath.getName() self.notify.debug("eventName = %s" % eventName) self.accept(eventName, self.toonHitSomething) def setupForceArrow(self, avId): arrow = loader.loadModel("phase_4/models/minigames/ice_game_arrow") priority = 0 if avId < 0: priority = -avId else: priority = self.avIdList.index(avId) if avId == self.localAvId: priority = 10 self.forceArrowDict[avId] = arrow def hideForceArrows(self): for forceArrow in self.forceArrowDict.values(): forceArrow.hide() def showForceArrows(self, realPlayersOnly=True): for avId in self.forceArrowDict: if realPlayersOnly: if avId > 0: self.forceArrowDict[avId].show() else: self.forceArrowDict[avId].hide() else: self.forceArrowDict[avId].show() def localForceArrow(self): if self.localAvId in self.forceArrowDict: return self.forceArrowDict[self.localAvId] else: return None return None def setChoices(self, input0, input1, input2, input3): pass def startDebugTask(self): taskMgr.add(self.debugTask, self.debugTaskName) def stopDebugTask(self): taskMgr.remove(self.debugTaskName) def debugTask(self, task): if self.canDrive and self.tireDict.has_key(localAvatar.doId): dt = globalClock.getDt() forceMove = 25000 forceMoveDt = forceMove tireBody = self.tireDict[localAvatar.doId]["tireBody"] if self.arrowKeys.upPressed() and not tireBody.isEnabled(): x = 0 y = 1 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.downPressed() and not tireBody.isEnabled(): x = 0 y = -1 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.leftPressed() and not tireBody.isEnabled(): x = -1 y = 0 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.rightPressed() and not tireBody.isEnabled(): x = 1 y = 0 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) return task.cont def __upArrowPressed(self): pass def __downArrowPressed(self): pass def __leftArrowPressed(self): pass def __rightArrowPressed(self): pass def __controlPressed(self): if self.gameFSM.getCurrentState().getName() == "inputChoice": self.sendForceArrowUpdateAsap = True self.updateLocalForceArrow() self.controlKeyPressed = True self.sendUpdate("setAvatarChoice", [self.curForce, self.curHeading]) self.gameFSM.request("waitServerChoices") def startTimer(self): now = globalClock.getFrameTime() elapsed = now - self.timerStartTime self.timer.posInTopRightCorner() self.timer.setTime(IceGameGlobals.InputTimeout) self.timer.countdown(IceGameGlobals.InputTimeout - elapsed, self.handleChoiceTimeout) self.timer.show() def setTimerStartTime(self, timestamp): if not self.hasLocalToon: return self.timerStartTime = globalClockDelta.networkToLocalTime(timestamp) if self.timer != None: self.startTimer() return def handleChoiceTimeout(self): self.sendUpdate("setAvatarChoice", [0, 0]) self.gameFSM.request("waitServerChoices") def localTireNp(self): ret = None if self.localAvId in self.tireDict: ret = self.tireDict[self.localAvId]["tireNodePath"] return ret def localTireBody(self): ret = None if self.localAvId in self.tireDict: ret = self.tireDict[self.localAvId]["tireBody"] return ret def getTireBody(self, avId): ret = None if avId in self.tireDict: ret = self.tireDict[avId]["tireBody"] return ret def getTireNp(self, avId): ret = None if avId in self.tireDict: ret = self.tireDict[avId]["tireNodePath"] return ret def updateForceArrow(self, avId, curHeading, curForce): forceArrow = self.forceArrowDict[avId] tireNp = self.tireDict[avId]["tireNodePath"] tireNp.setH(curHeading) tireBody = self.tireDict[avId]["tireBody"] tireBody.setQuaternion(tireNp.getQuat()) self.notify.debug("curHeading = %s" % curHeading) yScale = curForce / 100.0 yScale *= 1 headY = yScale * 15 xScale = (yScale - 1) / 2.0 + 1.0 shaft = forceArrow.find("**/arrow_shaft") head = forceArrow.find("**/arrow_head") shaft.setScale(xScale, yScale, 1) head.setPos(0, headY, 0) head.setScale(xScale, xScale, 1) def updateLocalForceArrow(self): avId = self.localAvId self.b_setForceArrowInfo(avId, self.curHeading, self.curForce) def __aimTask(self, task): if not hasattr(self, "arrowKeys"): return task.done dt = globalClock.getDt() headingMomentumChange = dt * 60.0 forceMomentumChange = dt * 160.0 arrowUpdate = False arrowRotating = False arrowUp = False arrowDown = False if self.arrowKeys.upPressed() and not self.arrowKeys.downPressed(): self.forceMomentum += forceMomentumChange if self.forceMomentum < 0: self.forceMomentum = 0 if self.forceMomentum > 50: self.forceMomentum = 50 oldForce = self.curForce self.curForce += self.forceMomentum * dt arrowUpdate = True if oldForce < self.MaxLocalForce: arrowUp = True elif self.arrowKeys.downPressed() and not self.arrowKeys.upPressed(): self.forceMomentum += forceMomentumChange if self.forceMomentum < 0: self.forceMomentum = 0 if self.forceMomentum > 50: self.forceMomentum = 50 oldForce = self.curForce self.curForce -= self.forceMomentum * dt arrowUpdate = True if oldForce > 0.01: arrowDown = True else: self.forceMomentum = 0 if self.arrowKeys.leftPressed() and not self.arrowKeys.rightPressed(): self.headingMomentum += headingMomentumChange if self.headingMomentum < 0: self.headingMomentum = 0 if self.headingMomentum > 50: self.headingMomentum = 50 self.curHeading += self.headingMomentum * dt arrowUpdate = True arrowRotating = True elif self.arrowKeys.rightPressed() and not self.arrowKeys.leftPressed(): self.headingMomentum += headingMomentumChange if self.headingMomentum < 0: self.headingMomentum = 0 if self.headingMomentum > 50: self.headingMomentum = 50 self.curHeading -= self.headingMomentum * dt arrowUpdate = True arrowRotating = True else: self.headingMomentum = 0 if arrowUpdate: self.normalizeHeadingAndForce() self.updateLocalForceArrow() if arrowRotating: if not self.arrowRotateSound.status() == self.arrowRotateSound.PLAYING: base.playSfx(self.arrowRotateSound, looping=True) else: self.arrowRotateSound.stop() if arrowUp: if not self.arrowUpSound.status() == self.arrowUpSound.PLAYING: base.playSfx(self.arrowUpSound, looping=False) else: self.arrowUpSound.stop() if arrowDown: if not self.arrowDownSound.status() == self.arrowDownSound.PLAYING: base.playSfx(self.arrowDownSound, looping=False) else: self.arrowDownSound.stop() return task.cont def normalizeHeadingAndForce(self): if self.curForce > self.MaxLocalForce: self.curForce = self.MaxLocalForce if self.curForce < 0.01: self.curForce = 0.01 def setTireInputs(self, tireInputs): if not self.hasLocalToon: return self.allTireInputs = tireInputs self.gameFSM.request("moveTires") def enableAllTireBodies(self): for avId in self.tireDict.keys(): self.tireDict[avId]["tireBody"].enable() def disableAllTireBodies(self): for avId in self.tireDict.keys(): self.tireDict[avId]["tireBody"].disable() def areAllTiresDisabled(self): for avId in self.tireDict.keys(): if self.tireDict[avId]["tireBody"].isEnabled(): return False return True def __moveTiresTask(self, task): if self.areAllTiresDisabled(): self.sendTirePositions() self.gameFSM.request("synch") return task.done return task.cont def sendTirePositions(self): tirePositions = [] for index in xrange(len(self.avIdList)): avId = self.avIdList[index] tire = self.getTireBody(avId) pos = Point3(tire.getPosition()) tirePositions.append([pos[0], pos[1], pos[2]]) for index in xrange(len(self.avIdList), 4): avId = -index tire = self.getTireBody(avId) pos = Point3(tire.getPosition()) tirePositions.append([pos[0], pos[1], pos[2]]) self.sendUpdate("endingPositions", [tirePositions]) def setFinalPositions(self, finalPos): if not self.hasLocalToon: return for index in xrange(len(self.avIdList)): avId = self.avIdList[index] tire = self.getTireBody(avId) np = self.getTireNp(avId) pos = finalPos[index] tire.setPosition(pos[0], pos[1], pos[2]) np.setPos(pos[0], pos[1], pos[2]) for index in xrange(len(self.avIdList), 4): avId = -index tire = self.getTireBody(avId) np = self.getTireNp(avId) pos = finalPos[index] tire.setPosition(pos[0], pos[1], pos[2]) np.setPos(pos[0], pos[1], pos[2]) def updateInfoLabel(self): self.infoLabel["text"] = TTLocalizer.IceGameInfo % { "curMatch": self.curMatch + 1, "numMatch": IceGameGlobals.NumMatches, "curRound": self.curRound + 1, "numRound": IceGameGlobals.NumRounds, } def setMatchAndRound(self, match, round): if not self.hasLocalToon: return self.curMatch = match self.curRound = round self.updateInfoLabel() def setScores(self, match, round, scores): if not self.hasLocalToon: return self.newMatch = match self.newRound = round self.newScores = scores def setNewState(self, state): if not self.hasLocalToon: return self.notify.debug("setNewState gameFSM=%s newState=%s" % (self.gameFSM, state)) self.gameFSM.request(state) def putAllTiresInStartingPositions(self): for index in xrange(len(self.avIdList)): avId = self.avIdList[index] np = self.tireDict[avId]["tireNodePath"] np.setPos(IceGameGlobals.StartingPositions[index]) self.notify.debug("avId=%s newPos=%s" % (avId, np.getPos)) np.setHpr(0, 0, 0) quat = np.getQuat() body = self.tireDict[avId]["tireBody"] body.setPosition(IceGameGlobals.StartingPositions[index]) body.setQuaternion(quat) for index in xrange(len(self.avIdList), 4): avId = -index np = self.tireDict[avId]["tireNodePath"] np.setPos(IceGameGlobals.StartingPositions[index]) self.notify.debug("avId=%s newPos=%s" % (avId, np.getPos)) np.setHpr(0, 0, 0) quat = np.getQuat() body = self.tireDict[avId]["tireBody"] body.setPosition(IceGameGlobals.StartingPositions[index]) body.setQuaternion(quat) def b_setForceArrowInfo(self, avId, force, heading): self.setForceArrowInfo(avId, force, heading) self.d_setForceArrowInfo(avId, force, heading) def d_setForceArrowInfo(self, avId, force, heading): sendIt = False curTime = self.getCurrentGameTime() if self.sendForceArrowUpdateAsap: sendIt = True elif curTime - self.lastForceArrowUpdateTime > 0.2: sendIt = True if sendIt: self.sendUpdate("setForceArrowInfo", [avId, force, heading]) self.sendForceArrowUpdateAsap = False self.lastForceArrowUpdateTime = self.getCurrentGameTime() def setForceArrowInfo(self, avId, force, heading): if not self.hasLocalToon: return self.updateForceArrow(avId, force, heading) def setupStartOfMatch(self): self.putAllTiresInStartingPositions() szId = self.getSafezoneId() self.numTreasures = IceGameGlobals.NumTreasures[szId] if self.treasures: for treasure in self.treasures: treasure.destroy() self.treasures = [] index = 0 treasureMargin = IceGameGlobals.TireRadius + 1.0 while len(self.treasures) < self.numTreasures: xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5, IceGameGlobals.MaxWall[0] - 5) yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5, IceGameGlobals.MaxWall[1] - 5) self.notify.debug("yPos=%s" % yPos) pos = Point3(xPos, yPos, IceGameGlobals.TireRadius) newTreasure = IceTreasure.IceTreasure(self.treasureModel, pos, index, self.doId, penalty=False) goodSpot = True for obstacle in self.obstacles: if newTreasure.nodePath.getDistance(obstacle) < treasureMargin: goodSpot = False break if goodSpot: for treasure in self.treasures: if newTreasure.nodePath.getDistance(treasure.nodePath) < treasureMargin: goodSpot = False break if goodSpot: self.treasures.append(newTreasure) index += 1 else: newTreasure.destroy() self.numPenalties = IceGameGlobals.NumPenalties[szId] if self.penalties: for penalty in self.penalties: penalty.destroy() self.penalties = [] index = 0 while len(self.penalties) < self.numPenalties: xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5, IceGameGlobals.MaxWall[0] - 5) yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5, IceGameGlobals.MaxWall[1] - 5) self.notify.debug("yPos=%s" % yPos) pos = Point3(xPos, yPos, IceGameGlobals.TireRadius) newPenalty = IceTreasure.IceTreasure(self.penaltyModel, pos, index, self.doId, penalty=True) goodSpot = True for obstacle in self.obstacles: if newPenalty.nodePath.getDistance(obstacle) < treasureMargin: goodSpot = False break if goodSpot: for treasure in self.treasures: if newPenalty.nodePath.getDistance(treasure.nodePath) < treasureMargin: goodSpot = False break if goodSpot: for penalty in self.penalties: if newPenalty.nodePath.getDistance(penalty.nodePath) < treasureMargin: goodSpot = False break if goodSpot: self.penalties.append(newPenalty) index += 1 else: newPenalty.destroy() def toonHitSomething(self, entry): self.notify.debug("---- treasure Enter ---- ") self.notify.debug("%s" % entry) name = entry.getIntoNodePath().getName() parts = name.split("-") if len(parts) < 3: self.notify.debug("collided with %s, but returning" % name) return if not int(parts[1]) == self.doId: self.notify.debug("collided with %s, but doId doesn't match" % name) return treasureNum = int(parts[2]) if "penalty" in parts[0]: self.__penaltyGrabbed(treasureNum) else: self.__treasureGrabbed(treasureNum) def __treasureGrabbed(self, treasureNum): self.treasures[treasureNum].showGrab() self.treasureGrabSound.play() self.sendUpdate("claimTreasure", [treasureNum]) def setTreasureGrabbed(self, avId, treasureNum): if not self.hasLocalToon: return self.notify.debug("treasure %s grabbed by %s" % (treasureNum, avId)) if avId != self.localAvId: self.treasures[treasureNum].showGrab() i = self.avIdList.index(avId) self.scores[i] += 1 self.scorePanels[i].setScore(self.scores[i]) def __penaltyGrabbed(self, penaltyNum): self.penalties[penaltyNum].showGrab() self.sendUpdate("claimPenalty", [penaltyNum]) def setPenaltyGrabbed(self, avId, penaltyNum): if not self.hasLocalToon: return self.notify.debug("penalty %s grabbed by %s" % (penaltyNum, avId)) if avId != self.localAvId: self.penalties[penaltyNum].showGrab() i = self.avIdList.index(avId) self.scores[i] -= 1 self.scorePanels[i].setScore(self.scores[i]) def postStep(self): DistributedIceWorld.DistributedIceWorld.postStep(self) if not self.colCount: return for count in xrange(self.colCount): c0, c1 = self.getOrderedContacts(count) if c1 in self.tireCollideIds: tireIndex = self.tireCollideIds.index(c1) if c0 in self.tireCollideIds: self.tireSounds[tireIndex]["tireHit"].play() elif c0 == self.wallCollideId: self.tireSounds[tireIndex]["wallHit"].play() elif c0 == self.obstacleCollideId: self.tireSounds[tireIndex]["obstacleHit"].play() def forceLocalToonToTire(self): toon = localAvatar if toon and self.localAvId in self.tireDict: tireNp = self.tireDict[self.localAvId]["tireNodePath"] toon.reparentTo(tireNp) toon.setPosHpr(0, 0, 0, 0, 0, 0) toon.setY(1.0) toon.setZ(-3)
class VoteResultsTrolleyPanel(DirectFrame): notify = DirectNotifyGlobal.directNotify.newCategory( 'VoteResultsTrolleyPanel') def __init__(self, numPlayers, avIdList, votes, directions, namesList, disconnectedList, directionToGo, directionReason, directionTotals, *args, **kwargs): opts = { 'relief': None, 'geom': DGG.getDefaultDialogGeom(), 'geom_color': ToontownGlobals.GlobalDialogColor[:3] + (0.8, ), 'geom_scale': (1.75, 1, 0.25), 'pos': (0, 0, 0.825) } opts.update(kwargs) DirectFrame.__init__(self, *args, **opts) self.initialiseoptions(VoteResultsTrolleyPanel) listMultiplier = 1 if TravelGameGlobals.SpoofFour: listMultiplier = 4 self.avIdList = avIdList * listMultiplier self.numPlayers = numPlayers * listMultiplier self.votes = votes * listMultiplier self.directions = directions * listMultiplier self.namesList = namesList * listMultiplier self.disconnectedList = disconnectedList * listMultiplier self.directionToGo = directionToGo self.directionReason = directionReason self.directionTotals = directionTotals self.entryList = [] self.rowFrame = [] self.upDownFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(-1)) self.upLabel = DirectLabel(parent=self, relief=None, pos=(-0.5, 0, 0.06), text=TTLocalizer.TravelGameDirections[0] + ':', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.downLabel = DirectLabel(parent=self, relief=None, pos=(0.5, 0, 0.06), text=TTLocalizer.TravelGameDirections[1] + ':', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalVotesUpLabel = DirectLabel(parent=self.upLabel, relief=None, pos=(0.2, 0, 0.0), text='0', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalVotesDownLabel = DirectLabel(parent=self.downLabel, relief=None, pos=(0.2, 0, 0.0), text='0', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight) self.totalFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(self.numPlayers)) self.totalVotesLabels = [ self.totalVotesUpLabel, self.totalVotesDownLabel ] self.resultFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(0.5)) self.resultLabel = DirectLabel(parent=self.resultFrame, text='', text_scale=0.06, pos=(0.7, 0, 0.0), text_align=TextNode.ACenter) self.setupResultLabel() for index in xrange(self.numPlayers): frame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(index)) self.rowFrame.append(frame) nameLabel = DirectFrame(parent=frame, relief=None, pos=(0.46, 0.0, 0.0), text=self.namesList[index], text_fg=(0.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ACenter, text_font=DGG.getDefaultFont()) votesUpLabel = DirectLabel(parent=frame, relief=None, pos=(1.2, 0.0, 0.0), text='', text_fg=(0, 0, 1, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont()) votesDownLabel = DirectLabel(parent=frame, relief=None, pos=(1.43, 0.0, 0.0), text='', text_fg=(1, 0, 0, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont()) nameLabel.hide() self.entryList.append((nameLabel, votesUpLabel, votesDownLabel)) self.avVotesLabel = {} self.avArrows = {} matchingGameGui = loader.loadModel( 'phase_3.5/models/gui/matching_game_gui') minnieArrow = matchingGameGui.find('**/minnieArrow') from toontown.minigame.DistributedTravelGame import map3dToAspect2d for index in xrange(self.numPlayers): avId = self.avIdList[index] av = base.cr.doId2do.get(avId) if av: height = av.getHeight() avPos = av.getPos(render) avPos.setZ(av.getZ() + 5) labelPos = map3dToAspect2d(render, avPos) if not labelPos: continue labelPos.setZ(labelPos.getZ() + 0.3) arrow = None if self.votes[index] > 0: arrow = aspect2d.attachNewNode('avArrow') minnieArrow.copyTo(arrow) arrow.setScale(1.1, 1, 1.15) arrow.setPos(labelPos) if self.directions[index] == 0: arrow.setR(-90) arrow.setColorScale(0, 0, 1, 1) else: arrow.setR(90) arrow.setColorScale(1, 0, 0, 1) arrow.wrtReparentTo(self.resultFrame) arrow.hide() self.avArrows[index] = arrow fgColor = Vec4(0, 0, 0, 1) if self.votes[index] > 0: if self.directions[index] == 0: fgColor = Vec4(0, 0, 1, 1) else: fgColor = Vec4(1, 0, 0, 1) if self.votes[index] > 0: newLabel = DirectLabel( parent=aspect2d, relief=None, pos=labelPos, text='test', text_fg=(1, 1, 1, 1), text_scale=0.1, text_align=TextNode.ACenter, text_font=ToontownGlobals.getSignFont(), text_pos=(0, -0.01, 0)) else: newLabel = DirectLabel( parent=aspect2d, geom=DGG.getDefaultDialogGeom(), geom_scale=(0.2, 1, 0.2), relief=None, pos=labelPos, text='test', text_fg=(0.5, 0.5, 0.5, 1), text_scale=0.1, text_align=TextNode.ACenter, text_font=ToontownGlobals.getSignFont(), text_pos=(0, -0.035, 0)) newLabel.wrtReparentTo(self.resultFrame) newLabel.hide() self.avVotesLabel[index] = newLabel matchingGameGui.removeNode() self.curArrowSfxIndex = 0 self.upArrowSfx = [] self.downArrowSfx = [] for i in xrange(5): self.upArrowSfx.append( base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.ogg')) self.downArrowSfx.append( base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_red_arrow.ogg')) self.winVoteSfx = base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_win_vote.ogg') self.noVoteSfx = base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_square_no_vote_1.ogg') self.loseVoteSfx = base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_lose_vote.ogg') self.localAvatarWon = False self.localAvatarLost = False localIndex = self.avIdList.index(base.localAvatar.doId) localDirection = self.directions[localIndex] localVotes = self.votes[localIndex] if localVotes: if localDirection == self.directionToGo: if not TravelGameGlobals.ReverseWin: self.localAvatarWon = True else: self.localAvatarLost = True elif not TravelGameGlobals.ReverseWin: self.localAvatarLost = True else: self.localAvatarWon = True return def getRowPos(self, place): return Point3(-0.72, -0.01, 0.0 - place * 0.1) def setupResultLabel(self): reasonStr = '' if self.directionReason == TravelGameGlobals.ReasonVote: if self.directionToGo == 0: losingDirection = 1 else: losingDirection = 0 diffVotes = self.directionTotals[ self.directionToGo] - self.directionTotals[losingDirection] if diffVotes > 1: reasonStr = TTLocalizer.TravelGameReasonVotesPlural % { 'dir': TTLocalizer.TravelGameDirections[self.directionToGo], 'numVotes': diffVotes } else: reasonStr = TTLocalizer.TravelGameReasonVotesSingular % { 'dir': TTLocalizer.TravelGameDirections[self.directionToGo], 'numVotes': diffVotes } elif self.directionReason == TravelGameGlobals.ReasonRandom: reasonStr = TTLocalizer.TravelGameReasonRandom % { 'dir': TTLocalizer.TravelGameDirections[self.directionToGo], 'numVotes': self.directionTotals[self.directionToGo] } elif self.directionReason == TravelGameGlobals.ReasonPlaceDecider: reasonStr = TravelGameReasonPlace % { 'name': 'TODO NAME', 'dir': TTLocalizer.TravelGameDirections[self.directionToGo] } self.resultLabel['text'] = reasonStr self.resultLabel.hide() def createOnePlayerSequence(self, index, duration): numVotes = self.votes[index] direction = self.directions[index] def ticketTicker(t, label=self.entryList[index][direction + 1], startVotes=0, endVotes=numVotes): label['text'] = str(int(t * endVotes + startVotes)) track = Parallel() startVotes = 0 for prev in xrange(index): if self.directions[prev] == direction: startVotes += self.votes[prev] def totalTicker(t, label=self.totalVotesLabels[direction], startVotes=startVotes, additionalVotes=numVotes): label['text'] = str(int(t * additionalVotes + startVotes)) track.append( LerpFunc(totalTicker, duration=duration, name='countTotal %d' % index)) if self.avVotesLabel.has_key(index): def avVotesTicker(t, label=self.avVotesLabel[index], startVotes=0, endVotes=numVotes, direction=direction): oldValue = label['text'] newValue = int(t * endVotes + startVotes) label['text'] = str(newValue) if not oldValue == label['text']: if newValue: if direction == 0: self.upArrowSfx[self.curArrowSfxIndex].play() else: self.downArrowSfx[self.curArrowSfxIndex].play() self.curArrowSfxIndex += 1 if self.curArrowSfxIndex >= len(self.upArrowSfx): self.curArrowSfxIndex = 0 label = self.avVotesLabel[index] track.append( Func(self.avVotesLabel[index].show, name='showName %d' % index)) if self.avArrows.has_key(index): track.append( Func(self.avArrows[index].show, name='showArrow %d' % index)) if direction == 0 and numVotes: pass elif direction == 1 and numVotes: pass else: track.append(SoundInterval(self.noVoteSfx)) track.append( LerpFunc(avVotesTicker, duration=duration, name='countAvVotes %d' % index)) return track def startMovie(self): self.movie = Sequence() for index in xrange(self.numPlayers): track = self.createOnePlayerSequence(index, 1.25) self.movie.append(track) self.movie.append(Wait(0.75)) self.movie.append(Func(self.resultLabel.show)) soundAndWait = Parallel() soundAndWait.append(Wait(2.0)) if self.localAvatarWon: soundAndWait.append(SoundInterval(self.winVoteSfx)) elif self.localAvatarLost: soundAndWait.append(SoundInterval(self.loseVoteSfx, duration=0.43)) self.movie.append(soundAndWait) self.movie.start() def destroy(self): self.movie.finish() del self.movie del self.winVoteSfx del self.noVoteSfx del self.upArrowSfx del self.loseVoteSfx del self.downArrowSfx DirectFrame.destroy(self)
class DistCogdoGame(DistCogdoGameBase, DistributedObject): notify = directNotify.newCategory('DistCogdoGame') def __init__(self, cr): DistributedObject.__init__(self, cr) base.cogdoGame = self cr.cogdoGame = self self._waitingStartLabel = DirectLabel(text=TTL.MinigameWaitingForOtherPlayers, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075) self._waitingStartLabel.hide() self.loadFSM = ClassicFSM.ClassicFSM('DistCogdoGame.loaded', [State.State('NotLoaded', self.enterNotLoaded, self.exitNotLoaded, ['Loaded']), State.State('Loaded', self.enterLoaded, self.exitLoaded, ['NotLoaded'])], 'NotLoaded', 'NotLoaded') self.loadFSM.enterInitialState() self.fsm = ClassicFSM.ClassicFSM('DistCogdoGame', [State.State('Visible', self.enterVisible, self.exitVisible, ['Intro']), State.State('Intro', self.enterIntro, self.exitIntro, ['WaitServerStart']), State.State('WaitServerStart', self.enterWaitServerStart, self.exitWaitServerStart, ['Game']), State.State('Game', self.enterGame, self.exitGame, ['Finish']), State.State('Finish', self.enterFinish, self.exitFinish, ['Off']), State.State('Off', self.enterOff, self.exitOff, ['Visible'])], 'Off', 'Off') self.fsm.enterInitialState() self.difficultyOverride = None self.exteriorZoneOverride = None self._gotInterior = StateVar(False) self._toonsInEntranceElev = StateVar(False) self._wantStashElevator = StateVar(False) self._stashElevatorFC = FunctionCall(self._doStashElevator, self._toonsInEntranceElev, self._gotInterior, self._wantStashElevator) def getTitle(self): pass def getInstructions(self): pass def setInteriorId(self, interiorId): self._interiorId = interiorId def setExteriorZone(self, exteriorZone): self.exteriorZone = exteriorZone def setDifficultyOverrides(self, difficultyOverride, exteriorZoneOverride): if difficultyOverride != CogdoGameConsts.NoDifficultyOverride: self.difficultyOverride = difficultyOverride / float(CogdoGameConsts.DifficultyOverrideMult) if exteriorZoneOverride != CogdoGameConsts.NoExteriorZoneOverride: self.exteriorZoneOverride = exteriorZoneOverride def getInterior(self): return self.cr.getDo(self._interiorId) def getEntranceElevator(self, callback): return self.getInterior().getEntranceElevator(callback) def getToonIds(self): interior = self.getInterior() if interior is not None: return interior.getToonIds() else: return [] def getToon(self, toonId): if self.cr.doId2do.has_key(toonId): return self.cr.doId2do[toonId] else: return None def getNumPlayers(self): return len(self.getToonIds()) def isSinglePlayer(self): if self.getNumPlayers() == 1: return 1 else: return 0 def announceGenerate(self): DistributedObject.announceGenerate(self) self.loadFSM.request('Loaded') self._requestInterior() self.notify.info('difficulty: %s, safezoneId: %s' % (self.getDifficulty(), self.getSafezoneId())) def _requestInterior(self): self.cr.relatedObjectMgr.requestObjects([self._interiorId], allCallback=self._handleGotInterior) def _handleGotInterior(self, objs): self._gotInterior.set(True) self.getEntranceElevator(self.placeEntranceElev) def stashEntranceElevator(self): self._wantStashElevator.set(True) def placeEntranceElev(self, elev): pass def _doStashElevator(self, toonsInEntranceElev, gotInterior, wantStashElevator): if gotInterior: interior = self.getInterior() if interior: if not toonsInEntranceElev and wantStashElevator: interior.stashElevatorIn() else: interior.stashElevatorIn(False) def disable(self): base.cogdoGame = None self.cr.cogdoGame = None self.fsm.requestFinalState() self.loadFSM.requestFinalState() self.fsm = None self.loadFSM = None DistributedObject.disable(self) def delete(self): self._stashElevatorFC.destroy() self._wantStashElevator.destroy() self._toonsInEntranceElev.destroy() self._gotInterior.destroy() self._waitingStartLabel.destroy() self._waitingStartLabel = None DistributedObject.delete(self) def getDifficulty(self): if self.difficultyOverride is not None: return self.difficultyOverride if hasattr(base, 'cogdoGameDifficulty'): return float(base.cogdoGameDifficulty) return CogdoGameConsts.getDifficulty(self.getSafezoneId()) def getSafezoneId(self): if self.exteriorZoneOverride is not None: return self.exteriorZoneOverride if hasattr(base, 'cogdoGameSafezoneId'): return CogdoGameConsts.getSafezoneId(base.cogdoGameSafezoneId) return CogdoGameConsts.getSafezoneId(self.exteriorZone) def enterNotLoaded(self): pass def exitNotLoaded(self): pass def enterLoaded(self): pass def exitLoaded(self): pass def enterOff(self): pass def exitOff(self): pass def setVisible(self): self.fsm.request('Visible') def setIntroStart(self): self.fsm.request('Intro') def enterVisible(self): self._toonsInEntranceElev.set(True) def exitVisible(self): pass def enterIntro(self, duration = MinigameGlobals.rulesDuration): base.cr.playGame.getPlace().fsm.request('Game') self._rulesDoneEvent = self.uniqueName('cogdoGameRulesDone') self.accept(self._rulesDoneEvent, self._handleRulesDone) self._rulesPanel = CogdoGameRulesPanel('CogdoGameRulesPanel', self.getTitle(), '', self._rulesDoneEvent, timeout=duration) self._rulesPanel.load() self._rulesPanel.enter() def exitIntro(self): self._toonsInEntranceElev.set(False) self.ignore(self._rulesDoneEvent) if self._rulesPanel: self._rulesPanel.exit() self._rulesPanel.unload() self._rulesPanel = None def _handleRulesDone(self): self.ignore(self._rulesDoneEvent) self._rulesPanel.exit() self._rulesPanel.unload() self._rulesPanel = None self.fsm.request('WaitServerStart') self.d_setAvatarReady() def d_setAvatarReady(self): self.sendUpdate('setAvatarReady', []) def enterWaitServerStart(self): numToons = 1 interior = self.getInterior() if interior: numToons = len(interior.getToonIds()) if numToons > 1: msg = TTL.MinigameWaitingForOtherPlayers else: msg = TTL.MinigamePleaseWait self._waitingStartLabel['text'] = msg self._waitingStartLabel.show() def exitWaitServerStart(self): self._waitingStartLabel.hide() def setGameStart(self, timestamp): self._startTime = globalClockDelta.networkToLocalTime(timestamp) self.fsm.request('Game') def getStartTime(self): return self._startTime def enterGame(self): if SCHELLGAMES_DEV: self.acceptOnce('escape', messenger.send, ['magicWord', ['~endMaze']]) def exitGame(self): if SCHELLGAMES_DEV: self.ignore('escape') def setGameFinish(self, timestamp): self._finishTime = globalClockDelta.networkToLocalTime(timestamp) self.fsm.request('Finish') def getFinishTime(self): return self._finishTime def enterFinish(self): pass def exitFinish(self): pass def setToonSad(self, toonId): pass def setToonDisconnect(self, toonId): pass
class JellybeanRewardGui(DirectFrame): """ This class does not load a gui model specifically created for this purpose. Instead, it loads sub-parts of other models and cobbles them together into a frankenstein gui. As such, changing any of those models could inadvertently change how this gui looks. Ideally this class would be refactored to use a gui model specific to this class. """ notify = directNotify.newCategory("JellybeanRewardGui") PreCountdownDelay = 1.0 CountDownRate = 0.2 # how quickly we transfer beans from reward box to your jar JarLabelTextColor = (0.95, 0.95, 0.0, 1.0) JarLabelMaxedTextColor = (1.0, 0.0, 0.0, 1.0) def __init__(self, doneEvent): self.doneEvent = doneEvent DirectFrame.__init__(self) self.reparentTo(aspect2d) self.setPos(0.0, 0.0, 0.16) self.stash() # load the public party gui and extract the sub-chunk of the model that # we will use as the background for this gui publicPartyGui = loader.loadModel( "phase_4/models/parties/publicPartyGUI") # create a top level DirectFrame to hold everything else self.frame = DirectFrame( parent=self, geom=publicPartyGui.find("**/activities_background"), geom_pos=(-0.8, 0.0, 0.2), geom_scale=2.0, relief=None, ) # counter for beans won in the activity self.earnedLabel = DirectLabel( parent=self, relief=None, text=str(0), text_align=TextNode.ACenter, text_pos=(0.0, -0.07), text_scale=0.2, text_fg=(0.95, 0.95, 0.0, 1.0), text_font=ToontownGlobals.getSignFont(), textMayChange=True, image=DirectGuiGlobals.getDefaultDialogGeom(), image_scale=(0.33, 1.0, 0.33), pos=(-0.3, 0.0, 0.2), scale=0.9, ) # counter with jellybean jar in the background for beans in the # "pocketbook" (the beans you carry around with you that are not in your # home bank) purchaseModels = loader.loadModel("phase_4/models/gui/purchase_gui") jarImage = purchaseModels.find("**/Jar") self.jarLabel = DirectLabel( parent=self, relief=None, text=str(0), text_align=TextNode.ACenter, text_pos=(0.0, -0.07), text_scale=0.2, text_fg=JellybeanRewardGui.JarLabelTextColor, text_font=ToontownGlobals.getSignFont(), textMayChange=True, image=jarImage, scale=0.7, pos=(0.3, 0.0, 0.17), ) purchaseModels.removeNode() del purchaseModels jarImage.removeNode() del jarImage # message text self.messageLabel = DirectLabel( parent=self, relief=None, text="", text_align=TextNode.ALeft, text_wordwrap=16.0, text_scale=0.07, pos=(-0.52, 0.0, -0.1), textMayChange=True, ) self.doubledJellybeanLabel = DirectLabel( parent=self, relief=None, text=TTLocalizer.PartyRewardDoubledJellybean, text_align=TextNode.ACenter, text_wordwrap=12.0, text_scale=0.09, text_fg=(1.0, 0.125, 0.125, 1.0), pos=(0.0, 0.0, -0.465), textMayChange=False, ) self.doubledJellybeanLabel.hide() # button to close the gui when the player is done reading it self.closeButton = DirectButton( parent=self, relief=None, text=TTLocalizer.PartyJellybeanRewardOK, text_align=TextNode.ACenter, text_scale=0.065, text_pos=(0.0, -0.625), geom=( publicPartyGui.find("**/startButton_up"), publicPartyGui.find("**/startButton_down"), publicPartyGui.find("**/startButton_rollover"), publicPartyGui.find("**/startButton_inactive"), ), geom_pos=(-0.39, 0.0, 0.125), # place the geom to line up with the text command=self._close, ) publicPartyGui.removeNode() del publicPartyGui self.countSound = base.loadSfx( "phase_13/audio/sfx/tick_counter_short.mp3") self.overMaxSound = base.loadSfx( "phase_13/audio/sfx/tick_counter_overflow.mp3") def showReward(self, earnedAmount, jarAmount, message): """ This function assumes that the amount earned has already been updated for the toon. Parameters: earnedAmount- How many jellybeans the toon gets jarAmount- Amount in their pocketbook jar message- Activity-specific information to display while showing the jellybean reward animation. """ JellybeanRewardGui.notify.debug( "showReward( earnedAmount=%d, jarAmount=%d, ...)" % (earnedAmount, jarAmount)) # set parameters self.earnedCount = earnedAmount self.earnedLabel["text"] = str(self.earnedCount) self.jarCount = jarAmount self.jarMax = base.localAvatar.getMaxMoney() self.jarLabel["text"] = str(self.jarCount) self.jarLabel["text_fg"] = JellybeanRewardGui.JarLabelTextColor self.messageLabel["text"] = message if base.cr.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_DAY): self.doubledJellybeanLabel.show() else: self.doubledJellybeanLabel.hide() # show the gui self.unstash() taskMgr.doMethodLater( JellybeanRewardGui.PreCountdownDelay, self.transferOneJellybean, "JellybeanRewardGuiTransferOneJellybean", extraArgs=[], ) def transferOneJellybean(self): if self.earnedCount == 0: return # count the beans won counter down and the total counter up self.earnedCount -= 1 self.earnedLabel["text"] = str(self.earnedCount) self.jarCount += 1 # only update the total display if under max if self.jarCount <= self.jarMax: self.jarLabel['text'] = str(self.jarCount) # if we have reached the max, color the jar text accordingly elif self.jarCount > self.jarMax: self.jarLabel[ "text_fg"] = JellybeanRewardGui.JarLabelMaxedTextColor # play the counting sound if self.jarCount <= self.jarMax: base.playSfx(self.countSound) # or the over max sound else: base.playSfx(self.overMaxSound) taskMgr.doMethodLater( JellybeanRewardGui.CountDownRate, self.transferOneJellybean, "JellybeanRewardGuiTransferOneJellybean", extraArgs=[], ) def _close(self): taskMgr.remove("JellybeanRewardGuiTransferOneJellybean") self.stash() messenger.send(self.doneEvent) def destroy(self): taskMgr.remove("JellybeanRewardGuiTransferOneJellybean") del self.countSound del self.overMaxSound self.frame.destroy() self.earnedLabel.destroy() self.jarLabel.destroy() self.messageLabel.destroy() self.closeButton.destroy() DirectFrame.destroy(self)