예제 #1
0
        private void BowDamage()
        {
            if (entityBehaviour)
            {
                // Can we see target? Then apply damage.
                if (senses.TargetInSight)
                {
                    EnemyEntity entity = entityBehaviour.Entity as EnemyEntity;
                    if (entityBehaviour.Target == GameManager.Instance.PlayerEntityBehaviour)
                    {
                        damage = ApplyDamageToPlayer(entity.ItemEquipTable.GetItem(Items.EquipSlots.RightHand));
                    }
                    else
                    {
                        damage = ApplyDamageToNonPlayer(entity.ItemEquipTable.GetItem(Items.EquipSlots.RightHand), true);
                    }

                    // Play arrow sound and add arrow to target inventory
                    if (entityBehaviour.Target == GameManager.Instance.PlayerEntityBehaviour)
                    {
                        GameManager.Instance.PlayerObject.SendMessage("PlayArrowSound");
                    }
                    else
                    {
                        EnemySounds targetSounds = entityBehaviour.Target.GetComponent <EnemySounds>();
                        targetSounds.PlayArrowSound();
                    }
                    Items.DaggerfallUnityItem arrow = Items.ItemBuilder.CreateItem(Items.ItemGroups.Weapons, (int)Items.Weapons.Arrow);
                    entityBehaviour.Target.Entity.Items.AddItem(arrow);
                }
            }
        }
예제 #2
0
 void Start()
 {
     motor           = GetComponent <EnemyMotor>();
     senses          = GetComponent <EnemySenses>();
     sounds          = GetComponent <EnemySounds>();
     mobile          = GetComponentInChildren <DaggerfallMobileUnit>();
     entityBehaviour = GetComponent <DaggerfallEntityBehaviour>();
 }
예제 #3
0
 void Start()
 {
     motor           = GetComponent <EnemyMotor>();
     senses          = GetComponent <EnemySenses>();
     sounds          = GetComponent <EnemySounds>();
     mobile          = GetComponent <DaggerfallEnemy>().MobileUnit;
     dfMobile        = mobile as DaggerfallMobileUnit;
     entityBehaviour = GetComponent <DaggerfallEntityBehaviour>();
 }
예제 #4
0
        // Handle charging into enemies.
        private void HandleCharge(GameObject hitGO, DaggerfallEntityBehaviour hitEntityBehaviour, Vector3 direction)
        {
            if (hitEntityBehaviour.Entity is EnemyEntity)
            {
                EnemyEntity hitEnemyEntity = (EnemyEntity)hitEntityBehaviour.Entity;
                if (!hitEnemyEntity.PickpocketByPlayerAttempted)
                {
                    // Play heavy hit sound.
                    EnemySounds          enemySounds      = hitGO.GetComponent <EnemySounds>();
                    DaggerfallMobileUnit entityMobileUnit = hitGO.GetComponentInChildren <DaggerfallMobileUnit>();
                    Genders gender;
                    if (entityMobileUnit.Summary.Enemy.Gender == MobileGender.Male || hitEnemyEntity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch)
                    {
                        gender = Genders.Male;
                    }
                    else
                    {
                        gender = Genders.Female;
                    }
                    enemySounds.PlayCombatVoice(gender, false, true);

                    // Knockback the enemy.
                    EnemyMotor enemyMotor = hitGO.GetComponent <EnemyMotor>();
                    enemyMotor.KnockbackSpeed     = 100;
                    enemyMotor.KnockbackDirection = direction;

                    // Handle charge hit damage and fatigue loss.
                    PlayerEntity playerEntity = GameManager.Instance.PlayerEntity;
                    hitEnemyEntity.PickpocketByPlayerAttempted = true;
                    playerEntity.DecreaseFatigue(PlayerEntity.DefaultFatigueLoss * 15);

                    int minBaseDamage = FormulaHelper.CalculateHandToHandMinDamage(playerEntity.Skills.GetLiveSkillValue(DFCareer.Skills.HandToHand));
                    int maxBaseDamage = FormulaHelper.CalculateHandToHandMaxDamage(playerEntity.Skills.GetLiveSkillValue(DFCareer.Skills.HandToHand));
                    int damage        = UnityEngine.Random.Range(minBaseDamage, maxBaseDamage + 1);
                    damage += playerEntity.Stats.GetLiveStatValue(DFCareer.Stats.Agility) / 10;
                    damage += playerEntity.Stats.GetLiveStatValue(DFCareer.Stats.Willpower) / 10;
                    DaggerfallEntityBehaviour playerEntityBehaviour = playerEntity.EntityBehaviour;
                    hitEntityBehaviour.DamageHealthFromSource(playerEntityBehaviour, damage, true, BloodPos());

                    Debug.LogFormat("Charged down a {0} for {1} damage!", hitEntityBehaviour.name, damage);
                }
            }
        }
