public void BuildHitbox(AbilityCastData castData)
        {
            _castData    = castData;
            _abilityData = _castData.AbilityCast;
            _hitboxData  = _abilityData.Hitbox;
            _hitboxLife  = _hitboxData.MaxTargetHit;

            if (_hitboxData.RandomSpeed == false)
            {
                _currentMoveSpeed = _hitboxData.MoveSpeed;
            }
            else
            {
                _currentMoveSpeed = Random.Range(_hitboxData.MoveSpeed, _hitboxData.MaxMoveSpeed);
            }

            if (_abilityData.Visual.HitboxVisualModel != null)
            {
                _visualModel = PinouApp.Pooler.Retrieve(_abilityData.Visual.HitboxVisualModel, transform.position, transform.rotation, transform);
                _visualModelStoreCoroutine =
                    PinouUtils.Coroutine.Invoke(
                        PinouApp.Pooler.Store,
                        castData.AbilityCast.Visual.HitboxVisualLifeSpan + castData.AbilityCast.Hitbox.LifeSpan,
                        _visualModel, true);
            }
            Destroy(gameObject, castData.AbilityCast.Hitbox.LifeSpan);

            s_abilityHitboxes.Add(_castData, this);

            _abilityData.Visual.HitboxVisualParameters.Apply(gameObject);
        }
 public static void ApplyAbilityPerformedOnHitEntities(AbilityCastData castData, ICollection <Entity> entities)
 {
     foreach (Entity entity in entities)
     {
         ApplyAbilityPerformedOnHitEntity(castData, entity);
     }
 }
Example #3
0
 protected virtual void OnPerformAbility(Entity ent, AbilityCastData castData)
 {
     AbilityPerformer.HandleAbilityCastDataVisual(castData);
     if (castData.AbilityCast.Main.RotateOnCast == true)
     {
         RotateTowardsCastDirection(castData);
     }
 }
 public static void DestroyFromCastData(AbilityCastData castData)
 {
     if (s_abilityHitboxes.ContainsKey(castData))
     {
         Destroy(s_abilityHitboxes[castData]);
         s_abilityHitboxes.Remove(castData);
     }
 }
        public static void ApplyAbilityPerformedOnHitEntity(AbilityCastData castData, Entity entity, AbilityCastResult existingResult = null)
        {
            AbilityCastResult result = existingResult == null ? new AbilityCastResult(castData) : existingResult;

            result.FillVictim(entity);
            if (result.ImpactFilled == false)
            {
                result.FillImpact(ComputePerformedAbilityImpact(castData, entity));
            }

            entity.ReceiveAbilityHit(result);
        }
Example #6
0
            protected virtual void OnAbilityPerformed(Entity ent, AbilityCastData castData)
            {
                if (castData.AbilityCast.Methods.RecoilCondition != RecoilCondition.MustHit || castData.Results.Length > 0)
                {
                    Vector3 recoil = DetermineAbilityRecoil(castData);
                    references.RigidBody.velocity += recoil;
                }

                if (castData.AbilityCast.HasVelocityOverrides == true)
                {
                    StartVelocityOverrideFromAbilityCast(castData);
                }
            }
Example #7
0
            protected virtual void PerformAbility(AbilityCastData castData)
            {
                if (castData.AbilityCast.Methods.CastOriginTiming == AbilityCastOriginTiming.PerformEntrance)
                {
                    castData.FillOrigin(DetermineCastOrigin(castData.AbilityCast));
                }

                OnPerformAbility.Invoke(master, castData);

                castData.OnResultEmitted.Subscribe(OnCastDataEmitResult);
                AbilityPerformer.PerformAbility(castData);

                OnAbilityPerformed.Invoke(master, castData);
            }
