import copy from direct.controls.ControlManager import CollisionHandlerRayStart from direct.directnotify import DirectNotifyGlobal from direct.directtools.DirectGeometry import CLAMP from direct.distributed.ClockDelta import * from direct.fsm import ClassicFSM from direct.fsm import State from direct.interval.IntervalGlobal import * from direct.task import Task import math from pandac.PandaModules import * import DistributedSuitPlanner import Suit import SuitBase import SuitDNA import SuitDialog import SuitTimings from otp.avatar import DistributedAvatar from otp.otpbase import OTPGlobals from toontown.battle import BattleProps from toontown.battle import DistributedBattle from toontown.chat.ChatGlobals import * from toontown.nametag.NametagGlobals import * from toontown.toonbase import TTLocalizer from toontown.toonbase import ToontownBattleGlobals from toontown.toonbase import ToontownGlobals class DistributedSuitBase(DistributedAvatar.DistributedAvatar, Suit.Suit, SuitBase.SuitBase): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedSuitBase') def __init__(self, cr): try: self.DistributedSuitBase_initialized return except: self.DistributedSuitBase_initialized = 1 DistributedAvatar.DistributedAvatar.__init__(self, cr) Suit.Suit.__init__(self) SuitBase.SuitBase.__init__(self) self.activeShadow = 0 self.virtual = 0 self.battleDetectName = None self.cRay = None self.cRayNode = None self.cRayNodePath = None self.cRayBitMask = None self.lifter = None self.cTrav = None self.sp = None self.fsm = None self.prop = None self.propInSound = None self.propOutSound = None self.reparentTo(hidden) self.loop('neutral') self.skeleRevives = 0 self.maxSkeleRevives = 0 self.sillySurgeText = False self.interactivePropTrackBonus = -1 return def setVirtual(self, virtual): pass def getVirtual(self): return 0 def setSkeleRevives(self, num): if num == None: num = 0 self.skeleRevives = num if num > self.maxSkeleRevives: self.maxSkeleRevives = num if self.getSkeleRevives() > 0: nameInfo = TTLocalizer.SuitBaseNameWithLevel % {'name': self.name, 'dept': self.getStyleDept(), 'level': '%s%s' % (self.getActualLevel(), TTLocalizer.SkeleRevivePostFix % (self.skeleRevives + 1))} self.setDisplayName(nameInfo) else: nameInfo = TTLocalizer.SuitBaseNameWithLevel % {'name': self.name, 'dept': self.getStyleDept(), 'level': self.getActualLevel()} self.setDisplayName(nameInfo) return def getSkeleRevives(self): return self.skeleRevives def getMaxSkeleRevives(self): return self.maxSkeleRevives def generate(self): DistributedAvatar.DistributedAvatar.generate(self) def disable(self): self.notify.debug('DistributedSuit %d: disabling' % self.getDoId()) self.ignoreAll() self.__removeCollisionData() self.cleanupLoseActor() self.stop() taskMgr.remove(self.uniqueName('blink-task')) DistributedAvatar.DistributedAvatar.disable(self) def delete(self): try: self.DistributedSuitBase_deleted except: self.DistributedSuitBase_deleted = 1 self.notify.debug('DistributedSuit %d: deleting' % self.getDoId()) del self.dna del self.sp DistributedAvatar.DistributedAvatar.delete(self) Suit.Suit.delete(self) SuitBase.SuitBase.delete(self) def setDNAString(self, dnaString): Suit.Suit.setDNAString(self, dnaString) def setDNA(self, dna): Suit.Suit.setDNA(self, dna) def getHP(self): return self.currHP def getMaxHP(self): return self.maxHP def setHP(self, hp): if hp > self.maxHP: self.currHP = self.maxHP else: self.currHP = hp return None def getDialogueArray(self, *args): return Suit.Suit.getDialogueArray(self, *args) def __removeCollisionData(self): self.enableRaycast(0) self.cRay = None self.cRayNode = None self.cRayNodePath = None self.lifter = None self.cTrav = None return def setHeight(self, height): Suit.Suit.setHeight(self, height) def getRadius(self): return Suit.Suit.getRadius(self) def setLevelDist(self, level): if self.notify.getDebug(): self.notify.debug('Got level %d from server for suit %d' % (level, self.getDoId())) self.setLevel(level) def attachPropeller(self): if self.prop == None: self.prop = BattleProps.globalPropPool.getProp('propeller') if self.propInSound == None: self.propInSound = base.loadSfx('phase_5/audio/sfx/ENC_propeller_in.ogg') if self.propOutSound == None: self.propOutSound = base.loadSfx('phase_5/audio/sfx/ENC_propeller_out.ogg') if base.config.GetBool('want-new-cogs', 0): head = self.find('**/to_head') if head.isEmpty(): head = self.find('**/joint_head') else: head = self.find('**/joint_head') self.prop.reparentTo(head) return def detachPropeller(self): if self.prop: self.prop.cleanup() self.prop.removeNode() self.prop = None if self.propInSound: self.propInSound = None if self.propOutSound: self.propOutSound = None return def beginSupaFlyMove(self, pos, moveIn, trackName, walkAfterLanding=True): skyPos = Point3(pos) if moveIn: skyPos.setZ(pos.getZ() + SuitTimings.fromSky * ToontownGlobals.SuitWalkSpeed) else: skyPos.setZ(pos.getZ() + SuitTimings.toSky * ToontownGlobals.SuitWalkSpeed) groundF = 28 dur = self.getDuration('landing') fr = self.getFrameRate('landing') if fr: animTimeInAir = groundF / fr else: animTimeInAir = groundF impactLength = dur - animTimeInAir timeTillLanding = SuitTimings.fromSky - impactLength waitTime = timeTillLanding - animTimeInAir if self.prop == None: self.prop = BattleProps.globalPropPool.getProp('propeller') propDur = self.prop.getDuration('propeller') lastSpinFrame = 8 fr = self.prop.getFrameRate('propeller') spinTime = lastSpinFrame / fr openTime = (lastSpinFrame + 1) / fr if moveIn: lerpPosTrack = Sequence(self.posInterval(timeTillLanding, pos, startPos=skyPos), Wait(impactLength)) shadowScale = self.dropShadow.getScale() shadowTrack = Sequence(Func(self.dropShadow.reparentTo, render), Func(self.dropShadow.setPos, pos), self.dropShadow.scaleInterval(timeTillLanding, self.scale, startScale=Vec3(0.01, 0.01, 1.0)), Func(self.dropShadow.reparentTo, self.getShadowJoint()), Func(self.dropShadow.setPos, 0, 0, 0), Func(self.dropShadow.setScale, shadowScale)) fadeInTrack = Sequence(Func(self.setTransparency, 1), self.colorScaleInterval(1, colorScale=VBase4(1, 1, 1, 1), startColorScale=VBase4(1, 1, 1, 0)), Func(self.clearColorScale), Func(self.clearTransparency)) animTrack = Sequence(Func(self.pose, 'landing', 0), Wait(waitTime), ActorInterval(self, 'landing', duration=dur)) if walkAfterLanding: animTrack.append(Func(self.loop, 'walk')) self.attachPropeller() propTrack = Parallel(SoundInterval(self.propInSound, duration=waitTime + dur, node=self), Sequence(ActorInterval(self.prop, 'propeller', constrainedLoop=1, duration=waitTime + spinTime, startTime=0.0, endTime=spinTime), ActorInterval(self.prop, 'propeller', duration=propDur - openTime, startTime=openTime), Func(self.detachPropeller))) return Parallel(lerpPosTrack, shadowTrack, fadeInTrack, animTrack, propTrack, name=self.taskName('trackName')) else: lerpPosTrack = Sequence(Wait(impactLength), LerpPosInterval(self, timeTillLanding, skyPos, startPos=pos)) shadowTrack = Sequence(Func(self.dropShadow.reparentTo, render), Func(self.dropShadow.setPos, pos), self.dropShadow.scaleInterval(timeTillLanding, Vec3(0.01, 0.01, 1.0), startScale=self.scale), Func(self.dropShadow.reparentTo, self.getShadowJoint()), Func(self.dropShadow.setPos, 0, 0, 0)) fadeOutTrack = Sequence(Func(self.setTransparency, 1), self.colorScaleInterval(1, colorScale=VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1)), Func(self.clearColorScale), Func(self.clearTransparency), Func(self.reparentTo, hidden)) actInt = ActorInterval(self, 'landing', loop=0, startTime=dur, endTime=0.0) self.attachPropeller() self.prop.hide() propTrack = Parallel(SoundInterval(self.propOutSound, duration=waitTime + dur, node=self), Sequence(Func(self.prop.show), ActorInterval(self.prop, 'propeller', endTime=openTime, startTime=propDur), ActorInterval(self.prop, 'propeller', constrainedLoop=1, duration=propDur - openTime, startTime=spinTime, endTime=0.0), Func(self.detachPropeller))) return Parallel(ParallelEndTogether(lerpPosTrack, shadowTrack, fadeOutTrack), actInt, propTrack, name=self.taskName('trackName')) return def enableBattleDetect(self, name, handler): if self.collTube: self.battleDetectName = self.taskName(name) self.collNode = CollisionNode(self.battleDetectName) self.collNode.addSolid(self.collTube) self.collNodePath = self.attachNewNode(self.collNode) self.collNode.setCollideMask(ToontownGlobals.WallBitmask) self.accept('enter' + self.battleDetectName, handler) return Task.done def disableBattleDetect(self): if self.battleDetectName: self.ignore('enter' + self.battleDetectName) self.battleDetectName = None if self.collNodePath: self.collNodePath.removeNode() self.collNodePath = None return def enableRaycast(self, enable = 1): if not self.cTrav or not hasattr(self, 'cRayNode') or not self.cRayNode: return self.cTrav.removeCollider(self.cRayNodePath) if enable: if self.notify.getDebug(): self.notify.debug('enabling raycast') self.cTrav.addCollider(self.cRayNodePath, self.lifter) elif self.notify.getDebug(): self.notify.debug('disabling raycast') def b_setBrushOff(self, index): self.setBrushOff(index) self.d_setBrushOff(index) def d_setBrushOff(self, index): self.sendUpdate('setBrushOff', [index]) def setBrushOff(self, index): self.setChatAbsolute(SuitDialog.getBrushOffText(self.getStyleName(), index), CFSpeech | CFTimeout) def initializeBodyCollisions(self, collIdStr): DistributedAvatar.DistributedAvatar.initializeBodyCollisions(self, collIdStr) if not self.ghostMode: self.collNode.setCollideMask(self.collNode.getIntoCollideMask() | ToontownGlobals.PieBitmask) self.cRay = CollisionRay(0.0, 0.0, CollisionHandlerRayStart, 0.0, 0.0, -1.0) self.cRayNode = CollisionNode(self.taskName('cRay')) self.cRayNode.addSolid(self.cRay) self.cRayNodePath = self.attachNewNode(self.cRayNode) self.cRayNodePath.hide() self.cRayBitMask = ToontownGlobals.FloorBitmask self.cRayNode.setFromCollideMask(self.cRayBitMask) self.cRayNode.setIntoCollideMask(BitMask32.allOff()) self.lifter = CollisionHandlerFloor() self.lifter.setOffset(ToontownGlobals.FloorOffset) self.lifter.setReach(6.0) self.lifter.setMaxVelocity(8.0) self.lifter.addCollider(self.cRayNodePath, self) self.cTrav = base.cTrav def disableBodyCollisions(self): self.disableBattleDetect() self.enableRaycast(0) if self.cRayNodePath: self.cRayNodePath.removeNode() del self.cRayNode del self.cRay del self.lifter def denyBattle(self): self.notify.debug('denyBattle()') place = self.cr.playGame.getPlace() if place.fsm.getCurrentState().getName() == 'WaitForBattle': place.setState('walk') self.resumePath(self.pathState) def makePathTrack(self, nodePath, posPoints, velocity, name): track = Sequence(name=name) nodePath.setPos(posPoints[0]) for pointIndex in xrange(len(posPoints) - 1): startPoint = posPoints[pointIndex] endPoint = posPoints[pointIndex + 1] track.append(Func(nodePath.headsUp, endPoint[0], endPoint[1], endPoint[2])) distance = Vec3(endPoint - startPoint).length() duration = distance / velocity track.append(LerpPosInterval(nodePath, duration=duration, pos=Point3(endPoint), startPos=Point3(startPoint))) return track def setState(self, state): if self.fsm == None: return 0 if self.fsm.getCurrentState().getName() == state: return 0 return self.fsm.request(state) def subclassManagesParent(self): return 0 def enterOff(self, *args): self.hideNametag3d() self.hideNametag2d() if not self.subclassManagesParent(): self.setParent(ToontownGlobals.SPHidden) def exitOff(self): if not self.subclassManagesParent(): self.setParent(ToontownGlobals.SPRender) self.showNametag3d() self.showNametag2d() self.loop('neutral', 0) def enterBattle(self): self.loop('neutral', 0) self.disableBattleDetect() self.corpMedallion.hide() self.healthBar.show() if self.currHP < self.maxHP: self.updateHealthBar(0, 1) def exitBattle(self): self.healthBar.hide() self.corpMedallion.show() self.currHP = self.maxHP self.interactivePropTrackBonus = -1 def enterWaitForBattle(self): self.loop('neutral', 0) def exitWaitForBattle(self): pass def setSkelecog(self, flag): SuitBase.SuitBase.setSkelecog(self, flag) if flag: Suit.Suit.makeSkeleton(self) def setWaiter(self, flag): SuitBase.SuitBase.setWaiter(self, flag) if flag: Suit.Suit.makeWaiter(self) def showHpText(self, number, bonus = 0, scale = 1, attackTrack = -1): if self.HpTextEnabled and not self.ghostMode: if number != 0: if self.hpText: self.hideHpText() self.HpTextGenerator.setFont(OTPGlobals.getSignFont()) if number < 0: self.HpTextGenerator.setText(str(number)) if base.cr.newsManager.isHolidayRunning(ToontownGlobals.SILLY_SURGE_HOLIDAY): self.sillySurgeText = True absNum = abs(number) if absNum > 0 and absNum <= 10: self.HpTextGenerator.setText(str(number) + '\n' + TTLocalizer.SillySurgeTerms[1]) elif absNum > 10 and absNum <= 20: self.HpTextGenerator.setText(str(number) + '\n' + TTLocalizer.SillySurgeTerms[2]) elif absNum > 20 and absNum <= 30: self.HpTextGenerator.setText(str(number) + '\n' + TTLocalizer.SillySurgeTerms[3]) elif absNum > 30 and absNum <= 40: self.HpTextGenerator.setText(str(number) + '\n' + TTLocalizer.SillySurgeTerms[4]) elif absNum > 40 and absNum <= 50: self.HpTextGenerator.setText(str(number) + '\n' + TTLocalizer.SillySurgeTerms[5]) elif absNum > 50 and absNum <= 60: self.HpTextGenerator.setText(str(number) + '\n' + TTLocalizer.SillySurgeTerms[6]) elif absNum > 60 and absNum <= 70: self.HpTextGenerator.setText(str(number) + '\n' + TTLocalizer.SillySurgeTerms[7]) elif absNum > 70 and absNum <= 80: self.HpTextGenerator.setText(str(number) + '\n' + TTLocalizer.SillySurgeTerms[8]) elif absNum > 80 and absNum <= 90: self.HpTextGenerator.setText(str(number) + '\n' + TTLocalizer.SillySurgeTerms[9]) elif absNum > 90 and absNum <= 100: self.HpTextGenerator.setText(str(number) + '\n' + TTLocalizer.SillySurgeTerms[10]) elif absNum > 100 and absNum <= 110: self.HpTextGenerator.setText(str(number) + '\n' + TTLocalizer.SillySurgeTerms[11]) else: self.HpTextGenerator.setText(str(number) + '\n' + TTLocalizer.SillySurgeTerms[12]) if self.interactivePropTrackBonus > -1 and self.interactivePropTrackBonus == attackTrack: self.sillySurgeText = True if attackTrack in TTLocalizer.InteractivePropTrackBonusTerms: self.HpTextGenerator.setText(str(number) + '\n' + TTLocalizer.InteractivePropTrackBonusTerms[attackTrack]) else: self.HpTextGenerator.setText('+' + str(number)) self.HpTextGenerator.clearShadow() self.HpTextGenerator.setAlign(TextNode.ACenter) if bonus == 1: r = 1.0 g = 1.0 b = 0 a = 1 elif bonus == 2: r = 1.0 g = 0.5 b = 0 a = 1 elif number < 0: r = 0.9 g = 0 b = 0 a = 1 if self.interactivePropTrackBonus > -1 and self.interactivePropTrackBonus == attackTrack: r = 0 g = 0 b = 1 a = 1 else: r = 0 g = 0.9 b = 0 a = 1 self.HpTextGenerator.setTextColor(r, g, b, a) self.hpTextNode = self.HpTextGenerator.generate() self.hpText = self.attachNewNode(self.hpTextNode) self.hpText.setScale(scale) self.hpText.setBillboardPointEye() self.hpText.setBin('fixed', 100) if self.sillySurgeText: self.nametag3d.setDepthTest(0) self.nametag3d.setBin('fixed', 99) self.hpText.setPos(0, 0, self.height / 2) seq = Sequence(self.hpText.posInterval(1.0, Point3(0, 0, self.height + 1.5), blendType='easeOut'), Wait(0.85), self.hpText.colorInterval(0.1, Vec4(r, g, b, 0), 0.1), Func(self.hideHpText)) seq.start() def hideHpText(self): DistributedAvatar.DistributedAvatar.hideHpText(self) if self.sillySurgeText: self.nametag3d.clearDepthTest() self.nametag3d.clearBin() self.sillySurgeText = False def getAvIdName(self): try: level = self.getActualLevel() except: level = '???' return '%s\n%s\nLevel %s' % (self.getName(), self.doId, level)