예제 #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
        /// <summary>
        /// Sets up enemy based on current settings.
        /// </summary>
        public void ApplyEnemySettings(MobileGender gender)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;
            Dictionary <int, MobileEnemy> enemyDict = GameObjectHelper.EnemyDict;
            MobileEnemy mobileEnemy = enemyDict[(int)EnemyType];

            if (AlliedToPlayer)
            {
                mobileEnemy.Team = MobileTeams.PlayerAlly;
            }

            // Find mobile unit in children
            MobileUnit dfMobile = GetMobileBillboardChild();

            if (dfMobile != null)
            {
                // Setup mobile billboard
                Vector2 size = Vector2.one;
                mobileEnemy.Gender    = gender;
                mobileEnemy.Reactions = EnemyReaction;
                dfMobile.SetEnemy(dfUnity, mobileEnemy, EnemyReaction, ClassicSpawnDistanceType);

                // Setup controller
                CharacterController controller = GetComponent <CharacterController>();
                if (controller)
                {
                    // Set base height from sprite
                    size = dfMobile.GetSize();
                    controller.height = size.y;

                    // Reduce height of flying creatures as their wing animation makes them taller than desired
                    // This helps them get through doors while aiming for player eye height
                    if (dfMobile.Enemy.Behaviour == MobileBehaviour.Flying)
                    {
                        // (in frame 0 wings are in high position, assume body is  the lower half)
                        AdjustControllerHeight(controller, controller.height / 2, ControllerJustification.BOTTOM);
                    }

                    // Limit minimum controller height
                    // Stops very short characters like rats from being walked upon
                    if (controller.height < 1.6f)
                    {
                        AdjustControllerHeight(controller, 1.6f, ControllerJustification.BOTTOM);
                    }

                    controller.gameObject.layer = LayerMask.NameToLayer("Enemies");
                }

                // Setup sounds
                EnemySounds enemySounds = GetComponent <Game.EnemySounds>();
                if (enemySounds)
                {
                    enemySounds.MoveSound   = (SoundClips)dfMobile.Enemy.MoveSound;
                    enemySounds.BarkSound   = (SoundClips)dfMobile.Enemy.BarkSound;
                    enemySounds.AttackSound = (SoundClips)dfMobile.Enemy.AttackSound;
                }

                MeshRenderer meshRenderer = dfMobile.GetComponent <MeshRenderer>();
                if (meshRenderer)
                {
                    if (dfMobile.Enemy.Behaviour == MobileBehaviour.Spectral)
                    {
                        meshRenderer.material.shader = Shader.Find(MaterialReader._DaggerfallGhostShaderName);
                        meshRenderer.material.SetFloat("_Cutoff", 0.1f);
                    }
                    if (dfMobile.Enemy.NoShadow)
                    {
                        meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
                    }
                    if (dfMobile.Enemy.GlowColor != null)
                    {
                        meshRenderer.receiveShadows = false;
                        GameObject enemyLightGameObject = Instantiate(LightAura);
                        enemyLightGameObject.transform.parent        = dfMobile.transform;
                        enemyLightGameObject.transform.localPosition = new Vector3(0, 0.3f, 0.2f);
                        Light enemyLight = enemyLightGameObject.GetComponent <Light>();
                        enemyLight.color   = (Color)dfMobile.Enemy.GlowColor;
                        enemyLight.shadows = DaggerfallUnity.Settings.DungeonLightShadows ? LightShadows.Soft : LightShadows.None;
                    }
                }

                // Setup entity
                if (entityBehaviour)
                {
                    EnemyEntity entity = new EnemyEntity(entityBehaviour);
                    entityBehaviour.Entity = entity;

                    // Enemies are initially added to same world context as player
                    entity.WorldContext = GameManager.Instance.PlayerEnterExit.WorldContext;

                    int enemyIndex = (int)EnemyType;
                    if (enemyIndex >= 0 && enemyIndex <= 42)
                    {
                        entityBehaviour.EntityType = EntityTypes.EnemyMonster;
                        entity.SetEnemyCareer(mobileEnemy, entityBehaviour.EntityType);
                    }
                    else if (enemyIndex >= 128 && enemyIndex <= 146)
                    {
                        entityBehaviour.EntityType = EntityTypes.EnemyClass;
                        entity.SetEnemyCareer(mobileEnemy, entityBehaviour.EntityType);
                    }
                    else
                    {
                        entityBehaviour.EntityType = EntityTypes.None;
                    }
                }

                // Add special behaviour for Daedra Seducer mobiles
                if (dfMobile.Enemy.ID == (int)MobileTypes.DaedraSeducer)
                {
                    dfMobile.gameObject.AddComponent <DaedraSeducerMobileBehaviour>();
                }
            }
        }
