oldschool-toontown/toontown/suit/DistributedFactorySuit.py

415 lines
15 KiB
Python
Raw Normal View History

from panda3d.core import *
2019-11-02 17:27:54 -05:00
from direct.interval.IntervalGlobal import *
from direct.fsm import ClassicFSM, State
from direct.fsm import State
from direct.directnotify import DirectNotifyGlobal
from . import DistributedSuitBase
2019-11-02 17:27:54 -05:00
from direct.task.Task import Task
import random
from toontown.toonbase import ToontownGlobals
from otp.level import LevelConstants
from toontown.distributed.DelayDeletable import DelayDeletable
class DistributedFactorySuit(DistributedSuitBase.DistributedSuitBase, DelayDeletable):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedFactorySuit')
def __init__(self, cr):
try:
self.DistributedSuit_initialized
except:
self.DistributedSuit_initialized = 1
DistributedSuitBase.DistributedSuitBase.__init__(self, cr)
self.fsm = ClassicFSM.ClassicFSM('DistributedSuit', [State.State('Off', self.enterOff, self.exitOff, ['Walk', 'Battle']),
State.State('Walk', self.enterWalk, self.exitWalk, ['WaitForBattle', 'Battle', 'Chase']),
State.State('Chase', self.enterChase, self.exitChase, ['WaitForBattle', 'Battle', 'Return']),
State.State('Return', self.enterReturn, self.exitReturn, ['WaitForBattle', 'Battle', 'Walk']),
State.State('Battle', self.enterBattle, self.exitBattle, ['Walk', 'Chase', 'Return']),
State.State('WaitForBattle', self.enterWaitForBattle, self.exitWaitForBattle, ['Battle'])], 'Off', 'Off')
self.path = None
self.walkTrack = None
self.chaseTrack = None
self.returnTrack = None
self.fsm.enterInitialState()
self.chasing = 0
self.paused = 0
self.pauseTime = 0
self.velocity = 3
self.factoryRequest = None
return
def generate(self):
DistributedSuitBase.DistributedSuitBase.generate(self)
def setLevelDoId(self, levelDoId):
self.notify.debug('setLevelDoId(%s)' % levelDoId)
self.levelDoId = levelDoId
def setCogId(self, cogId):
self.cogId = cogId
def setReserve(self, reserve):
self.reserve = reserve
def denyBattle(self):
self.notify.warning('denyBattle()')
place = self.cr.playGame.getPlace()
if place.fsm.getCurrentState().getName() == 'WaitForBattle':
place.setState('walk')
def doReparent(self):
self.notify.debug('Suit requesting reparenting')
if not hasattr(self, 'factory'):
self.notify.warning('no factory, get Redmond to look at DistributedFactorySuit.announceGenerate()')
self.factory.requestReparent(self, self.spec['parentEntId'])
if self.pathEntId:
self.factory.setEntityCreateCallback(self.pathEntId, self.setPath)
else:
self.setPath()
def setCogSpec(self, spec):
self.spec = spec
self.setPos(spec['pos'])
self.setH(spec['h'])
self.originalPos = spec['pos']
self.escapePos = spec['pos']
self.pathEntId = spec['path']
self.behavior = spec['behavior']
self.skeleton = spec['skeleton']
self.revives = spec.get('revives')
self.boss = spec['boss']
if self.reserve:
self.reparentTo(hidden)
else:
self.doReparent()
def comeOutOfReserve(self):
self.doReparent()
def getCogSpec(self, cogId):
if self.reserve:
return self.factory.getReserveCogSpec(cogId)
else:
return self.factory.getCogSpec(cogId)
def announceGenerate(self):
self.notify.debug('announceGenerate %s' % self.doId)
def onFactoryGenerate(factoryList, self = self):
self.factory = factoryList[0]
def onFactoryReady(self = self):
self.notify.debug('factory ready, read spec')
spec = self.getCogSpec(self.cogId)
self.setCogSpec(spec)
self.factoryRequest = None
return
self.factory.setEntityCreateCallback(LevelConstants.LevelMgrEntId, onFactoryReady)
self.factoryRequest = self.cr.relatedObjectMgr.requestObjects([self.levelDoId], onFactoryGenerate)
DistributedSuitBase.DistributedSuitBase.announceGenerate(self)
def disable(self):
self.ignoreAll()
if self.factoryRequest is not None:
self.cr.relatedObjectMgr.abortRequest(self.factoryRequest)
self.factoryRequest = None
self.notify.debug('DistributedSuit %d: disabling' % self.getDoId())
self.setState('Off')
if self.walkTrack:
del self.walkTrack
self.walkTrack = None
DistributedSuitBase.DistributedSuitBase.disable(self)
taskMgr.remove(self.taskName('returnTask'))
taskMgr.remove(self.taskName('checkStray'))
taskMgr.remove(self.taskName('chaseTask'))
return
def delete(self):
try:
self.DistributedSuit_deleted
except:
self.DistributedSuit_deleted = 1
self.notify.debug('DistributedSuit %d: deleting' % self.getDoId())
del self.fsm
DistributedSuitBase.DistributedSuitBase.delete(self)
def d_requestBattle(self, pos, hpr):
self.cr.playGame.getPlace().setState('WaitForBattle')
self.factory.lockVisibility(zoneNum=self.factory.getEntityZoneEntId(self.spec['parentEntId']))
self.sendUpdate('requestBattle', [pos[0],
pos[1],
pos[2],
hpr[0],
hpr[1],
hpr[2]])
def handleBattleBlockerCollision(self):
self.__handleToonCollision(None)
return
def __handleToonCollision(self, collEntry):
if collEntry:
if collEntry.getFromNodePath().getParent().getKey() != localAvatar.getKey():
return
if hasattr(self, 'factory') and hasattr(self.factory, 'lastToonZone'):
factoryZone = self.factory.lastToonZone
unitsBelow = self.getPos(render)[2] - base.localAvatar.getPos(render)[2]
if factoryZone == 24 and unitsBelow > 10.0:
self.notify.warning('Ignoring toon collision in %d from %f below.' % (factoryZone, unitsBelow))
return
if not base.localAvatar.wantBattles:
return
toonId = base.localAvatar.getDoId()
self.notify.debug('Distributed suit %d: requesting a Battle with toon: %d' % (self.doId, toonId))
self.d_requestBattle(self.getPos(), self.getHpr())
self.setState('WaitForBattle')
return None
def setPath(self):
self.notify.debug('setPath %s' % self.doId)
if self.pathEntId != None:
parent = self.factory.entities.get(self.spec['parentEntId'])
self.path = self.factory.entities.get(self.pathEntId)
self.idealPathNode = self.path.attachNewNode('idealPath')
self.reparentTo(self.idealPathNode)
self.setPos(0, 0, 0)
self.path.reparentTo(parent)
self.walkTrack = self.path.makePathTrack(self.idealPathNode, self.velocity, self.uniqueName('suitWalk'))
self.setState('Walk')
return
def initializeBodyCollisions(self, collIdStr):
DistributedSuitBase.DistributedSuitBase.initializeBodyCollisions(self, collIdStr)
self.sSphere = CollisionSphere(0.0, 0.0, 0.0, 15)
name = self.uniqueName('toonSphere')
self.sSphereNode = CollisionNode(name)
self.sSphereNode.addSolid(self.sSphere)
self.sSphereNodePath = self.attachNewNode(self.sSphereNode)
self.sSphereNodePath.hide()
self.sSphereBitMask = ToontownGlobals.WallBitmask
self.sSphereNode.setCollideMask(self.sSphereBitMask)
self.sSphere.setTangible(0)
self.accept('enter' + name, self.__handleToonCollision)
def enableBattleDetect(self, name, handler):
DistributedSuitBase.DistributedSuitBase.enableBattleDetect(self, name, handler)
self.lookForToon(1)
def disableBattleDetect(self):
DistributedSuitBase.DistributedSuitBase.disableBattleDetect(self)
self.lookForToon(0)
def subclassManagesParent(self):
return 1
def enterWalk(self, ts = 0):
self.enableBattleDetect('walk', self.__handleToonCollision)
if self.path:
if self.walkTrack:
self.walkTrack.loop()
self.walkTrack.pause()
if self.paused:
self.walkTrack.setT(self.pauseTime)
else:
self.walkTrack.setT(ts)
self.walkTrack.resume()
self.loop('walk', 0)
self.paused = 0
else:
self.loop('neutral', 0)
def exitWalk(self):
self.disableBattleDetect()
if self.walkTrack:
self.pauseTime = self.walkTrack.pause()
self.paused = 1
def lookForToon(self, on = 1):
if self.behavior in ['chase']:
if on:
self.accept(self.uniqueName('entertoonSphere'), self.__handleToonAlert)
else:
self.ignore(self.uniqueName('entertoonSphere'))
def __handleToonAlert(self, collEntry):
self.notify.debug('%s: ahah! i saw you' % self.doId)
toonZ = base.localAvatar.getZ(render)
suitZ = self.getZ(render)
dZ = abs(toonZ - suitZ)
if dZ < 8.0:
self.sendUpdate('setAlert', [base.localAvatar.doId])
def resumePath(self, state):
self.setState('Walk')
def enterChase(self):
self.enableBattleDetect('walk', self.__handleToonCollision)
self.startChaseTime = globalClock.getFrameTime()
self.startCheckStrayTask(1)
self.startChaseTask()
def exitChase(self):
self.disableBattleDetect()
taskMgr.remove(self.taskName('chaseTask'))
if self.chaseTrack:
self.chaseTrack.pause()
del self.chaseTrack
self.chaseTrack = None
self.chasing = 0
self.startCheckStrayTask(0)
return
def setConfrontToon(self, avId):
self.notify.debug('DistributedFactorySuit.setConfrontToon %d' % avId)
self.chasing = avId
self.setState('Chase')
def startChaseTask(self, delay = 0):
self.notify.debug('DistributedFactorySuit.startChaseTask delay=%s' % delay)
taskMgr.remove(self.taskName('chaseTask'))
taskMgr.doMethodLater(delay, self.chaseTask, self.taskName('chaseTask'))
def chaseTask(self, task):
if not self.chasing:
return Task.done
av = base.cr.doId2do.get(self.chasing, None)
if not av:
self.notify.warning("avatar %s isn't here to chase" % self.chasing)
return Task.done
if globalClock.getFrameTime() - self.startChaseTime > 3.0:
self.setReturn()
return Task.done
toonPos = av.getPos(self.getParent())
suitPos = self.getPos()
distance = Vec3(suitPos - toonPos).length()
if self.chaseTrack:
self.chaseTrack.pause()
del self.chaseTrack
self.chaseTrack = None
import random
rand1 = 0.5
rand2 = 0.5
rand3 = 0.5
targetPos = Vec3(toonPos[0] + 4.0 * (rand1 - 0.5), toonPos[1] + 4.0 * (rand2 - 0.5), suitPos[2])
track = Sequence(Func(self.headsUp, targetPos[0], targetPos[1], targetPos[2]), Func(self.loop, 'walk', 0))
chaseSpeed = 4.0
duration = distance / chaseSpeed
track.extend([LerpPosInterval(self, duration=duration, pos=Point3(targetPos), startPos=Point3(suitPos))])
self.chaseTrack = track
self.chaseTrack.start()
self.startChaseTask(1.0)
return
def startCheckStrayTask(self, on = 1):
taskMgr.remove(self.taskName('checkStray'))
if on:
taskMgr.add(self.checkStrayTask, self.taskName('checkStray'))
def checkStrayTask(self, task):
curPos = self.getPos()
distance = Vec3(curPos - self.originalPos).length()
if distance > 10.0:
self.sendUpdate('setStrayed', [])
def enterReturn(self):
self.enableBattleDetect('walk', self.__handleToonCollision)
self.lookForToon(0)
self.startReturnTask()
def exitReturn(self):
self.disableBattleDetect()
taskMgr.remove(self.taskName('checkStray'))
taskMgr.remove(self.taskName('returnTask'))
if self.returnTrack:
self.returnTrack.pause()
self.returnTrack = None
return
def setReturn(self):
self.notify.debug('DistributedFactorySuit.setReturn')
self.setState('Return')
def startReturnTask(self, delay = 0):
taskMgr.remove(self.taskName('returnTask'))
taskMgr.doMethodLater(delay, self.returnTask, self.taskName('returnTask'))
def returnTask(self, task):
self.factory.requestReparent(self, self.spec['parentEntId'])
if self.returnTrack:
self.returnTrack.pause()
self.returnTrack = None
if self.path:
targetPos = VBase3(0, 0, 0)
else:
targetPos = self.originalPos
track = Sequence(Func(self.headsUp, targetPos[0], targetPos[1], targetPos[2]), Func(self.loop, 'walk', 0))
curPos = self.getPos()
distance = Vec3(curPos - targetPos).length()
duration = distance / 3.0
track.append(LerpPosInterval(self, duration=duration, pos=Point3(targetPos), startPos=Point3(curPos)))
track.append(Func(self.returnDone))
self.returnTrack = track
self.returnTrack.start()
return
def returnDone(self):
self.setHpr(self.spec['h'], 0, 0)
self.setState('Walk')
if not self.path:
self.loop('neutral')
def setActive(self, active):
if active:
self.setState('Walk')
else:
self.setState('Off')
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 disableBodyCollisions(self):
self.disableBattleDetect()
self.enableRaycast(0)
if self.cRayNodePath:
self.cRayNodePath.removeNode()
if hasattr(self, 'cRayNode'):
del self.cRayNode
if hasattr(self, 'cRay'):
del self.cRay
if hasattr(self, 'lifter'):
del self.lifter
def removeCollisions(self):
self.enableRaycast(0)
self.cRay = None
self.cRayNode = None
self.cRayNodePath = None
self.lifter = None
self.cTrav = None
return
def setVirtual(self, isVirtual = 1):
self.virtual = isVirtual
if self.virtual:
actorNode = self.find('**/__Actor_modelRoot')
actorCollection = actorNode.findAllMatches('*')
parts = ()
for thingIndex in range(0, actorCollection.getNumPaths()):
thing = actorCollection[thingIndex]
if thing.getName() not in ('joint_attachMeter', 'joint_nameTag', 'def_nameTag'):
thing.setColorScale(1.0, 0.0, 0.0, 1.0)
thing.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))
thing.setDepthWrite(False)
thing.setBin('fixed', 1)
def getVirtual(self):
return self.virtual