Beispiel #1
0
        private void EnemyEntity_OnDeath(DaggerfallEntity entity)
        {
            // Disable enemy gameobject
            // Do not destroy as we must still save enemy state when dead
            gameObject.SetActive(false);

            // Show death message
            string deathMessage = HardStrings.thingJustDied;

            deathMessage = deathMessage.Replace("%s", mobile.Summary.Enemy.Name);
            DaggerfallUI.Instance.PopupMessage(deathMessage);

            // Generate lootable corpse marker
            DaggerfallLoot loot = GameObjectHelper.CreateLootableCorpseMarker(
                GameManager.Instance.PlayerObject,
                entityBehaviour.gameObject,
                enemyEntity,
                mobile.Summary.Enemy.CorpseTexture,
                DaggerfallUnity.NextUID);

            // Generate items
            loot.GenerateItems();

            // Raise static event
            if (OnEnemyDeath != null)
            {
                OnEnemyDeath(this, null);
            }
        }
Beispiel #2
0
        void OfferToPlayerWithQuestComplete(Item item)
        {
            // Quest successful
            ParentQuest.QuestSuccess = true;

            // Show quest complete message
            DaggerfallMessageBox messageBox = ParentQuest.ShowMessagePopup((int)QuestMachine.QuestMessages.QuestComplete);

            // If no item for reward then we are done
            if (item == null)
            {
                return;
            }

            // Release item so we can offer back to player
            // Sometimes a quest item is both carried by player then offered back to them
            // Example is Sx010 where "curse" is removed and player can keep item
            GameManager.Instance.PlayerEntity.ReleaseQuestItemForReoffer(ParentQuest.UID, item, true);

            // Create a dropped loot container window for player to loot their reward
            rewardLoot = GameObjectHelper.CreateDroppedLootContainer(GameManager.Instance.PlayerObject, DaggerfallUnity.NextUID);
            rewardLoot.ContainerImage = InventoryContainerImages.Merchant;
            rewardLoot.Items.AddItem(item.DaggerfallUnityItem);

            // Schedule loot window to open when player dismisses message
            messageBox.OnClose += QuestCompleteMessage_OnClose;
        }
Beispiel #3
0
        /// <summary>
        /// Creates a generic loot container.
        /// </summary>
        /// <param name="containerType">Type of container.</param>
        /// <param name="containerImage">Icon to display in loot UI.</param>
        /// <param name="position">Position to spawn container.</param>
        /// <param name="parent">Parent GameObject.</param>
        /// <param name="textureArchive">Texture archive for billboard containers.</param>
        /// <param name="textureRecord">Texture record for billboard containers.</param>
        /// <param name="loadID">Unique LoadID for save system.</param>
        /// <returns>DaggerfallLoot.</returns>
        public static DaggerfallLoot CreateLootContainer(
            LootContainerTypes containerType,
            InventoryContainerImages containerImage,
            Vector3 position,
            Transform parent,
            int textureArchive,
            int textureRecord,
            ulong loadID = 0)
        {
            // Setup initial loot container prefab
            GameObject go = InstantiatePrefab(DaggerfallUnity.Instance.Option_LootContainerPrefab.gameObject, containerType.ToString(), parent, position);

            // Setup billboard component
            DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>();

            dfBillboard.SetMaterial(textureArchive, textureRecord);

            // Setup DaggerfallLoot component to make lootable
            DaggerfallLoot loot = go.GetComponent <DaggerfallLoot>();

            if (loot)
            {
                loot.LoadID         = loadID;
                loot.ContainerType  = containerType;
                loot.ContainerImage = containerImage;
                loot.TextureArchive = textureArchive;
                loot.TextureRecord  = textureRecord;
            }

            // Now move up loot icon by half own size so bottom is aligned with position
            position.y += (dfBillboard.Summary.Size.y / 2f);
            loot.transform.position = position;

            return(loot);
        }
 void Awake()
 {
     loot = GetComponent <DaggerfallLoot>();
     if (!loot)
     {
         throw new Exception("DaggerfallLoot not found.");
     }
 }
 // Check if raycast hit a lootable object
 private bool LootCheck(RaycastHit hitInfo, out DaggerfallLoot loot)
 {
     loot = hitInfo.transform.GetComponent<DaggerfallLoot>();
     if (loot == null)
         return false;
     else
         return true;
 }
Beispiel #6
0
        void CompleteDeath()
        {
            if (!entityBehaviour)
            {
                return;
            }

            // If enemy associated with quest system, make sure quest system is done with it first
            QuestResourceBehaviour questResourceBehaviour = GetComponent <QuestResourceBehaviour>();

            if (questResourceBehaviour)
            {
                if (!questResourceBehaviour.IsFoeDead)
                {
                    return;
                }
            }

            // Play body collapse sound
            if (DaggerfallUI.Instance.DaggerfallAudioSource)
            {
                AudioClip collapseSound = DaggerfallUI.Instance.DaggerfallAudioSource.GetAudioClip((int)SoundClips.BodyFall);
                AudioSource.PlayClipAtPoint(collapseSound, entityBehaviour.transform.position);
            }

            // Disable enemy gameobject
            // Do not destroy as we must still save enemy state when dead
            gameObject.SetActive(false);

            // Show death message
            string deathMessage = HardStrings.thingJustDied;

            deathMessage = deathMessage.Replace("%s", mobile.Summary.Enemy.Name);
            DaggerfallUI.Instance.PopupMessage(deathMessage);

            // Generate lootable corpse marker
            DaggerfallLoot loot = GameObjectHelper.CreateLootableCorpseMarker(
                GameManager.Instance.PlayerObject,
                entityBehaviour.gameObject,
                enemyEntity,
                mobile.Summary.Enemy.CorpseTexture,
                DaggerfallUnity.NextUID);

            // Generate items
            loot.GenerateItems();
            entityBehaviour.CorpseLootContainer = loot;

            // Transfer any items owned by entity to loot container
            // Many quests will stash a reward in enemy inventory for player to find
            // This will be in addition to normal random loot table generation
            loot.Items.TransferAll(entityBehaviour.Entity.Items);

            // Raise static event
            if (OnEnemyDeath != null)
            {
                OnEnemyDeath(this, null);
            }
        }
        void RayCheckForObstacle(Vector3 direction)
        {
            obstacleDetected = false;
            RaycastHit hit;
            int        checkDistance = 2;
            Vector3    rayOrigin     = transform.position + controller.center;

            rayOrigin.y     -= controller.height / 3;
            foundUpwardSlope = false;
            foundDoor        = false;

            Ray ray = new Ray(rayOrigin, direction);

            if (Physics.Raycast(ray, out hit, checkDistance))
            {
                obstacleDetected = true;
                float firstDistance = hit.distance;

                rayOrigin.y += 0.5f;
                ray          = new Ray(rayOrigin, direction);
                RaycastHit hit2;
                bool       secondRayHit = Physics.Raycast(ray, out hit2, checkDistance);

                if (!secondRayHit || firstDistance < hit2.distance)
                {
                    obstacleDetected = false;
                    foundUpwardSlope = true;
                }

                DaggerfallEntityBehaviour entityBehaviour2 = hit.transform.GetComponent <DaggerfallEntityBehaviour>();
                if (entityBehaviour2 == senses.Target)
                {
                    obstacleDetected = false;
                }

                DaggerfallActionDoor door = hit.transform.GetComponent <DaggerfallActionDoor>();
                if (door)
                {
                    obstacleDetected = false;
                    foundDoor        = true;
                    if (senses.TargetIsWithinYawAngle(5.625f, door.transform.position))
                    {
                        senses.LastKnownDoor  = door;
                        senses.DistanceToDoor = Vector3.Distance(transform.position, door.transform.position);
                    }
                }

                DaggerfallLoot loot = hit.transform.GetComponent <DaggerfallLoot>();
                if (loot)
                {
                    obstacleDetected = false;
                }
            }
        }
 // Check if raycast hit a lootable object
 private bool LootCheck(RaycastHit hitInfo, out DaggerfallLoot loot)
 {
     loot = hitInfo.transform.GetComponent <DaggerfallLoot>();
     if (loot == null)
     {
         return(false);
     }
     else
     {
         return(true);
     }
 }