예제 #8
0
        private int ApplyDamageToNonPlayer(Items.DaggerfallUnityItem weapon, Vector3 direction, bool bowAttack = false)
        {
            if (senses.Target == null)
            {
                return(0);
            }
            // TODO: Merge with hit code in WeaponManager to eliminate duplicate code
            EnemyEntity entity       = entityBehaviour.Entity as EnemyEntity;
            EnemyEntity targetEntity = senses.Target.Entity as EnemyEntity;
            EnemySounds targetSounds = senses.Target.GetComponent <EnemySounds>();
            EnemyMotor  targetMotor  = senses.Target.transform.GetComponent <EnemyMotor>();

            // Calculate damage
            damage = FormulaHelper.CalculateAttackDamage(entity, targetEntity, false, 0, weapon);

            // Break any "normal power" concealment effects on enemy
            if (entity.IsMagicallyConcealedNormalPower && damage > 0)
            {
                EntityEffectManager.BreakNormalPowerConcealmentEffects(entityBehaviour);
            }

            // Play hit sound and trigger blood splash at hit point
            if (damage > 0)
            {
                targetSounds.PlayHitSound(weapon);

                EnemyBlood          blood            = senses.Target.transform.GetComponent <EnemyBlood>();
                CharacterController targetController = senses.Target.transform.GetComponent <CharacterController>();
                Vector3             bloodPos         = senses.Target.transform.position + targetController.center;
                bloodPos.y += targetController.height / 8;

                if (blood)
                {
                    blood.ShowBloodSplash(targetEntity.MobileEnemy.BloodIndex, bloodPos);
                }

                // Knock back enemy based on damage and enemy weight
                if (targetMotor && (targetMotor.KnockbackSpeed <= (5 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)) &&
                                    (entityBehaviour.EntityType == EntityTypes.EnemyClass || targetEntity.MobileEnemy.Weight > 0)))
                {
                    float enemyWeight    = targetEntity.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));
                    }
                    targetMotor.KnockbackSpeed     = KnockbackSpeed;
                    targetMotor.KnockbackDirection = direction;
                }

                if (DaggerfallUnity.Settings.CombatVoices && senses.Target.EntityType == EntityTypes.EnemyClass && Dice100.SuccessRoll(40))
                {
                    DaggerfallMobileUnit targetMobileUnit = senses.Target.GetComponentInChildren <DaggerfallMobileUnit>();
                    Genders gender;
                    if (targetMobileUnit.Summary.Enemy.Gender == MobileGender.Male || targetEntity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch)
                    {
                        gender = Genders.Male;
                    }
                    else
                    {
                        gender = Genders.Female;
                    }

                    targetSounds.PlayCombatVoice(gender, false, damage >= targetEntity.MaxHealth / 4);
                }
            }
            else
            {
                WeaponTypes weaponType = WeaponTypes.Melee;
                if (weapon != null)
                {
                    weaponType = DaggerfallUnity.Instance.ItemHelper.ConvertItemToAPIWeaponType(weapon);
                }

                if ((!bowAttack && !targetEntity.MobileEnemy.ParrySounds) || weaponType == WeaponTypes.Melee)
                {
                    sounds.PlayMissSound(weapon);
                }
                else if (targetEntity.MobileEnemy.ParrySounds)
                {
                    targetSounds.PlayParrySound();
                }
            }

            // Handle Strikes payload from enemy to non-player target - this could change damage amount
            if (weapon != null && weapon.IsEnchanted)
            {
                EntityEffectManager effectManager = GetComponent <EntityEffectManager>();
                if (effectManager)
                {
                    damage = effectManager.DoItemEnchantmentPayloads(EnchantmentPayloadFlags.Strikes, weapon, entity.Items, targetEntity.EntityBehaviour, damage);
                }
            }

            targetEntity.DecreaseHealth(damage);

            if (targetMotor)
            {
                targetMotor.MakeEnemyHostileToAttacker(entityBehaviour);
            }

            return(damage);
        }
