oldschool-toontown/toontown/minigame/TwoDDrive.py
2023-04-24 00:12:43 -04:00

171 lines
6.2 KiB
Python

from panda3d.core import Point3, Vec3
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.interval.IntervalGlobal import LerpHprInterval
from direct.showbase.MessengerGlobal import messenger
from direct.showbase.PythonUtil import fitSrcAngle2Dest
from direct.task.TaskManagerGlobal import taskMgr
from otp.otpbase import OTPGlobals
from toontown.minigame.ArrowKeys import ArrowKeys
from toontown.toonbase.ToonBaseGlobal import base
class TwoDDrive:
notify = directNotify.newCategory('TwoDDrive')
TASK_NAME = 'TwoDDriveTask'
SET_ATREST_HEADING_TASK = 'setAtRestHeadingTask'
def __init__(self, game, speed, maxFrameMove = None, customCollisionCallback = None, priority = 0, setHeading = 1, upHeading = 0):
self.game = game
self.speed = speed
self.maxFrameMove = maxFrameMove
self.customCollisionCallback = customCollisionCallback
self.priority = priority
self.setHeading = setHeading
self.upHeading = upHeading
self.arrowKeys = ArrowKeys()
self.wasUpReleased = True
self.lt = base.localAvatar
base.localAvatar.useTwoDControls()
base.localAvatar.controlManager.currentControls.avatarControlJumpForce = 30.0
self.ONE_JUMP_PER_UP_PRESSED = True
self.lastAction = None
self.isMovingX = False
def destroy(self):
self.game = None
base.localAvatar.controlManager.currentControls.avatarControlJumpForce = 24.0
base.localAvatar.useWalkControls()
self.arrowKeys.destroy()
del self.arrowKeys
del self.customCollisionCallback
self.lastAction = None
def start(self):
self.notify.debug('start')
self.__placeToonHOG(self.lt.getPos())
base.localAvatar.enableAvatarControls()
taskMgr.remove(TwoDDrive.TASK_NAME)
taskMgr.add(self.__update, TwoDDrive.TASK_NAME, priority=self.priority)
def __placeToonHOG(self, pos, h = None):
if h == None:
h = self.lt.getH()
self.lt.setPos(pos)
self.lt.setH(h)
self.lastPos = pos
self.atRestHeading = h
self.oldAtRestHeading = h
self.lastXVel = 0
self.lastYVel = 0
def stop(self):
self.notify.debug('stop')
base.localAvatar.disableAvatarControls()
taskMgr.remove(TwoDDrive.TASK_NAME)
taskMgr.remove(TwoDDrive.SET_ATREST_HEADING_TASK)
if hasattr(self, 'turnLocalToonIval'):
if self.turnLocalToonIval.isPlaying():
self.turnLocalToonIval.pause()
del self.turnLocalToonIval
base.localAvatar.setSpeed(0, 0)
base.localAvatar.stopSound()
def __update(self, task):
vel = Vec3(0, 0, 0)
xVel = 0
yVel = 0
if self.ONE_JUMP_PER_UP_PRESSED:
if not self.arrowKeys.upPressed():
self.wasUpReleased = True
elif self.arrowKeys.upPressed() and self.wasUpReleased:
self.wasUpReleased = False
if not self.game.isHeadInFloor:
if base.localAvatar.controlManager.currentControls == base.localAvatar.controlManager.get('twoD'):
base.localAvatar.controlManager.currentControls.jumpPressed()
elif self.arrowKeys.upPressed():
if not self.game.isHeadInFloor:
if base.localAvatar.controlManager.currentControls == base.localAvatar.controlManager.get('twoD'):
base.localAvatar.controlManager.currentControls.jumpPressed()
if self.arrowKeys.leftPressed():
xVel -= 1
if self.arrowKeys.rightPressed():
xVel += 1
vel.setX(xVel)
vel.setY(yVel)
vel.normalize()
vel *= self.speed
if abs(xVel) > 0:
if not self.isMovingX:
self.isMovingX = True
messenger.send('avatarMovingX')
elif self.isMovingX:
self.isMovingX = False
messenger.send('avatarStoppedX')
speed = vel.length()
action = self.lt.setSpeed(speed, 0)
if action != self.lastAction:
self.lastAction = action
if action == OTPGlobals.RUN_INDEX:
base.localAvatar.runSound()
else:
base.localAvatar.stopSound()
if self.setHeading:
self.__handleHeading(xVel, yVel)
toonPos = self.lt.getPos()
dt = base.clock.getDt()
posOffset = vel * dt
if self.customCollisionCallback:
toonPos = self.customCollisionCallback(toonPos, toonPos + posOffset)
else:
toonPos += posOffset
self.lt.setPos(toonPos)
self.lastPos = toonPos
return task.cont
def __handleHeading(self, xVel, yVel):
def getHeading(xVel, yVel):
angTab = [[None, 0, 180], [-90, -45, -135], [90, 45, 135]]
return angTab[xVel][yVel] + self.upHeading
def orientToon(angle, self = self):
startAngle = self.lt.getH()
startAngle = fitSrcAngle2Dest(startAngle, angle)
dur = 0.1 * abs(startAngle - angle) / 90
self.turnLocalToonIval = LerpHprInterval(self.lt, dur, Point3(angle, 0, 0), startHpr=Point3(startAngle, 0, 0), name='TwoDDriveLerpHpr')
self.turnLocalToonIval.start()
if self.atRestHeading != self.oldAtRestHeading:
self.oldAtRestHeading = self.atRestHeading
messenger.send('avatarOrientationChanged', [self.atRestHeading])
if xVel != self.lastXVel or yVel != self.lastYVel:
taskMgr.remove(TwoDDrive.SET_ATREST_HEADING_TASK)
if not (xVel or yVel):
orientToon(self.atRestHeading)
else:
curHeading = getHeading(xVel, yVel)
if ((self.lastXVel and self.lastYVel) and not (xVel and yVel)):
def setAtRestHeading(task, self = self, angle = curHeading):
self.atRestHeading = angle
return task.done
taskMgr.doMethodLater(0.05, setAtRestHeading, TwoDDrive.SET_ATREST_HEADING_TASK)
else:
self.atRestHeading = curHeading
orientToon(curHeading)
self.lastXVel = xVel
self.lastYVel = yVel