Beispiel #9
0
        public static bool GenerateLoot(DaggerfallLoot loot, int locationIndex)
        {
            string[] lootTableKeys =
            {
                "K", // Crypt
                "N", // Orc Stronghold
                "N", // Human Stronghold
                "N", // Prison
                "K", // Desecrated Temple
                "M", // Mine
                "M", // Natural Cave
                "Q", // Coven
                "K", // Vampire Haunt
                "U", // Laboratory
                "D", // Harpy Nest
                "N", // Ruined Castle
                "L", // Spider Nest
                "F", // Giant Stronghold
                "S", // Dragon's Den
                "N", // Barbarian Stronghold
                "M", // Volcanic Caves
                "L", // Scorpion Nest
                "N", // Cemetery
            };

            // Get loot table key
            if (locationIndex < lootTableKeys.Length)
            {
                DaggerfallLoot.GenerateItems(lootTableKeys[locationIndex], loot.Items);

                // Randomly add map
                char key           = lootTableKeys[locationIndex][0];
                int  alphabetIndex = key - 64;

                if (alphabetIndex >= 10 && alphabetIndex <= 15) // between keys J and O
                {
                    int[] mapChances = { 2, 1, 1, 2, 2, 15 };
                    int   mapChance  = mapChances[alphabetIndex - 10];
                    DaggerfallLoot.RandomlyAddMap(mapChance, loot.Items);
                    DaggerfallLoot.RandomlyAddPotion(4, loot.Items);
                    DaggerfallLoot.RandomlyAddPotionRecipe(2, loot.Items);
                }

                OnLootSpawned?.Invoke(null, new TabledLootSpawnedEventArgs {
                    LocationIndex = locationIndex, Key = lootTableKeys[locationIndex], Items = loot.Items
                });

                return(true);
            }
            return(false);
        }
        void RestoreExteriorPositionHandler(DaggerfallLoot loot, LootContainerData_v1 data, WorldContext lootContext)
        {
            // If loot context matches serialized world context then loot was saved after floating y change
            // Need to get relative difference between current and serialized world compensation to get actual y position
            if (lootContext == data.worldContext)
            {
                float diffY = GameManager.Instance.StreamingWorld.WorldCompensation.y - data.worldCompensation.y;
                loot.transform.position = data.currentPosition + new Vector3(0, diffY, 0);
                return;
            }

            // Otherwise we migrate a legacy exterior position by adjusting for world compensation
            loot.transform.position = data.currentPosition + GameManager.Instance.StreamingWorld.WorldCompensation;
        }
Beispiel #11
0
        /// <summary>
        /// Destroys/Disables a loot container.
        /// Custom drop containers will be destroyed from world.
        /// Fixed containers will be disabled so their empty state continues to be serialized.
        /// </summary>
        /// <param name="loot">DaggerfallLoot.</param>
        public static void RemoveLootContainer(DaggerfallLoot loot)
        {
            // Corpse markers are not removed from world even if empty
            if (loot.ContainerType == LootContainerTypes.CorpseMarker)
            {
                return;
            }

            // Destroy or disable based on custom flag
            if (loot.customDrop)
            {
                GameObject.Destroy(loot.gameObject);
            }
            else
            {
                loot.gameObject.SetActive(false);
            }
        }
Beispiel #12
0
        void OfferToPlayerWithQuestComplete(Item item)
        {
            // Show quest complete message
            DaggerfallMessageBox messageBox = ParentQuest.ShowMessagePopup((int)QuestMachine.QuestMessages.QuestComplete);

            // If no item for reward then we are done
            if (item == null)
            {
                return;
            }

            // Create a dropped loot container window for player to loot their reward
            rewardLoot = GameObjectHelper.CreateDroppedLootContainer(GameManager.Instance.PlayerObject, DaggerfallUnity.NextUID);
            rewardLoot.ContainerImage = InventoryContainerImages.Merchant;
            rewardLoot.Items.AddItem(item.DaggerfallUnityItem);

            // Schedule loot window to open when player dismisses message
            messageBox.OnClose += QuestCompleteMessage_OnClose;
        }
        void RestoreInteriorPositionHandler(DaggerfallLoot loot, LootContainerData_v1 data, WorldContext lootContext)
        {
            // If loot context matches serialized world context then loot was saved after floating y change
            // Can simply restore local position relative to parent interior
            if (lootContext == data.worldContext)
            {
                loot.transform.localPosition = data.localPosition;
                return;
            }

            // Otherwise we need to migrate a legacy interior position to floating y
            if (GameManager.Instance.PlayerEnterExit.LastInteriorStartFlag)
            {
                // Loading interior uses serialized absolute position (as interior also serialized this way)
                loot.transform.position = data.currentPosition;
            }
            else
            {
                // Transition to interior must offset serialized absolute position by floating y compensation
                loot.transform.position = data.currentPosition + GameManager.Instance.StreamingWorld.WorldCompensation;
            }
        }