Example #8
0
            protected IEnumerator CastAbilityTimingCoroutine(AbilityCastData castData)
            {
                _currentAbilityState = AbilityState.Casting;

                int   arrayIndex        = 0;
                float attackSpeedFactor = HasStats ? Stats.EvaluateAbilitiesStat(EntityAbilitiesStat.AttackSpeed, 1f) : 1f;

                float[] durationArray =
                {
                    (castData.AbilityCast.Timing.CastDuration) * attackSpeedFactor,
                    (castData.AbilityCast.Timing.CastDuration + castData.AbilityCast.Timing.PerformDuration) * attackSpeedFactor,
                    (castData.AbilityCast.Timing.CastDuration + castData.AbilityCast.Timing.PerformDuration + castData.AbilityCast.Timing.HardRecoverDuration) * attackSpeedFactor,
                    (castData.AbilityCast.Timing.CastDuration + castData.AbilityCast.Timing.PerformDuration + castData.AbilityCast.Timing.HardRecoverDuration + castData.AbilityCast.Timing.SoftRecoverDuration) * attackSpeedFactor
                };


                float timeAtStart    = Time.time;
                float lastDifference = 0f;

                while (arrayIndex < durationArray.Length)
                {
                    float timeDifference = Time.time - timeAtStart;

                    if (timeDifference > durationArray[arrayIndex])
                    {
                        if (lastDifference <= durationArray[arrayIndex])
                        {
                            _currentAbilityState = _abilityCastStatesArray[arrayIndex];
                            if (_abilityCastStatesArray[arrayIndex] == AbilityState.Performing)
                            {
                                PerformAbility(castData);
                            }

                            arrayIndex++;
                        }
                    }

                    lastDifference = timeDifference;
                    yield return(new WaitForFixedUpdate());
                }

                _activeCastData = null;
                _abilityCastTimingsCoroutine = null;
            }
        private static Vector3 ComputePerformedAbilityImpact(AbilityCastData castData, Entity entity)
        {
            switch (castData.AbilityCast.Methods.ImpactMethod)
            {
            case AbilityImpactMethod.VictimCenter:
                return(entity.Position);

            case AbilityImpactMethod.CastOrigin:
                return(castData.Origin);

            case AbilityImpactMethod.OriginVictimCenterAverage:
                return((entity.Position + castData.Origin) * 0.5f);

            case AbilityImpactMethod.RayCastTowardVictim:
                throw new System.NotImplementedException();

            case AbilityImpactMethod.ProjectileImpact:
                throw new System.Exception("This line can not be called, projectiles' impacts are calculated earlier.");
            }

            throw new System.Exception("Enum AbilityImapctMethod changed. Require update here.");
        }
