Esempio n. 1
0
        public void TakeDamage(ActorHitInfo data)
        {
            if (MetaState.Instance.SessionFlags.Contains("GodMode") || GameState.Instance.PlayerFlags.Contains(PlayerFlags.Invulnerable) || IsDying)
            {
                return;
            }

            CharacterModel playerModel = GameState.Instance.PlayerRpgState;

            //damage model is very stupid right now, we will make it better later
            var(dt, dr) = playerModel.GetDamageThresholdAndResistance(data.DamageType);
            float damageTaken = RpgValues.DamageTaken(data.Damage, data.DamagePierce, dt, dr);

            if (data.HitLocation == (int)ActorBodyPart.Head)
            {
                damageTaken *= 2.0f;
            }
            else if (data.HitLocation == (int)ActorBodyPart.LeftArm || data.HitLocation == (int)ActorBodyPart.LeftLeg || data.HitLocation == (int)ActorBodyPart.RightArm || data.HitLocation == (int)ActorBodyPart.RightLeg)
            {
                damageTaken *= 0.75f;
            }

            if (damageTaken > 0)
            {
                if (PainSound != null && !PainSound.isPlaying)
                {
                    PainSound.Play();
                }
            }

            playerModel.Health -= damageTaken;
        }
Esempio n. 2
0
        private void DoRadiusDamage()
        {
            //do radius damage

            var bulletHitInfo = BulletScript.HitInfo;

            ActorHitInfo hitInfo = new ActorHitInfo(Damage, 0, bulletHitInfo.DamageType, (int)DefaultDamageEffectors.Explosion, false, 0, 0, bulletHitInfo.Originator, bulletHitInfo.OriginatorFaction, HitPuff, null, bulletHitInfo.HitFlags);

            //TODO we copy flags, should we also copy ExtraFlags and ExtraData?

            WorldUtils.RadiusDamage(transform.position, Radius, UseFalloff, true, false, false, false, hitInfo);

            Triggered = true;
        }
Esempio n. 3
0
        /// <summary>
        /// Calculates applied damage given hitinfo and armor values
        /// </summary>
        public static float DamageTaken(ActorHitInfo hitInfo, float threshold, float resistance)
        {
            float damage       = hitInfo.Damage;
            float damagePierce = hitInfo.DamagePierce;

            if (hitInfo.HitFlags.HasFlag(BuiltinHitFlags.IgnoreArmor))
            {
                return(damage + damagePierce);
            }

            if (hitInfo.HitFlags.HasFlag(BuiltinHitFlags.PierceConsiderArmor))
            {
                damage      += damagePierce;
                damagePierce = 0;
            }

            float d1 = damage * ((100f - Mathf.Min(resistance, 99f)) / 100f);
            float dt = Mathf.Max(0, threshold); //threshold-pierce
            float d2 = Mathf.Max(d1 - dt, damage * 0.1f);

            float dp = damagePierce;

            return(d2 + dp);
        }
Esempio n. 4
0
        public void TakeDamage(ActorHitInfo data)
        {
            if (MetaState.Instance.SessionFlags.Contains("GodMode") || GameState.Instance.PlayerFlags.Contains(PlayerFlags.Invulnerable) || IsDying)
            {
                return;
            }

            if (!data.HarmFriendly)
            {
                string hitFaction = data.OriginatorFaction;
                if (!string.IsNullOrEmpty(hitFaction))
                {
                    FactionRelationStatus relation = FactionModel.GetRelation(hitFaction, PredefinedFaction.Player.ToString()); //this looks backwards but it's because we're checking if the Bullet is-friendly-to the Actor
                    if (relation == FactionRelationStatus.Friendly)
                    {
                        return; //no friendly fire
                    }
                }
            }

            if (DamageHandler != null)
            {
                var hitOut = DamageHandler(data);
                if (hitOut.HasValue)
                {
                    data = hitOut.Value;
                }
                else
                {
                    return;
                }
            }

            CharacterModel playerModel = GameState.Instance.PlayerRpgState;

            var(damageToShields, damageToArmor, damageToCharacter) = RpgValues.DamageRatio(data.Damage, data.DamagePierce, playerModel);

            float oldShields = playerModel.Shields;

            playerModel.Shields -= damageToShields;

            if (oldShields > 0 && playerModel.Shields <= 0)
            {
                MessageInterface.PushToBus(new QdmsFlagMessage("PlayerShieldsLost"));
                ShieldComponent.Ref()?.SignalLostShields();
            }

            var(dt, dr) = playerModel.GetDamageThresholdAndResistance(data.DamageType);
            float damageTaken = RpgValues.DamageTaken(damageToArmor, damageToCharacter, dt, dr);

            if (data.HitLocation == (int)ActorBodyPart.Head)
            {
                damageTaken *= 2.0f;
            }
            else if (data.HitLocation == (int)ActorBodyPart.LeftArm || data.HitLocation == (int)ActorBodyPart.LeftLeg || data.HitLocation == (int)ActorBodyPart.RightArm || data.HitLocation == (int)ActorBodyPart.RightLeg)
            {
                damageTaken *= 0.75f;
            }

            playerModel.Health -= damageTaken;

            if (damageTaken > PainSoundThreshold)
            {
                if (PainSound != null && !PainSound.isPlaying)
                {
                    PainSound.Play();
                }
            }

            if (damageToShields > 0 || damageTaken > 0)
            {
                ShieldComponent.Ref()?.SignalTookDamage(damageToShields, damageTaken);

                var damageValues = new Dictionary <string, object>()
                {
                    { "DamageTaken", damageTaken },
                    { "DamageToShields", damageToShields },
                    { "DamageToArmor", damageToArmor },
                    { "DamageToCharacter", damageToCharacter }
                };
                MessageInterface.PushToBus(new QdmsKeyValueMessage(damageValues, "PlayerTookDamage"));
            }
        }