Beispiel #14
0
    private static void DropAllItems()
    {
        UnequipAll();

        GameObject player = GameManager.Instance.PlayerObject;
        List <DaggerfallUnityItem> dropList = new List <DaggerfallUnityItem>();

        for (int i = 0; i < playerEntity.Items.Count; i++)
        {
            DaggerfallUnityItem item = playerEntity.Items.GetItem(i);
            if (item.QuestItemSymbol != null || item.IsQuestItem || item.IsSummoned || item.TemplateIndex == 132 || item.TemplateIndex == 93 || item.TemplateIndex == 94)
            {
            }
            else
            {
                if (item.IsEquipped)
                {
                    item.currentCondition /= 2;
                }
                else
                {
                    dropList.Add(item);
                }
            }
        }

        if (dropList.Count >= 1)
        {
            DaggerfallLoot equipPile = GameObjectHelper.CreateDroppedLootContainer(player, DaggerfallUnity.NextUID);
            equipPile.customDrop  = true;
            equipPile.playerOwned = true;

            foreach (DaggerfallUnityItem item in dropList)
            {
                equipPile.Items.Transfer(item, playerEntity.Items);
            }
            DaggerfallUI.MessageBox("You tear off your clothes and armor.");
        }
    }
Beispiel #15
0
    private static void DropAllItems()
    {
        GameObject player = GameManager.Instance.PlayerObject;

        dropCollection = new ItemCollection();
        ItemCollection keepItemsCollection = new ItemCollection();

        UnequipAll();

        dropCollection.AddItems(playerEntity.Items.CloneAll());

        for (int i = 0; i < dropCollection.Count; i++)
        {
            DaggerfallUnityItem item = dropCollection.GetItem(i);
            if (item.QuestItemSymbol != null || item.IsQuestItem || item.IsSummoned || item.TemplateIndex == 132 || item.TemplateIndex == 93 || item.TemplateIndex == 94)
            {
                if (item.IsEquipped)
                {
                    item.UnequipItem(playerEntity);
                }
                keepItemsCollection.AddItem(item);
                dropCollection.RemoveItem(item);
            }
        }
        DaggerfallLoot equipPile = GameObjectHelper.CreateDroppedLootContainer(player, DaggerfallUnity.NextUID);

        equipPile.customDrop  = true;
        equipPile.playerOwned = true;
        equipPile.Items.AddItems(dropCollection.CloneAll());
        playerEntity.Items.Clear();
        dropCollection.Clear();

        for (int i = 0; i < keepItemsCollection.Count; i++)
        {
            DaggerfallUnityItem item = keepItemsCollection.GetItem(i);
            playerEntity.Items.AddItem(item);
        }
        keepItemsCollection.Clear();
    }
        public void RestoreLootContainerData(LootContainerData_v1[] lootContainers)
        {
            if (lootContainers == null || lootContainers.Length == 0)
            {
                return;
            }

            for (int i = 0; i < lootContainers.Length; i++)
            {
                // Skip null containers
                if (lootContainers[i] == null)
                {
                    continue;
                }

                // Restore loot containers
                ulong key = lootContainers[i].loadID;
                if (SerializableLootContainers.ContainsKey(key))
                {
                    // Apply to known loot container that is part of scene build
                    SerializableLootContainers[key].RestoreSaveData(lootContainers[i]);
                }
                else
                {
                    // Add custom drop containers back to scene (e.g. dropped loot, slain foes)
                    if (lootContainers[i].customDrop)
                    {
                        DaggerfallLoot            customLootContainer       = GameObjectHelper.CreateDroppedLootContainer(GameManager.Instance.PlayerObject, key, lootContainers[i].textureArchive, lootContainers[i].textureRecord);
                        SerializableLootContainer serializableLootContainer = customLootContainer.GetComponent <SerializableLootContainer>();
                        if (serializableLootContainer)
                        {
                            serializableLootContainer.RestoreSaveData(lootContainers[i]);
                        }
                        //Debug.LogFormat("created loot container {0} containing {1} parent {2}", key, customLootContainer.Items.GetItem(0).shortName, customLootContainer.transform.parent.name);
                    }
                }
            }
        }
        WorldContext GetLootWorldContext(DaggerfallLoot loot)
        {
            // Must be a parented loot container
            if (!loot || !loot.transform.parent)
            {
                return(WorldContext.Nothing);
            }

            // Interior
            if (loot.transform.parent.GetComponentInParent <DaggerfallInterior>())
            {
                return(WorldContext.Interior);
            }

            // Dungeon
            if (loot.transform.parent.GetComponentInParent <DaggerfallDungeon>())
            {
                return(WorldContext.Dungeon);
            }

            // Exterior (loose world object)
            return(WorldContext.Exterior);
        }
        void RestoreLootContainerData(LootContainerData_v1[] lootContainers)
        {
            if (lootContainers == null || lootContainers.Length == 0)
            {
                return;
            }

            for (int i = 0; i < lootContainers.Length; i++)
            {
                // Skip null containers
                if (lootContainers[i] == null)
                {
                    continue;
                }

                // Restore loot containers
                ulong key = lootContainers[i].loadID;
                if (serializableLootContainers.ContainsKey(key))
                {
                    // Apply to known loot container that is part of scene build
                    serializableLootContainers[key].RestoreSaveData(lootContainers[i]);
                }
                else
                {
                    // Add custom drop containers back to scene (e.g. dropped loot, slain foes)
                    if (lootContainers[i].customDrop)
                    {
                        DaggerfallLoot            customLootContainer       = GameObjectHelper.CreateDroppedLootContainer(GameManager.Instance.PlayerObject, key);
                        SerializableLootContainer serializableLootContainer = customLootContainer.GetComponent <SerializableLootContainer>();
                        if (serializableLootContainer)
                        {
                            serializableLootContainer.RestoreSaveData(lootContainers[i]);
                        }
                    }
                }
            }
        }
