388 lines
15 KiB
Python
388 lines
15 KiB
Python
from panda3d.core import *
|
|
from direct.interval.IntervalGlobal import *
|
|
from StomperGlobals import *
|
|
from direct.distributed import ClockDelta
|
|
from direct.showbase.PythonUtil import lerp
|
|
import math
|
|
from otp.level import DistributedEntity
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
from pandac.PandaModules import NodePath
|
|
from otp.level import BasicEntities
|
|
from direct.task import Task
|
|
from toontown.toonbase import ToontownGlobals
|
|
from toontown.coghq import BattleBlocker
|
|
import random
|
|
from math import *
|
|
|
|
def circleX(angle, radius, centerX, centerY):
|
|
x = radius * cos(angle) + centerX
|
|
return x
|
|
|
|
|
|
def circleY(angle, radius, centerX, centerY):
|
|
y = radius * sin(angle) + centerY
|
|
return y
|
|
|
|
|
|
def getCirclePoints(segCount, centerX, centerY, radius, wideX = 1.0, wideY = 1.0):
|
|
returnShape = []
|
|
for seg in xrange(0, int(segCount)):
|
|
coordX = wideX * circleX(pi * 2.0 * float(float(seg) / float(segCount)), radius, centerX, centerY)
|
|
coordY = wideY * circleY(pi * 2.0 * float(float(seg) / float(segCount)), radius, centerX, centerY)
|
|
returnShape.append((coordX, coordY, 1))
|
|
|
|
coordX = wideX * circleX(pi * 2.0 * float(0 / segCount), radius, centerX, centerY)
|
|
coordY = wideY * circleY(pi * 2.0 * float(0 / segCount), radius, centerX, centerY)
|
|
returnShape.append((coordX, coordY, 1))
|
|
return returnShape
|
|
|
|
|
|
class DistributedSecurityCamera(BasicEntities.DistributedNodePathEntity):
|
|
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedSecurityCamera')
|
|
laserFieldModels = ['phase_9/models/cogHQ/square_stomper']
|
|
|
|
def __init__(self, cr):
|
|
BasicEntities.DistributedNodePathEntity.__init__(self, cr)
|
|
node = hidden.attachNewNode('DistributedNodePathEntity')
|
|
self.trackBeamGN = None
|
|
self.trackFloorGN = None
|
|
self.trackX = 10.0
|
|
self.trackY = -5.0
|
|
self.radius = 5.0
|
|
self.trackShape = []
|
|
self.trackShape = getCirclePoints(7, 0.0, 0.0, self.radius)
|
|
self.trackShapeFloor = []
|
|
self.trackShapeFloor = getCirclePoints(16, 0.0, 0.0, self.radius)
|
|
self.zFloat = 0.05
|
|
self.projector = Point3(0, 0, 25)
|
|
self.isToonIn = 0
|
|
self.toonX = 0
|
|
self.toonY = 0
|
|
self.canDamage = 1
|
|
self.accel = 0.5
|
|
self.maxVel = 1.0
|
|
self.vX = 0.0
|
|
self.vY = 0.0
|
|
self.targetX = self.trackX
|
|
self.targetY = self.trackY
|
|
self.target = 0
|
|
self.trackTargetList = [None,
|
|
None,
|
|
None,
|
|
None]
|
|
self.lastTime = 0.0
|
|
self.currentTime = 0.0
|
|
self.delta = 0.0
|
|
self.Norm = {}
|
|
self.Norm['Red'] = 0.2
|
|
self.Norm['Green'] = 0.2
|
|
self.Norm['Blue'] = 0.2
|
|
self.Norm['Alpha'] = 1.0
|
|
self.Alert = {}
|
|
self.Alert['Red'] = 1.0
|
|
self.Alert['Green'] = 0.0
|
|
self.Alert['Blue'] = 0.0
|
|
self.Alert['Alpha'] = 1.0
|
|
self.attackSound = loader.loadSfx('phase_9/audio/sfx/CHQ_GOON_tractor_beam_alarmed.ogg')
|
|
self.onSound = loader.loadSfx('phase_11/audio/sfx/LB_camera_shutter_2.ogg')
|
|
self.attackTrack = Parallel(SoundInterval(self.attackSound, node=self, volume=0.8), SoundInterval(self.onSound, node=self, volume=0.8))
|
|
self.moveStartSound = loader.loadSfx('phase_11/audio/sfx/LB_laser_beam_on_2.ogg')
|
|
self.moveStartTrack = Parallel(SoundInterval(self.moveStartSound, node=self, volume=0.4))
|
|
self.moveLoopSound = loader.loadSfx('phase_11/audio/sfx/LB_laser_beam_hum_2.ogg')
|
|
self.moveLoopSound.setLoop()
|
|
self.moveLoopTrack = Parallel(SoundInterval(self.moveLoopSound, node=self, volume=0.4))
|
|
self.moveStopSound = loader.loadSfx('phase_11/audio/sfx/LB_laser_beam_off_2.ogg')
|
|
self.moveStopTrack = Parallel(SoundInterval(self.moveStopSound, node=self, volume=0.4))
|
|
self.taskName = None
|
|
return
|
|
|
|
def generateInit(self):
|
|
self.notify.debug('generateInit')
|
|
BasicEntities.DistributedNodePathEntity.generateInit(self)
|
|
|
|
def generate(self):
|
|
self.notify.debug('generate')
|
|
BasicEntities.DistributedNodePathEntity.generate(self)
|
|
|
|
def announceGenerate(self):
|
|
self.notify.debug('announceGenerate')
|
|
BasicEntities.DistributedNodePathEntity.announceGenerate(self)
|
|
self.trackBeamNode = self.attachNewNode('tracking Beam Node')
|
|
self.trackBeamGN = GeomNode('tracking Beam')
|
|
self.trackBeamNode.attachNewNode(self.trackBeamGN)
|
|
self.trackBeamNode.setTransparency(TransparencyAttrib.MAlpha)
|
|
self.trackBeamNode.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))
|
|
self.trackBeamNode.setTwoSided(False)
|
|
self.trackBeamNode.setDepthWrite(False)
|
|
self.trackFloorNode = self.attachNewNode('tracking floor Node')
|
|
self.trackFloorGN = GeomNode('tracking Floor')
|
|
self.trackFloorNode.attachNewNode(self.trackFloorGN)
|
|
self.trackFloorNode.setTransparency(TransparencyAttrib.MAlpha)
|
|
self.trackFloorNode.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))
|
|
self.trackFloorNode.setTwoSided(False)
|
|
self.trackFloorNode.setDepthWrite(False)
|
|
if not hasattr(self, 'trackTarget1'):
|
|
self.trackTarget1 = None
|
|
else:
|
|
self.trackTargetList[1] = self.trackTarget1
|
|
if not hasattr(self, 'trackTarget2'):
|
|
self.trackTarget2 = None
|
|
else:
|
|
self.trackTargetList[2] = self.trackTarget2
|
|
if not hasattr(self, 'trackTarget3'):
|
|
self.trackTarget3 = None
|
|
else:
|
|
self.trackTargetList[3] = self.trackTarget3
|
|
self.loadModel()
|
|
self.detectName = 'securityCamera %s' % self.doId
|
|
return
|
|
|
|
def initCollisionGeom(self):
|
|
pass
|
|
|
|
def sendFail(self):
|
|
self.battleStart()
|
|
self.sendUpdate('trapFire', [])
|
|
|
|
def battleStart(self):
|
|
pass
|
|
|
|
def setTarget(self, targetHash):
|
|
targetCount = targetHash % 3
|
|
sanity = 10
|
|
self.target = None
|
|
while targetCount >= 0 and sanity > 0:
|
|
sanity -= 1
|
|
for index in xrange(1, 4):
|
|
if self.trackTargetList[index]:
|
|
if targetCount == 0:
|
|
self.target = self.trackTargetList[index]
|
|
targetCount -= 1
|
|
|
|
return
|
|
|
|
def setTrackTarget1(self, targetId):
|
|
self.trackTarget1 = targetId
|
|
self.trackTargetList[1] = targetId
|
|
|
|
def setTrackTarget2(self, targetId):
|
|
self.trackTarget2 = targetId
|
|
self.trackTargetList[2] = targetId
|
|
|
|
def setTrackTarget3(self, targetId):
|
|
self.trackTarget3 = targetId
|
|
self.trackTargetList[3] = targetId
|
|
|
|
def __detect(self, task):
|
|
distance = self.getDistance(localAvatar)
|
|
greaterDim = self.gridScaleX
|
|
if self.gridScaleY > self.gridScaleX:
|
|
greaterDim = self.gridScaleY
|
|
if distance < greaterDim * 1.6:
|
|
if localAvatar.getPos(self)[0] > 0 and localAvatar.getPos(self)[0] < self.gridScaleX and localAvatar.getPos(self)[1] > 0 and localAvatar.getPos(self)[1] < self.gridScaleY:
|
|
self.__toonHit()
|
|
else:
|
|
if self.isToonIn:
|
|
self.isToonIn = 0
|
|
self.isToonIn = 0
|
|
taskMgr.doMethodLater(0.1, self.__detect, self.detectName)
|
|
return Task.done
|
|
|
|
def __toonHit(self):
|
|
posX = localAvatar.getPos(self)[0]
|
|
posY = localAvatar.getPos(self)[1]
|
|
tileX = int(posX / (self.gridScaleX / self.gridNumX))
|
|
tileY = int(posY / (self.gridScaleY / self.gridNumY))
|
|
if self.toonX != tileX or self.toonY != tileY or not self.isToonIn:
|
|
self.toonX = tileX
|
|
self.toonY = tileY
|
|
self.isToonIn = 1
|
|
if self.gridData[tileX][tileY] < len(self.gridSymbols):
|
|
tileFunction = self.gridSymbols[self.gridData[tileX][tileY]][0]
|
|
if tileFunction:
|
|
tileFunction()
|
|
self.sendHit()
|
|
self.isToonIn = 1
|
|
|
|
def sendHit(self):
|
|
self.sendUpdate('hit', [self.toonX, self.toonY])
|
|
|
|
def disable(self):
|
|
self.notify.debug('disable')
|
|
if self.moveLoopTrack.isPlaying():
|
|
self.moveLoopTrack.finish()
|
|
if self.attackTrack.isPlaying():
|
|
self.attackTrack.finish()
|
|
if self.moveStartTrack.isPlaying():
|
|
self.moveStartTrack.finish()
|
|
if self.moveStopTrack.isPlaying():
|
|
self.moveStopTrack.finish()
|
|
self.ignoreAll()
|
|
taskMgr.remove(self.detectName)
|
|
BasicEntities.DistributedNodePathEntity.disable(self)
|
|
|
|
def delete(self):
|
|
self.notify.debug('delete')
|
|
self.unloadModel()
|
|
if self.taskName:
|
|
taskMgr.remove(self.taskName)
|
|
BasicEntities.DistributedNodePathEntity.delete(self)
|
|
|
|
def loadModel(self):
|
|
self.rotateNode = self.attachNewNode('rotate')
|
|
self.model = loader.loadModel(self.laserFieldModels[self.modelPath])
|
|
self.model.reparentTo(self.rotateNode)
|
|
self.model.setPos(0, 1, 0)
|
|
self.taskName = 'securityCameraupdate %s' % self.doId
|
|
taskMgr.add(self.__updateTrack, self.taskName, priority=25)
|
|
|
|
def unloadModel(self):
|
|
if self.model:
|
|
self.model.removeNode()
|
|
del self.model
|
|
self.model = None
|
|
return
|
|
|
|
def __updateTrack(self, task):
|
|
if self.target and self.level and hasattr(self.level, 'entities'):
|
|
thing = self.level.entities.get(self.target, None)
|
|
self.targetX = thing.getPos(self)[0]
|
|
self.targetY = thing.getPos(self)[1]
|
|
else:
|
|
return Task.cont
|
|
self.rotateNode.setPos(self.projector)
|
|
self.rotateNode.lookAt(Point3(self.trackX, self.trackY, 0.0))
|
|
dt = globalClock.getDt()
|
|
deccel = 1.0 - 1.0 * (dt * 7.0)
|
|
if deccel < 0:
|
|
deccel = 0.0
|
|
dirX = 0.0
|
|
dirY = 0.0
|
|
distX = self.targetX - self.trackX
|
|
distY = self.targetY - self.trackY
|
|
trigDist = math.sqrt(distX * distX + distY * distY)
|
|
totalDist = abs(distX) + abs(distY)
|
|
propX = abs(distX) / (totalDist + 0.01)
|
|
propY = abs(distY) / (totalDist + 0.01)
|
|
if self.targetX != self.trackX:
|
|
dirX = distX / abs(distX)
|
|
if self.targetY != self.trackY:
|
|
dirY = distY / abs(distY)
|
|
if trigDist < self.radius * 0.5 + 1.0:
|
|
self.vX = self.vX * deccel
|
|
self.vY = self.vY * deccel
|
|
self.moveStopTrack.start()
|
|
self.moveLoopTrack.finish()
|
|
else:
|
|
if not self.moveLoopTrack.isPlaying():
|
|
self.moveLoopTrack.start()
|
|
self.moveStartTrack.start()
|
|
self.vX += dirX * self.accel * propX
|
|
self.vY += dirY * self.accel * propY
|
|
if self.vX > self.maxVel:
|
|
self.vX = self.maxVel
|
|
if self.vX < -self.maxVel:
|
|
self.vX = -self.maxVel
|
|
if self.vY > self.maxVel:
|
|
self.vY = self.maxVel
|
|
if self.vY < -self.maxVel:
|
|
self.vY = -self.maxVel
|
|
self.trackX += self.vX * dt
|
|
self.trackY += self.vY * dt
|
|
self.genTrack()
|
|
dist = self.getDist(base.localAvatar)
|
|
if dist < self.radius and self.canDamage:
|
|
self.canDamage = 0
|
|
self.sendUpdate('trapFire', [])
|
|
taskMgr.doMethodLater(2.0, self._resetDam, 'reset Damage')
|
|
self.attackTrack.start()
|
|
return Task.cont
|
|
|
|
def _resetDam(self, task = None):
|
|
self.canDamage = 1
|
|
|
|
def getDist(self, thing):
|
|
posTX = thing.getX()
|
|
posTY = thing.getY()
|
|
dx = thing.getPos(self)[0] - self.trackX
|
|
dy = thing.getPos(self)[1] - self.trackY
|
|
return sqrt(dx * dx + dy * dy)
|
|
|
|
def genTrack(self):
|
|
dist = self.getDist(base.localAvatar)
|
|
draw = 1.0 / (0.01 + float(pow(dist, 0.4)))
|
|
self.trackShape = []
|
|
wideX = 1
|
|
wideY = 1
|
|
self.trackShape = getCirclePoints(5 + draw * 12.0, 0.0, 0.0, self.radius, wideX, wideY)
|
|
self.trackShapeFloor = []
|
|
self.trackShapeFloor = getCirclePoints(5 + draw * 50.0, 0.0, 0.0, self.radius, wideX, wideY)
|
|
if self.trackBeamGN:
|
|
self.trackBeamGN.removeAllGeoms()
|
|
if self.trackFloorGN:
|
|
self.trackFloorGN.removeAllGeoms()
|
|
beamRed = 0.0
|
|
beamGreen = 0.0
|
|
beamBlue = 0.0
|
|
beamAlpha = 1.0
|
|
origin = {}
|
|
origin['Red'] = 0.2
|
|
origin['Green'] = 0.2
|
|
origin['Blue'] = 0.2
|
|
origin['Alpha'] = 1.0
|
|
if self.canDamage:
|
|
origin = self.Norm
|
|
else:
|
|
origin = self.Alert
|
|
self.gFormat = GeomVertexFormat.getV3cp()
|
|
self.trackBeamVertexData = GeomVertexData('holds my vertices', self.gFormat, Geom.UHDynamic)
|
|
self.trackBeamVertexWriter = GeomVertexWriter(self.trackBeamVertexData, 'vertex')
|
|
self.trackBeamColorWriter = GeomVertexWriter(self.trackBeamVertexData, 'color')
|
|
self.trackFloorVertexData = GeomVertexData('holds my vertices', self.gFormat, Geom.UHDynamic)
|
|
self.trackFloorVertexWriter = GeomVertexWriter(self.trackFloorVertexData, 'vertex')
|
|
self.trackFloorColorWriter = GeomVertexWriter(self.trackFloorVertexData, 'color')
|
|
self.trackBeamVertexWriter.addData3f(self.projector[0], self.projector[1], self.projector[2])
|
|
self.trackBeamColorWriter.addData4f(origin['Red'], origin['Green'], origin['Blue'], origin['Alpha'])
|
|
self.trackFloorVertexWriter.addData3f(self.trackX, self.trackY, self.zFloat)
|
|
self.trackFloorColorWriter.addData4f(origin['Red'], origin['Green'], origin['Blue'], origin['Alpha'])
|
|
for vertex in self.trackShape:
|
|
self.trackBeamVertexWriter.addData3f(self.trackX + vertex[0], self.trackY + vertex[1], self.zFloat)
|
|
self.trackBeamColorWriter.addData4f(beamRed, beamGreen, beamBlue, beamAlpha)
|
|
|
|
for vertex in self.trackShapeFloor:
|
|
self.trackFloorVertexWriter.addData3f(self.trackX + vertex[0], self.trackY + vertex[1], self.zFloat)
|
|
self.trackFloorColorWriter.addData4f(origin['Red'], origin['Green'], origin['Blue'], origin['Alpha'])
|
|
|
|
self.trackBeamTris = GeomTrifans(Geom.UHStatic)
|
|
self.trackFloorTris = GeomTrifans(Geom.UHStatic)
|
|
sizeTrack = len(self.trackShape)
|
|
self.trackBeamTris.addVertex(0)
|
|
for countVertex in xrange(1, sizeTrack + 1):
|
|
self.trackBeamTris.addVertex(countVertex)
|
|
|
|
self.trackBeamTris.addVertex(1)
|
|
self.trackBeamTris.closePrimitive()
|
|
self.trackBeamGeom = Geom(self.trackBeamVertexData)
|
|
self.trackBeamGeom.addPrimitive(self.trackBeamTris)
|
|
self.trackBeamGN.addGeom(self.trackBeamGeom)
|
|
sizeTrack = len(self.trackShapeFloor)
|
|
self.trackFloorTris.addVertex(0)
|
|
for countVertex in xrange(1, sizeTrack + 1):
|
|
self.trackFloorTris.addVertex(countVertex)
|
|
|
|
self.trackFloorTris.addVertex(1)
|
|
self.trackFloorTris.closePrimitive()
|
|
self.trackFloorGeom = Geom(self.trackFloorVertexData)
|
|
self.trackFloorGeom.addPrimitive(self.trackFloorTris)
|
|
self.trackFloorGN.addGeom(self.trackFloorGeom)
|
|
|
|
def setProjector(self, projPoint):
|
|
self.projector = projPoint
|
|
if self.trackBeamGN and self.trackFloorGN:
|
|
self.genTrack()
|
|
|
|
def setHideModel(self, flag):
|
|
if flag:
|
|
self.model.stash()
|
|
else:
|
|
self.model.unstash()
|