// -----------------------------------------------------------------------------------
    // Update
    // -----------------------------------------------------------------------------------
    private void Update()
    {
        Player player = Player.localPlayer;

        if (!player)
        {
            return;
        }

        // hotkey (not while typing in chat, etc.)
        if (Input.GetKeyDown(hotKey) && !UIUtils.AnyInputActive())
        {
            panel.SetActive(!panel.activeSelf);
        }

        if (panel.activeSelf)
        {
            List <UCE_Quest> activeQuests = new List <UCE_Quest>();

            if (showActiveQuests)
            {
                activeQuests = player.UCE_quests.Where(q => !q.completed || (q.repeatable > 0 && !q.completedAgain)).ToList();
            }
            else
            {
                activeQuests = player.UCE_quests.Where(q => q.completed).ToList();
            }

            if (cacheTimer == null || cacheTimer.Length != activeQuests.Count)
            {
                cacheTooltip = new string[player.UCE_quests.Count];
                cacheTimer   = new float[player.UCE_quests.Count];
            }

            UIUtils.BalancePrefabs(slotPrefab.gameObject, activeQuests.Count, content);

            // -- refresh all
            for (int i = 0; i < activeQuests.Count; ++i)
            {
                int index              = i;
                UCE_UI_QuestSlot slot  = content.GetChild(index).GetComponent <UCE_UI_QuestSlot>();
                UCE_Quest        quest = activeQuests[index];

                // -- check cache
                if (Time.time > cacheTimer[index])
                {
                    // =======================================================================

                    // -- check gathered items
                    int[] gathered = player.checkGatheredItems(quest);

                    // -- check explored areas
                    int explored = 0;
#if _iMMOEXPLORATION
                    foreach (UCE_Area_Exploration area in quest.exploreTarget)
                    {
                        if (player.UCE_HasExploredArea(area))
                        {
                            explored++;
                        }
                    }
#endif

                    // -- check faction requirement
                    bool factionRequirementsMet = true;
#if _iMMOFACTIONS
                    factionRequirementsMet = player.UCE_CheckFactionRating(quest.factionRequirement);
#endif

                    // =======================================================================

                    // name button
                    GameObject descriptionPanel = slot.descriptionText.gameObject;
                    string     prefix           = descriptionPanel.activeSelf ? hidePrefix : expandPrefix;
                    slot.nameButton.GetComponentInChildren <Text>().text = prefix + quest.name;

                    if (showActiveQuests)
                    {
                        if (quest.IsFulfilled(gathered, explored, factionRequirementsMet))
                        {
                            slot.nameButton.GetComponent <Image>().color = fulfilledQuestColor;
                        }
                        else
                        {
                            slot.nameButton.GetComponent <Image>().color = inprogressQuestColor;
                        }
                    }
                    else
                    {
                        slot.nameButton.GetComponent <Image>().color = fulfilledQuestColor;
                    }

                    slot.nameButton.onClick.SetListener(() =>
                    {
                        descriptionPanel.SetActive(!descriptionPanel.activeSelf);
                    });

                    // -- cancel button
                    if (showActiveQuests)
                    {
                        slot.cancelButton.gameObject.SetActive(true);
                        slot.cancelButton.onClick.SetListener(() =>
                        {
                            cancelQuestPanel.Show(quest.name);
                        });
                    }
                    else
                    {
                        slot.cancelButton.gameObject.SetActive(false);
                    }

                    // -- update cache
                    cacheTooltip[index] = quest.ToolTip(gathered, explored, factionRequirementsMet);
                    cacheTimer[index]   = Time.time + cacheInterval;

                    // -- update description
                    slot.descriptionText.text = cacheTooltip[index];
                }
            }
        }
    }
    // -----------------------------------------------------------------------------------
    // Update
    // -----------------------------------------------------------------------------------
    private void Update()
    {
        Player player = Player.localPlayer;

        if (!player)
        {
            return;
        }

        if (player.target != null && player.target is Npc &&
            Utils.ClosestDistance(player.collider, player.target.collider) <= player.interactionRange)
        {
            Npc npc = (Npc)player.target;

            List <UCE_ScriptableQuest> questsAvailable = npc.UCE_QuestsVisibleFor(player);

            UIUtils.BalancePrefabs(slotPrefab.gameObject, questsAvailable.Count, content);

            // refresh all
            for (int i = 0; i < questsAvailable.Count; ++i)
            {
                UCE_UI_NpcQuestSlot slot = content.GetChild(i).GetComponent <UCE_UI_NpcQuestSlot>();

                // find quest index in original npc quest list (unfiltered)
                int npcIndex = Array.FindIndex(npc.UCE_quests, q => q.name == questsAvailable[i].name);

                // find quest index in player quest list
                int questIndex = player.UCE_GetQuestIndexByName(npc.UCE_quests[npcIndex].name);

                if (questIndex != -1)
                {
                    UCE_Quest quest = player.UCE_quests[questIndex];

                    // -- quest must be acceptable or complete-able to show
                    if (player.UCE_CanRestartQuest(quest.data) || player.UCE_CanAcceptQuest(quest.data) || player.UCE_CanCompleteQuest(quest.name))
                    {
                        ScriptableItem reward = null;
                        int            amount = 0;
                        if (npc.UCE_quests[npcIndex].questRewards.Length > 0 &&
                            npc.UCE_quests[npcIndex].questRewards[0].rewardItem.Length > 0)
                        {
                            reward = npc.UCE_quests[npcIndex].questRewards[0].rewardItem[0].item;
                            amount = npc.UCE_quests[npcIndex].questRewards[0].rewardItem[0].amount;
                        }

                        int gathered = 0;
                        foreach (UCE_gatherTarget gatherTarget in npc.UCE_quests[npcIndex].gatherTarget)
                        {
                            gathered += player.InventoryCount(new Item(gatherTarget.target));
                        }

                        // -- check explored areas
                        int explored = 0;
#if _iMMOEXPLORATION
                        foreach (UCE_Area_Exploration area in quest.exploreTarget)
                        {
                            if (player.UCE_HasExploredArea(area))
                            {
                                explored++;
                            }
                        }
#endif

                        // -- check faction requirement
                        bool factionRequirementsMet = true;
#if _iMMOFACTIONS
                        factionRequirementsMet = player.UCE_CheckFactionRating(quest.factionRequirement);
#endif
                        // -- check has space
                        bool hasSpace = player.getHasEnoughSpace(quest);

                        // -- set gameobject active
                        slot.gameObject.SetActive(true);

                        // -- name button
                        GameObject descriptionText = slot.descriptionText.gameObject;
                        string     prefix          = descriptionText.activeSelf ? hidePrefix : expandPrefix;

                        slot.nameButton.GetComponentInChildren <Text>().text = prefix + quest.name;
                        slot.nameButton.onClick.SetListener(() =>
                        {
                            descriptionText.SetActive(!descriptionText.activeSelf);
                        });

                        // description + not enough space warning (if needed)
                        slot.descriptionText.text = quest.ToolTip(player.checkGatheredItems(quest), explored, factionRequirementsMet);
                        if (!hasSpace)
                        {
                            slot.descriptionText.text += "\n<color=red>" + notEnoughSpace + "</color>";
                        }

                        if (player.UCE_CanAcceptQuest(quest.data))
                        {
                            // repeatable quest
                            slot.actionButton.interactable = true;
                            slot.actionButton.GetComponentInChildren <Text>().text = acceptButton;
                            slot.actionButton.onClick.SetListener(() =>
                            {
                                player.Cmd_UCE_AcceptQuest(npcIndex);
                            });
                        }
                        else
                        {
                            slot.actionButton.interactable = player.UCE_CanCompleteQuest(quest.name) && hasSpace;
                            slot.actionButton.GetComponentInChildren <Text>().text = completeButton;
                            slot.actionButton.onClick.SetListener(() =>
                            {
                                player.Cmd_UCE_CompleteQuest(npcIndex);
                                panel.SetActive(false);
                            });
                        }
                    }
                    else
                    {
                        // -- deactivate slot
                        slot.gameObject.SetActive(false);
                    }
                }
                else
                {
                    UCE_Quest quest = new UCE_Quest(npc.UCE_quests[npcIndex]);

                    // -- set gameobject active
                    slot.gameObject.SetActive(true);

                    // -- name button
                    GameObject descriptionText = slot.descriptionText.gameObject;
                    string     prefix          = descriptionText.activeSelf ? hidePrefix : expandPrefix;
                    slot.nameButton.GetComponentInChildren <Text>().text = prefix + quest.name;
                    slot.nameButton.onClick.SetListener(() =>
                    {
                        descriptionText.SetActive(!descriptionText.activeSelf);
                    });

                    // -- new quest
                    slot.descriptionText.text      = quest.ToolTip(player.checkGatheredItems(quest));
                    slot.actionButton.interactable = true;
                    slot.actionButton.GetComponentInChildren <Text>().text = acceptButton;
                    slot.actionButton.onClick.SetListener(() =>
                    {
                        player.Cmd_UCE_AcceptQuest(npcIndex);
                    });
                }
            }
        }
        else
        {
            panel.SetActive(false);
        }
    }