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); } }
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); }
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); } }
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); }
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."); }
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()); }
protected virtual void RotateTowardsCastDirection(AbilityCastData castData) { RotateTowardsDirection(castData.CastDirection, Mathf.Infinity); }
private void OnCastDataEmitResult(AbilityCastData castData, AbilityCastResult result) { OnAbilityHitResultEmitted.Invoke(master, result); }
protected virtual void StartVelocityOverrideFromAbilityCast(AbilityCastData castData) { voAgent = castData.AbilityCast.VelocityOverrideChain.StartChain(references.RigidBody, Is2D ? Forward2D.ToV3() : Forward); voAgent.OnAgentStop.Subscribe(OnVelocityOverrideStops); }
protected Vector3 DetermineAbilityRecoil(AbilityCastData castData) { return(PinouUtils.Transform.TransformVector(castData.BaseRecoil, PinouUtils.Quaternion.SafeLookRotation(castData.CastDirection, -Forward)) * RecoilFactor); }