Beispiel #19
0
        void FindDetour(Vector3 motion)
        {
            Vector3 motion2d = motion;

            motion2d.y = 0;

            // First get whether we check clockwise or counterclockwise
            if (checkingClockWiseCounter == 0)
            {
                Vector3 toTarget          = targetPos - transform.position;
                Vector3 directionToTarget = toTarget.normalized;
                float   angleToTarget     = Vector3.SignedAngle(directionToTarget, motion, Vector3.up);

                if (angleToTarget > 0)
                {
                    checkingClockWise = false;
                }
                else
                {
                    checkingClockWise = true;
                }


                if (checkingClockWise)
                {
                    angleToTarget = 30;
                }
                else
                {
                    angleToTarget = -30;
                }
                RaycastHit hit;
                Vector3    testAngle = Quaternion.AngleAxis(angleToTarget, Vector3.up) * motion;
                motion2d.y = 0;
                int     checkDistance = 2;
                Vector3 rayOrigin     = transform.position;
                rayOrigin.y -= controller.height / 4;

                if (targetPos.y > transform.position.y + controller.height / 2)
                {
                    rayOrigin.y += controller.height / 2;
                }

                Ray ray = new Ray(rayOrigin, testAngle);

                if (Physics.Raycast(ray, out hit, checkDistance))
                {
                    bool testObstacleDetected = true;
                    if (lastYPos < transform.position.y)
                    {
                        testObstacleDetected = false;
                    }

                    DaggerfallEntityBehaviour entityBehaviour2 = hit.transform.GetComponent <DaggerfallEntityBehaviour>();
                    if (entityBehaviour2 == entityBehaviour.Target)
                    {
                        testObstacleDetected = false;
                    }

                    DaggerfallActionDoor door = hit.transform.GetComponent <DaggerfallActionDoor>();
                    if (door)
                    {
                        testObstacleDetected = false;
                    }

                    DaggerfallLoot loot = hit.transform.GetComponent <DaggerfallLoot>();
                    if (loot)
                    {
                        testObstacleDetected = false;
                    }

                    if (testObstacleDetected)
                    {
                        // Tested 30 degrees in the clockwise/counter-clockwise direction we chose,
                        // but hit something, so try other one.
                        checkingClockWise = !checkingClockWise;
                    }
                }
                checkingClockWiseCounter = 5;
            }
            else
            {
                checkingClockWiseCounter--;
            }

            float angle = 15;

            if (!checkingClockWise)
            {
                angle *= -1;
            }

            Vector3 detour;

            if (detourNumber == 0)
            {
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else if (detourNumber == 1)
            {
                angle *= 2;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else if (detourNumber == 2)
            {
                angle *= 3;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else if (detourNumber == 3)
            {
                angle *= 4;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else if (detourNumber == 4)
            {
                angle *= 5;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else if (detourNumber == 5)
            {
                angle *= 6;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else if (detourNumber == 6)
            {
                angle *= -1;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else if (detourNumber == 7)
            {
                angle *= -2;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else if (detourNumber == 8)
            {
                angle *= -3;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else if (detourNumber == 9)
            {
                angle *= -4;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else if (detourNumber == 10)
            {
                angle *= -5;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else if (detourNumber == 11)
            {
                angle *= -6;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else if (detourNumber == 12)
            {
                angle *= 7;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else if (detourNumber == 13)
            {
                angle *= -7;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else if (detourNumber == 14)
            {
                angle *= 8;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }
            else
            {
                angle *= -8;
                detour = Quaternion.AngleAxis(angle, Vector3.up) * motion;
            }

            detourNumber++;
            if (detourNumber == 16)
            {
                detourNumber = 0;
            }

            tempMovePos   = transform.position + detour.normalized * 3;
            tempMovePos.y = transform.position.y;

            lookingForDetour = true;

            moveInForAttack = true;
        }
Beispiel #20
0
        /// <summary>
        /// Creates a loot container for enemies slain by the player.
        /// </summary>
        /// <param name="player">Player object, must have PlayerEnterExit attached.</param>
        /// <param name="enemy">Enemy object, must have EnemyMotor attached.</param>
        /// <param name="corpseTexture">Packed corpse texture index from entity summary.</param>
        /// <param name="loadID">Unique LoadID for save system.</param>
        /// <returns>DaggerfallLoot.</returns>
        public static DaggerfallLoot CreateLootableCorpseMarker(GameObject player, GameObject enemy, EnemyEntity enemyEntity, int corpseTexture, ulong loadID)
        {
            // Player must have a PlayerEnterExit component
            PlayerEnterExit playerEnterExit = player.GetComponent <PlayerEnterExit>();

            if (!playerEnterExit)
            {
                throw new Exception("CreateLootableCorpseMarker() player game object must have PlayerEnterExit component.");
            }

            // Enemy must have an EnemyMotor component
            EnemyMotor enemyMotor = enemy.GetComponent <EnemyMotor>();

            if (!enemyMotor)
            {
                throw new Exception("CreateLootableCorpseMarker() enemy game object must have EnemyMotor component.");
            }

            // Get parent by context
            Transform parent = null;

            if (GameManager.Instance.IsPlayerInside)
            {
                if (GameManager.Instance.IsPlayerInsideDungeon)
                {
                    parent = playerEnterExit.Dungeon.transform;
                }
                else
                {
                    parent = playerEnterExit.Interior.transform;
                }
            }
            else
            {
                parent = GameManager.Instance.StreamingTarget.transform;
            }

            // Get corpse marker texture indices
            int archive, record;

            EnemyBasics.ReverseCorpseTexture(corpseTexture, out archive, out record);

            // Find ground position below player
            Vector3 position = enemyMotor.FindGroundPosition();

            // Create loot container
            DaggerfallLoot loot = CreateLootContainer(
                LootContainerTypes.CorpseMarker,
                InventoryContainerImages.Corpse2,
                position,
                parent,
                archive,
                record,
                loadID);

            // Set properties
            loot.LoadID       = loadID;
            loot.LootTableKey = enemyEntity.MobileEnemy.LootTableKey;
            loot.playerOwned  = false;
            loot.customDrop   = true;

            // If dropped outside ask StreamingWorld to track loose object
            if (!GameManager.Instance.IsPlayerInside)
            {
                GameManager.Instance.StreamingWorld.TrackLooseObject(loot.gameObject);
            }

            return(loot);
        }
Beispiel #21
0
        /// <summary>
        /// Sets enemy career and prepares entity settings.
        /// </summary>
        public void SetEnemyCareer(MobileEnemy mobileEnemy, EntityTypes entityType)
        {
            // Try custom career first
            career = GetCustomCareerTemplate(mobileEnemy.ID);

            if (career != null)
            {
                // Custom enemy
                careerIndex = mobileEnemy.ID;
                stats.SetPermanentFromCareer(career);

                if (entityType == EntityTypes.EnemyMonster)
                {
                    // Default like a monster
                    level     = mobileEnemy.Level;
                    maxHealth = Random.Range(mobileEnemy.MinHealth, mobileEnemy.MaxHealth + 1);
                    for (int i = 0; i < ArmorValues.Length; i++)
                    {
                        ArmorValues[i] = (sbyte)(mobileEnemy.ArmorValue * 5);
                    }
                }
                else
                {
                    // Default like a class enemy
                    level     = GameManager.Instance.PlayerEntity.Level;
                    maxHealth = FormulaHelper.RollEnemyClassMaxHealth(level, career.HitPointsPerLevel);
                }
            }
            else if (entityType == EntityTypes.EnemyMonster)
            {
                careerIndex = mobileEnemy.ID;
                career      = GetMonsterCareerTemplate((MonsterCareers)careerIndex);
                stats.SetPermanentFromCareer(career);

                // Enemy monster has predefined level, health and armor values.
                // Armor values can be modified below by equipment.
                level     = mobileEnemy.Level;
                maxHealth = UnityEngine.Random.Range(mobileEnemy.MinHealth, mobileEnemy.MaxHealth + 1);
                for (int i = 0; i < ArmorValues.Length; i++)
                {
                    ArmorValues[i] = (sbyte)(mobileEnemy.ArmorValue * 5);
                }
            }
            else if (entityType == EntityTypes.EnemyClass)
            {
                careerIndex = mobileEnemy.ID - 128;
                career      = GetClassCareerTemplate((ClassCareers)careerIndex);
                stats.SetPermanentFromCareer(career);

                // Enemy class is levelled to player and uses similar health rules
                // City guards are 3 to 6 levels above the player
                level = GameManager.Instance.PlayerEntity.Level;
                if (careerIndex == (int)MobileTypes.Knight_CityWatch - 128)
                {
                    level += UnityEngine.Random.Range(3, 7);
                }

                maxHealth = FormulaHelper.RollEnemyClassMaxHealth(level, career.HitPointsPerLevel);
            }
            else
            {
                career      = new DFCareer();
                careerIndex = -1;
                return;
            }

            this.mobileEnemy = mobileEnemy;
            this.entityType  = entityType;
            name             = career.Name;
            minMetalToHit    = mobileEnemy.MinMetalToHit;
            team             = mobileEnemy.Team;

            short skillsLevel = (short)((level * 5) + 30);

            if (skillsLevel > 100)
            {
                skillsLevel = 100;
            }

            for (int i = 0; i <= DaggerfallSkills.Count; i++)
            {
                skills.SetPermanentSkillValue(i, skillsLevel);
            }

            // Generate loot table items
            DaggerfallLoot.GenerateItems(mobileEnemy.LootTableKey, items);

            // Enemy classes and some monsters use equipment
            if (careerIndex == (int)MonsterCareers.Orc || careerIndex == (int)MonsterCareers.OrcShaman)
            {
                SetEnemyEquipment(0);
            }
            else if (careerIndex == (int)MonsterCareers.Centaur || careerIndex == (int)MonsterCareers.OrcSergeant)
            {
                SetEnemyEquipment(1);
            }
            else if (careerIndex == (int)MonsterCareers.OrcWarlord)
            {
                SetEnemyEquipment(2);
            }
            else if (entityType == EntityTypes.EnemyClass)
            {
                SetEnemyEquipment(UnityEngine.Random.Range(0, 2)); // 0 or 1
            }

            // Assign spell lists
            if (entityType == EntityTypes.EnemyMonster)
            {
                if (careerIndex == (int)MonsterCareers.Imp)
                {
                    SetEnemySpells(ImpSpells);
                }
                else if (careerIndex == (int)MonsterCareers.Ghost)
                {
                    SetEnemySpells(GhostSpells);
                }
                else if (careerIndex == (int)MonsterCareers.OrcShaman)
                {
                    SetEnemySpells(OrcShamanSpells);
                }
                else if (careerIndex == (int)MonsterCareers.Wraith)
                {
                    SetEnemySpells(WraithSpells);
                }
                else if (careerIndex == (int)MonsterCareers.FrostDaedra)
                {
                    SetEnemySpells(FrostDaedraSpells);
                }
                else if (careerIndex == (int)MonsterCareers.FireDaedra)
                {
                    SetEnemySpells(FireDaedraSpells);
                }
                else if (careerIndex == (int)MonsterCareers.Daedroth)
                {
                    SetEnemySpells(DaedrothSpells);
                }
                else if (careerIndex == (int)MonsterCareers.Vampire)
                {
                    SetEnemySpells(VampireSpells);
                }
                else if (careerIndex == (int)MonsterCareers.DaedraSeducer)
                {
                    SetEnemySpells(SeducerSpells);
                }
                else if (careerIndex == (int)MonsterCareers.VampireAncient)
                {
                    SetEnemySpells(VampireAncientSpells);
                }
                else if (careerIndex == (int)MonsterCareers.DaedraLord)
                {
                    SetEnemySpells(DaedraLordSpells);
                }
                else if (careerIndex == (int)MonsterCareers.Lich)
                {
                    SetEnemySpells(LichSpells);
                }
                else if (careerIndex == (int)MonsterCareers.AncientLich)
                {
                    SetEnemySpells(AncientLichSpells);
                }
            }
            else if (entityType == EntityTypes.EnemyClass && (mobileEnemy.CastsMagic))
            {
                int spellListLevel = level / 3;
                if (spellListLevel > 6)
                {
                    spellListLevel = 6;
                }
                SetEnemySpells(EnemyClassSpells[spellListLevel]);
            }

            // Chance of adding map
            DaggerfallLoot.RandomlyAddMap(mobileEnemy.MapChance, items);

            if (!string.IsNullOrEmpty(mobileEnemy.LootTableKey))
            {
                // Chance of adding potion
                DaggerfallLoot.RandomlyAddPotion(3, items);
                // Chance of adding potion recipe
                DaggerfallLoot.RandomlyAddPotionRecipe(2, items);
            }

            OnLootSpawned?.Invoke(this, new EnemyLootSpawnedEventArgs {
                MobileEnemy = mobileEnemy, EnemyCareer = career, Items = items
            });

            FillVitalSigns();
        }
 void Awake()
 {
     loot = GetComponent<DaggerfallLoot>();
     if (!loot)
         throw new Exception("DaggerfallLoot not found.");
 }
Beispiel #23
0
        /// <summary>
        /// Sets enemy career and prepares entity settings.
        /// </summary>
        public void SetEnemyCareer(MobileEnemy mobileEnemy, EntityTypes entityType)
        {
            if (entityType == EntityTypes.EnemyMonster)
            {
                careerIndex = (int)mobileEnemy.ID;
                career      = GetMonsterCareerTemplate((MonsterCareers)careerIndex);
                stats.SetPermanentFromCareer(career);

                // Enemy monster has predefined level, health and armor values.
                // Armor values can be modified below by equipment.
                level     = mobileEnemy.Level;
                maxHealth = UnityEngine.Random.Range(mobileEnemy.MinHealth, mobileEnemy.MaxHealth + 1);
                for (int i = 0; i < ArmorValues.Length; i++)
                {
                    ArmorValues[i] = (sbyte)(mobileEnemy.ArmorValue * 5);
                }
            }
            else if (entityType == EntityTypes.EnemyClass)
            {
                careerIndex = (int)mobileEnemy.ID - 128;
                career      = GetClassCareerTemplate((ClassCareers)careerIndex);
                stats.SetPermanentFromCareer(career);

                // Enemy class is levelled to player and uses similar health rules
                level     = GameManager.Instance.PlayerEntity.Level;
                maxHealth = FormulaHelper.RollEnemyClassMaxHealth(level, career.HitPointsPerLevel);
            }
            else
            {
                career      = new DFCareer();
                careerIndex = -1;
                return;
            }

            this.mobileEnemy = mobileEnemy;
            this.entityType  = entityType;
            name             = career.Name;
            minMetalToHit    = mobileEnemy.MinMetalToHit;

            short skillsLevel = (short)((level * 5) + 30);

            if (skillsLevel > 100)
            {
                skillsLevel = 100;
            }

            for (int i = 0; i <= DaggerfallSkills.Count; i++)
            {
                skills.SetPermanentSkillValue(i, skillsLevel);
            }

            // Generate loot table items
            DaggerfallLoot.GenerateItems(mobileEnemy.LootTableKey, items);

            // Enemy classes and some monsters use equipment
            if (careerIndex == (int)MonsterCareers.Orc || careerIndex == (int)MonsterCareers.OrcShaman)
            {
                SetEnemyEquipment(0);
            }
            else if (careerIndex == (int)MonsterCareers.Centaur || careerIndex == (int)MonsterCareers.OrcSergeant)
            {
                SetEnemyEquipment(1);
            }
            else if (careerIndex == (int)MonsterCareers.OrcWarlord)
            {
                SetEnemyEquipment(2);
            }
            else if (entityType == EntityTypes.EnemyClass)
            {
                SetEnemyEquipment(UnityEngine.Random.Range(0, 2)); // 0 or 1
            }

            // Chance of adding map
            DaggerfallLoot.RandomlyAddMap(mobileEnemy.MapChance, items);

            if (!string.IsNullOrEmpty(mobileEnemy.LootTableKey))
            {
                // Chance of adding potion
                DaggerfallLoot.RandomlyAddPotion(3, items);
                // Chance of adding potion recipe
                DaggerfallLoot.RandomlyAddPotionRecipe(2, items);
            }

            FillVitalSigns();
        }
Beispiel #24
0
        /// <summary>
        /// Creates a loot container for items dropped by the player.
        /// </summary>
        /// <param name="player">Player object, must have PlayerEnterExit and PlayerMotor attached.</param>
        /// <param name="loadID">Unique LoadID for save system.</param>
        /// <returns>DaggerfallLoot.</returns>
        public static DaggerfallLoot CreateDroppedLootContainer(GameObject player, ulong loadID)
        {
            // Player must have a PlayerEnterExit component
            PlayerEnterExit playerEnterExit = player.GetComponent <PlayerEnterExit>();

            if (!playerEnterExit)
            {
                throw new Exception("CreateDroppedLootContainer() player game object must have PlayerEnterExit component.");
            }

            // Player must have a PlayerMotor component
            PlayerMotor playerMotor = player.GetComponent <PlayerMotor>();

            if (!playerMotor)
            {
                throw new Exception("CreateDroppedLootContainer() player game object must have PlayerMotor component.");
            }

            // Get parent by context
            Transform parent = null;

            if (GameManager.Instance.IsPlayerInside)
            {
                if (GameManager.Instance.IsPlayerInsideDungeon)
                {
                    parent = playerEnterExit.Dungeon.transform;
                }
                else
                {
                    parent = playerEnterExit.Interior.transform;
                }
            }
            else
            {
                parent = GameManager.Instance.StreamingTarget.transform;
            }

            // Randomise container texture
            int iconIndex  = UnityEngine.Random.Range(0, DaggerfallLoot.randomTreasureIconIndices.Length);
            int iconRecord = DaggerfallLoot.randomTreasureIconIndices[iconIndex];

            // Find ground position below player
            Vector3 position = playerMotor.FindGroundPosition();

            // Create loot container
            DaggerfallLoot loot = CreateLootContainer(
                LootContainerTypes.DroppedLoot,
                InventoryContainerImages.Chest,
                position,
                parent,
                DaggerfallLoot.randomTreasureArchive,
                iconRecord,
                loadID);

            // Set properties
            loot.LoadID       = loadID;
            loot.LootTableKey = string.Empty;
            loot.playerOwned  = true;
            loot.customDrop   = true;

            // If dropped outside ask StreamingWorld to track loose object
            if (!GameManager.Instance.IsPlayerInside)
            {
                GameManager.Instance.StreamingWorld.TrackLooseObject(loot.gameObject);
            }

            return(loot);
        }
Beispiel #25
0
        /// <summary>
        /// Sets enemy career and prepares entity settings.
        /// </summary>
        public void SetEnemyCareer(MobileEnemy mobileEnemy, EntityTypes entityType)
        {
            if (entityType == EntityTypes.EnemyMonster)
            {
                careerIndex = mobileEnemy.ID;
                career      = GetMonsterCareerTemplate((MonsterCareers)careerIndex);
                stats.SetPermanentFromCareer(career);

                // Enemy monster has predefined level, health and armor values.
                // Armor values can be modified below by equipment.
                level     = mobileEnemy.Level;
                maxHealth = UnityEngine.Random.Range(mobileEnemy.MinHealth, mobileEnemy.MaxHealth + 1);
                for (int i = 0; i < ArmorValues.Length; i++)
                {
                    ArmorValues[i] = (sbyte)(mobileEnemy.ArmorValue * 5);
                }
            }
            else if (entityType == EntityTypes.EnemyClass)
            {
                careerIndex = mobileEnemy.ID - 128;
                career      = GetClassCareerTemplate((ClassCareers)careerIndex);
                stats.SetPermanentFromCareer(career); // I may have a better way to alter the attributes of individual enemy entities, this seems to be where it originates from, will possibly alter later on.

                // Enemy class is levelled to player and uses similar health rules
                // City guards are 3 to 6 levels above the player
                //level = GameManager.Instance.PlayerEntity.Level; // Definitely going to want to mess with this a lot eventually, this is apparently what makes the human enemies equal to the player level, will alter that.
                level = UnityEngine.Random.Range(1, 31);
                if (careerIndex == (int)MobileTypes.Knight_CityWatch)
                {
                    level += UnityEngine.Random.Range(3, 7);
                }

                maxHealth = FormulaHelper.RollEnemyClassMaxHealth(level, career.HitPointsPerLevel);
            }
            else
            {
                career      = new DFCareer();
                careerIndex = -1;
                return;
            }

            this.mobileEnemy = mobileEnemy;
            this.entityType  = entityType;
            name             = career.Name;
            minMetalToHit    = mobileEnemy.MinMetalToHit;
            team             = mobileEnemy.Team;

            short skillsLevel = (short)((level * 5) + 30);

            if (skillsLevel > 100)
            {
                skillsLevel = 100;
            }

            for (int i = 0; i <= DaggerfallSkills.Count; i++)
            {
                skills.SetPermanentSkillValue(i, skillsLevel);
            }

            int[] personalityTraits = DaggerfallWorkshop.Utility.EnemyBasics.EnemyPersonalityTraitGenerator(this);
            // May put the method for the "context based" inventory modifiers here, but first i'll have to figure out how i'm going to do that exactly first.

            DaggerfallLoot.GenerateEnemyItems(items, personalityTraits, this);

            // Enemy classes and some monsters use equipment
            if (EquipmentUser())
            {
                SetEnemyEquipment(personalityTraits);
            }

            // Assign spell lists
            if (entityType == EntityTypes.EnemyMonster)
            {
                if (careerIndex == (int)MonsterCareers.Imp)
                {
                    SetEnemySpells(ImpSpells);
                }
                else if (careerIndex == (int)MonsterCareers.Ghost)
                {
                    SetEnemySpells(GhostSpells);
                }
                else if (careerIndex == (int)MonsterCareers.OrcShaman)
                {
                    SetEnemySpells(OrcShamanSpells);
                }
                else if (careerIndex == (int)MonsterCareers.Wraith)
                {
                    SetEnemySpells(WraithSpells);
                }
                else if (careerIndex == (int)MonsterCareers.FrostDaedra)
                {
                    SetEnemySpells(FrostDaedraSpells);
                }
                else if (careerIndex == (int)MonsterCareers.FireDaedra)
                {
                    SetEnemySpells(FireDaedraSpells);
                }
                else if (careerIndex == (int)MonsterCareers.Daedroth)
                {
                    SetEnemySpells(DaedrothSpells);
                }
                else if (careerIndex == (int)MonsterCareers.Vampire)
                {
                    SetEnemySpells(VampireSpells);
                }
                else if (careerIndex == (int)MonsterCareers.DaedraSeducer)
                {
                    SetEnemySpells(SeducerSpells);
                }
                else if (careerIndex == (int)MonsterCareers.VampireAncient)
                {
                    SetEnemySpells(VampireAncientSpells);
                }
                else if (careerIndex == (int)MonsterCareers.DaedraLord)
                {
                    SetEnemySpells(DaedraLordSpells);
                }
                else if (careerIndex == (int)MonsterCareers.Lich)
                {
                    SetEnemySpells(LichSpells);
                }
                else if (careerIndex == (int)MonsterCareers.AncientLich)
                {
                    SetEnemySpells(AncientLichSpells);
                }
            }
            else if (entityType == EntityTypes.EnemyClass && (mobileEnemy.CastsMagic))
            {
                int spellListLevel = level / 3;
                if (spellListLevel > 6)
                {
                    spellListLevel = 6;
                }
                SetEnemySpells(EnemyClassSpells[spellListLevel]);
            }

            FillVitalSigns(); // Could use this to set enemies health and other vitals at a lower level when they first spawn, to simulate them being already wounded or something.
        }
        /// <summary>
        /// Destroys/Disables a loot container.
        /// Custom drop containers will be destroyed from world.
        /// Fixed containers will be disabled so their empty state continues to be serialized.
        /// </summary>
        /// <param name="loot">DaggerfallLoot.</param>
        public static void RemoveLootContainer(DaggerfallLoot loot)
        {
            // Corpse markers are not removed from world even if empty
            if (loot.ContainerType == LootContainerTypes.CorpseMarker)
                return;

            // Destroy or disable based on custom flag
            if (loot.customDrop)
                GameObject.Destroy(loot.gameObject);
            else
                loot.gameObject.SetActive(false);
        }
Beispiel #27
0
        /// <summary>
        /// Check for a large fall, and proceed with move if none found.
        /// </summary>
        void MoveIfNoFallDetected(Vector3 motion)
        {
            // Check at classic rate to limit ray casts
            if (classicUpdate)
            {
                obstacleDetected = false;
                fallDetected     = false;
                float currentYPos = transform.position.y;

                // First check if there is something to collide with directly in movement direction, such as upward sloping ground.
                // If there is, we assume we won't fall.
                RaycastHit hit;
                Vector3    motion2d = motion.normalized;
                motion2d.y = 0;
                int     checkDistance = 2;
                Vector3 rayOrigin     = transform.position;
                rayOrigin.y -= controller.height / 4;

                if (targetPos.y > transform.position.y + controller.height / 2)
                {
                    rayOrigin.y += controller.height / 2;
                }

                Ray ray = new Ray(rayOrigin, motion2d);

                if (Physics.Raycast(ray, out hit, checkDistance))
                {
                    fallDetected     = false;
                    obstacleDetected = true;

                    if (lastYPos < currentYPos)
                    {
                        obstacleDetected = false;
                    }

                    DaggerfallEntityBehaviour entityBehaviour2 = hit.transform.GetComponent <DaggerfallEntityBehaviour>();
                    if (entityBehaviour2 == entityBehaviour.Target)
                    {
                        obstacleDetected = false;
                    }

                    DaggerfallActionDoor door = hit.transform.GetComponent <DaggerfallActionDoor>();
                    if (door)
                    {
                        obstacleDetected = false;
                    }

                    DaggerfallLoot loot = hit.transform.GetComponent <DaggerfallLoot>();
                    if (loot)
                    {
                        obstacleDetected = false;
                    }
                }
                // Nothing to collide with. Check for a long fall.
                else
                {
                    motion2d    *= checkDistance;
                    ray          = new Ray(rayOrigin + motion2d, Vector3.down);
                    fallDetected = !Physics.Raycast(ray, out hit, 5);
                }

                if ((fallDetected || obstacleDetected) && DaggerfallUnity.Settings.EnhancedCombatAI)
                {
                    FindDetour(motion);
                }

                lastYPos = currentYPos;
            }

            if (!fallDetected && !obstacleDetected)
            {
                controller.SimpleMove(motion);

                if (lookingForDetour)
                {
                    lookingForDetour    = false;
                    avoidObstaclesTimer = .5f;
                    lastTimeWasStuck    = Time.time;
                    detourNumber--;
                }
            }
            if (Time.time - lastTimeWasStuck > 3f)
            {
                detourNumber = 0;
            }
        }
Beispiel #28
0
        void CompleteDeath()
        {
            if (!entityBehaviour)
            {
                return;
            }

            // If enemy associated with quest system, make sure quest system is done with it first
            QuestResourceBehaviour questResourceBehaviour = GetComponent <QuestResourceBehaviour>();

            if (questResourceBehaviour)
            {
                if (!questResourceBehaviour.IsFoeDead)
                {
                    return;
                }
            }

            // Disable enemy gameobject
            // Do not destroy as we must still save enemy state when dead
            gameObject.SetActive(false);

            // Show death message
            string deathMessage = TextManager.Instance.GetLocalizedText("thingJustDied");

            deathMessage = deathMessage.Replace("%s", TextManager.Instance.GetLocalizedEnemyName(mobile.Summary.Enemy.ID));
            DaggerfallUI.Instance.PopupMessage(deathMessage);

            // Generate lootable corpse marker
            DaggerfallLoot loot = GameObjectHelper.CreateLootableCorpseMarker(
                GameManager.Instance.PlayerObject,
                entityBehaviour.gameObject,
                enemyEntity,
                mobile.Summary.Enemy.CorpseTexture,
                DaggerfallUnity.NextUID);

            // This is still required so enemy equipment is not marked as equipped
            // This item collection is transferred to loot container below
            for (int i = (int)Items.EquipSlots.Head; i <= (int)Items.EquipSlots.Feet; i++)
            {
                Items.DaggerfallUnityItem item = enemyEntity.ItemEquipTable.GetItem((Items.EquipSlots)i);
                if (item != null)
                {
                    enemyEntity.ItemEquipTable.UnequipItem((Items.EquipSlots)i);
                }
            }

            entityBehaviour.CorpseLootContainer = loot;

            // Transfer any items owned by entity to loot container
            // Many quests will stash a reward in enemy inventory for player to find
            // This will be in addition to normal random loot table generation
            loot.Items.TransferAll(entityBehaviour.Entity.Items);

            // Play body collapse sound
            if (DaggerfallUI.Instance.DaggerfallAudioSource)
            {
                DaggerfallUI.Instance.DaggerfallAudioSource.PlayClipAtPoint(SoundClips.BodyFall, loot.transform.position, 1f);
            }

            // Lower enemy alert state on player now that enemy is dead
            // If this is final enemy targeting player then alert state will remain clear
            // Other enemies still targeting player will continue to raise alert state every update
            EnemySenses senses = entityBehaviour.GetComponent <EnemySenses>();

            if (senses && senses.Target == GameManager.Instance.PlayerEntityBehaviour)
            {
                GameManager.Instance.PlayerEntity.SetEnemyAlert(false);
            }

            // Raise static event
            if (OnEnemyDeath != null)
            {
                OnEnemyDeath(this, null);
            }
        }
        public override void OnPop()
        {
            // Clear any loot target on exit
            if (lootTarget != null)
            {
                // Remove loot container if empty
                if (lootTarget.Items.Count == 0)
                    GameObjectHelper.RemoveLootContainer(lootTarget);

                lootTarget.OnInventoryClose();
                lootTarget = null;
            }

            // Generate serializable loot pile in world for dropped items
            if (droppedItems.Count > 0)
            {
                DaggerfallLoot droppedLootContainer = GameObjectHelper.CreateDroppedLootContainer(GameManager.Instance.PlayerObject, DaggerfallUnity.NextUID);
                droppedLootContainer.Items.TransferAll(droppedItems);
            }
        }
        void CompleteDeath()
        {
            if (!entityBehaviour)
            {
                return;
            }

            // If enemy associated with quest system, make sure quest system is done with it first
            QuestResourceBehaviour questResourceBehaviour = GetComponent <QuestResourceBehaviour>();

            if (questResourceBehaviour)
            {
                if (!questResourceBehaviour.IsFoeDead)
                {
                    return;
                }
            }

            // Play body collapse sound
            if (DaggerfallUI.Instance.DaggerfallAudioSource)
            {
                AudioClip collapseSound = DaggerfallUI.Instance.DaggerfallAudioSource.GetAudioClip((int)SoundClips.BodyFall);
                AudioSource.PlayClipAtPoint(collapseSound, entityBehaviour.transform.position, 1.05f);
            }

            // Disable enemy gameobject
            // Do not destroy as we must still save enemy state when dead
            gameObject.SetActive(false);

            // Show death message
            string deathMessage = HardStrings.thingJustDied;

            deathMessage = deathMessage.Replace("%s", mobile.Summary.Enemy.Name);
            DaggerfallUI.Instance.PopupMessage(deathMessage);

            // Generate lootable corpse marker
            DaggerfallLoot loot = GameObjectHelper.CreateLootableCorpseMarker(
                GameManager.Instance.PlayerObject,
                entityBehaviour.gameObject,
                enemyEntity,
                mobile.Summary.Enemy.CorpseTexture,
                DaggerfallUnity.NextUID);

            // Generate items
            loot.GenerateItems();

            // This is still required so enemy equipment is not marked as equipped
            // This item collection is transferred to loot container below
            for (int i = (int)Items.EquipSlots.Head; i <= (int)Items.EquipSlots.Feet; i++)
            {
                Items.DaggerfallUnityItem item = enemyEntity.ItemEquipTable.GetItem((Items.EquipSlots)i);
                if (item != null)
                {
                    enemyEntity.ItemEquipTable.UnequipItem((Items.EquipSlots)i);
                }
            }

            // Chance of adding map
            loot.RandomlyAddMap(mobile.Summary.Enemy.MapChance);

            if (!string.IsNullOrEmpty(mobile.Summary.Enemy.LootTableKey))
            {
                // Chance of adding potion
                loot.RandomlyAddPotion(3);
                // Chance of adding potion recipe
                loot.RandomlyAddPotionRecipe(2);
            }

            entityBehaviour.CorpseLootContainer = loot;

            // Transfer any items owned by entity to loot container
            // Many quests will stash a reward in enemy inventory for player to find
            // This will be in addition to normal random loot table generation
            loot.Items.TransferAll(entityBehaviour.Entity.Items);

            // Raise static event
            if (OnEnemyDeath != null)
            {
                OnEnemyDeath(this, null);
            }
        }