Esempio n. 5
0
        public static (float damageToShields, float damageToArmor, float damageToCharacter) DamageRatio(ActorHitInfo hitInfo, CharacterModel character)
        {
            //for now we'll keep returning all 3 values but we'll probably combine the functionality of DamageTaken into this as well and just spit out "damage to shields" and "raw damage"

            float damage       = hitInfo.Damage;
            float damagePierce = hitInfo.DamagePierce;

            if (character.DerivedStats.ShieldParams.MaxShields == 0 || character.Shields == 0 || hitInfo.HitFlags.HasFlag(BuiltinHitFlags.IgnoreShields))
            {
                if (hitInfo.HitFlags.HasFlag(BuiltinHitFlags.PierceConsiderArmor))
                {
                    damage      += damagePierce;
                    damagePierce = 0;
                }

                return(0, damage, damagePierce);
            }

            //keep it simple for now
            float shields  = character.Shields;
            float leakRate = character.DerivedStats.ShieldParams.LeakRate;
            float damageToShieldsFromPierce = 0;

            if (hitInfo.HitFlags.HasFlag(BuiltinHitFlags.PierceConsiderShields))
            {
                damageToShieldsFromPierce = Mathf.Min(shields, damagePierce - (damagePierce * leakRate));
                damagePierce -= damageToShieldsFromPierce;
            }

            float damageToShields = Mathf.Min(Mathf.Max(0, shields - damageToShieldsFromPierce), (damage - (damage * leakRate)));
            float damageToArmor   = damage - damageToShields;

            if (hitInfo.HitFlags.HasFlag(BuiltinHitFlags.PierceConsiderArmor))
            {
                damageToArmor += damagePierce;
                damagePierce   = 0;
            }

            return(damageToShields, damageToArmor, damagePierce);
        }
