/// <summary>
        /// Assigns a new QuestResourceBehaviour component if this is a Questor NPC.
        /// Can happen either at runtime or during scene layout.
        /// </summary>
        public void AssignQuestResourceBehaviour()
        {
            // Static NPC data must match a known questor Person resource
            Person questorPerson = QuestMachine.Instance.ActiveQuestor(Data);

            if (questorPerson == null)
            {
                return;
            }

            // Can only have a single QuestResourceBehaviour
            if (GetComponent <QuestResourceBehaviour>())
            {
                return;
            }

            // Assign new QuestResourceBehaviour and link to Person resource in quest system
            QuestResourceBehaviour resourceBehaviour = gameObject.AddComponent <QuestResourceBehaviour>();

            if (resourceBehaviour)
            {
                resourceBehaviour.AssignResource(questorPerson);
                Debug.LogFormat("Added new QuestResourceBehaviour to object {0} and assigned Questor Person resource {1}", gameObject.name, questorPerson.DisplayName);
            }
        }
        /// <summary>
        /// Add a quest NPC to marker position.
        /// </summary>
        static void AddQuestNPC(SiteTypes siteType, Quest quest, QuestMarker marker, Person person, Transform parent)
        {
            // Get billboard texture data
            FactionFile.FlatData flatData;
            if (person.IsIndividualNPC)
            {
                // Individuals are always flat1 no matter gender
                flatData = FactionFile.GetFlatData(person.FactionData.flat1);
            }
            if (person.Gender == Genders.Male)
            {
                // Male has flat1
                flatData = FactionFile.GetFlatData(person.FactionData.flat1);
            }
            else
            {
                // Female has flat2
                flatData = FactionFile.GetFlatData(person.FactionData.flat2);
            }

            // Create target GameObject
            GameObject go = CreateDaggerfallBillboardGameObject(flatData.archive, flatData.record, parent);

            go.name = string.Format("Quest NPC [{0}]", person.DisplayName);

            // Set position and adjust up by half height if not inside a dungeon
            Vector3 dungeonBlockPosition = new Vector3(marker.dungeonX * RDBLayout.RDBSide, 0, marker.dungeonZ * RDBLayout.RDBSide);

            go.transform.localPosition = dungeonBlockPosition + marker.flatPosition;
            DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>();

            if (siteType != SiteTypes.Dungeon)
            {
                go.transform.localPosition += new Vector3(0, dfBillboard.Summary.Size.y / 2, 0);
            }

            // Add people data to billboard
            dfBillboard.SetRMBPeopleData(person.FactionIndex, person.FactionData.flags);

            // Add QuestResourceBehaviour to GameObject
            QuestResourceBehaviour questResourceBehaviour = go.AddComponent <QuestResourceBehaviour>();

            questResourceBehaviour.AssignResource(person);

            // Set QuestResourceBehaviour in Person object
            person.QuestResourceBehaviour = questResourceBehaviour;

            // Add StaticNPC behaviour
            StaticNPC npc = go.AddComponent <StaticNPC>();

            npc.SetLayoutData((int)marker.flatPosition.x, (int)marker.flatPosition.y, (int)marker.flatPosition.z, person);

            // Set tag
            go.tag = QuestMachine.questPersonTag;
        }
        /// <summary>
        /// Adds a quest item to marker position.
        /// </summary>
        static void AddQuestItem(SiteTypes siteType, Quest quest, QuestMarker marker, Item item, Transform parent = null)
        {
            // Texture indices for quest items are from world texture record
            int textureArchive = item.DaggerfallUnityItem.WorldTextureArchive;
            int textureRecord  = item.DaggerfallUnityItem.WorldTextureRecord;

            // Create billboard
            GameObject          go          = CreateDaggerfallBillboardGameObject(textureArchive, textureRecord, parent);
            DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>();

            // Set name
            go.name = string.Format("Quest Item [{0} | {1}]", item.Symbol.Original, item.DaggerfallUnityItem.LongName);

            // Setup custom material if available
            if (AssetInjection.TextureReplacement.CustomTextureExist(textureArchive, textureRecord))
            {
                AssetInjection.TextureReplacement.SetBillboardCustomMaterial(go, textureArchive, textureRecord);
            }

            // Marker position
            Vector3 position;
            Vector3 dungeonBlockPosition = new Vector3(marker.dungeonX * RDBLayout.RDBSide, 0, marker.dungeonZ * RDBLayout.RDBSide);

            position = dungeonBlockPosition + marker.flatPosition;

            // Dungeon flats have a different origin (centre point) than elsewhere (base point)
            // Find bottom of marker in world space as it should be aligned to placement surface (e.g. ground, table, shelf, etc.)
            if (siteType == SiteTypes.Dungeon)
            {
                position.y += (-DaggerfallLoot.randomTreasureMarkerDim / 2 * MeshReader.GlobalScale);
            }

            // Now move up item icon by half own size and assign position
            position.y += (dfBillboard.Summary.Size.y / 2f);
            go.transform.localPosition = position;

            // Add QuestResourceBehaviour to GameObject
            QuestResourceBehaviour questResourceBehaviour = go.AddComponent <QuestResourceBehaviour>();

            questResourceBehaviour.AssignResource(item);

            // Set QuestResourceBehaviour in Item object
            item.QuestResourceBehaviour = questResourceBehaviour;

            // Assign a trigger collider for clicks
            SphereCollider collider = go.AddComponent <SphereCollider>();

            collider.isTrigger = true;
        }
        /// <summary>
        /// Adds a single quest foe to marker position.
        /// </summary>
        static void AddQuestFoe(SiteTypes siteType, Quest quest, QuestMarker marker, Foe foe, Transform parent)
        {
            // Create enemy GameObject
            Vector3    dungeonBlockPosition = new Vector3(marker.dungeonX * RDBLayout.RDBSide, 0, marker.dungeonZ * RDBLayout.RDBSide);
            GameObject go = CreateEnemy("Quest Foe", foe.FoeType, dungeonBlockPosition + marker.flatPosition, parent);

            // Add QuestResourceBehaviour to GameObject
            QuestResourceBehaviour questResourceBehaviour = go.AddComponent <QuestResourceBehaviour>();

            questResourceBehaviour.AssignResource(foe);

            // Set QuestResourceBehaviour in this particular instantiated Foe object
            // Each GameObject placed in world for this Foe will reference same Foe quest resource
            // Keep this one-to-many relationship in mind for Foe handling
            foe.QuestResourceBehaviour = questResourceBehaviour;

            // Rearm injured trigger at time of placement
            // Notes for later:
            //  * This should be rearmed at the beginning of each wave
            //  * Only first wounding of a wave will trigger "injured aFoe" until rearmed on next wave
            foe.RearmInjured();
        }