Forum rules - please read before posting.

Dynamic Wait Time with Progress Bar

Hello! New user to adventure creator and so far I am loving it but have run into a situation I am not sure how to handle:

What I want: Player uses item on hotspot and this will take a certain amount of time that is based on the players skill. I want the wait time to be dynamic based on this value which could change (through player improving skill) and show a UI element to fill up like a progress bar.

Example: Player uses lock pick on door to unlock it.. player has a 50% skill on lock picking, therefore it should take 3 seconds (0% takes 6, 50% takes 3, 100% takes 1.5 for example) to complete the action. While completing the action, a little progress bar shows on screen to alert how much time is left.

Is this possible with AC? If so, any ideas how to approach? If not, do I need to create a custom action or a complete c# script?

Thanks for any and all help :smile:

Comments

  • Welcome to the community, @bowersrd.

    Yes, a custom C# script is probably the best way forward - particularly since your wait time vs skill calculation isn't linear.

    This is a two-step problem: setting the correct wait time based on the skill level, and then displaying it as a timer.

    For the first, you'll want to rely on a Global Variable to store the Player's lockpicking skill so that it can be accessed from anywhere in the game. If this ranges from 0 to 100%, best to store this as a decimal with a Float variable so that calcuations are easier.

    To have a dynamic wait time based on this skill, you'll need to make use of an ActionList parameter - which allows you to dynamically alter fields inside an ActionList at runtime. A tutorial on this topic can be found here, but a more relevant example for you would be to have an Engine: Wait Action that pauses gameplay by the amount set from your skill level.

    To do this, view your Interaction ActionList's Inspector, check Use parameters?, and create a new Float parameter named e.g. "Unlock timer". If you then go ahead and create an Engine: Wait Action, you'll find that you can override its Wait time (s) field with this parameter.

    What you can then do is attach a script that calculates this parameter value at the moment the ActionList is triggered - allowing you to set it based on the Player's lockpicking skill dynamically.

    Here's a sample script that will set this using a linear scale, based on the Global Float variable that records the Player's lockpicking skill:

    using UnityEngine;
    using AC;
    
    public class SetDynamicWaitTime : MonoBehaviour
    {
    
        private void OnEnable () { EventManager.OnBeginActionList += OnBeginActionList; }
        private void OnDisable () { EventManager.OnBeginActionList -= OnBeginActionList; }
    
        private void OnBeginActionList (ActionList actionList, ActionListAsset actionListAsset, int startingIndex, bool isSkipping)
        {
            if (actionList == GetComponent<ActionList> ())
            {
                GVar skillVariable = GlobalVariables.GetVariable ("Lockpicking skill");
                float lockpickingSkill = skillVariable.IntegerValue;
                float waitTime = 6f - (lockpickingSkill * 4.5f);
                actionList.GetParameter (0).floatValue = waitTime;
            }
        }
    
    }
    

    This code assumes your Global Float variable is named "Lockpicking skill", but you can amend the code to match your own.

    If this script is attached as a component to the same GameObject as your Interaction ActionList, it'll update the "Unlock timer" parameter at the moment the ActionList is run. Try testing this out with a simple Engine: Wait Action to confirm this is all working before moving on.

    The next stage would be to display the time left as a timer. This could be a little more complicated, but I wonder if it'd be possible to make use of AC's Quick-Time Events feature to do this without the need for any more code. QTEs can be set up to show the time remaining, and the Input: QTE Action can similarly have its Duration (s) field overridden with a Float parameter.

    Depending on your needs, it may be enough to make use of this Action, set to Single Keypress, with both its Win and Fail states set to run the same thing afterwards - so that it's not something the Player technically has to "win".

    Tutorials on QTEs can be found here.

  • Wow, thank you so much for the detailed response. I didn’t even realize we could place a script as a parameter and this basically solves my other question regarding dynamics. I will give this a go! Also big thank you for the script.
  • edited August 2021

    I am having user use an item on a door to "lock pick" so the component is the hotspot and the inventory action is "lock pick" on door. GetComponent ActionList() is returning "null" in this case, I tried to skim through the scripting guide but could not find the correct alternative.

    I have the above working like a charm (but I am just having it match itself so it runs, thus throws errors with any other interaction in the game right now), sans the QTE timer as I am still working on #1 before moving to that haha.

    Thanks for any follow help :smile:

  • The script is intended to be placed on the same object as the Interaction ActionList. The ActionList can be of any scene-based ActionList type - it should still work for Hotspot Inventory interactions.

    Where is the script currently placed in the scene?

    You're not limited to having it work this way, though. This alternative exposes the ActionList it should work for in its Inspector:

    using UnityEngine;
    using AC;
    
    public class SetDynamicWaitTime : MonoBehaviour
    {
    
        public ActionList actionList;
    
        private void OnEnable () { EventManager.OnBeginActionList += OnBeginActionList; }
        private void OnDisable () { EventManager.OnBeginActionList -= OnBeginActionList; }
    
        private void OnBeginActionList (ActionList actionList, ActionListAsset actionListAsset, int startingIndex, bool isSkipping)
        {
            if (actionList == this.actionList)
            {
                GVar skillVariable = GlobalVariables.GetVariable ("Lockpicking skill");
                float lockpickingSkill = skillVariable.IntegerValue;
                float waitTime = 6f - (lockpickingSkill * 4.5f);
                actionList.GetParameter (0).floatValue = waitTime;
            }
        }
    
    }
    

    If you can share screens showing your situation, I'll try to spot where the issue lies.

  • This worked perfect. Thank you again Chris! Also just in case anyone else is looking for something similar, the QTE timer worked AWESOME. It was exactly what I needed.

    I used a run in parallel action that takes the wait parameter and runs on both the QTE and Engine: Waif so they complete at the same time and connected both to the same follow up node. I also decided to add right click to the QTE so a user could “cancel” the action, genius suggestion on your part, I would’ve never tried the QTE!
  • edited August 2021

    You're welcome, and thanks for the update!

    You may be able to simplify it further though, to just an Input: QTE Action, since you can plug the same parameter into that Action. My earlier mention of Engine: Wait was meant more as an example of how parameters can be used - it should be that the QTE will serve the same purpose.

  • Man, lol.. sometimes overthinking gets you. I didn’t even realize QTE was just needed by itself. Many thanks Chris!
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.