Esempio n. 6
0
        public void TakeDamage(ActorHitInfo data)
        {
            //damage model is very stupid right now, we will make it better later
            float dt          = data.DamageType < DamageThreshold.Length ? DamageThreshold[(int)data.DamageType] : 0f;
            float dr          = data.DamageType < DamageThreshold.Length ? DamageResistance[(int)data.DamageType] : 0f;
            float damageTaken = RpgValues.DamageTaken(data.Damage, data.DamagePierce, dt, dr);

            if (data.HitLocation == (int)ActorBodyPart.Head)
            {
                damageTaken *= 2.0f;
            }
            else if (data.HitLocation == (int)ActorBodyPart.LeftArm || data.HitLocation == (int)ActorBodyPart.LeftLeg || data.HitLocation == (int)ActorBodyPart.RightArm || data.HitLocation == (int)ActorBodyPart.RightLeg)
            {
                damageTaken *= 0.75f;
            }

            damageTaken *= (1f / ConfigState.Instance.GetGameplayConfig().Difficulty.ActorStrength);

            if (!Invincible)
            {
                Health -= damageTaken;
            }

            /*
             * if(!string.IsNullOrEmpty(data.HitPuff))
             * {
             *  Debug.Log($"Spawning hitpuff \"{data.HitPuff}\" at {data.HitCoords}");
             *  Vector3 hitCoords = data.HitCoords.HasValue ? data.HitCoords.Value : transform.position;
             *  WorldUtils.SpawnEffect(data.HitPuff, hitCoords, transform.eulerAngles, null);
             * }
             * else if(!string.IsNullOrEmpty(DefaultHitPuff))
             * {
             *  Vector3 hitCoords = data.HitCoords.HasValue ? data.HitCoords.Value : transform.position;
             *  WorldUtils.SpawnEffect(DefaultHitPuff, hitCoords, transform.eulerAngles, null);
             * }
             */
            //we no longer spawn hitpuffs here

            if (CurrentAiState == ActorAiState.Dead) //abort if we're already dead
            {
                return;
            }

            bool didTakePain = UnityEngine.Random.Range(0f, 1f) < PainChance;

            if (Defensive && data.Originator != null && data.Originator != this)
            {
                FactionRelationStatus relation = FactionRelationStatus.Neutral;
                if (data.Originator is PlayerController)
                {
                    relation = FactionModel.GetRelation(Faction, "Player");
                }
                else if (data.Originator is ActorController)
                {
                    relation = FactionModel.GetRelation(Faction, ((ActorController)data.Originator).Faction);
                }

                if (relation != FactionRelationStatus.Friendly || Infighting)
                {
                    Target  = data.Originator.transform;
                    BeenHit = true;

                    if (DisableInteractionOnHit && InteractionComponent != null)
                    {
                        InteractionComponent.InteractionDisabledByHit = true;
                    }

                    if (FeelPain && didTakePain)
                    {
                        EnterState(ActorAiState.Hurting);
                    }
                    else
                    {
                        EnterState(ActorAiState.Chasing);
                    }
                }
                else
                {
                    EnterState(ActorAiState.Hurting);
                }
            }
            else if (FeelPain && didTakePain)
            {
                EnterState(ActorAiState.Hurting);
            }
        }
Esempio n. 7
0
        public void TakeDamage(ActorHitInfo data)
        {
            if (!data.HarmFriendly)
            {
                string hitFaction = data.OriginatorFaction;
                if (!string.IsNullOrEmpty(hitFaction))
                {
                    FactionRelationStatus relation = FactionModel.GetRelation(hitFaction, Faction); //this looks backwards but it's because we're checking if the Bullet is-friendly-to the Actor
                    if (relation == FactionRelationStatus.Friendly)
                    {
                        return; //no friendly fire
                    }
                }
            }

            //damage model is very stupid right now, we will make it better later
            float dt          = data.DamageType < DamageThreshold.Length ? DamageThreshold[(int)data.DamageType] : 0f;
            float dr          = data.DamageType < DamageThreshold.Length ? DamageResistance[(int)data.DamageType] : 0f;
            float damageTaken = RpgValues.DamageTaken(data.Damage, data.DamagePierce, dt, dr);

            if (data.HitLocation == (int)ActorBodyPart.Head)
            {
                damageTaken *= 2.0f;
            }
            else if (data.HitLocation == (int)ActorBodyPart.LeftArm || data.HitLocation == (int)ActorBodyPart.LeftLeg || data.HitLocation == (int)ActorBodyPart.RightArm || data.HitLocation == (int)ActorBodyPart.RightLeg)
            {
                damageTaken *= 0.75f;
            }

            damageTaken *= (1f / ConfigState.Instance.GetGameplayConfig().Difficulty.ActorStrength);

            if (!Invincible)
            {
                Health -= damageTaken;
            }

            if (CurrentAiState == ActorAiState.Dead) //abort if we're already dead
            {
                return;
            }

            bool didTakePain = UnityEngine.Random.Range(0f, 1f) < PainChance; //shouldn't this be weighted by damage?

            if (Defensive && data.Originator != null && data.Originator != this)
            {
                FactionRelationStatus relation = FactionRelationStatus.Neutral;
                if (data.Originator is PlayerController)
                {
                    relation = FactionModel.GetRelation(Faction, "Player");
                }
                else if (data.Originator is ActorController)
                {
                    relation = FactionModel.GetRelation(Faction, ((ActorController)data.Originator).Faction);
                }

                if (relation != FactionRelationStatus.Friendly || Infighting)
                {
                    Target  = data.Originator.transform;
                    BeenHit = true;

                    if (DisableInteractionOnHit && InteractionComponent != null)
                    {
                        InteractionComponent.InteractionDisabledByHit = true;
                    }

                    if (FeelPain && didTakePain)
                    {
                        if (CurrentAiState != ActorAiState.Hurting)
                        {
                            EnterState(ActorAiState.Hurting);
                        }
                        else
                        {
                            EnterState(ActorAiState.Chasing);
                        }
                    }
                }
                else if (CurrentAiState != ActorAiState.Hurting)
                {
                    EnterState(ActorAiState.Hurting);
                }
            }
            else if (FeelPain && didTakePain && CurrentAiState != ActorAiState.Hurting)
            {
                EnterState(ActorAiState.Hurting);
            }
        }
