2022-12-16 18:40:57 -06:00
|
|
|
from panda3d.core import DepthOffsetAttrib, NodePath, Vec3, Vec4, TextNode
|
2019-11-02 17:27:54 -05:00
|
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
|
|
from direct.fsm.FSM import FSM
|
|
|
|
from direct.interval.FunctionInterval import Wait
|
|
|
|
from direct.interval.IntervalGlobal import Func, LerpHprInterval, LerpScaleInterval, LerpFunctionInterval
|
|
|
|
from direct.interval.MetaInterval import Sequence, Parallel
|
|
|
|
from direct.distributed.ClockDelta import globalClockDelta
|
|
|
|
from toontown.toonbase import ToontownGlobals
|
|
|
|
from toontown.effects import DustCloud
|
2019-12-30 00:07:56 -06:00
|
|
|
from . import CogdoFlyingGameGlobals as Globals
|
|
|
|
from . import CogdoUtil
|
|
|
|
from .CogdoFlyingObjects import CogdoFlyingGatherable
|
|
|
|
from .CogdoFlyingUtil import swapAvatarShadowPlacer
|
2019-11-02 17:27:54 -05:00
|
|
|
|
|
|
|
class CogdoFlyingPlayer(FSM):
|
|
|
|
notify = DirectNotifyGlobal.directNotify.newCategory('CogdoFlyingPlayer')
|
|
|
|
|
|
|
|
def __init__(self, toon):
|
|
|
|
FSM.__init__(self, 'CogdoFlyingPlayer')
|
|
|
|
self.toon = toon
|
|
|
|
self.toon.reparentTo(render)
|
|
|
|
self.legalEaglesTargeting = []
|
|
|
|
self.activeBuffs = []
|
|
|
|
self.initModels()
|
|
|
|
self.initIntervals()
|
|
|
|
self.netTimeSentToStartDeath = 0
|
|
|
|
self.backpackState = -1
|
|
|
|
self.lastBackpackState = -1
|
|
|
|
self.lastPropellerSpinRate = Globals.Gameplay.NormalPropSpeed
|
|
|
|
self.propellerSpinRate = Globals.Gameplay.NormalPropSpeed
|
|
|
|
self.setFuelState(Globals.Gameplay.FuelStates.FuelNoPropeller)
|
|
|
|
self.setOldFuelState(self.fuelState)
|
|
|
|
CogdoFlyingPlayer.setBlades(self, Globals.Gameplay.FuelStates.FuelNoPropeller)
|
|
|
|
self.setBackpackState(Globals.Gameplay.BackpackStates.Normal)
|
|
|
|
|
|
|
|
def initModels(self):
|
|
|
|
self.createPropeller()
|
|
|
|
self.createRedTapeRing()
|
|
|
|
|
|
|
|
def createPropeller(self):
|
|
|
|
self.propellerSmoke = DustCloud.DustCloud(self.toon, wantSound=False)
|
|
|
|
self.propellerSmoke.setBillboardPointEye()
|
|
|
|
self.propellerSmoke.setBin('fixed', 5002)
|
|
|
|
self.backpack = CogdoUtil.loadFlyingModel('propellerPack')
|
|
|
|
self.backpack.setScale(1.3)
|
|
|
|
self.backpack.setHpr(180.0, 0.0, 0.0)
|
|
|
|
self.backpackInstances = []
|
|
|
|
self.backpackTextureCard = CogdoUtil.loadFlyingModel('propellerPack_card')
|
|
|
|
parts = self.toon.getTorsoParts()
|
|
|
|
for part in parts:
|
|
|
|
backpackInstance = part.attachNewNode('backpackInstance')
|
|
|
|
animal = self.toon.style.getAnimal()
|
|
|
|
bodyScale = ToontownGlobals.toonBodyScales[animal]
|
|
|
|
backpackHeight = ToontownGlobals.torsoHeightDict[self.toon.style.torso] * bodyScale - 0.5
|
|
|
|
backpackInstance.setPos(0.0, -0.325, backpackHeight)
|
|
|
|
self.backpackInstances.append(backpackInstance)
|
|
|
|
self.backpack.instanceTo(backpackInstance)
|
|
|
|
|
|
|
|
self.propInstances = []
|
|
|
|
self.propeller = CogdoUtil.loadFlyingModel('toonPropeller')
|
|
|
|
for part in self.backpackInstances:
|
|
|
|
propInstance = part.attachNewNode('propInstance')
|
|
|
|
propInstance.setPos(0.0, -0.275, 0.0)
|
|
|
|
propInstance.setHpr(0.0, 20.0, 0.0)
|
|
|
|
propInstance.setScale(1.0, 1.0, 1.25)
|
|
|
|
self.propInstances.append(propInstance)
|
|
|
|
self.propeller.instanceTo(propInstance)
|
|
|
|
|
|
|
|
self.blades = []
|
|
|
|
self.activeBlades = []
|
|
|
|
index = 1
|
|
|
|
blade = self.propeller.find('**/propeller%d' % index)
|
|
|
|
while not blade.isEmpty():
|
|
|
|
self.blades.append(blade)
|
|
|
|
index += 1
|
|
|
|
blade = self.propeller.find('**/propeller%d' % index)
|
|
|
|
|
|
|
|
for blade in self.blades:
|
|
|
|
self.activeBlades.append(blade)
|
|
|
|
|
|
|
|
def createRedTapeRing(self):
|
|
|
|
self.redTapeRing = CogdoUtil.loadFlyingModel('redTapeRing')
|
|
|
|
self.redTapeRing.setTwoSided(True)
|
|
|
|
self.redTapeRing.reparentTo(self.toon)
|
|
|
|
self.redTapeRing.hide()
|
|
|
|
self.redTapeRing.setScale(1.25)
|
|
|
|
self.redTapeRing.setZ(self.toon.getHeight() / 2.0)
|
|
|
|
|
|
|
|
def initIntervals(self):
|
|
|
|
self.baseSpinDuration = 1.0
|
|
|
|
self.propellerSpinLerp = LerpFunctionInterval(self.propeller.setH, fromData=0.0, toData=360.0, duration=self.baseSpinDuration, name='%s.propellerSpinLerp-%s' % (self.__class__.__name__, self.toon.doId))
|
|
|
|
singleBlinkTime = Globals.Gameplay.TargetedWarningSingleBlinkTime
|
|
|
|
blinkTime = Globals.Gameplay.TargetedWarningBlinkTime
|
|
|
|
self.blinkLoop = Sequence(Wait(singleBlinkTime / 2.0), Func(self.setBackpackTexture, Globals.Gameplay.BackpackStates.Attacked), Wait(singleBlinkTime / 2.0), Func(self.setBackpackTexture, Globals.Gameplay.BackpackStates.Targeted), name='%s.blinkLoop-%s' % (self.__class__.__name__, self.toon.doId))
|
|
|
|
self.blinkWarningSeq = Sequence(Func(self.blinkLoop.loop), Wait(blinkTime), Func(self.blinkLoop.clearToInitial), name='%s.blinkWarningSeq-%s' % (self.__class__.__name__, self.toon.doId))
|
|
|
|
dur = Globals.Gameplay.BackpackRefuelDuration
|
|
|
|
self.refuelSeq = Sequence(Func(self.setPropellerSpinRate, Globals.Gameplay.RefuelPropSpeed), Wait(dur), Func(self.returnBackpackToLastStateFunc), name='%s.refuelSeq-%s' % (self.__class__.__name__, self.toon.doId))
|
|
|
|
scale = self.redTapeRing.getScale()
|
|
|
|
pulseTime = 1.0
|
|
|
|
self.pulseBubbleSeq = Parallel(Sequence(LerpFunctionInterval(self.redTapeRing.setScale, fromData=scale, toData=scale * 1.1, duration=pulseTime / 2.0, blendType='easeInOut'), LerpFunctionInterval(self.redTapeRing.setScale, fromData=scale * 1.1, toData=scale, duration=pulseTime / 2.0, blendType='easeInOut')), LerpHprInterval(self.redTapeRing, pulseTime, Vec3(360, 0, 0), startHpr=Vec3(0, 0, 0)), name='%s.pulseBubbleSeq-%s' % (self.__class__.__name__, self.toon.doId))
|
|
|
|
bouncePercent = 1.2
|
|
|
|
scaleTime = 0.5
|
|
|
|
scaleBounceTime = 0.25
|
|
|
|
self.popUpBubbleLerp = LerpScaleInterval(self.redTapeRing, scaleTime, scale * bouncePercent, startScale=0.0, blendType='easeInOut')
|
|
|
|
self.popUpBubbleSeq = Sequence(Func(self.updateLerpStartScale, self.popUpBubbleLerp, self.redTapeRing), Func(self.redTapeRing.show), self.popUpBubbleLerp, LerpScaleInterval(self.redTapeRing, scaleBounceTime, scale, startScale=scale * bouncePercent, blendType='easeInOut'), Func(self.pulseBubbleSeq.loop), name='%s.popUpBubbleSeq-%s' % (self.__class__.__name__, self.toon.doId))
|
|
|
|
self.removeBubbleLerp = LerpScaleInterval(self.redTapeRing, scaleBounceTime, scale * bouncePercent, startScale=scale, blendType='easeInOut')
|
|
|
|
self.removeBubbleSeq = Sequence(Func(self.pulseBubbleSeq.clearToInitial), Func(self.updateLerpStartScale, self.removeBubbleLerp, self.redTapeRing), self.removeBubbleLerp, LerpScaleInterval(self.redTapeRing, scaleTime, 0.0, startScale=scale * bouncePercent, blendType='easeInOut'), Func(self.redTapeRing.hide), name='%s.removeBubbleSeq-%s' % (self.__class__.__name__, self.toon.doId))
|
|
|
|
self.redTapeRing.setScale(0.0)
|
|
|
|
self.deathInterval = Sequence(Parallel(LerpHprInterval(self.toon, 1.0, Vec3(720, 0, 0)), LerpFunctionInterval(self.toon.setScale, fromData=1.0, toData=0.1, duration=1.0)), Func(self.toon.stash), name='%s.deathInterval-%s' % (self.__class__.__name__, self.toon.doId))
|
|
|
|
self.spawnInterval = Sequence(Func(self.toon.stash), Func(self.resetToon), Wait(1.0), Func(self.toon.setAnimState, 'TeleportIn'), Func(self.toon.unstash), name='%s.spawnInterval-%s' % (self.__class__.__name__, self.toon.doId))
|
|
|
|
singleBlinkTime = Globals.Gameplay.InvulSingleBlinkTime
|
|
|
|
blinkTime = Globals.Gameplay.InvulBlinkTime
|
|
|
|
invulBuffTime = Globals.Gameplay.InvulBuffTime
|
|
|
|
self.blinkBubbleLoop = Sequence(LerpFunctionInterval(self.redTapeRing.setAlphaScale, fromData=1.0, toData=0.0, duration=singleBlinkTime / 2.0, blendType='easeInOut'), LerpFunctionInterval(self.redTapeRing.setAlphaScale, fromData=0.0, toData=1.0, duration=singleBlinkTime / 2.0, blendType='easeInOut'), name='%s.blinkBubbleLoop-%s' % (self.__class__.__name__, self.toon.doId))
|
|
|
|
self.blinkBubbleSeq = Sequence(Wait(invulBuffTime - blinkTime), Func(self.blinkBubbleLoop.loop), Wait(blinkTime), Func(self.blinkBubbleLoop.finish), name='%s.blinkBubbleSeq-%s' % (self.__class__.__name__, self.toon.doId))
|
|
|
|
|
|
|
|
def returnBackpackToLastStateFunc(self):
|
|
|
|
if self.backpackState == Globals.Gameplay.BackpackStates.Refuel:
|
|
|
|
self.returnBackpackToLastState()
|
|
|
|
|
|
|
|
def setPropellerSpinRateFunc(self):
|
|
|
|
if self.propellerSpinRate == Globals.Gameplay.RefuelPropSpeed:
|
|
|
|
self.setPropellerSpinRate(self.lastPropellerSpinRate)
|
|
|
|
|
|
|
|
def returnBackpackToLastState(self):
|
|
|
|
self.setBackpackState(self.lastBackpackState)
|
|
|
|
|
|
|
|
def setBackpackState(self, state):
|
|
|
|
if state == self.backpackState:
|
|
|
|
return
|
|
|
|
self.lastBackpackState = self.backpackState
|
|
|
|
self.backpackState = state
|
|
|
|
self.blinkWarningSeq.clearToInitial()
|
|
|
|
self.refuelSeq.clearToInitial()
|
|
|
|
self.blinkLoop.clearToInitial()
|
|
|
|
if self.lastBackpackState == Globals.Gameplay.BackpackStates.Refuel:
|
|
|
|
self.setPropellerSpinRateFunc()
|
|
|
|
if state in Globals.Gameplay.BackpackStates:
|
|
|
|
if state == Globals.Gameplay.BackpackStates.Normal:
|
|
|
|
pass
|
|
|
|
elif state == Globals.Gameplay.BackpackStates.Targeted:
|
|
|
|
pass
|
|
|
|
elif state == Globals.Gameplay.BackpackStates.Refuel:
|
|
|
|
self.refuelSeq.start()
|
|
|
|
elif state == Globals.Gameplay.BackpackStates.Attacked:
|
|
|
|
self.blinkWarningSeq.start()
|
|
|
|
self.setBackpackTexture(state)
|
|
|
|
|
|
|
|
def setBackpackTexture(self, state):
|
|
|
|
texName = Globals.Gameplay.BackpackState2TextureName[state]
|
|
|
|
tex = self.backpackTextureCard.findTexture(texName)
|
|
|
|
self.backpack.setTexture(tex, 1)
|
|
|
|
|
|
|
|
def updateLerpStartScale(self, lerp, nodepath):
|
|
|
|
lerp.setStartScale(nodepath.getScale())
|
|
|
|
|
|
|
|
def handleEnterGatherable(self, gatherable, elapsedTime):
|
|
|
|
if gatherable.type == Globals.Level.GatherableTypes.InvulPowerup:
|
|
|
|
self.blinkBubbleSeq.clearToInitial()
|
|
|
|
self.blinkBubbleSeq.start(elapsedTime)
|
|
|
|
self.removeBubbleSeq.clearToInitial()
|
|
|
|
self.popUpBubbleSeq.start()
|
|
|
|
if gatherable.type not in self.activeBuffs:
|
|
|
|
self.activeBuffs.append(gatherable.type)
|
|
|
|
elif gatherable.type == Globals.Level.GatherableTypes.Propeller:
|
|
|
|
self.setBackpackState(Globals.Gameplay.BackpackStates.Refuel)
|
|
|
|
|
|
|
|
def handleDebuffPowerup(self, pickupType, elapsedTime):
|
|
|
|
if pickupType == Globals.Level.GatherableTypes.InvulPowerup:
|
|
|
|
self.blinkBubbleSeq.finish()
|
|
|
|
self.popUpBubbleSeq.clearToInitial()
|
|
|
|
self.removeBubbleSeq.start()
|
|
|
|
if pickupType in self.activeBuffs:
|
|
|
|
self.activeBuffs.remove(pickupType)
|
|
|
|
|
|
|
|
def isBuffActive(self, pickupType):
|
|
|
|
if pickupType in self.activeBuffs:
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
def isInvulnerable(self):
|
|
|
|
if Globals.Level.GatherableTypes.InvulPowerup in self.activeBuffs:
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
def setFuelState(self, fuelState):
|
|
|
|
self.fuelState = fuelState
|
|
|
|
|
|
|
|
def setOldFuelState(self, fuelState):
|
|
|
|
self.oldFuelState = fuelState
|
|
|
|
|
|
|
|
def hasFuelStateChanged(self):
|
|
|
|
if self.fuelState != self.oldFuelState:
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
|
|
|
def updatePropellerSmoke(self):
|
|
|
|
if not self.hasFuelStateChanged():
|
|
|
|
return
|
|
|
|
if self.fuelState in [Globals.Gameplay.FuelStates.FuelNoPropeller, Globals.Gameplay.FuelStates.FuelNormal]:
|
|
|
|
self.propellerSmoke.stop()
|
|
|
|
elif self.fuelState in [Globals.Gameplay.FuelStates.FuelVeryLow, Globals.Gameplay.FuelStates.FuelEmpty]:
|
|
|
|
self.propellerSmoke.stop()
|
|
|
|
self.propellerSmoke.setScale(0.25)
|
|
|
|
self.propellerSmoke.setZ(self.toon.getHeight() + 2.5)
|
|
|
|
self.propellerSmoke.loop(rate=48)
|
|
|
|
elif self.fuelState in [Globals.Gameplay.FuelStates.FuelLow]:
|
|
|
|
self.propellerSmoke.stop()
|
|
|
|
self.propellerSmoke.setScale(0.0825)
|
|
|
|
self.propellerSmoke.setZ(self.toon.getHeight() + 2.0)
|
|
|
|
self.propellerSmoke.loop(rate=24)
|
|
|
|
|
|
|
|
def resetBlades(self):
|
|
|
|
self.setBlades(len(self.blades))
|
|
|
|
|
|
|
|
def setAsLegalEagleTarget(self, legalEagle):
|
|
|
|
if legalEagle not in self.legalEaglesTargeting:
|
|
|
|
self.legalEaglesTargeting.append(legalEagle)
|
|
|
|
|
|
|
|
def removeAsLegalEagleTarget(self, legalEagle):
|
|
|
|
if legalEagle in self.legalEaglesTargeting:
|
|
|
|
self.legalEaglesTargeting.remove(legalEagle)
|
|
|
|
|
|
|
|
def isLegalEagleTarget(self):
|
|
|
|
if len(self.legalEaglesTargeting) > 0:
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
|
|
|
def setBlades(self, fuelState):
|
|
|
|
if fuelState not in Globals.Gameplay.FuelStates:
|
|
|
|
return
|
|
|
|
numBlades = fuelState - 1
|
|
|
|
if len(self.activeBlades) != numBlades:
|
|
|
|
for i in range(len(self.activeBlades)):
|
|
|
|
blade = self.activeBlades.pop()
|
|
|
|
blade.stash()
|
|
|
|
|
|
|
|
if numBlades > len(self.blades):
|
|
|
|
numBlades = len(self.blades)
|
|
|
|
if numBlades > 0:
|
|
|
|
for i in range(numBlades):
|
|
|
|
blade = self.blades[i]
|
|
|
|
self.activeBlades.append(blade)
|
|
|
|
blade.unstash()
|
|
|
|
|
|
|
|
if fuelState == Globals.Gameplay.FuelStates.FuelNoPropeller:
|
|
|
|
for prop in self.propInstances:
|
|
|
|
prop.hide()
|
|
|
|
|
|
|
|
else:
|
|
|
|
for prop in self.propInstances:
|
|
|
|
prop.show()
|
|
|
|
|
|
|
|
self.setFuelState(fuelState)
|
|
|
|
self.updatePropellerSmoke()
|
|
|
|
self.setOldFuelState(self.fuelState)
|
|
|
|
|
|
|
|
def bladeLost(self):
|
|
|
|
if len(self.activeBlades) > 0:
|
|
|
|
blade = self.activeBlades.pop()
|
|
|
|
blade.stash()
|
|
|
|
self.setFuelState(len(self.activeBlades) + 1)
|
|
|
|
self.updatePropellerSmoke()
|
|
|
|
self.setOldFuelState(self.fuelState)
|
|
|
|
|
|
|
|
def setPropellerSpinRate(self, newRate):
|
|
|
|
self.lastPropellerSpinRate = self.propellerSpinRate
|
|
|
|
self.propellerSpinRate = newRate
|
|
|
|
self.notify.debug('(%s) New propeller speed:%s, old propeller speed:%s' % (self.toon.doId, self.propellerSpinRate, self.lastPropellerSpinRate))
|
|
|
|
self.propellerSpinLerp.setPlayRate(newRate)
|
|
|
|
|
|
|
|
def died(self, elapsedTime):
|
|
|
|
self.deathInterval.start(elapsedTime)
|
|
|
|
self.propellerSmoke.stop()
|
|
|
|
|
|
|
|
def spawn(self, elapsedTime):
|
|
|
|
self.spawnInterval.start(elapsedTime)
|
|
|
|
|
|
|
|
def resetToon(self):
|
|
|
|
self.toon.setScale(1.0)
|
|
|
|
|
|
|
|
def enable(self):
|
|
|
|
self.toon.setAnimState('Happy', 1.0)
|
|
|
|
self.toon.setForceJumpIdle(True)
|
|
|
|
self.toon.setSpeed(0, 0)
|
|
|
|
self.setPropellerSpinRate(Globals.Gameplay.NormalPropSpeed)
|
|
|
|
self.propellerSpinLerp.loop()
|
|
|
|
|
|
|
|
def disable(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def unload(self):
|
|
|
|
self.ignoreAll()
|
|
|
|
if self.toon:
|
|
|
|
self.toon.showName()
|
|
|
|
self.backpackTextureCard.removeNode()
|
|
|
|
del self.backpackTextureCard
|
|
|
|
self.refuelSeq.clearToInitial()
|
|
|
|
del self.refuelSeq
|
|
|
|
self.pulseBubbleSeq.clearToInitial()
|
|
|
|
del self.pulseBubbleSeq
|
|
|
|
self.blinkBubbleLoop.clearToInitial()
|
|
|
|
del self.blinkBubbleLoop
|
|
|
|
self.blinkBubbleSeq.clearToInitial()
|
|
|
|
del self.blinkBubbleSeq
|
|
|
|
self.popUpBubbleLerp.clearToInitial()
|
|
|
|
del self.popUpBubbleLerp
|
|
|
|
self.popUpBubbleSeq.clearToInitial()
|
|
|
|
del self.popUpBubbleSeq
|
|
|
|
self.removeBubbleLerp.clearToInitial()
|
|
|
|
del self.removeBubbleLerp
|
|
|
|
self.removeBubbleSeq.clearToInitial()
|
|
|
|
del self.removeBubbleSeq
|
|
|
|
self.propellerSmoke.destroy()
|
|
|
|
del self.propellerSmoke
|
|
|
|
self.blinkWarningSeq.clearToInitial()
|
|
|
|
del self.blinkWarningSeq
|
|
|
|
self.blinkLoop.clearToInitial()
|
|
|
|
del self.blinkLoop
|
|
|
|
self.redTapeRing.removeNode()
|
|
|
|
del self.redTapeRing
|
|
|
|
self.propellerSpinLerp.clearToInitial()
|
|
|
|
del self.propellerSpinLerp
|
|
|
|
for prop in self.propInstances:
|
|
|
|
prop.removeNode()
|
|
|
|
|
|
|
|
del self.propInstances[:]
|
|
|
|
self.propeller.removeNode()
|
|
|
|
del self.propeller
|
|
|
|
for backpack in self.backpackInstances:
|
|
|
|
backpack.removeNode()
|
|
|
|
|
|
|
|
del self.backpackInstances[:]
|
|
|
|
self.backpack.removeNode()
|
|
|
|
del self.backpack
|
|
|
|
del self.activeBuffs[:]
|
|
|
|
del self.legalEaglesTargeting[:]
|
|
|
|
del self.toon
|
|
|
|
self.toon = None
|
|
|
|
if self.deathInterval:
|
|
|
|
self.deathInterval.clearToInitial()
|
|
|
|
self.deathInterval = None
|
|
|
|
if self.spawnInterval:
|
|
|
|
self.spawnInterval.clearToInitial()
|
|
|
|
self.spawnInterval = None
|
|
|
|
return
|
|
|
|
|
|
|
|
def start(self):
|
|
|
|
swapAvatarShadowPlacer(self.toon, self.toon.uniqueName('toonShadowPlacer'))
|
|
|
|
self.toon.startSmooth()
|
|
|
|
|
|
|
|
def exit(self):
|
|
|
|
self.toon.setForceJumpIdle(False)
|
|
|
|
self.propellerSmoke.reparentTo(hidden)
|
|
|
|
self.propellerSmoke.stop()
|
|
|
|
if self.toon:
|
|
|
|
CogdoFlyingPlayer.resetToon(self)
|
|
|
|
self.toon.setActiveShadow(0)
|
|
|
|
self.toon.deleteDropShadow()
|
|
|
|
self.toon.initializeDropShadow()
|
|
|
|
self.toon.setActiveShadow(1)
|
|
|
|
else:
|
|
|
|
self.notify.warning("There's no toon in offstage, this is bad!")
|