Example #10
0
            protected void CastAbility(IAbilityContainer container, Vector3 castDirection, int multiCastID)
            {
                if (container.ContainsAbility == false)
                {
                    return;
                }
                AbilityData     ability  = container.Ability;
                AbilityCastData castData = new AbilityCastData(master, container, -1, multiCastID);

                _activeCastData = castData;
                castData.FillBase(
                    ComputeResourcesImpacts(container),
                    ability.Main.BaseKnockback * (HasStats ? Stats.EvaluateAbilitiesStat(EntityAbilitiesStat.KnockbackInflictedFactor, 1f) : 1f),
                    ability.Main.BaseRecoil / container.AbilityTriggerData.MultiCastCount);

                if (castDirection.sqrMagnitude <= Mathf.Epsilon)
                {
                    castData.FillCastDirection(DetermineCastDirection(castData.AbilityCast, container.AbilityTriggerData));
                }
                else
                {
                    castData.FillCastDirection(castDirection);
                }
                if (castData.AbilityCast.Methods.CastOriginTiming == AbilityCastOriginTiming.CastEntrance)
                {
                    castData.FillOrigin(DetermineCastOrigin(castData.AbilityCast));
                }

                if (castData.AbilityCast.Timing.Instant == true)
                {
                    PerformAbility(castData);
                    _activeCastData = null;
                    _abilityCastTimingsCoroutine = null;
                }
                else
                {
                    master.RestartCoroutine(CastAbilityTimingCoroutine(castData), ref _abilityCastTimingsCoroutine);
                }
            }
        public static (Entity[], AdditionalHitInfos[]) ComputeMovingHitboxHitEntities(AbilityCastData castData, Vector3 hitBoxOrigin, float speed = -1f, ICollection <Entity> toIgnore = null)
        {
            AbilityHitboxData         hParams          = castData.AbilityCast.Hitbox;
            List <Entity>             hitEntities      = new List <Entity>();
            List <float>              hitEntitiesDst   = new List <float>();
            List <AdditionalHitInfos> hitEntitiesInfos = new List <AdditionalHitInfos>();
            Dictionary <Collider, AdditionalHitInfos> colliderHitInfos = new Dictionary <Collider, AdditionalHitInfos>();

            if (speed <= 0f)
            {
                speed = hParams.MoveSpeed;
            }

            #region Detect all entities hit
            Collider[]         entitiesHit  = null;
            AdditionalHitInfos baseHitInfos = new AdditionalHitInfos(hitBoxOrigin, castData.CastDirection, speed * Time.fixedDeltaTime, default);
            #region Static Hitboxes
            #endregion
            #region Moving Hitboxes
            if (hParams.Type == HitboxType.Sphere)
            {
                RaycastHit[] hits = Physics.SphereCastAll(
                    baseHitInfos.RayOrigin,
                    hParams.Radius,
                    baseHitInfos.RayDirection,
                    baseHitInfos.Distance,
                    PinouApp.Resources.Data.Layers.Entities);
                entitiesHit = new Collider[hits.Length];
                for (int i = 0; i < hits.Length; i++)
                {
                    entitiesHit[i] = hits[i].collider;
                    colliderHitInfos.Add(hits[i].collider, baseHitInfos.CopyWithHit(hits[i]));
                }
            }
            else if (hParams.Type == HitboxType.Box)
            {
                RaycastHit[] hits = Physics.BoxCastAll(
                    baseHitInfos.RayOrigin,
                    hParams.Size * 0.5f,
                    baseHitInfos.RayDirection,
                    Quaternion.Euler(hParams.Orientation),
                    baseHitInfos.Distance,
                    PinouApp.Resources.Data.Layers.Entities);

                entitiesHit = new Collider[hits.Length];
                for (int i = 0; i < hits.Length; i++)
                {
                    entitiesHit[i] = hits[i].collider;
                    colliderHitInfos.Add(hits[i].collider, baseHitInfos.CopyWithHit(hits[i]));
                }
            }
            #endregion
            #endregion

            #region Sort entities
            //Sort allowed entities and store them
            foreach (Collider coll in entitiesHit)
            {
                Entity collMaster = coll.GetComponentInParent <Entity>();
                if (hitEntities.Contains(collMaster) == false &&
                    (toIgnore == null || toIgnore.Contains(collMaster) == false) &&
                    CanPerformedAbilityHitEntity(castData, collMaster) == true)
                {
                    float dst = Vector3.SqrMagnitude(collMaster.Position - hitBoxOrigin);
                    if (hitEntities.Count == 0)
                    {
                        hitEntities.Add(collMaster);
                        hitEntitiesDst.Add(dst);
                        hitEntitiesInfos.Add(colliderHitInfos[coll]);
                    }
                    else
                    {
                        //Order the hit entity directly by distance
                        for (int i = hitEntities.Count - 1; i >= 0; i--)
                        {
                            if (dst > (hitEntitiesDst[i]))
                            {
                                hitEntities.Insert(i + 1, collMaster);
                                hitEntitiesDst.Insert(i + 1, dst);
                                hitEntitiesInfos.Add(colliderHitInfos[coll]);
                                break;
                            }
                            else if (i == 0)
                            {
                                hitEntities.Insert(0, collMaster);
                                hitEntitiesDst.Insert(0, dst);
                                hitEntitiesInfos.Add(colliderHitInfos[coll]);
                                break;
                            }
                        }
                    }
                }
            }

            //Keep only nearest entities and right count
            if (hitEntities.Count > hParams.MaxTargetHit)
            {
                hitEntities.RemoveRange(hParams.MaxTargetHit, hitEntities.Count - hParams.MaxTargetHit);
            }
            #endregion

            return(hitEntities.ToArray(), hitEntitiesInfos.ToArray());
        }
Example #12
0
 protected virtual void RotateTowardsCastDirection(AbilityCastData castData)
 {
     RotateTowardsDirection(castData.CastDirection, Mathf.Infinity);
 }
Example #13
0
 private void OnCastDataEmitResult(AbilityCastData castData, AbilityCastResult result)
 {
     OnAbilityHitResultEmitted.Invoke(master, result);
 }
Example #14
0
 protected virtual void StartVelocityOverrideFromAbilityCast(AbilityCastData castData)
 {
     voAgent = castData.AbilityCast.VelocityOverrideChain.StartChain(references.RigidBody, Is2D ? Forward2D.ToV3() : Forward);
     voAgent.OnAgentStop.Subscribe(OnVelocityOverrideStops);
 }
Example #15
0
 protected Vector3 DetermineAbilityRecoil(AbilityCastData castData)
 {
     return(PinouUtils.Transform.TransformVector(castData.BaseRecoil, PinouUtils.Quaternion.SafeLookRotation(castData.CastDirection, -Forward)) * RecoilFactor);
 }