Esempio n. 8
0
 /// <summary>
 /// Calculates damage to shields, armor, and character given damage and a character model
 /// </summary>
 public static (float damageToShields, float damageToArmor, float damageToCharacter) DamageRatio(ActorHitInfo hitInfo, CharacterModel character) => DamageRatioImpl(hitInfo, character);
Esempio n. 9
0
        //both the damage methods below need to be reworked/replaced to handle flags among other things

        /// <summary>
        /// Calculates applied damage given input damage and resistance
        /// </summary>
        public static float DamageTaken(ActorHitInfo hitInfo, float threshold, float resistance) //this is a dumb spot and we will move it later
        => DamageTakenImpl(hitInfo, threshold, resistance);
Esempio n. 10
0
        public void TakeDamage(ActorHitInfo data)
        {
            LastHit       = null;
            LastHitDamage = 0;

            if (!data.HarmFriendly)
            {
                string hitFaction = data.OriginatorFaction;
                if (!string.IsNullOrEmpty(hitFaction))
                {
                    FactionRelationStatus relation = GameState.Instance.FactionState.GetRelation(hitFaction, Faction); //this looks backwards but it's because we're checking if the Bullet is-friendly-to the Actor
                    if (relation == FactionRelationStatus.Friendly)
                    {
                        return; //no friendly fire
                    }
                }
            }

            ActorDamageHandlerResult?damageHandlerResult = null;

            if (DamageHandler != null)
            {
                damageHandlerResult = DamageHandler(data);
                if (damageHandlerResult.Value.HitInfo.HasValue)
                {
                    data = damageHandlerResult.Value.HitInfo.Value;
                }
                else
                {
                    return;
                }
            }

            LastHit = data;

            float damageTaken;

            if (damageHandlerResult?.DamageTaken != null)
            {
                damageTaken = damageHandlerResult.Value.DamageTaken.Value;
            }
            else
            {
                //new way of doing dr/dt
                float dt = 0, dr = 0;
                foreach (var dNode in DamageResistances)
                {
                    if ((int)dNode.DamageType == data.DamageType)
                    {
                        dt = dNode.DamageThreshold;
                        dr = dNode.DamageResistance;
                    }
                }

                damageTaken = RpgValues.DamageTaken(data, dt, dr);

                if (!data.HitFlags.HasFlag(BuiltinHitFlags.IgnoreHitLocation))
                {
                    if (data.HitLocation == (int)ActorBodyPart.Head)
                    {
                        damageTaken *= 2.0f; //do we want more flexibility here?
                    }
                    else if (data.HitLocation == (int)ActorBodyPart.LeftArm || data.HitLocation == (int)ActorBodyPart.LeftLeg || data.HitLocation == (int)ActorBodyPart.RightArm || data.HitLocation == (int)ActorBodyPart.RightLeg)
                    {
                        damageTaken *= 0.75f;
                    }
                }

                damageTaken *= (1f / ConfigState.Instance.GetGameplayConfig().Difficulty.ActorStrength);
            }

            if (!Invincible)
            {
                LastHitDamage = damageTaken;
                Health       -= damageTaken;
            }

            //handle extreme death
            if (damageHandlerResult?.ExtremeDeath != null)
            {
                WasExtremeDeath = damageHandlerResult.Value.ExtremeDeath.Value;
            }
            else
            {
                if (data.HitFlags.HasFlag(BuiltinHitFlags.AlwaysExtremeDeath))
                {
                    WasExtremeDeath = true;
                }
                else if (data.HitFlags.HasFlag(BuiltinHitFlags.NeverExtremeDeath))
                {
                    WasExtremeDeath = false;
                }
                else
                {
                    if (ExtremeDeathThreshold > 0)
                    {
                        //interpret as -(maxhealth * threshold)
                        WasExtremeDeath = Health < (-(MaxHealth * ExtremeDeathThreshold));
                    }
                    else if (ExtremeDeathThreshold < 0)
                    {
                        //interpret as absolute value
                        WasExtremeDeath = Health < ExtremeDeathThreshold;
                    }
                    else
                    {
                        //ExtremeDeathThreshold == 0, no extreme death
                        WasExtremeDeath = false;
                    }
                }
            }

            //TODO do we force into death state here?

            //TODO consider moving this, but probably wait until we start thinking about abuse of corpses
            if (CurrentAiState == ActorAiState.Dead) //abort if we're already dead
            {
                return;
            }

            bool didTakePain;

            if (damageHandlerResult?.TookPain != null)
            {
                didTakePain = damageHandlerResult.Value.TookPain.Value;
            }
            else
            {
                float derivedPainChance = PainChance;
                if (PainGuaranteeThreshold != 0)
                {
                    float damageForMaxPain = Mathf.Abs(PainGuaranteeRelative ? (PainGuaranteeThreshold * MaxHealth) : PainGuaranteeThreshold);
                    derivedPainChance = MathUtils.ScaleRange(damageTaken, 0, damageForMaxPain, PainChance, 1);
                }
                derivedPainChance = Mathf.Min(derivedPainChance, PainMaxChance);

                didTakePain = (data.HitFlags.HasFlag(BuiltinHitFlags.AlwaysPain) || UnityEngine.Random.Range(0f, 1f) < derivedPainChance) && !data.HitFlags.HasFlag(BuiltinHitFlags.NoPain); //TODO shouldn't this be weighted by damage?
            }

            if (Defensive && data.Originator != null && data.Originator != this && !data.HitFlags.HasFlag(BuiltinHitFlags.NeverAlert))
            {
                FactionRelationStatus relation = FactionRelationStatus.Neutral;
                if (data.Originator is PlayerController)
                {
                    relation = GameState.Instance.FactionState.GetRelation(Faction, "Player");
                }
                else if (data.Originator is ActorController)
                {
                    relation = GameState.Instance.FactionState.GetRelation(Faction, ((ActorController)data.Originator).Faction);
                }

                if (relation != FactionRelationStatus.Friendly || Infighting)
                {
                    Target  = data.Originator.transform;
                    BeenHit = true;

                    if (DisableInteractionOnHit && InteractionComponent != null)
                    {
                        InteractionComponent.InteractionDisabledByHit = true;
                    }

                    if (FeelPain && didTakePain && CurrentAiState != ActorAiState.ScriptedAction && CurrentAiState != ActorAiState.ScriptedMoveTo)
                    {
                        if (PainStateAllowRestart || CurrentAiState != ActorAiState.Hurting)
                        {
                            EnterState(ActorAiState.Hurting);
                        }
                    }
                    else if (CurrentAiState != ActorAiState.Chasing && CurrentAiState != ActorAiState.Attacking && CurrentAiState != ActorAiState.ScriptedAction && CurrentAiState != ActorAiState.ScriptedMoveTo)
                    {
                        EnterState(ActorAiState.Chasing);
                    }
                }
                else if ((PainStateAllowRestart || CurrentAiState != ActorAiState.Hurting) && FeelPain && CurrentAiState != ActorAiState.ScriptedAction && CurrentAiState != ActorAiState.ScriptedMoveTo)
                {
                    EnterState(ActorAiState.Hurting);
                }
            }
            else if (FeelPain && didTakePain && (PainStateAllowRestart || CurrentAiState != ActorAiState.Hurting) && CurrentAiState != ActorAiState.ScriptedAction && CurrentAiState != ActorAiState.ScriptedMoveTo)
            {
                EnterState(ActorAiState.Hurting);
            }
        }
