public override void Process() { Game.DisableControlThisFrame(2, Control.ParachuteSmoke); var camRay = WorldProbe.StartShapeTestRay(GameplayCamera.Position, GameplayCamera.Position + GameplayCamera.Direction * 100f, ShapeTestFlags.IntersectPeds | ShapeTestFlags.IntersectVehicles, PlayerCharacter).GetResult(); if (camRay.Hit) { var bounds = camRay.EntityHit.Model.GetDimensions(); var z = bounds.Z / 2; World.DrawMarker(MarkerType.UpsideDownCone, camRay.EntityHit.Position + Vector3.WorldUp * z * 1.5f, Vector3.Zero, Vector3.Zero, new Vector3(0.3f, 0.3f, 0.3f), Color.White); if (Game.IsDisabledControlJustPressed(2, Control.ParachuteSmoke)) { var directionToEntity = camRay.EntityHit.Position - PlayerCharacter.Position; var distance = directionToEntity.Length(); directionToEntity.Normalize(); // Set the player's heading towards the target. PlayerCharacter.Heading = directionToEntity.ToHeading(); // Play the web shoot animation. PlayerCharacter.Task.PlayAnimation("guard_reactions", "1hand_aiming_to_idle", 8.0f, -8.0f, -1, (AnimationFlags)40, 0.0f); var playerBone = PlayerCharacter.GetBoneCoord(Bone.SKEL_R_Hand); var rope = Rope.AddRope(playerBone, distance, GTARopeType.ThickRope, 0.2f, 0.1f, true, false); var timer = 2.0f; var counter = 0; while (timer > 0) { PlayerCharacter.SetAnimationSpeed("guard_reactions", "1hand_aiming_to_idle", 0f); playerBone = PlayerCharacter.GetBoneCoord(Bone.SKEL_R_Hand); rope.PinVertex(0, playerBone); rope.PinVertex(rope.VertexCount - 1, camRay.EntityHit.Position); timer -= Time.DeltaTime; directionToEntity = camRay.EntityHit.Position - PlayerCharacter.Position; PlayerCharacter.Heading = directionToEntity.ToHeading(); if (counter % 10 == 0) { if (camRay.EntityType == EntityType.Ped) { var ped = new Ped(camRay.EntityHit.Handle); Utilities.ShockPed(ped, 15); } Utilities.CreateParticleChain(playerBone, camRay.EntityHit.Position, Vector3.Zero, nodeSize: 0.5f, noiseMultiplier: 0.0f); } counter++; Script.Yield(); } if (camRay.EntityType == EntityType.Vehicle) { var veh = new Vehicle(camRay.EntityHit.Handle); veh.Explode(); } PlayerCharacter.Task.ClearAll(); rope.Delete(); } } }
private void DoSwing(Vector3 hitPoint, Entity webHitHelper, Control webControl, bool checkMinAngle = true) { // Create a helper prop for rotations. var rotationHelper = World.CreateVehicle("bmx", Profile.LocalUser.Position); rotationHelper.Alpha = 0; // Store the initial velocity. var initialVelocity = Profile.LocalUser.Velocity; // Clear the player tasks. Profile.LocalUser.Task.ClearAll(); // Attach the player to the helper prop. Profile.LocalUser.AttachToEntity(rotationHelper, 0, new Vector3(0, -0.25f, -1.15f), Vector3.Zero, false, false, true, 0, true); var t = 0.5f; while (!Profile.LocalUser.IsAttached() && t > 0) { t -= Time.UnscaledDeltaTime; Script.Yield(); } // We should play the base animation initially for good blending Profile.LocalUser.Task.PlayAnimation("move_fall", "fall_high", 8.0f, -4.0f, -1, AnimationFlags.StayInEndFrame, 0.0f); // The rappel anim! Profile.LocalUser.Task.PlayAnimation("missrappel", "rappel_idle", 4.0f, -4.0f, -1, AnimationFlags.Loop | AnimationFlags.AllowRotation | AnimationFlags.UpperBodyOnly, 0.0f); // Create our rope. var initialLength = Vector3.Distance(rotationHelper.Position, hitPoint); if (initialLength <= 0) { initialLength = 1; } var rope = Rope.AddRope(rotationHelper.Position, initialLength, GTARopeType.ThickRope, initialLength, 0.1f, true, false); // Attach the two helpers. rope.AttachEntities(rotationHelper, Vector3.Zero, webHitHelper, Vector3.Zero, initialLength); rope.ActivatePhysics(); // Init a rotation. var initalDirection = Vector3.ProjectOnPlane(Profile.GetCameraDirection(), (webHitHelper.Position - rotationHelper.Position).Normalized); // Apply an initial force to the rotation helper. rotationHelper.Velocity = initalDirection * initialVelocity.Length() * 1.5f; // A bool to help us determine if we've played our forward swing // animation or not. var forwardSwing = false; // The amount of momentum we build. var momentumBuild = 1f; // Here's our loop. while (true) { // Disable the parachute deploy control. Game.DisableControlThisFrame(2, Control.ParachuteDeploy); // Disable the jump control. Game.DisableControlThisFrame(2, webControl); if (rotationHelper.HasCollidedWithAnything) { var normal = rotationHelper.GetLastCollisionNormal(); var dir = Vector3.Reflect(rotationHelper.Velocity, normal); dir.Normalize(); Profile.LocalUser.Detach(); Profile.LocalUser.Heading = dir.ToHeading(); Profile.LocalUser.Velocity = dir * rotationHelper.Velocity.Length() / 2; Profile.LocalUser.Task.Skydive(); Profile.LocalUser.Task.PlayAnimation("swimming@swim", "recover_flip_back_to_front", 4.0f, -2.0f, 1150, (AnimationFlags)40, 0.0f); Profile.LocalUser.Quaternion.Normalize(); Audio.ReleaseSound(Audio.PlaySoundFromEntity(Profile.LocalUser, "DLC_Exec_Office_Non_Player_Footstep_Mute_group_MAP")); GTAGraphics.StartParticle("core", "ent_dst_dust", Profile.LocalUser.Position, Profile.LocalUser.Rotation, 1f); break; } // If we're near the ground then stop. if (Profile.LocalUser.HeightAboveGround <= 2f) { // The swing was canceled. break; } // If we release the attach control then // we should start the skydive. if (Game.IsDisabledControlJustReleased(2, webControl)) { ReleaseWebToAir(-1, rotationHelper); break; } // Set the hand ik positions. var ropeCoord = rope[0]; var boneOffset = Profile.LocalUser.RightVector * 0.05f; Profile.LocalUser.SetIKTarget(IKIndex.LeftArm, ropeCoord - boneOffset, -1f, 0f); Profile.LocalUser.SetIKTarget(IKIndex.RightArm, ropeCoord + boneOffset, -1f, 0f); // Swing the player's legs based on his forward direction. var dot = Vector3.Dot(Vector3.WorldUp, Profile.LocalUser.ForwardVector); // Swinging down. if (dot < 0) { // Check our flag. if (!forwardSwing) { // Play the down swinging anim. Profile.LocalUser.Task.PlayAnimation("skydive@parachute@", "chute_idle_alt", 1.0f, -4.0f, -1, AnimationFlags.Loop, 0.0f); // Set our flag. forwardSwing = true; } } // Swinging up. else if (dot > 0) { // Check our flag. if (forwardSwing) { // Play the up swinging anim. Profile.LocalUser.Task.PlayAnimation("skydive@parachute@", "chute_forward", 1.0f, -4.0f, -1, AnimationFlags.Loop, 0.0f); // Set our flag. forwardSwing = false; } } // Get the desired rotation for our // rotation helper. var directionToWebHit = webHitHelper.Position - rotationHelper.Position; directionToWebHit.Normalize(); var dirVel = Vector3.ProjectOnPlane(rotationHelper.Velocity, directionToWebHit); var rotation = Maths.LookRotation(dirVel, directionToWebHit); rotationHelper.Quaternion = rotation; // Get the direction of input. var moveDir = Profile.GetInputDirection(); var relativeDir = Quaternion.Euler(Profile.GetCameraRotation()) * moveDir; relativeDir = Vector3.ProjectOnPlane(relativeDir, directionToWebHit); // Apply force of input. if (momentumBuild < 2.5f) { momentumBuild += Time.DeltaTime; } rotationHelper.ApplyForce(relativeDir * momentumBuild * 50f * Time.UnscaledDeltaTime); rotationHelper.ApplyForce(Vector3.WorldDown * 15f * Time.UnscaledDeltaTime); if (checkMinAngle) { var angle = Vector3.Angle(directionToWebHit, Vector3.WorldUp); if (angle > 70) { ReleaseWebToAir(0, rotationHelper); break; } } // Yield the script. Script.Yield(); } // Reset the cooldown! _webSwingCooldown = 0.7f; Profile.LocalUser.Task.ClearAnimation("skydive@parachute@", "chute_idle_alt"); Profile.LocalUser.Task.ClearAnimation("skydive@parachute@", "chute_forward"); Profile.LocalUser.Task.ClearAnimation("missrappel", "rappel_idle"); // Delete the helper props. rotationHelper.Delete(); // Delete the rope. rope.Delete(); }
/// <summary> /// Update's a 2 handed rope. /// </summary> /// <param name="vehicle"></param> /// <param name="ropes"></param> /// <param name="ropeDeleteDelay"></param> /// <returns></returns> private float UpdateRopes2(ISpatial vehicle, IList <Rope> ropes, float ropeDeleteDelay) { // Let's update the swimming anim for this if any. if (Profile.LocalUser.IsPlayingAnimation("swimming@swim", "recover_flip_back_to_front")) { if (Profile.LocalUser.GetAnimationTime("swimming@swim", "recover_flip_back_to_front") > 0.25f) { Profile.LocalUser.Task.PlayAnimation("move_fall", "fall_med", 2.0f, -4.0f, -1, AnimationFlags.StayInEndFrame, 0.0f); } } // Get the right hand coord. var rHand = Profile.LocalUser.GetBoneCoord(Bone.SKEL_R_Hand); // Check if the player is playing the web pull anim on // the upper body. if (!Profile.LocalUser.IsPlayingAnimation("weapons@projectile@", "throw_m_fb_stand")) { if (ropeDeleteDelay <= 0) { // Despawn the ropes at this point. DespawnRopes(ropes); } else { // Count down the rope delete delay. ropeDeleteDelay -= Time.DeltaTime; // If we've spawned the ropes... if (ropes.Count > 0) { // Pin the vertices accordingly. ropes[0].UnpinVertex(0); // Unpin the one from our hand. ropes[0].PinVertex(ropes[0].VertexCount - 1, vehicle.Position); } } } // The animation's not playing so let's // add the ropes in. else { // Make sure there are no ropes. if (ropes.Count <= 0) { // The distance to the target // will be used as the rope length. var dist = Vector3.Distance(rHand, vehicle.Position); var rope = Rope.AddRope(rHand, dist, GTARopeType.ThickRope, dist / 2, 0.1f, true, false); ropes.Add(rope); } // The rope is there. else { // Now let's pin the vertex coords. ropes[0].PinVertex(0, rHand); ropes[0].PinVertex(ropes[0].VertexCount - 1, vehicle.Position); } } return(ropeDeleteDelay); }
/// <summary> /// Updates a 1 handed rope. /// </summary> /// <param name="vehicle"></param> /// <param name="ropes"></param> /// <param name="ropeDeleteDelay"></param> /// <returns></returns> private float UpdateRopes1(ISpatial vehicle, IList <Rope> ropes, float ropeDeleteDelay) { // Stop the upper body animation after some time, and move to // a falling animation. if (Profile.LocalUser.IsPlayingAnimation("swimming@swim", "recover_back_to_idle")) { if (Profile.LocalUser.GetAnimationTime("swimming@swim", "recover_back_to_idle") > 0.2f) { Profile.LocalUser.Task.PlayAnimation("move_fall", "fall_med", 2.0f, -4.0f, -1, AnimationFlags.StayInEndFrame, 0.0f); } } // Get the hand coordinates. var lHand = Profile.LocalUser.GetBoneCoord(Bone.SKEL_L_Hand); var rHand = Profile.LocalUser.GetBoneCoord(Bone.SKEL_R_Hand); // Check if this player is playing the web pull animation. if (!Profile.LocalUser.IsPlayingAnimation("amb@world_vehicle_police_carbase", "base")) { // If the ropes are ready to be deleted... if (ropeDeleteDelay <= 0) { // We need to despawn the dual webs. DespawnRopes(ropes); } // Otherwise... else { // Make sure we decrease the rope delay. ropeDeleteDelay -= Time.DeltaTime; // Unpin the vertex coordinates from // our hands. if (ropes.Count > 0) { ropes[0].UnpinVertex(0); ropes[1].UnpinVertex(0); // Also pin the vertices to the target // until we're done here. ropes[0].PinVertex(ropes[0].VertexCount - 1, vehicle.Position); ropes[1].PinVertex(ropes[1].VertexCount - 1, vehicle.Position); } } } // Otherwise we need to spawn them, // and update them. else { // Spawn the ropes first. if (ropes.Count == 0) { // Create the left and right hand ropes for two hand web jump. var lHandDistance = Vector3.Distance(lHand, vehicle.Position); var rHandDistance = Vector3.Distance(rHand, vehicle.Position); var rope1 = Rope.AddRope(lHand, lHandDistance, GTARopeType.ThickRope, lHandDistance / 2, 0.1f, true, false); var rope2 = Rope.AddRope(rHand, rHandDistance, GTARopeType.ThickRope, rHandDistance / 2, 0.1f, true, false); // Add the ropes to the rope collection. ropes.Add(rope1); ropes.Add(rope2); } // Now we need to update the vertex coordinates. else { // Pin the vertices. ropes[0].PinVertex(0, lHand); ropes[0].PinVertex(ropes[0].VertexCount - 1, vehicle.Position); ropes[1].PinVertex(0, rHand); ropes[1].PinVertex(ropes[1].VertexCount - 1, vehicle.Position); } } return(ropeDeleteDelay); }
/// <summary> /// Grapples the player towards a point on the map. /// </summary> private void WorldGrapple(Vector3 targetPoint) { // Make sure that this point is not // empty just for safety. if (targetPoint == Vector3.Zero) { return; } // Disable the reload control for now. Game.DisableControlThisFrame(2, Control.Reload); // Now once we press the reload key, we want // to grapple the player (also make sure // he's not on the ground already). if (Game.IsDisabledControlJustPressed(2, Control.Reload)) { // Get the direction from the player to the point. var directionToPoint = targetPoint - Profile.LocalUser.Position; // If we're on the ground then move us upwards. if (Profile.LocalUser.GetConfigFlag(60)) { directionToPoint += Vector3.WorldUp * 0.5f; } directionToPoint.Normalize(); // Normalize the direcion vector. // Set the player's heading accordingly. Profile.LocalUser.Heading = directionToPoint.ToHeading(); var speed = Vector3.Distance(Profile.LocalUser.Position, targetPoint); speed = Maths.Clamp(speed, 65f, 150f) * Profile.WebZipForceMultiplier; // Play the falling animation. // Reset the player's velocity if anything is left over. Profile.LocalUser.Task.ClearAllImmediately(); Profile.LocalUser.Velocity = Vector3.Zero; Profile.LocalUser.Task.Jump(); // Initialize our rope variable. Rope rope = null; var isOnGround = Profile.LocalUser.GetConfigFlag(60); var timer = 0.025f; if (isOnGround) { // Wait until the player is no longer on the ground. while (timer > 0f) { Profile.LocalUser.Velocity += Vector3.WorldUp * 500f * Time.DeltaTime; timer -= Time.DeltaTime; Script.Yield(); } GameWaiter.Wait(150); } // Now we need to set player's velocity. Profile.LocalUser.Velocity = directionToPoint * speed; // Make sure we've left the ground. if (!Profile.LocalUser.GetConfigFlag(60)) { // Play the web grapple animation. Profile.LocalUser.Task.PlayAnimation("weapons@projectile@", "throw_m_fb_stand", 8.0f, -4.0f, 250, AnimationFlags.UpperBodyOnly | AnimationFlags.AllowRotation, 0.0f); timer = 0.5f; while (!Profile.LocalUser.IsPlayingAnimation("weapons@projectile@", "throw_m_fb_stand") && timer > 0f) { timer -= Time.DeltaTime; Script.Yield(); } Profile.LocalUser.SetAnimationSpeed("weapons@projectile@", "throw_m_fb_stand", -1f); } timer = 0.7f; while (timer > 0f) { if (Profile.LocalUser.HasCollidedWithAnything) { break; } if (CheckFallAndCatchLanding(rope)) { break; } // Cache the players right hand coord. var rHand = Profile.LocalUser.GetBoneCoord(Bone.SKEL_R_Hand); // Create the rope. if (rope == null) { // Get the inital distance to the target. var initialDist = rHand.DistanceTo(targetPoint); rope = Rope.AddRope(rHand, initialDist, GTARopeType.ThickRope, initialDist / 2, 0.1f, true, false); } // Check if the player is playing the grapple animation. if (Profile.LocalUser.IsPlayingAnimation("weapons@projectile@", "throw_m_fb_stand")) { // Pin the rope vertices. rope.PinVertex(0, rHand); rope.PinVertex(rope.VertexCount - 1, targetPoint); // Reverse the grapple animation. Profile.LocalUser.SetAnimationSpeed("weapons@projectile@", "throw_m_fb_stand", -1f); } else { // Otherwise delete the rope. rope.UnpinVertex(0); rope.PinVertex(rope.VertexCount - 1, targetPoint); } timer -= Time.DeltaTime; Script.Yield(); } // Clear the throwing anim. Profile.LocalUser.Task.ClearAnimation("weapons@projectile@", "throw_m_fb_stand"); // Destroy the rope here. if (Rope.Exists(rope)) { rope?.Delete(); } //OverrideFallHeight(float.MaxValue); } }
/// <summary> /// Catch our landing so we don't die from high falls. /// </summary> private bool CheckFallAndCatchLanding(Rope rope = null) { // If the player is falling then... if (Profile.LocalUser.IsFalling) { // Check the falling flag. if (!_falling) { _fallHeight = Profile.LocalUser.HeightAboveGround; } // Set the flag regardless. We're just // using it as a trigger of sorts. _falling = true; } else { // Like before, set it regardless. _falling = false; // Set the input vector before we start falling. } // Catch our landing at high falls. bool didCollide; if (!(didCollide = Profile.LocalUser.GetConfigFlag(60)) && !(Profile.LocalUser.HeightAboveGround < 2f)) { return(false); } // Check the fall height, catch the landing, // and reset the fall height. const float maxFallHeight = 5f; if (_fallHeight > maxFallHeight) { if (!didCollide) { var vel = Profile.LocalUser.Velocity; Profile.LocalUser.SetCoordsSafely(Profile.LocalUser.Position - Vector3.WorldUp * Profile.LocalUser.HeightAboveGround); Profile.LocalUser.Velocity = vel; } // Try to catch our landing. rope?.Delete(); CatchLanding(); CaughtLanding?.Invoke(this, new EventArgs(), _fallHeight); _fallHeight = 0f; } else { // If we should splat then let us, so that // the falling anim isn't constantly playing. Profile.LocalUser.Task.ClearAnimation("move_fall", "fall_high"); } // This will return true since we landed. return(true); // Nothing happened so we return false. }
public override void Process() { if (Game.IsDisabledControlJustPressed(2, Control.Cover)) { var peds = World.GetNearbyPeds(PlayerCharacter.Position, 20f); if (peds.Length <= 0) { return; } var playerForward = Vector3.ProjectOnPlane(GameplayCamera.Direction, Vector3.WorldUp); var playerPosition = PlayerCharacter.Position; var pList = new List <Ped>(); for (var i = 0; i < peds.Length; i++) { var ped = peds[i]; if (ped.IsPlayer) { continue; } if (ped.IsInVehicle()) { continue; } if (ped.IsDead) { continue; } var dir = ped.Position - playerPosition; dir.Normalize(); var angle = Vector3.Angle(playerForward.Normalized, dir); if (angle < 90f) { var ray = WorldProbe.StartShapeTestRay(playerPosition, ped.Position, ShapeTestFlags.IntersectMap, PlayerCharacter); var result = ray.GetResult(); if (result.Hit) { continue; } if (ped.Weapons.Current == null) { continue; } if (ped.Weapons.Current.Hash == WeaponHash.Unarmed) { continue; } pList.Add(ped); } } if (pList.Count <= 0) { return; } var boneCoord = PlayerCharacter.GetBoneCoord(Bone.SKEL_R_Hand); var helperObj = World.CreateVehicle("bmx", boneCoord); helperObj.Alpha = 0; helperObj.AttachTo(PlayerCharacter, PlayerCharacter.GetBoneIndex(Bone.SKEL_R_Hand)); var center = Vector3.Zero; var rList = new List <Rope>(); foreach (var p in pList) { center += p.Position; var d = Vector3.Distance(helperObj.Position, p.Position); var r = Rope.AddRope(helperObj.Position, d, GTARopeType.ThickRope, d, 0.1f, true, false); r.AttachEntities(helperObj, Vector3.Zero, p, Vector3.Zero, d); r.ActivatePhysics(); rList.Add(r); } center /= pList.Count; PlayerCharacter.PlayAimAnim(center); GameWaiter.Wait(300); PlayerCharacter.PlayGrappleAnim(-1f); foreach (var r in rList) { r.Delete(); } foreach (var p in pList) { DisarmPed(p); } helperObj.Delete(); } }