예제 #9
0
        // 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);
        }
예제 #10
0
        /// <summary>
        /// Sets up enemy based on current settings.
        /// </summary>
        public void ApplyEnemySettings(MobileGender gender)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;
            Dictionary <int, MobileEnemy> enemyDict = GameObjectHelper.EnemyDict;
            MobileEnemy mobileEnemy = enemyDict[(int)EnemyType];

            // Find mobile unit in children
            DaggerfallMobileUnit dfMobile = GetMobileBillboardChild();

            if (dfMobile != null)
            {
                // Setup mobile billboard
                Vector2 size = Vector2.one;
                mobileEnemy.Gender = gender;
                dfMobile.SetEnemy(dfUnity, mobileEnemy, EnemyReaction, ClassicSpawnDistanceType);

                // Setup controller
                CharacterController controller = GetComponent <CharacterController>();
                if (controller)
                {
                    // Set base height from sprite
                    size = dfMobile.Summary.RecordSizes[0];
                    controller.height = size.y;

                    // Reduce height of flying creatures as their wing animation makes them taller than desired
                    // This helps them get through doors while aiming for player eye height
                    if (dfMobile.Summary.Enemy.Behaviour == MobileBehaviour.Flying)
                    {
                        controller.height /= 2f;
                    }

                    // Limit maximum controller height
                    // Some particularly tall sprites (e.g. giants) require this hack to get through doors
                    if (controller.height > 1.78f)
                    {
                        // Adjust center so that sprite doesn't sink into the ground
                        Vector3 newCenter = controller.center;
                        newCenter.y      += (1.78f - controller.height) / 2;
                        controller.center = newCenter;
                        controller.height = 1.78f;
                    }

                    controller.gameObject.layer = LayerMask.NameToLayer("Enemies");
                }

                // Setup sounds
                EnemySounds enemySounds = GetComponent <Game.EnemySounds>();
                if (enemySounds)
                {
                    enemySounds.MoveSound   = (SoundClips)dfMobile.Summary.Enemy.MoveSound;
                    enemySounds.BarkSound   = (SoundClips)dfMobile.Summary.Enemy.BarkSound;
                    enemySounds.AttackSound = (SoundClips)dfMobile.Summary.Enemy.AttackSound;
                }

                // Setup entity
                if (entityBehaviour)
                {
                    EnemyEntity entity = new EnemyEntity(entityBehaviour);
                    entityBehaviour.Entity = entity;

                    // Enemies are initially added to same world context as player
                    entity.WorldContext = GameManager.Instance.PlayerEnterExit.WorldContext;

                    int enemyIndex = (int)EnemyType;
                    if (enemyIndex >= 0 && enemyIndex <= 42)
                    {
                        entityBehaviour.EntityType = EntityTypes.EnemyMonster;
                        entity.SetEnemyCareer(mobileEnemy, entityBehaviour.EntityType);
                    }
                    else if (enemyIndex >= 128 && enemyIndex <= 146)
                    {
                        entityBehaviour.EntityType = EntityTypes.EnemyClass;
                        entity.SetEnemyCareer(mobileEnemy, entityBehaviour.EntityType);
                    }
                    else
                    {
                        entityBehaviour.EntityType = EntityTypes.None;
                    }
                }
            }
        }
 void Start()
 {
     motor = GetComponent<EnemyMotor>();
     senses = GetComponent<EnemySenses>();
     sounds = GetComponent<EnemySounds>();
     mobile = GetComponentInChildren<DaggerfallMobileUnit>();
     entityBehaviour = GetComponent<DaggerfallEntityBehaviour>();
 }
        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);
                }
            }
        }
