Permanently equipped flashlight

SeeSharpist

New member
Hey guys, I'm wondering if there is a way ootb to create a flashlight that's always equipped and toggled by a key, say L. Nothing fancy, no animations, just toggle on, toggle off. I think it'd be similar to this post, where they want to have two items equipped in slots 0 and 1, but grenades always equipped and available in a new slot. https://www.opsive.com/forum/index.php?threads/having-trouble-with-grenades-and-dual-wielding.4136/ Similarly, the player should be able to flip the light on and off no matter what item is equipped.

I tried creating a Gameobject as a flashlight for slot 2, the slot is attached to my helmet so the light would follow where I look when on. I can't seem to get it to equip though. I'm using the Ultimate Inventory System, which complicates it a bit more. Does it need it's own ItemCollection in the inventory with a toggle or equip/unequip for the inventory specifically? Not sure of the best way to go about that. Attached the setup for the UIS item, the Slot 2 use skill and the flashlight script on the flashlight prefab. Thanks!
 

Attachments

  • flashlightsetup.png
    flashlightsetup.png
    171.2 KB · Views: 11
Out of curiosity, if you simply need to toggle a light on and off without any character animation, wouldn't it be easier to just toggle a spot light game object on/off instead of using a UCC Item? That would be the easiest way to do it, as long as you always have the flashlight equipped.

You could check that the flashlight Item is in your inventory using UIS, without worrying about the UCC side of things.

If you really want to use the the UCC flashlight item, another solution would be to do something similar to how we added magic items in the UCC+UIS integration demo. If you check the character in the integration demo, you'll see that we have a third slot for magic. Having a third slot lets you equip another item in parallel to the right and left hand, and you can place the equipped item on the characters head quite easily.
 
Just to follow up, I ended up combining the Flashlight script with Ability and it seems to work fairly well. only bug I need to work out is that disabling the Battery AttrModifier doesn't flip the attribute back to Increase like it started on. a negative value works just as well though.

I looked into the Magic slot you mentioned as well and plan on using it for something else, thanks!


C#:
using Opsive.Shared.Events;
using Opsive.Shared.Game;
using Opsive.UltimateCharacterController.Character;
using Opsive.UltimateCharacterController.Character.Abilities;
using Opsive.UltimateCharacterController.Items;
using Opsive.UltimateCharacterController.Items.Actions.PerspectiveProperties;
using Opsive.UltimateCharacterController.Traits;
using UnityEngine;

/// <summary>
/// The Suit Light Toggle ability allows the character toggle a light on their character on or off.
/// </summary>
[DefaultInputName("Flashlight")]
[DefaultStartType(AbilityStartType.ButtonDown)]
[DefaultStopType(AbilityStopType.Automatic)]
public class SuitLightToggle : Ability
{
    [Tooltip("Is the ability a concurrent ability?")]
    [SerializeField] protected bool m_ConcurrentAbility = true;

    //[Tooltip("The name of the health attribute.")]
    //[SerializeField] protected string m_HealthAttributeName = "Health";

    [Tooltip("The battery attribute that should be modified when the flashlight is active.")]
        [HideInInspector] [SerializeField] protected AttributeModifier m_BatteryModifier = new AttributeModifier("Battery", 0, Attribute.AutoUpdateValue.Decrease);

        public AttributeModifier BatteryModifier { get { return m_BatteryModifier; } set { m_BatteryModifier = value; } }

        private IFlashlightPerspectiveProperties m_FlashlightPerpectiveProperties;

        protected ItemPerspectiveProperties m_ActivePerspectiveProperties;

        protected ItemPerspectiveProperties m_FirstPersonPerspectiveProperties;
        protected ItemPerspectiveProperties m_ThirdPersonPerspectiveProperties;

    public bool ConcurrentAbility { get { return m_ConcurrentAbility; } set { m_ConcurrentAbility = value; } }

    public override bool IsConcurrent { get { return m_ConcurrentAbility; } }

    /// <summary>
    /// Initialize the collider storage arrays.
    /// </summary>
    public override void Start()
    {
        base.Start();

         m_CharacterLocomotion = m_GameObject.GetCachedComponent<UltimateCharacterLocomotion>();
         Debug.Log(m_CharacterLocomotion.FirstPersonPerspective);
         var perspectiveProperties = m_CharacterLocomotion.gameObject.GetComponents<ItemPerspectiveProperties>();
            for (int i = 0; i < perspectiveProperties.Length; ++i) {
                if (perspectiveProperties[i].FirstPersonItem) {
                    m_FirstPersonPerspectiveProperties = perspectiveProperties[i];
                } else {
                    m_ThirdPersonPerspectiveProperties = perspectiveProperties[i];
                }
            }
            m_ActivePerspectiveProperties = m_CharacterLocomotion.FirstPersonPerspective ? m_FirstPersonPerspectiveProperties : m_ThirdPersonPerspectiveProperties;

        m_FlashlightPerpectiveProperties = m_ActivePerspectiveProperties as IFlashlightPerspectiveProperties;

            if (m_BatteryModifier != null) {
                if (m_BatteryModifier.Initialize(m_CharacterLocomotion.gameObject)) {
                    EventHandler.RegisterEvent(m_BatteryModifier.Attribute, "OnAttributeReachedDestinationValue", OnBatteryEmpty);
                }
            }

        if (m_FlashlightPerpectiveProperties == null) {
                m_FlashlightPerpectiveProperties = m_ActivePerspectiveProperties as IFlashlightPerspectiveProperties;

                if (m_FlashlightPerpectiveProperties == null) {
                    Debug.LogError("Error: The First/Third Person Flashlight Item Properties component cannot be found ." +
                                   "Ensure the component exists and the component's Action ID matches the Action ID )");
                }
            }
        EventHandler.RegisterEvent<bool>(m_CharacterLocomotion.gameObject, "OnCharacterChangePerspectives", OnChangePerspectives);
    }

