Ejemplo n.º 1
0
    public void Update(GameTime time, RobotWeaponA weapon, ref CharacterReplicatedData charRepAll, float deltaTime)
    {
        GameDebug.Assert(weapon.barrelSetup != null && weapon.barrelSetup.barrels.Length > 0, "Robotweapon has no barrels defined");

        // Initialize barrels
        if (weapon.barrelSetup.states == null)
        {
            weapon.barrelSetup.states = new GunBarrelState[weapon.barrelSetup.barrels.Length];
            for (var i = 0; i < weapon.barrelSetup.states.Length; i++)
            {
                weapon.barrelSetup.states[i].startPosition = weapon.barrelSetup.barrels[i].transform.localPosition;
                weapon.barrelSetup.states[i].animTime      = 1;
            }
        }

        // Update using chaingun ability state
        var chaingunAbility = charRepAll.FindAbilityWithComponent(EntityManager, typeof(Ability_Chaingun.InterpolatedState));

        GameDebug.Assert(chaingunAbility != Entity.Null, "AbilityController does not own a Ability_Chaingun ability");
        var chaingunInterpolatedState = EntityManager.GetComponentData <Ability_Chaingun.InterpolatedState>(chaingunAbility);

        if (weapon.primFireEvent.Update(time, chaingunInterpolatedState.fireTick))
        {
            weapon.barrelSetup.index = (weapon.barrelSetup.index + 1) % weapon.barrelSetup.barrels.Length;

            var index = weapon.barrelSetup.index;
            weapon.barrelSetup.states[index].animTime = 0;
            weapon.barrelSetup.muzzleFlash[index].Play();
            if (weapon.barrelSetup.fireSoundHandle.IsValid() && weapon.barrelSetup.fireSoundHandle.emitter.playing)
            {
                Game.SoundSystem.Stop(weapon.barrelSetup.fireSoundHandle, 0.1f);
            }
            weapon.barrelSetup.fireSoundHandle = Game.SoundSystem.Play(weapon.barrelSetup.fireSound,
                                                                       weapon.barrelSetup.muzzleFlash[index].transform.position);
        }

        // Update using grenade ability state
        var grenadeAbility = charRepAll.FindAbilityWithComponent(EntityManager, typeof(Ability_GrenadeLauncher.InterpolatedState));

        GameDebug.Assert(grenadeAbility != Entity.Null, "AbilityController does not own a Ability_GrenadeLauncher ability");
        var grenadeInterpolatedState = EntityManager.GetComponentData <Ability_GrenadeLauncher.InterpolatedState>(grenadeAbility);

        if (weapon.secFireEvent.Update(time, grenadeInterpolatedState.fireTick))
        {
            if (weapon.secondaryFireSound != null)
            {
                Game.SoundSystem.Play(weapon.secondaryFireSound, weapon.transform.position);
            }

            if (weapon.secondaryMuzzleFlash != null)
            {
                weapon.secondaryMuzzleFlash.Play();
            }
        }


        // Update using Melee ability ability state
        var meleeAbility = charRepAll.FindAbilityWithComponent(EntityManager, typeof(Ability_Melee.InterpolatedState));

        GameDebug.Assert(meleeAbility != Entity.Null, "AbilityController does not own a Ability_Melee ability");
        var meleeInterpolatedState = EntityManager.GetComponentData <Ability_Melee.InterpolatedState>(meleeAbility);

        if (weapon.meleeImpactEvent.Update(time, meleeInterpolatedState.impactTick))
        {
            if (weapon.meleeImpactSound != null)
            {
                Game.SoundSystem.Play(weapon.meleeImpactSound, weapon.transform.position);// TODO this should be hand position
            }
            if (weapon.meleeImpactEffect != null)
            {
                weapon.meleeImpactEffect.Play();
            }
        }

        // Update barrel state
        for (var i = 0; i < weapon.barrelSetup.states.Length; i++)
        {
            weapon.barrelSetup.states[i].animTime += deltaTime;
        }

        // Apply barrel state
        for (var i = 0; i < weapon.barrelSetup.states.Length; i++)
        {
            var localPos = weapon.barrelSetup.states[i].startPosition;

            var animDuration = weapon.barrelSetup.fireAnimCurve[weapon.barrelSetup.fireAnimCurve.length - 1].time;
            if (weapon.barrelSetup.states[i].animTime < animDuration)
            {
                var offset = weapon.barrelSetup.fireAnimCurve.Evaluate(weapon.barrelSetup.states[i].animTime);
                localPos.z += offset;
            }

            weapon.barrelSetup.barrels[i].transform.localPosition = localPos;
        }
    }
