def handleCameraFloorInteraction(self): if self.__onLevelGround or not base.localAvatarReachable() or ( base.localAvatarReachable() and base.localAvatar.battleControls): return self.putCameraFloorRayOnCamera() pointA = render.getRelativePoint(camera.getParent(), self.floorLineStart) pointB = pointA + (Vec3.down() * 1000) result = PhysicsUtils.rayTestClosestNotMe(base.localAvatar, pointA, pointB, CIGlobals.FloorGroup) if not result: return camObstrCollisionEntry = result camHeightFromFloor = (camera.getRelativePoint( render, camObstrCollisionEntry.getHitPos())).getZ() heightOfFloorUnderCamera = (camera.getPos()[2] - CIGlobals.FloorOffset) + camHeightFromFloor self.cameraZOffset = camera.getPos()[2] + camHeightFromFloor if self.cameraZOffset < 0: self.cameraZOffset = self.cameraZOffset * 0.33333333329999998 camHeight = max(base.localAvatar.getHeight(), 3.0) if self.cameraZOffset < -(camHeight * 0.5): if self.cameraZOffset < -camHeight: self.cameraZOffset = 0.0 else: self.cameraZOffset = -(camHeight * 0.5) if self.__floorDetected == 0: self.__floorDetected = 1 self.popCameraToDest()
def fireLaser(self): result = PhysicsUtils.rayTestClosestNotMe( self, self.laserVec[0], self.laserVec[1], CIGlobals.WorldGroup | CIGlobals.CharacterGroup, self.getBattleZone().getPhysicsWorld()) traceEnd = self.laserVec[1] if result: traceEnd = result.getHitPos() hitNode = NodePath(result.getNode()) avNP = hitNode.getParent() for obj in base.air.avatars[self.getBattleZone().zoneId]: if (CIGlobals.isAvatar(obj) and obj.getKey() == avNP.getKey() and self.getBattleZone().getGameRules().canDamage( self, obj, None)): dmgInfo = TakeDamageInfo(self, -1, 10, traceEnd, self.laserVec[0]) obj.takeDamage(dmgInfo) break self.getBattleZone().getTempEnts().makeLaser(self.laserVec[0], traceEnd, Vec4(1, 0, 0, 1), 1.0)
def doJump(self): self.emitSound(SOUND_COMBAT, self.getViewOrigin(), volume=3.0) for av in self.air.avatars[self.getBattleZone().zoneId]: if self.battleZone.getGameRules().canDamage(self, av, None): result = False if av.doId == ModGlobals.LocalAvatarID: # Check if on ground result = PhysicsUtils.rayTestClosestNotMe( av, av.getPos() + (0, 0, 0.1), av.getPos() - (0, 0, 0.3), CIGlobals.FloorGroup, self.battleZone.physicsWorld) else: if av.getActivity()[0] != ACT_JUMP: result = True av.onHitByVPJump() if result: # On ground, damage dmgInfo = TakeDamageInfo(self, -1, 10, av.getPos(), self.getPos()) av.takeDamage(dmgInfo) if av.doId == ModGlobals.LocalAvatarID: av.sendUpdateToAvatarId(av.doId, 'doVPJumpCameraShake', [])
def __updateParticleParent(self): if not CIGlobals.isNodePathOk(self.waterStreamParent): return time = globalClock.getFrameTime() streamPos = self.waterStreamParent.getPos(render) distance = self.sprayParticleDist if self.isLocal(): camQuat = camera.getQuat(render) pFrom = camera.getPos(render) push = (streamPos - pFrom).length() pFrom += camQuat.xform(Vec3.forward()) * push pTo = pFrom + camQuat.xform( Vec3.forward()) * (self.sprayParticleDist + (pFrom - streamPos).length()) hitPos = Point3(pTo) result = base.physicsWorld.rayTestClosest(pFrom, pTo, CIGlobals.WorldGroup) if result.hasHit(): node = result.getNode() hitPos = result.getHitPos() distance = (hitPos - streamPos).length() if time - self.lastSprayTime >= self.SprayTraceIval and not self.released: if result.hasHit(): self.__doSplat(distance, hitPos) self.getFPSCam().addViewPunch( Vec3(random.uniform(-0.6, 0.6), random.uniform(0.25, 1.0), 0.0)) self.primaryFirePress(True) self.lastSprayTime = time else: pFrom = self.avatar.getPos(render) + self.avatar.getEyePoint() + ( 1, 0, 0) quat = Quat() quat.setHpr( self.avatar.getHpr(render) + (0, self.avatar.lookPitch, 0)) pTo = pFrom + quat.xform( Vec3.forward()) * (self.sprayParticleDist + (pFrom - streamPos).length()) hitPos = Point3(pTo) hit = PhysicsUtils.rayTestClosestNotMe( self.avatar, pFrom, pTo, CIGlobals.WorldGroup | CIGlobals.LocalAvGroup) if hit is not None: hitPos = hit.getHitPos() distance = (hitPos - streamPos).length() self.waterStreamParent.lookAt(render, hitPos) if self.sprayParticle: system = self.sprayParticle.getParticlesNamed('particles-1') # Make the particles die off at the hit point. lifespan = min( 1, distance / self.sprayParticleDist) * self.sprayParticleLife system.factory.setLifespanBase(lifespan)
def __handleUse(self, task): #if self.mode == LocalControls.MThirdPerson: # return task.cont time = globalClock.getFrameTime() use = inputState.isSet('use') if use: # see if there is anything for us to use. distance = 7.5 camQuat = base.camera.getQuat(render) camFwd = camQuat.xform(Vec3.forward()) camPos = base.camera.getPos(render) if self.mode == self.MFirstPerson: start = camPos else: # Move the line out to their character. # This prevents the player from using things that # are behind their character, but in front of # the camera. laPos = base.localAvatar.getPos(render) camToPlyr = (camPos.getXy() - laPos.getXy()).length() start = camPos + (camFwd * camToPlyr) stop = start + (camFwd * distance) hit = PhysicsUtils.rayTestClosestNotMe(base.localAvatar, start, stop, CIGlobals.UseableGroup) somethingToUse = False if hit is not None: node = hit.getNode() if node.hasPythonTag("useableObject"): somethingToUse = True obj = node.getPythonTag("useableObject") if obj.canUse(): if self.currentObjectUsing != obj: if self.currentObjectUsing is not None: self.currentObjectUsing.stopUse() obj.startUse() self.lastUseObjectTime = time elif time - self.lastUseObjectTime >= obj.useIval: obj.use() self.lastUseObjectTime = time self.currentObjectUsing = obj if not somethingToUse and not self.lastUse: self.useInvalidSound.play() else: if self.currentObjectUsing is not None: self.currentObjectUsing.stopUse() self.currentObjectUsing = None self.lastUse = use return task.cont
def consider(self, node, pos, eyeHeight): self.reparentTo(node) self.setPos(pos) result = None floorLineStart = self.getPos(render) + (0, 0, 0.1) floorLineEnd = floorLineStart - (0, 0, 10000) floorResult = base.physicsWorld.rayTestClosest(floorLineStart, floorLineEnd, CIGlobals.FloorMask) if floorResult.hasHit(): floorPoint = self.getRelativePoint(render, floorResult.getHitPos()) if abs(floorPoint[2]) <= 4.0: pos += floorPoint self.setPos(pos) base.physicsWorld.attach(self.cSphereNodePath.node()) self.cSphereNodePath.node().setTransformDirty() sphereContactResult = base.physicsWorld.contactTest(self.cSphereNodePath.node()) base.physicsWorld.remove(self.cSphereNodePath.node()) wallEntry = False for iContact in range(sphereContactResult.getNumContacts()): contact = sphereContactResult.getContact(iContact) node0 = NodePath(contact.getNode0()) node1 = NodePath(contact.getNode1()) if (node0 == self.cSphereNodePath and not base.localAvatar.isAncestorOf(node1) and not node.isAncestorOf(node1)): if not (node1.getCollideMask() & CIGlobals.WallGroup).isZero(): wallEntry = True break elif (node1 == self.cSphereNodePath and not base.localAvatar.isAncestorOf(node0) and not node.isAncestorOf(node0)): if not (node0.getCollideMask() & CIGlobals.WallGroup).isZero(): wallEntry = True break if not wallEntry: lineStart = render.getRelativePoint(self, (0, 0, eyeHeight)) lineEnd = render.getRelativePoint(self, (-pos[0], -pos[1], eyeHeight)) lineResult = PhysicsUtils.rayTestClosestNotMe(node, lineStart, lineEnd, CIGlobals.WallGroup) if not lineResult: result = pos self.reparentTo(hidden) return result
def doesLineTraceToPlayer(self, plyr): # Do we have a clear LOS to the player? world = self.battleZone.physicsWorld result = PhysicsUtils.rayTestClosestNotMe(self, self.getPos(render) + self.getEyePosition(), plyr.getPos(render) + plyr.getEyePosition(), CIGlobals.WorldGroup | CIGlobals.CharacterGroup, world) # Assume clear LOS if ray hit nothing if not result: return True # Also clear LOS if ray hits the player np = NodePath(result.getNode()).getParent() return np.getKey() == plyr.getKey()
def doTraceAndDamage(self, origin, dir, dist, traces=1, impact=True): # Trace a line from the trace origin outward along the trace direction # to find out what we hit, and adjust the direction of the hitscan traceEnd = origin + (dir * dist) hit = PhysicsUtils.rayTestClosestNotMe( self.avatar, origin, traceEnd, self.TraceMask, self.avatar.getBattleZone().getPhysicsWorld()) if hit is not None: node = hit.getNode() hitPos = hit.getHitPos() distance = (hitPos - origin).length() self.__handleHitSomething_trace(NodePath(node), hitPos, distance, origin, traces, impact) return node return None
def __updateEyeRay(self): fromOrigin = camera.getPos(render) toOrigin = fromOrigin + (camera.getQuat(render).getForward() * 100) result = PhysicsUtils.rayTestClosestNotMe(self.movementParent, fromOrigin, toOrigin) if self.__eyeRayNode and ((not result) or (result.getNode() != self.__eyeRayNode)): node = self.__eyeRayNode messenger.send('rayexit' + node.getName(), [NodePath(node)]) self.__eyeRayNode = None if result: if (self.__eyeRayNode != result.getNode()): node = result.getNode() messenger.send('rayenter' + node.getName(), [NodePath(node)]) self.__eyeRayNode = node else: self.__eyeRayNode = None
def start(self): Gag.start(self) self.hitSfx.play() gag = self.gag if self.isLocal(): vm = self.getViewModel() fpsCam = self.getFPSCam() fpsCam.setVMAnimTrack( Sequence(ActorInterval(vm, "sg_shoot_begin"), ActorInterval(vm, "sg_shoot_end"), Func(vm.loop, "sg_idle"))) gag = self.getVMGag() nozzle = gag.find("**/joint_nozzle") if self.isLocal() and base.localAvatar.battleControls: if base.localAvatar.isFirstPerson(): self.getFPSCam().resetViewPunch() self.getFPSCam().addViewPunch( Vec3(random.uniform(-0.6, 0.6), random.uniform(-0.25, -0.5), 0.0)) startPos = camera.getPos(render) else: startPos = nozzle.getPos(render) hitPos = PhysicsUtils.getHitPosFromCamera() else: startPos = nozzle.getPos(render) quat = Quat() quat.setHpr( self.avatar.getHpr(render) + (0, self.avatar.lookPitch, 0)) hitPos = quat.xform(Vec3.forward() * 10000) hit = PhysicsUtils.rayTestClosestNotMe( self.avatar, startPos, hitPos, CIGlobals.WorldGroup | CIGlobals.LocalAvGroup) if hit is not None: hitPos = hit.getHitPos() pellet = WaterPellet(self.isLocal()) pellet.addToWorld(nozzle.getPos(render), lookAt=hitPos, velo=Vec3.forward() * self.pelletSpeed) if self.isLocal(): base.localAvatar.sendUpdate('usedGag', [self.id])
def addExitWaypoint(self): vpos = self.getPos() quat = self.getQuat() if self.rearOrFront == 0: endPos = vpos + quat.xform((0, 11, 0)) else: endPos = vpos + quat.xform((0, -11, 0)) # Snap to floor result = PhysicsUtils.rayTestClosestNotMe( self, endPos + (0, 0, 0.5), endPos - (0, 0, 20), CIGlobals.WorldGroup, self.getBattleZone().getPhysicsWorld()) if result: endPos = result.getHitPos() self.motor.setWaypoints([endPos]) self.motor.setFwdSpeed(5.0)
def think(self): BaseAttackAI.think(self) time = self.ThrowAfterTime if not time: try: time = self.__calculateThrowAfterTime() except: pass if self.action == self.StateThrow: if not CIGlobals.isNodePathOk(self.target): return # Lock onto the target self.avatar.headsUp(self.target) if self.getActionTime() >= time and not self.didThrow: self.calibrate(self.target) # Trace a line from the trace origin outward along the trace direction # to find out what we hit, and adjust the direction of the projectile launch traceEnd = self.traceOrigin + (self.traceVector * 10000) hit = PhysicsUtils.rayTestClosestNotMe( self.avatar, self.traceOrigin, traceEnd, CIGlobals.WorldGroup | CIGlobals.CharacterGroup, self.avatar.getBattleZone().getPhysicsWorld()) if hit is not None: hitPos = hit.getHitPos() else: hitPos = traceEnd vecThrow = (hitPos - self.throwOrigin).normalized() endPos = self.throwOrigin + (vecThrow * self.ThrowPower) proj = GenericThrowableLinearProjectileAI(base.air) proj.setData(self.ID) proj.setLinear(1.5, self.throwOrigin, endPos, globalClockDelta.getFrameNetworkTime()) proj.generateWithRequired(self.avatar.getBattleZone().zoneId) proj.addHitCallback(self.onProjectileHit) proj.addExclusion(self.avatar) self.didThrow = True
def updateSmartCamera(self, task): if base.localAvatarReachable( ) and base.localAvatar.battleControls and base.localAvatar.isFirstPerson( ): return Task.cont if not self.__camCollCanMove and not self.__cameraHasBeenMoved: if self.__lastPosWrtRender == camera.getPos(render): if self.__lastHprWrtRender == camera.getHpr(render): return Task.cont self.__cameraHasBeenMoved = 0 self.__lastPosWrtRender = camera.getPos(render) self.__lastHprWrtRender = camera.getHpr(render) self.__idealCameraObstructed = 0 self.updateSmartCameraCollisionLineSegment() if not self.__disableSmartCam: pointA = render.getRelativePoint(camera.getParent(), self.pointA) pointB = render.getRelativePoint(camera.getParent(), self.pointB) mask = CIGlobals.WallGroup | CIGlobals.CameraGroup if base.localAvatarReachable(): if base.localAvatar.battleControls: mask |= (CIGlobals.FloorGroup | CIGlobals.StreetVisGroup) result = PhysicsUtils.rayTestClosestNotMe( base.localAvatar, pointA, pointB, mask) if result: self.handleCameraObstruction(result) if not self.__onLevelGround: self.handleCameraFloorInteraction() if not self.__idealCameraObstructed: self.nudgeCamera() return Task.cont
def __updateParticleParent(self, task=None): time = globalClock.getFrameTime() streamPos = self.waterStreamParent.getPos(render) distance = self.sprayParticleDist if self.isLocal(): if base.localAvatar.backpack.getSupply(self.id) <= 0: base.localAvatar.b_gagThrow(self.id) return task.done camQuat = camera.getQuat(render) pFrom = camera.getPos(render) push = (streamPos - pFrom).length() pFrom += camQuat.xform(Vec3.forward()) * push pTo = pFrom + camQuat.xform( Vec3.forward()) * (self.sprayParticleDist + (pFrom - streamPos).length()) hitPos = Point3(pTo) result = base.physicsWorld.rayTestClosest(pFrom, pTo, CIGlobals.WorldGroup) if result.hasHit(): node = result.getNode() hitPos = result.getHitPos() distance = (hitPos - streamPos).length() if time - self.lastDmgTime >= self.dmgIval: self._handleSprayCollision(NodePath(node), hitPos, distance) self.lastDmgTime = time if time - self.lastSprayTime >= self.dmgIval: self.getFPSCam().addViewPunch( Vec3(random.uniform(-0.6, 0.6), random.uniform(0.25, 1.0), 0.0)) base.localAvatar.sendUpdate('usedGag', [self.id]) self.lastSprayTime = time else: pFrom = self.avatar.getPos(render) + self.avatar.getEyePoint() + ( 1, 0, 0) quat = Quat() quat.setHpr( self.avatar.getHpr(render) + (0, self.avatar.lookPitch, 0)) pTo = pFrom + quat.xform( Vec3.forward()) * (self.sprayParticleDist + (pFrom - streamPos).length()) hitPos = Point3(pTo) hit = PhysicsUtils.rayTestClosestNotMe( self.avatar, pFrom, pTo, CIGlobals.WorldGroup | CIGlobals.LocalAvGroup) if hit is not None: hitPos = hit.getHitPos() distance = (hitPos - streamPos).length() self.waterStreamParent.lookAt(render, hitPos) if self.sprayParticle: system = self.sprayParticle.getParticlesNamed('particles-1') # Make the particles die off at the hit point. lifespan = min( 1, distance / self.sprayParticleDist) * self.sprayParticleLife system.factory.setLifespanBase(lifespan) if task: return task.cont
def release(self): Gag.release(self) base.audio3d.attachSoundToObject(self.woosh, self.gag) base.playSfx(self.woosh, node=self.gag) if self.isLocal() and base.localAvatar.battleControls: if base.localAvatar.isFirstPerson(): # Add a small kick to the camera to give more feedback self.getFPSCam().addViewPunch( Vec3(random.uniform(.5, 1), random.uniform(-.5, -1), 0)) startPos = camera.getPos(render) + camera.getQuat( render).xform(Vec3.right()) push = 0.0 else: startPos = self.handJoint.getPos(render) push = (startPos - camera.getPos(render)).length() hitPos = PhysicsUtils.getHitPosFromCamera() else: startPos = self.handJoint.getPos(render) quat = Quat() quat.setHpr( self.avatar.getHpr(render) + (0, self.avatar.lookPitch, 0)) hitPos = quat.xform(Vec3.forward() * self.power) hit = PhysicsUtils.rayTestClosestNotMe( self.avatar, startPos, hitPos, CIGlobals.WorldGroup | CIGlobals.LocalAvGroup) if hit is not None: hitPos = hit.getHitPos() throwDir = (hitPos - startPos).normalized() endPos = startPos + (throwDir * self.power) - (0, 0, 90) entity = self.gag if not entity: entity = self.build() gagRoot = render.attachNewNode('gagRoot') gagRoot.setPos(startPos) entity.reparentTo(render) entity.setPos(0, 0, 0) entity.headsUp(throwDir) rot = entity.getHpr(render) entity.reparentTo(gagRoot) entity.setHpr(rot[0], -90, 0) self.gag = None if not self.handJoint: self.handJoint = self.avatar.find('**/def_joint_right_hold') track = FlightProjectileInterval(gagRoot, startPos=startPos, endPos=endPos, gravityMult=1.07, duration=2.5) event = self.avatar.uniqueName('throwIvalDone') + '-' + str( hash(entity)) track.setDoneEvent(event) base.acceptOnce(event, self.__handlePieIvalDone, [entity]) track.start() if self.isLocal(): collider = self.buildCollisions(entity) self.entities.append([gagRoot, track, collider]) base.localAvatar.sendUpdate('usedGag', [self.id]) else: self.entities.append([gagRoot, track, NodePath()]) self.reset()