示例#1
0
        public void SetTargetNPC(MobilePersonNPC targetMobileNPC, int reactionToPlayer)
        {
            if (targetMobileNPC == lastTargetMobileNPC)
            {
                return;
            }

            this.targetMobileNPC = targetMobileNPC;

            DaggerfallUI.Instance.TalkWindow.SetNPCPortrait(DaggerfallTalkWindow.FacePortraitArchive.CommonFaces, targetMobileNPC.PersonFaceRecordId);

            lastTargetMobileNPC = targetMobileNPC;

            nameNPC = targetMobileNPC.NameNPC;
            DaggerfallUI.Instance.TalkWindow.UpdateNameNPC();

            this.reactionToPlayer = reactionToPlayer;

            // reset npc knowledge, for now it resets every time the npc has changed (player talked to new npc)
            // TODO: match classic daggerfall - in classic npc remember their knowledge about topics for their time of existence
            resetNPCKnowledgeInTopicListRecursively(listTopicLocation);
            resetNPCKnowledgeInTopicListRecursively(listTopicPerson);
            resetNPCKnowledgeInTopicListRecursively(listTopicThing);
            resetNPCKnowledgeInTopicListRecursively(listTopicTellMeAbout);
        }
 // Handle trampling civilian NPCs.
 private void OnTriggerEnter(Collider other)
 {
     if (playerMotor.IsRiding && playerMotor.IsRunning)
     {
         PlayerEntity    playerEntity = GameManager.Instance.PlayerEntity;
         Transform       npcTransform = other.gameObject.transform;
         MobilePersonNPC mobileNpc    = npcTransform.GetComponent <MobilePersonNPC>();
         if (mobileNpc)
         {
             Debug.Log("Rode over an NPC trampling them!");
             if (!mobileNpc.IsGuard)
             {
                 EnemyBlood blood = npcTransform.GetComponent <EnemyBlood>();
                 if (blood)
                 {
                     blood.ShowBloodSplash(0, BloodPos());
                 }
                 AudioClip trampleClip = mobileNpc.Gender == Genders.Male ? trampleMaleClip : trampleFemaleClip;
                 dfAudioSource.AudioSource.PlayOneShot(trampleClip, GameManager.Instance.TransportManager.RidingVolumeScale * DaggerfallUnity.Settings.SoundVolume);
                 playerEntity.SpawnCityGuards(true);
             }
             else
             {
                 GameObject guard = playerEntity.SpawnCityGuard(mobileNpc.transform.position, mobileNpc.transform.forward);
                 DaggerfallEntityBehaviour guardBehaviour = guard.GetComponent <DaggerfallEntityBehaviour>();
                 HandleCharge(guard, guardBehaviour, transform.forward);
             }
             playerEntity.CrimeCommitted = PlayerEntity.Crimes.Assault;  // Nearest to manslaughter
             mobileNpc.Motor.gameObject.SetActive(false);
         }
     }
 }
 // Check if raycast hit a mobile NPC
 private bool MobilePersonMotorCheck(RaycastHit hitInfo, out MobilePersonNPC mobileNPC)
 {
     mobileNPC = hitInfo.transform.GetComponent <MobilePersonNPC>();
     if (mobileNPC != null)
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
示例#4
0
        // Player has clicked on a mobile talk target
        public void TalkToMobileNPC(MobilePersonNPC targetNPC)
        {
            const int youGetNoResponseTextId = 7205;

            // Get NPC faction
            FactionFile.FactionData NPCfaction;
            int oneBasedPlayerRegion = GameManager.Instance.PlayerGPS.CurrentOneBasedRegionIndex;

            FactionFile.FactionData[] factions = GameManager.Instance.PlayerEntity.FactionData.FindFactions(
                (int)FactionFile.FactionTypes.Province, -1, -1, oneBasedPlayerRegion);

            // Should always find a region
            if (factions == null || factions.Length == 0)
            {
                throw new Exception("TalkToMobileNPC() did not find a match for NPC faction.");
            }

            // Warn if more than 1 region is found
            if (factions.Length > 1)
            {
                Debug.LogWarningFormat("TalkToMobileNPC() found more than 1 matching NPC faction for region {0}.", oneBasedPlayerRegion);
            }

            NPCfaction = factions[0];

            // Get reaction to player
            int          reactionToPlayer = 0;
            PlayerEntity player           = GameManager.Instance.PlayerEntity;

            reactionToPlayer  = NPCfaction.rep;
            reactionToPlayer += player.BiographyReactionMod;

            if (NPCfaction.sgroup < player.SGroupReputations.Length) // one of the five general social groups
            {
                reactionToPlayer += player.SGroupReputations[NPCfaction.sgroup];
            }

            if (reactionToPlayer >= -20)
            {
                DaggerfallUI.UIManager.PushWindow(DaggerfallUI.Instance.TalkWindow);
                GameManager.Instance.TalkManager.SetTargetNPC(targetNPC, reactionToPlayer);
            }
            else
            {
                DaggerfallUI.MessageBox(youGetNoResponseTextId);
            }
        }
示例#5
0
        // Returns true if hit an enemy entity
        public bool WeaponDamage(RaycastHit hit, Vector3 direction, bool arrowHit = false)
        {
            DaggerfallUnityItem strikingWeapon = null;

            // Check if hit has an DaggerfallAction component
            DaggerfallAction action = hit.transform.gameObject.GetComponent <DaggerfallAction>();

            if (action)
            {
                action.Receive(player, DaggerfallAction.TriggerTypes.Attack);
            }

            // Check if hit has an DaggerfallActionDoor component
            DaggerfallActionDoor actionDoor = hit.transform.gameObject.GetComponent <DaggerfallActionDoor>();

            if (actionDoor)
            {
                actionDoor.AttemptBash();
                return(false);
            }

            // Check if hit an entity and remove health
            DaggerfallEntityBehaviour entityBehaviour  = hit.transform.GetComponent <DaggerfallEntityBehaviour>();
            DaggerfallMobileUnit      entityMobileUnit = hit.transform.GetComponentInChildren <DaggerfallMobileUnit>();

            if (entityBehaviour)
            {
                if (entityBehaviour.EntityType == EntityTypes.EnemyMonster || entityBehaviour.EntityType == EntityTypes.EnemyClass)
                {
                    EnemyEntity enemyEntity = entityBehaviour.Entity as EnemyEntity;

                    // Calculate damage
                    int damage;
                    if (!arrowHit)
                    {
                        if (usingRightHand)
                        {
                            strikingWeapon = currentRightHandWeapon;
                        }
                        else
                        {
                            strikingWeapon = currentLeftHandWeapon;
                        }
                    }
                    else
                    {
                        strikingWeapon = lastBowUsed;
                    }

                    damage = FormulaHelper.CalculateAttackDamage(playerEntity, enemyEntity, strikingWeapon, entityMobileUnit.Summary.AnimStateRecord);

                    // Break any "normal power" concealment effects on player
                    if (playerEntity.IsMagicallyConcealedNormalPower && damage > 0)
                    {
                        EntityEffectManager.BreakNormalPowerConcealmentEffects(GameManager.Instance.PlayerEntityBehaviour);
                    }

                    EnemyMotor  enemyMotor  = hit.transform.GetComponent <EnemyMotor>();
                    EnemySounds enemySounds = hit.transform.GetComponent <EnemySounds>();

                    // Play arrow sound and add arrow to target's inventory
                    if (arrowHit)
                    {
                        DaggerfallUnityItem arrow = ItemBuilder.CreateItem(ItemGroups.Weapons, (int)Weapons.Arrow);
                        enemyEntity.Items.AddItem(arrow);
                    }

                    // Play hit sound and trigger blood splash at hit point
                    if (damage > 0)
                    {
                        if (usingRightHand)
                        {
                            enemySounds.PlayHitSound(currentRightHandWeapon);
                        }
                        else
                        {
                            enemySounds.PlayHitSound(currentLeftHandWeapon);
                        }

                        EnemyBlood blood = hit.transform.GetComponent <EnemyBlood>();
                        if (blood)
                        {
                            blood.ShowBloodSplash(enemyEntity.MobileEnemy.BloodIndex, hit.point);
                        }

                        // Knock back enemy based on damage and enemy weight
                        if (enemyMotor)
                        {
                            if (enemyMotor.KnockBackSpeed <= (5 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)) &&
                                entityBehaviour.EntityType == EntityTypes.EnemyClass ||
                                enemyEntity.MobileEnemy.Weight > 0)
                            {
                                float enemyWeight    = enemyEntity.GetWeightInClassicUnits();
                                float tenTimesDamage = damage * 10;
                                float twoTimesDamage = damage * 2;

                                float knockBackAmount = ((tenTimesDamage - enemyWeight) * 256) / (enemyWeight + tenTimesDamage) * twoTimesDamage;
                                float knockBackSpeed  = (tenTimesDamage / enemyWeight) * (twoTimesDamage - (knockBackAmount / 256));
                                knockBackSpeed /= (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10);

                                if (knockBackSpeed < (15 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)))
                                {
                                    knockBackSpeed = (15 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10));
                                }
                                enemyMotor.KnockBackSpeed     = knockBackSpeed;
                                enemyMotor.KnockBackDirection = direction;
                            }
                        }

                        if (DaggerfallUnity.Settings.CombatVoices && entityBehaviour.EntityType == EntityTypes.EnemyClass && UnityEngine.Random.Range(1, 101) <= 40)
                        {
                            Genders gender;
                            if (entityMobileUnit.Summary.Enemy.Gender == MobileGender.Male || enemyEntity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch)
                            {
                                gender = Genders.Male;
                            }
                            else
                            {
                                gender = Genders.Female;
                            }

                            bool heavyDamage = damage >= enemyEntity.MaxHealth / 4;
                            enemySounds.PlayCombatVoice(gender, false, heavyDamage);
                        }
                    }
                    else
                    {
                        if ((!arrowHit && !enemyEntity.MobileEnemy.ParrySounds) || strikingWeapon == null)
                        {
                            ScreenWeapon.PlaySwingSound();
                        }
                        else if (enemyEntity.MobileEnemy.ParrySounds)
                        {
                            enemySounds.PlayParrySound();
                        }
                    }

                    // Remove health
                    enemyEntity.DecreaseHealth(damage);

                    // Assign "cast when strikes" to target entity
                    if (strikingWeapon != null && strikingWeapon.IsEnchanted)
                    {
                        EntityEffectManager enemyEffectManager = enemyEntity.EntityBehaviour.GetComponent <EntityEffectManager>();
                        if (enemyEffectManager)
                        {
                            enemyEffectManager.StrikeWithItem(strikingWeapon, GameManager.Instance.PlayerEntityBehaviour);
                        }
                    }

                    // Make foe attack their aggressor
                    // Currently this is just player, but should be expanded later
                    // for a wider variety of behaviours
                    if (enemyMotor)
                    {
                        // Make enemies in an area aggressive if player attacked a non-hostile one.
                        if (!enemyMotor.IsHostile)
                        {
                            GameManager.Instance.MakeEnemiesHostile();
                        }
                        enemyMotor.MakeEnemyHostileToAttacker(GameManager.Instance.PlayerEntityBehaviour);
                    }

                    return(true);
                }
            }

            // Check if hit a mobile NPC
            MobilePersonNPC mobileNpc = hit.transform.GetComponent <MobilePersonNPC>();

            if (mobileNpc)
            {
                EnemyBlood blood = hit.transform.GetComponent <EnemyBlood>();
                if (blood)
                {
                    blood.ShowBloodSplash(0, hit.point);
                }
                mobileNpc.Motor.gameObject.SetActive(false);
                playerEntity.TallyCrimeGuildRequirements(false, 5);
                // TODO: LOS check from each townsperson. If seen, register crime and start spawning guards as below.
                playerEntity.CrimeCommitted = PlayerEntity.Crimes.Murder;
                playerEntity.SpawnCityGuards(true);
            }

            return(false);
        }
        // Returns true if hit an enemy entity
        public bool WeaponDamage(DaggerfallUnityItem strikingWeapon, bool arrowHit, bool arrowSummoned, Transform hitTransform, Vector3 impactPosition, Vector3 direction)
        {
            DaggerfallEntityBehaviour entityBehaviour = hitTransform.GetComponent <DaggerfallEntityBehaviour>();
            var         entityMobileUnit = hitTransform.GetComponentInChildren <MobileUnit>();
            EnemyMotor  enemyMotor       = hitTransform.GetComponent <EnemyMotor>();
            EnemySounds enemySounds      = hitTransform.GetComponent <EnemySounds>();

            // Check if hit a mobile NPC
            MobilePersonNPC mobileNpc = hitTransform.GetComponent <MobilePersonNPC>();

            if (mobileNpc)
            {
                if (!mobileNpc.IsGuard)
                {
                    EnemyBlood blood = hitTransform.GetComponent <EnemyBlood>();
                    if (blood)
                    {
                        blood.ShowBloodSplash(0, impactPosition);
                    }
                    mobileNpc.Motor.gameObject.SetActive(false);
                    playerEntity.TallyCrimeGuildRequirements(false, 5);
                    playerEntity.CrimeCommitted = PlayerEntity.Crimes.Murder;
                    playerEntity.SpawnCityGuards(true);

                    // Allow custom race handling of weapon hit against mobile NPCs, e.g. vampire feeding or lycanthrope killing
                    if (entityBehaviour)
                    {
                        entityBehaviour.Entity.SetHealth(0);
                        RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();
                        if (racialOverride != null)
                        {
                            racialOverride.OnWeaponHitEntity(GameManager.Instance.PlayerEntity, entityBehaviour.Entity);
                        }
                    }
                }
                else
                {
                    playerEntity.CrimeCommitted = PlayerEntity.Crimes.Assault;
                    GameObject guard = playerEntity.SpawnCityGuard(mobileNpc.transform.position, mobileNpc.transform.forward);
                    entityBehaviour  = guard.GetComponent <DaggerfallEntityBehaviour>();
                    entityMobileUnit = guard.GetComponentInChildren <MobileUnit>();
                    enemyMotor       = guard.GetComponent <EnemyMotor>();
                    enemySounds      = guard.GetComponent <EnemySounds>();
                }
                mobileNpc.Motor.gameObject.SetActive(false);
            }

            // Check if hit an entity and remove health
            if (entityBehaviour)
            {
                if (entityBehaviour.EntityType == EntityTypes.EnemyMonster || entityBehaviour.EntityType == EntityTypes.EnemyClass)
                {
                    EnemyEntity enemyEntity = entityBehaviour.Entity as EnemyEntity;

                    // Calculate damage
                    int  animTime = (int)(ScreenWeapon.GetAnimTime() * 1000);   // Get animation time, converted to ms.
                    bool isEnemyFacingAwayFromPlayer = entityMobileUnit.IsBackFacing &&
                                                       entityMobileUnit.EnemyState != MobileStates.SeducerTransform1 &&
                                                       entityMobileUnit.EnemyState != MobileStates.SeducerTransform2;
                    int damage = FormulaHelper.CalculateAttackDamage(playerEntity, enemyEntity, isEnemyFacingAwayFromPlayer, animTime, strikingWeapon);

                    // Break any "normal power" concealment effects on player
                    if (playerEntity.IsMagicallyConcealedNormalPower && damage > 0)
                    {
                        EntityEffectManager.BreakNormalPowerConcealmentEffects(GameManager.Instance.PlayerEntityBehaviour);
                    }

                    // Add arrow to target's inventory
                    if (arrowHit && !arrowSummoned)
                    {
                        DaggerfallUnityItem arrow = ItemBuilder.CreateItem(ItemGroups.Weapons, (int)Weapons.Arrow);
                        enemyEntity.Items.AddItem(arrow);
                    }

                    // Play hit sound and trigger blood splash at hit point
                    if (damage > 0)
                    {
                        if (usingRightHand)
                        {
                            enemySounds.PlayHitSound(currentRightHandWeapon);
                        }
                        else
                        {
                            enemySounds.PlayHitSound(currentLeftHandWeapon);
                        }

                        EnemyBlood blood = hitTransform.GetComponent <EnemyBlood>();
                        if (blood)
                        {
                            blood.ShowBloodSplash(enemyEntity.MobileEnemy.BloodIndex, impactPosition);
                        }

                        // Knock back enemy based on damage and enemy weight
                        if (enemyMotor)
                        {
                            if (enemyMotor.KnockbackSpeed <= (5 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)) &&
                                entityBehaviour.EntityType == EntityTypes.EnemyClass ||
                                enemyEntity.MobileEnemy.Weight > 0)
                            {
                                float enemyWeight    = enemyEntity.GetWeightInClassicUnits();
                                float tenTimesDamage = damage * 10;
                                float twoTimesDamage = damage * 2;

                                float knockBackAmount = ((tenTimesDamage - enemyWeight) * 256) / (enemyWeight + tenTimesDamage) * twoTimesDamage;
                                float KnockbackSpeed  = (tenTimesDamage / enemyWeight) * (twoTimesDamage - (knockBackAmount / 256));
                                KnockbackSpeed /= (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10);

                                if (KnockbackSpeed < (15 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)))
                                {
                                    KnockbackSpeed = (15 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10));
                                }
                                enemyMotor.KnockbackSpeed     = KnockbackSpeed;
                                enemyMotor.KnockbackDirection = direction;
                            }
                        }

                        if (DaggerfallUnity.Settings.CombatVoices && entityBehaviour.EntityType == EntityTypes.EnemyClass && Dice100.SuccessRoll(40))
                        {
                            Genders gender;
                            if (entityMobileUnit.Enemy.Gender == MobileGender.Male || enemyEntity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch)
                            {
                                gender = Genders.Male;
                            }
                            else
                            {
                                gender = Genders.Female;
                            }

                            bool heavyDamage = damage >= enemyEntity.MaxHealth / 4;
                            enemySounds.PlayCombatVoice(gender, false, heavyDamage);
                        }
                    }
                    else
                    {
                        if ((!arrowHit && !enemyEntity.MobileEnemy.ParrySounds) || strikingWeapon == null)
                        {
                            ScreenWeapon.PlaySwingSound();
                        }
                        else if (enemyEntity.MobileEnemy.ParrySounds)
                        {
                            enemySounds.PlayParrySound();
                        }
                    }

                    // Handle weapon striking enchantments - this could change damage amount
                    if (strikingWeapon != null && strikingWeapon.IsEnchanted)
                    {
                        EntityEffectManager effectManager = GetComponent <EntityEffectManager>();
                        if (effectManager)
                        {
                            damage = effectManager.DoItemEnchantmentPayloads(EnchantmentPayloadFlags.Strikes, strikingWeapon, GameManager.Instance.PlayerEntity.Items, enemyEntity.EntityBehaviour, damage);
                        }
                        strikingWeapon.RaiseOnWeaponStrikeEvent(entityBehaviour, damage);
                    }

                    // Remove health
                    enemyEntity.DecreaseHealth(damage);

                    // Handle attack from player
                    enemyEntity.EntityBehaviour.HandleAttackFromSource(GameManager.Instance.PlayerEntityBehaviour);

                    // Allow custom race handling of weapon hit against enemies, e.g. vampire feeding or lycanthrope killing
                    RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();
                    if (racialOverride != null)
                    {
                        racialOverride.OnWeaponHitEntity(GameManager.Instance.PlayerEntity, entityBehaviour.Entity);
                    }

                    return(true);
                }
            }

            return(false);
        }