Ejemplo n.º 2
0
    public void Update(GameTime time, RobotWeaponA weapon, ref CharacterReplicatedData charRepAll, float deltaTime)
    {
        GameDebug.Assert(weapon.barrelSetup != null && weapon.barrelSetup.barrels.Length > 0, "Robotweapon has no barrels defined");

        // Initialize barrels
        if (weapon.barrelSetup.states == null)
        {
            weapon.barrelSetup.states = new GunBarrelState[weapon.barrelSetup.barrels.Length];
            for (var i = 0; i < weapon.barrelSetup.states.Length; i++)
            {
                weapon.barrelSetup.states[i].startPosition = weapon.barrelSetup.barrels[i].transform.localPosition;
                weapon.barrelSetup.states[i].animTime      = 1;
            }
        }

        // Update using chaingun ability state
        var chaingunAbility = charRepAll.FindAbilityWithComponent(EntityManager, typeof(Ability_Chaingun.InterpolatedState));

        GameDebug.Assert(chaingunAbility != Entity.Null, "AbilityController does not own a Ability_Chaingun ability");
        var chaingunInterpolatedState = EntityManager.GetComponentData <Ability_Chaingun.InterpolatedState>(chaingunAbility);

        if (weapon.primFireEvent.Update(time, chaingunInterpolatedState.fireTick))
        {
            weapon.barrelSetup.index = (weapon.barrelSetup.index + 1) % weapon.barrelSetup.barrels.Length;

            var index = weapon.barrelSetup.index;
            weapon.barrelSetup.states[index].animTime = 0;
            weapon.barrelSetup.muzzleFlash[index].Play();

            //-----------------------------------------------------------
            //Added by Logan 10-12-2021
            //Last updated 10-25-2021: Changed to List system like Terraformer
            //Updated 12-30-2021: Changed to fit Scriptable Objects stuff

            //Just like Robot Fire, but List-based to be more dynamic. Hoping it's more performant
            if (weapon.barrelSetup.fireSoundList == null)
            {
                weapon.barrelSetup.fireSoundList = new List <FMOD.Studio.EventInstance>();
            }
            weapon.barrelSetup.fireSoundList.Add(new FMOD.Studio.EventInstance());
            weapon.barrelSetup.currentFireSoundInstance = weapon.barrelSetup.fireSoundList.Count - 1;
            if (weapon.isThirdPerson)
            {
                weapon.barrelSetup.fireSoundList[weapon.barrelSetup.currentFireSoundInstance] = FMODUnity.RuntimeManager.CreateInstance(weapon.playerAudio.Robot_WeaponFire_3P);
            }
            else
            {
                weapon.barrelSetup.fireSoundList[weapon.barrelSetup.currentFireSoundInstance] = FMODUnity.RuntimeManager.CreateInstance(weapon.playerAudio.Robot_WeaponFire_1P);
            }

            if (weapon.barrelSetup.fireSoundList[weapon.barrelSetup.currentFireSoundInstance].isValid())
            {
                //If there's more than one item in the list, stop the last one
                //You'd think we only need the second check, but PlaybackStates can evaluate kinda funny unless you're being specific
                if (weapon.barrelSetup.currentFireSoundInstance - 1 >= 0 &&
                    PlaybackState(weapon.barrelSetup.fireSoundList[weapon.barrelSetup.currentFireSoundInstance - 1]) == FMOD.Studio.PLAYBACK_STATE.PLAYING)
                {
                    weapon.barrelSetup.fireSoundList[weapon.barrelSetup.currentFireSoundInstance - 1].stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
                }
                //Attach to the muzzle
                FMODUnity.RuntimeManager.AttachInstanceToGameObject(weapon.barrelSetup.fireSoundList[weapon.barrelSetup.currentFireSoundInstance],
                                                                    weapon.barrelSetup.muzzleFlash[index].transform);
                //And fire!
                weapon.barrelSetup.fireSoundList[weapon.barrelSetup.currentFireSoundInstance].start();
            }
            //-----------------------------------------------------------
        }

        // Update using grenade ability state
        var grenadeAbility = charRepAll.FindAbilityWithComponent(EntityManager, typeof(Ability_GrenadeLauncher.InterpolatedState));

        GameDebug.Assert(grenadeAbility != Entity.Null, "AbilityController does not own a Ability_GrenadeLauncher ability");
        var grenadeInterpolatedState = EntityManager.GetComponentData <Ability_GrenadeLauncher.InterpolatedState>(grenadeAbility);

        if (weapon.secFireEvent.Update(time, grenadeInterpolatedState.fireTick))
        {
            //Added by Logan 10-12-2021
            //Plays the grenade fire event
            if (weapon.isThirdPerson)
            {
                FMODUnity.RuntimeManager.PlayOneShotAttached(weapon.playerAudio.Robot_SecondaryFire_3P, weapon.gameObject);
            }
            else
            {
                FMODUnity.RuntimeManager.PlayOneShotAttached(weapon.playerAudio.Robot_SecondaryFire_1P, weapon.gameObject);
            }

            if (weapon.secondaryMuzzleFlash != null)
            {
                weapon.secondaryMuzzleFlash.Play();
            }
        }


        // Update using Melee ability ability state
        var meleeAbility = charRepAll.FindAbilityWithComponent(EntityManager, typeof(Ability_Melee.InterpolatedState));

        GameDebug.Assert(meleeAbility != Entity.Null, "AbilityController does not own a Ability_Melee ability");
        var meleeInterpolatedState = EntityManager.GetComponentData <Ability_Melee.InterpolatedState>(meleeAbility);

        if (weapon.meleeImpactEvent.Update(time, meleeInterpolatedState.impactTick))
        {
            //Added by Logan 10-12-2021
            //Plays the Melee event
            if (weapon.isThirdPerson)
            {
                FMODUnity.RuntimeManager.PlayOneShotAttached(weapon.playerAudio.Robot_MeleeFire_3P, weapon.gameObject);
            }
            else
            {
                FMODUnity.RuntimeManager.PlayOneShotAttached(weapon.playerAudio.Robot_MeleeFire_1P, weapon.gameObject);
            }

            if (weapon.meleeImpactEffect != null)
            {
                weapon.meleeImpactEffect.Play();
            }
        }

        // Update barrel state
        for (var i = 0; i < weapon.barrelSetup.states.Length; i++)
        {
            weapon.barrelSetup.states[i].animTime += deltaTime;
        }

        // Apply barrel state
        for (var i = 0; i < weapon.barrelSetup.states.Length; i++)
        {
            var localPos = weapon.barrelSetup.states[i].startPosition;

            var animDuration = weapon.barrelSetup.fireAnimCurve[weapon.barrelSetup.fireAnimCurve.length - 1].time;
            if (weapon.barrelSetup.states[i].animTime < animDuration)
            {
                var offset = weapon.barrelSetup.fireAnimCurve.Evaluate(weapon.barrelSetup.states[i].animTime);
                localPos.z += offset;
            }

            weapon.barrelSetup.barrels[i].transform.localPosition = localPos;
        }
    }
