示例#1
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"));
            }
        }
示例#2
0
        private void SelectTarget()
        {
            var gameplayConfig = ConfigState.Instance.GetGameplayConfig();

            if (TotalTickCount % SearchInterval * (1f / gameplayConfig.Difficulty.ActorAggression) != 0)
            {
                return;
            }

            var detectionDifficultyFactor = 1f / gameplayConfig.Difficulty.ActorPerception;

            //check player first since it's (relatively) cheap
            if (FactionModel.GetRelation(Faction, "Player") == FactionRelationStatus.Hostile && !MetaState.Instance.SessionFlags.Contains("NoTarget") && !GameState.Instance.PlayerFlags.Contains(PlayerFlags.NoTarget))
            {
                var playerObj = WorldUtils.GetPlayerObject();
                if (playerObj != null && RpgWorldUtils.TargetIsAlive(playerObj.transform))
                {
                    PlayerController pc = playerObj.GetComponent <PlayerController>();

                    if ((playerObj.transform.position - transform.position).magnitude <= SearchRadius &&
                        UnityEngine.Random.Range(0f, 1f * detectionDifficultyFactor) <= RpgValues.DetectionChance(GameState.Instance.PlayerRpgState, pc.MovementComponent.IsCrouching, pc.MovementComponent.IsRunning))
                    {
                        if (UseLineOfSight)
                        {
                            //additional check
                            RaycastHit hitinfo;
                            if (Physics.Raycast(transform.position + new Vector3(0, 1.0f, 0), (playerObj.transform.position - transform.position), out hitinfo))
                            {
                                if (hitinfo.collider.gameObject == playerObj)
                                {
                                    Target = playerObj.transform;
                                    return;
                                }
                            }
                        }
                        else
                        {
                            //otherwise, close enough
                            Target = playerObj.transform;
                            return;
                        }
                    }
                }
            }

            //if(TargetNpc)
            {
                //var sw = System.Diagnostics.Stopwatch.StartNew();

                //new code should be faster if n is large but it may not bear out in practice, and it probably allocs more dedotated wam

                var colliders = Physics.OverlapSphere(transform.position, SearchRadius, LayerMask.GetMask("Default", "ActorHitbox"));
                HashSet <ActorController> potentialTargets = new HashSet <ActorController>();

                foreach (var collider in colliders)
                {
                    var actorController = collider.GetComponent <ActorController>();
                    if (actorController != null)
                    {
                        potentialTargets.Add(actorController);
                        break;
                    }

                    var hitboxComponent = collider.GetComponent <IHitboxComponent>();
                    if (hitboxComponent != null && hitboxComponent.ParentController is ActorController hitboxAC)
                    {
                        potentialTargets.Add(hitboxAC);
                        break;
                    }
                }


                //old stupid code: should work well enough as long as n is small and your computer is fast enough
                //IEnumerable<ActorController> potentialTargets = transform.root.GetComponentsInChildren<ActorController>();

                foreach (var potentialTarget in potentialTargets)
                {
                    if (RpgWorldUtils.TargetIsAlive(potentialTarget.transform) &&
                        (potentialTarget.transform.position - transform.position).magnitude <= SearchRadius &&
                        FactionModel.GetRelation(Faction, potentialTarget.Faction) == FactionRelationStatus.Hostile &&
                        !(potentialTarget == this))
                    {
                        //roll some dice
                        if (potentialTarget.Detectability < 1 && UnityEngine.Random.Range(0f, 1f * detectionDifficultyFactor) > potentialTarget.Detectability) //probably correct
                        {
                            continue;
                        }

                        if (UseLineOfSight)
                        {
                            //additional check
                            RaycastHit hitinfo;
                            if (Physics.Raycast(transform.position + new Vector3(0, 1.0f, 0), (potentialTarget.transform.position - transform.position), out hitinfo))
                            {
                                if (hitinfo.collider.gameObject == potentialTarget.gameObject)
                                {
                                    Target = potentialTarget.transform;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            //otherwise, close enough
                            Target = potentialTarget.transform;
                            break;
                        }
                    }
                }

                //sw.Stop();
                //Debug.Log($"Target lookup: {sw.Elapsed.TotalMilliseconds:F4} ms");
            }

            if (!RpgWorldUtils.TargetIsAlive(Target))
            {
                Target = null;
            }
        }
示例#3
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);
            }
        }
示例#4
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);
            }
        }