Esempio n. 11
0
        public void DoAttack()
        {
            Vector3 shootPos = ShootPoint == null ? (transform.position + (transform.forward * 0.6f) + (transform.up * 1.25f)) : ShootPoint.position;

            if (UseSuicide)
            {
                //ActorController.TakeDamage(new ActorHitInfo(0, Mathf.Min(ActorController.MaxHealth * 100, float.MaxValue), 0, 0, 0, ActorController));
                ActorController.Health = 0;
            }
            else
            {
                var target = ActorController.Target;

                Vector3 aimPoint = target.position;

                var targetAC = target.GetComponent <ActorController>();
                if (targetAC != null && targetAC.TargetPoint != null)
                {
                    aimPoint = targetAC.TargetPoint.position;
                }

                var targetPC = target.GetComponent <PlayerController>();
                if (targetPC != null && targetPC.TargetPoint != null)
                {
                    aimPoint = targetPC.TargetPoint.position;
                }

                aimPoint.y += UnityEngine.Random.Range(-AttackSpread, AttackSpread);
                aimPoint.x += UnityEngine.Random.Range(-AttackSpread, AttackSpread);
                aimPoint.z += UnityEngine.Random.Range(-AttackSpread, AttackSpread);


                Vector3 shootVec = (aimPoint - shootPos).normalized; //I screwed this up the first time

                float randomFactor = Mathf.Max(0, 1 + UnityEngine.Random.Range(-AttackRandomFactor, AttackRandomFactor));

                var modHit         = new ActorHitInfo(AttackHit);
                var gameplayConfig = ConfigState.Instance.GetGameplayConfig();
                modHit.Damage       *= gameplayConfig.Difficulty.ActorStrength * randomFactor;
                modHit.DamagePierce *= gameplayConfig.Difficulty.ActorStrength * randomFactor;
                modHit.Originator    = ActorController;
                if (FriendlyFire == FriendlyFireMode.Always)
                {
                    modHit.HarmFriendly = true;
                }
                else if (FriendlyFire == FriendlyFireMode.Never)
                {
                    modHit.HarmFriendly = false;
                }
                else
                {
                    modHit.HarmFriendly = GameParams.UseFriendlyFire;
                }
                if (string.IsNullOrEmpty(modHit.OriginatorFaction))
                {
                    modHit.OriginatorFaction = ActorController.Faction;
                }

                modHit.HitFlags = TypeUtils.FlagsFromCollection(AttackHitFlags);

                if (UseMelee)
                {
                    if (AutoDamageEffector)
                    {
                        modHit.DamageEffector = (int)DamageEffector.Melee;
                    }

                    //melee path (raycast)
                    LayerMask lm = WorldUtils.GetAttackLayerMask();

                    //TODO 2D/3D attack range, or just increase attack range?

                    var            rc = Physics.RaycastAll(shootPos, shootVec, AttackRange, lm, QueryTriggerInteraction.Collide);
                    BaseController ac = null;
                    foreach (var r in rc)
                    {
                        var go   = r.collider.gameObject;
                        var ahgo = go.GetComponent <IHitboxComponent>();
                        if (ahgo != null)
                        {
                            ac = ahgo.ParentController;
                            break;
                        }
                        var acgo = go.GetComponent <ActorController>();
                        if (acgo != null)
                        {
                            ac = acgo;
                            break;
                        }
                    }
                    if (ac != null)
                    {
                        if (ac is ITakeDamage itd)
                        {
                            itd.TakeDamage(modHit);
                        }
                    }
                }
                else if (BulletPrefab != null)
                {
                    if (AutoDamageEffector)
                    {
                        modHit.DamageEffector = (int)DamageEffector.Projectile;
                    }

                    //bullet path (shoot)
                    //var bullet = Instantiate<GameObject>(BulletPrefab, shootPos + (shootVec * 0.25f), Quaternion.identity, transform.root);
                    Quaternion bulletRotation  = Quaternion.LookRotation(shootVec.normalized, Vector3.up);
                    var        bullet          = WorldUtils.SpawnEffect(BulletPrefab, shootPos + (shootVec * 0.25f), bulletRotation.eulerAngles, transform.root);
                    var        bulletRigidbody = bullet.GetComponent <Rigidbody>();
                    bulletRigidbody.velocity = (shootVec * BulletSpeed);
                    var bulletScript = bullet.GetComponent <BulletScript>();
                    bulletScript.HitInfo = modHit;
                    bulletScript.Target  = target;
                }
                else
                {
                    CDebug.LogEx(string.Format("{0} tried to shoot a bullet, but has no prefab defined!", name), LogLevel.Error, this);
                }
            }

            //show the effect, if applicable
            if (!string.IsNullOrEmpty(AttackEffectPrefab))
            {
                WorldUtils.SpawnEffect(AttackEffectPrefab, shootPos, Vector3.zero, ParentAttackEffect ? (ShootPoint == null ? transform : ShootPoint) : null);
                //Instantiate(AttackEffectPrefab, shootPos, Quaternion.identity, (ShootPoint == null ? transform : ShootPoint));
            }
            if (AttackSound != null)
            {
                AttackSound.Play();
            }

            DidAttack      = true;
            LastAttackTime = Time.time;
        }