示例#1
0
        private void DoClawAttack()
        {
            //Debug.LogWarning("ClawAttack!");

            //do damage to what we know is the target
            //raycast to see if we actually can hit
            //only half works unfortunately
            var itd = ActorController.Target.GetComponent <BaseController>() as ITakeDamage;

            if (itd != null)
            {
                LayerMask lm = WorldUtils.GetAttackLayerMask();
                Vector3   vecThisToTarget = ActorController.Target.position - transform.position;
                if (Physics.Raycast(transform.position, vecThisToTarget, out var raycastHit, 100, lm, QueryTriggerInteraction.Collide))
                {
                    var hitController = raycastHit.collider.GetComponentInParent <BaseController>();
                    if (hitController != null && hitController == (BaseController)itd)
                    {
                        var modHit         = ClawHit;
                        var gameplayConfig = ConfigState.Instance.GetGameplayConfig();
                        modHit.Damage       *= gameplayConfig.Difficulty.ActorStrength;
                        modHit.DamagePierce *= gameplayConfig.Difficulty.ActorStrength;
                        modHit.Originator    = ActorController;
                        itd.TakeDamage(modHit);
                        if (HitSoundClip != null)
                        {
                            AudioPlayer.Instance.PlaySoundPositional(HitSoundClip, false, ActorController.Target.position);
                        }
                    }
                }
            }
        }
示例#2
0
        private void DoFlameAttack()
        {
            //basically copied from ActorAttackComponent

            var gameplayConfig = ConfigState.Instance.GetGameplayConfig();

            var modHit = FlameHit;

            modHit.Damage       *= gameplayConfig.Difficulty.ActorStrength;
            modHit.DamagePierce *= gameplayConfig.Difficulty.ActorStrength;
            modHit.Originator    = ActorController;
            LayerMask lm = WorldUtils.GetAttackLayerMask();

            var            rc = Physics.RaycastAll(FirePoint.position, FirePoint.forward, FlameRange, lm, QueryTriggerInteraction.Collide);
            BaseController ac = null;

            foreach (var r in rc) //TODO move some of this to utils (RaycastForHit?)
            {
                var go   = r.collider.gameObject;
                var ahgo = go.GetComponent <ActorHitboxComponent>();
                if (ahgo != null)
                {
                    ac = ahgo.ParentController;
                    break;
                }
                var acgo = go.GetComponent <ActorController>();
                if (acgo != null)
                {
                    ac = acgo;
                    break;
                }
            }

            if (ac != null && ac is ITakeDamage dac)
            {
                //raycast check for cover
                Physics.Raycast(FirePoint.position, FirePoint.forward, out var nearestRaycastHit, FlameRange, lm, QueryTriggerInteraction.Collide);
                var nearestController = nearestRaycastHit.collider.GetComponentInParent <BaseController>();
                if (nearestController == null || nearestController != ac)
                {
                    //nop
                }
                else
                {
                    dac.TakeDamage(modHit);
                }
            }
        }
示例#3
0
        public void DoAttack()
        {
            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 shootPos = ShootPoint == null ? (transform.position + (transform.forward * 0.6f) + (transform.up * 1.25f)) : ShootPoint.position;
            Vector3 shootVec = (aimPoint - shootPos).normalized; //I screwed this up the first time

            var modHit         = AttackHit;
            var gameplayConfig = ConfigState.Instance.GetGameplayConfig();

            modHit.Damage       *= gameplayConfig.Difficulty.ActorStrength;
            modHit.DamagePierce *= gameplayConfig.Difficulty.ActorStrength;
            modHit.Originator    = ActorController;

            if (UseMelee)
            {
                //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)
            {
                //bullet path (shoot)
                //var bullet = Instantiate<GameObject>(BulletPrefab, shootPos + (shootVec * 0.25f), Quaternion.identity, transform.root);
                var bullet          = WorldUtils.SpawnEffect(BulletPrefab, shootPos + (shootVec * 0.25f), Vector3.zero, transform.root);
                var bulletRigidbody = bullet.GetComponent <Rigidbody>();
                bulletRigidbody.velocity = (shootVec * BulletSpeed);
                bullet.GetComponent <BulletScript>().HitInfo = modHit;
            }
            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 (AttackEffectPrefab != null)
            {
                WorldUtils.SpawnEffect(AttackEffectPrefab, shootPos, Vector3.zero, (ShootPoint == null ? transform : ShootPoint));
                //Instantiate(AttackEffectPrefab, shootPos, Quaternion.identity, (ShootPoint == null ? transform : ShootPoint));
            }
            if (AttackSound != null)
            {
                AttackSound.Play();
            }

            DidAttack      = true;
            LastAttackTime = Time.time;
        }
示例#4
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) <= ((IAmTargetable)pc).Detectability)
                    {
                        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, WorldUtils.GetAttackLayerMask());
                HashSet <IAmTargetable> potentialTargets = new HashSet <IAmTargetable>();

                foreach (var collider in colliders)
                {
                    var baseController = collider.GetComponent <BaseController>();
                    if (baseController != null)
                    {
                        if (baseController is IAmTargetable iat && iat.ValidTarget)
                        {
                            potentialTargets.Add(iat);
                        }
                        continue; //continue anyway since we've found a base controller and it's either targetable or it's not
                    }

                    var hitboxComponent = collider.GetComponent <IHitboxComponent>();
                    if (hitboxComponent != null && hitboxComponent.ParentController is IAmTargetable iat2 && iat2.ValidTarget)
                    {
                        potentialTargets.Add(iat2);
                        continue;
                    }
                }


                //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)
                {
                    BaseController targetController = potentialTarget as BaseController;
                    if (targetController == null)
                    {
                        continue;
                    }

                    if (RpgWorldUtils.TargetIsAlive(targetController.transform) &&
                        (targetController.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), (targetController.transform.position - transform.position), out hitinfo))
                            {
                                if (hitinfo.collider.gameObject == targetController.gameObject)
                                {
                                    Target = targetController.transform;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            //otherwise, close enough
                            Target = targetController.transform;
                            break;
                        }
                    }
                }

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

            if (!RpgWorldUtils.TargetIsAlive(Target))
            {
                Target = null;
            }
        }
示例#5
0
        private bool CheckLineOfSight(BaseController targetController)
        {
            //this will kinda work
            RaycastHit hitinfo;

            if (Physics.Raycast(transform.position + new Vector3(0, 1.0f, 0), (targetController.transform.position - transform.position), out hitinfo, SearchRadius, WorldUtils.GetAttackLayerMask(), QueryTriggerInteraction.Ignore))
            {
                //Debug.Log($"LoS raycast hit {hitinfo.collider.gameObject.name}");

                if (hitinfo.collider.gameObject == targetController.gameObject || hitinfo.collider.GetComponentInParent <BaseController>() == targetController)
                {
                    return(true);
                }
            }

            return(false);
        }
示例#6
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;
        }