Ejemplo n.º 3
0
    void Update(GameTime time, TerraformerWeaponA weapon, ref CharacterReplicatedData charRepAll)
    {
        // Update using AutoRifle ability state
        var autoRifleAbility = charRepAll.FindAbilityWithComponent(EntityManager, typeof(Ability_AutoRifle.InterpolatedState));

        GameDebug.Assert(autoRifleAbility != Entity.Null, "AbilityController does not own a Ability_AutoRifle ability");
        var autoRifleInterpolatedState = EntityManager.GetComponentData <Ability_AutoRifle.InterpolatedState>(autoRifleAbility);

        if (weapon.primaryFireEvent.Update(time, autoRifleInterpolatedState.fireTick))
        {
            if (weapon.primaryFireSound != null)
            {
                if (weapon.primaryFireSoundHandle.IsValid() && weapon.primaryFireSoundHandle.emitter.playing)
                {
                    Game.SoundSystem.Stop(weapon.primaryFireSoundHandle, 0.05f);
                }
                weapon.primaryFireSoundHandle = Game.SoundSystem.Play(weapon.primaryFireSound, weapon.muzzle);
            }

            if (weapon.primaryMuzzleFlash != null)
            {
                weapon.primaryMuzzleFlash.Play();
            }

            if (weapon.hitscanEffect != null)
            {
                World.GetExistingSystem <HandleHitscanEffectRequests>().Request(weapon.hitscanEffect,
                                                                                weapon.muzzle.position, autoRifleInterpolatedState.fireEndPos);
            }

            if (autoRifleInterpolatedState.impactType != Ability_AutoRifle.ImpactType.None)
            {
                var rotation = Quaternion.LookRotation(autoRifleInterpolatedState.impactNormal);
                if (autoRifleInterpolatedState.impactType == Ability_AutoRifle.ImpactType.Character)
                {
                    World.GetExistingSystem <HandleSpatialEffectRequests>().Request(weapon.characterImpactEffect,
                                                                                    autoRifleInterpolatedState.fireEndPos, rotation);
                }
                else
                {
                    World.GetExistingSystem <HandleSpatialEffectRequests>().Request(weapon.environmentImpactEffect,
                                                                                    autoRifleInterpolatedState.fireEndPos, rotation);
                }
            }
        }

        // Update using ProjectileLauncher ability state
        var rocketAbility = charRepAll.FindAbilityWithComponent(EntityManager, typeof(Ability_ProjectileLauncher.InterpolatedState));

        GameDebug.Assert(rocketAbility != Entity.Null, "AbilityController does not own a Ability_ProjectileLauncher ability");
        var rocketLaunchInterpolatedState = EntityManager.GetComponentData <Ability_ProjectileLauncher.InterpolatedState>(rocketAbility);

        if (weapon.secondaryFireEvent.Update(time, rocketLaunchInterpolatedState.fireTick))
        {
            if (weapon.secondaryFireSound != null)
            {
                Game.SoundSystem.Play(weapon.secondaryFireSound, weapon.muzzle);
            }

            if (weapon.secondaryMuzzleFlash != null)
            {
                weapon.secondaryMuzzleFlash.Play();
            }
        }

        // Update using Melee ability ability state
        var meleeAbility = charRepAll.FindAbilityWithComponent(EntityManager, typeof(Ability_Melee.InterpolatedState));

        GameDebug.Assert(meleeAbility != Entity.Null, "AbilityController does not own a Ability_Melee ability");
        var meleeInterpolatedState = EntityManager.GetComponentData <Ability_Melee.InterpolatedState>(meleeAbility);

        if (weapon.meleeImpactEvent.Update(time, meleeInterpolatedState.impactTick))
        {
            if (weapon.meleeImpactSound != null)
            {
                Game.SoundSystem.Play(weapon.meleeImpactSound, weapon.transform.position);
            }

            if (weapon.meleeImpactEffect != null)
            {
                weapon.meleeImpactEffect.Play();
            }
        }



        // Vents disabled vents until we find out what to do with them
        // Update vents
//            if (entity.vents != null)
//            {
//                for (int ventIndex = 0; ventIndex < entity.vents.Length; ventIndex++)
//                {
//                    if (entity.ventRotationSpeed[ventIndex] == 0)
//                        continue;
//
//                    // Rotate
//                    float deltaRot = entity.ventRotationSpeed[ventIndex] * m_world.frameDuration;
//                    Vector3 eulerRot = entity.vents[ventIndex].rotation.eulerAngles;
//                    eulerRot.z += deltaRot;
//                    entity.vents[ventIndex].rotation = Quaternion.Euler(eulerRot);
//
//                    // Damp speed
//                    float deltaSpeed = entity.ventDampSpeed * m_world.frameDuration;
//                    float absSpeed = Mathf.Abs(entity.ventRotationSpeed[ventIndex]);
//                    if (deltaSpeed >= absSpeed)
//                        entity.ventRotationSpeed[ventIndex] = 0;
//                    else
//                        entity.ventRotationSpeed[ventIndex] -= Mathf.Sign(entity.ventRotationSpeed[ventIndex]) * deltaSpeed;
//                }
//
//                Character.State.Action newAction = weapon.action;
//                if (newAction != entity.m_prevAction)
//                {
//                    if (newAction == Character.State.Action.PrimaryFire)
//                    {
//                        entity.ventRotationSpeed[entity.nextVentIndex] = entity.ventStartSpeed;
//                        entity.ventRotationSpeed[entity.nextVentIndex + 1] = -entity.ventStartSpeed;
//                        entity.nextVentIndex = (entity.nextVentIndex + 2) % entity.vents.Length;
//                    }
//                    if (newAction == Character.State.Action.SecondaryFire)
//                    {
//                        entity.timelineGrenadeRefill.time = 0;
//                        entity.timelineGrenadeRefill.Play();
//                    }
//
//                    entity.m_prevAction = newAction;
//                }
//            }


        // Velocity based ammo fuel angle
        if (weapon.grenadeFuelBase != null)
        {
            Vector3 basePos = weapon.grenadeFuelBase.position;
            Vector3 moveVec = basePos - weapon.m_lastGrenadeFuelWorldPos;
            weapon.m_lastGrenadeFuelWorldPos = basePos;

            Vector3    rotateAxis = Vector3.Cross(moveVec, Vector3.up).normalized;
            float      moveVel    = moveVec.magnitude / m_world.frameDuration;
            float      angle      = moveVel * 2;
            Quaternion targetRot  = Quaternion.AngleAxis(-angle, rotateAxis);

            weapon.grenadeFuelBase.rotation = Quaternion.Lerp(weapon.grenadeFuelBase.rotation, targetRot, 3 * m_world.frameDuration);
        }
    }
