Poodletooth-iLand/toontown/suit/DistributedFactorySuit.py

414 lines
15 KiB
Python

from panda3d.core import *
from direct.interval.IntervalGlobal import *
from direct.fsm import ClassicFSM, State
from direct.fsm import State
from direct.directnotify import DirectNotifyGlobal
import DistributedSuitBase
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 xrange(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