    /// <summary>
    /// Called when the ablity is tried to be started. If false is returned then the ability will not be started.
    /// </summary>
    /// <returns>True if the ability can be started.</returns>
    public override bool CanStartAbility()
    {
        // An attribute may prevent the ability from starting.
        if (!base.CanStartAbility()) {
            return false;
        }

        // The flashlight can't be used if there is no battery left.
        if (m_BatteryModifier != null && !m_BatteryModifier.IsValid()) {
            return false;
        }

        return true;
    }

    /// <summary>
    /// The ability has started.
    /// </summary>
    protected override void AbilityStarted()
    {
        base.AbilityStarted();
        //ToggleFlashlight(!m_FlashlightPerpectiveProperties.Light.activeSelf);
        ToggleFlashlight(true);

    }

    /// <summary>
    /// Can the ability be stopped?
    /// </summary>
    /// <returns>True if the ability can be stopped.</returns>
    public override bool CanStopAbility()
    {
        return base.CanStopAbility();
    }

    /// <summary>
    /// Called when another ability is attempting to start and the current ability is active.
    /// Returns true or false depending on if the new ability should be blocked from starting.
    /// </summary>
    /// <param name="startingAbility">The ability that is starting.</param>
    /// <returns>True if the ability should be blocked.</returns>
    public override bool ShouldBlockAbilityStart(Ability startingAbility)
    {
        return false;
    }

    /// <summary>
    /// Called when the current ability is attempting to start and another ability is active.
    /// Returns true or false depending on if the active ability should be stopped.
    /// </summary>
    /// <param name="activeAbility">The ability that is currently active.</param>
    public override bool ShouldStopActiveAbility(Ability activeAbility)
    {
        return false;
    }

    /// <summary>
    /// The ability has stopped running.
    /// </summary>
    /// <param name="force">Was the ability force stopped?</param>
    protected override void AbilityStopped(bool force)
    {
        AbilityStopped(force, true);
        ToggleFlashlight(false);
    }

    /// <summary>
    /// The ability has stopped running.
    /// </summary>
    /// <param name="force">Was the ability force stopped?</param>
    /// <param name="resetStoredInputs">Should the capsule collider height be reset?</param>
    protected void AbilityStopped(bool force, bool resetCapsuleColliderHeight)
    {
        base.AbilityStopped(force);
        ToggleFlashlight(false);
        
    }

    /// <summary>
    /// The flashlight battery is empty.
    /// </summary>
    private void OnBatteryEmpty()
    {
        AbilityStopped(true, false);
        //ToggleFlashlight(false);
    }

    // <summary>
    /// Activates or deactives the flashlight.
    /// </summary>
    /// <param name="active">Should the flashlight be activated?</param>
    public void ToggleFlashlight(bool active)
    {
        m_FlashlightPerpectiveProperties.Light.SetActive(active);
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
        if (m_NetworkInfo != null) {
            if (!m_NetworkInfo.IsLocalPlayer()) {
                return;
            }
            m_NetworkCharacter.ToggleFlashlight(this, active);
        }
#endif
        if (m_BatteryModifier != null) {
            m_BatteryModifier.EnableModifier(active);
        }
    }

    /// <summary>
        /// The character perspective between first and third person has changed.
        /// </summary>
        /// <param name="firstPersonPerspective">Is the character in a first person perspective?</param>
        protected void OnChangePerspectives(bool firstPersonPerspective)
        {
            m_ActivePerspectiveProperties = firstPersonPerspective ? m_FirstPersonPerspectiveProperties : m_ThirdPersonPerspectiveProperties;

            var active = m_FlashlightPerpectiveProperties.Light.activeSelf;
            m_FlashlightPerpectiveProperties.Light.SetActive(false);
            m_FlashlightPerpectiveProperties = m_ActivePerspectiveProperties as IFlashlightPerspectiveProperties;
            if (active) {
                m_FlashlightPerpectiveProperties.Light.SetActive(true);
            }
        }
}
 
Top