Ejemplo n.º 4
0
    void Update(GameTime time, TerraformerWeaponA weapon, ref CharacterReplicatedData charRepAll)
    {
        // Update using AutoRifle ability state
        var autoRifleAbility = charRepAll.FindAbilityWithComponent(EntityManager, typeof(Ability_AutoRifle.InterpolatedState));

        GameDebug.Assert(autoRifleAbility != Entity.Null, "AbilityController does not own a Ability_AutoRifle ability");
        var autoRifleInterpolatedState = EntityManager.GetComponentData <Ability_AutoRifle.InterpolatedState>(autoRifleAbility);

        if (weapon.primaryFireEvent.Update(time, autoRifleInterpolatedState.fireTick))
        {
            //if(weapon.primaryFireSound != null)
            //{
            //    if (weapon.primaryFireSoundHandle.IsValid() && weapon.primaryFireSoundHandle.emitter.playing)
            //        Game.SoundSystem.Stop(weapon.primaryFireSoundHandle, 0.05f);
            //    weapon.primaryFireSoundHandle = Game.SoundSystem.Play(weapon.primaryFireSound, weapon.muzzle);
            //}

            //-----------------------------------------------------------
            //Added by Logan 10-16-2021
            //Just like Robot Fire, but List-based to be more dynamic. Hoping it's more performant.
            if (weapon.primaryFireSoundList == null)
            {
                weapon.primaryFireSoundList = new List <FMOD.Studio.EventInstance>();
            }
            weapon.primaryFireSoundList.Add(new FMOD.Studio.EventInstance());
            weapon.currentFireSoundInstance = weapon.primaryFireSoundList.Count - 1;
            if (weapon.isThirdPerson)
            {
                weapon.primaryFireSoundList[weapon.currentFireSoundInstance] = FMODUnity.RuntimeManager.CreateInstance(weapon.playerAudio.Girl_WeaponFire_3P);
            }
            else
            {
                weapon.primaryFireSoundList[weapon.currentFireSoundInstance] = FMODUnity.RuntimeManager.CreateInstance(weapon.playerAudio.Girl_WeaponFire_1P);
            }

            if (weapon.primaryFireSoundList[weapon.currentFireSoundInstance].isValid())
            {
                //If there's more than one item in the list, stop the last one
                //Might only need the second check, as it wouldn't evaluate right if it got a negative index
                if (weapon.currentFireSoundInstance - 1 >= 0 &&
                    PlaybackState(weapon.primaryFireSoundList[weapon.currentFireSoundInstance - 1]) == FMOD.Studio.PLAYBACK_STATE.PLAYING)
                {
                    weapon.primaryFireSoundList[weapon.currentFireSoundInstance - 1].stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
                }
                //Attach to the muzzle
                FMODUnity.RuntimeManager.AttachInstanceToGameObject(weapon.primaryFireSoundList[weapon.currentFireSoundInstance], weapon.muzzle);
                //And fire!
                weapon.primaryFireSoundList[weapon.currentFireSoundInstance].start();
            }

            if (weapon.primaryMuzzleFlash != null)
            {
                weapon.primaryMuzzleFlash.Play();
            }

            if (weapon.hitscanEffect != null)
            {
                World.GetExistingManager <HandleHitscanEffectRequests>().Request(weapon.hitscanEffect,
                                                                                 weapon.muzzle.position, autoRifleInterpolatedState.fireEndPos);
            }

            if (autoRifleInterpolatedState.impactType != Ability_AutoRifle.ImpactType.None)
            {
                var rotation = Quaternion.LookRotation(autoRifleInterpolatedState.impactNormal);
                if (autoRifleInterpolatedState.impactType == Ability_AutoRifle.ImpactType.Character)
                {
                    World.GetExistingManager <HandleSpatialEffectRequests>().Request(weapon.characterImpactEffect,
                                                                                     autoRifleInterpolatedState.fireEndPos, rotation);
                }
                else
                {
                    World.GetExistingManager <HandleSpatialEffectRequests>().Request(weapon.environmentImpactEffect,
                                                                                     autoRifleInterpolatedState.fireEndPos, rotation);
                }
            }
        }

        // Update using ProjectileLauncher ability state
        var rocketAbility = charRepAll.FindAbilityWithComponent(EntityManager, typeof(Ability_ProjectileLauncher.InterpolatedState));

        GameDebug.Assert(rocketAbility != Entity.Null, "AbilityController does not own a Ability_ProjectileLauncher ability");
        var rocketLaunchInterpolatedState = EntityManager.GetComponentData <Ability_ProjectileLauncher.InterpolatedState>(rocketAbility);

        if (weapon.secondaryFireEvent.Update(time, rocketLaunchInterpolatedState.fireTick))
        {
            //if(weapon.secondaryFireSound != null)
            //    Game.SoundSystem.Play(weapon.secondaryFireSound, weapon.muzzle);

            //Added by Logan, 10-16-2021
            //Updated 12-30-2021
            if (weapon.isThirdPerson)
            {
                FMODUnity.RuntimeManager.PlayOneShotAttached(weapon.playerAudio.Girl_SecondaryFire_3P, weapon.muzzle.gameObject);
            }
            else
            {
                FMODUnity.RuntimeManager.PlayOneShotAttached(weapon.playerAudio.Girl_SecondaryFire_1P, weapon.muzzle.gameObject);
            }


            if (weapon.secondaryMuzzleFlash != null)
            {
                weapon.secondaryMuzzleFlash.Play();
            }
        }

        // Update using Melee ability ability state
        var meleeAbility = charRepAll.FindAbilityWithComponent(EntityManager, typeof(Ability_Melee.InterpolatedState));

        GameDebug.Assert(meleeAbility != Entity.Null, "AbilityController does not own a Ability_Melee ability");
        var meleeInterpolatedState = EntityManager.GetComponentData <Ability_Melee.InterpolatedState>(meleeAbility);

        if (weapon.meleeImpactEvent.Update(time, meleeInterpolatedState.impactTick))
        {
            //if(weapon.meleeImpactSound != null)
            //    Game.SoundSystem.Play(weapon.meleeImpactSound, weapon.transform.position);

            //Added by Logan, 10-16-2021
            if (weapon.isThirdPerson)
            {
                FMODUnity.RuntimeManager.PlayOneShotAttached(weapon.playerAudio.Girl_MeleeFire_3P, weapon.gameObject);
            }
            else
            {
                FMODUnity.RuntimeManager.PlayOneShotAttached(weapon.playerAudio.Girl_MeleeFire_1P, weapon.gameObject);
            }

            if (weapon.meleeImpactEffect != null)
            {
                weapon.meleeImpactEffect.Play();
            }
        }



        // Vents disabled vents until we find out what to do with them
        // Update vents
        //            if (entity.vents != null)
        //            {
        //                for (int ventIndex = 0; ventIndex < entity.vents.Length; ventIndex++)
        //                {
        //                    if (entity.ventRotationSpeed[ventIndex] == 0)
        //                        continue;
        //
        //                    // Rotate
        //                    float deltaRot = entity.ventRotationSpeed[ventIndex] * m_world.frameDuration;
        //                    Vector3 eulerRot = entity.vents[ventIndex].rotation.eulerAngles;
        //                    eulerRot.z += deltaRot;
        //                    entity.vents[ventIndex].rotation = Quaternion.Euler(eulerRot);
        //
        //                    // Damp speed
        //                    float deltaSpeed = entity.ventDampSpeed * m_world.frameDuration;
        //                    float absSpeed = Mathf.Abs(entity.ventRotationSpeed[ventIndex]);
        //                    if (deltaSpeed >= absSpeed)
        //                        entity.ventRotationSpeed[ventIndex] = 0;
        //                    else
        //                        entity.ventRotationSpeed[ventIndex] -= Mathf.Sign(entity.ventRotationSpeed[ventIndex]) * deltaSpeed;
        //                }
        //
        //                Character.State.Action newAction = weapon.action;
        //                if (newAction != entity.m_prevAction)
        //                {
        //                    if (newAction == Character.State.Action.PrimaryFire)
        //                    {
        //                        entity.ventRotationSpeed[entity.nextVentIndex] = entity.ventStartSpeed;
        //                        entity.ventRotationSpeed[entity.nextVentIndex + 1] = -entity.ventStartSpeed;
        //                        entity.nextVentIndex = (entity.nextVentIndex + 2) % entity.vents.Length;
        //                    }
        //                    if (newAction == Character.State.Action.SecondaryFire)
        //                    {
        //                        entity.timelineGrenadeRefill.time = 0;
        //                        entity.timelineGrenadeRefill.Play();
        //                    }
        //
        //                    entity.m_prevAction = newAction;
        //                }
        //            }


        // Velocity based ammo fuel angle
        if (weapon.grenadeFuelBase != null)
        {
            Vector3 basePos = weapon.grenadeFuelBase.position;
            Vector3 moveVec = basePos - weapon.m_lastGrenadeFuelWorldPos;
            weapon.m_lastGrenadeFuelWorldPos = basePos;

            Vector3    rotateAxis = Vector3.Cross(moveVec, Vector3.up).normalized;
            float      moveVel    = moveVec.magnitude / m_world.frameDuration;
            float      angle      = moveVel * 2;
            Quaternion targetRot  = Quaternion.AngleAxis(-angle, rotateAxis);

            weapon.grenadeFuelBase.rotation = Quaternion.Lerp(weapon.grenadeFuelBase.rotation, targetRot, 3 * m_world.frameDuration);
        }
    }