/// <summary> /// adds recoil to the weapon springs in response to hitting /// something /// </summary> void ApplyRecoil() { FPWeapon.StopSprings(); FPWeapon.AddForce(ImpactPositionSpringRecoil, ImpactRotationSpringRecoil); FPWeapon.AddForce2(ImpactPositionSpring2Recoil, ImpactRotationSpring2Recoil); Reset(); }
/// <summary> /// resets the weapon state to normal /// </summary> void Reset() { vp_Timer.In(0.05f, delegate() { if (FPWeapon != null) { FPWeapon.SetState(WeaponStatePull, false); FPWeapon.SetState(WeaponStateSwing, false); FPWeapon.Refresh(); if (AttackPickRandomState) { ResetState(); } } }, ResetTimer); }
/// <summary> /// applies some advanced recoil motions on the weapon when fired /// </summary> protected override void ApplyRecoil() { // return the weapon to its forward looking state by certain // position, rotation and velocity factors FPWeapon.ResetSprings(MotionPositionReset, MotionRotationReset, MotionPositionPause, MotionRotationPause); // add a positional and angular force to the weapon for one frame if (MotionRotationRecoil.z == 0.0f) { FPWeapon.AddForce2(MotionPositionRecoil, MotionRotationRecoil); // if we have positional camera recoil factor, also shake the camera if (MotionPositionRecoilCameraFactor != 0.0f) { FPCamera.AddForce2(MotionPositionRecoil * MotionPositionRecoilCameraFactor); } } else { // if we have rotation recoil around the z vector, also do dead zone logic FPWeapon.AddForce2(MotionPositionRecoil, Vector3.Scale(MotionRotationRecoil, (Vector3.one + Vector3.back)) + // recoil around x & y (((Random.value < 0.5f) ? Vector3.forward : Vector3.back) * // spin direction (left / right around z) Random.Range(MotionRotationRecoil.z * MotionRotationRecoilDeadZone, MotionRotationRecoil.z))); // spin force // if we have positional camera recoil factor, also shake the camera if (MotionPositionRecoilCameraFactor != 0.0f) { FPCamera.AddForce2(MotionPositionRecoil * MotionPositionRecoilCameraFactor); } // if we have angular camera recoil factor, also twist the camera left / right if (MotionRotationRecoilCameraFactor != 0.0f) { FPCamera.AddRollForce((Random.Range(MotionRotationRecoil.z * MotionRotationRecoilDeadZone, MotionRotationRecoil.z) // dead zone * MotionRotationRecoilCameraFactor) * // camera rotation factor ((Random.value < 0.5f) ? 1.0f : -1.0f)); // direction } } }
/// <summary> /// /// </summary> protected override void OnStart_Attack() { base.OnStart_Attack(); // set spawn position for the projectile if (Player.IsFirstPerson.Get()) { // in 1st person, don't necessarily fire the projectile from the // center of the camera, but perhaps a little bit to the right // where the arm would be Shooter.m_ProjectileSpawnPoint = FirePosition.gameObject; FirePosition.localPosition = FirePositionOffset; FirePosition.localEulerAngles = Vector3.zero; } else { // in 3rd person, always spawn the projectile exactly where the weapon is Shooter.m_ProjectileSpawnPoint = Weapon.Weapon3rdPersonModel; } // don't attempt lookdown adjustments while throwing things (it just gets crazy) FPWeapon.LookDownActive = false; // NOTE: this is restored later // as soon as the fire animation has pulled the arm out of sight, perform // some tasks in preparation for the next throw vp_Timer.In(Shooter.ProjectileSpawnDelay, delegate() { // unwield or rewield the weapon depending on inventory state if (!HaveAmmoForCurrentWeapon) // if there are no more units of this type to throw ... { // ... set the 'ReWield' state to avoid popping of the arm ... FPWeapon.SetState("ReWield"); FPWeapon.Refresh(); vp_Timer.In(1.0f, delegate() { if (!Player.SetNextWeapon.Try()) // ... then try to set the next weapon ... { // ... but if we have no other weapon: instead disarm! vp_Timer.In(0.5f, delegate() { RewindAnimation(); Player.SetWeapon.Start(0); }, m_Timer2); } }); } else // if we DO have additional units like this one ... { if (Player.IsFirstPerson.Get()) { // set the 'ReWield' state to avoid popping of the arm FPWeapon.SetState("ReWield"); FPWeapon.Refresh(); // rewind animation and restore rewield state in 1 sec vp_Timer.In(1.0f, delegate() { RewindAnimation(); FPWeapon.Rendering = true; FPWeapon.SetState("ReWield", false); FPWeapon.Refresh(); }, m_Timer3); } else { // force-stop the attack activity half a second after the throw vp_Timer.In(0.5f, delegate() { Player.Attack.Stop(); }, m_Timer4); } } }, m_Timer1); }
/// <summary> /// simulates a melee swing by carrying out a sequence of /// timers, state changes and soft forces on the weapon springs /// </summary> protected void UpdateAttack() { if (!Player.Attack.Active) { return; } if (Player.SetWeapon.Active) { return; } if (FPWeapon == null) { return; } if (!FPWeapon.Wielded) { return; } if (Time.time < m_NextAllowedSwingTime) { return; } m_NextAllowedSwingTime = Time.time + SwingRate; // enable random attack states on the melee and weapon components if (AttackPickRandomState) { PickAttack(); } // set 'raise' state (of the chosen attack state) on the weapon component FPWeapon.SetState(WeaponStatePull); FPWeapon.Refresh(); // after a short delay, swing the weapon vp_Timer.In(SwingDelay, delegate() { // play a random swing sound if (SoundSwing.Count > 0) { Audio.pitch = Random.Range(SoundSwingPitch.x, SoundSwingPitch.y) * Time.timeScale; Audio.clip = (AudioClip)SoundSwing[(int)Random.Range(0, (SoundSwing.Count))]; if (vp_Utility.IsActive(gameObject)) { Audio.Play(); } } // switch to the swing state FPWeapon.SetState(WeaponStatePull, false); FPWeapon.SetState(WeaponStateSwing); FPWeapon.Refresh(); // apply soft forces of the current attack FPWeapon.AddSoftForce(SwingPositionSoftForce, SwingRotationSoftForce, SwingSoftForceFrames); // check for target impact after a predetermined duration vp_Timer.In(ImpactTime, delegate() { // perform a sphere cast ray from center of controller, at height // of camera and along camera angle RaycastHit hit; Ray ray = new Ray(new Vector3(FPController.Transform.position.x, FPCamera.Transform.position.y, FPController.Transform.position.z), FPCamera.Transform.forward); Physics.Raycast(ray, out hit, (Bullet != null ? Bullet.Range : 2), vp_Layer.Mask.BulletBlockers); // hit something: perform impact functionality if (hit.collider != null) { if (WeaponShooter != null) { WeaponShooter.FirePosition = Camera.main.transform.position; WeaponShooter.TryFire(); } ApplyRecoil(); } else { // didn't hit anything: carry on swinging until time is up vp_Timer.In(SwingDuration - ImpactTime, delegate() { FPWeapon.StopSprings(); Reset(); }, SwingDurationTimer); } }, ImpactTimer); }, SwingDelayTimer); }