oldschool-toontown/toontown/parties/DistributedPartyTugOfWarActivity.py
2019-12-30 01:07:56 -05:00

697 lines
31 KiB
Python

import math
from pandac.PandaModules import CollisionTube
from pandac.PandaModules import CollisionNode
from pandac.PandaModules import Point3
from pandac.PandaModules import VBase3
from pandac.PandaModules import RopeNode
from direct.interval.IntervalGlobal import LerpPosHprInterval
from direct.interval.IntervalGlobal import LerpPosInterval
from direct.interval.IntervalGlobal import Wait
from direct.interval.IntervalGlobal import ActorInterval
from direct.interval.MetaInterval import Sequence
from direct.interval.MetaInterval import Parallel
from direct.interval.FunctionInterval import Func
from direct.showutil.Rope import Rope
from direct.showbase.PythonUtil import fitDestAngle2Src
from direct.fsm.StatePush import StateVar, FunctionCall
from toontown.toonbase import TTLocalizer
from toontown.toonbase import ToontownGlobals
from toontown.effects import Splash
from toontown.minigame.MinigamePowerMeter import MinigamePowerMeter
from toontown.minigame.ArrowKeys import ArrowKeys
from . import PartyGlobals
from . import PartyUtils
from .DistributedPartyTeamActivity import DistributedPartyTeamActivity
class DistributedPartyTugOfWarActivity(DistributedPartyTeamActivity):
notify = directNotify.newCategory('DistributedPartyTugOfWarActivity')
def __init__(self, cr):
DistributedPartyTeamActivity.__init__(self, cr, PartyGlobals.ActivityIds.PartyTugOfWar, startDelay=PartyGlobals.TugOfWarStartDelay)
self.buttons = [0, 1]
self.arrowKeys = None
self.keyTTL = []
self.idealRate = 0.0
self.keyRate = 0
self.allOutMode = False
self.rateMatchAward = 0.0
self.toonIdsToStartPositions = {}
self.toonIdsToIsPullingFlags = {}
self.toonIdsToRightHands = {}
self.fallenToons = []
self.fallenPositions = []
self.unusedFallenPositionsIndices = [0,
1,
2,
3]
self.toonIdsToAnimIntervals = {}
self.tugRopes = []
return
def generate(self):
DistributedPartyTeamActivity.generate(self)
self._hopOffFinishedSV = StateVar(True)
self._rewardFinishedSV = StateVar(True)
self._isWalkStateReadyFC = FunctionCall(self._testWalkStateReady, self._hopOffFinishedSV, self._rewardFinishedSV)
def delete(self):
self._isWalkStateReadyFC.destroy()
self._hopOffFinishedSV.destroy()
self._rewardFinishedSV.destroy()
DistributedPartyTeamActivity.delete(self)
def handleToonJoined(self, toonId):
DistributedPartyTeamActivity.handleToonJoined(self, toonId)
self.toonIdsToAnimIntervals[toonId] = None
if toonId == base.localAvatar.doId:
base.cr.playGame.getPlace().fsm.request('activity')
camera.wrtReparentTo(self.root)
self.cameraMoveIval = LerpPosHprInterval(camera, 1.5, PartyGlobals.TugOfWarCameraPos, PartyGlobals.TugOfWarCameraInitialHpr, other=self.root)
self.cameraMoveIval.start()
self.localToonPosIndex = self.getIndex(base.localAvatar.doId, self.localToonTeam)
self.notify.debug('posIndex: %d' % self.localToonPosIndex)
toon = self.getAvatar(toonId)
targetPos = self.dockPositions[self.localToonTeam][self.localToonPosIndex]
if toon.getZ(self.root) < PartyGlobals.TugOfWarToonPositionZ:
toon.setZ(self.root, PartyGlobals.TugOfWarToonPositionZ)
targetH = fitDestAngle2Src(toon.getH(self.root), PartyGlobals.TugOfWarHeadings[self.localToonTeam])
travelVector = targetPos - toon.getPos(self.root)
duration = travelVector.length() / 5.0
if self.toonIdsToAnimIntervals[toonId] is not None:
self.toonIdsToAnimIntervals[toonId].finish()
self.toonIdsToAnimIntervals[toonId] = Sequence(Func(toon.startPosHprBroadcast, 0.1), Func(toon.b_setAnimState, 'run'), LerpPosHprInterval(toon, duration, targetPos, VBase3(targetH, 0.0, 0.0), other=self.root), Func(toon.stopPosHprBroadcast), Func(toon.b_setAnimState, 'neutral'))
self.toonIdsToAnimIntervals[toonId].start()
return
def handleToonExited(self, toonId):
DistributedPartyTeamActivity.handleToonExited(self, toonId)
if toonId == base.localAvatar.doId:
self.cameraMoveIval.pause()
if toonId not in self.fallenToons:
if toonId in self.toonIdsToAnimIntervals and self.toonIdsToAnimIntervals[toonId] is not None:
self.toonIdsToAnimIntervals[toonId].finish()
toon = self.getAvatar(toonId)
targetH = fitDestAngle2Src(toon.getH(self.root), 180.0)
targetPos = self.hopOffPositions[self.getTeam(toonId)][self.getIndex(toonId, self.getTeam(toonId))]
hopOffAnim = Sequence(Func(toon.startPosHprBroadcast, 0.1), toon.hprInterval(0.2, VBase3(targetH, 0.0, 0.0), other=self.root), Func(toon.b_setAnimState, 'jump', 1.0), Wait(0.4), PartyUtils.arcPosInterval(0.75, toon, targetPos, 5.0, self.root), Func(toon.stopPosHprBroadcast), Func(toon.sendCurrentPosition), Func(self.hopOffFinished, toonId))
self.toonIdsToAnimIntervals[toonId] = hopOffAnim
self._hopOffFinishedSV.set(False)
self.toonIdsToAnimIntervals[toonId].start()
else:
self._hopOffFinishedSV.set(True)
del self.toonIdsToAnimIntervals[toonId]
return
def handleRewardDone(self):
self._rewardFinishedSV.set(True)
def _testWalkStateReady(self, hoppedOff, rewardFinished):
if hoppedOff and rewardFinished:
DistributedPartyTeamActivity.handleRewardDone(self)
def hopOffFinished(self, toonId):
if hasattr(self, 'toonIdsToAnimIntervals') and toonId in self.toonIdsToAnimIntervals:
del self.toonIdsToAnimIntervals[toonId]
if toonId == base.localAvatar.doId:
if hasattr(self._hopOffFinishedSV, '_value'):
self._hopOffFinishedSV.set(True)
def handleToonShifted(self, toonId):
if toonId == base.localAvatar.doId:
self.localToonPosIndex = self.getIndex(base.localAvatar.doId, self.localToonTeam)
if self.toonIdsToAnimIntervals[toonId] is not None:
self.toonIdsToAnimIntervals[toonId].finish()
toon = self.getAvatar(toonId)
targetPos = self.dockPositions[self.localToonTeam][self.localToonPosIndex]
self.toonIdsToAnimIntervals[toonId] = Sequence(Wait(0.6), Func(toon.startPosHprBroadcast, 0.1), Func(toon.b_setAnimState, 'run'), toon.posInterval(0.5, targetPos, other=self.root), Func(toon.stopPosHprBroadcast), Func(toon.b_setAnimState, 'neutral'))
self.toonIdsToAnimIntervals[toonId].start()
return
def handleToonDisabled(self, toonId):
if toonId in self.toonIdsToAnimIntervals:
if self.toonIdsToAnimIntervals[toonId]:
if self.toonIdsToAnimIntervals[toonId].isPlaying():
self.toonIdsToAnimIntervals[toonId].finish()
else:
self.notify.debug('self.toonIdsToAnimIntervals[%d] is none' % toonId)
def setToonsPlaying(self, leftTeamToonIds, rightTeamToonIds):
DistributedPartyTeamActivity.setToonsPlaying(self, leftTeamToonIds, rightTeamToonIds)
self.toonIdsToRightHands.clear()
for toonId in self.getToonIdsAsList():
toon = self.getAvatar(toonId)
if toon:
self.toonIdsToRightHands[toonId] = toon.getRightHands()[0]
def load(self):
DistributedPartyTeamActivity.load(self)
self.loadModels()
self.loadGuiElements()
self.loadSounds()
self.loadIntervals()
self.arrowKeys = ArrowKeys()
def loadModels(self):
self.playArea = loader.loadModel('phase_13/models/parties/partyTugOfWar')
self.playArea.reparentTo(self.root)
self.sign.reparentTo(self.playArea.find('**/TugOfWar_sign_locator'))
self.dockPositions = [[], []]
for i in range(4):
self.dockPositions[0].append(Point3(-PartyGlobals.TugOfWarInitialToonPositionsXOffset - PartyGlobals.TugOfWarToonPositionXSeparation * i, 0.0, PartyGlobals.TugOfWarToonPositionZ))
for i in range(4):
self.dockPositions[1].append(Point3(PartyGlobals.TugOfWarInitialToonPositionsXOffset + PartyGlobals.TugOfWarToonPositionXSeparation * i, 0.0, PartyGlobals.TugOfWarToonPositionZ))
self.hopOffPositions = [[], []]
for i in range(1, 5):
self.hopOffPositions[PartyGlobals.TeamActivityTeams.LeftTeam].append(self.playArea.find('**/leftTeamHopOff%d_locator' % i).getPos())
self.hopOffPositions[PartyGlobals.TeamActivityTeams.RightTeam].append(self.playArea.find('**/rightTeamHopOff%d_locator' % i).getPos())
for i in range(1, 5):
pos = self.playArea.find('**/fallenToon%d_locator' % i).getPos()
self.fallenPositions.append(pos)
self.joinCollision = []
self.joinCollisionNodePaths = []
for i in range(len(PartyGlobals.TeamActivityTeams)):
collShape = CollisionTube(PartyGlobals.TugOfWarJoinCollisionEndPoints[0], PartyGlobals.TugOfWarJoinCollisionEndPoints[1], PartyGlobals.TugOfWarJoinCollisionRadius)
collShape.setTangible(True)
self.joinCollision.append(CollisionNode('TugOfWarJoinCollision%d' % i))
self.joinCollision[i].addSolid(collShape)
tubeNp = self.playArea.attachNewNode(self.joinCollision[i])
tubeNp.node().setCollideMask(ToontownGlobals.WallBitmask)
self.joinCollisionNodePaths.append(tubeNp)
self.joinCollisionNodePaths[i].setPos(PartyGlobals.TugOfWarJoinCollisionPositions[i])
self.__enableCollisions()
ropeModel = loader.loadModel('phase_4/models/minigames/tug_of_war_rope')
self.ropeTexture = ropeModel.findTexture('*')
ropeModel.removeNode()
for i in range(PartyGlobals.TugOfWarMaximumPlayersPerTeam * 2 - 1):
rope = Rope(self.uniqueName('TugRope%d' % i))
if rope.showRope:
rope.ropeNode.setRenderMode(RopeNode.RMBillboard)
rope.ropeNode.setThickness(0.2)
rope.setTexture(self.ropeTexture)
rope.ropeNode.setUvMode(RopeNode.UVDistance)
rope.ropeNode.setUvDirection(1)
rope.setTransparency(1)
rope.setColor(0.89, 0.89, 0.6, 1.0)
rope.reparentTo(self.root)
rope.stash()
self.tugRopes.append(rope)
self.splash = Splash.Splash(self.root)
self.splash.setScale(2.0, 4.0, 1.0)
pos = self.fallenPositions[0]
self.splash.setPos(pos[0], pos[1], PartyGlobals.TugOfWarSplashZOffset)
self.splash.hide()
def loadGuiElements(self):
self.powerMeter = MinigamePowerMeter(PartyGlobals.TugOfWarPowerMeterSize)
self.powerMeter.reparentTo(aspect2d)
self.powerMeter.setPos(0.0, 0.0, 0.6)
self.powerMeter.hide()
self.arrows = [None] * 2
for x in range(len(self.arrows)):
self.arrows[x] = loader.loadModel('phase_3/models/props/arrow')
self.arrows[x].reparentTo(self.powerMeter)
self.arrows[x].setScale(0.2 - 0.4 * x, 0.2, 0.2)
self.arrows[x].setPos(0.12 - 0.24 * x, 0, -.26)
return
def loadSounds(self):
self.splashSound = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_splash.mp3')
self.whistleSound = base.loader.loadSfx('phase_4/audio/sfx/AA_sound_whistle.mp3')
def loadIntervals(self):
self.updateIdealRateInterval = Sequence()
self.updateIdealRateInterval.append(Wait(PartyGlobals.TugOfWarTargetRateList[0][0]))
for i in range(1, len(PartyGlobals.TugOfWarTargetRateList)):
duration = PartyGlobals.TugOfWarTargetRateList[i][0]
idealRate = PartyGlobals.TugOfWarTargetRateList[i][1]
self.updateIdealRateInterval.append(Func(self.setIdealRate, idealRate))
if i == len(PartyGlobals.TugOfWarTargetRateList) - 1:
self.updateIdealRateInterval.append(Func(setattr, self, 'allOutMode', True))
else:
self.updateIdealRateInterval.append(Wait(duration))
self.updateKeyPressRateInterval = Sequence(Wait(PartyGlobals.TugOfWarKeyPressUpdateRate), Func(self.updateKeyPressRate))
self.reportToServerInterval = Sequence(Wait(PartyGlobals.TugOfWarKeyPressReportRate), Func(self.reportToServer))
self.setupInterval = Parallel()
self.globalSetupInterval = Sequence(Wait(PartyGlobals.TugOfWarReadyDuration + PartyGlobals.TugOfWarGoDuration), Func(self.tightenRopes))
self.localSetupInterval = Sequence(Func(self.setStatus, TTLocalizer.PartyTugOfWarReady), Func(self.showStatus), Wait(PartyGlobals.TugOfWarReadyDuration), Func(base.playSfx, self.whistleSound), Func(self.setStatus, TTLocalizer.PartyTugOfWarGo), Wait(PartyGlobals.TugOfWarGoDuration), Func(self.enableKeys), Func(self.hideStatus), Func(self.updateIdealRateInterval.start), Func(self.updateKeyPressRateInterval.loop), Func(self.reportToServerInterval.loop))
self.splashInterval = Sequence(Func(base.playSfx, self.splashSound), Func(self.splash.play))
def unload(self):
DistributedPartyTeamActivity.unload(self)
self.arrowKeys.destroy()
self.unloadIntervals()
self.unloadModels()
self.unloadGuiElements()
self.unloadSounds()
if hasattr(self, 'toonIds'):
del self.toonIds
del self.buttons
del self.arrowKeys
del self.keyTTL
del self.idealRate
del self.keyRate
del self.allOutMode
del self.rateMatchAward
del self.toonIdsToStartPositions
del self.toonIdsToIsPullingFlags
del self.toonIdsToRightHands
del self.fallenToons
del self.fallenPositions
del self.unusedFallenPositionsIndices
self.toonIdsToAnimIntervals.clear()
del self.toonIdsToAnimIntervals
def unloadModels(self):
self.playArea.removeNode()
del self.playArea
del self.dockPositions
del self.hopOffPositions
self.__disableCollisions()
while len(self.joinCollision) > 0:
collNode = self.joinCollision.pop()
del collNode
while len(self.joinCollisionNodePaths) > 0:
collNodePath = self.joinCollisionNodePaths.pop()
collNodePath.removeNode()
del collNodePath
while len(self.tugRopes) > 0:
rope = self.tugRopes.pop()
if rope is not None:
rope.removeNode()
del rope
del self.tugRopes
self.splash.destroy()
del self.splash
return
def unloadGuiElements(self):
for arrow in self.arrows:
if arrow is not None:
arrow.removeNode()
del arrow
del self.arrows
if self.powerMeter is not None:
self.powerMeter.cleanup()
del self.powerMeter
return
def unloadSounds(self):
del self.splashSound
del self.whistleSound
def unloadIntervals(self):
self.updateIdealRateInterval.pause()
del self.updateIdealRateInterval
self.updateKeyPressRateInterval.pause()
del self.updateKeyPressRateInterval
self.reportToServerInterval.pause()
del self.reportToServerInterval
self.setupInterval.pause()
del self.setupInterval
self.globalSetupInterval.pause()
del self.globalSetupInterval
self.localSetupInterval.pause()
del self.localSetupInterval
self.splashInterval.pause()
del self.splashInterval
def __enableCollisions(self):
for i in range(len(PartyGlobals.TeamActivityTeams)):
self.accept('enterTugOfWarJoinCollision%d' % i, getattr(self, '_join%s' % PartyGlobals.TeamActivityTeams.getString(i)))
def __disableCollisions(self):
for i in range(len(PartyGlobals.TeamActivityTeams)):
self.ignore('enterTugOfWarJoinCollision%d' % i)
def startWaitForEnough(self):
DistributedPartyTeamActivity.startWaitForEnough(self)
self.__enableCollisions()
def finishWaitForEnough(self):
DistributedPartyTeamActivity.finishWaitForEnough(self)
self.__disableCollisions()
def startWaitToStart(self, waitStartTimestamp):
DistributedPartyTeamActivity.startWaitToStart(self, waitStartTimestamp)
self.__enableCollisions()
def finishWaitToStart(self):
DistributedPartyTeamActivity.finishWaitToStart(self)
self.__disableCollisions()
def startRules(self):
DistributedPartyTeamActivity.startRules(self)
self.setUpRopes()
if self.isLocalToonPlaying:
self.showControls()
def finishRules(self):
DistributedPartyTeamActivity.finishRules(self)
if self.activityFSM.getCurrentOrNextState() == 'WaitForEnough':
self.hideRopes()
self.hideControls()
def finishWaitForServer(self):
DistributedPartyTeamActivity.finishWaitForServer(self)
if self.activityFSM.getCurrentOrNextState() == 'WaitForEnough':
self.hideRopes()
self.hideControls()
def startActive(self):
DistributedPartyTeamActivity.startActive(self)
self.toonIdsToStartPositions.clear()
self.toonIdsToIsPullingFlags.clear()
for toonId in self.getToonIdsAsList():
self.toonIdsToIsPullingFlags[toonId] = False
toon = self.getAvatar(toonId)
if toon:
self.toonIdsToStartPositions[toonId] = toon.getPos(self.root)
else:
self.notify.warning("couldn't find toon %d assigning 0,0,0 to startPos" % toonId)
self.toonIdsToStartPositions[toonId] = Point3(0, 0, 0)
self.unusedFallenPositionsIndices = [0,
1,
2,
3]
self.setupInterval = Parallel(self.globalSetupInterval)
if self.isLocalToonPlaying:
self.keyTTL = []
self.idealForce = 0.0
self.keyRate = 0
self.rateMatchAward = 0.0
self.allOutMode = False
self.setIdealRate(PartyGlobals.TugOfWarTargetRateList[0][1])
self.setupInterval.append(self.localSetupInterval)
self.setupInterval.start()
def finishActive(self):
DistributedPartyTeamActivity.finishActive(self)
self.hideControls()
self.disableKeys()
self.setupInterval.pause()
self.reportToServerInterval.pause()
self.updateKeyPressRateInterval.pause()
self.updateIdealRateInterval.pause()
self.hideRopes()
def startConclusion(self, losingTeam):
DistributedPartyTeamActivity.startConclusion(self, losingTeam)
if self.isLocalToonPlaying:
self._rewardFinishedSV.set(False)
if losingTeam == PartyGlobals.TeamActivityNeitherTeam:
self.setStatus(TTLocalizer.PartyTeamActivityGameTie)
else:
self.setStatus(TTLocalizer.PartyTugOfWarGameEnd)
self.showStatus()
if losingTeam == PartyGlobals.TeamActivityNeitherTeam:
for toonId in self.getToonIdsAsList():
if self.getAvatar(toonId):
self.getAvatar(toonId).loop('neutral')
else:
for toonId in self.toonIds[losingTeam]:
if self.getAvatar(toonId):
self.getAvatar(toonId).loop('neutral')
for toonId in self.toonIds[1 - losingTeam]:
if self.getAvatar(toonId):
self.getAvatar(toonId).loop('victory')
for ival in list(self.toonIdsToAnimIntervals.values()):
if ival is not None:
ival.finish()
return
def finishConclusion(self):
DistributedPartyTeamActivity.finishConclusion(self)
self.fallenToons = []
def getTitle(self):
return TTLocalizer.PartyTugOfWarTitle
def getInstructions(self):
return TTLocalizer.TugOfWarInstructions
def showControls(self):
for arrow in self.arrows:
arrow.setColor(PartyGlobals.TugOfWarDisabledArrowColor)
self.powerMeter.setTarget(PartyGlobals.TugOfWarTargetRateList[0][1])
self.powerMeter.setPower(PartyGlobals.TugOfWarTargetRateList[0][1])
self.powerMeter.setBarColor((0.0, 1.0, 0.0, 0.5))
self.powerMeter.clearTooSlowTooFast()
self.powerMeter.show()
def hideControls(self):
self.powerMeter.hide()
def setUpRopes(self):
self.notify.debug('setUpRopes')
ropeIndex = 0
leftToonId = -1
if self.toonIds[PartyGlobals.TeamActivityTeams.LeftTeam]:
leftToonId = self.toonIds[PartyGlobals.TeamActivityTeams.LeftTeam][0]
rightToonId = -1
if self.toonIds[PartyGlobals.TeamActivityTeams.RightTeam]:
rightToonId = self.toonIds[PartyGlobals.TeamActivityTeams.RightTeam][0]
if leftToonId in self.toonIdsToRightHands and rightToonId in self.toonIdsToRightHands:
self.tugRopes[ropeIndex].setup(3, ((self.toonIdsToRightHands[leftToonId], (0, 0, 0)), (self.root, (0.0, 0.0, 2.5)), (self.toonIdsToRightHands[rightToonId], (0, 0, 0))), [0,
0,
0,
1,
1,
1])
self.tugRopes[ropeIndex].unstash()
ropeIndex += 1
teams = [PartyGlobals.TeamActivityTeams.LeftTeam, PartyGlobals.TeamActivityTeams.RightTeam]
for currTeam in teams:
numToons = len(self.toonIds[currTeam])
if numToons > 1:
for i in range(numToons - 1, 0, -1):
toon1 = self.toonIds[currTeam][i]
toon2 = self.toonIds[currTeam][i - 1]
if toon1 not in self.toonIdsToRightHands:
self.notify.warning('Toon in tug of war activity but not properly setup: %s' % toon1)
elif toon2 not in self.toonIdsToRightHands:
self.notify.warning('Toon in tug of war activity but not properly setup: %s' % toon2)
else:
self.notify.debug('Connecting rope between toon %d and toon %d of team %d.' % (i, i - 1, currTeam))
self.tugRopes[ropeIndex].setup(3, ((self.toonIdsToRightHands[toon1], (0, 0, 0)), (self.toonIdsToRightHands[toon1], (0, 0, 0)), (self.toonIdsToRightHands[toon2], (0, 0, 0))), [0,
0,
0,
1,
1,
1])
self.tugRopes[ropeIndex].unstash()
ropeIndex += 1
def tightenRopes(self):
self.notify.debug('tightenRopes')
self.tugRopes[0].setup(3, ((self.toonIdsToRightHands[self.toonIds[PartyGlobals.TeamActivityTeams.LeftTeam][0]], (0, 0, 0)), (self.toonIdsToRightHands[self.toonIds[PartyGlobals.TeamActivityTeams.LeftTeam][0]], (0, 0, 0)), (self.toonIdsToRightHands[self.toonIds[PartyGlobals.TeamActivityTeams.RightTeam][0]], (0, 0, 0))), [0,
0,
0,
1,
1,
1])
def hideRopes(self):
self.notify.debug('hideRopes')
for rope in self.tugRopes:
rope.stash()
def handleGameTimerExpired(self):
self.disableKeys()
def setIdealRate(self, idealRate):
self.notify.debug('setIdealRate( %d )' % idealRate)
self.idealRate = idealRate
self.idealForce = self.advantage * (4 + 0.4 * self.idealRate)
def updateKeyPressRate(self):
for i in range(len(self.keyTTL)):
self.keyTTL[i] -= PartyGlobals.TugOfWarKeyPressUpdateRate
for i in range(len(self.keyTTL)):
if self.keyTTL[i] <= 0.0:
a = self.keyTTL[0:i]
del self.keyTTL
self.keyTTL = a
break
self.keyRate = len(self.keyTTL)
if self.keyRate == self.idealRate or self.keyRate == self.idealRate + 1:
self.rateMatchAward += 0.3
else:
self.rateMatchAward = 0.0
def reportToServer(self):
self.currentForce = self.computeForce(self.keyRate)
self.sendUpdate('reportKeyRateForce', [self.keyRate, self.currentForce])
self.setSpeedGauge()
self.setAnimState(base.localAvatar.doId, self.keyRate)
def computeForce(self, keyRate):
F = 0
if self.allOutMode:
F = 0.75 * keyRate
else:
stdDev = 0.25 * self.idealRate
F = self.advantage * (self.rateMatchAward + 4 + 0.4 * self.idealRate) * math.pow(math.e, -math.pow(keyRate - self.idealRate, 2) / (2.0 * math.pow(stdDev, 2)))
return F
def setSpeedGauge(self):
self.powerMeter.setPower(self.keyRate)
self.powerMeter.setTarget(self.idealRate)
if not self.allOutMode:
self.powerMeter.updateTooSlowTooFast()
index = float(self.currentForce) / self.idealForce
bonus = 0.0
if index > 1.0:
bonus = max(1.0, index - 1.0)
index = 1.0
color = (0,
0.75 * index + 0.25 * bonus,
0.75 * (1 - index),
0.5)
self.powerMeter.setBarColor(color)
else:
self.powerMeter.setBarColor((0.0, 1.0, 0.0, 0.5))
def updateToonKeyRate(self, toonId, keyRate):
if toonId != base.localAvatar.doId:
self.setAnimState(toonId, keyRate)
def setAnimState(self, toonId, keyRate):
if self.activityFSM.state != 'Active':
return
toon = self.getAvatar(toonId)
if toonId not in self.toonIdsToIsPullingFlags:
if self.getTeam(toonId) == None:
self.notify.warning("setAnimState called with toonId (%d) that wasn't in self.toonIds" % toonId)
return
else:
self.notify.warning('setAnimState called with toonId (%d) that was in self.toonIds but not in self.toonIdsToIsPullingFlags. Adding it.' % toonId)
self.toonIdsToIsPullingFlags[toonId] = False
if keyRate > 0 and not self.toonIdsToIsPullingFlags[toonId]:
if toon:
toon.loop('tug-o-war')
else:
self.notify.warning('toon %d is None, skipping toon.loop(tugowar)' % toonId)
self.toonIdsToIsPullingFlags[toonId] = True
if keyRate <= 0 and self.toonIdsToIsPullingFlags[toonId]:
if toon:
toon.pose('tug-o-war', 3)
toon.startLookAround()
else:
self.notify.warning('toon %d is None, skipping toon.startLookAround' % toonId)
self.toonIdsToIsPullingFlags[toonId] = False
return
def enableKeys(self):
self.notify.debug('enableKeys')
self.arrowKeys.setPressHandlers([lambda : self.__pressHandler(2),
lambda : self.__pressHandler(3),
lambda : self.__pressHandler(1),
lambda : self.__pressHandler(0)])
self.arrowKeys.setReleaseHandlers([lambda : self.__releaseHandler(2),
lambda : self.__releaseHandler(3),
lambda : self.__releaseHandler(1),
lambda : self.__releaseHandler(0)])
for arrow in self.arrows:
arrow.setColor(PartyGlobals.TugOfWarEnabledArrowColor)
def disableKeys(self):
self.arrowKeys.setPressHandlers(self.arrowKeys.NULL_HANDLERS)
self.arrowKeys.setReleaseHandlers(self.arrowKeys.NULL_HANDLERS)
def __pressHandler(self, index):
if index == self.buttons[0]:
self.arrows[index].setColor(PartyGlobals.TugOfWarHilightedArrowColor)
self.keyTTL.insert(0, PartyGlobals.TugOfWarKeyPressTimeToLive)
self.buttons.reverse()
def __releaseHandler(self, index):
if index in self.buttons:
self.arrows[index].setColor(PartyGlobals.TugOfWarEnabledArrowColor)
def updateToonPositions(self, offset):
if self.activityFSM.state != 'Active':
return
if self.isLocalToonPlaying:
camera.lookAt(self.root, offset, 0.0, PartyGlobals.TugOfWarCameraLookAtHeightOffset)
for toonId in self.getToonIdsAsList():
if hasattr(self, 'fallenToons') and toonId not in self.fallenToons:
toon = self.getAvatar(toonId)
if toon is not None:
origPos = self.toonIdsToStartPositions[toonId]
curPos = toon.getPos(self.root)
newPos = Point3(origPos[0] + offset, curPos[1], curPos[2])
if self.toonIdsToAnimIntervals[toonId] != None:
if self.toonIdsToAnimIntervals[toonId].isPlaying():
self.toonIdsToAnimIntervals[toonId].finish()
self.checkIfFallen(toonId)
if toonId not in self.fallenToons:
self.toonIdsToAnimIntervals[toonId] = Sequence(LerpPosInterval(toon, duration=PartyGlobals.TugOfWarKeyPressReportRate, pos=newPos, other=self.root), Func(self.checkIfFallen, toonId))
self.toonIdsToAnimIntervals[toonId].start()
return
def checkIfFallen(self, toonId):
if hasattr(self, 'fallenToons') and toonId not in self.fallenToons:
toon = self.getAvatar(toonId)
if toon:
curPos = toon.getPos(self.root)
team = self.getTeam(toonId)
if team == PartyGlobals.TeamActivityTeams.LeftTeam and curPos[0] > -2.0 or team == PartyGlobals.TeamActivityTeams.RightTeam and curPos[0] < 2.0:
losingTeam = self.getTeam(toonId)
self.throwTeamInWater(losingTeam)
self.sendUpdate('reportFallIn', [losingTeam])
def throwTeamInWater(self, losingTeam):
self.notify.debug('throwTeamInWater( %s )' % PartyGlobals.TeamActivityTeams.getString(losingTeam))
splashSet = False
for toonId in self.toonIds[losingTeam]:
self.fallenToons.append(toonId)
toon = self.getAvatar(toonId)
fallenPosIndex = self.toonIds[losingTeam].index(toonId)
if fallenPosIndex < 0 or fallenPosIndex >= 4:
fallenPosIndex = 0
newPos = self.fallenPositions[fallenPosIndex]
if toonId in self.toonIdsToAnimIntervals and self.toonIdsToAnimIntervals[toonId] is not None:
if self.toonIdsToAnimIntervals[toonId].isPlaying():
self.toonIdsToAnimIntervals[toonId].finish()
if toon:
parallel = Parallel(ActorInterval(actor=toon, animName='slip-forward', duration=2.0), LerpPosInterval(toon, duration=2.0, pos=newPos, other=self.root))
else:
self.notify.warning('toon %d is none, skipping slip-forward' % toonId)
parallel = Parallel()
if not splashSet:
splashSet = True
parallel.append(self.splashInterval)
if toon:
self.toonIdsToAnimIntervals[toonId] = Sequence(parallel, Func(toon.loop, 'neutral'))
else:
self.notify.warning('toon %d is none, skipping toon.loop(neutral)' % toonId)
self.toonIdsToAnimIntervals[toonId] = parallel
self.toonIdsToAnimIntervals[toonId].start()
return
def setAdvantage(self, advantage):
DistributedPartyTeamActivity.setAdvantage(self, advantage)
if self.isLocalToonPlaying:
self.setIdealRate(PartyGlobals.TugOfWarTargetRateList[0][1])