/// <summary> /// The update / tick method for our ability. /// </summary> public override void Update() { // Loop this. if (Profile.LocalUser.IsRagdoll) { GameWaiter.Wait(300); Profile.LocalUser.Task.ClearAllImmediately(); } Profile.LocalUser.CanRagdoll = false; // DarkSouls-style roll. HandleRoll(); // Set the player state accordingly. SetPlayerState(); // Check if we hit the ground, and make sure there are no cancelation flags. if (GroundRay(out var normal) && !SprintCancelationFlags()) { //////////////////////////////////////////////////////////// // Now we need to speed up the player by the speed we want. // For now we'll use a value of 300% normal speed. Or about 20/ms. //////////////////////////////////////////////////////////// // First we need to get the direction we want. var direction = Vector3.Cross(-Profile.LocalUser.RightVector, normal); direction.Normalize(); // We'll have to normalize this, just in case. // We're going to do some debugging. //GameGraphics.DrawLine(PlayerCharacter.Position, PlayerCharacter.Position + direction * 5f, Color.Red); // For now we'll use a constant for the desired speed. var velocity = direction * _desiredSpeed * Profile.RunSpeedMultiplier; _desiredSpeed = _playerState != PlayerState.None ? Maths.Lerp(_desiredSpeed, 26.8224f, Time.UnscaledDeltaTime * 0.4f) : Maths.Lerp(_desiredSpeed, 10f, Time.UnscaledDeltaTime * 5f); //Now for our switch case we're going to see //what state the player is in. switch (_playerState) { // Let's set the velocity to the direction // multiplied by our desired speed. case PlayerState.Run: Profile.LocalUser.Velocity = velocity / 2; // dividing by 2 so running is slower. break; case PlayerState.Sprint: Profile.LocalUser.Velocity = velocity; break; } }
/// <summary> /// If you call this as soon as the player /// hit's the ground, it will recover him with a roll (or /// if not moving just a plain landing animation). /// </summary> private void CatchLanding() { // Clear the player's tasks. Profile.LocalUser.ClearTasksImmediately(); // Check our movement vector. var moveVector = Profile.GetInputDirection(); // Play the movement dependant animations. if (moveVector.Length() > 0) { // Add a little bit of dust. GTAGraphics.StartParticle("core", "ent_dst_dust", Profile.LocalUser.Position - Vector3.WorldUp, Vector3.Zero, 2f); // Play the rolling animation. Profile.LocalUser.Task.PlayAnimation("move_fall", "land_roll", 8.0f, -4.0f, 750, AnimationFlags.AllowRotation, 0.0f); } else { // Add a little bit of dust. GTAGraphics.StartParticle("core", "ent_dst_dust", Profile.LocalUser.Position - Vector3.WorldUp, Vector3.Zero, 2f); // Play our super hero landing animation. Profile.LocalUser.Velocity = Vector3.Zero; Profile.LocalUser.Task.PlayAnimation("move_crouch_proto", "idle_intro", 6.0f, -4.0f, 450, AnimationFlags.Loop, 0.0f); Profile.LocalUser.Task.PlayAnimation("skydive@base", "ragdoll_to_free_idle", 6.0f, -4.0f, 450, AnimationFlags.AllowRotation | AnimationFlags.UpperBodyOnly, 0.0f); var timer = 0.5f; while (!Profile.LocalUser.IsPlayingAnimation("skydive@base", "ragdoll_to_free_idle") && timer > 0f) { timer -= Time.DeltaTime; Script.Yield(); } Profile.LocalUser.SetAnimationSpeed("skydive@base", "ragdoll_to_free_idle", 0f); } // Clear the falling animation. Profile.LocalUser.Task.ClearAnimation("move_fall", "fall_high"); GameWaiter.Wait(500); }
private void UpdateClimbing(Vector3 surfacePosition, Vector3 surfaceNormal) { // Create the attachmentObject. var attachmentObject = World.CreateProp("w_pi_pistol", surfacePosition, false, false); attachmentObject.PositionNoOffset = surfacePosition; attachmentObject.HasCollision = false; attachmentObject.FreezePosition = true; attachmentObject.Quaternion = Maths.LookRotation(Vector3.WorldUp, surfaceNormal); attachmentObject.Alpha = 0; // attachmentObject.Alpha = 0; // Attach the player to the attachment object. Profile.LocalUser.Task.ClearAllImmediately(); Profile.LocalUser.AttachTo(attachmentObject, 0, new Vector3(0, 0, 1), Vector3.Zero); Profile.LocalUser.Task.PlayAnimation("move_crouch_proto", "idle_intro", 8.0f, -1, AnimationFlags.Loop); // Delay for the control. GameWaiter.Wait(10); // Create camera. var camDirection = Vector3.Zero; var moveDirection = Vector3.Zero; //var camSpawn = attachmentObject.GetOffsetInWorldCoords(new Vector3(0, -2, 1)); //var cam = World.CreateCamera(camSpawn, Vector3.Zero, 60); //cam.Direction = attachmentObject.Position - cam.Position; //cam.TransitionIn(100); //var pivot = World.CreateProp("w_pi_pistol", attachmentObject.Position, false, false); //pivot.FreezePosition = true; //pivot.IsVisible = false; //pivot.Quaternion = attachmentObject.Quaternion; //// Camera rotation. //var xRotation = 0f; //var yRotation = 45f; // flags. var cancelClimb = false; var idleTimer = 0f; while (!cancelClimb) { // Override the enabled controls. SetActiveControls(); GameplayCamera.ClampPitch(-90, 90); // Rotate the wall cam. //RotateCam(cam, pivot, attachmentObject, ref xRotation, ref yRotation); // Get the movement vector. var movement = GetMovementVector(); // Move the player attachment. Move(/*cam, */ surfaceNormal, attachmentObject, ref camDirection, ref moveDirection, movement); // Play the player movement animations. DoMovementAnimations(attachmentObject, movement.Length(), ref idleTimer); // Start a new surface ray. var surfaceRay = WorldProbe.StartShapeTestRay(attachmentObject.Position + attachmentObject.UpVector, attachmentObject.Position - attachmentObject.UpVector, ShapeTestFlags.IntersectMap, attachmentObject); // Handle the ejection keys. HandleEject(ref cancelClimb, attachmentObject); // Make sure the result is not empty. var result = surfaceRay.GetResult(); if (!result.Hit) { DetachPlayer(attachmentObject); GameWaiter.Wait(10); if (Game.IsDisabledControlPressed(2, Control.Sprint)) { Profile.LocalUser.HasCollision = false; Profile.LocalUser.IsCollisionProof = true; Profile.LocalUser.SetConfigFlag(60, false); Profile.LocalUser.Task.Skydive(); Profile.LocalUser.Task.PlayAnimation("swimming@swim", "recover_back_to_idle", 2.0f, -2.0f, 1150, AnimationFlags.AllowRotation, 0.0f); Profile.LocalUser.Velocity = Vector3.WorldUp * 25f; WebZip.OverrideFallHeight(float.MaxValue); var t = 0.1f; while (t > 0f) { t -= Game.LastFrameTime; Profile.LocalUser.HasCollision = false; Script.Yield(); } Profile.LocalUser.HasCollision = true; Profile.LocalUser.IsCollisionProof = false; } else { Profile.LocalUser.Task.Climb(); WebZip.OverrideFallHeight(0f); } break; } // Set the surface position. surfacePosition = result.EndCoords; // Check the surface normal. if (surfaceNormal != result.SurfaceNormal) { // If the surface normal has changed, then change immediately rotation the player // to match the normal. surfaceNormal = result.SurfaceNormal; Move(/*cam, */ surfaceNormal, attachmentObject, ref camDirection, ref moveDirection, movement, false); } attachmentObject.PositionNoOffset = surfacePosition; Script.Yield(); } // Destroy the camera. //Utilities.DestroyAllCameras(); // Delte the camera pivot. //pivot.Delete(); }
private void ProcessRopeAttachment() { while (Attached) { Controls.DisableControlsKeepRecording(2); Game.EnableControlThisFrame(2, Control.ReplayStartStopRecording); Game.EnableControlThisFrame(2, Control.LookLeftRight); Game.EnableControlThisFrame(2, Control.LookBehind); Game.EnableControlThisFrame(2, Control.LookUpDown); Game.EnableControlThisFrame(2, Control.MoveLeftRight); Game.EnableControlThisFrame(2, Control.MoveUpDown); Game.EnableControlThisFrame(2, Control.NextCamera); Game.EnableControlThisFrame(2, Control.Sprint); Game.EnableControlThisFrame(2, Control.FrontendPause); Game.EnableControlThisFrame(2, Control.FrontendPauseAlternate); UI.ShowHudComponentThisFrame(HudComponent.Reticle); // If the entity died then end to prevent crashing. if (_ropeAttachedEntity.IsDead) { EndAttachment(); break; } // Cancel the web. if (Game.IsDisabledControlJustPressed(2, Control.Aim)) { EndAttachment(); break; } var entityType = _ropeAttachedEntity.GetEntityType(); var isPed = entityType == EntityType.Ped; var isVeh = entityType == EntityType.Vehicle; var headingDirection = Profile.LocalUser.ForwardVector; var directionToEntity = _ropeAttachedEntity.Position - Profile.LocalUser.Position; directionToEntity.Normalize(); var distance = Vector3.Distance(Profile.LocalUser.Position, _ropeAttachedEntity.Position); var reverse = Vector3.Angle(headingDirection, directionToEntity) < 45; if (Game.IsDisabledControlJustPressed(2, Control.Attack)) { var flip = false; if (reverse) { headingDirection = -directionToEntity; if (distance < 25 && isVeh) { flip = true; } else { Profile.LocalUser.PlayGrappleAnim(-1f); } } else { Profile.LocalUser.PlayGrappleAnim(1f); } if (isPed) { var ped = new Ped(_ropeAttachedEntity.Handle); ped.Task.ClearAllImmediately(); ped.SetToRagdoll(500); ped.Velocity = headingDirection * distance; } _ropeAttachedEntity.Velocity = headingDirection * 25; EndAttachment(); if (flip) { FrontFlip(); } GameWaiter.Wait(150); break; } if (Game.IsDisabledControlJustPressed(2, Control.Enter) && isVeh) { var veh = new Vehicle(_ropeAttachedEntity.Handle); var driver = veh.Driver; if (Entity.Exists(driver)) { driver.Task.ClearAllImmediately(); driver.SetToRagdoll(500); driver.Velocity += veh.Velocity; veh.BreakDoor(VehicleDoor.FrontLeftDoor); if (reverse) { Profile.LocalUser.PlayGrappleAnim(-1f); } else { Profile.LocalUser.PlayGrappleAnim(1f); } EndAttachment(); break; } } if (Game.IsDisabledControlJustPressed(2, Control.Jump)) { Profile.LocalUser.Task.PlayAnimation("move_crouch_proto", "idle_intro", 8.0f, -8.0f, -1, AnimationFlags.Loop, 0.0f); Profile.LocalUser.Task.PlayAnimation("amb@code_human_wander_texting@male@base", "static", 8.0f, -8.0f, -1, AnimationFlags.UpperBodyOnly | AnimationFlags.Loop | AnimationFlags.AllowRotation, 0.0f); } if (Game.IsDisabledControlPressed(2, Control.Jump)) { var velocityDir = Profile.LocalUser.RightVector; _ropeAttachedEntity.ApplyForce(velocityDir); Profile.LocalUser.Heading = directionToEntity.ToHeading(); Profile.LocalUser.SetIKTarget(IKIndex.LeftArm, Profile.LocalUser.Position + directionToEntity, 0, 0); Profile.LocalUser.SetIKTarget(IKIndex.RightArm, Profile.LocalUser.Position + directionToEntity, 0, 0); Profile.LocalUser.SetIKTarget(IKIndex.Head, _ropeAttachedEntity.Position + Vector3.WorldUp * 5f, 0, 0); } if (Game.IsDisabledControlJustReleased(2, Control.Jump)) { Profile.LocalUser.Task.ClearAll(); EndAttachment(); break; } if (Game.IsDisabledControlJustPressed(2, Control.ParachuteSmoke)) { var ray = WorldProbe.StartShapeTestRay(GameplayCamera.Position, GameplayCamera.Position + GameplayCamera.Direction * 100f, ShapeTestFlags.Everything, Profile.LocalUser); var res = ray.GetResult(); if (res.Hit) { var entity = GetEntityFromRayResult(res); SetAttachedEntityToRagdollIfPed(); var rope = AttachRopeAttachedEntityToEntity(entity); AddAttachment(entity, _ropeAttachedEntity, rope); EndAttachment(); break; } } Script.Yield(); } }
private void LiftThrowVehicle(Vehicle vehicle) { // We have our vehicle. if (vehicle == null || !vehicle.Exists() || !Profile.LocalUser.IsTouching(vehicle)) { return; } // The direction to the vehicle. var directionToVehicle = vehicle.Position - Profile.LocalUser.Position; directionToVehicle.Normalize(); // Make sure we're not on top of this vehicle. var dot = Vector3.Dot(directionToVehicle, Vector3.WorldUp); if (dot < -0.4f) { return; } // Get the mass of the vehicle. var weight = HandlingFile.GetHandlingValue(vehicle, 0x000C); // The maximum weight spidey can lift, // about 10 tons. const float maxWeight = 9071.85f; // If the weight is over the max then we can't lift it. if (weight > maxWeight) { if (Profile.LocalUser.IsPlayer) { UI.Notify("This vehicle is FAR to heavy for spidey to lift."); } return; } // Lifting: // amb@world_human_yoga@male@base => base_b // Pickup: // anim@mp_snowball => pickup_snowball // Set the current pickup vehicle. _currentPickupVehicle = vehicle; // Clear the player tasks and make him play // the pickup animation. Profile.LocalUser.ClearTasksImmediately(); Profile.LocalUser.Heading = directionToVehicle.ToHeading(); Profile.LocalUser.Task.PlayAnimation("anim@mp_snowball", "pickup_snowball", 8.0f, -8.0f, 500, AnimationFlags.StayInEndFrame, 0.0f); // Let's us keep track of whether or not we played the animation. var hasPlayedAnimation = false; // Set the vehicle alpha to transparent so the // player can see where he's going to throw. vehicle.Alpha = 100; GameWaiter.Wait(100); while (true) { Profile.DisableControls(); if (Profile.LocalUser.IsPlayer) { Game.EnableControlThisFrame(2, Control.ReplayStartStopRecording); Game.EnableControlThisFrame(2, Control.MoveLeftRight); Game.EnableControlThisFrame(2, Control.MoveUpDown); Game.EnableControlThisFrame(2, Control.LookLeftRight); Game.EnableControlThisFrame(2, Control.LookUpDown); Game.EnableControlThisFrame(2, Control.NextCamera); } if (weight < maxWeight / 2) { if (Profile.LocalUser.IsPlayer) { Game.EnableControlThisFrame(2, Control.Jump); Game.EnableControlThisFrame(2, Control.Sprint); } } if (Profile.LocalUser.IsRagdoll || Profile.LocalUser.IsBeingStunned || Profile.LocalUser.IsDead || Profile.LocalUser.IsInVehicle() || Profile.LocalUser.IsGettingUp) { break; } // Play our pickup animation sequence. if (Profile.LocalUser.IsPlayingAnimation("anim@mp_snowball", "pickup_snowball")) { hasPlayedAnimation = true; vehicle.Velocity = Vector3.Zero; } // Now that we've played that animation let's continue. else if (hasPlayedAnimation) { Profile.LocalUser.ClearTasksImmediately(); Profile.LocalUser.Task.PlayAnimation("random@arrests", "kneeling_arrest_get_up", 8.0f, -8.0f, -1, AnimationFlags.Loop | AnimationFlags.AllowRotation | AnimationFlags.UpperBodyOnly, 0.06f); var model = vehicle.Model; var d = model.GetDimensions(); d.X = Math.Max(1.25f, d.X); var height = d.X * 0.8f; // Attack the vehicle to the player. vehicle.AttachToEntity(Profile.LocalUser, -1, Profile.LocalUser.UpVector * height, new Vector3(0, 90, 90), false, false, false, 0, true); // Make sure to only do this once. hasPlayedAnimation = false; } if (Profile.LocalUser.GetConfigFlag(60)) { Profile.LocalUser.Velocity += Vector3.WorldDown * (weight * .002f * Time.UnscaledDeltaTime); } // Set the animation speed to 0 so it loops in that pose. Profile.LocalUser.SetAnimationSpeed("random@arrests", "kneeling_arrest_get_up", 0.0f); // If we press vehicle enter again, then let's set down the vehicle. if (Profile.LocalUser.IsPlayer && Game.IsDisabledControlJustPressed(2, Control.Enter)) { Profile.LocalUser.Task.ClearAll(); Profile.LocalUser.Task.PlayAnimation("anim@mp_snowball", "pickup_snowball", 8.0f, -4.0f, 500, AnimationFlags.AllowRotation, 0.0f); GameWaiter.Wait(250); vehicle.Detach(); vehicle.SetCoordsSafely(Profile.LocalUser.Position + Profile.LocalUser.ForwardVector * 2.5f); break; } if (GetCanThrow()) { Profile.LocalUser.Task.ClearAll(); Profile.LocalUser.Task.PlayAnimation("weapons@projectile@", "throw_m_fb_stand", 8.0f, -4.0f, 500, AnimationFlags.AllowRotation, 0.1f); vehicle.Detach(); vehicle.Velocity += Profile.LocalUser.Velocity; vehicle.Velocity = Profile.GetCameraDirection() * 25000 / weight; Profile.LocalUser.Velocity = Vector3.Zero; ThrowVehicle = false; break; } Script.Yield(); } // Detach the vehicle if needed. if (vehicle.IsAttached()) { vehicle.Detach(); } vehicle.ResetAlpha(); // Clear this animation from the player if it's still playing. Profile.LocalUser.Task.ClearAnimation("random@arrests", "kneeling_arrest_get_up"); // Make sure to clear the current pickup vehicle. _currentPickupVehicle = null; var timer = DateTime.Now + new TimeSpan(0, 0, 0, 0, 600); while (DateTime.Now < timer) { vehicle.SetNoCollision(Profile.LocalUser, true); Script.Yield(); } vehicle.SetNoCollision(Profile.LocalUser, false); }
private void PunchEntity(Entity targetEntity) { //int ms = 0; Profile.LocalUser.IsCollisionProof = true; Profile.LocalUser.IsMeleeProof = true; Profile.LocalUser.Task.ClearAll(); var m = Profile.LocalUser.Model.GetDimensions(); Profile.LocalUser.SetCoordsSafely(Profile.LocalUser.Position + Vector3.WorldDown * m.Z / 2); Profile.LocalUser.Velocity = Vector3.Zero; Function.Call(Hash.SET_ENTITY_RECORDS_COLLISIONS, Profile.LocalUser.Handle, false); GetComboMoveData(out var dict, out var anim, out var duration, out var punchTime, out var bone); Profile.LocalUser.Task.PlayAnimation(dict, anim, 8.0f, -4.0f, duration, AnimationFlags.AllowRotation, 0.0f); var timer = 1f; while (timer > 0f) { timer -= Time.DeltaTime; if (Profile.LocalUser.IsRagdoll) { break; } // Continue to disable the controls. Profile.DisableControls(); if (Profile.LocalUser.IsPlayer) { Game.EnableControlThisFrame(2, Control.LookLeftRight); Game.EnableControlThisFrame(2, Control.LookUpDown); } // Cache some variables. var direction = targetEntity.Position - Profile.LocalUser.Position; Profile.LocalUser.SetAnimationSpeed(dict, anim, 1.25f); // Set the player heading towards the entity. Profile.LocalUser.Heading = direction.ToHeading(); Profile.LocalUser.Velocity = direction.Normalized * direction.Length() * 2 / 0.25f /* + targetEntity.Velocity*/; Profile.LocalUser.SetConfigFlag(60, true); Profile.LocalUser.SetConfigFlag(104, true); //ms++; //UI.ShowSubtitle(ms + "\n" + // PlayerCharacter.GetAnimationTime("melee@unarmed@streamed_core", "heavy_finishing_punch")); var boneCoord = Profile.LocalUser.GetBoneCoord(bone); if (Profile.LocalUser.GetAnimationTime(dict, anim) > punchTime) { var ray = World.RaycastCapsule(boneCoord, boneCoord, 1f, (IntersectOptions)(int)(ShapeTestFlags.IntersectObjects | ShapeTestFlags.IntersectPeds | ShapeTestFlags.IntersectVehicles), Profile.LocalUser); if (ray.DitHitEntity) { var entity = ray.HitEntity; var type = entity.GetEntityType(); ApplyDamage(direction, entity, type, boneCoord); } else if (Profile.LocalUser.IsTouching(targetEntity)) { ApplyDamage(direction, targetEntity, targetEntity.GetEntityType(), boneCoord); } break; } Script.Yield(); } Profile.LocalUser.SetConfigFlag(60, false); Profile.LocalUser.IsMeleeProof = false; Profile.LocalUser.IsCollisionProof = false; Function.Call(Hash.SET_ENTITY_RECORDS_COLLISIONS, Profile.LocalUser.Handle, true); GameWaiter.Wait(75); }
/// <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); } }
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(); } }