예제 #13
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);
                }
            }
        }
예제 #14
0
        private int ApplyDamageToNonPlayer(Items.DaggerfallUnityItem weapon, Vector3 direction, bool bowAttack = false)
        {
            if (senses.Target == null)
            {
                return(0);
            }
            // TODO: Merge with hit code in WeaponManager to eliminate duplicate code
            EnemyEntity entity       = entityBehaviour.Entity as EnemyEntity;
            EnemyEntity targetEntity = senses.Target.Entity as EnemyEntity;
            EnemySounds targetSounds = senses.Target.GetComponent <EnemySounds>();
            EnemyMotor  targetMotor  = senses.Target.transform.GetComponent <EnemyMotor>();

            int enemyDamType = EnemyDamageTypeUsed(entity, weapon); // Returns an integer value that corresponds to a specific damage type that this type of enemy can use, will use later on in combat formula.

            // Calculate damage
            damage = FormulaHelper.CalculateAttackDamage(entity, targetEntity, -1, 0, weapon, out bool shieldBlockSuccess, out int mainDamType, out bool critStrikeSuccess, out bool armorPartAbsorbed, out bool armorCompleteAbsorbed, out Items.DaggerfallUnityItem addedAIWeapon, out bool hitSuccess, out bool metalShield, out bool metalArmor, enemyDamType);

            // Break any "normal power" concealment effects on enemy
            if (entity.IsMagicallyConcealedNormalPower && damage > 0)
            {
                EntityEffectManager.BreakNormalPowerConcealmentEffects(entityBehaviour);
            }

            // If the AI was given a weapon through the damage formula, this gives them that weapon for this part of the calling method for later use.
            if (weapon == null)
            {
                weapon = addedAIWeapon;
            }

            // Play associated sound when armor/shield was responsible for absorbing damage completely.
            if (damage <= 0)
            {
                if (hitSuccess && shieldBlockSuccess)
                {
                    targetSounds.PlayShieldBlockSound(weapon, metalShield);
                }
                else if (hitSuccess && armorCompleteAbsorbed)
                {
                    targetSounds.PlayArmorAbsorbSound(weapon, metalArmor);
                }
                else
                {
                    WeaponTypes weaponType = WeaponTypes.Melee;
                    if (weapon != null)
                    {
                        weaponType = DaggerfallUnity.Instance.ItemHelper.ConvertItemToAPIWeaponType(weapon);
                    }

                    if ((!bowAttack && !targetEntity.MobileEnemy.ParrySounds) || weaponType == WeaponTypes.Melee)
                    {
                        sounds.PlayMissSound(weapon);
                    }
                    else if (targetEntity.MobileEnemy.ParrySounds)
                    {
                        targetSounds.PlayParrySound();
                    }
                }
            }

            // Play hit sound and trigger blood splash at hit point
            if (damage > 0)
            {
                if (shieldBlockSuccess && armorPartAbsorbed)
                {
                    sounds.PlayShieldBlockSound(weapon, metalShield);
                }
                targetSounds.PlayHitSound(weapon);

                EnemyBlood          blood            = senses.Target.transform.GetComponent <EnemyBlood>();
                CharacterController targetController = senses.Target.transform.GetComponent <CharacterController>();
                Vector3             bloodPos         = senses.Target.transform.position + targetController.center;
                bloodPos.y += targetController.height / 8;

                if (blood)
                {
                    blood.ShowBloodSplash(targetEntity.MobileEnemy.BloodIndex, bloodPos);
                }

                // Knock back enemy based on damage and enemy weight
                if (targetMotor && (targetMotor.KnockbackSpeed <= (5 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)) &&
                                    (entityBehaviour.EntityType == EntityTypes.EnemyClass || targetEntity.MobileEnemy.Weight > 0)))
                {
                    float enemyWeight    = targetEntity.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));
                    }
                    targetMotor.KnockbackSpeed     = KnockbackSpeed;
                    targetMotor.KnockbackDirection = direction;
                }

                if (DaggerfallUnity.Settings.CombatVoices && senses.Target.EntityType == EntityTypes.EnemyClass && Dice100.SuccessRoll(40))
                {
                    DaggerfallMobileUnit targetMobileUnit = senses.Target.GetComponentInChildren <DaggerfallMobileUnit>();
                    Genders gender;
                    if (targetMobileUnit.Summary.Enemy.Gender == MobileGender.Male || targetEntity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch)
                    {
                        gender = Genders.Male;
                    }
                    else
                    {
                        gender = Genders.Female;
                    }

                    targetSounds.PlayCombatVoice(gender, false, damage >= targetEntity.MaxHealth / 4);
                }
            }

            // Handle Strikes payload from enemy to non-player target - this could change damage amount
            if (weapon != null && weapon.IsEnchanted)
            {
                EntityEffectManager effectManager = GetComponent <EntityEffectManager>();
                if (effectManager)
                {
                    damage = effectManager.DoItemEnchantmentPayloads(EnchantmentPayloadFlags.Strikes, weapon, entity.Items, targetEntity.EntityBehaviour, damage);
                }
            }

            targetEntity.DecreaseHealth(damage);

            if (targetMotor)
            {
                targetMotor.MakeEnemyHostileToAttacker(entityBehaviour);
            }

            return(damage);
        }
