Esempio n. 1
0
        void UpdateHeadTexture()
        {
            ImageData head;

            // Check for racial override head
            RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();

            if (racialOverride != null && racialOverride.GetCustomHeadImageData(playerEntity, out head))
            {
                HeadTexture = head.texture;
                return;
            }

            // Otherwise just get standard head based on gender and race
            switch (playerEntity.Gender)
            {
            default:
            case Genders.Male:
                head = ImageReader.GetImageData(playerEntity.RaceTemplate.PaperDollHeadsMale, playerEntity.FaceIndex, 0, true);
                break;

            case Genders.Female:
                head = ImageReader.GetImageData(playerEntity.RaceTemplate.PaperDollHeadsFemale, playerEntity.FaceIndex, 0, true);
                break;
            }
            HeadTexture = head.texture;
        }
Esempio n. 2
0
        // Update player background panel
        void RefreshBackground(PlayerEntity entity)
        {
            // Allow racial override background (vampire / transformed were-creature)
            // If racial override is not present or returns null then standard racial background will be used
            // The racial override has full control over which texture is displayed, such as when were-creature transformed or not
            Texture2D            customBackground;
            RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();

            if (racialOverride != null && racialOverride.GetCustomPaperDollBackgroundTexture(entity, out customBackground))
            {
                backgroundPanel.BackgroundTexture = customBackground;
                backgroundPanel.Size = new Vector2(paperDollWidth, paperDollHeight);
                lastBackgroundName   = string.Empty;
                return;
            }

            // Use standard racial background
            string backgroundName = GetPaperDollBackground(entity);

            if (lastBackgroundName != backgroundName)
            {
                Texture2D texture = ImageReader.GetTexture(backgroundName, 0, 0, false);
                backgroundPanel.BackgroundTexture = ImageReader.GetSubTexture(texture, backgroundSubRect, backgroundFullSize);
                backgroundPanel.Size = new Vector2(paperDollWidth, paperDollHeight);
                lastBackgroundName   = backgroundName;
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Redraws paper doll image and selection mask.
        /// Call this after changing equipment, loading a new game, etc.
        /// Only call when required as constructing paper doll image is expensive.
        /// </summary>
        /// <param name="playerEntity"></param>
        public void Refresh(PlayerEntity playerEntity = null)
        {
            // Get current player entity if one not provided
            if (playerEntity == null)
            {
                playerEntity = GameManager.Instance.PlayerEntity;
            }

            // Racial override can suppress body and items
            bool suppressBody = false;
            RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();

            if (racialOverride != null)
            {
                suppressBody = racialOverride.SuppressPaperDollBodyAndItems;
            }

            // Update background
            RefreshBackground(playerEntity);

            // Display paper doll render
            DaggerfallUI.Instance.PaperDollRenderer.Refresh(PaperDollRenderer.LayerFlags.All, playerEntity);
            characterPanel.BackgroundTexture = DaggerfallUI.Instance.PaperDollRenderer.PaperDollTexture;

            // Update armour values
            RefreshArmourValues(playerEntity, suppressBody);
        }
Esempio n. 4
0
        /// <summary>
        /// Renders a new paper doll image for the specified player entity.
        /// </summary>
        /// <param name="layers">Flags controlling which layers of paper doll to draw.</param>
        /// <param name="playerEntity">Player entity to use for paper doll construction. Use null for live player entity.</param>
        public void Refresh(LayerFlags layers = LayerFlags.All, PlayerEntity playerEntity = null)
        {
            // Clear current item layout
            itemLayout.Clear();

            // Get current player entity if one not provided
            if (playerEntity == null)
            {
                playerEntity = GameManager.Instance.PlayerEntity;
            }

            // Racial override can suppress body and items
            bool suppressBody = false;
            RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();

            if (racialOverride != null)
            {
                suppressBody = racialOverride.SuppressPaperDollBodyAndItems;
            }

            // Start rendering to paper doll target
            RenderTexture oldRT = RenderTexture.active;

            RenderTexture.active = target;
            GL.PushMatrix();
            GL.LoadPixelMatrix(0, target.width, target.height, 0);

            // Clear render target
            GL.Clear(true, true, Color.clear);

            if (!suppressBody)
            {
                // Cloak interior
                if ((layers & LayerFlags.CloakInterior) == LayerFlags.CloakInterior)
                {
                    BlitCloakInterior(playerEntity);
                }

                // Body
                if ((layers & LayerFlags.Body) == LayerFlags.Body)
                {
                    BlitBody(playerEntity);
                }

                // Items
                if ((layers & LayerFlags.Items) == LayerFlags.Items)
                {
                    BlitItems(playerEntity);
                }
            }

            // Copy render to new output
            paperDollTexture.ReadPixels(new Rect(0, 0, target.width, target.height), 0, 0);
            paperDollTexture.Apply();

            // Switch back to previous render target
            GL.PopMatrix();
            RenderTexture.active = oldRT;
        }
        // Capture this message so we can play pain voice
        public void RemoveHealth(int amount)
        {
            // Racial override can suppress optional attack voice
            RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();
            bool suppressCombatVoices           = racialOverride != null && racialOverride.SuppressOptionalCombatVoices;

            if (dfAudioSource && DaggerfallUnity.Settings.CombatVoices && !suppressCombatVoices && Dice100.SuccessRoll(40))
            {
                Entity.PlayerEntity playerEntity = GameManager.Instance.PlayerEntity;
                bool       heavyDamage           = amount >= playerEntity.MaxHealth / 4;
                SoundClips sound = Entity.DaggerfallEntity.GetRaceGenderPainSound(playerEntity.Race, playerEntity.Gender, heavyDamage);
                float      pitch = dfAudioSource.AudioSource.pitch;
                dfAudioSource.AudioSource.pitch = pitch + Random.Range(0, 0.3f);
                dfAudioSource.PlayOneShot((int)sound, 0, 1f);
                dfAudioSource.AudioSource.pitch = pitch;
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Redraws paper doll image and selection mask.
        /// Call this after changing equipment, loading a new game, etc.
        /// Only call when required as constructing paper doll image is expensive.
        /// </summary>
        /// <param name="playerEntity"></param>
        public void Refresh(PlayerEntity playerEntity = null)
        {
            // Get current player entity if one not provided
            if (playerEntity == null)
            {
                playerEntity = GameManager.Instance.PlayerEntity;
            }

            // Racial override can suppress body and items
            bool suppressBody = false;
            RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();

            if (racialOverride != null)
            {
                suppressBody = racialOverride.SuppressPaperDollBodyAndItems;
            }

            // Update paper doll
            ClearPaperDoll();
            RefreshBackground(playerEntity);
            if (!suppressBody)
            {
                BlitCloakInterior(playerEntity);
                BlitBody(playerEntity);
                BlitItems(playerEntity);
            }

            // Destroy old paper doll texture
            characterPanel.BackgroundTexture = null;
            GameObject.Destroy(paperDollTexture);
            paperDollTexture = null;

            // Update paper doll texture
            paperDollTexture = ImageReader.GetTexture(paperDollColors, paperDollWidth, paperDollHeight);
            characterPanel.BackgroundTexture = paperDollTexture;

            // Display using new paper doll renderer
            //DaggerfallUI.Instance.PaperDollRenderer.Refresh(PaperDollRenderer.LayerFlags.All, playerEntity);
            //characterPanel.BackgroundTexture = DaggerfallUI.Instance.PaperDollRenderer.PaperDollTexture;

            //TextureReader.SaveTextureToPNG(DaggerfallUI.Instance.PaperDollRenderer.PaperDollTexture, "c:\\test\\testrender.png");

            // Update armour values
            RefreshArmourValues(playerEntity, suppressBody);
        }
Esempio n. 7
0
        ImageData GetHeadImageData(PlayerEntity entity)
        {
            // Check for racial override head
            ImageData            customHead;
            RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();

            if (racialOverride != null && racialOverride.GetCustomHeadImageData(entity, out customHead))
            {
                return(customHead);
            }

            // Otherwise just get standard head based on gender and race
            switch (entity.Gender)
            {
            default:
            case Genders.Male:
                return(ImageReader.GetImageData(entity.RaceTemplate.PaperDollHeadsMale, entity.FaceIndex, 0, true));

            case Genders.Female:
                return(ImageReader.GetImageData(entity.RaceTemplate.PaperDollHeadsFemale, entity.FaceIndex, 0, true));
            }
        }
        void ApplyWeapon()
        {
            if (!ScreenWeapon)
            {
                return;
            }

            RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();

            if (racialOverride != null && racialOverride.SetFPSWeapon(ScreenWeapon))
            {
                return;
            }
            else if (usingRightHand)
            {
                if (currentRightHandWeapon == null)
                {
                    SetMelee(ScreenWeapon);
                }
                else
                {
                    SetWeapon(ScreenWeapon, currentRightHandWeapon);
                }
            }
            else
            {
                if (currentLeftHandWeapon == null)
                {
                    SetMelee(ScreenWeapon);
                }
                else
                {
                    SetWeapon(ScreenWeapon, currentLeftHandWeapon);
                }
            }

            ScreenWeapon.Reach = defaultWeaponReach;
        }
        // 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(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  = hit.transform.GetComponent <DaggerfallEntityBehaviour>();
            DaggerfallMobileUnit      entityMobileUnit = hit.transform.GetComponentInChildren <DaggerfallMobileUnit>();
            EnemyMotor  enemyMotor  = hit.transform.GetComponent <EnemyMotor>();
            EnemySounds enemySounds = hit.transform.GetComponent <EnemySounds>();

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

            if (mobileNpc)
            {
                if (!mobileNpc.Billboard.IsUsingGuardTexture)
                {
                    EnemyBlood blood = hit.transform.GetComponent <EnemyBlood>();
                    if (blood)
                    {
                        blood.ShowBloodSplash(0, hit.point);
                    }
                    mobileNpc.Motor.gameObject.SetActive(false);
                    playerEntity.TallyCrimeGuildRequirements(false, 5);
                    playerEntity.CrimeCommitted = PlayerEntity.Crimes.Murder;
                    playerEntity.SpawnCityGuards(true);
                }
                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 = 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 and raise special strike handling event
                    if (strikingWeapon != null && strikingWeapon.IsEnchanted)
                    {
                        EntityEffectManager enemyEffectManager = enemyEntity.EntityBehaviour.GetComponent <EntityEffectManager>();
                        if (enemyEffectManager)
                        {
                            enemyEffectManager.StrikeWithItem(strikingWeapon, GameManager.Instance.PlayerEntityBehaviour);
                        }
                        strikingWeapon.RaiseOnWeaponStrikeEvent(entityBehaviour, 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, e.g. vampire feeding
                    RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();
                    if (racialOverride != null)
                    {
                        racialOverride.OnWeaponHitEnemy(GameManager.Instance.PlayerEntity, enemyEntity);
                    }

                    return(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);
        }
        void Update()
        {
            // Automatically update weapons from inventory when PlayerEntity available
            if (playerEntity != null)
            {
                UpdateHands();
            }
            else
            {
                playerEntity = GameManager.Instance.PlayerEntity;
            }

            // Reset variables if there isn't an attack ongoing
            if (!IsWeaponAttacking())
            {
                // If an attack with a bow just finished, set cooldown
                if (ScreenWeapon.WeaponType == WeaponTypes.Bow && isAttacking)
                {
                    cooldownTime = Time.time + FormulaHelper.GetBowCooldownTime(playerEntity);
                }

                isAttacking        = false;
                isDamageFinished   = false;
                isBowSoundFinished = false;
            }

            // Do nothing while weapon cooldown. Used for bow.
            if (Time.time < cooldownTime)
            {
                return;
            }

            // Do nothing if player paralyzed or is climbing
            if (GameManager.Instance.PlayerEntity.IsParalyzed || GameManager.Instance.ClimbingMotor.IsClimbing)
            {
                ShowWeapons(false);
                return;
            }

            bool doToggleSheath = false;

            // Hide weapons and do nothing if spell is ready or cast animation in progress
            if (GameManager.Instance.PlayerEffectManager)
            {
                if (GameManager.Instance.PlayerEffectManager.HasReadySpell || GameManager.Instance.PlayerSpellCasting.IsPlayingAnim)
                {
                    if (!isAttacking && InputManager.Instance.ActionStarted(InputManager.Actions.ReadyWeapon))
                    {
                        GameManager.Instance.PlayerEffectManager.AbortReadySpell();

                        //if currently unsheathed, then sheath it, so we can give the effect of unsheathing it again
                        if (!Sheathed)
                        {
                            ToggleSheath();
                        }

                        doToggleSheath = true;
                    }
                    else
                    {
                        ShowWeapons(false);
                        return;
                    }
                }
            }

            // Toggle weapon sheath
            if (doToggleSheath || (!isAttacking && InputManager.Instance.ActionStarted(InputManager.Actions.ReadyWeapon)))
            {
                ToggleSheath();
            }

            // Toggle weapon hand
            if (!isAttacking && InputManager.Instance.ActionComplete(InputManager.Actions.SwitchHand))
            {
                ToggleHand();
            }

            // Do nothing if weapon isn't done equipping
            if ((usingRightHand && EquipCountdownRightHand != 0) ||
                (!usingRightHand && EquipCountdownLeftHand != 0))
            {
                ShowWeapons(false);
                return;
            }

            // Do nothing if weapons sheathed
            if (Sheathed)
            {
                ShowWeapons(false);
                return;
            }
            else
            {
                ShowWeapons(true);
            }

            // Do nothing if player has cursor active over large HUD (player is clicking on HUD not clicking to attack)
            if (GameManager.Instance.PlayerMouseLook.cursorActive &&
                DaggerfallUI.Instance.DaggerfallHUD != null &&
                DaggerfallUI.Instance.DaggerfallHUD.LargeHUD.ActiveMouseOverLargeHUD)
            {
                return;
            }

            // Get if bow is equipped
            bool bowEquipped = (ScreenWeapon && ScreenWeapon.WeaponType == WeaponTypes.Bow);

            // Handle beginning a new attack
            if (!isAttacking)
            {
                if (!DaggerfallUnity.Settings.ClickToAttack || bowEquipped)
                {
                    // Reset tracking if user not holding down 'SwingWeapon' button and no attack in progress
                    if (!InputManager.Instance.HasAction(InputManager.Actions.SwingWeapon))
                    {
                        lastAttackHand = Hand.None;
                        _gesture.Clear();
                        return;
                    }
                }
                else
                {
                    // Player must click to attack
                    if (InputManager.Instance.ActionStarted(InputManager.Actions.SwingWeapon))
                    {
                        isClickAttack = true;
                    }
                    else
                    {
                        _gesture.Clear();
                        return;
                    }
                }
            }

            var attackDirection = MouseDirections.None;

            if (!isAttacking)
            {
                if (bowEquipped)
                {
                    // Ensure attack button was released before starting the next attack
                    if (lastAttackHand == Hand.None)
                    {
                        attackDirection = DaggerfallUnity.Settings.BowDrawback ? MouseDirections.Up : MouseDirections.Down; // Force attack without tracking a swing for Bow
                    }
                }
                else if (isClickAttack)
                {
                    attackDirection = (MouseDirections)UnityEngine.Random.Range((int)MouseDirections.UpRight, (int)MouseDirections.DownRight + 1);
                    isClickAttack   = false;
                }
                else
                {
                    attackDirection = TrackMouseAttack(); // Track swing direction for other weapons
                }
            }
            if (isAttacking && bowEquipped && DaggerfallUnity.Settings.BowDrawback && ScreenWeapon.GetCurrentFrame() == 3)
            {
                if (InputManager.Instance.HasAction(InputManager.Actions.ActivateCenterObject) || ScreenWeapon.GetAnimTime() > MaxBowHeldDrawnSeconds)
                {   // Un-draw the bow without releasing an arrow.
                    ScreenWeapon.ChangeWeaponState(WeaponStates.Idle);
                }
                else if (!InputManager.Instance.HasAction(InputManager.Actions.SwingWeapon))
                {   // Release arrow. Debug.Log("Release arrow!");
                    attackDirection = MouseDirections.Down;
                }
            }

            // Start attack if one has been initiated
            if (attackDirection != MouseDirections.None)
            {
                ExecuteAttacks(attackDirection);
                isAttacking = true;
            }

            // Stop here if no attack is happening
            if (!isAttacking)
            {
                return;
            }

            if (!isBowSoundFinished && ScreenWeapon.WeaponType == WeaponTypes.Bow && ScreenWeapon.GetCurrentFrame() == 4)
            {
                ScreenWeapon.PlaySwingSound();
                isBowSoundFinished = true;
            }
            else if (!isDamageFinished && ScreenWeapon.GetCurrentFrame() == ScreenWeapon.GetHitFrame())
            {
                // Racial override can suppress optional attack voice
                RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();
                bool suppressCombatVoices           = racialOverride != null && racialOverride.SuppressOptionalCombatVoices;

                // Chance to play attack voice
                if (DaggerfallUnity.Settings.CombatVoices && !suppressCombatVoices && ScreenWeapon.WeaponType != WeaponTypes.Bow && Dice100.SuccessRoll(20))
                {
                    ScreenWeapon.PlayAttackVoice();
                }

                // Transfer damage.
                bool hitEnemy = false;

                // Non-bow weapons
                if (ScreenWeapon.WeaponType != WeaponTypes.Bow)
                {
                    MeleeDamage(ScreenWeapon, out hitEnemy);
                }
                // Bow weapons
                else
                {
                    DaggerfallMissile missile = Instantiate(ArrowMissilePrefab);
                    if (missile)
                    {
                        // Remove arrow
                        ItemCollection      playerItems = playerEntity.Items;
                        DaggerfallUnityItem arrow       = playerItems.GetItem(ItemGroups.Weapons, (int)Weapons.Arrow, allowQuestItem: false, priorityToConjured: true);
                        bool isArrowSummoned            = arrow.IsSummoned;
                        playerItems.RemoveOne(arrow);

                        missile.Caster          = GameManager.Instance.PlayerEntityBehaviour;
                        missile.TargetType      = TargetTypes.SingleTargetAtRange;
                        missile.ElementType     = ElementTypes.None;
                        missile.IsArrow         = true;
                        missile.IsArrowSummoned = isArrowSummoned;

                        lastBowUsed = usingRightHand ? currentRightHandWeapon : currentLeftHandWeapon;;
                    }
                }

                // Fatigue loss
                playerEntity.DecreaseFatigue(swingWeaponFatigueLoss);

                // Play swing sound if attack didn't hit an enemy.
                if (!hitEnemy && ScreenWeapon.WeaponType != WeaponTypes.Bow)
                {
                    ScreenWeapon.PlaySwingSound();
                }
                else
                {
                    // Tally skills
                    if (ScreenWeapon.WeaponType == WeaponTypes.Melee || ScreenWeapon.WeaponType == WeaponTypes.Werecreature)
                    {
                        playerEntity.TallySkill(DFCareer.Skills.HandToHand, 1);
                    }
                    else if (usingRightHand && (currentRightHandWeapon != null))
                    {
                        playerEntity.TallySkill(currentRightHandWeapon.GetWeaponSkillID(), 1);
                    }
                    else if (currentLeftHandWeapon != null)
                    {
                        playerEntity.TallySkill(currentLeftHandWeapon.GetWeaponSkillID(), 1);
                    }

                    playerEntity.TallySkill(DFCareer.Skills.CriticalStrike, 1);
                }
                isDamageFinished = true;
            }
        }
Esempio n. 12
0
        // Gets factionID of a faction type NPC
        int GetFactionTypeFactionID(string factionTypeName)
        {
            // Only allowing a small range of random faction types for now
            FactionFile.FactionTypes[] randomFactionTypes = new FactionFile.FactionTypes[]
            {
                FactionFile.FactionTypes.Courts,
                FactionFile.FactionTypes.Province,
                FactionFile.FactionTypes.People,
                FactionFile.FactionTypes.Temple,
            };

            // P3 is faction type
            int   factionType;
            Table factionsTable = QuestMachine.Instance.FactionsTable;

            if (factionsTable.HasValue(factionTypeName))
            {
                factionType = Parser.ParseInt(factionsTable.GetValue("p3", factionTypeName));
            }
            else
            {
                Debug.LogErrorFormat("Could not find factionTypeName {0}", factionTypeName);
                return(-1);
            }

            // Handle random faction type
            // This selects from a restricted pool to ensure vital NPCs don't get randomly selected
            if (factionType == -1)
            {
                factionType = (int)UnityEngine.Random.Range(0, randomFactionTypes.Length);
            }

            // Assign factionID based on factionType
            // This value is 0-15 and maps to "type:" in faction.txt
            // Daggerfall seems to largely select from selected pool of factionType objects at random
            // But some factionTypes do not exist in file and suspect special handling for others
            // Treating on a case-by-case basis for now
            switch ((FactionFile.FactionTypes)factionType)
            {
            // These faction types do not generally have a specific region associated with them
            // Select from pool of all objects this faction type
            case FactionFile.FactionTypes.Daedra:
            case FactionFile.FactionTypes.Group:
            case FactionFile.FactionTypes.Subgroup:
            case FactionFile.FactionTypes.Official:
            case FactionFile.FactionTypes.Temple:
                return(GetRandomFactionOfType(factionType));

            // Faction type of God is never used in quests
            // Many of these factions do not have an NPC flat
            // Recommend never using - not sure how to redirect to working state yet
            case FactionFile.FactionTypes.God:
                return(GetRandomFactionOfType(factionType));

            // The individual type is not used by any canonical quests
            // It is more or less equivalent to reserving an individual NPC
            // Not recommended to use this in quests
            // Just returning a random person to ensure NPC is created
            case FactionFile.FactionTypes.Individual:
                return(GetRandomFactionOfType(factionType));

            // Classic is bugged there as it always selects a random vampire clan.
            // Here we fix it by using player vampire clan for vampire and cure vampirism quests
            // and by using the vampire clan affiliated to the current region otherwise.
            case FactionFile.FactionTypes.VampireClan:
                if (ParentQuest.QuestName.StartsWith("P0") || ParentQuest.QuestName.StartsWith("$CUREVAM"))
                {
                    RacialOverrideEffect racialEffect = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();
                    return((int)(racialEffect as VampirismEffect).VampireClan);
                }
                else
                {
                    return(GameManager.Instance.PlayerGPS.GetCurrentRegionVampireClan());
                }

            // Assign an NPC from current player region
            case FactionFile.FactionTypes.Province:
                return(GameManager.Instance.PlayerGPS.GetCurrentRegionFaction());

            // Not all regions have a witches coven associated
            // Just select a random coven for now
            case FactionFile.FactionTypes.WitchesCoven:
                return(GetRandomFactionOfType(factionType));

            // Type 10 Knightly_Guard does not exist in FACTION.TXT but IS used in some quests
            // Redirecting this to "Generic Knightly Order" #844 to ensure NPC is created
            case FactionFile.FactionTypes.KnightlyGuard:
                return(844);

            // Type 11 Magic_User does not exist in FACTION.TXT and is not used in any quests
            // Redirecting this to "Mages Guild" #40 to ensure NPC is created
            case FactionFile.FactionTypes.MagicUser:
                return(40);

            // Type 12 Generic_Group does not exist in FACTION.TXT and is not used in any quests
            // Redirecting this to a random choice between "Generic Temple" #450 and "Generic Knightly Order" #844 to ensure NPC is created
            case FactionFile.FactionTypes.Generic:
                return((UnityEngine.Random.Range(0f, 1f) < 0.5f) ? 450 : 844);

            // Type 13 Thieves_Den does not exist in FACTION.TXT and is not used in any quests
            // Redirecting this to "Thieves Guild" #42 to ensure NPC is created
            case FactionFile.FactionTypes.Thieves:
                return(42);

            // Get "court of" current region
            case FactionFile.FactionTypes.Courts:
                return(GameManager.Instance.PlayerGPS.GetCourtOfCurrentRegion());

            // Get "people of" current region
            case FactionFile.FactionTypes.People:
                return(GameManager.Instance.PlayerGPS.GetPeopleOfCurrentRegion());

            // Give up
            default:
                return(-1);
            }
        }
        public static SoundClips GetRaceGenderAttackSound(Races race, Genders gender, bool isPlayerAttack = false)
        {
            // Check for racial override attack sound for player only
            if (isPlayerAttack)
            {
                SoundClips           customSound;
                RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();
                if (racialOverride != null && racialOverride.GetCustomRaceGenderAttackSoundData(GameManager.Instance.PlayerEntity, out customSound))
                {
                    return(customSound);
                }
            }

            if (gender == Genders.Male)
            {
                switch (race)
                {
                case Races.Breton:
                    return(SoundClips.BretonMalePain1);

                case Races.Redguard:
                    return(SoundClips.RedguardMalePain1);

                case Races.Nord:
                    return(SoundClips.NordMalePain1);

                case Races.DarkElf:
                    return(SoundClips.DarkElfMalePain1);

                case Races.HighElf:
                    return(SoundClips.HighElfMalePain1);

                case Races.WoodElf:
                    return(SoundClips.WoodElfMalePain1);

                case Races.Khajiit:
                    return(SoundClips.KhajiitMalePain1);

                case Races.Argonian:
                    return(SoundClips.ArgonianMalePain1);

                default:
                    return(SoundClips.None);
                }
            }
            else
            {
                switch (race)
                {
                case Races.Breton:
                case Races.Redguard:
                case Races.Nord:
                    int random = UnityEngine.Random.Range(0, 3);
                    if (random == 0)
                    {
                        return(SoundClips.BretonFemalePain1);
                    }
                    else if (random == 1)
                    {
                        return(SoundClips.BretonFemalePain2);
                    }
                    else
                    {
                        return(SoundClips.DarkElfFemalePain2);
                    }

                case Races.DarkElf:
                case Races.HighElf:
                case Races.WoodElf:
                    random = UnityEngine.Random.Range(0, 2);
                    if (random == 0)
                    {
                        return(SoundClips.HighElfFemalePain1);
                    }
                    else
                    {
                        return(SoundClips.HighElfFemalePain2);
                    }

                case Races.Khajiit:
                    random = UnityEngine.Random.Range(0, 2);
                    if (random == 0)
                    {
                        return(SoundClips.KhajiitFemalePain1);
                    }
                    else
                    {
                        return(SoundClips.KhajiitFemalePain2);
                    }

                case Races.Argonian:
                    random = UnityEngine.Random.Range(0, 2);
                    if (random == 0)
                    {
                        return(SoundClips.ArgonianFemalePain1);
                    }
                    else
                    {
                        return(SoundClips.ArgonianFemalePain2);
                    }

                default:
                    return(SoundClips.None);
                }
            }
        }
Esempio n. 14
0
        void Update()
        {
            // Automatically update weapons from inventory when PlayerEntity available
            if (playerEntity != null)
            {
                UpdateHands();
            }
            else
            {
                playerEntity = GameManager.Instance.PlayerEntity;
            }

            // Reset variables if there isn't an attack ongoing
            if (!IsWeaponAttacking())
            {
                // If an attack with a bow just finished, set cooldown
                if (ScreenWeapon.WeaponType == WeaponTypes.Bow && isAttacking)
                {
                    float cooldown = 10 * (100 - playerEntity.Stats.LiveSpeed) + 800;
                    cooldownTime = Time.time + (cooldown / 980); // Approximates classic frame update
                }

                isAttacking        = false;
                isDamageFinished   = false;
                isBowSoundFinished = false;
            }

            // Do nothing while weapon cooldown. Used for bow.
            if (Time.time < cooldownTime)
            {
                return;
            }

            // Do nothing if weapon isn't done equipping
            if ((usingRightHand && EquipCountdownRightHand != 0) ||
                (!usingRightHand && EquipCountdownLeftHand != 0))
            {
                ShowWeapons(false);
                return;
            }

            // Hide weapons and do nothing if spell is ready or cast animation in progress
            if (GameManager.Instance.PlayerEffectManager)
            {
                if (GameManager.Instance.PlayerEffectManager.HasReadySpell || GameManager.Instance.PlayerSpellCasting.IsPlayingAnim)
                {
                    ShowWeapons(false);
                    return;
                }
            }

            // Do nothing if player paralyzed
            if (GameManager.Instance.PlayerEntity.IsParalyzed)
            {
                ShowWeapons(false);
                return;
            }

            // Toggle weapon sheath
            if (!isAttacking && InputManager.Instance.ActionStarted(InputManager.Actions.ReadyWeapon))
            {
                ToggleSheath();
            }

            // Toggle weapon hand
            if (!isAttacking && InputManager.Instance.ActionComplete(InputManager.Actions.SwitchHand))
            {
                ToggleHand();
            }

            // Do nothing if weapons sheathed
            if (Sheathed)
            {
                ShowWeapons(false);
                return;
            }
            else
            {
                ShowWeapons(true);
            }

            // Get if bow is equipped
            bool bowEquipped = (ScreenWeapon && ScreenWeapon.WeaponType == WeaponTypes.Bow);

            // Handle beginning a new attack
            if (!isAttacking)
            {
                if (!DaggerfallUnity.Settings.ClickToAttack || bowEquipped)
                {
                    // Reset tracking if user not holding down 'SwingWeapon' button and no attack in progress
                    if (!InputManager.Instance.HasAction(InputManager.Actions.SwingWeapon))
                    {
                        lastAttackHand = Hand.None;
                        _gesture.Clear();
                        return;
                    }
                }
                else
                {
                    // Player must click to attack
                    if (InputManager.Instance.ActionStarted(InputManager.Actions.SwingWeapon))
                    {
                        isClickAttack = true;
                    }
                    else
                    {
                        _gesture.Clear();
                        return;
                    }
                }
            }

            var attackDirection = MouseDirections.None;

            if (!isAttacking)
            {
                if (bowEquipped)
                {
                    // Ensure attack button was released before starting the next attack
                    if (lastAttackHand == Hand.None)
                    {
                        attackDirection = MouseDirections.Down; // Force attack without tracking a swing for Bow
                    }
                }
                else if (isClickAttack)
                {
                    attackDirection = (MouseDirections)UnityEngine.Random.Range((int)MouseDirections.Left, (int)MouseDirections.DownRight + 1);
                    isClickAttack   = false;
                }
                else
                {
                    attackDirection = TrackMouseAttack(); // Track swing direction for other weapons
                }
            }

            // Start attack if one has been initiated
            if (attackDirection != MouseDirections.None)
            {
                ExecuteAttacks(attackDirection);
                isAttacking = true;
            }

            // Stop here if no attack is happening
            if (!isAttacking)
            {
                return;
            }

            if (!isBowSoundFinished && ScreenWeapon.WeaponType == WeaponTypes.Bow && ScreenWeapon.GetCurrentFrame() == 3)
            {
                ScreenWeapon.PlaySwingSound();
                isBowSoundFinished = true;

                // Remove arrow
                ItemCollection      playerItems = playerEntity.Items;
                DaggerfallUnityItem arrow       = playerItems.GetItem(ItemGroups.Weapons, (int)Weapons.Arrow);
                playerItems.RemoveOne(arrow);
            }
            else if (!isDamageFinished && ScreenWeapon.GetCurrentFrame() == ScreenWeapon.GetHitFrame())
            {
                // Racial override can suppress optional attack voice
                RacialOverrideEffect racialOverride = GameManager.Instance.PlayerEffectManager.GetRacialOverrideEffect();
                bool suppressCombatVoices           = racialOverride != null && racialOverride.SuppressOptionalCombatVoices;

                // Chance to play attack voice
                if (DaggerfallUnity.Settings.CombatVoices && !suppressCombatVoices && ScreenWeapon.WeaponType != WeaponTypes.Bow && Dice100.SuccessRoll(20))
                {
                    ScreenWeapon.PlayAttackVoice();
                }

                // Transfer damage.
                bool hitEnemy = false;

                // Non-bow weapons
                if (ScreenWeapon.WeaponType != WeaponTypes.Bow)
                {
                    MeleeDamage(ScreenWeapon, out hitEnemy);
                }
                // Bow weapons
                else
                {
                    DaggerfallMissile missile = Instantiate(ArrowMissilePrefab);
                    if (missile)
                    {
                        missile.Caster      = GameManager.Instance.PlayerEntityBehaviour;
                        missile.TargetType  = TargetTypes.SingleTargetAtRange;
                        missile.ElementType = ElementTypes.None;
                        missile.IsArrow     = true;

                        lastBowUsed = currentRightHandWeapon;
                    }
                }

                // Fatigue loss
                playerEntity.DecreaseFatigue(swingWeaponFatigueLoss);

                // Play swing sound if attack didn't hit an enemy.
                if (!hitEnemy && ScreenWeapon.WeaponType != WeaponTypes.Bow)
                {
                    ScreenWeapon.PlaySwingSound();
                }
                else
                {
                    // Tally skills
                    if (ScreenWeapon.WeaponType == WeaponTypes.Melee || ScreenWeapon.WeaponType == WeaponTypes.Werecreature)
                    {
                        playerEntity.TallySkill(DFCareer.Skills.HandToHand, 1);
                    }
                    else if (usingRightHand && (currentRightHandWeapon != null))
                    {
                        playerEntity.TallySkill(currentRightHandWeapon.GetWeaponSkillID(), 1);
                    }
                    else if (currentLeftHandWeapon != null)
                    {
                        playerEntity.TallySkill(currentLeftHandWeapon.GetWeaponSkillID(), 1);
                    }

                    playerEntity.TallySkill(DFCareer.Skills.CriticalStrike, 1);
                }
                isDamageFinished = true;
            }
        }