示例#7
0
        private void WeaponDamage(FPSWeapon weapon, out bool hitEnemy)
        {
            hitEnemy = false;

            if (!mainCamera || !weapon)
            {
                return;
            }

            // Fire ray along player facing using weapon range
            RaycastHit hit;
            Ray        ray = new Ray(mainCamera.transform.position, mainCamera.transform.forward);

            if (Physics.SphereCast(ray, SphereCastRadius, out hit, weapon.Reach - SphereCastRadius))
            {
                // Check if hit has an DaggerfallAction component
                DaggerfallAction action = hit.transform.gameObject.GetComponent <DaggerfallAction>();
                if (action)
                {
                    action.Receive(player, DaggerfallAction.TriggerTypes.Attack);
                }

                // Check if hit has an DaggerfallActionDoor component
                DaggerfallActionDoor actionDoor = hit.transform.gameObject.GetComponent <DaggerfallActionDoor>();
                if (actionDoor)
                {
                    actionDoor.AttemptBash();
                    return;
                }

                // Check if hit an entity and remove health
                DaggerfallEntityBehaviour entityBehaviour = hit.transform.GetComponent <DaggerfallEntityBehaviour>();
                if (entityBehaviour)
                {
                    if (entityBehaviour.EntityType == EntityTypes.EnemyMonster || entityBehaviour.EntityType == EntityTypes.EnemyClass)
                    {
                        EnemyEntity enemyEntity = entityBehaviour.Entity as EnemyEntity;

                        // Calculate damage
                        int damage = FormulaHelper.CalculateWeaponDamage(playerEntity, enemyEntity, weapon);

                        // Play hit sound and trigger blood splash at hit point
                        if (damage > 0)
                        {
                            weapon.PlayHitSound();
                            EnemyBlood blood = hit.transform.GetComponent <EnemyBlood>();
                            if (blood)
                            {
                                blood.ShowBloodSplash(enemyEntity.MobileEnemy.BloodIndex, hit.point);
                            }
                        }
                        else
                        {
                            if (!enemyEntity.MobileEnemy.ParrySounds || weapon.WeaponType == WeaponTypes.Melee)
                            {
                                weapon.PlaySwingSound();
                            }
                            else
                            {
                                weapon.PlayParrySound();
                            }
                        }

                        // Remove health
                        enemyEntity.DecreaseHealth(damage);
                        hitEnemy = true;

                        // Make foe attack their aggressor
                        // Currently this is just player, but should be expanded later
                        // for a wider variety of behaviours
                        EnemyMotor enemyMotor = hit.transform.GetComponent <EnemyMotor>();
                        if (enemyMotor)
                        {
                            // Make enemies in an area aggressive if player attacked a non-hostile one.
                            if (!enemyMotor.IsHostile)
                            {
                                GameManager.Instance.MakeEnemiesHostile();
                            }
                            enemyMotor.MakeEnemyHostileToPlayer(gameObject);
                        }
                    }
                }

                // Check if hit a mobile NPC
                MobilePersonNPC mobileNpc = hit.transform.GetComponent <MobilePersonNPC>();
                if (mobileNpc)
                {
                    // TODO: Create blood splash.
                    weapon.PlayHitSound();
                    mobileNpc.Motor.gameObject.SetActive(false);
                    //GameManager.Instance.PlayerEntity.TallyCrimeGuildRequirements(false, 5);
                }
            }
        }
        void Update()
        {
            if (mainCamera == null)
            {
                return;
            }

            // Change activate mode
            if (InputManager.Instance.ActionStarted(InputManager.Actions.StealMode))
            {
                ChangeInteractionMode(PlayerActivateModes.Steal);
            }
            else if (InputManager.Instance.ActionStarted(InputManager.Actions.GrabMode))
            {
                ChangeInteractionMode(PlayerActivateModes.Grab);
            }
            else if (InputManager.Instance.ActionStarted(InputManager.Actions.InfoMode))
            {
                ChangeInteractionMode(PlayerActivateModes.Info);
            }
            else if (InputManager.Instance.ActionStarted(InputManager.Actions.TalkMode))
            {
                ChangeInteractionMode(PlayerActivateModes.Talk);
            }

            // Fire ray into scene
            if (InputManager.Instance.ActionStarted(InputManager.Actions.ActivateCenterObject))
            {
                // TODO: Clean all this up

                // Ray origin is slightly below camera height to ensure it originates inside player's own collider
                // This prevents ray from intersecting with player's own collider and blocking looting or low triggers
                Ray        ray = new Ray(transform.position + Vector3.up * 0.7f, mainCamera.transform.forward);
                RaycastHit hit;
                RayDistance = 75f; // Approximates classic at full view distance (default setting). Classic seems to do raycasts for as far as it can render objects.
                bool hitSomething = Physics.Raycast(ray, out hit, RayDistance);
                if (hitSomething)
                {
                    bool hitBuilding      = false;
                    bool buildingUnlocked = false;
                    DFLocation.BuildingTypes buildingType = DFLocation.BuildingTypes.AllValid;
                    StaticBuilding           building     = new StaticBuilding();

                    #region Hit Checks

                    // Trigger quest resource behaviour click on anything but NPCs
                    QuestResourceBehaviour questResourceBehaviour;
                    if (QuestResourceBehaviourCheck(hit, out questResourceBehaviour))
                    {
                        if (!(questResourceBehaviour.TargetResource is Person))
                        {
                            if (hit.distance > (DefaultActivationDistance * MeshReader.GlobalScale))
                            {
                                DaggerfallUI.SetMidScreenText(HardStrings.youAreTooFarAway);
                                return;
                            }

                            // Only trigger click when not in info mode
                            if (currentMode != PlayerActivateModes.Info)
                            {
                                TriggerQuestResourceBehaviourClick(questResourceBehaviour);
                            }
                        }
                    }

                    // Check for a static building hit
                    Transform buildingOwner;
                    DaggerfallStaticBuildings buildings = GetBuildings(hit.transform, out buildingOwner);
                    if (buildings)
                    {
                        if (buildings.HasHit(hit.point, out building))
                        {
                            hitBuilding = true;

                            // Get building directory for location
                            BuildingDirectory buildingDirectory = GameManager.Instance.StreamingWorld.GetCurrentBuildingDirectory();
                            if (!buildingDirectory)
                            {
                                return;
                            }

                            // Get detailed building data from directory
                            BuildingSummary buildingSummary;
                            if (!buildingDirectory.GetBuildingSummary(building.buildingKey, out buildingSummary))
                            {
                                return;
                            }

                            // Check if door is unlocked
                            buildingUnlocked = BuildingIsUnlocked(buildingSummary);

                            // Store building type
                            buildingType = buildingSummary.BuildingType;

                            if (currentMode == PlayerActivateModes.Info)
                            {
                                // Discover building
                                GameManager.Instance.PlayerGPS.DiscoverBuilding(building.buildingKey);

                                // Get discovered building
                                PlayerGPS.DiscoveredBuilding db;
                                if (GameManager.Instance.PlayerGPS.GetDiscoveredBuilding(building.buildingKey, out db))
                                {
                                    // TODO: Check against quest system for an overriding quest-assigned display name for this building
                                    DaggerfallUI.AddHUDText(db.displayName);

                                    if (!buildingUnlocked && buildingType < DFLocation.BuildingTypes.Temple &&
                                        buildingType != DFLocation.BuildingTypes.HouseForSale)
                                    {
                                        string storeClosedMessage = HardStrings.storeClosed;
                                        storeClosedMessage = storeClosedMessage.Replace("%d1", openHours[(int)buildingType].ToString());
                                        storeClosedMessage = storeClosedMessage.Replace("%d2", closeHours[(int)buildingType].ToString());
                                        DaggerfallUI.Instance.PopupMessage(storeClosedMessage);
                                    }
                                }
                            }
                        }
                    }

                    // Check for a static door hit
                    Transform             doorOwner;
                    DaggerfallStaticDoors doors = GetDoors(hit.transform, out doorOwner);
                    if (doors && playerEnterExit)
                    {
                        StaticDoor door;
                        if (doors.HasHit(hit.point, out door))
                        {
                            // Check if close enough to activate
                            if (hit.distance > (DoorActivationDistance * MeshReader.GlobalScale))
                            {
                                DaggerfallUI.SetMidScreenText(HardStrings.youAreTooFarAway);
                                return;
                            }

                            if (door.doorType == DoorTypes.Building && !playerEnterExit.IsPlayerInside)
                            {
                                // Discover building
                                GameManager.Instance.PlayerGPS.DiscoverBuilding(building.buildingKey);

                                // TODO: Implement lockpicking and door bashing for exterior doors
                                // For now, any locked building door can be entered by using steal mode
                                if (!buildingUnlocked)
                                {
                                    if (currentMode != PlayerActivateModes.Steal)
                                    {
                                        string Locked = "Locked.";
                                        DaggerfallUI.Instance.PopupMessage(Locked);
                                        return;
                                    }
                                    else     // Breaking into building
                                    {
                                        PlayerEntity player = GameManager.Instance.PlayerEntity;
                                        //player.TallyCrimeGuildRequirements(true, 1);
                                    }
                                }

                                // If entering a shop let player know the quality level
                                // If entering an open home, show greeting
                                if (hitBuilding)
                                {
                                    const int houseGreetingsTextId = 256;

                                    DaggerfallMessageBox mb;

                                    if (buildingUnlocked && buildingType >= DFLocation.BuildingTypes.House1 &&
                                        buildingType <= DFLocation.BuildingTypes.House4)
                                    {
                                        string greetingText = DaggerfallUnity.Instance.TextProvider.GetRandomText(houseGreetingsTextId);
                                        mb = DaggerfallUI.MessageBox(greetingText);
                                    }
                                    else
                                    {
                                        mb = PresentShopQuality(building);
                                    }

                                    if (mb != null)
                                    {
                                        // Defer transition to interior to after user closes messagebox
                                        deferredInteriorDoorOwner = doorOwner;
                                        deferredInteriorDoor      = door;
                                        mb.OnClose += Popup_OnClose;
                                        return;
                                    }
                                }

                                // Hit door while outside, transition inside
                                TransitionInterior(doorOwner, door, true);
                                return;
                            }
                            else if (door.doorType == DoorTypes.Building && playerEnterExit.IsPlayerInside)
                            {
                                // Hit door while inside, transition outside
                                playerEnterExit.TransitionExterior(true);
                                return;
                            }
                            else if (door.doorType == DoorTypes.DungeonEntrance && !playerEnterExit.IsPlayerInside)
                            {
                                if (playerGPS)
                                {
                                    // Hit dungeon door while outside, transition inside
                                    playerEnterExit.TransitionDungeonInterior(doorOwner, door, playerGPS.CurrentLocation, true);
                                    return;
                                }
                            }
                            else if (door.doorType == DoorTypes.DungeonExit && playerEnterExit.IsPlayerInside)
                            {
                                // Hit dungeon exit while inside, ask if access wagon or transition outside
                                if (GameManager.Instance.PlayerEntity.Items.Contains(ItemGroups.Transportation, (int)Transportation.Small_cart))
                                {
                                    DaggerfallMessageBox messageBox = new DaggerfallMessageBox(DaggerfallUI.UIManager, DaggerfallMessageBox.CommonMessageBoxButtons.YesNo, 38, DaggerfallUI.UIManager.TopWindow);
                                    messageBox.OnButtonClick += DungeonWagonAccess_OnButtonClick;
                                    DaggerfallUI.UIManager.PushWindow(messageBox);
                                    return;
                                }
                                else
                                {
                                    playerEnterExit.TransitionDungeonExterior(true);
                                }
                            }
                        }
                    }

                    // Check for an action door hit
                    DaggerfallActionDoor actionDoor;
                    if (ActionDoorCheck(hit, out actionDoor))
                    {
                        // Check if close enough to activate
                        if (hit.distance > (DoorActivationDistance * MeshReader.GlobalScale))
                        {
                            DaggerfallUI.SetMidScreenText(HardStrings.youAreTooFarAway);
                            return;
                        }

                        if (currentMode == PlayerActivateModes.Steal && actionDoor.IsLocked && !actionDoor.IsOpen)
                        {
                            actionDoor.AttemptLockpicking();
                        }
                        else
                        {
                            actionDoor.ToggleDoor(true);
                        }
                    }

                    // Check for action record hit
                    DaggerfallAction action;
                    if (ActionCheck(hit, out action))
                    {
                        if (hit.distance <= (DefaultActivationDistance * MeshReader.GlobalScale))
                        {
                            action.Receive(this.gameObject, DaggerfallAction.TriggerTypes.Direct);
                        }
                    }

                    // Check for lootable object hit
                    DaggerfallLoot loot;
                    if (LootCheck(hit, out loot))
                    {
                        switch (currentMode)
                        {
                        case PlayerActivateModes.Info:
                            if (loot.ContainerType == LootContainerTypes.CorpseMarker && !string.IsNullOrEmpty(loot.entityName))
                            {
                                string message = string.Empty;
                                if (loot.isEnemyClass)
                                {
                                    message = HardStrings.youSeeADeadPerson;
                                }
                                else
                                {
                                    message = HardStrings.youSeeADead;
                                    message = message.Replace("%s", loot.entityName);
                                }
                                DaggerfallUI.Instance.PopupMessage(message);
                            }
                            break;

                        case PlayerActivateModes.Grab:
                        case PlayerActivateModes.Talk:
                        case PlayerActivateModes.Steal:
                            // Check if close enough to activate
                            if (loot.ContainerType == LootContainerTypes.CorpseMarker)
                            {
                                if (hit.distance > CorpseActivationDistance * MeshReader.GlobalScale)
                                {
                                    DaggerfallUI.SetMidScreenText(HardStrings.youAreTooFarAway);
                                    break;
                                }
                            }
                            else if (hit.distance > TreasureActivationDistance * MeshReader.GlobalScale)
                            {
                                DaggerfallUI.SetMidScreenText(HardStrings.youAreTooFarAway);
                                break;
                            }

                            // For bodies, check has treasure first
                            if (loot.ContainerType == LootContainerTypes.CorpseMarker && loot.Items.Count == 0)
                            {
                                DaggerfallUI.AddHUDText(HardStrings.theBodyHasNoTreasure);
                                break;
                            }

                            // Open inventory window with loot as remote target
                            DaggerfallUI.Instance.InventoryWindow.LootTarget = loot;
                            DaggerfallUI.PostMessage(DaggerfallUIMessages.dfuiOpenInventoryWindow);
                            break;
                        }
                    }

                    // Check for static NPC hit
                    StaticNPC npc;
                    if (NPCCheck(hit, out npc))
                    {
                        switch (currentMode)
                        {
                        case PlayerActivateModes.Info:
                            PresentNPCInfo(npc);
                            break;

                        case PlayerActivateModes.Grab:
                        case PlayerActivateModes.Talk:
                        case PlayerActivateModes.Steal:
                            if (hit.distance > (StaticNPCActivationDistance * MeshReader.GlobalScale))
                            {
                                DaggerfallUI.SetMidScreenText(HardStrings.youAreTooFarAway);
                                break;
                            }
                            StaticNPCClick(npc);
                            break;
                        }
                    }

                    // Check for mobile NPC hit
                    MobilePersonNPC mobileNpc = null;
                    if (MobilePersonMotorCheck(hit, out mobileNpc))
                    {
                        switch (currentMode)
                        {
                        case PlayerActivateModes.Info:
                        case PlayerActivateModes.Grab:
                        case PlayerActivateModes.Talk:
                            if (hit.distance > (MobileNPCActivationDistance * MeshReader.GlobalScale))
                            {
                                DaggerfallUI.SetMidScreenText(HardStrings.youAreTooFarAway);
                                break;
                            }
                            GameManager.Instance.TalkManager.TalkToMobileNPC(mobileNpc);
                            break;

                        case PlayerActivateModes.Steal:
                            if (!mobileNpc.PickpocketByPlayerAttempted)
                            {
                                if (hit.distance > (PickpocketDistance * MeshReader.GlobalScale))
                                {
                                    DaggerfallUI.SetMidScreenText(HardStrings.youAreTooFarAway);
                                    break;
                                }
                                mobileNpc.PickpocketByPlayerAttempted = true;
                                Pickpocket();
                            }
                            break;
                        }
                    }

                    // Check for mobile enemy hit
                    DaggerfallEntityBehaviour mobileEnemyBehaviour;
                    if (MobileEnemyCheck(hit, out mobileEnemyBehaviour))
                    {
                        EnemyEntity enemyEntity = mobileEnemyBehaviour.Entity as EnemyEntity;
                        switch (currentMode)
                        {
                        case PlayerActivateModes.Info:
                        case PlayerActivateModes.Grab:
                        case PlayerActivateModes.Talk:
                            if (enemyEntity != null)
                            {
                                MobileEnemy mobileEnemy     = enemyEntity.MobileEnemy;
                                bool        startsWithVowel = "aeiouAEIOU".Contains(mobileEnemy.Name[0].ToString());
                                string      message;
                                if (startsWithVowel)
                                {
                                    message = HardStrings.youSeeAn;
                                }
                                else
                                {
                                    message = HardStrings.youSeeA;
                                }
                                message = message.Replace("%s", mobileEnemy.Name);
                                DaggerfallUI.Instance.PopupMessage(message);
                            }
                            break;

                        case PlayerActivateModes.Steal:
                            // Classic allows pickpocketing of NPC mobiles and enemy mobiles.
                            // In early versions the only enemy mobiles that can be pickpocketed are classes,
                            // but patch 1.07.212 allows pickpocketing of creatures.
                            // For now, the only enemy mobiles being allowed by DF Unity are classes.
                            if (mobileEnemyBehaviour && (mobileEnemyBehaviour.EntityType != EntityTypes.EnemyClass))
                            {
                                break;
                            }
                            // Classic doesn't set any flag when pickpocketing enemy mobiles, so infinite attempts are possible
                            if (enemyEntity != null && !enemyEntity.PickpocketByPlayerAttempted)
                            {
                                if (hit.distance > (PickpocketDistance * MeshReader.GlobalScale))
                                {
                                    DaggerfallUI.SetMidScreenText(HardStrings.youAreTooFarAway);
                                    break;
                                }
                                enemyEntity.PickpocketByPlayerAttempted = true;
                                Pickpocket(mobileEnemyBehaviour);
                            }
                            break;
                        }
                    }

                    // Trigger ladder hit
                    DaggerfallLadder ladder = hit.transform.GetComponent <DaggerfallLadder>();
                    if (ladder)
                    {
                        if (hit.distance > (DefaultActivationDistance * MeshReader.GlobalScale))
                        {
                            DaggerfallUI.SetMidScreenText(HardStrings.youAreTooFarAway);
                            return;
                        }

                        ladder.ClimbLadder();
                    }

                    #endregion
                }
            }
        }
        // Returns true if hit an enemy entity
        public bool WeaponDamage(RaycastHit hit, Vector3 direction, Collider arrowHitCollider = null, bool arrowHit = false)
        {
            DaggerfallUnityItem strikingWeapon = null;

            if (!arrowHit)
            {
                // Check if hit has an DaggerfallAction component
                DaggerfallAction action = hit.transform.gameObject.GetComponent <DaggerfallAction>();
                if (action)
                {
                    action.Receive(player, DaggerfallAction.TriggerTypes.Attack);
                }

                // Check if hit has an DaggerfallActionDoor component
                DaggerfallActionDoor actionDoor = hit.transform.gameObject.GetComponent <DaggerfallActionDoor>();
                if (actionDoor)
                {
                    actionDoor.AttemptBash(true);
                    return(false);
                }

                // Check if player hit a static exterior door
                if (GameManager.Instance.PlayerActivate.AttemptExteriorDoorBash(hit))
                {
                    return(false);
                }
            }

            // Set up for use below
            DaggerfallEntityBehaviour entityBehaviour  = null;
            DaggerfallMobileUnit      entityMobileUnit = null;
            EnemyMotor  enemyMotor  = null;
            EnemySounds enemySounds = null;

            if (!arrowHit)
            {
                entityBehaviour  = hit.transform.GetComponent <DaggerfallEntityBehaviour>();
                entityMobileUnit = hit.transform.GetComponentInChildren <DaggerfallMobileUnit>();
                enemyMotor       = hit.transform.GetComponent <EnemyMotor>();
                enemySounds      = hit.transform.GetComponent <EnemySounds>();
            }
            else if (arrowHitCollider != null)
            {
                entityBehaviour  = arrowHitCollider.gameObject.transform.GetComponent <DaggerfallEntityBehaviour>();
                entityMobileUnit = arrowHitCollider.gameObject.transform.GetComponentInChildren <DaggerfallMobileUnit>();
                enemyMotor       = arrowHitCollider.gameObject.transform.GetComponent <EnemyMotor>();
                enemySounds      = arrowHitCollider.gameObject.transform.GetComponent <EnemySounds>();
            }

            // Check if hit a mobile NPC
            MobilePersonNPC mobileNpc = null;

            if (!arrowHit)
            {
                mobileNpc = hit.transform.GetComponent <MobilePersonNPC>();
            }
            else if (arrowHitCollider != null)
            {
                mobileNpc = arrowHitCollider.gameObject.transform.GetComponent <MobilePersonNPC>();
            }

            if (mobileNpc)
            {
                if (!mobileNpc.Billboard.IsUsingGuardTexture)
                {
                    EnemyBlood blood = null;
                    if (!arrowHit)
                    {
                        blood = hit.transform.GetComponent <EnemyBlood>();
                    }
                    else if (arrowHitCollider != null)
                    {
                        blood = arrowHitCollider.gameObject.transform.GetComponent <EnemyBlood>();
                    }

                    if (blood)
                    {
                        if (!arrowHit)
                        {
                            blood.ShowBloodSplash(0, hit.point);
                        }
                        else
                        {
                            blood.ShowBloodSplash(0, arrowHitCollider.gameObject.transform.position);
                        }
                    }
                    mobileNpc.Motor.gameObject.SetActive(false);
                    playerEntity.TallyCrimeGuildRequirements(false, 5);
                    playerEntity.CrimeCommitted = PlayerEntity.Crimes.Murder;
                    playerEntity.SpawnCityGuards(true);

                    // Allow custom race handling of weapon hit against mobile NPCs, e.g. vampire feeding or lycanthrope killing
                    if (entityBehaviour)
                    {
                        entityBehaviour.Entity.SetHealth(0);
                        RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();
                        if (racialOverride != null)
                        {
                            racialOverride.OnWeaponHitEntity(GameManager.Instance.PlayerEntity, entityBehaviour.Entity);
                        }
                    }
                }
                else
                {
                    playerEntity.CrimeCommitted = PlayerEntity.Crimes.Assault;
                    GameObject guard = playerEntity.SpawnCityGuard(mobileNpc.transform.position, mobileNpc.transform.forward);
                    entityBehaviour  = guard.GetComponent <DaggerfallEntityBehaviour>();
                    entityMobileUnit = guard.GetComponentInChildren <DaggerfallMobileUnit>();
                    enemyMotor       = guard.GetComponent <EnemyMotor>();
                    enemySounds      = guard.GetComponent <EnemySounds>();
                }
                mobileNpc.Motor.gameObject.SetActive(false);
            }

            // Check if hit an entity and remove health
            if (entityBehaviour)
            {
                if (entityBehaviour.EntityType == EntityTypes.EnemyMonster || entityBehaviour.EntityType == EntityTypes.EnemyClass)
                {
                    EnemyEntity enemyEntity = entityBehaviour.Entity as EnemyEntity;

                    // Calculate damage
                    int damage;
                    if (!arrowHit)
                    {
                        if (usingRightHand)
                        {
                            strikingWeapon = currentRightHandWeapon;
                        }
                        else
                        {
                            strikingWeapon = currentLeftHandWeapon;
                        }
                    }
                    else
                    {
                        strikingWeapon = lastBowUsed;
                    }

                    damage = FormulaHelper.CalculateAttackDamage(playerEntity, enemyEntity, strikingWeapon, entityMobileUnit.Summary.AnimStateRecord);

                    // Break any "normal power" concealment effects on player
                    if (playerEntity.IsMagicallyConcealedNormalPower && damage > 0)
                    {
                        EntityEffectManager.BreakNormalPowerConcealmentEffects(GameManager.Instance.PlayerEntityBehaviour);
                    }

                    // Play arrow sound and add arrow to target's inventory
                    if (arrowHit)
                    {
                        DaggerfallUnityItem arrow = ItemBuilder.CreateItem(ItemGroups.Weapons, (int)Weapons.Arrow);
                        enemyEntity.Items.AddItem(arrow);
                    }

                    // Play hit sound and trigger blood splash at hit point
                    if (damage > 0)
                    {
                        if (usingRightHand)
                        {
                            enemySounds.PlayHitSound(currentRightHandWeapon);
                        }
                        else
                        {
                            enemySounds.PlayHitSound(currentLeftHandWeapon);
                        }

                        EnemyBlood blood = null;
                        if (!arrowHit)
                        {
                            blood = hit.transform.GetComponent <EnemyBlood>();
                        }
                        else if (arrowHitCollider != null)
                        {
                            blood = arrowHitCollider.gameObject.transform.GetComponent <EnemyBlood>();
                        }

                        if (blood)
                        {
                            blood.ShowBloodSplash(enemyEntity.MobileEnemy.BloodIndex, hit.point);
                        }

                        // Knock back enemy based on damage and enemy weight
                        if (enemyMotor)
                        {
                            if (enemyMotor.KnockbackSpeed <= (5 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)) &&
                                entityBehaviour.EntityType == EntityTypes.EnemyClass ||
                                enemyEntity.MobileEnemy.Weight > 0)
                            {
                                float enemyWeight    = enemyEntity.GetWeightInClassicUnits();
                                float tenTimesDamage = damage * 10;
                                float twoTimesDamage = damage * 2;

                                float knockBackAmount = ((tenTimesDamage - enemyWeight) * 256) / (enemyWeight + tenTimesDamage) * twoTimesDamage;
                                float KnockbackSpeed  = (tenTimesDamage / enemyWeight) * (twoTimesDamage - (knockBackAmount / 256));
                                KnockbackSpeed /= (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10);

                                if (KnockbackSpeed < (15 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)))
                                {
                                    KnockbackSpeed = (15 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10));
                                }
                                enemyMotor.KnockbackSpeed     = KnockbackSpeed;
                                enemyMotor.KnockbackDirection = direction;
                            }
                        }

                        if (DaggerfallUnity.Settings.CombatVoices && entityBehaviour.EntityType == EntityTypes.EnemyClass && Dice100.SuccessRoll(40))
                        {
                            Genders gender;
                            if (entityMobileUnit.Summary.Enemy.Gender == MobileGender.Male || enemyEntity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch)
                            {
                                gender = Genders.Male;
                            }
                            else
                            {
                                gender = Genders.Female;
                            }

                            bool heavyDamage = damage >= enemyEntity.MaxHealth / 4;
                            enemySounds.PlayCombatVoice(gender, false, heavyDamage);
                        }
                    }
                    else
                    {
                        if ((!arrowHit && !enemyEntity.MobileEnemy.ParrySounds) || strikingWeapon == null)
                        {
                            ScreenWeapon.PlaySwingSound();
                        }
                        else if (enemyEntity.MobileEnemy.ParrySounds)
                        {
                            enemySounds.PlayParrySound();
                        }
                    }

                    // Handle weapon striking enchantments - this could change damage amount
                    if (strikingWeapon != null && strikingWeapon.IsEnchanted)
                    {
                        EntityEffectManager effectManager = GetComponent <EntityEffectManager>();
                        if (effectManager)
                        {
                            damage = effectManager.DoItemEnchantmentPayloads(EnchantmentPayloadFlags.Strikes, strikingWeapon, GameManager.Instance.PlayerEntity.Items, enemyEntity.EntityBehaviour, damage);
                        }
                        strikingWeapon.RaiseOnWeaponStrikeEvent(entityBehaviour, damage);
                    }

                    // Remove health
                    enemyEntity.DecreaseHealth(damage);

                    // Make foe attack their aggressor
                    // Currently this is just player, but should be expanded later
                    // for a wider variety of behaviours
                    if (enemyMotor)
                    {
                        // Make enemies in an area aggressive if player attacked a non-hostile one.
                        if (!enemyMotor.IsHostile)
                        {
                            GameManager.Instance.MakeEnemiesHostile();
                        }
                        enemyMotor.MakeEnemyHostileToAttacker(GameManager.Instance.PlayerEntityBehaviour);
                    }

                    if (enemyEntity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch && enemyEntity.CurrentHealth <= 0)
                    {
                        playerEntity.TallyCrimeGuildRequirements(false, 1);
                        playerEntity.CrimeCommitted = PlayerEntity.Crimes.Murder;
                    }

                    // Allow custom race handling of weapon hit against enemies, e.g. vampire feeding or lycanthrope killing
                    RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();
                    if (racialOverride != null)
                    {
                        racialOverride.OnWeaponHitEntity(GameManager.Instance.PlayerEntity, entityBehaviour.Entity);
                    }

                    return(true);
                }
            }

            return(false);
        }
        private void WeaponDamage(FPSWeapon weapon, out bool hitEnemy)
        {
            hitEnemy = false;
            DaggerfallUnityItem strikingWeapon = null;

            if (!mainCamera || !weapon)
            {
                return;
            }

            // Fire ray along player facing using weapon range
            // Origin point of ray is set back slightly to fix issue where strikes against enemy capsules touching player capsule do not connect
            RaycastHit hit;
            Ray        ray = new Ray(mainCamera.transform.position + -mainCamera.transform.forward * 0.1f, mainCamera.transform.forward);

            if (Physics.SphereCast(ray, SphereCastRadius, out hit, weapon.Reach - SphereCastRadius))
            {
                // Check if hit has an DaggerfallAction component
                DaggerfallAction action = hit.transform.gameObject.GetComponent <DaggerfallAction>();
                if (action)
                {
                    action.Receive(player, DaggerfallAction.TriggerTypes.Attack);
                }

                // Check if hit has an DaggerfallActionDoor component
                DaggerfallActionDoor actionDoor = hit.transform.gameObject.GetComponent <DaggerfallActionDoor>();
                if (actionDoor)
                {
                    actionDoor.AttemptBash();
                    return;
                }

                // Check if hit an entity and remove health
                DaggerfallEntityBehaviour entityBehaviour  = hit.transform.GetComponent <DaggerfallEntityBehaviour>();
                DaggerfallMobileUnit      entityMobileUnit = hit.transform.GetComponentInChildren <DaggerfallMobileUnit>();
                if (entityBehaviour)
                {
                    if (entityBehaviour.EntityType == EntityTypes.EnemyMonster || entityBehaviour.EntityType == EntityTypes.EnemyClass)
                    {
                        EnemyEntity enemyEntity = entityBehaviour.Entity as EnemyEntity;

                        // Calculate damage
                        int damage;
                        if (usingRightHand)
                        {
                            damage         = FormulaHelper.CalculateAttackDamage(playerEntity, enemyEntity, (int)(EquipSlots.RightHand), entityMobileUnit.Summary.AnimStateRecord);
                            strikingWeapon = currentRightHandWeapon;
                        }
                        else
                        {
                            damage         = FormulaHelper.CalculateAttackDamage(playerEntity, enemyEntity, (int)(EquipSlots.LeftHand), entityMobileUnit.Summary.AnimStateRecord);
                            strikingWeapon = currentLeftHandWeapon;
                        }

                        // Break any "normal power" concealment effects on player
                        if (playerEntity.IsMagicallyConcealedNormalPower && damage > 0)
                        {
                            EntityEffectManager.BreakNormalPowerConcealmentEffects(GameManager.Instance.PlayerEntityBehaviour);
                        }

                        EnemyMotor  enemyMotor  = hit.transform.GetComponent <EnemyMotor>();
                        EnemySounds enemySounds = hit.transform.GetComponent <EnemySounds>();

                        // Play arrow sound and add arrow to target's inventory
                        if (weapon.WeaponType == WeaponTypes.Bow)
                        {
                            enemySounds.PlayArrowSound();
                            DaggerfallUnityItem arrow = ItemBuilder.CreateItem(ItemGroups.Weapons, (int)Weapons.Arrow);
                            enemyEntity.Items.AddItem(arrow);
                        }

                        // Play hit sound and trigger blood splash at hit point
                        if (damage > 0)
                        {
                            if (usingRightHand)
                            {
                                enemySounds.PlayHitSound(currentRightHandWeapon);
                            }
                            else
                            {
                                enemySounds.PlayHitSound(currentLeftHandWeapon);
                            }

                            EnemyBlood blood = hit.transform.GetComponent <EnemyBlood>();
                            if (blood)
                            {
                                blood.ShowBloodSplash(enemyEntity.MobileEnemy.BloodIndex, hit.point);
                            }

                            // Knock back enemy based on damage and enemy weight
                            if (enemyMotor)
                            {
                                if (enemyMotor.KnockBackSpeed <= (5 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)) &&
                                    entityBehaviour.EntityType == EntityTypes.EnemyClass ||
                                    enemyEntity.MobileEnemy.Weight > 0)
                                {
                                    float enemyWeight    = enemyEntity.GetWeightInClassicUnits();
                                    float tenTimesDamage = damage * 10;
                                    float twoTimesDamage = damage * 2;

                                    float knockBackAmount = ((tenTimesDamage - enemyWeight) * 256) / (enemyWeight + tenTimesDamage) * twoTimesDamage;
                                    float knockBackSpeed  = (tenTimesDamage / enemyWeight) * (twoTimesDamage - (knockBackAmount / 256));
                                    knockBackSpeed /= (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10);

                                    if (knockBackSpeed < (15 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)))
                                    {
                                        knockBackSpeed = (15 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10));
                                    }
                                    enemyMotor.KnockBackSpeed     = knockBackSpeed;
                                    enemyMotor.KnockBackDirection = mainCamera.transform.forward;
                                }
                            }
                        }
                        else
                        {
                            if ((weapon.WeaponType != WeaponTypes.Bow && !enemyEntity.MobileEnemy.ParrySounds) || weapon.WeaponType == WeaponTypes.Melee)
                            {
                                weapon.PlaySwingSound();
                            }
                            else if (enemyEntity.MobileEnemy.ParrySounds)
                            {
                                enemySounds.PlayParrySound();
                            }
                        }

                        // Remove health
                        enemyEntity.DecreaseHealth(damage);
                        hitEnemy = true;

                        // Assign "cast when strikes" to target entity
                        if (strikingWeapon != null && strikingWeapon.IsEnchanted)
                        {
                            EntityEffectManager enemyEffectManager = enemyEntity.EntityBehaviour.GetComponent <EntityEffectManager>();
                            if (enemyEffectManager)
                            {
                                enemyEffectManager.StrikeWithItem(strikingWeapon, GameManager.Instance.PlayerEntityBehaviour);
                            }
                        }

                        // Make foe attack their aggressor
                        // Currently this is just player, but should be expanded later
                        // for a wider variety of behaviours
                        if (enemyMotor)
                        {
                            // Make enemies in an area aggressive if player attacked a non-hostile one.
                            if (!enemyMotor.IsHostile)
                            {
                                GameManager.Instance.MakeEnemiesHostile();
                            }
                            enemyMotor.MakeEnemyHostileToPlayer(gameObject);
                        }
                    }
                }

                // Check if hit a mobile NPC
                MobilePersonNPC mobileNpc = hit.transform.GetComponent <MobilePersonNPC>();
                if (mobileNpc)
                {
                    EnemyBlood blood = hit.transform.GetComponent <EnemyBlood>();
                    if (blood)
                    {
                        blood.ShowBloodSplash(0, hit.point);
                    }
                    mobileNpc.Motor.gameObject.SetActive(false);
                    playerEntity.TallyCrimeGuildRequirements(false, 5);
                    // TODO: LOS check from each townsperson. If seen, register crime and start spawning guards as below.
                    playerEntity.CrimeCommitted = PlayerEntity.Crimes.Murder;
                    playerEntity.SpawnCityGuards(true);
                }
            }
        }