예제 #15
0
        /// <summary>
        /// Sets up enemy based on current settings.
        /// </summary>
        public void ApplyEnemySettings(MobileGender gender)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;
            Dictionary <int, MobileEnemy> enemyDict = GameObjectHelper.EnemyDict;
            MobileEnemy mobileEnemy = enemyDict[(int)EnemyType];

            // Find mobile unit in children
            DaggerfallMobileUnit dfMobile = GetMobileBillboardChild();

            if (dfMobile != null)
            {
                // Setup mobile billboard
                Vector2 size = Vector2.one;
                mobileEnemy.Gender = gender;
                dfMobile.SetEnemy(dfUnity, mobileEnemy, EnemyReaction);

                // Setup controller
                CharacterController controller = GetComponent <CharacterController>();
                if (controller)
                {
                    // Set base height from sprite
                    size = dfMobile.Summary.RecordSizes[0];
                    controller.height = size.y;

                    // Reduce height of flying creatures as their wing animation makes them taller than desired
                    // This helps them get through doors while aiming for player eye height
                    if (dfMobile.Summary.Enemy.Behaviour == MobileBehaviour.Flying)
                    {
                        controller.height /= 2f;
                    }

                    // Uncomment below lines to limit maximum controller height
                    // Some particularly tall sprites (e.g. giants) require this hack to get through doors
                    // However they will appear sunken into ground as a result
                    //if (controller.height > 1.9f)
                    //    controller.height = 1.9f;

                    controller.gameObject.layer = LayerMask.NameToLayer("Enemies");
                }

                // Setup sounds
                EnemySounds enemySounds = GetComponent <Game.EnemySounds>();
                if (enemySounds)
                {
                    enemySounds.MoveSound   = (SoundClips)dfMobile.Summary.Enemy.MoveSound;
                    enemySounds.BarkSound   = (SoundClips)dfMobile.Summary.Enemy.BarkSound;
                    enemySounds.AttackSound = (SoundClips)dfMobile.Summary.Enemy.AttackSound;
                }

                // Setup entity
                if (entityBehaviour)
                {
                    EnemyEntity entity = new EnemyEntity();
                    entityBehaviour.Entity = entity;

                    int enemyIndex = (int)EnemyType;
                    if (enemyIndex >= 0 && enemyIndex <= 42)
                    {
                        entityBehaviour.EntityType = EntityTypes.EnemyMonster;
                        entity.SetEnemyCareer(mobileEnemy, entityBehaviour.EntityType);
                    }
                    else if (enemyIndex >= 128 && enemyIndex <= 146)
                    {
                        entityBehaviour.EntityType = EntityTypes.EnemyClass;
                        entity.SetEnemyCareer(mobileEnemy, entityBehaviour.EntityType);
                    }
                    else
                    {
                        entityBehaviour.EntityType = EntityTypes.None;
                    }
                }
            }
        }