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 panda3d.core 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 range(0, 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 range(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(int(5 + draw * 12.0), 0.0, 0.0, self.radius, wideX, wideY) self.trackShapeFloor = [] self.trackShapeFloor = getCirclePoints(int(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 range(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 range(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()