示例#11
0
        private void WeaponDamage(FPSWeapon weapon, out bool hitEnemy)
        {
            hitEnemy = false;

            if (!mainCamera || !weapon)
            {
                return;
            }

            // Fire ray along player facing using weapon range
            RaycastHit hit;
            Ray        ray = new Ray(mainCamera.transform.position, mainCamera.transform.forward);

            if (Physics.SphereCast(ray, SphereCastRadius, out hit, weapon.Reach - SphereCastRadius))
            {
                // Check if hit has an DaggerfallAction component
                DaggerfallAction action = hit.transform.gameObject.GetComponent <DaggerfallAction>();
                if (action)
                {
                    action.Receive(player, DaggerfallAction.TriggerTypes.Attack);
                }

                // Check if hit has an DaggerfallActionDoor component
                DaggerfallActionDoor actionDoor = hit.transform.gameObject.GetComponent <DaggerfallActionDoor>();
                if (actionDoor)
                {
                    actionDoor.AttemptBash();
                    return;
                }

                // Check if hit an entity and remove health
                DaggerfallEntityBehaviour entityBehaviour  = hit.transform.GetComponent <DaggerfallEntityBehaviour>();
                DaggerfallMobileUnit      entityMobileUnit = hit.transform.GetComponentInChildren <DaggerfallMobileUnit>();
                if (entityBehaviour)
                {
                    if (entityBehaviour.EntityType == EntityTypes.EnemyMonster || entityBehaviour.EntityType == EntityTypes.EnemyClass)
                    {
                        EnemyEntity enemyEntity = entityBehaviour.Entity as EnemyEntity;

                        // Calculate damage
                        int damage;
                        if (usingRightHand)
                        {
                            damage = FormulaHelper.CalculateAttackDamage(playerEntity, enemyEntity, (int)(EquipSlots.RightHand), entityMobileUnit.Summary.AnimStateRecord);
                        }
                        else
                        {
                            damage = FormulaHelper.CalculateAttackDamage(playerEntity, enemyEntity, (int)(EquipSlots.LeftHand), entityMobileUnit.Summary.AnimStateRecord);
                        }

                        EnemyMotor  enemyMotor  = hit.transform.GetComponent <EnemyMotor>();
                        EnemySounds enemySounds = hit.transform.GetComponent <EnemySounds>();

                        // Play arrow sound and add arrow to target's inventory
                        if (weapon.WeaponType == WeaponTypes.Bow)
                        {
                            enemySounds.PlayArrowSound();
                            DaggerfallUnityItem arrow = ItemBuilder.CreateItem(ItemGroups.Weapons, (int)Weapons.Arrow);
                            enemyEntity.Items.AddItem(arrow);
                        }

                        // Play hit sound and trigger blood splash at hit point
                        if (damage > 0)
                        {
                            if (usingRightHand)
                            {
                                enemySounds.PlayHitSound(currentRightHandWeapon);
                            }
                            else
                            {
                                enemySounds.PlayHitSound(currentLeftHandWeapon);
                            }

                            EnemyBlood blood = hit.transform.GetComponent <EnemyBlood>();
                            if (blood)
                            {
                                blood.ShowBloodSplash(enemyEntity.MobileEnemy.BloodIndex, hit.point);
                            }

                            // Knock back enemy based on damage and enemy weight
                            if (enemyMotor)
                            {
                                if (enemyMotor.KnockBackSpeed <= (5 / (PlayerMotor.classicToUnitySpeedUnitRatio / 10)) &&
                                    entityBehaviour.EntityType == EntityTypes.EnemyClass ||
                                    enemyEntity.MobileEnemy.Weight > 0)
                                {
                                    float enemyWeight    = enemyEntity.GetWeightInClassicUnits();
                                    float tenTimesDamage = damage * 10;
                                    float twoTimesDamage = damage * 2;

                                    float knockBackAmount = ((tenTimesDamage - enemyWeight) * 256) / (enemyWeight + tenTimesDamage) * twoTimesDamage;
                                    float knockBackSpeed  = (tenTimesDamage / enemyWeight) * (twoTimesDamage - (knockBackAmount / 256));
                                    knockBackSpeed /= (PlayerMotor.classicToUnitySpeedUnitRatio / 10);

                                    if (knockBackSpeed < (15 / (PlayerMotor.classicToUnitySpeedUnitRatio / 10)))
                                    {
                                        knockBackSpeed = (15 / (PlayerMotor.classicToUnitySpeedUnitRatio / 10));
                                    }
                                    enemyMotor.KnockBackSpeed     = knockBackSpeed;
                                    enemyMotor.KnockBackDirection = mainCamera.transform.forward;
                                }
                            }
                        }
                        else
                        {
                            if ((weapon.WeaponType != WeaponTypes.Bow && !enemyEntity.MobileEnemy.ParrySounds) || weapon.WeaponType == WeaponTypes.Melee)
                            {
                                weapon.PlaySwingSound();
                            }
                            else if (enemyEntity.MobileEnemy.ParrySounds)
                            {
                                enemySounds.PlayParrySound();
                            }
                        }

                        // Remove health
                        enemyEntity.DecreaseHealth(damage);
                        hitEnemy = true;

                        // Make foe attack their aggressor
                        // Currently this is just player, but should be expanded later
                        // for a wider variety of behaviours
                        if (enemyMotor)
                        {
                            // Make enemies in an area aggressive if player attacked a non-hostile one.
                            if (!enemyMotor.IsHostile)
                            {
                                GameManager.Instance.MakeEnemiesHostile();
                            }
                            enemyMotor.MakeEnemyHostileToPlayer(gameObject);
                        }
                    }
                }

                // Check if hit a mobile NPC
                MobilePersonNPC mobileNpc = hit.transform.GetComponent <MobilePersonNPC>();
                if (mobileNpc)
                {
                    // TODO: Create blood splash.
                    mobileNpc.Motor.gameObject.SetActive(false);
                    //GameManager.Instance.PlayerEntity.TallyCrimeGuildRequirements(false, 5);
                }
            }
        }